From 6762bd3e92c8e03640960895f306540527cd5ae0 Mon Sep 17 00:00:00 2001 From: TimePath Date: Sun, 17 Apr 2016 11:48:36 +1000 Subject: [PATCH] Begin networking --- qcsrc/client/autocvars.qh | 1 - qcsrc/client/main.qc | 5 --- qcsrc/ecs/_mod.inc | 3 ++ qcsrc/ecs/cl_main.qc | 38 +++++++++++++++++++ qcsrc/ecs/components/physics.qc | 4 +- qcsrc/ecs/components/physics.qh | 5 ++- qcsrc/ecs/main.qh | 8 ++++ qcsrc/lib/_all.inc | 11 ++++-- qcsrc/lib/csqcmodel/interpolate.qc | 2 + qcsrc/lib/net.qh | 61 +++++++++++++++++++++++++++++- qcsrc/lib/unsafe.qh | 7 +++- qcsrc/server/cl_client.qc | 3 +- 12 files changed, 131 insertions(+), 17 deletions(-) diff --git a/qcsrc/client/autocvars.qh b/qcsrc/client/autocvars.qh index c36d45154..5efd7cb20 100644 --- a/qcsrc/client/autocvars.qh +++ b/qcsrc/client/autocvars.qh @@ -420,7 +420,6 @@ float autocvar_cl_eventchase_speed = 1.3; vector autocvar_cl_eventchase_maxs = '12 12 8'; vector autocvar_cl_eventchase_mins = '-12 -12 -8'; vector autocvar_cl_eventchase_viewoffset = '0 0 20'; -float autocvar_cl_lerpexcess; // TODO: int? string autocvar__togglezoom; int autocvar_cl_damageeffect; float autocvar_cl_damageeffect_ticrate; diff --git a/qcsrc/client/main.qc b/qcsrc/client/main.qc index 98b266c6d..8114023fd 100644 --- a/qcsrc/client/main.qc +++ b/qcsrc/client/main.qc @@ -100,11 +100,6 @@ void CSQC_Init() maxclients = i; } - // needs to be done so early because of the constants they create - static_init(); - static_init_late(); - static_init_precache(); - binddb = db_create(); tempdb = db_create(); ClientProgsDB = db_load("client.db"); diff --git a/qcsrc/ecs/_mod.inc b/qcsrc/ecs/_mod.inc index dd98e07ea..c509ebffd 100644 --- a/qcsrc/ecs/_mod.inc +++ b/qcsrc/ecs/_mod.inc @@ -3,3 +3,6 @@ #ifdef CSQC #include "cl_main.qc" #endif +#ifdef SVQC + #include "sv_main.qc" +#endif diff --git a/qcsrc/ecs/cl_main.qc b/qcsrc/ecs/cl_main.qc index 6064f7d64..b7e638f49 100644 --- a/qcsrc/ecs/cl_main.qc +++ b/qcsrc/ecs/cl_main.qc @@ -3,6 +3,11 @@ #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(); @@ -16,6 +21,39 @@ it.com_phys_gravity = 800; } + void CSQC_Ent_Update(bool isnew) + { + SELFPARAM(); + int id = ReadByte(); + entity recv = LinkedEntities_from(id); + if (isnew) this.classname = recv.netname; + if (recv) recv.m_read(this, NULL, isnew); + } + + 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(float w, float h) { entity it = me; diff --git a/qcsrc/ecs/components/physics.qc b/qcsrc/ecs/components/physics.qc index bfca3d1ba..b46b83716 100644 --- a/qcsrc/ecs/components/physics.qc +++ b/qcsrc/ecs/components/physics.qc @@ -5,6 +5,8 @@ bool autocvar_xon_com_phys_interpolate = true; void com_phys_interpolate(entity it, float a) { if (!autocvar_xon_com_phys_interpolate) a = 1; + // TODO: network time + // a = bound(0, (time - this.com_phys_time) / a, 1 /* + autocvar_cl_lerpexcess /* extrapolation frame limit */ */); it.origin = it.com_phys_pos * a + it.com_phys_pos_prev * (1 - a); - // TODO: orientation (slerp it) + it.angles = it.com_phys_ang * a + it.com_phys_ang_prev * (1 - a); // TODO: slerp, not lerp } diff --git a/qcsrc/ecs/components/physics.qh b/qcsrc/ecs/components/physics.qh index 92dae4cc7..fe22496b5 100644 --- a/qcsrc/ecs/components/physics.qh +++ b/qcsrc/ecs/components/physics.qh @@ -1,8 +1,9 @@ #pragma once +// TODO: store more frames for interpolation COMPONENT(phys); -.vector com_phys_pos; -.vector com_phys_pos_prev; +.vector com_phys_pos; .vector com_phys_pos_prev; +.vector com_phys_ang; .vector com_phys_ang_prev; .vector com_phys_vel; .vector com_phys_acc; diff --git a/qcsrc/ecs/main.qh b/qcsrc/ecs/main.qh index 9b7bf3523..e1f56a628 100644 --- a/qcsrc/ecs/main.qh +++ b/qcsrc/ecs/main.qh @@ -1,3 +1,11 @@ #pragma once +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/lib/_all.inc b/qcsrc/lib/_all.inc index ea1075a6e..667371b43 100644 --- a/qcsrc/lib/_all.inc +++ b/qcsrc/lib/_all.inc @@ -165,8 +165,8 @@ void isnt_bool(float this) { print(ftos(this)); } void ClientKill() { if (_ClientKill) _ClientKill(); } #define ClientKill _ClientKill - void _PlayerPreThink(); - void PlayerPreThink() { if (_PlayerPreThink) _PlayerPreThink(); } + void _PlayerPreThink(entity this); + void PlayerPreThink() { SELFPARAM(); if (_PlayerPreThink) _PlayerPreThink(this); } #define PlayerPreThink _PlayerPreThink void _PlayerPostThink(); @@ -176,7 +176,12 @@ void isnt_bool(float this) { print(ftos(this)); } #ifdef CSQC void _CSQC_Init(); - void CSQC_Init() { if (_CSQC_Init) _CSQC_Init(); } + void CSQC_Init() { + static_init(); + static_init_late(); + static_init_precache(); + if (_CSQC_Init) _CSQC_Init(); + } #define CSQC_Init _CSQC_Init void _CSQC_Shutdown(); diff --git a/qcsrc/lib/csqcmodel/interpolate.qc b/qcsrc/lib/csqcmodel/interpolate.qc index 4fd138360..bcfbadec7 100644 --- a/qcsrc/lib/csqcmodel/interpolate.qc +++ b/qcsrc/lib/csqcmodel/interpolate.qc @@ -125,6 +125,8 @@ void InterpolateOrigin_Note(entity this) } } +float autocvar_cl_lerpexcess; + /** set origin based on iorigin1 (old pos), iorigin2 (desired pos), and time */ void InterpolateOrigin_Do(entity this) { diff --git a/qcsrc/lib/net.qh b/qcsrc/lib/net.qh index faa24e71a..4323a227a 100644 --- a/qcsrc/lib/net.qh +++ b/qcsrc/lib/net.qh @@ -60,7 +60,7 @@ STATIC_INIT(RegisterTempEntities_renumber) { FOREACH(TempEntities, true, it.m_id #endif REGISTRY(LinkedEntities, BITS(8) - 1) -#define LinkedEntities_from(i) _LinkedEntities_from(i, NULL) +#define LinkedEntities_from(i) _LinkedEntities_from((i) - 1, NULL) REGISTER_REGISTRY(LinkedEntities) REGISTRY_SORT(LinkedEntities) REGISTRY_CHECK(LinkedEntities) @@ -209,6 +209,63 @@ STATIC_INIT(C2S_Protocol_renumber) { FOREACH(C2S_Protocol, true, it.m_id = i); } } MACRO_END #endif +// serialization: new + +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 + +#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 + +#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 + +#if defined(SVQC) + #define serialize_vector(stream, this) \ + MACRO_BEGIN \ + serialize_float(stream, this.x); \ + serialize_float(stream, this.y); \ + serialize_float(stream, this.z); \ + MACRO_END +#elif defined(CSQC) + #define serialize_vector(stream, this) \ + MACRO_BEGIN \ + vector _v; \ + serialize_float(stream, _v.x); \ + serialize_float(stream, _v.y); \ + serialize_float(stream, _v.z); \ + this = _v; \ + MACRO_END +#endif + +// serialization: old + #define ReadRegistered(r) r##_from(Read_byte()) #define WriteRegistered(r, to, it) Write_byte(to, it.m_id) @@ -272,7 +329,7 @@ STATIC_INIT(C2S_Protocol_renumber) { FOREACH(C2S_Protocol, true, it.m_id = i); } #define ReadVector() vec3(ReadFloat(), ReadFloat(), ReadFloat()) #define ReadVector2D() vec3(ReadFloat(), ReadFloat(), 0) - float servertime; + float servertime; float ReadApproxPastTime() { diff --git a/qcsrc/lib/unsafe.qh b/qcsrc/lib/unsafe.qh index 97e1c7958..60ad3d88d 100644 --- a/qcsrc/lib/unsafe.qh +++ b/qcsrc/lib/unsafe.qh @@ -1,10 +1,13 @@ #pragma once #define reinterpret_cast(T, it) _unsafe_cast_##T(0, it) -#define X(T) T _unsafe_cast_##T(int dummy, ...) { return ...(0, T); } +#define X(T) \ + T _unsafe_cast_##T(int dummy, ...) { return ...(0, T); } \ + USING(T##_fld, .T); T##_fld _unsafe_cast_##T##_fld(int dummy, ...) { return ...(0, T##_fld); } X(bool) X(int) X(float) +X(vector) X(entity) X(string) USING(rawfunc, float(...)); @@ -24,3 +27,5 @@ STATIC_INIT(INTEGER_ONE) { INTEGER_ONE = reinterpret_cast(int, _unsafe_fld2) - reinterpret_cast(int, _unsafe_fld1); } + +#define ARRAY_INDEX(T, arr, idx) (reinterpret_cast(T##_fld, reinterpret_cast(int, arr[0]) + FTOI(idx))) diff --git a/qcsrc/server/cl_client.qc b/qcsrc/server/cl_client.qc index ffbb55087..5e8db5559 100644 --- a/qcsrc/server/cl_client.qc +++ b/qcsrc/server/cl_client.qc @@ -2071,9 +2071,8 @@ Called every frame for each client before the physics are run void() nexball_setstatus; .float last_vehiclecheck; .int items_added; -void PlayerPreThink () +void PlayerPreThink (entity this) { - SELFPARAM(); WarpZone_PlayerPhysics_FixVAngle(this); STAT(GAMESTARTTIME, this) = game_starttime; -- 2.39.2