From 087cfd1cea8fdf645199df6c798cb496809e7cd6 Mon Sep 17 00:00:00 2001 From: "Ben Russell (300178622)" Date: Sun, 23 Jun 2013 15:50:29 +1200 Subject: [PATCH] [0.0-49] kicks are handled gracefully now; server can kick from the lua side; framework starting to be laid for ENet support --- Makefile | 3 +- Makefile.dedi | 3 +- Makefile.glmingw | 5 ++- Makefile.mingw | 5 ++- Makefile.opengl | 3 +- README.txt | 16 +++---- docs/modding_lua.txt | 20 +++++++-- include/common.h | 16 ++++++- pkg/base/client_start.lua | 21 +++++++++ pkg/base/commands.lua | 10 +++++ pkg/base/main_client.lua | 10 +++++ pkg/base/version.lua | 8 ++-- src/lua.c | 1 + src/lua_net.h | 34 +++++++++++++++ src/network.c | 92 ++++++++++++++++++++++++++++++--------- zipdist.sh | 2 +- 16 files changed, 203 insertions(+), 46 deletions(-) diff --git a/Makefile b/Makefile index ecb2424..45052cc 100644 --- a/Makefile +++ b/Makefile @@ -12,11 +12,12 @@ HEADERS_Lua = #-I /usr/include/lua5.1 LDFLAGS = -pg -g $(LDFLAGS_EXTRA) -fopenmp LIBS_SDL = `sdl-config --libs` +LIBS_ENet = xlibinc/libenet.a LIBS_Lua = -llua # Lua is not an acronym. Get used to typing it with lower case u/a. LIBS_zlib = -lz LIBS_sackit = -lsackit -LIBS = -Lxlibinc -lm $(LIBS_Lua) $(LIBS_SDL) $(LIBS_zlib) $(LIBS_sackit) +LIBS = -Lxlibinc -lm $(LIBS_Lua) $(LIBS_SDL) $(LIBS_zlib) $(LIBS_sackit) $(LIBS_ENet) BINNAME = iceball diff --git a/Makefile.dedi b/Makefile.dedi index 9b7d83e..16276bb 100644 --- a/Makefile.dedi +++ b/Makefile.dedi @@ -10,11 +10,12 @@ CFLAGS = -DDEDI -pg -O2 -fno-strict-aliasing -g -Wall -Wextra \ HEADERS_Lua = LDFLAGS = -pg -g -fopenmp $(LDFLAGS_EXTRA) +LIBS_ENet = xlibinc/libenet.a LIBS_Lua = -llua # Lua is not an acronym. Get used to typing it with lower case u/a. LIBS_zlib = -lz LIBS_sackit = -lsackit -LIBS = -Lxlibinc/ -lm $(LIBS_Lua) $(LIBS_zlib) $(LIBS_sackit) +LIBS = -Lxlibinc/ -lm $(LIBS_Lua) $(LIBS_zlib) $(LIBS_sackit) $(LIBS_ENet) BINNAME = dedi_iceball OBJDIR = build/dedi diff --git a/Makefile.glmingw b/Makefile.glmingw index c6c64bb..79f3b69 100644 --- a/Makefile.glmingw +++ b/Makefile.glmingw @@ -7,6 +7,8 @@ # - Stash Lua includes in winlibs/*.h. # - lua.h, lualib.h, lauxlib.h, luaconf.h # - Stash sackit.h and libsackit.a in winlibs/. +# - Stash libenet.a in winlibs/. +# - Stash ENet includes from enet/*.h in winlibs/enet/*.h. # CFLAGS = -O2 -fno-strict-aliasing -g -Wall -Wextra \ @@ -20,12 +22,13 @@ CFLAGS = -O2 -fno-strict-aliasing -g -Wall -Wextra \ LDFLAGS = -g $(LDFLAGS_EXTRA) LIBS_SDL = -lSDLmain -lSDL +LIBS_ENet = winlibs/libenet.a LIBS_Lua = -llua LIBS_Winsuck = -lws2_32 # Lua is not an acronym. Get used to typing it with lower case u/a. LIBS_zlib = -lz LIBS_sackit = -lsackit -LIBS = -Lwinlibs -lm -lmingw32 $(LIBS_Lua) $(LIBS_SDL) $(LIBS_zlib) $(LIBS_Winsuck) $(LIBS_sackit) ./glew32.dll -lopengl32 +LIBS = -Lwinlibs -lm -lmingw32 $(LIBS_Lua) $(LIBS_SDL) $(LIBS_zlib) $(LIBS_Winsuck) $(LIBS_sackit) ./glew32.dll -lopengl32 $(LIBS_ENet) BINNAME = iceball-gl.exe RENDERER = gl diff --git a/Makefile.mingw b/Makefile.mingw index b018484..f6f0ba4 100644 --- a/Makefile.mingw +++ b/Makefile.mingw @@ -7,6 +7,8 @@ # - Stash Lua includes in winlibs/*.h. # - lua.h, lualib.h, lauxlib.h, luaconf.h # - Stash sackit.h and libsackit.a in winlibs/. +# - Stash libenet.a in winlibs/. +# - Stash ENet includes from enet/*.h in winlibs/enet/*.h. # CFLAGS = -O2 -fno-strict-aliasing -g -Wall -Wextra \ @@ -20,12 +22,13 @@ CFLAGS = -O2 -fno-strict-aliasing -g -Wall -Wextra \ LDFLAGS = -g -fopenmp $(LDFLAGS_EXTRA) LIBS_SDL = -lSDLmain -lSDL +LIBS_ENet = winlibs/libenet.a LIBS_Lua = -llua LIBS_Winsuck = -lws2_32 # Lua is not an acronym. Get used to typing it with lower case u/a. LIBS_zlib = -lz LIBS_sackit = -lsackit -LIBS = -Lwinlibs -lm -lmingw32 $(LIBS_Lua) $(LIBS_SDL) $(LIBS_zlib) $(LIBS_Winsuck) $(LIBS_sackit) +LIBS = -Lwinlibs -lm -lmingw32 $(LIBS_Lua) $(LIBS_SDL) $(LIBS_zlib) $(LIBS_Winsuck) $(LIBS_sackit) $(LIBS_ENet) BINNAME = iceball.exe OBJDIR = build/mingw32 diff --git a/Makefile.opengl b/Makefile.opengl index 7b35faf..4755cd2 100644 --- a/Makefile.opengl +++ b/Makefile.opengl @@ -12,11 +12,12 @@ HEADERS_Lua = #-I /usr/include/lua5.1 LDFLAGS = -pg -g $(LDFLAGS_EXTRA) LIBS_SDL = `sdl-config --libs` +LIBS_ENet = xlibinc/libenet.a LIBS_Lua = -llua # Lua is not an acronym. Get used to typing it with lower case u/a. LIBS_zlib = -lz LIBS_sackit = -lsackit -LIBS = -Lxlibinc -lm $(LIBS_Lua) $(LIBS_SDL) $(LIBS_zlib) $(LIBS_sackit) -lGL -lGLEW +LIBS = -Lxlibinc -lm $(LIBS_Lua) $(LIBS_SDL) $(LIBS_zlib) $(LIBS_sackit) -lGL -lGLEW $(LIBS_ENet) BINNAME = iceball-gl RENDERER = gl diff --git a/README.txt b/README.txt index 0ba68bd..de888e8 100644 --- a/README.txt +++ b/README.txt @@ -1,19 +1,12 @@ GUYS GUYS GUYS FIRST THING YOU NEED TO READ: -docs/READ_THIS_FIRST.txt might work. +docs/READ_THIS_FIRST.txt might work (OK, it's out of date right now. Try running the tutorial.) If not, there's a tutorial on the forums: http://iceballga.me ------------------------------------------------------------------------------ -This is FINALLY a game, BUT is not ready to be released yet. - -NOTE: -By Stack's request, this project is now known as "Iceball". - -mesa.vxl is by Triplefox, and is currently being used to test load/render. - LICENSING NOTES: Iceball is licensed under the regular GNU GPL version 3. Ice Lua Components is licensed under the LGPL version 3. @@ -42,6 +35,7 @@ REQUIREMENTS: - zlib - http://zlib.net/ - sackit - https://github.com/iamgreaser/sackit/ - you should copy libsackit.a and sackit.h to xlibinc. +- enet 1.3 - http://enet.bespin.org/ - GNU make - if someone has BSD make, please tell us :) @@ -52,10 +46,10 @@ STUFF TO DO BEFORE 0.1 CAN BE RELEASED: - make kicking not suck MSVC readme (wip): -- create a folder 'winlibs' in the buldenthesnip dir +- create a folder 'winlibs' in the iceball dir dump all dll's + lib's in this folder (opengl,lua,zlib, sdl, glew) dump all includes in submaps (glew in glew submap, and so on) - /buldenthesnip/ + /iceball/ /winlibs/ /glew/ /lua/ @@ -79,7 +73,7 @@ for the git starters: - git update-index --assume-unchanged clsave\pub\user.json and to get updates from the main repo: -- git remote add upstream git://github.com/iamgreaser/buldthensnip.git +- git remote add upstream git://github.com/iamgreaser/iceball.git - git pull --rebase upstream master - git push origin master diff --git a/docs/modding_lua.txt b/docs/modding_lua.txt index 87be79b..7ce14a2 100644 --- a/docs/modding_lua.txt +++ b/docs/modding_lua.txt @@ -520,22 +520,36 @@ success = common.net_send(sockfd, str) @ "sockfd" is ignored C->S and should be nil S->C local multiplayer should set "sockfd" to "true" + COMPATIBILITY WARNING: + [ writing this before I actually do it --GM ] + before 0.0-50, sockfd pertains to an ACTUAL sockfd. + from 0.0-50 onwards, sockfd pertains to a CLIENT HANDLE. + + this should not be of any concern to you unless you do Really Stupid Stuff. + having said that, DO NOT EXPECT THIS TO BE A ONE-TO-ONE MAPPING TO CLIENT INDICES. + + oh, and as expected, same applies to common.net_recv and every other case you see a sockfd. + str, sockfd = common.net_recv() @ receives a packet for C->S "sockfd" is nil S->C local multiplayer will result in "sockfd" being "true" - returns nil if nothing is there + returns nil, nil if nothing is there + returns false, nil on the client if the connection was terminated -server.net_kick(sockfd, reason) +server.net_kick(sockfd, reason) @ kicks a client from the server - fails silently if sockfd is invalid, + fails silently if sockfd is invalid (but still a plausible parameter), or sockfd is closed / errors out throws a lua error for other weird errors. +client.hook_kick = fn(reason) @ + sets a hook called when the player gets kicked + wav = common.wav_load(fname) @ loads a sound with filename "fname" remember to free it when you're done diff --git a/include/common.h b/include/common.h index 0638069..b0eddd5 100644 --- a/include/common.h +++ b/include/common.h @@ -19,7 +19,7 @@ #define VERSION_X 0 #define VERSION_Y 0 #define VERSION_A 0 -#define VERSION_Z 48 +#define VERSION_Z 49 // Remember to bump "Z" basically every time you change the engine! // Remember to bump the version in Lua too! // Remember to document API changes in a new version! @@ -76,6 +76,8 @@ typedef unsigned __int64 uint64_t; #include +#include + #ifdef __cplusplus extern "C" { #endif @@ -108,6 +110,9 @@ extern "C" { // just so we can get getaddrinfo // you will need Windows 2000 at least! +#ifdef _WIN32_WINNT +#undef _WIN32_WINNT +#endif #define _WIN32_WINNT 0x0501 #include #include @@ -355,10 +360,14 @@ struct packet typedef struct client { + // legacy proto only packet_t *head, *tail; packet_t *send_head, *send_tail; int sockfd; int isfull; + + // enet proto only + ENetPeer *peer; // client only char *cfetch_ubuf; @@ -374,7 +383,7 @@ typedef struct client int sfetch_cpos; int sfetch_udtype; - // serialisation + // serialisation - legacy proto only char rpkt_buf[PACKET_LEN_MAX*2]; int rpkt_len; char spkt_buf[PACKET_LEN_MAX*2]; @@ -384,6 +393,7 @@ typedef struct client #define SOCKFD_NONE -1 #define SOCKFD_LOCAL -2 +#define SOCKFD_ENET -3 enum { @@ -498,6 +508,8 @@ int net_packet_push(int len, const char *data, int sockfd, packet_t **head, pack int net_packet_push_lua(int len, const char *data, int sockfd, packet_t **head, packet_t **tail); packet_t *net_packet_pop(packet_t **head, packet_t **tail); void net_packet_free(packet_t *pkt, packet_t **head, packet_t **tail); +void net_kick_sockfd_immediate(int sockfd, const char *msg); +void net_kick_client_immediate(client_t *cli, const char *msg); void net_flush(void); int net_connect(void); void net_disconnect(void); diff --git a/pkg/base/client_start.lua b/pkg/base/client_start.lua index 55497a4..1275228 100644 --- a/pkg/base/client_start.lua +++ b/pkg/base/client_start.lua @@ -858,6 +858,27 @@ client.hook_mouse_button = h_mouse_button client.hook_mouse_motion = h_mouse_motion client.hook_window_activate = h_window_activate +function client.hook_kick(reason) + print("Kicked - "..reason) + function client.hook_tick() + client.mouse_lock_set(false) + client.mouse_visible_set(true) + return 0.01 + end + local old_render = client.hook_render + local new_render = nil + function new_render_fn(...) + client.hook_render = old_render + local ret = client.hook_render(...) + old_render = client.hook_render + client.hook_render = new_render + font_large.print(30, 30, 0xFFAA0000, "KICKED") + font_mini.print(30, 65, 0xFFAA0000, reason) + end + new_render = new_render_fn + client.hook_render = new_render +end + print("pkg/base/client_start.lua loaded.") --dofile("pkg/base/plug_snow.lua") diff --git a/pkg/base/commands.lua b/pkg/base/commands.lua index 64e449e..c5bc15a 100644 --- a/pkg/base/commands.lua +++ b/pkg/base/commands.lua @@ -82,6 +82,16 @@ command_register({ end }) +-- for testing. not like it can be abused. well, i hope it can't be abused. --GM +command_register({ + command = "kickme", + permission = nil, + usage = "/kickme", + func = function(plr, plrid, sockfd, prms, msg) + server.net_kick(sockfd, "requested!") + end +}) + command_register({ command = "me", permission = "me", diff --git a/pkg/base/main_client.lua b/pkg/base/main_client.lua index 73cd4a0..0479d75 100644 --- a/pkg/base/main_client.lua +++ b/pkg/base/main_client.lua @@ -15,6 +15,16 @@ along with Ice Lua Components. If not, see . ]] +function client.hook_kick(reason) + print("Kicked - "..reason) + function client.hook_tick() + error("Kicked - "..reason) + end + function client.hook_render() + error("Kicked - "..reason) + end +end + dofile("pkg/base/preconf.lua") -- if you don't want music, set FILE_MUSIC to "true". diff --git a/pkg/base/version.lua b/pkg/base/version.lua index 6076fd8..805c932 100644 --- a/pkg/base/version.lua +++ b/pkg/base/version.lua @@ -16,9 +16,9 @@ ]] VERSION_ENGINE = { - cmp={0,0,0,0,48}, - num=48, - str="0.0-48", + cmp={0,0,0,0,49}, + num=49, + str="0.0-49", } VERSION_BUGS = { @@ -74,5 +74,7 @@ VERSION_BUGS = { {renderer="gl", intro=nil, fix=48, msg="[OpenGL] Chunk count is static and does not adapt to different fog values"}, {intro=nil, fix=48, msg="No way to determine from the Lua end what renderer a client is using"}, {renderer="gl", intro=nil, fix=48, msg="[OpenGL] Chunk generation pattern kinda sucks"}, +{intro=nil, fix=49, msg="Kick not handled gracefully"}, +{intro=49, fix=nil, msg="Kick message isn't communicated properly"}, } diff --git a/src/lua.c b/src/lua.c index ecd092d..933dc3f 100644 --- a/src/lua.c +++ b/src/lua.c @@ -166,6 +166,7 @@ struct icelua_entry icelua_common_client[] = { #endif struct icelua_entry icelua_common_server[] = { + {icelua_fn_server_net_kick, "net_kick"}, {NULL, NULL} }; diff --git a/src/lua_net.h b/src/lua_net.h index 28f40f5..c630dab 100644 --- a/src/lua_net.h +++ b/src/lua_net.h @@ -370,7 +370,14 @@ int icelua_fn_common_net_recv(lua_State *L) } else { packet_t *pkt = net_packet_pop(&(to_client_local.head), &(to_client_local.tail)); if(pkt == NULL) + { + if(to_client_local.sockfd == SOCKFD_NONE) + { + lua_pushboolean(L, 0); + return 1; + } return 0; + } if(pkt->data[0] >= 0x40 && pkt->data[0] <= 0x7E) lua_pushlstring(L, &pkt->data[1], pkt->len-1); @@ -386,3 +393,30 @@ int icelua_fn_common_net_recv(lua_State *L) return 2; } } + +int icelua_fn_server_net_kick(lua_State *L) +{ + int top = icelua_assert_stack(L, 2, 2); + + const char *msg = lua_tostring(L, 2); + if(msg == NULL) + return luaL_error(L, "not a string"); + + if(lua_isboolean(L, 1) && lua_toboolean(L, 1)) + { + // local player kick + net_kick_sockfd_immediate(SOCKFD_LOCAL, msg); + } else if(lua_isnumber(L, 1)) { + // remote player kick + int sockfd = lua_tointeger(L, 1); + if(sockfd >= 0) + net_kick_sockfd_immediate(sockfd, msg); + else + return luaL_error(L, "invalid sockfd"); + } else { + return luaL_error(L, "invalid sockfd"); + } + + return 0; +} + diff --git a/src/network.c b/src/network.c index e2e76ee..ea55148 100644 --- a/src/network.c +++ b/src/network.c @@ -33,8 +33,10 @@ int setsockopt( SOCKET s, int level, int optname, void* optval, int optlen ) #endif #endif -int server_sockfd_ipv4 = -1; -int server_sockfd_ipv6 = -1; +int server_sockfd_ipv4 = SOCKFD_NONE; +int server_sockfd_ipv6 = SOCKFD_NONE; +ENetPeer *server_peer; +ENetPeer *client_peer; client_t to_server; client_t to_client_local; @@ -238,15 +240,20 @@ void net_packet_free(packet_t *pkt, packet_t **head, packet_t **tail) void net_deinit_client(client_t *cli) { - while(cli->head != NULL) - net_packet_free(cli->head, &(cli->head), &(cli->tail)); - while(cli->send_head != NULL) - net_packet_free(cli->send_head, &(cli->send_head), &(cli->send_tail)); + if(cli->sockfd == SOCKFD_ENET) + { + // TODO: disconnect properly + } else { + while(cli->head != NULL) + net_packet_free(cli->head, &(cli->head), &(cli->tail)); + while(cli->send_head != NULL) + net_packet_free(cli->send_head, &(cli->send_head), &(cli->send_tail)); + } - cli->sockfd = -1; + cli->sockfd = SOCKFD_NONE; } -void net_kick_sockfd_immediate(int sockfd, char *msg) +void net_kick_sockfd_immediate(int sockfd, const char *msg) { char buf[260]; buf[0] = 0x17; @@ -283,27 +290,54 @@ void net_kick_sockfd_immediate(int sockfd, char *msg) lua_pop(lstate_server, 1); } } - - // nuke it - close(sockfd); + + // if sockfd is local, then send the kick message to the local client + if(sockfd == SOCKFD_LOCAL) + { + net_kick_client_immediate(&to_client_local, msg); + } else { + // otherwise, nuke it + close(sockfd); + } } -void net_kick_client_immediate(client_t *cli, char *msg) +void net_kick_client_immediate(client_t *cli, const char *msg) { if(cli == &to_client_local) { fprintf(stderr, "KICK: local \"%s\"\n", msg); - fprintf(stderr, "PANIC: I don't know how to handle a local client kick yet!\n"); - fflush(stderr); - abort(); + if(cli->sockfd == SOCKFD_NONE) + // we shouldn't reach here, but we might as well fail silently for now + // we might as well find out why people's comps are breaking if this ever DOES occur + return; + + lua_getglobal(lstate_client, "client"); + lua_getfield(lstate_client, -1, "hook_kick"); + lua_remove(lstate_client, -2); + if(lua_isnil(lstate_client, -1)) + { + lua_pop(lstate_client, 1); + } else { + lua_pushstring(lstate_client, msg); + + if(lua_pcall(lstate_client, 1, 0, 0) != 0) + { + fprintf(stderr, "ERROR running client Lua (hook_kick): %s\n" + , lua_tostring(lstate_client, -1)); + lua_pop(lstate_client, 1); + } + } } if(cli == NULL) return; - net_kick_sockfd_immediate(cli->sockfd, msg); - cli->sockfd = -1; - net_deinit_client(cli); + cli->sockfd = SOCKFD_NONE; + if(cli != &to_client_local) + { + net_kick_sockfd_immediate(cli->sockfd, msg); + net_deinit_client(cli); + } } const char *net_aux_gettype_str(int ftype) @@ -631,6 +665,16 @@ void net_eat_s2c(client_t *cli) net_packet_free(pkt, &(cli->head), &(cli->tail)); } break; + case 0x17: { + if(pkt->data[pkt->len-1] != '\x00') + { + fprintf(stderr, "ERROR: string not zero-terminated!\n"); + } else { + net_kick_client_immediate(&to_client_local, &(pkt->data[2])); + } + + net_packet_free(pkt, &(cli->head), &(cli->tail)); + } break; case 0x31: { // 0x31 clen.u32 ulen.u32: // file transfer initiation @@ -1109,6 +1153,9 @@ void net_flush_accept(void) void net_flush_snr(client_t *cli) { + if(cli->sockfd == SOCKFD_NONE) + return; + if(cli == &to_client_local) { if(boot_mode & 2) @@ -1537,16 +1584,19 @@ int net_init(void) for(i = 0; i < CLIENT_MAX; i++) { - to_clients[i].sockfd = -1; + to_clients[i].sockfd = SOCKFD_NONE; + to_clients[i].peer = NULL; to_clients[i].head = to_clients[i].tail = NULL; to_clients[i].send_head = to_clients[i].send_tail = NULL; } - to_server.sockfd = -1; + to_server.sockfd = SOCKFD_NONE; + to_server.peer = NULL; to_server.head = to_server.tail = NULL; to_server.send_head = to_server.send_tail = NULL; - to_client_local.sockfd = -1; + to_client_local.sockfd = SOCKFD_NONE; + to_client_local.peer = NULL; to_client_local.head = to_client_local.tail = NULL; to_client_local.send_head = to_client_local.send_tail = NULL; diff --git a/zipdist.sh b/zipdist.sh index f35f7ef..71798ca 100755 --- a/zipdist.sh +++ b/zipdist.sh @@ -1,6 +1,6 @@ #!/bin/sh -export ZIPNAME=nubdist/iceballfornoobs-0.0-48.zip +export ZIPNAME=nubdist/iceballfornoobs-0.0-49.zip #zip -r $ZIPNAME *.dll *.exe *.txt *.bat docs/ \ # pkg/base/*.lua \