From: TimePath Date: Fri, 6 Nov 2015 02:34:28 +0000 (+1100) Subject: Registry: network and verify checksums on connect X-Git-Tag: xonotic-v0.8.2~1700 X-Git-Url: https://git.rm.cloudns.org/?a=commitdiff_plain;h=910d5295d631181792d354f44a80b63dc3e629eb;p=xonotic%2Fxonotic-data.pk3dir.git Registry: network and verify checksums on connect --- diff --git a/qcsrc/client/main.qc b/qcsrc/client/main.qc index 523786e41..badc78ce6 100644 --- a/qcsrc/client/main.qc +++ b/qcsrc/client/main.qc @@ -934,8 +934,6 @@ NET_HANDLE(ENT_CLIENT_SCORES_INFO, bool isnew) NET_HANDLE(ENT_CLIENT_INIT, bool isnew) { - make_pure(this); - nb_pb_period = ReadByte() / 32; //Accuracy of 1/32th hook_shotorigin[0] = decompressShotOrigin(ReadInt24_t()); diff --git a/qcsrc/common/buffs/all.qh b/qcsrc/common/buffs/all.qh index 073e3b3aa..beabaa755 100644 --- a/qcsrc/common/buffs/all.qh +++ b/qcsrc/common/buffs/all.qh @@ -11,6 +11,7 @@ REGISTRY(Buffs, BITS(4)) #define Buffs_from(i) _Buffs_from(i, BUFF_Null) REGISTER_REGISTRY(RegisterBuffs) +REGISTRY_CHECK(Buffs) #define REGISTER_BUFF(id) \ REGISTER(RegisterBuffs, BUFF, Buffs, id, m_id, NEW(Buff)); \ diff --git a/qcsrc/common/constants.qh b/qcsrc/common/constants.qh index 8c94c37ca..192b8f6a1 100644 --- a/qcsrc/common/constants.qh +++ b/qcsrc/common/constants.qh @@ -53,6 +53,13 @@ const int RACE_NET_SERVER_RANKINGS = 11; const int RACE_NET_SERVER_STATUS = 12; const int RANKINGS_CNT = 15; +REGISTER_NET_LINKED(_ENT_CLIENT_INIT) +#ifdef CSQC +NET_HANDLE(_ENT_CLIENT_INIT, bool isnew) { return true; } +#endif +/** Sent as a temp entity from a persistent linked entity */ +REGISTER_NET_TEMP(ENT_CLIENT_INIT) + REGISTER_NET_LINKED(ENT_CLIENT_ENTCS) REGISTER_NET_LINKED(ENT_CLIENT_SCORES_INFO) REGISTER_NET_LINKED(ENT_CLIENT_SCORES) @@ -60,7 +67,6 @@ REGISTER_NET_LINKED(ENT_CLIENT_TEAMSCORES) REGISTER_NET_LINKED(ENT_CLIENT_NAGGER) // flags [votecalledvote] REGISTER_NET_LINKED(ENT_CLIENT_RADARLINK) // flags [startorigin] [endorigin] [startcolor+16*endcolor] REGISTER_NET_LINKED(ENT_CLIENT_PROJECTILE) -REGISTER_NET_LINKED(ENT_CLIENT_INIT) REGISTER_NET_LINKED(ENT_CLIENT_MAPVOTE) REGISTER_NET_LINKED(ENT_CLIENT_CLIENTDATA) REGISTER_NET_LINKED(ENT_CLIENT_RANDOMSEED) diff --git a/qcsrc/common/deathtypes/all.qh b/qcsrc/common/deathtypes/all.qh index 42aa6bb52..b3a671d26 100644 --- a/qcsrc/common/deathtypes/all.qh +++ b/qcsrc/common/deathtypes/all.qh @@ -6,6 +6,7 @@ REGISTRY(Deathtypes, BITS(8)) #define Deathtypes_from(i) _Deathtypes_from(i, NULL) REGISTER_REGISTRY(RegisterDeathtypes) +REGISTRY_CHECK(Deathtypes) .entity death_msgself; .entity death_msgmurder; diff --git a/qcsrc/common/effects/all.qh b/qcsrc/common/effects/all.qh index 87bd63e75..58284fb0e 100644 --- a/qcsrc/common/effects/all.qh +++ b/qcsrc/common/effects/all.qh @@ -11,6 +11,7 @@ void Send_Effect_(string eff_name, vector eff_loc, vector eff_vel, int eff_cnt); REGISTRY(Effects, BITS(8)) #define Effects_from(i) _Effects_from(i, EFFECT_Null) REGISTER_REGISTRY(RegisterEffects) +REGISTRY_CHECK(Effects) #define EFFECT(istrail, name, realname) \ REGISTER(RegisterEffects, EFFECT, Effects, name, m_id, Create_Effect_Entity(realname, istrail)); diff --git a/qcsrc/common/items/all.qh b/qcsrc/common/items/all.qh index 69805a568..809398bb2 100644 --- a/qcsrc/common/items/all.qh +++ b/qcsrc/common/items/all.qh @@ -12,6 +12,7 @@ REGISTER_REGISTRY(RegisterItems) #define REGISTER_ITEM(id, class) REGISTER(RegisterItems, ITEM, Items, id, m_id, NEW(class)) REGISTRY_SORT(Items, 0) +REGISTRY_CHECK(Items) STATIC_INIT(Items) { FOREACH(Items, true, LAMBDA(it.m_id = i)); } void Dump_Items(); diff --git a/qcsrc/common/mapinfo.qh b/qcsrc/common/mapinfo.qh index 04ea78e4c..055777bf8 100644 --- a/qcsrc/common/mapinfo.qh +++ b/qcsrc/common/mapinfo.qh @@ -45,6 +45,7 @@ ENDCLASS(Gametype) REGISTRY(Gametypes, BITS(4)) #define Gametypes_from(i) _Gametypes_from(i, NULL) REGISTER_REGISTRY(RegisterGametypes) +REGISTRY_CHECK(Gametypes) int MAPINFO_TYPE_ALL; #define REGISTER_GAMETYPE(hname, sname, g_name, NAME, gteamplay, mutators, defaults, gdescription) \ int MAPINFO_TYPE_##NAME; \ diff --git a/qcsrc/common/minigames/cl_minigames.qh b/qcsrc/common/minigames/cl_minigames.qh index ab5ffc7ea..6fb461c6b 100644 --- a/qcsrc/common/minigames/cl_minigames.qh +++ b/qcsrc/common/minigames/cl_minigames.qh @@ -114,6 +114,7 @@ void HUD_MinigameMenu_CustomEntry(entity parent, string message, string event_ar REGISTRY(Minigames, BITS(3)) #define Minigames_from(i) _Minigames_from(i, NULL) REGISTER_REGISTRY(RegisterMinigames) +REGISTRY_CHECK(Minigames) #define REGISTER_MINIGAME(name,nicename) \ REGISTER(RegisterMinigames, MINIGAME, Minigames, name, m_id, new(minigame_descriptor)); \ void name##_hud_board(vector, vector); \ diff --git a/qcsrc/common/minigames/sv_minigames.qh b/qcsrc/common/minigames/sv_minigames.qh index 422e78081..f60b2d6db 100644 --- a/qcsrc/common/minigames/sv_minigames.qh +++ b/qcsrc/common/minigames/sv_minigames.qh @@ -49,6 +49,7 @@ bool minigame_SendEntity(entity this, entity to, int sf); REGISTRY(Minigames, BITS(3)) #define Minigames_from(i) _Minigames_from(i, NULL) REGISTER_REGISTRY(RegisterMinigames) +REGISTRY_CHECK(Minigames) #define REGISTER_MINIGAME(name,nicename) \ REGISTER(RegisterMinigames, MINIGAME, Minigames, name, m_id, new(minigame_descriptor)); \ int name##_server_event(entity, string, ...); \ diff --git a/qcsrc/common/monsters/all.qh b/qcsrc/common/monsters/all.qh index 5e46e8a80..fd5978c91 100644 --- a/qcsrc/common/monsters/all.qh +++ b/qcsrc/common/monsters/all.qh @@ -9,6 +9,7 @@ REGISTRY(Monsters, BITS(5)) #define Monsters_from(i) _Monsters_from(i, MON_Null) #define get_monsterinfo(i) Monsters_from(i) REGISTER_REGISTRY(RegisterMonsters) +REGISTRY_CHECK(Monsters) const int MON_FIRST = 1; #define MON_LAST (Monsters_COUNT - 1) /** If you register a new monster, make sure to add it to all.inc */ diff --git a/qcsrc/common/mutators/mutator/waypoints/all.qh b/qcsrc/common/mutators/mutator/waypoints/all.qh index e04629b6f..3769412ec 100644 --- a/qcsrc/common/mutators/mutator/waypoints/all.qh +++ b/qcsrc/common/mutators/mutator/waypoints/all.qh @@ -6,6 +6,8 @@ REGISTRY(Waypoints, BITS(6)) #define Waypoints_from(i) _Waypoints_from(i, WP_Null) REGISTER_REGISTRY(RegisterWaypoints) +REGISTRY_CHECK(Waypoints) + /** If you register a new waypoint, make sure to add it to all.inc */ #define REGISTER_WAYPOINT_(id, init) REGISTER(RegisterWaypoints, WP, Waypoints, id, m_id, init) @@ -29,6 +31,8 @@ ENDCLASS(Waypoint) REGISTRY(RadarIcons, BITS(7)) #define RadarIcons_from(i) _RadarIcons_from(i, RADARICON_NONE) REGISTER_REGISTRY(RegisterRadarIcons) +REGISTRY_CHECK(RadarIcons) + .int m_radaricon; #define REGISTER_RADARICON(id, num) REGISTER(RegisterRadarIcons, RADARICON, RadarIcons, id, m_id, new(RadarIcon)) { make_pure(this); this.m_radaricon = num; this.netname = #id; } diff --git a/qcsrc/common/nades/all.qh b/qcsrc/common/nades/all.qh index 9b2b6ec35..235dd97dd 100644 --- a/qcsrc/common/nades/all.qh +++ b/qcsrc/common/nades/all.qh @@ -24,6 +24,8 @@ const int PROJECTILE_NADE_MONSTER_BURN = 83; REGISTRY(Nades, BITS(4)) #define Nades_from(i) _Nades_from(i, NADE_TYPE_Null) REGISTER_REGISTRY(RegisterNades) +REGISTRY_CHECK(Nades) + #define REGISTER_NADE(id) REGISTER(RegisterNades, NADE_TYPE, Nades, id, m_id, NEW(Nade)) CLASS(Nade, Object) diff --git a/qcsrc/common/turrets/all.qh b/qcsrc/common/turrets/all.qh index 0848478bf..fa6ef43d4 100644 --- a/qcsrc/common/turrets/all.qh +++ b/qcsrc/common/turrets/all.qh @@ -10,6 +10,7 @@ REGISTRY(Turrets, BITS(5)) #define Turrets_from(i) _Turrets_from(i, TUR_Null) #define get_turretinfo(i) Turrets_from(i) REGISTER_REGISTRY(RegisterTurrets) +REGISTRY_CHECK(Turrets) GENERIC_COMMAND(dumpturrets, "Dump all turrets into turrets_dump.txt") diff --git a/qcsrc/common/vehicles/all.qh b/qcsrc/common/vehicles/all.qh index f5d643431..d2d943c4e 100644 --- a/qcsrc/common/vehicles/all.qh +++ b/qcsrc/common/vehicles/all.qh @@ -7,6 +7,8 @@ REGISTRY(Vehicles, BITS(3)) #define Vehicles_from(i) _Vehicles_from(i, VEH_Null) #define get_vehicleinfo(i) Vehicles_from(i) REGISTER_REGISTRY(RegisterVehicles) +REGISTRY_CHECK(Vehicles) + const int VEH_FIRST = 1; #define VEH_LAST (Vehicles_COUNT - 1) diff --git a/qcsrc/common/weapons/all.qh b/qcsrc/common/weapons/all.qh index 584404917..10e804b47 100644 --- a/qcsrc/common/weapons/all.qh +++ b/qcsrc/common/weapons/all.qh @@ -140,6 +140,7 @@ REGISTER_WEAPON(Null, NEW(Weapon)); #define WEP_IMPULSE_END bound(WEP_IMPULSE_BEGIN, WEP_IMPULSE_BEGIN + (Weapons_COUNT - 1) - 1, 253) REGISTRY_SORT(Weapons, WEP_HARDCODED_IMPULSES + 1) +REGISTRY_CHECK(Weapons) STATIC_INIT(register_weapons_done) { diff --git a/qcsrc/lib/_all.inc b/qcsrc/lib/_all.inc index 416978814..cffa8f722 100644 --- a/qcsrc/lib/_all.inc +++ b/qcsrc/lib/_all.inc @@ -55,6 +55,7 @@ #include "progname.qh" #include "random.qc" #include "registry.qh" +#include "registry_net.qh" #include "replicate.qh" #include "self.qh" #include "sortlist.qc" diff --git a/qcsrc/lib/net.qh b/qcsrc/lib/net.qh index 7e3a1f1cb..f6013f97a 100644 --- a/qcsrc/lib/net.qh +++ b/qcsrc/lib/net.qh @@ -112,6 +112,7 @@ REGISTRY(LinkedEntities, BITS(8) - 1) #define LinkedEntities_from(i) _LinkedEntities_from(i, NULL) REGISTER_REGISTRY(RegisterLinkedEntities) REGISTRY_SORT(LinkedEntities, 0) +REGISTRY_CHECK(LinkedEntities) STATIC_INIT(RegisterLinkedEntities_renumber) { for (int i = 0; i < LinkedEntities_COUNT; ++i) @@ -141,6 +142,7 @@ REGISTRY(TempEntities, BITS(8) - 80) #define TempEntities_from(i) _TempEntities_from(i, NULL) REGISTER_REGISTRY(RegisterTempEntities) REGISTRY_SORT(TempEntities, 0) +REGISTRY_CHECK(TempEntities) STATIC_INIT(RegisterTempEntities_renumber) { for (int i = 0; i < TempEntities_COUNT; ++i) diff --git a/qcsrc/lib/registry.qh b/qcsrc/lib/registry.qh index eb8372f76..59ddf25ff 100644 --- a/qcsrc/lib/registry.qh +++ b/qcsrc/lib/registry.qh @@ -94,10 +94,21 @@ STATIC_INIT(Registry_sort_##id) \ { \ heapsort(id##_COUNT - (skip), _REGISTRY_SWAP_##id, _REGISTRY_CMP_##id, NULL); \ - } \ - REGISTRY_CHECK(id) + } + +#define REGISTRY_HASH(id) Registry_hash_##id + +[[accumulate]] void Registry_check(string r, string server) { } +[[accumulate]] void Registry_send_all() { } + +#ifdef SVQC +void Registry_send(string id, string hash); +#else +#define Registry_send(id, hash) +#endif #define REGISTRY_CHECK(id) \ + string REGISTRY_HASH(id); \ STATIC_INIT(Registry_check_##id) \ { \ string algo = "SHA256"; \ @@ -105,7 +116,20 @@ string s = ""; \ FOREACH(id, true, LAMBDA(s = strcat(s, join, it.registered_id))); \ s = substring(s, strlen(join), -1); \ - LOG_TRACEF(#id ": %s\n[%s]\n", digest_hex(algo, s), s); \ - } + string h = REGISTRY_HASH(id) = strzone(digest_hex(algo, s)); \ + LOG_TRACEF(#id ": %s\n[%s]\n", h, s); \ + } \ + [[accumulate]] void Registry_check(string r, string sv) \ + { \ + if (r == #id) \ + { \ + string cl = REGISTRY_HASH(id); \ + if (cl != sv) \ + { \ + LOG_FATALF("client/server mismatch (%s).\nCL: %s\nSV: %s\n", r, cl, sv); \ + } \ + } \ + } \ + [[accumulate]] void Registry_send_all() { Registry_send(#id, REGISTRY_HASH(id)); } \ #endif diff --git a/qcsrc/lib/registry_net.qh b/qcsrc/lib/registry_net.qh new file mode 100644 index 000000000..14e4dbc3c --- /dev/null +++ b/qcsrc/lib/registry_net.qh @@ -0,0 +1,28 @@ +#ifndef REGISTRY_NET_H +#define REGISTRY_NET_H + +#include "net.qh" + +REGISTER_NET_TEMP(registry) + +#ifdef CSQC +NET_HANDLE(registry, bool isnew) +{ + string k = ReadString(); + string v = ReadString(); + Registry_check(k, v); + return true; +} +#endif + +#ifdef SVQC +void Registry_send(string id, string hash) +{ + int channel = MSG_ONE; + WriteHeader(channel, registry); + WriteString(channel, id); + WriteString(channel, hash); +} +#endif + +#endif diff --git a/qcsrc/server/cl_client.qc b/qcsrc/server/cl_client.qc index a604055b8..4994c1936 100644 --- a/qcsrc/server/cl_client.qc +++ b/qcsrc/server/cl_client.qc @@ -630,36 +630,40 @@ void PutClientInServer() // changes and just have a console command to update this? bool ClientInit_SendEntity(entity this, entity to, int sf) { - WriteHeader(MSG_ENTITY, ENT_CLIENT_INIT); - WriteByte(MSG_ENTITY, g_nexball_meter_period * 32); - WriteInt24_t(MSG_ENTITY, compressShotOrigin(hook_shotorigin[0])); - WriteInt24_t(MSG_ENTITY, compressShotOrigin(hook_shotorigin[1])); - WriteInt24_t(MSG_ENTITY, compressShotOrigin(hook_shotorigin[2])); - WriteInt24_t(MSG_ENTITY, compressShotOrigin(hook_shotorigin[3])); - WriteInt24_t(MSG_ENTITY, compressShotOrigin(arc_shotorigin[0])); - WriteInt24_t(MSG_ENTITY, compressShotOrigin(arc_shotorigin[1])); - WriteInt24_t(MSG_ENTITY, compressShotOrigin(arc_shotorigin[2])); - WriteInt24_t(MSG_ENTITY, compressShotOrigin(arc_shotorigin[3])); + WriteHeader(MSG_ENTITY, _ENT_CLIENT_INIT); + return = true; + msg_entity = to; + Registry_send_all(); + int channel = MSG_ONE; + WriteHeader(channel, ENT_CLIENT_INIT); + WriteByte(channel, g_nexball_meter_period * 32); + WriteInt24_t(channel, compressShotOrigin(hook_shotorigin[0])); + WriteInt24_t(channel, compressShotOrigin(hook_shotorigin[1])); + WriteInt24_t(channel, compressShotOrigin(hook_shotorigin[2])); + WriteInt24_t(channel, compressShotOrigin(hook_shotorigin[3])); + WriteInt24_t(channel, compressShotOrigin(arc_shotorigin[0])); + WriteInt24_t(channel, compressShotOrigin(arc_shotorigin[1])); + WriteInt24_t(channel, compressShotOrigin(arc_shotorigin[2])); + WriteInt24_t(channel, compressShotOrigin(arc_shotorigin[3])); if(sv_foginterval && world.fog != "") - WriteString(MSG_ENTITY, world.fog); + WriteString(channel, world.fog); else - WriteString(MSG_ENTITY, ""); - WriteByte(MSG_ENTITY, self.count * 255.0); // g_balance_armor_blockpercent - WriteCoord(MSG_ENTITY, self.bouncefactor); // g_balance_mortar_bouncefactor // WEAPONTODO - WriteCoord(MSG_ENTITY, self.bouncestop); // g_balance_mortar_bouncestop - WriteCoord(MSG_ENTITY, self.ebouncefactor); // g_balance_mortar_bouncefactor - WriteCoord(MSG_ENTITY, self.ebouncestop); // g_balance_mortar_bouncestop - WriteByte(MSG_ENTITY, WEP_CVAR(vortex, secondary)); // client has to know if it should zoom or not // WEAPONTODO - WriteByte(MSG_ENTITY, WEP_CVAR(rifle, secondary)); // client has to know if it should zoom or not // WEAPONTODO - WriteByte(MSG_ENTITY, serverflags); // client has to know if it should zoom or not - WriteByte(MSG_ENTITY, WEP_CVAR(minelayer, limit)); // minelayer max mines // WEAPONTODO - WriteByte(MSG_ENTITY, WEP_CVAR_SEC(hagar, load_max)); // hagar max loadable rockets // WEAPONTODO - WriteCoord(MSG_ENTITY, autocvar_g_trueaim_minrange); - WriteByte(MSG_ENTITY, WEP_CVAR(porto, secondary)); // WEAPONTODO + WriteString(channel, ""); + WriteByte(channel, self.count * 255.0); // g_balance_armor_blockpercent + WriteCoord(channel, self.bouncefactor); // g_balance_mortar_bouncefactor // WEAPONTODO + WriteCoord(channel, self.bouncestop); // g_balance_mortar_bouncestop + WriteCoord(channel, self.ebouncefactor); // g_balance_mortar_bouncefactor + WriteCoord(channel, self.ebouncestop); // g_balance_mortar_bouncestop + WriteByte(channel, WEP_CVAR(vortex, secondary)); // client has to know if it should zoom or not // WEAPONTODO + WriteByte(channel, WEP_CVAR(rifle, secondary)); // client has to know if it should zoom or not // WEAPONTODO + WriteByte(channel, serverflags); // client has to know if it should zoom or not + WriteByte(channel, WEP_CVAR(minelayer, limit)); // minelayer max mines // WEAPONTODO + WriteByte(channel, WEP_CVAR_SEC(hagar, load_max)); // hagar max loadable rockets // WEAPONTODO + WriteCoord(channel, autocvar_g_trueaim_minrange); + WriteByte(channel, WEP_CVAR(porto, secondary)); // WEAPONTODO MUTATOR_CALLHOOK(Ent_Init); - return true; } void ClientInit_CheckUpdate()