]> git.rm.cloudns.org Git - xonotic/xonotic-data.pk3dir.git/commitdiff
Half working branch for ECS
authorMario <mario@smbclan.net>
Mon, 14 May 2018 08:05:47 +0000 (18:05 +1000)
committerMario <mario@smbclan.net>
Mon, 14 May 2018 08:05:47 +0000 (18:05 +1000)
13 files changed:
qcsrc/Makefile
qcsrc/client/progs.inc
qcsrc/ecs/_mod.inc
qcsrc/ecs/cl_main.qc [new file with mode: 0644]
qcsrc/ecs/components/physics.qh
qcsrc/ecs/events/physics.qh
qcsrc/ecs/main.qh
qcsrc/ecs/sv_main.qc [new file with mode: 0644]
qcsrc/ecs/systems/cl_physics.qc
qcsrc/ecs/systems/input.qc
qcsrc/ecs/systems/physics.qc
qcsrc/ecs/systems/sv_physics.qc
qcsrc/server/progs.inc

index d09b2c5ccffa730255a6545d0f411a11adc05fc5..0217e012819d92cdbb1d034f3f153f7f04f4c83e 100644 (file)
@@ -7,7 +7,7 @@ WORKDIR ?= ../.tmp
 QCCFLAGS_WATERMARK ?= $(shell git describe --tags --dirty='~')
 VER = $(subst *,\*,$(QCCFLAGS_WATERMARK))
 NDEBUG ?= 1
-XONOTIC ?= 1
+XONOTIC ?= 0
 ENABLE_EFFECTINFO ?= 0
 ENABLE_DEBUGDRAW ?= 0
 ENABLE_DEBUGTRACE ?= 0
@@ -52,7 +52,6 @@ QCCFLAGS ?= \
        -std=gmqcc \
        -Ooverlap-locals \
        -O3 \
-       $(QCCFLAGS_WERROR) \
        -Wall \
        $(QCCFLAGS_WTFS) \
        -flno -futf8 -fno-bail-on-werror \
index 3b607a7e14add199cd354940018de71d588f2566..0ce19844727e49df431133a5b8f93c57c63236ec 100644 (file)
@@ -17,8 +17,8 @@
 #include <lib/warpzone/server.qc>
 #include <lib/warpzone/util_server.qc>
 
-#include <ecs/_mod.inc>
 #endif
+#include <ecs/_mod.inc>
 
 #ifdef BUILD_MOD
 #include <mod/client/progs.inc>
index 48b7069b243578bea80576dc3d4a3c7715c12e6e..5a26fbda0931714be124efdada198042ef18fe16 100644 (file)
@@ -1,5 +1,11 @@
 // generated file; do not modify
 #include <ecs/main.qc>
+#ifdef CSQC
+    #include <ecs/cl_main.qc>
+#endif
+#ifdef SVQC
+    #include <ecs/sv_main.qc>
+#endif
 
 #include <ecs/components/_mod.inc>
 #include <ecs/events/_mod.inc>
diff --git a/qcsrc/ecs/cl_main.qc b/qcsrc/ecs/cl_main.qc
new file mode 100644 (file)
index 0000000..e84c8f3
--- /dev/null
@@ -0,0 +1,85 @@
+#if !XONOTIC
+       entity me;
+
+       /** 6 bits provides up to 64 remembered states */
+       const int SNAP_BITS = 13;
+       .int snap;
+       .float times[1 << SNAP_BITS];
+
+       void CSQC_Init()
+       {
+               entity it = me = spawn();
+               it.mins = '-16 -16 -24';
+               it.maxs = '+16 +16 +45';
+               it.com_phys = true;
+               it.com_phys_nogravityonground = true;
+               it.com_phys_stepheight = 31;
+               it.com_phys_jumpvel = 260;
+               it.com_phys_friction = 6;
+               //it.com_phys_gravity = '0 0 800';
+               it.com_phys_noclip = true;
+
+               it.com_phys_pos = '0 0 200';
+       }
+
+       void CSQC_Ent_Update(entity this, bool isnew)
+       {
+               int id = ReadByte();
+               FOREACH(LinkedEntities, it.m_id == id, {
+                       if (isnew) this.classname = it.netname;
+                       it.m_read(this, NULL, isnew);
+                       break;
+               });
+       }
+
+       void rec()
+       {
+               me.ARRAY_INDEX(float, times, me.snap) = time;
+               // me.times[me.snap] = time;
+               me.snap = (me.snap + 1) & BITS(SNAP_BITS);
+       }
+
+       NET_HANDLE(ENT_OBJECT, bool isnew)
+       {
+               if (isnew)
+               {
+                       this.com_phys = true;
+                       precache_model("models/player/erebus.iqm");
+                       _setmodel(this, "models/player/erebus.iqm");
+                       this.drawmask = MASK_NORMAL;
+               }
+               this.com_phys_pos_prev = this.com_phys_pos;
+               this.com_phys_ang_prev = this.com_phys_ang;
+               serialize(ENT_OBJECT, 0, this);
+               this.com_phys_pos = this.origin;
+               this.com_phys_ang = this.angles;
+               return true;
+       }
+
+       void CSQC_UpdateView(entity this, float w, float h)
+       {
+               entity it = me;
+               it.com_in_move = input_movevalues;
+               it.com_in_angles = input_angles;
+               it.com_in_jump = input_buttons & BIT(1);
+               makevectors(it.com_in_angles);
+               vector dir = normalize(it.com_in_move);
+               vector upvec = '0 0 1';
+               vector vel = (v_forward * dir.x + v_right * dir.y + upvec * dir.z);
+               if (!it.com_phys_noclip) vel = vec_reflect(vel, upvec, 0);
+               vel = normalize(vel);
+               vel *= 360 * frametime * 8;
+               it.com_phys_vel += vel;
+
+               systems_update();
+
+               setproperty(VF_ORIGIN, it.origin + '0 0 35');
+               addentities(MASK_NORMAL);  // .drawmask
+               renderscene();
+               clearscene();
+
+               Net_Flush();
+               IL_ENDFRAME();
+       }
+#endif
+       
\ No newline at end of file
index f150a296c299e8d46980c1ba2d4fb278665947d4..aa4a0460314d2f6c4f3ce3352a2ff3f6b3e74286 100644 (file)
@@ -24,3 +24,9 @@ COMPONENT(phys);
 .bool com_phys_water;
 .bool com_phys_friction_air;
 .bool move_qcphysics;
+
+.bool com_phys_nogravityonground;
+.float com_phys_stepheight;
+.float com_phys_jumpvel;
+.float com_phys_bounce;
+.bool com_phys_noclip;
index df32c557d1ec661a1c46331e8a05526648c51694..dc965d918954245eb0710a5804400db5008a4dc3 100644 (file)
@@ -1,3 +1,6 @@
 #pragma once
 
 EVENT(phys_land, (entity this));
+
+EVENT(phys_stepfall, (entity this));
+EVENT(phys_stepland, (entity this));
index 724cb1ef8963bf8eb7ddeb447a1f0e5bbf15af53..a28de528ce89277f5c1a6ea469507a023512f647 100644 (file)
@@ -2,4 +2,12 @@
 
 #include "lib.qh"
 
+REGISTER_NET_LINKED(ENT_OBJECT);
+
+#define serialize_ENT_OBJECT(stream, this) \
+       MACRO_BEGIN \
+       serialize_vector(stream, this.origin); \
+       serialize_vector(stream, this.angles); \
+       MACRO_END
+
 void systems_update();
diff --git a/qcsrc/ecs/sv_main.qc b/qcsrc/ecs/sv_main.qc
new file mode 100644 (file)
index 0000000..49b4204
--- /dev/null
@@ -0,0 +1,54 @@
+#if !XONOTIC
+// interpolating with the engine:
+// it.movetype = MOVETYPE_STEP; // engine only interpolates this movetype
+// it.flags |= FL_FLY;          // don't apply forces
+// it.solid = SOLID_NOT;        // don't make stepping sounds
+
+entity testent;
+
+bool net_object_send(entity this, entity to, int sendflags)
+{
+       WriteHeader(MSG_ENTITY, ENT_OBJECT);
+       serialize(ENT_OBJECT, MSG_ENTITY, this);
+       return true;
+}
+
+spawnfunc(worldspawn)
+{
+       static_init();
+       static_init_late();
+       // static_init_precache();
+
+       entity it = testent = spawn();
+       precache_model("models/player/erebus.iqm");
+       _setmodel(it, "models/player/erebus.iqm");
+
+       //Net_LinkEntity(it, true, 0, net_object_send);
+
+       __spawnfunc_spawn_all();
+}
+
+void PlayerPreThink(entity this)
+{
+       // the truth: time
+       // what the client knows: time - this.ping
+       // for fairness, don't compensate shots beyond 400ms
+       // what the client sees: _ - this.cl_interp;
+}
+
+void StartFrame()
+{
+       float f = 1 / autocvar_xon_sys_phys_dt;
+       float n = 5;
+       float x = ((floor(time * f) / f) % n) / n;
+       vector norg = '0 1 0' * x * 500;
+       if (norg != testent.origin)
+       {
+               if (!norg) testent.effects |= EF_TELEPORT_BIT;
+               testent.SendFlags |= 1;
+               setorigin(testent, norg);
+               testent.angles = '0 -360 0' * x;
+               // testent.origin = norg;
+       }
+}
+#endif
index fa087b5eb48bbb29c78bee163e703ee7e9e60a3a..10b5d6579d7e9e75b2b9347d93de6c0c7e69a88e 100644 (file)
@@ -1,5 +1,6 @@
 #include "physics.qh"
 
+#if XONOTIC
 void sys_phys_fix(entity this, float dt)
 {
        this.team = myteam + 1; // is this correct?
@@ -26,3 +27,4 @@ void sys_phys_pregame_hold(entity this) {}
 void sys_phys_spectator_control(entity this) {}
 
 void sys_phys_fixspeed(entity this, float maxspeed_mod) {}
+#endif
index eac36250ba547fe0b411035b5a1fdca087fc8981..d41bcda098d145484ef1e7715accc0e8c1546678 100644 (file)
@@ -2,6 +2,8 @@
 
 void sys_in_update(entity this, float dt)
 {
+#if XONOTIC
        this.com_in_jump = PHYS_INPUT_BUTTON_JUMP(this);
        this.com_in_crouch = PHYS_INPUT_BUTTON_CROUCH(this);
+#endif
 }
index 8896b5a442ba42d78c4420ee3c0332dacb2956c6..e1dc6705a61f17dac1800b81d92fea33660b3f7a 100644 (file)
@@ -1,6 +1,7 @@
 #include "physics.qh"
 #include "input.qh"
 
+#if XONOTIC
 .int disableclientprediction;
 
 void sys_phys_simulate(entity this, float dt);
@@ -494,3 +495,172 @@ void sys_phys_update_single(entity this)
 {
        sys_phys_simulate_simple(this, frametime);
 }
+
+#else
+const int PHYSICS_TRACE_PLANE_MAX = 5;
+
+// NOTE: currently unsuitable for players
+void sys_phys_update(entity this, float dt)
+{
+       // x: { 60: 0.5, 45: ~0.7, 30: ~0.9 }, from: 'vec2(0, 1) * vec2(cos(90 - x), sin(90 - x))'
+       // read as 'within x degrees'
+       float maxgrounddot = 0.5;
+       float maxstepdot = 0.7;
+       vector upvec = '0 0 1';
+       float groundsnap = 1;
+       bool jump = this.com_in_jump;
+       bool jumpstep = true;
+
+       vector mn = this.mins;
+       vector mx = this.maxs;
+
+       vector acc = this.com_phys_acc;
+       vector vel = this.com_phys_vel;
+       vector pos = this.com_phys_pos_prev = this.com_phys_pos;
+       bool onground = this.com_phys_ground;
+
+       bool nogravityonground = this.com_phys_nogravityonground;
+       float stepheight = this.com_phys_stepheight;
+       float stepdownheight = -stepheight;
+       float jumpvel = this.com_phys_jumpvel;
+       float bounce = this.com_phys_bounce;
+       float friction = this.com_phys_friction;
+       float gravity = this.com_phys_gravity.z;
+       bool noclip = this.com_phys_noclip;
+       if (noclip)
+       {
+               jump = false;
+               nogravityonground = false;
+       }
+
+       vector g = upvec * -gravity;
+
+       // apply accelaration in two steps: https://www.niksula.hut.fi/~hkankaan/Homepages/gravity.html
+       // alternatives: rk4, verlet, euler
+       vel += (acc + g) * dt / 2;
+       {
+               if (onground || noclip)
+               {
+                       if (nogravityonground)
+                       {
+                               g = '0 0 0';
+                               if (vel * upvec < 0) vel = vec_reflect(vel, upvec, 0);  // kill downward velocity
+                       }
+                       if (jump)
+                       {
+                               vel += upvec * jumpvel;
+                       }
+                       else  // the first landing frame is free
+                       {
+                               // friction
+                               vector slide = noclip ? vel : vec_reflect(vel, upvec, 0);
+                               vector push = vel - slide;
+                               // TODO: slick
+                               slide *= 1 - friction * dt;
+                               vel = slide + push;
+                       }
+               }
+               vector step = vel * dt;
+               bool pass = false;
+               bool foundground = false;                  // assume until proven otherwise
+               if (nogravityonground) foundground = true; // override
+               bool steplimit = 1;
+               if (noclip)
+               {
+                       pass = true;
+               }
+               else
+               {
+                       for (int i = 0; i < PHYSICS_TRACE_PLANE_MAX; ++i)
+                       {
+                               vector p0 = pos;
+                               vector p1 = p0 + step;
+                               tracebox(p0, mn, mx, p1, MOVE_NORMAL, this);
+                               float frac = trace_fraction;
+                               vector norm = trace_plane_normal;
+                               if (frac == 1)
+                               {
+                                       // all clear
+                                       if (steplimit > 0 && onground && vel * upvec <= 0)
+                                       {
+                                               // can we step down?
+                                               tracebox(p1, mn, mx, p1 + upvec * stepdownheight, MOVE_NORMAL, this);
+                                               if (trace_fraction == 1)
+                                               {
+                                                       // no stairs here
+                                               }
+                                               else if (trace_plane_normal * upvec >= maxstepdot)
+                                               {
+                                                       // step down
+                                                       step += upvec * (stepdownheight * trace_fraction);
+                                               }
+                                       }
+                                       pass = true;
+                                       break;
+                               }
+                               // hit something
+                               if (norm * upvec >= maxgrounddot) foundground = true;
+                               if (steplimit > 0 && (jumpstep || onground))    // try: vel * upvec >= 0
+                               {
+                                       // can we step up?
+                                       vector slide = vec_reflect(step, upvec, 0); // remove fall component
+                                       vector p1 = p0 + slide;                     // step is here
+                                       tracebox(p1 + upvec * stepheight, mn, mx, p1, MOVE_NORMAL, this);
+                                       if (trace_fraction < 1 && trace_plane_normal * upvec >= maxstepdot)
+                                       {
+                                               // there is a step in front of us, get above it
+                                               // TODO: not if it's slippery (slick)
+                                               vector stepup = upvec * (1 - trace_fraction) * stepheight;
+                                               tracebox(p0, mn, mx, p0 + stepup, MOVE_NORMAL, this);
+                                               if (trace_fraction == 1)
+                                               {
+                                                       // go over
+                                                       tracebox(p0 + stepup, mn, mx, p1 + stepup, MOVE_NORMAL, this);
+                                                       if (trace_fraction == 1)
+                                                       {
+                                                               // all clear
+                                                               steplimit -= 1;
+                                                               pos += stepup;
+                                                               if (vel * upvec < 0) vel = vec_reflect(vel, upvec, 0);  // kill downward velocity
+                                                               step = p1 - p0;
+                                                               pass = true;
+                                                               break;
+                                                       }
+                                               }
+                                       }
+                               }
+                               // no stairs here
+                               pos += frac * step;
+                               vel = vec_reflect(vel, norm, bounce);
+                               step = (1 - frac) * vel * dt;
+                               continue;
+                       }
+               }
+               if (nogravityonground)
+               {
+                       vector p1 = pos + step;
+                       tracebox(p1, mn, mx, p1 - groundsnap * upvec, MOVE_NORMAL, this);
+                       foundground = trace_plane_normal * upvec >= maxgrounddot;
+               }
+               if (pass)
+               {
+                       pos += step;
+                       if (!foundground)
+                       {
+                               if (onground) emit(phys_stepfall, this);
+                       }
+                       else
+                       {
+                               if (!onground) emit(phys_stepland, this);
+                       }
+                       onground = foundground;
+               }
+       }
+       vel += (acc + g) * dt / 2;
+
+       this.com_phys_acc = acc;
+       this.com_phys_vel = vel;
+       this.com_phys_pos = pos;
+       this.com_phys_ground = onground;
+}
+#endif
index c3594c0136cfff9cfca75c0573cbfd1349ed2d8e..59f8b07d0eab785a772507e30bfa78bb802b4a91 100644 (file)
@@ -1,5 +1,6 @@
 #include "physics.qh"
 
+#if XONOTIC
 void sys_phys_fix(entity this, float dt)
 {
        WarpZone_PlayerPhysics_FixVAngle(this);
@@ -121,3 +122,4 @@ STATIC_INIT(sys_phys)
        entity listener = new_pure(sys_phys);
        subscribe(listener, phys_land, sys_phys_land);
 }
+#endif
index fd0b0c99e2d60dc5f382747a860548a706b12017..81033514219efbfa9dbb593070b54e454c7d784c 100644 (file)
@@ -14,8 +14,8 @@
 #include <lib/warpzone/server.qc>
 #include <lib/warpzone/util_server.qc>
 
-#include <ecs/_mod.inc>
 #endif
+#include <ecs/_mod.inc>
 
 #ifdef BUILD_MOD
 #include <mod/server/progs.inc>