Xonotic
inventory.qh
Go to the documentation of this file.
1 #pragma once
2 
3 #include "all.qh"
4 
5 #ifdef GAMEQC
6 CLASS(Inventory, Object)
8  ATTRIBARRAY(Inventory, inv_items, int, REGISTRY_MAX(Items));
9 ENDCLASS(Inventory)
10 
11 
12 .Inventory inventory;
14 .Inventory inventory_store;
15 
16 REGISTER_NET_LINKED(ENT_CLIENT_INVENTORY)
17 
18 const int Inventory_groups_minor = 8; // must be a multiple of 8 (one byte) to optimize bandwidth usage
19 const int Inventory_groups_major = 4; // must be >= ceil(REGISTRY_COUNT(Items) / Inventory_groups_minor)
20 #endif
21 
22 // no need to perform these checks on both server and client
23 #ifdef CSQC
24 STATIC_INIT(Inventory)
25 {
26  if (Inventory_groups_minor / 8 != floor(Inventory_groups_minor / 8))
27  error("Inventory_groups_minor is not a multiple of 8.");
28  int min_major_value = ceil(REGISTRY_COUNT(Items) / Inventory_groups_minor);
29  if (Inventory_groups_major < min_major_value)
30  error(sprintf("Inventory_groups_major can not be < %d.", min_major_value));
31 }
32 #endif
33 
34 #ifdef SVQC
35 #define G_MAJOR(id) (floor((id) / Inventory_groups_minor))
36 #define G_MINOR(id) ((id) % Inventory_groups_minor)
37 #endif
38 
39 #ifdef CSQC
40 Inventory g_inventory;
41 void Inventory_remove(entity this)
42 {
43  if(g_inventory == this)
44  g_inventory = NULL;
45 }
46 
47 NET_HANDLE(ENT_CLIENT_INVENTORY, bool isnew)
48 {
49  make_pure(this);
50  g_inventory = this;
51  this.entremove = Inventory_remove;
52  const int majorBits = Readbits(Inventory_groups_major);
53  for (int i = 0; i < Inventory_groups_major; ++i) {
54  if (!(majorBits & BIT(i))) {
55  continue;
56  }
57  const int minorBits = Readbits(Inventory_groups_minor);
58  for (int j = 0; j < Inventory_groups_minor; ++j) {
59  if (!(minorBits & BIT(j))) {
60  continue;
61  }
62  const GameItem it = REGISTRY_GET(Items, Inventory_groups_minor * i + j);
63  .int fld = inv_items[it.m_id];
64  int prev = this.(fld);
65  int next = this.(fld) = ReadByte();
66  LOG_DEBUGF("%s: %.0f -> %.0f", it.m_name, prev, next);
67  }
68  }
69  return true;
70 }
71 #endif
72 
73 #ifdef SVQC
74 int minorBitsArr[Inventory_groups_major];
75 void Inventory_Write(Inventory data, Inventory store)
76 {
77  if (!data) {
78  WriteShort(MSG_ENTITY, 0);
79  return;
80  }
81  TC(Inventory, data);
82 
83  for (int i = 0; i < Inventory_groups_major; ++i)
84  minorBitsArr[i] = 0;
85 
86  int majorBits = 0;
87  FOREACH(Items, true, {
88  .int fld = inv_items[it.m_id];
89  const bool changed = store.(fld) != data.(fld);
90  store.(fld) = data.(fld);
91  if (changed) {
92  int maj = G_MAJOR(it.m_id);
93  majorBits = BITSET(majorBits, BIT(maj), true);
94  minorBitsArr[maj] = BITSET(minorBitsArr[maj], BIT(G_MINOR(it.m_id)), true);
95  }
96  });
97 
98  Writebits(MSG_ENTITY, majorBits, Inventory_groups_major);
99  for (int i = 0; i < Inventory_groups_major; ++i)
100  {
101  if (!(majorBits & BIT(i)))
102  continue;
103 
104  const int minorBits = minorBitsArr[i];
105  Writebits(MSG_ENTITY, minorBits, Inventory_groups_minor);
106  for (int j = 0; j < Inventory_groups_minor; ++j)
107  {
108  if (!(minorBits & BIT(j)))
109  continue;
110 
111  const entity it = REGISTRY_GET(Items, Inventory_groups_minor * i + j);
112  WriteByte(MSG_ENTITY, data.inv_items[it.m_id]);
113  }
114  }
115 }
116 #endif
117 
118 #undef G_MAJOR
119 #undef G_MINOR
120 
121 #ifdef SVQC
122 bool Inventory_Send(Inventory this, Client to, int sf)
123 {
124  TC(Inventory, this);
125  WriteHeader(MSG_ENTITY, ENT_CLIENT_INVENTORY);
126  TC(PlayerState, this.owner);
127  Inventory_Write(this, to.inventory_store);
128  return true;
129 }
130 
131 bool Inventory_customize(entity this, entity client)
132 {
133  // sends to spectators too!
134  return (PS(client) && PS(client).inventory == this);
135 }
136 
137 void Inventory_new(PlayerState this)
138 {
139  Inventory inv = NEW(Inventory);
140  setcefc(inv, Inventory_customize);
141  this.inventory = inv;
142  inv.owner = this;
143  Net_LinkEntity(inv, false, 0, Inventory_Send);
144 }
145 void Inventory_delete(entity e) { delete(e.inventory); }
146 void Inventory_update(entity e) { e.inventory.SendFlags = 0xFFFFFF; }
147 
148 void Inventory_clear(entity store)
149 {
150  // NOTE: you will need to perform Inventory_update after this to update the storage entity
151  // (unless store is the storage entity)
152  FOREACH(Items, true, {
153  .int fld = inv_items[it.m_id];
154  store.(fld) = 0;
155  });
156 }
157 
158 void InventoryStorage_attach(entity e) { e.inventory_store = NEW(Inventory); e.inventory_store.drawonlytoclient = e; }
159 void InventoryStorage_delete(entity e) { delete(e.inventory_store); }
160 #endif
#define REGISTER_NET_LINKED(id)
Definition: net.qh:67
#define NEW(cname,...)
Definition: oo.qh:105
CLASS(Object) Object
Definition: oo.qh:318
void InventoryStorage_delete(PlayerState this)
entity() spawn
prev
Definition: all.qh:66
#define REGISTRY_GET(id, i)
Definition: registry.qh:43
#define PS(this)
Definition: state.qh:18
#define NET_HANDLE(id, param)
Definition: net.qh:12
#define STATIC_INIT(func)
during worldspawn
Definition: static.qh:32
entity to
Definition: self.qh:96
int m_id
Definition: item.qh:105
entity owner
Definition: main.qh:73
#define REGISTRY_COUNT(id)
Definition: registry.qh:18
#define BIT(n)
Only ever assign into the first 24 bits in QC (so max is BIT(23)).
Definition: bits.qh:8
#define NULL
Definition: post.qh:17
#define TC(T, sym)
Definition: _all.inc:82
Definition: client.qh:88
#define REGISTRY_MAX(id)
Definition: registry.qh:17
#define make_pure(e)
Definition: oo.qh:12
#define BITSET(var, mask, flag)
Definition: bits.qh:11
Purpose: common player state, usable on client and server Client: singleton representing the viewed p...
Definition: state.qh:8
next
Definition: all.qh:88
void Inventory_clear(PlayerState this)
void Inventory_new(PlayerState this)
#define ENDCLASS(cname)
Definition: oo.qh:269
void Inventory_delete(entity this)
void InventoryStorage_attach(PlayerState this)
#define ATTRIBARRAY(cname, name, type, cnt)
Definition: oo.qh:254
#define FOREACH(list, cond, body)
Definition: iter.qh:19
#define LOG_DEBUGF(...)
Definition: log.qh:86