From a185c11f2397c0296a4b62cc266b4fa00a63c1e2 Mon Sep 17 00:00:00 2001 From: Stijn Buys Date: Wed, 14 May 2008 21:07:10 +0000 Subject: console, camera & interpolation --- src/core/application.cc | 26 ++++-- src/core/application.h | 4 + src/core/cvar.cc | 1 + src/core/cvar.h | 2 + src/core/gameconnection.cc | 4 +- src/core/gameinterface.cc | 207 +++++++++++++++++++++++---------------------- src/core/gameinterface.h | 4 +- src/core/gameserver.cc | 10 ++- src/core/gameserver.h | 1 + src/core/netconnection.cc | 14 +-- 10 files changed, 155 insertions(+), 118 deletions(-) (limited to 'src/core') diff --git a/src/core/application.cc b/src/core/application.cc index 79f4a28..67bb952 100644 --- a/src/core/application.cc +++ b/src/core/application.cc @@ -100,10 +100,10 @@ Application::Application() application_game = 0; #ifndef _WIN32 - //sys::signal(SIGHUP, signal_handler); - //sys::signal(SIGINT, signal_handler); - //sys::signal(SIGQUIT, signal_handler); - //sys::signal(SIGTERM, signal_handler); + sys::signal(SIGHUP, signal_handler); + sys::signal(SIGINT, signal_handler); + sys::signal(SIGQUIT, signal_handler); + sys::signal(SIGTERM, signal_handler); #endif } @@ -117,7 +117,7 @@ void Application::init(int count, char **arguments) { con_debug << "Debug messages enabled\n"; con_print << "^BInitializing core...\n"; - + filesystem::init(); CommandBuffer::init(); @@ -156,6 +156,14 @@ void Application::init(int count, char **arguments) Cvar::net_framerate = Cvar::get("net_framerate", "25", Cvar::Archive); Cvar::net_framerate->set_info("[int] network framerate in frames/sec"); +#ifdef _WIN32 + Cvar::con_ansi = Cvar::get("con_ansi", "0", Cvar::Archive); +#else + Cvar::con_ansi = Cvar::get("con_ansi", "1", Cvar::Archive); +#endif + Cvar::con_ansi->set_info("[bool] console ANSI colors"); + sys::ConsoleInterface::instance()->set_ansi(Cvar::con_ansi->value()); + #ifdef _WIN32 // Initialize win32 socket library WSADATA wsa_data; @@ -217,6 +225,8 @@ void Application::shutdown() void Application::quit(int status) { + console()->flush(); + sys::quit(status); } @@ -264,6 +274,8 @@ void Application::disconnect() void Application::frame(float seconds) { + console()->flush(); + // execute commands in the buffer CommandBuffer::exec(); @@ -278,9 +290,11 @@ void Application::frame(float seconds) // run a game interface frame application_game->frame(seconds); - + if (!application_game->running()) disconnect(); + + console()->flush(); } void Application::save_config() diff --git a/src/core/application.h b/src/core/application.h index 01f34cf..bec53d9 100644 --- a/src/core/application.h +++ b/src/core/application.h @@ -7,6 +7,7 @@ #ifndef __INCLUDED_CORE_APPLICATION_H__ #define __INCLUDED_CORE_APPLICATION_H__ +#include "sys/sys.h" #include "core/commandbuffer.h" #include "core/netserver.h" #include "core/netconnection.h" @@ -86,6 +87,9 @@ inline Application *application() { return Application::instance(); } /// pointer to the current GameInterface inline GameInterface *game() { return Application::instance()->game(); } +/// pointer to the console +inline sys::ConsoleInterface *console() { return sys::ConsoleInterface::instance(); }; + } // namespace core #endif // __INCLUDED_CORE_APPLICATION_H__ diff --git a/src/core/cvar.cc b/src/core/cvar.cc index 7593ac3..f8ea746 100644 --- a/src/core/cvar.cc +++ b/src/core/cvar.cc @@ -17,6 +17,7 @@ namespace core { +Cvar *Cvar::con_ansi = 0; Cvar *Cvar::sv_dedicated = 0; Cvar *Cvar::sv_private = 0; Cvar *Cvar::sv_framerate = 0; diff --git a/src/core/cvar.h b/src/core/cvar.h index 4125d3c..69fcae1 100644 --- a/src/core/cvar.h +++ b/src/core/cvar.h @@ -113,6 +113,8 @@ public: static Cvar *sv_private; // client with private server static Cvar *sv_framerate; // server framerate + static Cvar *con_ansi; // console ANSI colors + static Cvar *net_host; // network server ip (default binds to all interfaces) static Cvar *net_port; // network port static Cvar *net_maxclients;// maximum number of connected clients diff --git a/src/core/gameconnection.cc b/src/core/gameconnection.cc index 1d022c5..6090a52 100644 --- a/src/core/gameconnection.cc +++ b/src/core/gameconnection.cc @@ -88,9 +88,7 @@ void GameConnection::frame(float seconds) return; } - if (!Cvar::sv_dedicated->value()) { - update_clientstate(seconds); - } + update_clientstate(seconds); connection_network->frame(seconds); diff --git a/src/core/gameinterface.cc b/src/core/gameinterface.cc index 1f4a5cd..f50c1cc 100644 --- a/src/core/gameinterface.cc +++ b/src/core/gameinterface.cc @@ -18,6 +18,8 @@ namespace core { +const float MIN_DELTA = 10e-10; + void func_list_model(std::string const &args) { model::Model::list(); @@ -97,12 +99,10 @@ void GameInterface::clear() game_clientframetime = 0; } -void GameInterface::reset_clientstate(float servertime) +void GameInterface::reset_clientstate(float timestamp, float prevtimestamp) { - game_previousframetime = game_serverframetime; - game_clientframetime = game_serverframetime; - - game_serverframetime = servertime; + game_previousframetime = prevtimestamp; + game_serverframetime = timestamp; std::map::iterator it; for (it=core::Entity::registry.begin(); it != core::Entity::registry.end(); it++) { @@ -112,121 +112,130 @@ void GameInterface::reset_clientstate(float servertime) if (entity->state() && !(entity->flags() & core::Entity::Static)) entity->state()->assign(entity); } -} - -void GameInterface::update_clientstate(float seconds) -{ - game_clientframetime += seconds; - if (game_clientframetime > game_serverframetime) + if ( game_clientframetime < game_previousframetime) + game_clientframetime = game_previousframetime; + else if ( game_clientframetime > game_serverframetime) game_clientframetime = game_serverframetime; - std::map::iterator it; - for (it=Entity::registry.begin(); it != Entity::registry.end(); it++) { +} + - Entity *entity = (*it).second; +void GameInterface::update_entity_clientstate(Entity *entity) +{ + if (!entity->state()) { + entity->entity_clientstate = new core::ClientState(entity); + entity->entity_clientstate->assign(entity); + } - // update client state - if (!entity->state()) { - entity->entity_clientstate = new core::ClientState(entity); - } + if (!(entity->flags() & core::Entity::Static)) + return; + + if (game_clientframetime < game_serverframetime) { if (!(entity->flags() & core::Entity::Static)) { - + // clientstate location entity->state()->state_location = entity->state()->previouslocation() + - (entity->location() - entity->state()->previouslocation()) * core::game()->timeoffset(); - - if (core::game()->clientframetime() < core::game()->serverframetime()) { - - // http://local.wasp.uwa.edu.au/~pbourke/geometry/planeline/ - float cosangle; - float angle; - float side; - float u; - - math::Vector3f n; - math::Vector3f p; - - // clientstate axis: pitch - - // project entity->axis().up() into the plane with entity->state()->axis()->left() normal - n = entity->state()->axis().left(); - p = entity->axis().up(); - u = p[0]*n[0] + p[1]*n[1] + p[2]*n[2] / (-n[0]*n[0] - n[1]*n[1] - n[2] * n[2]); - p = entity->axis().up() + u * n; - - side = entity->state()->axis().forward().x * p.x + - entity->state()->axis().forward().y * p.y + - entity->state()->axis().forward().z * p.z; - - if (fabs(side) > 0.00005f) { - cosangle = math::dotproduct(p, entity->state()->axis().up()); - - if (fabs(cosangle) < 0.99995f) { - angle = acos(cosangle) * 180.0f / M_PI; - angle = math::sgnf(side) * angle * seconds / - (core::game()->serverframetime() - core::game()->clientframetime()); - - entity->state()->state_axis.change_pitch(-angle); - } + (entity->location() - entity->state()->previouslocation()) * timeoffset(); + + // http://local.wasp.uwa.edu.au/~pbourke/geometry/planeline/ + float cosangle; + float angle; + float side; + float u; + float l; + + math::Vector3f n; + math::Vector3f p; + + entity->state()->state_axis.assign(entity->state()->previousaxis()); + // clientstate axis: pitch + + // project entity->axis().up() into the plane with entity->state()->axis()->left() normal + n = entity->state()->axis().left(); + p = entity->axis().up(); + u = p[0]*n[0] + p[1]*n[1] + p[2]*n[2] / (-n[0]*n[0] - n[1]*n[1] - n[2] * n[2]); + p = entity->axis().up() + u * n; + + side = entity->state()->axis().forward().x * p.x + + entity->state()->axis().forward().y * p.y + + entity->state()->axis().forward().z * p.z; + + l = p.length(); + if ((fabs(side) - MIN_DELTA > 0)) { + cosangle = math::dotproduct(p, entity->state()->axis().up()); + if (fabs(cosangle) + MIN_DELTA < 1 ) { + angle = acos(cosangle) * 180.0f / M_PI; + angle = math::sgnf(side) * angle * timeoffset(); + entity->state()->state_axis.change_pitch(-angle); } - - // clientstate axis: direction - - // project entity->axis().forward() into the plane with entity->state()->axis().up() normal - n = entity->state()->axis().up(); - p = entity->axis().forward(); - u = p[0]*n[0] + p[1]*n[1] + p[2]*n[2] / (-n[0]*n[0] - n[1]*n[1] - n[2] * n[2]); - p = entity->axis().forward() + u * n; - - side = entity->state()->axis().left().x * p.x + - entity->state()->axis().left().y * p.y + - entity->state()->axis().left().z * p.z; - - if (fabs(side) > 0.00005f) { - cosangle = math::dotproduct(p, entity->state()->axis().forward()); - if (fabs(cosangle) < 0.99995f) { - angle = acos(cosangle) * 180.0f / M_PI; - angle = math::sgnf(side) * angle * seconds / - (core::game()->serverframetime() - core::game()->clientframetime()); - - entity->state()->state_axis.change_direction(angle); - } + } + + // clientstate axis: direction + + // project entity->axis().forward() into the plane with entity->state()->axis().up() normal + n = entity->state()->axis().up(); + p = entity->axis().forward(); + u = p[0]*n[0] + p[1]*n[1] + p[2]*n[2] / (-n[0]*n[0] - n[1]*n[1] - n[2] * n[2]); + p = entity->axis().forward() + u * n; + + side = entity->state()->axis().left().x * p.x + + entity->state()->axis().left().y * p.y + + entity->state()->axis().left().z * p.z; + + l = p.length(); + if ((fabs(side) - MIN_DELTA > 0)) { + cosangle = math::dotproduct(p, entity->state()->axis().forward()); + if (fabs(cosangle) + MIN_DELTA < 1 ) { + angle = acos(cosangle) * 180.0f / M_PI; + angle = math::sgnf(side) * angle * timeoffset(); + entity->state()->state_axis.change_direction(angle); } - - // clientstate axis: roll - - // project entity->axis().up() into the plane with entity->state()->axis().forward() normal - n = entity->state()->axis().forward(); - p = entity->axis().up(); - u = p[0]*n[0] + p[1]*n[1] + p[2]*n[2] / (-n[0]*n[0] - n[1]*n[1] - n[2] * n[2]); - p = entity->axis().up() + u * n; - - side = entity->state()->axis().left().x * p.x + - entity->state()->axis().left().y * p.y + - entity->state()->axis().left().z * p.z; - - if (fabs(side) > 0.00005f) { - cosangle = math::dotproduct(p, entity->state()->axis().up()); + } + + // clientstate axis: roll + + // project entity->axis().up() into the plane with entity->state()->axis().forward() normal + n = entity->state()->axis().forward(); + p = entity->axis().up(); + u = p[0]*n[0] + p[1]*n[1] + p[2]*n[2] / (-n[0]*n[0] - n[1]*n[1] - n[2] * n[2]); + p = entity->axis().up() + u * n; + + side = entity->state()->axis().left().x * p.x + + entity->state()->axis().left().y * p.y + + entity->state()->axis().left().z * p.z; + + l = p.length(); + if ((fabs(side) - MIN_DELTA > 0)) { + cosangle = math::dotproduct(p, entity->state()->axis().up()); + if (fabs(cosangle) + MIN_DELTA < 1 ) { angle = acos(cosangle) * 180.0f / M_PI; - if (fabs(cosangle) < 0.99995f) { - angle = math::sgnf(side) * angle * seconds / - (core::game()->serverframetime() - core::game()->clientframetime()); - - entity->state()->state_axis.change_roll(angle); - } + angle = math::sgnf(side) * angle * timeoffset(); + entity->state()->state_axis.change_roll(angle); } - } - } + } + + } else { + entity->state()->assign(entity); + } +} +void GameInterface::update_clientstate(float seconds) +{ + std::map::iterator it; + for (it=core::Entity::registry.begin(); it != core::Entity::registry.end(); it++) { + update_entity_clientstate((*it).second); } } float GameInterface::timeoffset() { + if (game_clientframetime > game_serverframetime) + return 1; + float d = game_serverframetime - game_previousframetime; if (d <= 0) return 0; diff --git a/src/core/gameinterface.h b/src/core/gameinterface.h index 0edcb1b..19c6886 100644 --- a/src/core/gameinterface.h +++ b/src/core/gameinterface.h @@ -52,11 +52,13 @@ public: void clear(); /// reset the client state - void reset_clientstate(float servertime); + void reset_clientstate(float timestamp, float prevtimestamp); /// update the client state timers void update_clientstate(float seconds); + void update_entity_clientstate(Entity *entity); + /*----- virtual mutators ------------------------------------------ */ /// run one game time frame diff --git a/src/core/gameserver.cc b/src/core/gameserver.cc index 11a8b13..fb828e2 100644 --- a/src/core/gameserver.cc +++ b/src/core/gameserver.cc @@ -34,6 +34,7 @@ GameServer::GameServer() : GameInterface() server_instance = this; server_network = 0; server_time = 0; + server_previoustime = 0; server_frametime = 0.0f; server_maxplayerid = 1; @@ -278,7 +279,7 @@ void GameServer::frame(float seconds) // copy the previous entity state to the client state if (!Cvar::sv_dedicated->value()) { - reset_clientstate(server_time); + reset_clientstate(server_time, server_previoustime); } // run a time frame on each entity @@ -308,7 +309,7 @@ void GameServer::frame(float seconds) // start server frame std::ostringstream framehdr; framehdr.str(""); - framehdr << "frame " << server_time << "\n"; + framehdr << "frame " << server_time << " " << server_previoustime << "\n"; server_network->broadcast(framehdr.str()); std::map::iterator it; @@ -377,7 +378,12 @@ void GameServer::frame(float seconds) } } + if (!Cvar::sv_dedicated->value()) { + update_clientstate(0); + } + server_frametime = 0; + server_previoustime = server_time; } diff --git a/src/core/gameserver.h b/src/core/gameserver.h index 4fb9c47..bcd9cc3 100644 --- a/src/core/gameserver.h +++ b/src/core/gameserver.h @@ -76,6 +76,7 @@ private: unsigned int server_maxplayerid; float server_frametime; float server_time; + float server_previoustime; }; inline GameServer *server() { return GameServer::instance(); } diff --git a/src/core/netconnection.cc b/src/core/netconnection.cc index 2bcd6dc..22614d2 100644 --- a/src/core/netconnection.cc +++ b/src/core/netconnection.cc @@ -307,9 +307,9 @@ 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); + float timestamp, prevtimestamp; + if ((msgstream >> timestamp) && (msgstream >> prevtimestamp)) { + game()->reset_clientstate(timestamp, prevtimestamp); } } else if (command == "die") { @@ -329,16 +329,16 @@ void NetConnection::parse_incoming_message(const std::string & message) switch (type) { case Entity::Default: - new Entity(msgstream); + game()->update_entity_clientstate(new Entity(msgstream)); break; case Entity::Dynamic: - new EntityDynamic(msgstream); + game()->update_entity_clientstate(new EntityDynamic(msgstream)); break; case Entity::Controlable: - new EntityControlable(msgstream); + game()->update_entity_clientstate(new EntityControlable(msgstream)); break; case Entity::Globe: - new EntityGlobe(msgstream); + game()->update_entity_clientstate(new EntityGlobe(msgstream)); break; default: con_warn << "Create for unknown entity type " << type << std::endl; -- cgit v1.2.3