diff options
Diffstat (limited to 'src/core')
-rw-r--r-- | src/core/Makefile.am | 4 | ||||
-rw-r--r-- | src/core/entity.cc | 14 | ||||
-rw-r--r-- | src/core/entity.h | 30 | ||||
-rw-r--r-- | src/core/gameconnection.cc | 4 | ||||
-rw-r--r-- | src/core/gameinterface.cc | 48 | ||||
-rw-r--r-- | src/core/gameinterface.h | 28 | ||||
-rw-r--r-- | src/core/gameserver.cc | 19 | ||||
-rw-r--r-- | src/core/gameserver.h | 1 | ||||
-rw-r--r-- | src/core/netconnection.cc | 26 | ||||
-rw-r--r-- | src/core/stats.h | 1 |
10 files changed, 138 insertions, 37 deletions
diff --git a/src/core/Makefile.am b/src/core/Makefile.am index 7c18362..efa4e7b 100644 --- a/src/core/Makefile.am +++ b/src/core/Makefile.am @@ -1,7 +1,7 @@ METASOURCES = AUTO INCLUDES = -I$(top_srcdir)/src -libcore_la_SOURCES = application.cc commandbuffer.cc core.cc cvar.cc entity.cc \ +libcore_la_SOURCES = application.cc commandbuffer.cc clientstate.cc core.cc cvar.cc entity.cc \ func.cc gameconnection.cc gameinterface.cc gameserver.cc module.cc netclient.cc \ netconnection.cc netserver.cc player.cc stats.cc libcore_la_LDFLAGS = -avoid-version -no-undefined @@ -9,7 +9,7 @@ libcore_la_LIBADD = $(top_builddir)/src/filesystem/libfilesystem.la \ $(top_builddir)/src/math/libmath.la $(top_builddir)/src/sys/libsys.la $(top_builddir)/src/model/libmodel.la noinst_LTLIBRARIES = libcore.la -noinst_HEADERS = application.h commandbuffer.h core.h cvar.h entity.h func.h \ +noinst_HEADERS = application.h commandbuffer.h clientstate.h core.h cvar.h entity.h func.h \ gameconnection.h gameinterface.h gameserver.h module.h net.h \ netclient.h netconnection.h netserver.cc player.h stats.h diff --git a/src/core/entity.cc b/src/core/entity.cc index d2fef43..cc956b0 100644 --- a/src/core/entity.cc +++ b/src/core/entity.cc @@ -7,13 +7,9 @@ #include <vector> #include <iomanip> -namespace core -{ - class Entity; -} - #include "sys/sys.h" #include "core/entity.h" +#include "core/cvar.h" namespace core { @@ -101,8 +97,7 @@ Entity::Entity(unsigned int flags) : entity_modelname.clear(); entity_name.clear(); - entity_renderstate = 0; - entity_renderfuzz = math::randomf(); + entity_clientstate = 0; add(this); } @@ -140,14 +135,15 @@ Entity::Entity(std::istream & is) entity_destroyed = false; entity_dirty = false; - entity_renderstate = 0; - entity_renderfuzz = math::randomf(); + entity_clientstate = 0; add(this, entity_id); } Entity::~Entity() { + if (entity_clientstate) + delete entity_clientstate; } void Entity::serialize(std::ostream & os) const diff --git a/src/core/entity.h b/src/core/entity.h index 1e80435..287157b 100644 --- a/src/core/entity.h +++ b/src/core/entity.h @@ -7,6 +7,10 @@ #ifndef __INCLUDED_CORE_ENTITY_H__ #define __INCLUDED_CORE_ENTITY_H__ +#include <iostream> +#include <string> +#include <map> + #include "model/model.h" #include "math/axis.h" #include "math/mathlib.h" @@ -19,12 +23,9 @@ class EntityControlable; } +#include "core/clientstate.h" #include "core/player.h" -#include <iostream> -#include <string> -#include <map> - namespace core { @@ -33,11 +34,11 @@ class Entity { public: /// Entity flags + /** + * entities with the Static flag set will not get client-side interpolation + */ enum Flags {Static=1, Solid=2, Bright=4}; - /// Entity render state flags - enum State {InRange=1, InCloseRange=2}; - /// Entity type constants enum Type {Default=0, Dynamic=1, Controlable=2, Globe=3}; @@ -64,12 +65,6 @@ public: /// core type id virtual inline unsigned int type() const { return Default; } - /// client state - inline unsigned int state() const { return entity_renderstate; } - - /// client render fuzz factor - inline float fuzz() const { return entity_renderfuzz; }; - /// entity flags inline unsigned int flags() const { return entity_flags; } @@ -79,6 +74,9 @@ public: /// entity model name inline std::string const & modelname() { return entity_modelname; } + /// entity client render state + inline ClientState * state() { return entity_clientstate; } + /// pointer to the model, is used client-side inline model::Model * model() { return entity_model; } @@ -158,8 +156,10 @@ public: bool entity_created; bool entity_destroyed; - unsigned int entity_renderstate; - float entity_renderfuzz; + /// timestamp when entity data was received from the server + float entity_servertimestamp; + + ClientState *entity_clientstate; private: /// add an entity to the registry diff --git a/src/core/gameconnection.cc b/src/core/gameconnection.cc index 4f410d5..baf0967 100644 --- a/src/core/gameconnection.cc +++ b/src/core/gameconnection.cc @@ -88,6 +88,10 @@ void GameConnection::frame(float seconds) return; } + if (!Cvar::sv_dedicated->value()) { + update_clientstate(); + } + connection_frametime += seconds; float f = 0; diff --git a/src/core/gameinterface.cc b/src/core/gameinterface.cc index 5789592..8d351a0 100644 --- a/src/core/gameinterface.cc +++ b/src/core/gameinterface.cc @@ -91,7 +91,53 @@ void GameInterface::clear() // remove all models model::Model::clear(); + + game_previousframetime = 0; + game_serverframetime = 0; + game_clientframetime = 0; + game_timestep = 0; + game_frames = 0; } +void GameInterface::reset_clientstate(float servertime) +{ + game_timestep = (servertime - game_serverframetime); + + if (game_timestep < 0) + game_timestep = 0; + + game_previousframetime = game_serverframetime; + game_serverframetime = servertime; + game_clientframetime = game_previousframetime; + + std::map<unsigned int, core::Entity *>::iterator it; + for (it=core::Entity::registry.begin(); it != core::Entity::registry.end(); it++) { + + core::Entity *entity = (*it).second; + + if (entity->state() && !(entity->flags() & Entity::Static)) + entity->state()->assign(entity); + } + + game_frames = 0; +} -} // namespace core +void GameInterface::update_clientstate() +{ + game_frames++; + game_clientframetime += game_timestep; + + if (game_clientframetime > game_serverframetime) + game_clientframetime = game_serverframetime; +} + +float GameInterface::timeoffset() { + float d = game_serverframetime - game_previousframetime; + if (d < 0) + d = 1; + float t = game_serverframetime - game_clientframetime; + + return t/d; +} + +} diff --git a/src/core/gameinterface.h b/src/core/gameinterface.h index e38c061..2324bb5 100644 --- a/src/core/gameinterface.h +++ b/src/core/gameinterface.h @@ -27,6 +27,20 @@ public: /// return the local player inline Player *localplayer() { return &game_localplayer; } + /// return the server time of the last received server frame + inline float serverframetime() const { return game_serverframetime; } + + /// return the server time of the previous received server frame + inline float previousframetime() const { return game_serverframetime; } + + /// return the server time of the previous received server frame + inline float clientframetime() const { return game_clientframetime; } + + /// client frame time between previousframetime and serverframetime, from 0 - 1 + float timeoffset(); + + inline float timestep() const { return game_timestep; } + /*----- virtual inspectors --------------------------------------- */ /// returns true if the game server can run a time frime @@ -37,6 +51,12 @@ public: /// clear all game variables, game functions and entities void clear(); + /// reset the client state + void reset_clientstate(float servertime); + + /// update the client state timers + void update_clientstate(); + /*----- virtual mutators ------------------------------------------ */ /// run one game time frame @@ -46,6 +66,14 @@ public: protected: /// the local player static Player game_localplayer; + + float game_serverframetime; + float game_previousframetime; + + float game_timestep; + float game_clientframetime; + + unsigned int game_frames; }; /// global local player instance diff --git a/src/core/gameserver.cc b/src/core/gameserver.cc index ae2b3a9..3c126fc 100644 --- a/src/core/gameserver.cc +++ b/src/core/gameserver.cc @@ -32,6 +32,7 @@ GameServer::GameServer() : GameInterface() con_print << "Initializing game server...\n"; server_instance = this; server_network = 0; + server_time = 0; server_frametime = 0.0f; server_maxplayerid = 1; @@ -243,6 +244,8 @@ void GameServer::frame(float seconds) if (error()) return; + server_time += seconds; + // process incoming network messages if (server_network) { server_network->receive(); @@ -256,6 +259,10 @@ void GameServer::frame(float seconds) if (localplayer()->dirty()) localplayer()->update_info(); + if (!Cvar::sv_dedicated->value()) { + update_clientstate(); + } + server_frametime += seconds; if ((Cvar::sv_dedicated->value() || Cvar::sv_private->value())) { @@ -266,7 +273,12 @@ void GameServer::frame(float seconds) } } } - + + // copy the previous entity state to the client state + if (!Cvar::sv_dedicated->value()) { + reset_clientstate(server_time); + } + // run a time frame on each entity std::map<unsigned int, Entity *>::iterator it; for (it=Entity::registry.begin(); it != Entity::registry.end(); it++) { @@ -292,6 +304,11 @@ void GameServer::frame(float seconds) server_network->transmit(); // TODO - start server frame + std::ostringstream framehdr; + framehdr.str(""); + framehdr << "frame " << server_time << "\n"; + server_network->broadcast(framehdr.str()); + std::map<unsigned int, Entity *>::iterator it; for (it=Entity::registry.begin(); it != Entity::registry.end(); it++) { Entity *entity = (*it).second; diff --git a/src/core/gameserver.h b/src/core/gameserver.h index 907d69e..4fb9c47 100644 --- a/src/core/gameserver.h +++ b/src/core/gameserver.h @@ -75,6 +75,7 @@ private: unsigned int server_maxplayerid; float server_frametime; + float server_time; }; inline GameServer *server() { return GameServer::instance(); } diff --git a/src/core/netconnection.cc b/src/core/netconnection.cc index dda339c..55480d2 100644 --- a/src/core/netconnection.cc +++ b/src/core/netconnection.cc @@ -267,6 +267,7 @@ void NetConnection::transmit() * msg public <name> <text> * die * ent + * frame * sup * pif */ @@ -305,6 +306,12 @@ void NetConnection::parse_incoming_message(const std::string & message) } else if (command == "ping") { + } else if (command == "frame") { + float timestamp; + if (msgstream >> timestamp) { + game()->reset_clientstate(timestamp); + } + } else if (command == "die") { unsigned int id; if (msgstream >> id) { @@ -339,14 +346,17 @@ void NetConnection::parse_incoming_message(const std::string & message) } } } else if (command == "sup") { - unsigned int id; - if (msgstream >> id) { - //con_debug << "Received update entity id " << id << std::endl; - Entity *entity = Entity::find(id); - if (!entity) { - con_warn << "Update for unknown entity " << id << std::endl; - } else - entity->recieve_server_update(msgstream); + if (connection_state == Connected) + { + unsigned int id; + if (msgstream >> id) { + //con_debug << "Received update entity id " << id << std::endl; + Entity *entity = Entity::find(id); + if (!entity) { + con_warn << "Update for unknown entity " << id << std::endl; + } else + entity->recieve_server_update(msgstream); + } } } else if (command == "pif") { diff --git a/src/core/stats.h b/src/core/stats.h index 44153ec..9d90fdc 100644 --- a/src/core/stats.h +++ b/src/core/stats.h @@ -7,7 +7,6 @@ #ifndef __INCLUDED_CORE_STATS_H__ #define __INCLUDED_CORE_STATS_H__ -/// this namespace contains the network subsystem namespace core { |