]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blobdiff - qcsrc/lib/net.qh
Make it compile without XONOTIC defined
[xonotic/xonotic-data.pk3dir.git] / qcsrc / lib / net.qh
index eb0366786359d32ddcfdd9ee1a0441f8f13fd227..f0a9e817dcb4cc56defaebd1fbca4cfe34e97267 100644 (file)
-#ifndef NET_H
-#define NET_H
+#pragma once
+
+#include "registry.qh"
+#include "sort.qh"
+#include "yenc.qh"
+
+.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)
+
+
+#ifdef CSQC
+       #define REGISTER_NET_TEMP(id) \
+               NET_HANDLE(id, bool); \
+               REGISTER(TempEntities, NET, id, m_id, new_pure(net_temp_packet)) \
+               { \
+                       this.netname = #id; \
+                       this.m_read = Net_Handle_##id; \
+               }
+#else
+       #define REGISTER_NET_TEMP(id) \
+               const bool NET_##id##_istemp = true; \
+               REGISTER(TempEntities, NET, id, m_id, new_pure(net_temp_packet)) \
+               { \
+                       this.netname = #id; \
+               }
+#endif
+#define REGISTER_NET_S2C(id) REGISTER_NET_TEMP(id)
+
+REGISTRY(TempEntities, BITS(8) - 80)
+#define TempEntities_from(i) _TempEntities_from(i, NULL)
+REGISTER_REGISTRY(TempEntities)
+REGISTRY_SORT(TempEntities)
+REGISTRY_CHECK(TempEntities)
+STATIC_INIT(RegisterTempEntities_renumber) { FOREACH(TempEntities, true, it.m_id = 80 + i); }
+
+
+
+#ifdef CSQC
+       #define REGISTER_NET_LINKED(id) \
+               [[accumulate]] NET_HANDLE(id, bool isnew) \
+               { \
+                       this = __self; \
+                       this.sourceLoc = __FILE__ ":" STR(__LINE__); \
+                       if (!this) isnew = true; \
+               } \
+               REGISTER(LinkedEntities, NET, id, m_id, new_pure(net_linked_packet)) \
+               { \
+                       this.netname = #id; \
+                       this.m_read = Net_Handle_##id; \
+               }
+#else
+       #define REGISTER_NET_LINKED(id) \
+               const bool NET_##id##_istemp = false; \
+               REGISTER(LinkedEntities, NET, id, m_id, new_pure(net_linked_packet)) \
+               { \
+                       this.netname = #id; \
+               }
+#endif
+
+REGISTRY(LinkedEntities, BITS(8) - 1)
+#define LinkedEntities_from(i) _LinkedEntities_from(i, NULL)
+REGISTER_REGISTRY(LinkedEntities)
+REGISTRY_SORT(LinkedEntities)
+REGISTRY_CHECK(LinkedEntities)
+STATIC_INIT(RegisterLinkedEntities_renumber) { FOREACH(LinkedEntities, true, it.m_id = 1 + i); }
+
+
+
+#ifdef SVQC
+       #define REGISTER_NET_C2S(id) \
+               NET_HANDLE(id, bool); \
+               REGISTER(C2S_Protocol, NET, id, m_id, new_pure(net_c2s_packet)) \
+               { \
+                       this.netname = #id; \
+                       this.m_read = Net_Handle_##id; \
+               }
+#else
+       #define REGISTER_NET_C2S(id) \
+               const bool NET_##id##_istemp = true; \
+               REGISTER(C2S_Protocol, NET, id, m_id, new_pure(net_c2s_packet)) \
+               { \
+                       this.netname = #id; \
+               }
+#endif
+
+REGISTRY(C2S_Protocol, BITS(8) - 1)
+#define C2S_Protocol_from(i) _C2S_Protocol_from(i, NULL)
+REGISTER_REGISTRY(C2S_Protocol)
+REGISTRY_SORT(C2S_Protocol)
+REGISTRY_CHECK(C2S_Protocol)
+STATIC_INIT(C2S_Protocol_renumber) { FOREACH(C2S_Protocol, true, it.m_id = i); }
 
 #ifdef SVQC
+       const int MSG_ENTITY = 5;
+
        .int Version;  // deprecated, use SendFlags
        .int SendFlags;
-       .bool(entity to, int sendflags) SendEntity;
-       /** return false to remove from the client */
-       .bool(entity this, entity to, int sendflags) SendEntity3;
 
-       bool SendEntity_self(entity to, int sendflags) { return self.SendEntity3(self, to, 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";
 
-               if (e.model == "" || self.modelindex == 0)
+               if (e.model == "" || e.modelindex == 0)
                {
                        vector mi = e.mins;
                        vector ma = e.maxs;
                        setsize(e, mi, ma);
                }
 
-               e.SendEntity = SendEntity_self;
-               e.SendEntity3 = sendfunc;
+               setSendEntity(e, sendfunc);
                e.SendFlags = 0xFFFFFF;
 
                if (!docull) e.effects |= EF_NODEPTHTEST;
                if (dt)
                {
                        e.nextthink = time + dt;
-                       e.think = SUB_Remove_self;
+                       setthink(e, SUB_Remove);
                }
        }
 
        void Net_UnlinkEntity(entity e)
        {
-               e.SendEntity = func_null;
+               setSendEntity(e, func_null);
        }
 
-       .void() uncustomizeentityforclient;
+       .void(entity this) uncustomizeentityforclient;
        .float uncustomizeentityforclient_set;
 
-       void SetCustomizer(entity e, float() customizer, void() uncustomizer)
+       void SetCustomizer(entity e, bool(entity this, entity client) customizer, void(entity this) uncustomizer)
        {
-               e.customizeentityforclient = customizer;
+               setcefc(e, customizer);
                e.uncustomizeentityforclient = uncustomizer;
                e.uncustomizeentityforclient_set = !!uncustomizer;
+               if(uncustomizer)
+                       IL_PUSH(g_uncustomizables, e);
        }
 
        void UncustomizeEntitiesRun()
        {
-               for (entity e = NULL; (e = findfloat(e, uncustomizeentityforclient_set, 1)); )
-                       WITH(entity, self, e, e.uncustomizeentityforclient());
+               IL_EACH(g_uncustomizables, it.uncustomizeentityforclient_set, it.uncustomizeentityforclient(it));
        }
 
-#endif
+       STRING_ITERATOR(g_buf, string_null, 0);
 
-#include "registry.qh"
-#include "sort.qh"
+       int ReadByte();
 
-.string netname;
-.int m_id;
-.bool(entity this, bool isNew) m_read;
+       void Net_ClientCommand(entity sender, string command)
+       {
+               // command matches `c2s "(.+)"`
+               string buf = substring(command, argv_start_index(1) + 1, -2);
+               if (buf == "") return;
+               STRING_ITERATOR_SET(g_buf, buf, 0);
+               for (int C2S; (C2S = ReadByte()) >= 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", C2S);
+                       return;
+               }
+               g_buf_i--;
+               int expected = strlen(buf);
+               if (g_buf_i > expected) LOG_WARNF("Underflow: %d", g_buf_i - expected);
+               if (g_buf_i < expected) LOG_WARNF("Overrflow: %d", expected - g_buf_i);
+       }
+
+#endif
 
 #ifdef CSQC
+       const int MSG_C2S = 0;
+
        #define Net_Accept(classname) \
-               do \
-               { \
+               MACRO_BEGIN { \
                        if (!this)    this = new(classname); \
-               } \
-               while (0)
+               } MACRO_END
        #define Net_Reject() \
-               do \
-               { \
-                       if (this)     remove(this); \
-               } \
-               while (0)
-       #define NET_HANDLE(id, param) \
-               bool Net_Handle_##id(entity this, param)
-#else
+               MACRO_BEGIN { \
+                       if (this)     delete(this); \
+               } MACRO_END
+
+       string g_buf;
+
+       void Net_Flush()
+       {
+               if (g_buf == "") return;
+               localcmd("\ncmd c2s \"", strreplace("$", "$$", g_buf), "\"\n");
+               strunzone(g_buf);
+               g_buf = string_null;
+       }
+#endif
+
+#if defined(CSQC)
        #define WriteHeader(to, id) \
-               do \
-               { \
+               MACRO_BEGIN { \
+                       WriteByte(to, NET_##id.m_id); \
+               } MACRO_END
+#elif defined(SVQC)
+       #define WriteHeader(to, id) \
+               MACRO_BEGIN { \
                        if (NET_##id##_istemp) WriteByte(to, SVC_TEMPENTITY); \
                        WriteByte(to, NET_##id.m_id); \
-               } \
-               while (0)
+               } MACRO_END
 #endif
 
-#ifdef CSQC
-       #define REGISTER_NET_LINKED(id) \
-               [[accumulate]] NET_HANDLE(id, bool isnew) \
-               { \
-                       this = self; \
-                       this.sourceLocFile = __FILE__; \
-                       this.sourceLocLine = __LINE__; \
-                       if (!this) isnew = true; \
-               } \
-               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) \
-               const bool NET_##id##_istemp = false; \
-               REGISTER(LinkedEntities, NET, id, m_id, new(net_linked_packet)) \
-               { \
-                       make_pure(this); \
-                       this.netname = #id; \
-               }
+// serialization: new style
+
+USING(Stream, int);
+#if defined(SVQC)
+       #define stream_reading(stream) false
+       #define stream_writing(stream) true
+#elif defined(CSQC)
+       #define stream_reading(stream) true
+       #define stream_writing(stream) false
 #endif
 
-REGISTRY(LinkedEntities, BITS(8) - 1)
-#define LinkedEntities_from(i) _LinkedEntities_from(i, NULL)
-REGISTER_REGISTRY(LinkedEntities)
-REGISTRY_SORT(LinkedEntities)
-REGISTRY_CHECK(LinkedEntities)
-STATIC_INIT(RegisterLinkedEntities_renumber)
-{
-       for (int i = 0; i < LinkedEntities_COUNT; ++i)
-               LinkedEntities_from(i).m_id = 1 + i;
-}
+#define serialize(T, stream, ...) serialize_##T(stream, __VA_ARGS__)
+
+#if defined(SVQC)
+       #define serialize_byte(stream, this) \
+               MACRO_BEGIN \
+               WriteByte(stream, this); \
+               MACRO_END
+#elif defined(CSQC)
+       #define serialize_byte(stream, this) \
+               MACRO_BEGIN \
+               this = ReadByte(); \
+               MACRO_END
+#endif
 
-#ifdef CSQC
-       #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) \
-               const bool NET_##id##_istemp = true; \
-               REGISTER(TempEntities, NET, id, m_id, new(net_temp_packet)) \
-               { \
-                       make_pure(this); \
-                       this.netname = #id; \
-               }
+#if defined(SVQC)
+       #define serialize_float(stream, this) \
+               MACRO_BEGIN \
+               WriteCoord(stream, this); \
+               MACRO_END
+#elif defined(CSQC)
+       #define serialize_float(stream, this) \
+               MACRO_BEGIN \
+               this = ReadCoord(); \
+               MACRO_END
 #endif
 
-REGISTRY(TempEntities, BITS(8) - 80)
-#define TempEntities_from(i) _TempEntities_from(i, NULL)
-REGISTER_REGISTRY(TempEntities)
-REGISTRY_SORT(TempEntities)
-REGISTRY_CHECK(TempEntities)
-STATIC_INIT(RegisterTempEntities_renumber)
-{
-       for (int i = 0; i < TempEntities_COUNT; ++i)
-               TempEntities_from(i).m_id = 80 + i;
-}
+#define serialize_vector(stream, this) \
+    MACRO_BEGIN \
+    vector _v = this; \
+    serialize_float(stream, _v.x); \
+    serialize_float(stream, _v.y); \
+    serialize_float(stream, _v.z); \
+    this = _v; \
+    MACRO_END
+
+// serialization: old
 
-#ifndef MENUQC
+#define ReadRegistered(r) r##_from(Read_byte())
+#define WriteRegistered(r, to, it) Write_byte(to, it.m_id)
+
+#define Read_byte() ReadByte()
+#define Write_byte(to, f) WriteByte(to, f)
+
+#if defined(CSQC)
+       int ReadByte();
+       void WriteByte(int to, int b)
+       {
+               assert(to == MSG_C2S);
+               string s = string_null;
+               yenc_single(b, s);
+               string tmp = strcat(g_buf, s);
+               if (g_buf) strunzone(g_buf);
+               g_buf = strzone(tmp);
+       }
+#elif defined(SVQC)
+       int ReadByte()
+       {
+               int ret = -1;
+               ydec_single(g_buf, ret);
+               return ret;
+       }
+       void WriteByte(int to, int b);
+#endif
+
+#define Read_int() ReadInt24_t()
+#define Write_int(to, f) WriteInt24_t(to, f)
+
+#define Read_float() ReadFloat()
+#define Write_float(to, f) WriteFloat(to, f)
+
+#define Read_string() ReadString()
+#define Write_string(to, f) WriteString(to, f)
+
+#ifdef GAMEQC
        const float APPROXPASTTIME_ACCURACY_REQUIREMENT = 0.05;
        #define APPROXPASTTIME_MAX (16384 * APPROXPASTTIME_ACCURACY_REQUIREMENT)
        #define APPROXPASTTIME_RANGE (64 * APPROXPASTTIME_ACCURACY_REQUIREMENT)
@@ -165,8 +301,8 @@ STATIC_INIT(RegisterTempEntities_renumber)
                entity ReadCSQCEntity()
                {
                        int f = ReadShort();
-                       if (f == 0) return world;
-                       return findfloat(world, entnum, f);
+                       if (f == 0) return NULL;
+                       return findfloat(NULL, entnum, f);
                }
                int ReadInt24_t()
                {
@@ -174,29 +310,16 @@ STATIC_INIT(RegisterTempEntities_renumber)
                        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;
-               }
+               #define ReadInt48_t() vec3(ReadInt24_t(), ReadInt24_t(), 0)
+               #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()
-        vector ReadVector() { vector v; v.x = ReadFloat(); v.y = ReadFloat(); v.z = ReadFloat(); return v; }
-               vector ReadVector2D() { vector v; v.x = ReadFloat(); v.y = ReadFloat(); v.z = 0; return v; }
+               #define ReadVector() vec3(ReadFloat(), ReadFloat(), ReadFloat())
+               #define ReadVector2D() vec3(ReadFloat(), ReadFloat(), 0)
 
+               float servertime; // TODO
                float ReadApproxPastTime()
                {
                        float dt = ReadByte();
@@ -208,8 +331,6 @@ STATIC_INIT(RegisterTempEntities_renumber)
                }
 
        #else
-               const int MSG_ENTITY = 5;
-
                void WriteInt24_t(float dst, float val)
                {
                        float v;
@@ -229,8 +350,8 @@ STATIC_INIT(RegisterTempEntities_renumber)
                }
 
         #define WriteFloat(to, f) WriteCoord(to, f)
-               #define WriteVector(to, v) do { WriteFloat(to, v.x); WriteFloat(to, v.y); WriteFloat(to, v.z); } while (0)
-        #define WriteVector2D(to, v) do { WriteFloat(to, v.x); WriteFloat(to, v.y); } while (0)
+               #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
@@ -255,22 +376,17 @@ STATIC_INIT(RegisterTempEntities_renumber)
                }
 
                // 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
+               #define WRITESPECTATABLE_MSG_ONE(to, statement) MACRO_BEGIN { \
+                       entity prev = msg_entity; \
+                       entity dst = to; \
+                       FOREACH_CLIENT(IS_REAL_CLIENT(it), { \
+                               if (it == dst || (it.classname == STR_SPECTATOR && it.enemy == dst)) \
+                               { \
+                                       msg_entity = it; \
+                                       LAMBDA(statement); \
+                               } \
+                       }); \
+                       msg_entity = prev; \
+               } MACRO_END
        #endif
 #endif
-
-#endif