diff --git a/datasrc/network.dts b/datasrc/network.dts new file mode 100644 index 000000000..ffa6dea44 --- /dev/null +++ b/datasrc/network.dts @@ -0,0 +1,2 @@ +const array:int sound = sounds.* +const array:int weapon = weapons.* diff --git a/default.bam b/default.bam index ef544015e..537edaf62 100644 --- a/default.bam +++ b/default.bam @@ -10,11 +10,26 @@ if family == "windows" then dat2c_compiler = "scripts\\dat2c.py" end +cmd5_tool = "python scripts/cmd5.py" +if family == "windows" then + cmd5_tool = "scripts\\cmd5.py" +end + function rc(output, input) print("rc " .. PathFilename(input)) return os.execute("rc /fo " .. output .. " " .. input) end +function cmd5(output, inputs) + print("cmd5 " .. PathFilename(output)) + cmd = cmd5_tool .. " " + for i,v in inputs do + cmd = cmd .. v .. " " + end + cmd = cmd .. " > " .. output + return os.execute(cmd) +end + function dat2c(output, data, name) print("dat2c " .. PathFilename(output) .. " = " .. PathFilename(data)) return os.execute(dat2c_compiler .. " " .. data .. " " .. name .. " > " .. output) @@ -40,6 +55,25 @@ function dc_cdata(output, data, script) return os.execute(dc_compiler .. " " .. data .. " " .. script .. " -c " .. output) end + +function CHash(output, ...) + local inputs = {} + local ih = collect_input(arg) + + output = Path(output) + + -- compile all the files + for index, inname in ih do + table.insert(inputs, Path(inname)) + end + + bam_add_job("cmd5", output, inputs) + for index, inname in inputs do + bam_add_dependency(output, inname) + end + return output +end + function ResCompile(scriptfile) scriptfile = Path(scriptfile) output = PathBase(scriptfile) .. ".res" @@ -60,18 +94,26 @@ function DataCompile(datafile, scriptfile, headerfile, sourcefile, outputdatafil datafile = Path(datafile) scriptfile = Path(scriptfile) headerfile = Path(headerfile) - sourcefile = Path(sourcefile) - outputdatafile = Path(outputdatafile) - bam_add_job("dc_source", sourcefile, datafile, scriptfile) + bam_add_job("dc_header", headerfile, datafile, scriptfile) - bam_add_job("dc_cdata", outputdatafile, datafile, scriptfile) - bam_add_dependency(sourcefile, datafile) - bam_add_dependency(sourcefile, scriptfile) - bam_add_dependency(sourcefile, headerfile) bam_add_dependency(headerfile, datafile) bam_add_dependency(headerfile, scriptfile) - bam_add_dependency(outputdatafile, datafile) - bam_add_dependency(outputdatafile, scriptfile) + + if sourcefile then + sourcefile = Path(sourcefile) + bam_add_job("dc_source", sourcefile, datafile, scriptfile) + bam_add_dependency(sourcefile, datafile) + bam_add_dependency(sourcefile, scriptfile) + bam_add_dependency(sourcefile, headerfile) + end + + if outputdatafile then + outputdatafile = Path(outputdatafile) + bam_add_job("dc_cdata", outputdatafile, datafile, scriptfile) + bam_add_dependency(outputdatafile, datafile) + bam_add_dependency(outputdatafile, scriptfile) + end + return {cdata = outputdatafile, header=headerfile, source=sourcefile} end @@ -89,6 +131,13 @@ clientdata = DataCompile( "src/game/client/data/client_data.cpp", "src/game/client/data/client_internal.cpp") +networkdata = DataCompile( + "datasrc/teewars.ds", + "datasrc/network.dts", + "src/game/protocol_ids.h") + +nethash = CHash("src/game/nethash.c", "src/engine/protocol.h", "src/game/game_protocol.h", networkdata.header) + client_link_other = {} if family == "windows" then client_link_other = {ResCompile("other/icons/teewars.rc")} @@ -171,7 +220,7 @@ function build(settings) server = Compile(engine_settings, Collect("src/engine/server/*.c")) masterserver = Compile(settings, Collect("src/mastersrv/*.cpp")) - game_shared = Compile(settings, Collect("src/game/*.cpp")) + game_shared = Compile(settings, Collect("src/game/*.cpp"), nethash) game_client = Compile(settings, Collect("src/game/client/*.cpp"), clientdata.source, clientdata.cdata) game_server = Compile(settings, Collect("src/game/server/*.cpp"), serverdata.source, serverdata.cdata) editor = Compile(settings, Collect("src/editor/*.cpp")) diff --git a/scripts/cmd5.py b/scripts/cmd5.py new file mode 100644 index 000000000..2e20ff5be --- /dev/null +++ b/scripts/cmd5.py @@ -0,0 +1,32 @@ +import md5, sys, re +m = md5.new() + +alphanum = "0123456789abcdefghijklmnopqrstuvwzyxABCDEFGHIJKLMNOPQRSTUVWXYZ_" + +def cstrip(lines): + d = "" + for l in lines: + l = re.sub("#.*", "", l) + l = re.sub("//.*", "", l) + d += l + " " + d = re.sub("\/\*.*?\*/", "", d) # remove /* */ comments + d = d.replace("\t", " ") # tab to space + d = re.sub(" *", " ", d) # remove double spaces + d = re.sub("", "", d) # remove /* */ comments + + d = d.strip() + + # this eats up cases like 'n {' + i = 1 + while i < len(d)-2: + if d[i] == ' ': + if not (d[i-1] in alphanum and d[i+1] in alphanum): + d = d[:i] + d[i+1:] + i += 1 + return d + +f = "" +for filename in sys.argv[1:]: + f += cstrip([l.strip() for l in file(filename)]) + +print '#define TEEWARS_NETVERSION_HASH "%s"' % md5.new(f).hexdigest().lower()[16:] diff --git a/src/engine/client/client.c b/src/engine/client/client.c index ab4b71091..fe8a73054 100644 --- a/src/engine/client/client.c +++ b/src/engine/client/client.c @@ -9,8 +9,6 @@ #include #include "ui.h" -#include - #include #include #include @@ -152,7 +150,7 @@ static void client_send_info() game_start_time = -1; msg_pack_start_system(NETMSG_INFO, MSGFLAG_VITAL); - msg_pack_string(TEEWARS_NETVERSION_STRING, 64); + msg_pack_string(modc_net_version(), 128); msg_pack_string(config.player_name, 128); msg_pack_string(config.clan_name, 128); msg_pack_string(config.password, 128); @@ -717,6 +715,7 @@ static void client_run(const char *direct_connect_server) // init the mod modc_init(); + dbg_msg("client", "version %s", modc_net_version()); // open socket NETADDR4 bindaddr; diff --git a/src/engine/interface.h b/src/engine/interface.h index 010a393e4..a46b826f5 100644 --- a/src/engine/interface.h +++ b/src/engine/interface.h @@ -708,6 +708,13 @@ int modmenu_render(int ingame); void modc_message(int msg); void mods_message(int msg, int client_id); +const char *modc_net_version(); +const char *mods_net_version(); + +// unused +// const char *modc_version(); +// const char *mods_version(); + /* server */ int server_getclientinfo(int client_id, CLIENT_INFO *info); int server_tick(); diff --git a/src/engine/server/server.c b/src/engine/server/server.c index b31c2a6cb..2c568e07b 100644 --- a/src/engine/server/server.c +++ b/src/engine/server/server.c @@ -11,7 +11,6 @@ #include #include -#include #include #include @@ -366,11 +365,11 @@ static void server_process_client_packet(NETPACKET *packet) { char version[64]; strncpy(version, msg_unpack_string(), 64); - if(strcmp(version, TEEWARS_NETVERSION_STRING) != 0) + if(strcmp(version, mods_net_version()) != 0) { // OH FUCK! wrong version, drop him char reason[256]; - sprintf(reason, "wrong version. server is running %s.", TEEWARS_NETVERSION_STRING); + sprintf(reason, "wrong version. server is running %s.", mods_net_version()); netserver_drop(net, cid, reason); return; } @@ -545,6 +544,7 @@ static int server_run() } mods_init(); + dbg_msg("server", "version %s", mods_net_version()); int64 time_per_tick = time_freq()/SERVER_TICK_SPEED; int64 time_per_heartbeat = time_freq() * 30; @@ -657,3 +657,4 @@ int main(int argc, char **argv) server_run(); return 0; } + diff --git a/src/engine/versions.h b/src/engine/versions.h deleted file mode 100644 index 001542e33..000000000 --- a/src/engine/versions.h +++ /dev/null @@ -1,3 +0,0 @@ -#define TEEWARS_NETVERSION 0xffffffff -#define TEEWARS_NETVERSION_STRING "development" -#define TEEWARS_VERSION "development" diff --git a/src/game/client/game_client.cpp b/src/game/client/game_client.cpp index e5969fcfb..2e0933087 100644 --- a/src/game/client/game_client.cpp +++ b/src/game/client/game_client.cpp @@ -9,6 +9,7 @@ extern "C" { }; #include "../game.h" +#include "../version.h" #include "mapres_image.h" #include "mapres_tilemap.h" #include "data.h" @@ -2204,3 +2205,6 @@ extern "C" void modc_message(int msg) client_datas[cid].emoticon_start = client_tick(); } } + + +extern "C" const char *modc_net_version() { return TEEWARS_NETVERSION; } diff --git a/src/game/client/menu.cpp b/src/game/client/menu.cpp index 1e7f1edc9..a307d1760 100644 --- a/src/game/client/menu.cpp +++ b/src/game/client/menu.cpp @@ -8,12 +8,12 @@ extern "C" { #include #include - #include #include #include } #include "../mapres.h" +#include "../version.h" #include "mapres_image.h" #include "mapres_tilemap.h" @@ -1289,7 +1289,7 @@ int render_popup(const char *caption, const char *text, const char *button_text) ui_do_label(x+w/2-tw/2, y+20, caption, 48.0f); tw = gfx_pretty_text_width(32.0f, text, -1); - ui_do_label(x+w/2-tw/2, y+130, text, 32.0f); + gfx_pretty_text(x+w/2-tw/2, y+130, 32.0f, text, -1); if(button_text) { @@ -1366,6 +1366,8 @@ static int menu_render(bool ingame) { ui_do_image(data->images[IMAGE_BANNER].id, 200, 20, 512, 128); ui_do_label(20.0f, 600.0f-40.0f, "Version: " TEEWARS_VERSION, 36); + if(config.debug) + ui_do_label(20.0f, 600.0f-60.0f, "Nethash: " TEEWARS_NETVERSION_HASH, 24); } } else diff --git a/src/game/game.h b/src/game/game.h index 45a19105c..5b860036e 100644 --- a/src/game/game.h +++ b/src/game/game.h @@ -4,6 +4,8 @@ #include "../engine/interface.h" #include "mapres_col.h" +#include "game_protocol.h" + inline vec2 get_direction(int angle) { float a = angle/256.0f; @@ -25,161 +27,6 @@ inline float get_angle(vec2 dir) inline bool col_check_point(float x, float y) { return col_check_point((int)x, (int)y) != 0; } inline bool col_check_point(vec2 p) { return col_check_point(p.x, p.y); } -// Network stuff - -enum -{ - OBJTYPE_NULL=0, - OBJTYPE_GAME, - OBJTYPE_PLAYER, - OBJTYPE_PROJECTILE, - OBJTYPE_POWERUP, - OBJTYPE_FLAG, - EVENT_EXPLOSION, - EVENT_DAMAGEINDICATION, - EVENT_SOUND, - EVENT_SMOKE, - EVENT_SPAWN, - EVENT_DEATH, -}; - -enum -{ - MSG_NULL=0, - MSG_SAY, - MSG_CHAT, - MSG_SETNAME, - MSG_KILLMSG, - MSG_SWITCHTEAM, - MSG_JOIN, - MSG_QUIT, - MSG_EMOTICON, - MSG_CHANGENAME, -}; - -enum -{ - EMOTE_NORMAL=0, - EMOTE_PAIN, - EMOTE_HAPPY, - EMOTE_SURPRISE, - EMOTE_ANGRY, - EMOTE_BLINK, -}; - -enum -{ - STATE_UNKNOWN=0, - STATE_PLAYING, - STATE_IN_MENU, - STATE_CHATTING, -}; - -struct player_input -{ - int left; - int right; - - int target_x; - int target_y; - - int jump; - int fire; - int hook; - int blink; - int activeweapon; - int state; -}; - - -struct ev_explosion -{ - int x, y; -}; - -struct ev_spawn -{ - int x, y; -}; - -struct ev_death -{ - int x, y; -}; - -struct ev_sound -{ - int x, y; - int sound; // if (0x80000000 flag is set -> looping) if (0x40000000 is set -> stop looping -}; - -struct ev_damageind -{ - int x, y; - int angle; -}; - -struct obj_game -{ - int round_start_tick; - int game_over; - int sudden_death; - int paused; - - int score_limit; - int time_limit; - int gametype; -}; - -struct obj_projectile -{ - int type; - int x, y; - int vx, vy; // should be an angle instead -}; - -struct obj_powerup -{ - int x, y; - int type; // why do we need two types? - int subtype; -}; - -struct obj_flag -{ - int x, y; - int team; -}; - -struct obj_player -{ - int local; - int clientid; - int state; - - int health; - int armor; - int ammocount; - - int x, y; - int vx, vy; - int angle; - - int weapon; // current active weapon - - int attacktick; // num attack ticks left of current attack - - int score; - int latency; - int latency_flux; - int emote; - - int hook_active; - int hook_x, hook_y; - int team; -}; - - struct mapres_spawnpoint { int x, y; diff --git a/src/game/game_protocol.h b/src/game/game_protocol.h new file mode 100644 index 000000000..f04df1483 --- /dev/null +++ b/src/game/game_protocol.h @@ -0,0 +1,154 @@ +// NOTE: Be very careful when editing this file as it will change the network version + +// Network stuff +enum +{ + OBJTYPE_NULL=0, + OBJTYPE_GAME, + OBJTYPE_PLAYER, + OBJTYPE_PROJECTILE, + OBJTYPE_POWERUP, + OBJTYPE_FLAG, + EVENT_EXPLOSION, + EVENT_DAMAGEINDICATION, + EVENT_SOUND, + EVENT_SMOKE, + EVENT_SPAWN, + EVENT_DEATH, +}; + +enum +{ + MSG_NULL=0, + MSG_SAY, + MSG_CHAT, + MSG_SETNAME, + MSG_KILLMSG, + MSG_SWITCHTEAM, + MSG_JOIN, + MSG_QUIT, + MSG_EMOTICON, + MSG_CHANGENAME, +}; + +enum +{ + EMOTE_NORMAL=0, + EMOTE_PAIN, + EMOTE_HAPPY, + EMOTE_SURPRISE, + EMOTE_ANGRY, + EMOTE_BLINK, +}; + +enum +{ + STATE_UNKNOWN=0, + STATE_PLAYING, + STATE_IN_MENU, + STATE_CHATTING, +}; + +struct player_input +{ + int left; + int right; + + int target_x; + int target_y; + + int jump; + int fire; + int hook; + int blink; + int activeweapon; + int state; +}; + + +struct ev_explosion +{ + int x, y; +}; + +struct ev_spawn +{ + int x, y; +}; + +struct ev_death +{ + int x, y; +}; + +struct ev_sound +{ + int x, y; + int sound; // if (0x80000000 flag is set -> looping) if (0x40000000 is set -> stop looping +}; + +struct ev_damageind +{ + int x, y; + int angle; +}; + +struct obj_game +{ + int round_start_tick; + int game_over; + int sudden_death; + int paused; + + int score_limit; + int time_limit; + int gametype; +}; + +struct obj_projectile +{ + int type; + int x, y; + int vx, vy; // should be an angle instead +}; + +struct obj_powerup +{ + int x, y; + int type; // why do we need two types? + int subtype; +}; + +struct obj_flag +{ + int x, y; + int team; +}; + +struct obj_player +{ + int local; + int clientid; + int state; + + int health; + int armor; + int ammocount; + + int x, y; + int vx, vy; + int angle; + + int weapon; // current active weapon + + int attacktick; // num attack ticks left of current attack + + int score; + int latency; + int latency_flux; + int emote; + + int hook_active; + int hook_x, hook_y; + int team; +}; diff --git a/src/game/server/game_server.cpp b/src/game/server/game_server.cpp index f7bf976ea..711a0d1b9 100644 --- a/src/game/server/game_server.cpp +++ b/src/game/server/game_server.cpp @@ -3,6 +3,7 @@ #include #include #include "../game.h" +#include "../version.h" #include "data.h" #include "game_server.h" @@ -2189,3 +2190,5 @@ void mods_init() void mods_shutdown() {} void mods_presnap() {} void mods_postsnap() {} + +extern "C" const char *mods_net_version() { return TEEWARS_NETVERSION; } diff --git a/src/game/version.h b/src/game/version.h new file mode 100644 index 000000000..10a03af0a --- /dev/null +++ b/src/game/version.h @@ -0,0 +1,3 @@ +#include "nethash.c" +#define TEEWARS_VERSION "0.3.0-dev" +#define TEEWARS_NETVERSION "0.3 " TEEWARS_NETVERSION_HASH