15#define NET_HANDLE(id, param) bool Net_Handle_##id(entity this, entity sender, param)
17#define NET_GUARD(id) \
18 bool Net_Handle_##id##_guard(entity this, entity sender, bool isNew) { \
20 serialize_marker(to, valid); \
21 if (!valid) LOG_FATALF("Last message not fully parsed: %s", _net_prevmsgstr); \
22 _net_prevmsgstr = #id; \
23 return Net_Handle_##id(this, sender, isNew); \
28 #define REGISTER_NET_TEMP(id) \
29 NET_HANDLE(id, bool); \
31 REGISTER(TempEntities, NET, id, m_id, new_pure(net_temp_packet)) { \
33 this.m_read = Net_Handle_##id##_guard; \
36 #define REGISTER_NET_TEMP(id) \
37 const bool NET_##id##_istemp = true; \
38 REGISTER(TempEntities, NET, id, m_id, new_pure(net_temp_packet)) \
55 #define REGISTER_NET_LINKED(id) \
56 ACCUMULATE NET_HANDLE(id, bool isnew) \
59 this.sourceLoc = __FILE__":"STR(__LINE__); \
60 if (!this) isnew = true; \
63 REGISTER(LinkedEntities, NET, id, m_id, new_pure(net_linked_packet)) \
66 this.m_read = Net_Handle_##id##_guard; \
69 #define REGISTER_NET_LINKED(id) \
70 const bool NET_##id##_istemp = false; \
71 REGISTER(LinkedEntities, NET, id, m_id, new_pure(net_linked_packet)) \
88 #define REGISTER_NET_C2S(id) \
89 NET_HANDLE(id, bool); \
90 REGISTER(C2S_Protocol, NET, id, m_id, new_pure(net_c2s_packet)) \
93 this.m_read = Net_Handle_##id; \
96 #define REGISTER_NET_C2S(id) \
97 const bool NET_##id##_istemp = true; \
98 REGISTER(C2S_Protocol, NET, id, m_id, new_pure(net_c2s_packet)) \
100 this.netname = #id; \
125 if (e.classname ==
"")
127 LOG_WARN(
"Net_LinkEntity called on an entity without a classname, assigning default");
128 e.classname =
"net_linked";
131 if (e.model ==
"" || e.modelindex == 0)
135 _setmodel(e,
"null");
140 e.SendFlags = 0xFFFFFF;
146 e.nextthink =
time + dt;
156 .void(
entity this) uncustomizeentityforclient;
162 e.uncustomizeentityforclient = uncustomizer;
163 e.uncustomizeentityforclient_set = !!uncustomizer;
181 if (buf ==
"")
return;
183 for (
int C2S; (C2S =
ReadByte()) >= 0; )
186 if (reader && reader.m_read && reader.m_read(
NULL, sender,
true))
continue;
187 LOG_SEVEREF(
"Net_ClientCommand() with malformed C2S=%d", C2S);
191 int expected =
strlen(buf);
192 if (g_buf_i > expected)
LOG_WARNF(
"Underflow: %d", g_buf_i - expected);
193 if (g_buf_i < expected)
LOG_WARNF(
"Overrflow: %d", expected - g_buf_i);
201 #define Net_Accept(classname) \
203 if (!this) this = new(classname); \
205 #define Net_Reject() \
207 if (this) delete(this); \
214 if (
g_buf ==
"")
return;
215 localcmd(
"\ncmd c2s \"", strreplace(
"$",
"$$",
g_buf),
"\"\n");
221 #define WriteHeader(to, id) \
222 WriteByte(to, NET_##id.m_id)
224 #define WriteHeader(to, id) \
226 if (NET_##id##_istemp) WriteByte(to, SVC_TEMPENTITY); \
227 WriteByte(to, NET_##id.m_id); \
228 bool _net_valid = false; serialize_marker(to, _net_valid); \
236 #define stream_reading(stream) false
237 #define stream_writing(stream) true
239 #define stream_reading(stream) true
240 #define stream_writing(stream) false
243#define serialize(T, stream, ...) \
245 noref Stream _stream = stream; \
246 serialize_##T(_stream, __VA_ARGS__); \
250 #define serialize_byte(stream, this) \
252 WriteByte(stream, this); \
255 #define serialize_byte(stream, this) \
262 #define serialize_float(stream, this) \
264 WriteCoord(stream, this); \
267 #define serialize_float(stream, this) \
269 this = ReadCoord(); \
273#define serialize_vector(stream, this) \
276 serialize_float(stream, _v.x); \
277 serialize_float(stream, _v.y); \
278 serialize_float(stream, _v.z); \
282#define serialize_marker(stream, this) \
287 int _de = 0xDE, _ad = 0xAD, _be = 0xBE, _ef = 0xEF; \
288 serialize_byte(stream, _de); \
289 serialize_byte(stream, _ad); \
290 serialize_byte(stream, _be); \
291 serialize_byte(stream, _ef); \
292 this = (_de == 0xDE && _ad == 0xAD && _be == 0xBE && _ef == 0xEF); \
298#define ReadRegistered(r) REGISTRY_GET(r, Read_byte())
299#define WriteRegistered(r, to, it) Write_byte(to, it.m_id)
301#define Read_byte() ReadByte()
302#define Write_byte(to, f) WriteByte(to, f)
333#define Read_int() ReadInt24_t()
334#define Write_int(to, f) WriteInt24_t(to, f)
336#define Read_float() ReadFloat()
337#define Write_float(to, f) WriteFloat(to, f)
339#define Read_string() ReadString()
340#define Write_string(to, f) WriteString(to, f)
344 #define APPROXPASTTIME_MAX (16384 * APPROXPASTTIME_ACCURACY_REQUIREMENT)
345 #define APPROXPASTTIME_RANGE (64 * APPROXPASTTIME_ACCURACY_REQUIREMENT)
352 if (f == 0)
return NULL;
357 int v = ReadShort() << 8;
361 #define ReadInt48_t() vec2(ReadInt24_t(), ReadInt24_t())
362 #define ReadInt72_t() vec3(ReadInt24_t(), ReadInt24_t(), ReadInt24_t())
365 #define ReadSByte() (_ReadSByte = ReadByte(), (_ReadSByte & BIT(7) ? -128 : 0) + (_ReadSByte & BITS(7)))
366 #define ReadFloat() ReadCoord()
367 #define ReadVector() vec3(ReadFloat(), ReadFloat(), ReadFloat())
368 #define ReadVector2D() vec2(ReadFloat(), ReadFloat())
369 #define ReadAngleVector() vec3(ReadAngle(), ReadAngle(), ReadAngle())
370 #define ReadAngleVector2D() vec2(ReadAngle(), ReadAngle())
375 if (num > 8)
return ReadShort();
390 void WriteInt24_t(
float dst,
float val)
396 void WriteInt48_t(
float dst,
vector val)
398 WriteInt24_t(dst, val.x);
399 WriteInt24_t(dst, val.y);
401 void WriteInt72_t(
float dst,
vector val)
403 WriteInt24_t(dst, val.x);
404 WriteInt24_t(dst, val.y);
405 WriteInt24_t(dst, val.z);
408 #define WriteFloat(to, f) WriteCoord(to, f)
409 #define WriteVector(to, v) MACRO_BEGIN WriteFloat(to, v.x); WriteFloat(to, v.y); WriteFloat(to, v.z); MACRO_END
410 #define WriteVector2D(to, v) MACRO_BEGIN WriteFloat(to, v.x); WriteFloat(to, v.y); MACRO_END
411 #define WriteAngleVector(to, v) MACRO_BEGIN WriteAngle(to, v.x); WriteAngle(to, v.y); WriteAngle(to, v.z); MACRO_END
412 #define WriteAngleVector2D(to, v) MACRO_BEGIN WriteAngle(to, v.x); WriteAngle(to, v.y); MACRO_END
414 void Writebits(
float dst,
float val,
int num)
416 if (num > 16) { WriteInt24_t(dst, val);
return; }
417 if (num > 8) {
WriteShort(dst, val);
return; }
426 void WriteApproxPastTime(
float dst,
float t)
444 #define WRITESPECTATABLE_MSG_ONE(to, statement) MACRO_BEGIN \
445 entity prev = msg_entity; \
447 FOREACH_CLIENT(IS_REAL_CLIENT(it), { \
448 if (it == dst || (it.classname == STR_SPECTATOR && it.enemy == dst)) \
var entity(vector mins, vector maxs,.entity tofield) findbox_tofield_OrFallback
limitations: NULL cannot be present elements can only be present once a maximum of IL_MAX lists can e...
const float EF_NODEPTHTEST
void SUB_Remove(entity this)
Remove entity.
ERASEABLE entity IL_PUSH(IntrusiveList this, entity it)
Push to tail.
#define IL_EACH(this, cond, body)
#define STRING_ITERATOR(this, s, i)
#define STRING_ITERATOR_SET(this, s, i)
#define FOREACH(list, cond, body)
void WriteByte(int to, int b)
void SetCustomizer(entity e, bool(entity this, entity client) customizer, void(entity this) uncustomizer)
float ReadApproxPastTime()
void Net_ClientCommand(entity sender, string command)
void Net_UnlinkEntity(entity e)
#define APPROXPASTTIME_MAX
void UncustomizeEntitiesRun()
IntrusiveList g_uncustomizables
float uncustomizeentityforclient_set
void Net_LinkEntity(entity e, bool docull, float dt, bool(entity this, entity to, int sendflags) sendfunc)
void WriteShort(int to, int b)
const float APPROXPASTTIME_ACCURACY_REQUIREMENT
strcat(_("^F4Countdown stopped!"), "\n^BG", _("Teams are too unbalanced."))
#define REGISTRY_SORT(...)
#define REGISTER_REGISTRY(id)
#define REGISTRY(id, max)
Declare a new registry.
#define REGISTRY_CHECK(id)
#define REGISTRY_DEFINE_GET(id, null)
#define REGISTRY_GET(id, i)
#define setSendEntity(e, f)
#define STATIC_INIT(func)
during worldspawn
#define yenc_single(c, ret)
#define ydec_single(stringiter, ret)