#include "sort.qh"
#include "yenc.qh"
+// netcode mismatch and not sure what caused it? developer_csqcentities 1
+
.string netname;
.int m_id;
.bool(entity this, entity sender, bool isNew) m_read;
#define NET_HANDLE(id, param) bool Net_Handle_##id(entity this, entity sender, param)
+#define NET_GUARD(id) \
+ bool Net_Handle_##id##_guard(entity this, entity sender, bool isNew) { \
+ bool valid = false; \
+ serialize_marker(to, valid); \
+ if (!valid) LOG_FATALF("Last message not fully parsed: %s", _net_prevmsgstr); \
+ _net_prevmsgstr = #id; \
+ return Net_Handle_##id(this, sender, isNew); \
+ }
#ifdef CSQC
+string _net_prevmsgstr;
#define REGISTER_NET_TEMP(id) \
NET_HANDLE(id, bool); \
- REGISTER(TempEntities, NET, id, m_id, new_pure(net_temp_packet)) \
- { \
+ NET_GUARD(id); \
+ REGISTER(TempEntities, NET, id, m_id, new_pure(net_temp_packet)) { \
this.netname = #id; \
- this.m_read = Net_Handle_##id; \
+ this.m_read = Net_Handle_##id##_guard; \
}
#else
#define REGISTER_NET_TEMP(id) \
REGISTER_REGISTRY(TempEntities)
REGISTRY_SORT(TempEntities)
REGISTRY_CHECK(TempEntities)
-STATIC_INIT(RegisterTempEntities_renumber) { FOREACH(TempEntities, true, it.m_id = 80 + i); }
+STATIC_INIT(TempEntities_renumber) { FOREACH(TempEntities, true, it.m_id = 80 + i); }
#ifdef CSQC
#define REGISTER_NET_LINKED(id) \
- [[accumulate]] NET_HANDLE(id, bool isnew) \
+ ACCUMULATE NET_HANDLE(id, bool isnew) \
{ \
this = __self; \
- this.sourceLoc = __FILE__ ":" STR(__LINE__); \
+ this.sourceLoc = __FILE__":"STR(__LINE__); \
if (!this) isnew = true; \
} \
+ NET_GUARD(id); \
REGISTER(LinkedEntities, NET, id, m_id, new_pure(net_linked_packet)) \
{ \
this.netname = #id; \
- this.m_read = Net_Handle_##id; \
+ this.m_read = Net_Handle_##id##_guard; \
}
#else
#define REGISTER_NET_LINKED(id) \
REGISTER_REGISTRY(LinkedEntities)
REGISTRY_SORT(LinkedEntities)
REGISTRY_CHECK(LinkedEntities)
-STATIC_INIT(RegisterLinkedEntities_renumber) { FOREACH(LinkedEntities, true, it.m_id = 1 + i); }
+STATIC_INIT(LinkedEntities_renumber) { FOREACH(LinkedEntities, true, it.m_id = 1 + i); }
#ifdef SVQC
const int MSG_ENTITY = 5;
- .int Version; // deprecated, use SendFlags
.int SendFlags;
+ IntrusiveList g_uncustomizables;
+ STATIC_INIT(g_uncustomizables) { g_uncustomizables = IL_NEW(); }
+
void Net_LinkEntity(entity e, bool docull, float dt, bool(entity this, entity to, int sendflags) sendfunc)
{
if (e.classname == "") e.classname = "net_linked";
setcefc(e, customizer);
e.uncustomizeentityforclient = uncustomizer;
e.uncustomizeentityforclient_set = !!uncustomizer;
+ if(uncustomizer)
+ IL_PUSH(g_uncustomizables, e);
}
void UncustomizeEntitiesRun()
{
- FOREACH_ENTITY_FLOAT(uncustomizeentityforclient_set, true, it.uncustomizeentityforclient(it));
+ IL_EACH(g_uncustomizables, it.uncustomizeentityforclient_set, it.uncustomizeentityforclient(it));
}
STRING_ITERATOR(g_buf, string_null, 0);
{
entity reader = C2S_Protocol_from(C2S);
if (reader && reader.m_read && reader.m_read(NULL, sender, true)) continue;
- LOG_SEVEREF("Net_ClientCommand() with malformed C2S=%d\n", C2S);
+ LOG_SEVEREF("Net_ClientCommand() with malformed C2S=%d", C2S);
return;
}
g_buf_i--;
const int MSG_C2S = 0;
#define Net_Accept(classname) \
- MACRO_BEGIN { \
- if (!this) this = new(classname); \
- } MACRO_END
+ MACRO_BEGIN \
+ if (!this) this = new(classname); \
+ MACRO_END
#define Net_Reject() \
- MACRO_BEGIN { \
- if (this) delete(this); \
- } MACRO_END
+ MACRO_BEGIN \
+ if (this) delete(this); \
+ MACRO_END
string g_buf;
{
if (g_buf == "") return;
localcmd("\ncmd c2s \"", strreplace("$", "$$", g_buf), "\"\n");
- strunzone(g_buf);
- g_buf = string_null;
+ strfree(g_buf);
}
#endif
#if defined(CSQC)
#define WriteHeader(to, id) \
- MACRO_BEGIN { \
- WriteByte(to, NET_##id.m_id); \
- } MACRO_END
+ WriteByte(to, NET_##id.m_id)
#elif defined(SVQC)
#define WriteHeader(to, id) \
- MACRO_BEGIN { \
+ MACRO_BEGIN \
if (NET_##id##_istemp) WriteByte(to, SVC_TEMPENTITY); \
WriteByte(to, NET_##id.m_id); \
- } MACRO_END
+ bool _net_valid = false; serialize_marker(to, _net_valid); \
+ MACRO_END
#endif
// serialization: new style
#define stream_writing(stream) false
#endif
-#define serialize(T, stream, ...) serialize_##T(stream, __VA_ARGS__)
+#define serialize(T, stream, ...) \
+MACRO_BEGIN \
+ noref Stream _stream = stream; \
+ serialize_##T(_stream, __VA_ARGS__); \
+MACRO_END
#if defined(SVQC)
#define serialize_byte(stream, this) \
#endif
#define serialize_vector(stream, this) \
- MACRO_BEGIN \
+MACRO_BEGIN \
vector _v = this; \
serialize_float(stream, _v.x); \
serialize_float(stream, _v.y); \
serialize_float(stream, _v.z); \
this = _v; \
- MACRO_END
+MACRO_END
+
+#define serialize_marker(stream, this) \
+MACRO_BEGIN \
+ if (NDEBUG) { \
+ this = true; \
+ } else { \
+ int _de = 0xDE, _ad = 0xAD, _be = 0xBE, _ef = 0xEF; \
+ serialize_byte(stream, _de); \
+ serialize_byte(stream, _ad); \
+ serialize_byte(stream, _be); \
+ serialize_byte(stream, _ef); \
+ this = (_de == 0xDE && _ad == 0xAD && _be == 0xBE && _ef == 0xEF); \
+ } \
+MACRO_END
// serialization: old
string s = string_null;
yenc_single(b, s);
string tmp = strcat(g_buf, s);
- if (g_buf) strunzone(g_buf);
- g_buf = strzone(tmp);
+ strcpy(g_buf, tmp);
+ }
+ void WriteShort(int to, int b)
+ {
+ WriteByte(to, (b >> 8) & 0xFF);
+ WriteByte(to, b & 0xFF);
}
#elif defined(SVQC)
int ReadByte()
ydec_single(g_buf, ret);
return ret;
}
+ int ReadShort()
+ {
+ return (ReadByte() << 8) | (ReadByte());
+ }
void WriteByte(int to, int b);
#endif
#define Read_string() ReadString()
#define Write_string(to, f) WriteString(to, f)
-#ifndef MENUQC
+#ifdef GAMEQC
const float APPROXPASTTIME_ACCURACY_REQUIREMENT = 0.05;
#define APPROXPASTTIME_MAX (16384 * APPROXPASTTIME_ACCURACY_REQUIREMENT)
#define APPROXPASTTIME_RANGE (64 * APPROXPASTTIME_ACCURACY_REQUIREMENT)
#ifdef CSQC
+ float servertime;
entity ReadCSQCEntity()
{
int f = ReadShort();
v += ReadByte(); // note: this is unsigned
return v;
}
- #define ReadInt48_t() vec3(ReadInt24_t(), ReadInt24_t(), 0)
+ #define ReadInt48_t() vec2(ReadInt24_t(), ReadInt24_t())
#define ReadInt72_t() vec3(ReadInt24_t(), ReadInt24_t(), ReadInt24_t())
- int _ReadSByte;
+ noref int _ReadSByte;
#define ReadSByte() (_ReadSByte = ReadByte(), (_ReadSByte & BIT(7) ? -128 : 0) + (_ReadSByte & BITS(7)))
#define ReadFloat() ReadCoord()
#define ReadVector() vec3(ReadFloat(), ReadFloat(), ReadFloat())
- #define ReadVector2D() vec3(ReadFloat(), ReadFloat(), 0)
+ #define ReadVector2D() vec2(ReadFloat(), ReadFloat())
float ReadApproxPastTime()
{
WriteInt24_t(dst, val.z);
}
- #define WriteFloat(to, f) WriteCoord(to, f)
- #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
+ #define WriteFloat(to, f) WriteCoord(to, f)
+ #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
// this will use the value:
// 128
}
// allow writing to also pass through to spectators (like so spectators see the same centerprints as players for example)
- #define WRITESPECTATABLE_MSG_ONE(to, statement) MACRO_BEGIN { \
+ #define WRITESPECTATABLE_MSG_ONE(to, statement) MACRO_BEGIN \
entity prev = msg_entity; \
entity dst = to; \
FOREACH_CLIENT(IS_REAL_CLIENT(it), { \
} \
}); \
msg_entity = prev; \
- } MACRO_END
+ MACRO_END
#endif
#endif