X-Git-Url: http://de.git.xonotic.org/?a=blobdiff_plain;f=qcsrc%2Flib%2Fnet.qh;h=07385b092da1cbdac01a3803b91d84262b96b97a;hb=46ae54b152183f3e2895457f958fe830b1d97eb8;hp=834de760f503e8a2739b3b3bcda3b448bc811566;hpb=3b8f792333c5c245e54bdf0612d2a442bcfe61dc;p=xonotic%2Fxonotic-data.pk3dir.git diff --git a/qcsrc/lib/net.qh b/qcsrc/lib/net.qh index 834de760f..07385b092 100644 --- a/qcsrc/lib/net.qh +++ b/qcsrc/lib/net.qh @@ -2,52 +2,53 @@ #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; + .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); } + 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"; + 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); - } + 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; + e.SendEntity = SendEntity_self; + e.SendEntity3 = sendfunc; + e.SendFlags = 0xFFFFFF; - if (!docull) e.effects |= EF_NODEPTHTEST; + if (!docull) e.effects |= EF_NODEPTHTEST; - if (dt) { - e.nextthink = time + dt; - e.think = SUB_Remove; - } -} + if (dt) + { + e.nextthink = time + dt; + e.think = SUB_Remove; + } + } -.void() uncustomizeentityforclient; -.float uncustomizeentityforclient_set; + .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 SetCustomizer(entity e, float() customizer, 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()); - } -} + void UncustomizeEntitiesRun() + { + for (entity e = NULL; (e = findfloat(e, uncustomizeentityforclient_set, 1)); ) + WITH(entity, self, e, e.uncustomizeentityforclient()); + } #endif @@ -56,111 +57,203 @@ void UncustomizeEntitiesRun() .string netname; .int m_id; -.void(entity this, bool isNew) m_read; +.bool(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) + #define Net_Accept(classname) \ + do \ + { \ + if (!this) this = new(classname); \ + } \ + while (0) + #define Net_Reject() \ + do \ + { \ + if (this) remove(this); \ + } \ + while (0) + #define NET_HANDLE(id, param) \ + bool Net_Handle_##id(entity this, param) #else - #define WriteHeader(to, id) do { \ - if (NET_##id##_istemp) WriteByte(to, SVC_TEMPENTITY); \ - WriteByte(to, NET_##id.m_id); \ - } while (0) + #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) + #define REGISTER_NET_LINKED(id) \ + [[accumulate]] NET_HANDLE(id, bool) \ + { \ + this = self; \ + this.sourceLocFile = __FILE__; \ + this.sourceLocLine = __LINE__; \ + } \ + REGISTER(LinkedEntities, NET, id, m_id, new(net_linked_packet)) \ + { \ + make_pure(this); \ + this.netname = #id; \ + this.m_read = Net_Handle_##id; \ + } #else - #define REGISTER_NET_LINKED(id, param) \ - const bool NET_##id##_istemp = false; \ - REGISTER(RegisterLinkedEntities, NET, LinkedEntities, id, m_id, spawn()) { \ - this.netname = #id; \ - } + #define REGISTER_NET_LINKED(id) \ + const bool NET_##id##_istemp = false; \ + REGISTER(LinkedEntities, NET, id, m_id, new(net_linked_packet)) \ + { \ + make_pure(this); \ + 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; - } +REGISTRY(LinkedEntities, BITS(8) - 1) +#define LinkedEntities_from(i) _LinkedEntities_from(i, NULL) +REGISTER_REGISTRY(LinkedEntities) +REGISTRY_SORT(LinkedEntities, 0) +REGISTRY_CHECK(LinkedEntities) +STATIC_INIT(RegisterLinkedEntities_renumber) +{ + for (int i = 0; i < LinkedEntities_COUNT; ++i) + LinkedEntities_from(i).m_id = 1 + 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) + #define REGISTER_NET_TEMP(id) \ + NET_HANDLE(id, bool); \ + REGISTER(TempEntities, NET, id, m_id, new(net_temp_packet)) \ + { \ + make_pure(this); \ + this.netname = #id; \ + this.m_read = Net_Handle_##id; \ + } #else - #define REGISTER_NET_TEMP(id, param) \ - const bool NET_##id##_istemp = true; \ - REGISTER(RegisterTempEntities, NET, TempEntities, id, m_id, spawn()) { \ - this.netname = #id; \ - } + #define REGISTER_NET_TEMP(id) \ + const bool NET_##id##_istemp = true; \ + REGISTER(TempEntities, NET, id, m_id, new(net_temp_packet)) \ + { \ + make_pure(this); \ + 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; - } +REGISTRY(TempEntities, BITS(8) - 80) +#define TempEntities_from(i) _TempEntities_from(i, NULL) +REGISTER_REGISTRY(TempEntities) +REGISTRY_SORT(TempEntities, 0) +REGISTRY_CHECK(TempEntities) +STATIC_INIT(RegisterTempEntities_renumber) +{ + for (int i = 0; i < TempEntities_COUNT; ++i) + TempEntities_from(i).m_id = 80 + 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 + const float APPROXPASTTIME_ACCURACY_REQUIREMENT = 0.05; + #define APPROXPASTTIME_MAX (16384 * APPROXPASTTIME_ACCURACY_REQUIREMENT) + #define APPROXPASTTIME_RANGE (64 * APPROXPASTTIME_ACCURACY_REQUIREMENT) + + #ifdef CSQC + entity ReadCSQCEntity() + { + int f = ReadShort(); + if (f == 0) return world; + return findfloat(world, entnum, f); + } + 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; + } + + float ReadApproxPastTime() + { + float dt = ReadByte(); + + // map from range...PPROXPASTTIME_MAX / 256 + dt = (APPROXPASTTIME_MAX / 256) * (dt / (256 - dt)); + + return servertime - dt; + } + + #else + const int MSG_ENTITY = 5; + + 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); + } + + // this will use the value: + // 128 + // accuracy near zero is APPROXPASTTIME_MAX/(256*255) + // accuracy at x is 1/derivative, i.e. + // APPROXPASTTIME_MAX * (1 + 256 * (dt / APPROXPASTTIME_MAX))^2 / 65536 + void WriteApproxPastTime(float dst, float t) + { + float dt = time - t; + + // warning: this is approximate; do not resend when you don't have to! + // be careful with sendflags here! + // we want: 0 -> 0.05, 1 -> 0.1, ..., 255 -> 12.75 + + // map to range... + dt = 256 * (dt / ((APPROXPASTTIME_MAX / 256) + dt)); + + // round... + dt = rint(bound(0, dt, 255)); + + WriteByte(dst, dt); + } + + // allow writing to also pass through to spectators (like so spectators see the same centerprints as players for example) + #define WRITESPECTATABLE_MSG_ONE_VARNAME(varname, statement) \ + entity varname; varname = msg_entity; \ + FOR_EACH_REALCLIENT(msg_entity) \ + if (msg_entity == varname || (msg_entity.classname == STR_SPECTATOR && msg_entity.enemy == varname)) \ + statement msg_entity = varname + #define WRITESPECTATABLE_MSG_ONE(statement) \ + do \ + { \ + WRITESPECTATABLE_MSG_ONE_VARNAME(oldmsg_entity, statement); \ + } \ + while (0) + #define WRITESPECTATABLE(msg, statement) \ + if (msg == MSG_ONE) WRITESPECTATABLE_MSG_ONE(statement); \ + else \ + statement float WRITESPECTATABLE_workaround = 0 + #endif #endif #endif