#ifndef NET_H #define NET_H #ifdef SVQC .int Version; // deprecated, use SendFlags .int SendFlags; .bool(entity to, int sendflags) SendEntity; .bool(entity this, entity to, int sendflags) SendEntity3; bool SendEntity_self(entity to, int sendflags) { return self.SendEntity3(self, to, sendflags); } void Net_LinkEntity(entity e, bool docull, float dt, bool(entity this, entity to, int sendflags) sendfunc) { if (e.classname == "") e.classname = "net_linked"; if (e.model == "" || self.modelindex == 0) { vector mi = e.mins; vector ma = e.maxs; _setmodel(e, "null"); setsize(e, mi, ma); } e.SendEntity = SendEntity_self; e.SendEntity3 = sendfunc; e.SendFlags = 0xFFFFFF; if (!docull) e.effects |= EF_NODEPTHTEST; if (dt) { e.nextthink = time + dt; e.think = SUB_Remove; } } .void() uncustomizeentityforclient; .float uncustomizeentityforclient_set; void SetCustomizer(entity e, float(void) customizer, void(void) uncustomizer) { e.customizeentityforclient = customizer; e.uncustomizeentityforclient = uncustomizer; e.uncustomizeentityforclient_set = !!uncustomizer; } void UncustomizeEntitiesRun() { for (entity e = NULL; (e = findfloat(e, uncustomizeentityforclient_set, 1)); ) { WITH(entity, self, e, e.uncustomizeentityforclient()); } } #endif #include "registry.qh" #include "sort.qh" .string netname; .int m_id; .void(entity this, bool isNew) m_read; #ifdef CSQC #define Net_Accept() do { if (!this) this = spawn(); } while (0) #define Net_Reject() do { if (this) remove(this); } while (0) #else #define WriteHeader(to, id) do { \ if (NET_##id##_istemp) WriteByte(to, SVC_TEMPENTITY); \ WriteByte(to, NET_##id.m_id); \ } while (0) #endif #ifdef CSQC #define REGISTER_NET_LINKED(id, param) \ void Ent_Read##id(entity this, param) { this = self; } \ REGISTER(RegisterLinkedEntities, NET, LinkedEntities, id, m_id, spawn()) { \ this.netname = #id; \ this.m_read = Ent_Read##id; \ } \ [[accumulate]] void Ent_Read##id(entity this, param) #else #define REGISTER_NET_LINKED(id, param) \ const bool NET_##id##_istemp = false; \ REGISTER(RegisterLinkedEntities, NET, LinkedEntities, id, m_id, spawn()) { \ this.netname = #id; \ } #endif REGISTRY(LinkedEntities, BIT(0)) REGISTER_REGISTRY(RegisterLinkedEntities) REGISTRY_SORT(LinkedEntities, netname, 0) STATIC_INIT(RegisterLinkedEntities_renumber) { for (int i = 0; i < LinkedEntities_COUNT; ++i) { LinkedEntities[i].m_id = 100 + i; } } #ifdef CSQC #define REGISTER_NET_TEMP(id, param) \ void Net_Read##id(entity this, param); \ REGISTER(RegisterTempEntities, NET, TempEntities, id, m_id, spawn()) { \ this.netname = #id; \ this.m_read = Net_Read##id; \ } \ void Net_Read##id(entity this, param) #else #define REGISTER_NET_TEMP(id, param) \ const bool NET_##id##_istemp = true; \ REGISTER(RegisterTempEntities, NET, TempEntities, id, m_id, spawn()) { \ this.netname = #id; \ } #endif REGISTRY(TempEntities, BIT(0)) REGISTER_REGISTRY(RegisterTempEntities) REGISTRY_SORT(TempEntities, netname, 0) STATIC_INIT(RegisterTempEntities_renumber) { for (int i = 0; i < TempEntities_COUNT; ++i) { TempEntities[i].m_id = 115 + i; } } #ifndef MENUQC #ifdef CSQC int ReadInt24_t() { int v = ReadShort() << 8; // note: this is signed v += ReadByte(); // note: this is unsigned return v; } vector ReadInt48_t() { vector v; v.x = ReadInt24_t(); v.y = ReadInt24_t(); v.z = 0; return v; } vector ReadInt72_t() { vector v; v.x = ReadInt24_t(); v.y = ReadInt24_t(); v.z = ReadInt24_t(); return v; } #else void WriteInt24_t(float dst, float val) { float v; WriteShort(dst, (v = floor(val >> 8))); WriteByte(dst, val - (v << 8)); // 0..255 } void WriteInt48_t(float dst, vector val) { WriteInt24_t(dst, val.x); WriteInt24_t(dst, val.y); } void WriteInt72_t(float dst, vector val) { WriteInt24_t(dst, val.x); WriteInt24_t(dst, val.y); WriteInt24_t(dst, val.z); } #endif #endif #endif