Inventory system
authorTimePath <andrew.hardaker1995@gmail.com>
Wed, 13 May 2015 05:46:07 +0000 (15:46 +1000)
committerTimePath <andrew.hardaker1995@gmail.com>
Wed, 13 May 2015 05:46:07 +0000 (15:46 +1000)
Counts collected items and sends them with delta compression

qcsrc/client/main.qc
qcsrc/common/constants.qh
qcsrc/common/items/all.inc
qcsrc/common/items/all.qh
qcsrc/common/items/inventory.qh [new file with mode: 0644]
qcsrc/common/items/item.qh
qcsrc/common/items/item/pickup.qc [new file with mode: 0644]
qcsrc/common/items/item/pickup.qh
qcsrc/server/cl_client.qc
qcsrc/server/miscfunctions.qc
qcsrc/server/miscfunctions.qh

index ad727bf..0cedf8f 100644 (file)
@@ -859,6 +859,7 @@ void CSQC_Ent_Update(float bIsNewEntity)
                case ENT_CLIENT_WARPZONE_TELEPORTED: WarpZone_Teleported_Read(bIsNewEntity); break;
                case ENT_CLIENT_TRIGGER_MUSIC: Ent_ReadTriggerMusic(); break;
                case ENT_CLIENT_HOOK: Ent_ReadHook(bIsNewEntity, ENT_CLIENT_HOOK); break;
+               case ENT_CLIENT_INVENTORY: Inventory_Read(self); break;
                case ENT_CLIENT_ARC_BEAM: Ent_ReadArcBeam(bIsNewEntity); break;
                case ENT_CLIENT_ACCURACY: Ent_ReadAccuracy(); break;
                case ENT_CLIENT_AUXILIARYXHAIR: Net_AuXair2(bIsNewEntity); break;
index 45a65ab..8c7cb6b 100644 (file)
@@ -64,6 +64,7 @@ const int ENT_CLIENT_WARPZONE = 24;
 const int ENT_CLIENT_WARPZONE_CAMERA = 25;
 const int ENT_CLIENT_TRIGGER_MUSIC = 26;
 const int ENT_CLIENT_HOOK = 27;
+const int ENT_CLIENT_INVENTORY = 28;
 const int ENT_CLIENT_ARC_BEAM = 29; // WEAPONTODO: fix numbers
 const int ENT_CLIENT_ACCURACY = 30;
 const int ENT_CLIENT_SHOWNAMES = 31;
index f009bbe..2c4f1de 100644 (file)
@@ -3,4 +3,5 @@
 #include "item/buff.qc"
 #include "item/health.qc"
 #include "item/jetpack.qc"
+#include "item/pickup.qc"
 #include "item/powerup.qc"
index 7290b95..1786b42 100644 (file)
@@ -1,12 +1,12 @@
 #ifndef ALL_H
 #define ALL_H
 
-const int MAX_ITEMS = 23;
+const int MAX_ITEMS = 24;
 entity ITEMS[MAX_ITEMS];
 
 #define ITEMS_FOREACH(pred, body) do {      \
     for (int i = 0; i < ITEM_COUNT; i++) {  \
-        const entity it = ITEMS[i];         \
+        const noref entity it = ITEMS[i];   \
         if (pred) { body }                  \
     }                                       \
 } while(0)
@@ -14,25 +14,6 @@ entity ITEMS[MAX_ITEMS];
 void RegisterItems();
 void Dump_Items();
 
-#ifdef CSQC
-void ReadItems()
-{
-/*
-    const int flags = read();
-    for (int i = 0; i < MAX_ITEMS; i++) {
-        if (flags & BIT(i)) {
-            self.items[i] = read();
-        }
-    }
-*/
-}
 #endif
 
-#ifdef SVQC
-void WriteItems()
-{
-
-}
-#endif
-
-#endif
+#include "inventory.qh"
diff --git a/qcsrc/common/items/inventory.qh b/qcsrc/common/items/inventory.qh
new file mode 100644 (file)
index 0000000..9b277bf
--- /dev/null
@@ -0,0 +1,64 @@
+#ifndef INVENTORY_H
+#define INVENTORY_H
+
+#include "all.qh"
+#include "item/pickup.qh"
+
+entityclass(Inventory);
+/** Stores counts of items, the id being the index */
+class(Inventory) .int inv_items[MAX_ITEMS];
+
+/** Player inventory; Inventories also have one inventory for storing the previous state */
+.Inventory inventory;
+
+#ifdef CSQC
+void Inventory_Read(Inventory data)
+{
+    const int bits = ReadInt24_t();
+    ITEMS_FOREACH(bits & BIT(i), LAMBDA({
+        int prev = data.inv_items[i];
+        int next = data.inv_items[i] = ReadByte();
+        dprintf("%s: %.0f -> %.0f\n", ITEMS[i].m_name, prev, next);
+    }));
+}
+#endif
+
+#ifdef SVQC
+void Inventory_Write(Inventory data)
+{
+    int bits = 0;
+    ITEMS_FOREACH(true, LAMBDA({
+        .int idx = inv_items[i];
+        bits = BITSET(bits, BIT(i), data.inventory.(idx) != (data.inventory.(idx) = data.(idx)));
+    }));
+    WriteInt24_t(MSG_ENTITY, bits);
+    ITEMS_FOREACH(bits & BIT(i), LAMBDA({
+        WriteByte(MSG_ENTITY, data.inv_items[i]);
+    }));
+}
+#endif
+
+#ifdef SVQC
+bool Inventory_Send(entity to, int sf)
+{
+    WriteByte(MSG_ENTITY, ENT_CLIENT_INVENTORY);
+    entity e = self.owner;
+    if (IS_SPEC(e)) e = e.enemy;
+    Inventory data = e.inventory;
+    Inventory_Write(data);
+    return true;
+}
+
+void Inventory_new(entity e)
+{
+    Inventory inv = new(Inventory), bak = new(Inventory);
+    inv.classname = "inventory", bak.classname = "inventory";
+    inv.inventory = bak;
+    inv.drawonlytoclient = e;
+    Net_LinkEntity((inv.owner = e).inventory = inv, false, 0, Inventory_Send);
+}
+void Inventory_delete(entity e) { remove(e.inventory.inventory); remove(e.inventory); }
+void Inventory_update(entity e) { e.inventory.SendFlags = 0xFFFFFF; }
+#endif
+
+#endif
index 6ca1314..da4e7a4 100644 (file)
@@ -3,6 +3,7 @@
 #include "../oo.qh"
 #define ITEM_HANDLE(signal, ...) __Item_Send_##signal(__VA_ARGS__)
 CLASS(GameItem, Object)
+    ATTRIB(GameItem, m_id, int, 0)
     METHOD(GameItem, show, void(entity this))
     void GameItem_show(entity this) { print("A game item\n"); }
     void ITEM_HANDLE(Show, entity this) { this.show(this); }
@@ -15,6 +16,7 @@ int ITEM_COUNT;
     void RegisterItems_##id() {                 \
         const entity this = NEW(class);         \
         ITEM_##id = this;                       \
+        this.m_id = ITEM_COUNT;                 \
         ITEMS[ITEM_COUNT++] = this;             \
         body                                    \
     }                                           \
diff --git a/qcsrc/common/items/item/pickup.qc b/qcsrc/common/items/item/pickup.qc
new file mode 100644 (file)
index 0000000..35aac2b
--- /dev/null
@@ -0,0 +1,13 @@
+#include "pickup.qh"
+
+#ifdef SVQC
+bool ITEM_HANDLE(Pickup, entity this, entity item, entity player) {
+    bool b = this.giveTo(this, item, player);
+    if (b) {
+        dprintf("entity %i picked up %s\n", player, this.m_name);
+        player.inventory.inv_items[this.m_id]++;
+        Inventory_update(player);
+    }
+    return b;
+}
+#endif
index 47788f3..1875517 100644 (file)
@@ -16,7 +16,7 @@ CLASS(Pickup, GameItem)
     ATTRIB(Pickup, m_respawntimejitter, float(), func_null)
     METHOD(Pickup, giveTo, bool(entity this, entity item, entity player))
     bool Pickup_giveTo(entity this, entity item, entity player) { return Item_GiveTo(item, player); }
-    bool ITEM_HANDLE(Pickup, entity this, entity item, entity player) { printf("%s picked up %s\n", etos(player), this.m_name); return this.giveTo(this, item, player); }
+    bool ITEM_HANDLE(Pickup, entity this, entity item, entity player);
 #endif
 ENDCLASS(Pickup)
 
index 259b7e2..b73eebb 100644 (file)
@@ -35,6 +35,8 @@
 
 #include "../common/net_notice.qh"
 
+#include "../common/items/inventory.qh"
+
 #include "../common/monsters/sv_monsters.qh"
 
 #include "../warpzonelib/server.qh"
@@ -1096,6 +1098,7 @@ void ClientConnect (void)
        PlayerScore_Attach(self);
        ClientData_Attach();
        accuracy_init(self);
+       Inventory_new(self);
 
        bot_clientconnect();
 
@@ -1338,6 +1341,7 @@ void ClientDisconnect (void)
        bot_relinkplayerlist();
 
        accuracy_free(self);
+       Inventory_delete(self);
        ClientData_Detach();
        PlayerScore_Detach(self);
 
index 41f388e..5f663cc 100644 (file)
@@ -1270,7 +1270,7 @@ void SetCustomizer(entity e, float(void) customizer, void(void) uncustomizer)
 }
 
 
-void Net_LinkEntity(entity e, float docull, float dt, bool(entity, int) sendfunc)
+void Net_LinkEntity(entity e, bool docull, float dt, bool(entity, int) sendfunc)
 {
     vector mi, ma;
 
index a8a9117..3acc883 100644 (file)
@@ -468,6 +468,6 @@ entity initialize_entity_first;
 float sound_allowed(float dest, entity e);
 void InitializeEntity(entity e, void(void) func, float order);
 void SetCustomizer(entity e, float(void) customizer, void(void) uncustomizer);
-void Net_LinkEntity(entity e, float docull, float dt, float(entity, float) sendfunc);
+void Net_LinkEntity(entity e, bool docull, float dt, bool(entity, int) sendfunc);
 
 #endif