From 0a80807da0987ca2d3922a0534c5673bf3a7c928 Mon Sep 17 00:00:00 2001 From: terencehill Date: Fri, 29 May 2020 21:58:31 +0200 Subject: [PATCH] Inventory: check at runtime if the Inventory_groups_* costants are correct, automatically detect the correct number of bytes to read/write based on their values --- qcsrc/common/items/inventory.qh | 26 ++++++++++++++++++++------ qcsrc/lib/net.qh | 14 ++++++++++++++ 2 files changed, 34 insertions(+), 6 deletions(-) diff --git a/qcsrc/common/items/inventory.qh b/qcsrc/common/items/inventory.qh index 5109628e8f..ca53f718d1 100644 --- a/qcsrc/common/items/inventory.qh +++ b/qcsrc/common/items/inventory.qh @@ -15,9 +15,23 @@ ENDCLASS(Inventory) REGISTER_NET_LINKED(ENT_CLIENT_INVENTORY) -const int Inventory_groups_minor = 8; // exactly 1 byte -const int Inventory_groups_major = 4; // ceil(REGISTRY_MAX(Items) / Inventory_groups_minor) +const int Inventory_groups_minor = 8; // must be a multiple of 8 (one byte) to optimize bandwidth usage +const int Inventory_groups_major = 4; // must be >= ceil(REGISTRY_COUNT(Items) / Inventory_groups_minor) +#endif +// no need to perform these checks on both server and client +#ifdef CSQC +STATIC_INIT(Inventory) +{ + if (Inventory_groups_minor / 8 != floor(Inventory_groups_minor / 8)) + error("Inventory_groups_minor is not a multiple of 8."); + int min_major_value = ceil(REGISTRY_COUNT(Items) / Inventory_groups_minor); + if (Inventory_groups_major < min_major_value) + error(sprintf("Inventory_groups_major can not be < %d.", min_major_value)); +} +#endif + +#ifdef SVQC #define G_MAJOR(id) (floor((id) / Inventory_groups_minor)) #define G_MINOR(id) ((id) % Inventory_groups_minor) #endif @@ -28,12 +42,12 @@ NET_HANDLE(ENT_CLIENT_INVENTORY, bool isnew) { make_pure(this); g_inventory = this; - const int majorBits = ReadByte(); + const int majorBits = Readbits(Inventory_groups_major); for (int i = 0; i < Inventory_groups_major; ++i) { if (!(majorBits & BIT(i))) { continue; } - const int minorBits = ReadByte(); + const int minorBits = Readbits(Inventory_groups_minor); for (int j = 0; j < Inventory_groups_minor; ++j) { if (!(minorBits & BIT(j))) { continue; @@ -72,15 +86,15 @@ void Inventory_Write(Inventory data) minorBitsArr[maj] = BITSET(minorBitsArr[maj], BIT(G_MINOR(it.m_id)), true); } }); - WriteByte(MSG_ENTITY, majorBits); + Writebits(MSG_ENTITY, majorBits, Inventory_groups_major); for (int i = 0; i < Inventory_groups_major; ++i) { if (!(majorBits & BIT(i))) continue; const int minorBits = minorBitsArr[i]; - WriteByte(MSG_ENTITY, minorBits); + Writebits(MSG_ENTITY, minorBits, Inventory_groups_minor); for (int j = 0; j < Inventory_groups_minor; ++j) { if (!(minorBits & BIT(j))) diff --git a/qcsrc/lib/net.qh b/qcsrc/lib/net.qh index 71950fb73c..3cec9fd9ba 100644 --- a/qcsrc/lib/net.qh +++ b/qcsrc/lib/net.qh @@ -358,6 +358,13 @@ MACRO_END #define ReadVector() vec3(ReadFloat(), ReadFloat(), ReadFloat()) #define ReadVector2D() vec2(ReadFloat(), ReadFloat()) + int Readbits(int num) + { + if (num > 16) return ReadInt24_t(); + if (num > 8) return ReadShort(); + return ReadByte(); + } + float ReadApproxPastTime() { float dt = ReadByte(); @@ -391,6 +398,13 @@ MACRO_END #define WriteVector(to, v) MACRO_BEGIN WriteFloat(to, v.x); WriteFloat(to, v.y); WriteFloat(to, v.z); MACRO_END #define WriteVector2D(to, v) MACRO_BEGIN WriteFloat(to, v.x); WriteFloat(to, v.y); MACRO_END + void Writebits(float dst, float val, int num) + { + if (num > 16) { WriteInt24_t(dst, val); return; } + if (num > 8) { WriteShort(dst, val); return; } + WriteByte(dst, val); + } + // this will use the value: // 128 // accuracy near zero is APPROXPASTTIME_MAX/(256*255) -- 2.39.2