Project::OSiRiON - Git repositories
Project::OSiRiON
News . About . Screenshots . Downloads . Forum . Wiki . Tracker . Git
summaryrefslogtreecommitdiff
path: root/src/core
diff options
context:
space:
mode:
authorStijn Buys <ingar@osirion.org>2008-05-06 21:07:11 +0000
committerStijn Buys <ingar@osirion.org>2008-05-06 21:07:11 +0000
commit91d3a0352088611d3b78d3344b7a2bf2d4955a0a (patch)
tree74c0a6adf15ae15aa144f66f20272c1fd58a7db3 /src/core
parent8fefc1d995083f0d4a9873f216ccc6e15688d0a9 (diff)
client-side frame interpolation: frames and timers
Diffstat (limited to 'src/core')
-rw-r--r--src/core/Makefile.am4
-rw-r--r--src/core/entity.cc14
-rw-r--r--src/core/entity.h30
-rw-r--r--src/core/gameconnection.cc4
-rw-r--r--src/core/gameinterface.cc48
-rw-r--r--src/core/gameinterface.h28
-rw-r--r--src/core/gameserver.cc19
-rw-r--r--src/core/gameserver.h1
-rw-r--r--src/core/netconnection.cc26
-rw-r--r--src/core/stats.h1
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
{