From eb075660e7cb61b138c2da337115c59857f89e17 Mon Sep 17 00:00:00 2001 From: Stijn Buys Date: Wed, 16 Jul 2008 22:55:07 +0000 Subject: network protocol cleanup, radar test (doesn't work) --- osirion.kdevelop.pcs | Bin 777319 -> 779161 bytes osirion.kdevses | 18 ++++-- src/auxiliary/functions.cc | 13 +++- src/auxiliary/functions.h | 5 +- src/client/console.cc | 1 + src/client/keyboard.cc | 4 +- src/client/radar.cc | 36 ++++++++++- src/client/view.cc | 131 +++++++++++++++++++------------------ src/core/clientstate.cc | 5 ++ src/core/clientstate.h | 5 ++ src/core/gameconnection.cc | 32 ++++----- src/core/gameinterface.cc | 4 +- src/core/gameserver.cc | 157 ++++++++++++++++++++------------------------- src/core/gameserver.h | 6 +- src/core/netclient.cc | 3 + src/core/netconnection.cc | 90 ++++++++++++++++++++------ src/core/netconnection.h | 21 ++++-- src/core/netserver.cc | 145 +++++++++++++++++++++++++++++++++++++---- src/core/netserver.h | 30 +++++++-- src/render/camera.cc | 26 +++++--- src/render/camera.h | 5 +- src/render/draw.cc | 65 +++++++++++++------ src/render/text.cc | 8 +-- 23 files changed, 551 insertions(+), 259 deletions(-) diff --git a/osirion.kdevelop.pcs b/osirion.kdevelop.pcs index 9d49317..fd56608 100644 Binary files a/osirion.kdevelop.pcs and b/osirion.kdevelop.pcs differ diff --git a/osirion.kdevses b/osirion.kdevses index 650010c..c959ca4 100644 --- a/osirion.kdevses +++ b/osirion.kdevses @@ -1,19 +1,25 @@ - + - + - + - - + + - + + + + + + + diff --git a/src/auxiliary/functions.cc b/src/auxiliary/functions.cc index 5edff56..dbfc799 100644 --- a/src/auxiliary/functions.cc +++ b/src/auxiliary/functions.cc @@ -96,7 +96,7 @@ const std::string text_strip_lowercase(const std::string &text) return r; } -const std::string spaces(const std::string &text,size_t n) +const std::string pad_left(const std::string &text,size_t n) { size_t l = text_length(text); if (n <= l) @@ -108,6 +108,17 @@ const std::string spaces(const std::string &text,size_t n) return s; } +const std::string pad_right(const std::string &text,size_t n) +{ + size_t l = text_length(text); + if (n <= l) + return text; + + std::string s(text); + s.append(n-l, ' '); + return s; +} + void to_lowercase(std::string &text) { for (std::string::iterator i = text.begin(); i != text.end(); ++i) diff --git a/src/auxiliary/functions.h b/src/auxiliary/functions.h index e8704d4..557ab45 100644 --- a/src/auxiliary/functions.h +++ b/src/auxiliary/functions.h @@ -35,7 +35,10 @@ inline bool is_color_code(char const *c) { return (is_base_color_code(c) || is_c size_t text_length(const std::string &text); /// prepend spaces to a string up to the desired lenght, excluding color codes -const std::string spaces(const std::string &text, size_t n); +const std::string pad_left(const std::string &text, size_t n); + +/// append spaces to a string up to the desired lenght, excluding color codes +const std::string pad_right(const std::string &text, size_t n); /// convert a string to lowercase void to_lowercase(std::string &text); diff --git a/src/client/console.cc b/src/client/console.cc index b52f8a0..7bb1aaf 100644 --- a/src/client/console.cc +++ b/src/client/console.cc @@ -69,6 +69,7 @@ void Console::clear() } void Console::draw() { + flush(); if (visible()) draw_console(); else diff --git a/src/client/keyboard.cc b/src/client/keyboard.cc index 83d31e8..be2240a 100644 --- a/src/client/keyboard.cc +++ b/src/client/keyboard.cc @@ -315,7 +315,7 @@ void Keyboard::add_key(const char *name, const unsigned int keysym, const char a void Keyboard::list_keys() { for (iterator it = begin(); it != end(); it++) { - con_print << " " << aux::spaces((*it).second->name(), 6) << " " << (*it).second->bind() << std::endl; + con_print << " " << aux::pad_left((*it).second->name(), 6) << " " << (*it).second->bind() << std::endl; } con_print << keys.size() << " keys" << std::endl; } @@ -325,7 +325,7 @@ void Keyboard::list_binds() size_t n =0; for (iterator it = begin(); it != end(); it++) { if ((*it).second->bind().size()) { - con_print << " " << aux::spaces((*it).second->name(), 6) << " " << (*it).second->bind() << std::endl; + con_print << " " << aux::pad_left((*it).second->name(), 6) << " " << (*it).second->bind() << std::endl; n++; } } diff --git a/src/client/radar.cc b/src/client/radar.cc index cc4257e..cdf5391 100644 --- a/src/client/radar.cc +++ b/src/client/radar.cc @@ -4,14 +4,48 @@ the terms of the GNU General Public License version 2 */ +#include "auxiliary/functions.h" #include "core/core.h" #include "client/radar.h" #include "client/video.h" #include "render/draw.h" #include "render/render.h" +#include "render/text.h" + namespace client { +void Radar::draw() { + using namespace render; + + if (!core::localcontrol()) + return; + + float y = 4 + Text::fontheight(); + Text::draw(4, y, "^N------------ ^BRadar test ^N--------------"); + y += Text::fontheight(); + + gl::color(1.0f, 1.0f, 1.0f, 1.0f); + + std::map::iterator it; + for (it=core::Entity::registry.begin(); it != core::Entity::registry.end(); it++) { + core::Entity *entity = (*it).second; + core::ClientState *state = entity->state(); + + if (state && state->targetable() && entity->label().size()) { + gl::color(entity->color()); + std::ostringstream line; + line << aux::pad_right(entity->name(), 24) << + state->state_screenlocation[0] << " " << + state->state_screenlocation[1] << " " << + state->state_screenlocation[2] << " "; + Text::draw(4, y, line.str()); + y += Text::fontheight(); + } + } + +} +/* void Radar::draw() { using namespace render; @@ -75,5 +109,5 @@ void Radar::draw() glDisableClientState(GL_NORMAL_ARRAY); //glDisableClientState(GL_COLOR_ARRAY); } - +*/ } diff --git a/src/client/view.cc b/src/client/view.cc index 2bbae15..63718e1 100644 --- a/src/client/view.cc +++ b/src/client/view.cc @@ -63,69 +63,12 @@ void shutdown() { } -void reset() -{ - using namespace render; - - // set clear color - gl::clearcolor(0.0f, 0.0f, 0.0f, 1.0f); - - // shading model: Gouraud (smooth, the default) - gl::shademodel(GL_SMOOTH); - //gl::shademodel(GL_FLAT); - - // load identity matrices - gl::matrixmode(GL_MODELVIEW); - gl::loadidentity(); - - gl::matrixmode(GL_MODELVIEW); - gl::loadidentity(); - - // lighting - GLfloat light_position[] = { 0.0, 0.0, 0.0, 1.0 }; - GLfloat ambient_light[] = { 0.01f, 0.01f, 0.01f, 1.0f }; - GLfloat diffuse_light[] = { 0.2f, 0.2f, 0.2f, 1.0f }; - GLfloat specular_light[] = { 0.2f, 0.2f, 0.2f, 1.0f }; - - glLightfv(GL_LIGHT0, GL_POSITION, light_position); - glLightfv(GL_LIGHT0, GL_AMBIENT, ambient_light); - glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuse_light); - glLightfv(GL_LIGHT0, GL_SPECULAR, specular_light); - - // color tracking - glColorMaterial(GL_FRONT, GL_AMBIENT_AND_DIFFUSE); - - GLfloat specular_reflectance[] = { 0.2f, 0.2f, 0.2f, 1.0f }; - glMaterialfv(GL_FRONT, GL_SPECULAR, specular_reflectance); - glMateriali(GL_FRONT, GL_SHININESS, 128); // shininess 1-128 - - gl::disable(GL_LIGHTING); - gl::enable(GL_LIGHT0); - gl::disable(GL_COLOR_MATERIAL); - - // culling - gl::cullface(GL_BACK); - gl::frontface(GL_CCW); - gl::disable(GL_CULL_FACE); - - // depth - gl::depthmask(GL_TRUE); - gl::disable(GL_DEPTH_TEST); - - // alpha-blending - gl::blendfunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - gl::enable(GL_BLEND); - - // client state -} - void draw_loader() { using namespace render; render::Textures::bind("bitmaps/loader"); - gl::color(1.0f, 1.0f, 1.0f, 1.0f); - + gl::begin(gl::Quads); glTexCoord2f(0.0f, 0.0f); @@ -139,6 +82,7 @@ void draw_loader() glTexCoord2f(0.0f, 1.0f); gl::vertex(0,video::height,0); + gl::end(); } @@ -282,6 +226,62 @@ void draw_cursor() gl::end(); } +void reset() +{ + using namespace render; + + // set clear color + gl::clearcolor(0.0f, 0.0f, 0.0f, 1.0f); + + // load identity matrices + gl::matrixmode(GL_MODELVIEW); + gl::loadidentity(); + + gl::matrixmode(GL_MODELVIEW); + gl::loadidentity(); + + // shading model: Gouraud (smooth, the default) + gl::shademodel(GL_SMOOTH); + //gl::shademodel(GL_FLAT); + + // lighting settings for the default light GL_LIGHT0 + GLfloat light_position[] = { 0.0, 0.0, 0.0, 1.0 }; + GLfloat ambient_light[] = { 0.01f, 0.01f, 0.01f, 1.0f }; + GLfloat diffuse_light[] = { 0.2f, 0.2f, 0.2f, 1.0f }; + GLfloat specular_light[] = { 0.2f, 0.2f, 0.2f, 1.0f }; + + glLightfv(GL_LIGHT0, GL_POSITION, light_position); + glLightfv(GL_LIGHT0, GL_AMBIENT, ambient_light); + glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuse_light); + glLightfv(GL_LIGHT0, GL_SPECULAR, specular_light); + + // GL_LIGHT0 is always enabled + gl::enable(GL_LIGHT0); + + // color tracking + glColorMaterial(GL_FRONT, GL_AMBIENT_AND_DIFFUSE); + + // material settings + GLfloat specular_reflectance[] = { 0.2f, 0.2f, 0.2f, 1.0f }; + glMaterialfv(GL_FRONT, GL_SPECULAR, specular_reflectance); + glMateriali(GL_FRONT, GL_SHININESS, 128); // shininess 1-128 + + // alpha blending function + gl::blendfunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + gl::disable(GL_LIGHTING); + gl::disable(GL_COLOR_MATERIAL); + + gl::cullface(GL_BACK); + gl::frontface(GL_CCW); + gl::disable(GL_CULL_FACE); + gl::disable(GL_DEPTH_TEST); + gl::disable(GL_BLEND); + + gl::disable(GL_TEXTURE_2D); + +} + void frame(float seconds) { using namespace render; @@ -300,21 +300,20 @@ void frame(float seconds) if (core::application()->connected() && core::game()->serverframetime()) { render::draw(seconds); // draw the world - if (draw_radar->value()) { - Radar::draw(); - } } // switch to ortographic projection to draw the GUI gl::matrixmode(GL_PROJECTION); gl::loadidentity(); - glOrtho(0, video::width, video::height, 0, -1000.0f, 1000.0f); + glOrtho(0, video::width, video::height, 0, -1024.0f, 1024.0f); gl::matrixmode(GL_MODELVIEW); gl::loadidentity(); gl::enable(GL_TEXTURE_2D); + gl::color(1.0f, 1.0f, 1.0f, 1.0f); + if (!core::application()->connected()) { // draw the loader bitmap draw_loader(); @@ -322,9 +321,15 @@ void frame(float seconds) // draw text elements if (draw_ui->value()) { + Text::setfont("bitmaps/fonts/gui", 16, 24); + draw_status(); + if (draw_radar->value()) { + Radar::draw(); + } + // draw the mouse cursor draw_cursor(); } @@ -334,6 +339,8 @@ void frame(float seconds) console()->draw(); gl::disable(GL_TEXTURE_2D); + + gl::disable(GL_BLEND); } } //namespace view diff --git a/src/core/clientstate.cc b/src/core/clientstate.cc index b34b16a..cc9c79e 100644 --- a/src/core/clientstate.cc +++ b/src/core/clientstate.cc @@ -12,6 +12,11 @@ ClientState::ClientState() { state_visible = false; state_detailvisible = false; + state_targetable = false; + + for (size_t i = 0; i < 3; i++) + state_screenlocation[i] = 0; + state_fuzz = math::randomf(); } diff --git a/src/core/clientstate.h b/src/core/clientstate.h index 915f96f..6cd283d 100644 --- a/src/core/clientstate.h +++ b/src/core/clientstate.h @@ -41,6 +41,8 @@ public: inline bool detailvisible() const { return state_detailvisible; } + inline bool targetable() const { return state_targetable; } + /// client render fuzz factor inline float fuzz() const { return state_fuzz; }; @@ -53,8 +55,11 @@ public: math::Vector3f state_previouslocation; math::Axis state_previousaxis; + double state_screenlocation[3]; + bool state_visible; bool state_detailvisible; + bool state_targetable; float state_fuzz; }; diff --git a/src/core/gameconnection.cc b/src/core/gameconnection.cc index daf47e1..2085adb 100644 --- a/src/core/gameconnection.cc +++ b/src/core/gameconnection.cc @@ -22,6 +22,7 @@ GameConnection::GameConnection(std::string const &connectionstr) connection_instance = this; connection_network = 0; connection_running = false; + connection_frametime = 0; unsigned int port = DEFAULTPORT; std::string host(connectionstr); @@ -48,12 +49,14 @@ GameConnection::GameConnection(std::string const &connectionstr) } // send connect request - std::stringstream netmsgstream(""); - netmsgstream << "connect " << PROTOCOLVERSION << "\n"; - connection_network->send(netmsgstream.str()); + connection_network->send_connect(); connection_network->transmit(); - connection_frametime = 0; + if (!connection_network->connected()) { + abort(); + return; + } + connection_running = true; } @@ -77,10 +80,7 @@ void GameConnection::forward(std::string const &cmdline) if (!connection_network->connected()) return; - std::string netmessage("cmd "); - netmessage.append(cmdline); - netmessage += '\n'; - connection_network->send(netmessage); + connection_network->send_command(cmdline); } void GameConnection::say(std::string const &args) @@ -88,10 +88,7 @@ void GameConnection::say(std::string const &args) if (!connection_network->connected()) return; - std::string netmessage("say "); - netmessage.append(args); - netmessage += '\n'; - connection_network->send(netmessage); + connection_network->send_say(args); } void GameConnection::frame(float seconds) @@ -120,15 +117,10 @@ void GameConnection::frame(float seconds) if (connection_network->state() == NetConnection::Connected) { - if(localcontrol() && localcontrol()->dirty()) { - std::ostringstream netmsg; - netmsg << "cup " << localcontrol()->id() << " "; - localcontrol()->serialize_client_update(netmsg); - netmsg << "\n"; - - connection_network->send(netmsg.str()); + if(localcontrol() && localcontrol()->dirty()) { + connection_network->send_clientupdate(localcontrol()); localcontrol()->entity_dirty = false; - //con_debug << netmsg.str(); + } if (localplayer()->dirty()) { diff --git a/src/core/gameinterface.cc b/src/core/gameinterface.cc index 4aa59be..23b27bc 100644 --- a/src/core/gameinterface.cc +++ b/src/core/gameinterface.cc @@ -130,8 +130,7 @@ void GameInterface::update_entity_clientstate(Entity *entity) if(Cvar::cl_prediction->value() == 0) { - entity->state()->state_axis.assign(entity->axis()); - entity->state()->state_location.assign(entity->location()); + entity->state()->assign(entity); return; } @@ -227,7 +226,6 @@ void GameInterface::update_entity_clientstate(Entity *entity) } } else { - entity->state()->assign(entity); } } diff --git a/src/core/gameserver.cc b/src/core/gameserver.cc index 0a2370c..1866ad3 100644 --- a/src/core/gameserver.cc +++ b/src/core/gameserver.cc @@ -155,14 +155,14 @@ GameServer::GameServer() : GameInterface() func->set_info("[player] [reason] kick a player from the server"); /* func = Func::add("grant_rcon", func_grant_rcon); - func->set_info("[player] grant a player rcon rights"); + func->set_info("[player] grant rcon rights"); func = Func::add("revoke_rcon", func_grant_rcon); - func->set_info("[player] revoke a player's rcon rights"); + func->set_info("[player] revoke rcon rights"); */ /* -- player functions --*/ func = Func::add("time", func_time, Func::Shared); - func->set_info("get the server uptime and current localtime"); + func->set_info("get the server uptime and current server localtime"); func = Func::add("who", func_who, Func::Shared); func->set_info("get a list of connected players"); @@ -224,7 +224,7 @@ void GameServer::list_players() for (std::list:: iterator it = players.begin(); it != players.end(); it++) { msgstr.str(""); - con_print << setw(3) << (*it)->id() << aux::spaces((*it)->name(), 24) << std::endl; + con_print << setw(3) << (*it)->id() << aux::pad_left((*it)->name(), 24) << std::endl; count++; } @@ -293,16 +293,13 @@ void GameServer::say(Player *player, std::string const &message) // broadcast to remote clients if (server_network) { - std::string netmessage("msg public "); - netmessage.append(notification); - netmessage += '\n'; - server_network->broadcast(netmessage); + server_network->broadcast_message("public", notification); } } +// FIXME kicked by void GameServer::kick(Player *player, std::string const &reason) { - // FIXME kicked by if (!server_network) { con_print << "Not running a networked server." << std::endl; return; @@ -322,92 +319,100 @@ void GameServer::kick(Player *player, std::string const &reason) } } +// broadcast an "info" message to all players void GameServer::broadcast(std::string const & message, Player *ignore_player) { + if (!message.size()) + return; + // send to application if (ignore_player != game()->localplayer()) application()->notify_message(message); // broadcast to remote clients if (server_network) { - std::string netmessage("msg info "); - netmessage.append(message); - netmessage += '\n'; - server_network->broadcast(netmessage, ignore_player); + server_network->broadcast_message("info", message, ignore_player); } } -void GameServer::broadcast_sound(std::string const & sound, Player *ignore_player) +// send and "info" message to a single player +void GameServer::send(Player *player, std::string message) { + if (!message.size()) + return; + // send to application - if (ignore_player != game()->localplayer()) - application()->notify_sound(sound.c_str()); + if (player == localplayer()) { + application()->notify_message(message); + return; + } - // broadcast to remote clients + // send to remote clients if (server_network) { - std::string netmessage("msg snd "); - netmessage.append(sound); - netmessage += '\n'; - server_network->broadcast(netmessage, ignore_player); + NetClient *client = server_network->find_client(player); + if (client) { + server_network->send_message(client, "info", message); + } } } -void GameServer::send(Player *player, std::string message) +// broadcast a sound event to all players +void GameServer::broadcast_sound(std::string const & sound, Player *ignore_player) { + if (!sound.size()) + return; + // send to application - if (player->id() == localplayer()->id()) { - application()->notify_message(message); + if (ignore_player != game()->localplayer()) { + application()->notify_sound(sound.c_str()); } - // send to remote clients + // broadcast to remote clients if (server_network) { - NetClient *client = server_network->find_client(player); - if (client) { - std::string netmessage("msg info "); - netmessage.append(message); - netmessage += '\n'; - server_network->send(client, netmessage); - } + server_network->broadcast_message("snd", sound, ignore_player); } } -void GameServer::send_rcon(Player *player, std::string message) +// send a sound event to a single player +void GameServer::send_sound(Player *player, std::string sound) { + if (!sound.size()) + return; + // send to application - if (player->id() == localplayer()->id()) { - con_print << message << std::endl; + if (player == localplayer()) { + application()->notify_sound(sound.c_str()); + return; } - // send to remote clients + // send to remote client if (server_network) { NetClient *client = server_network->find_client(player); if (client) { - std::string netmessage("msg rcon "); - netmessage.append(message); - netmessage += '\n'; - server_network->send(client, netmessage); + server_network->send_message(client, "snd", sound); } } } -void GameServer::send_sound(Player *player, std::string sound) +// send an rcon message to a single player +void GameServer::send_rcon(Player *player, std::string message) { - if (player->id() == localplayer()->id()) { - application()->notify_sound(sound.c_str()); + // send to application + if (player == localplayer()) { + con_print << message << std::endl; + return; } // send to remote clients if (server_network) { NetClient *client = server_network->find_client(player); if (client) { - std::string netmessage("msg snd "); - netmessage.append(sound); - netmessage += '\n'; - server_network->send(client, netmessage); + server_network->send_message(client, "rcon", message); } } } +// execute a command for a remote player void GameServer::exec(Player *player, std::string const & cmdline) { std::string command; @@ -415,8 +420,6 @@ void GameServer::exec(Player *player, std::string const & cmdline) cmdstream.str(cmdline); cmdstream >> command; - //con_debug << "Executing " << player->name() << ": " << cmdline << "\n"; - Func *function = Func::find(command); if (function ) { @@ -425,7 +428,6 @@ void GameServer::exec(Player *player, std::string const & cmdline) args.assign(cmdline.substr(command.size()+1)); if ((function ->flags() & Func::Game) == Func::Game) { - //con_debug << "About to execute " << function->name() << " " << args << "'\n"; function->exec(player, args); return; } else if ((function->flags() & Func::Shared) == Func::Shared) { @@ -436,8 +438,8 @@ void GameServer::exec(Player *player, std::string const & cmdline) char line[MAXCMDSIZE]; - while(console()->buffer().getline(line, MAXCMDSIZE-1)) { - send_rcon(player, std::string(line)); + while(console()->buffer().getline(line, MAXCMDSIZE-1)) { + send(player, std::string(line)); } // disable rcon buffering @@ -552,61 +554,44 @@ void GameServer::frame(float seconds) // send updates if (server_network) { + // FIXME prevent connecting clients from receiving update frames + // transmit buffered sends server_network->transmit(); // start server frame - std::ostringstream framehdr; - framehdr.str(""); - framehdr << "frame " << server_time << " " << server_previoustime << "\n"; - server_network->broadcast(framehdr.str()); + server_network->broadcast_frame(server_time, server_previoustime); + // send changes in the world std::map::iterator it; for (it=Entity::registry.begin(); it != Entity::registry.end(); it++) { + Entity *entity = (*it).second; + if (entity->entity_destroyed) { + if (!entity->entity_created) { - std::ostringstream netmsg; - netmsg.str(""); - netmsg << "die " << entity->id() << "\n"; - server_network->broadcast(netmsg.str()); + server_network->broadcast_entity_delete(entity); } + core::Entity::remove(entity->id()); + } else if (entity->entity_created) { - std::ostringstream netmsg; - netmsg.str(""); - netmsg << "ent "; - entity->serialize(netmsg); - netmsg << "\n"; - server_network->broadcast(netmsg.str()); + + server_network->broadcast_entity_create(entity); entity->entity_created = false; } else if (entity->dirty()) { - std::ostringstream netmsg; - netmsg.str(""); - netmsg << "sup " << entity->id() << " "; - entity->serialize_server_update(netmsg); - netmsg << "\n"; - netmsg.flush(); - server_network->broadcast(netmsg.str()); + + server_network->broadcast_entity_update(entity); } + entity->entity_dirty = false; } // update player info - for (std::list::iterator it = server_network->clients.begin(); it != server_network->clients.end(); it++) { - NetClient *client = *it; - if (client->player()->dirty() && (client->state() == NetClient::Connected)) { - // send player data - std::ostringstream netmsg; - netmsg.str(""); - netmsg << "pif "; - client->player()->serialize_server_update(netmsg); - netmsg << "\n"; - client->send(netmsg.str()); - client->player()->player_dirty = false; - } - } + server_network->broadcast_player_update(); + // transmit buffered sends server_network->transmit(); diff --git a/src/core/gameserver.h b/src/core/gameserver.h index 172fb94..daf1abb 100644 --- a/src/core/gameserver.h +++ b/src/core/gameserver.h @@ -58,12 +58,12 @@ public: /// broadcast a message to all players void broadcast(std::string const & message, Player *ignore_player = 0); - /// broadcast a sound to all players - void broadcast_sound(std::string const & sound, Player *ignore_player = 0); - /// send a message to a single player void send(Player *player, std::string message); + /// broadcast a sound to all players + void broadcast_sound(std::string const & sound, Player *ignore_player = 0); + /// send a sound to a single player void send_sound(Player *player, std::string sound); diff --git a/src/core/netclient.cc b/src/core/netclient.cc index 310a64c..6113f32 100644 --- a/src/core/netclient.cc +++ b/src/core/netclient.cc @@ -113,6 +113,9 @@ void NetClient::receive(char *data) void NetClient::send(std::string const &msg) { + if (error()) + return; + sendq.append(msg); } diff --git a/src/core/netconnection.cc b/src/core/netconnection.cc index bee0843..e415518 100644 --- a/src/core/netconnection.cc +++ b/src/core/netconnection.cc @@ -274,23 +274,7 @@ void NetConnection::frame(float seconds) } } -void NetConnection::send(std::string const &msg) -{ - sendq.append(msg); -} - -void NetConnection::send_playerinfo() -{ - localplayer()->update_info(); - - std::ostringstream osstream; - osstream << "pif "; - localplayer()->serialize_client_update(osstream); - osstream << '\n'; - send(osstream.str()); - localplayer()->player_dirty = false; -} - +// transmit all queued messages void NetConnection::transmit() { @@ -328,6 +312,73 @@ void NetConnection::transmit() connection_keepalive = application()->time(); } +// queue a mmessage to the server +void NetConnection::send(std::string const &msg) +{ + sendq.append(msg); +} + +// functions for outgoing messages +/** + * the following outgoing messages can be send + * + * connect + * pif + * cup + * cmd + * say + */ + +// send a "connect" message to the server +void NetConnection::send_connect() +{ + std::ostringstream msg; + msg << "connect " << PROTOCOLVERSION << "\n"; + this->send(msg.str()); +} + +// send a "pif" player info message to the server +void NetConnection::send_playerinfo() +{ + localplayer()->update_info(); + + std::ostringstream msg; + msg << "pif "; + localplayer()->serialize_client_update(msg); + msg << '\n'; + this->send(msg.str()); + localplayer()->player_dirty = false; +} + +// send a "cup" client update message to the server +void NetConnection::send_clientupdate(Entity *entity) +{ + // cup + std::ostringstream msg; + msg << "cup " << entity->id() << " "; + entity->serialize_client_update(msg); + msg << '\n'; + this->send(msg.str()); +} + +// send a "cmd" command line message to the server +void NetConnection::send_command(std::string const &cmdline) +{ + std::string msg("cmd "); + msg.append(cmdline); + msg += '\n'; + this->send(msg); +} + +// send a "say" chat message message to the server +void NetConnection::send_say(std::string const &text) +{ + std::string msg("say "); + msg.append(text); + msg += '\n'; + this->send(msg); +} + // parse incoming client messages /** * The following incoming messages are parsed; @@ -442,9 +493,12 @@ void NetConnection::parse_incoming_message(const std::string & message) //con_debug << "Received update entity id " << id << std::endl; Entity *entity = Entity::find(id); if (!entity) { + // FIXME request entity from the server con_warn << "Update for unknown entity " << id << std::endl; - } else + } else { + // FIXME check of the received update matches the actual entity entity->recieve_server_update(msgstream); + } } } diff --git a/src/core/netconnection.h b/src/core/netconnection.h index a2e9f2f..4e8d9f9 100644 --- a/src/core/netconnection.h +++ b/src/core/netconnection.h @@ -28,6 +28,7 @@ #include #include +#include "core/entity.h" #include "core/net.h" namespace core @@ -49,13 +50,22 @@ public: /// process pending incoming messages void frame(float seconds); - /// buffer outgoing data - void send(std::string const &msg); + /// send a connect message to the remote server + void send_connect(); - /// sennd a player info message + /// send a player info message to the remote server void send_playerinfo(); - /// send bufered outgoing data + /// send a client update message to the remote server + void send_clientupdate(Entity *entity); + + /// send a chat message + void send_say(std::string const &text); + + /// send a command line to the remote server + void send_command(std::string const &cmdline); + + /// transmit messages in the outgoing queue to the remote server void transmit(); void abort(); @@ -81,6 +91,9 @@ public: State connection_state; protected: + /// add a message to the queue + void send(std::string const &msg); + /// receive incoming data and store messages void receive(); diff --git a/src/core/netserver.cc b/src/core/netserver.cc index fe6e45b..ac24f33 100644 --- a/src/core/netserver.cc +++ b/src/core/netserver.cc @@ -310,34 +310,153 @@ void NetServer::client_initialize(NetClient *client) { client->client_state = NetClient::Pending; } -void NetServer::send(NetClient * client, std::string const & message) +// find the client corresponding to a player +NetClient *NetServer::find_client(Player const *player) { - client->send(message); + for (std::list::iterator it = clients.begin(); it != clients.end(); it++) { + if ((*it)->player() == player) { + return (*it); + } + } + return 0; } -// send a message to all clients -void NetServer::broadcast(std::string const & message, Player *ignore_player) +// send outgoing messages to clients + +/** + * The followig messages can be send to a client + * + * frame + * ent + * die + * sup + + * msg + * supported message channels are "info" "public" "rcon" and "snd" + * "snd" is a special channel to transmit sound events + */ + +// broadcast a "msg " message to all clients +void NetServer::broadcast_message(const char *channel, std::string const & message, Player *ignore_player) { - //std::cout << "NetServer: " << osstream.str(); + if (!channel) + return; + + std::string msg("msg "); + msg.append(channel); + msg += ' '; + msg.append(message); + msg += '\n'; + for (std::list::iterator it = clients.begin(); it != clients.end(); it++) { - NetClient *client = *it; - if (!client->error() && (client->state() == NetClient::Connected) && client->player() != ignore_player) - client->send(message); + if (((*it)->player() && (*it)->player() != ignore_player) && ((*it)->state() == NetClient::Connected)) { + (*it)->send(msg); + } } } -// find the client corresponding to a player -NetClient *NetServer::find_client(Player const *player) +// send a "msg " message to one client +void NetServer::send_message(NetClient *client, const char *channel, std::string const & message) +{ + if (!channel) + return; + + std::string msg("msg "); + msg.append(channel); + msg += ' '; + msg.append(message); + msg += '\n'; + + client->send(msg); +} + +// broadcast a "frame" message to all clients +void NetServer::broadcast_frame(float timestamp, float previoustimestamp) { + std::ostringstream msg(""); + msg << "frame " << timestamp << " " << previoustimestamp << "\n"; + for (std::list::iterator it = clients.begin(); it != clients.end(); it++) { - if ((*it)->player() == player) { - return (*it); + if ((*it)->state() == NetClient::Connected) { + (*it)->send(msg.str()); + } + } +} + +// broadcast a "die" delete entity message to all clients +void NetServer::broadcast_entity_delete(Entity *entity) +{ + std::ostringstream msg(""); + msg << "die " << entity->id() << '\n'; + + for (std::list::iterator it = clients.begin(); it != clients.end(); it++) { + if ((*it)->state() == NetClient::Connected) { + (*it)->send(msg.str()); + } + } +} + +// broadcast a "ent" create entity message to all clients +void NetServer::broadcast_entity_create(Entity *entity) +{ + std::ostringstream msg; + msg << "ent "; + entity->serialize(msg); + msg << '\n'; + + for (std::list::iterator it = clients.begin(); it != clients.end(); it++) { + if ((*it)->state() == NetClient::Connected) { + (*it)->send(msg.str()); + } + } +} + +// broadcast a "sup" server update entity message to all clients +void NetServer::broadcast_entity_update(Entity *entity) +{ + std::ostringstream msg; + msg << "sup " << entity->id() << " "; + entity->serialize_server_update(msg); + msg << '\n'; + + for (std::list::iterator it = clients.begin(); it != clients.end(); it++) { + if ((*it)->state() == NetClient::Connected) { + (*it)->send(msg.str()); + } + } +} + +// broadcast a "pif" update player information if necessary +void NetServer::broadcast_player_update() +{ + for (std::list::iterator it = clients.begin(); it != clients.end(); it++) { + NetClient *client = *it; + + if (client->player()->dirty()) { + // send player data + std::ostringstream msg; + msg << "pif "; + client->player()->serialize_server_update(msg); + msg << '\n'; + client->send(msg.str()); + + client->player()->player_dirty = false; } } - return 0; +} + +// send a "pif" update player information to a single player +void NetServer::send_player_update(NetClient *client) +{ + std::ostringstream msg; + msg << "pif "; + client->player()->serialize_server_update(msg); + msg << '\n'; + client->send(msg.str()); } // parse incoming client messages + /** * The following incoming protocol messages are parsed; * diff --git a/src/core/netserver.h b/src/core/netserver.h index a83229c..25bca5f 100644 --- a/src/core/netserver.h +++ b/src/core/netserver.h @@ -52,17 +52,33 @@ public: /// transmit data to clients void transmit(); - /// broadcast network data to all clients - void broadcast(std::string const & message, Player *ignore_player=0); + /// broadcast a message + void broadcast_message(const char *channel, std::string const & message, Player *ignore_player=0); - /// send network data to one client - void send(NetClient * client, std::string const & message); + /// send a message to a single client + void send_message(NetClient *client, const char *channel, std::string const & message); + + /// broadcast a server frame message + void broadcast_frame(float timestamp, float previoustimestamp); + + /// broadcast a delete entity event + void broadcast_entity_delete(Entity *entity); + + /// broadcast a create entity event + void broadcast_entity_create(Entity *entity); + + /// broadcast a update entity event + void broadcast_entity_update(Entity *entity); + + /// broadcast updated player information, if necessary + void broadcast_player_update(); + + /// send an update player information message to a single client + void send_player_update(NetClient *client); /// find the client corresponding to a player NetClient *find_client(Player const *player); - std::list clients; - protected: /// set the error state void abort(); @@ -88,6 +104,8 @@ private: int fdmax; char recbuf[FRAMESIZE]; + + std::list clients; }; } diff --git a/src/render/camera.cc b/src/render/camera.cc index 287e4ad..8fe84a7 100644 --- a/src/render/camera.cc +++ b/src/render/camera.cc @@ -150,9 +150,8 @@ void Camera::next_mode() } } -void Camera::draw(float seconds) +void Camera::frame(float seconds) { - math::Matrix4f matrix; math::Axis target_axis; float d = 0; @@ -304,14 +303,28 @@ void Camera::draw(float seconds) distance += frustum_front; + // calculate eye position + camera_eye = camera_target - (distance * camera_axis.forward()); +} + +void Camera::draw() +{ + // Change to the projection matrix and set our viewing volume large enough for the skysphere + gl::matrixmode(GL_PROJECTION); + gl::loadidentity(); + gl::frustum(-frustum_size*Camera::aspect(), frustum_size*Camera::aspect(), + -frustum_size, frustum_size, frustum_front, 2048.0f); + + gl::matrixmode(GL_MODELVIEW); + gl::loadidentity(); + // map world coordinates to opengl coordinates gl::rotate(90.0f, 0, 1.0, 0); gl::rotate(-90.0f, 1.0f , 0, 0); - // assign transformation matrix - matrix.assign(camera_axis); - // apply the transpose of the axis transformation (the axis is orhtonormal) + math::Matrix4f matrix; + matrix.assign(camera_axis); gl::multmatrix(matrix.transpose()); // match the camera with the current target @@ -319,9 +332,6 @@ void Camera::draw(float seconds) // apply camera offset gl::translate(distance * camera_axis.forward()); - - // calculate eye position - camera_eye = camera_target - (distance * camera_axis.forward()); } void Camera::set_direction(float direction) diff --git a/src/render/camera.h b/src/render/camera.h index 52d2e13..edc3496 100644 --- a/src/render/camera.h +++ b/src/render/camera.h @@ -46,8 +46,11 @@ public: /// reset the current mode static void reset(); + /// progress the camera + static void frame(float elapsed); + /// draw the OpenGL camera transformation - static void draw(float elapsed); + static void draw(); /// set target direction static void set_direction(float direction); diff --git a/src/render/draw.cc b/src/render/draw.cc index c650169..18c3d73 100644 --- a/src/render/draw.cc +++ b/src/render/draw.cc @@ -12,6 +12,7 @@ #include "render/render.h" #include "render/textures.h" #include "render/draw.h" +#include "render/gl.h" namespace render { @@ -36,7 +37,7 @@ math::Vector3f v6(-1, 1, -1); math::Vector3f v7(-1, -1, -1); const float drawdistance = 128.0f; -const float drawfxdistance = 32.0f; +const float drawfxdistance = 64.0f; float angle = 0; @@ -299,6 +300,15 @@ void pass_prepare(float seconds) // reset light state gl::disable(GL_LIGHT1); + // get the current OpenGL transformation matrices + GLdouble gl_projection_matrix[16]; + GLdouble gl_model_matrix[16]; + GLint gl_viewport[4]; + + glGetDoublev(GL_PROJECTION, gl_projection_matrix); + glGetDoublev(GL_MODELVIEW, gl_model_matrix); + glGetIntegerv(GL_VIEWPORT, gl_viewport); + std::map::iterator it; for (it=core::Entity::registry.begin(); it != core::Entity::registry.end(); it++) { @@ -353,8 +363,9 @@ void pass_prepare(float seconds) entity->entity_clientstate = new core::ClientState(entity); } - entity->state()->state_visible = true; + entity->state()->state_visible = false; entity->state()->state_detailvisible = false; + entity->state()->state_targetable = false; // calculate visibility for entities with models if (entity->model()) { @@ -373,6 +384,8 @@ void pass_prepare(float seconds) } } else { + entity->state()->state_visible = true; + if (entity->type() == core::Entity::Globe) { core::EntityGlobe *globe = (core::EntityGlobe *) entity; @@ -408,6 +421,21 @@ void pass_prepare(float seconds) } } } + + // calculate screen position + if (entity->state()->visible()) { + GLdouble x = 0; + GLdouble y = 0; + GLdouble z = 0; + + math::Vector3f const & pos = entity->state()->location(); + if (gluProject((GLdouble) pos.x , (GLdouble)pos.y, (GLdouble)pos.z, gl_model_matrix, gl_projection_matrix, gl_viewport, &x, &y, &z) == GL_TRUE) { + entity->state()->state_screenlocation[0] = x; + entity->state()->state_screenlocation[1] = y; + entity->state()->state_screenlocation[2] = z; + entity->state()->state_targetable = true; + } + } } } @@ -723,7 +751,7 @@ void draw_pass_sky() gl::push(); gl::translate(Camera::eye()); - draw_sphere_inside(math::Color(), 8192); + draw_sphere_inside(math::Color(), 128); gl::pop(); gl::disable(GL_TEXTURE_2D); @@ -747,6 +775,7 @@ void draw_pass_spacegrid() gl::normal(0, 0, 1.0f); gl::begin(gl::Lines); + for (int i=-gridsize; i <= gridsize; i++) { gl::color(0,0, 0, 0); gl::vertex(i-dx, -gridsize-dy, z); @@ -780,15 +809,8 @@ void draw(float seconds) angle -= 360.0f; } - // Change to the projection matrix and set our viewing volume large enough for the skysphere - gl::matrixmode(GL_PROJECTION); - gl::loadidentity(); - gl::frustum(-frustum_size*Camera::aspect(), frustum_size*Camera::aspect(), - -frustum_size, frustum_size, frustum_front, 8192.0f); - - gl::matrixmode(GL_MODELVIEW); - gl::loadidentity(); - Camera::draw(seconds); // draw the current camera transformation + Camera::frame(seconds); + Camera::draw(); // draw the current camera transformation // calculate client state pass_prepare(seconds); @@ -813,24 +835,27 @@ void draw(float seconds) glEnableClientState(GL_NORMAL_ARRAY); glDisableClientState(GL_COLOR_ARRAY); - gl::disable(GL_BLEND); // disbable alpha blending - gl::disable(GL_RESCALE_NORMAL); + gl::enable(GL_DEPTH_TEST); + gl::depthmask(GL_FALSE); // disable depth buffer writing draw_pass_sky(); // draw the skysphere - gl::enable(GL_DEPTH_TEST); // enable depth buffer writing + + gl::depthmask(GL_TRUE); // enable writing to the depth buffer + gl::enable(GL_CULL_FACE); // enable culling gl::enable(GL_COLOR_MATERIAL); // enable color tracking gl::enable(GL_LIGHTING); gl::enable(GL_RESCALE_NORMAL); // rescale normals by the transformation matrix scale factor - + draw_pass_default(); // draw entities without model + + gl::disable(GL_RESCALE_NORMAL); glEnableClientState(GL_COLOR_ARRAY); - gl::disable(GL_RESCALE_NORMAL); draw_pass_model_vertex(); // draw entities with model - + glDisableClientState(GL_COLOR_ARRAY); draw_pass_model_evertex(); // draw entities with model, vertices with entity color @@ -855,8 +880,8 @@ void draw(float seconds) gl::disable(GL_LIGHTING); gl::disable(GL_COLOR_MATERIAL); // disable color tracking gl::disable(GL_CULL_FACE); // disable culling - gl::disable(GL_DEPTH_TEST); // disable depth buffer - + + gl::disable(GL_DEPTH_TEST); // disable depth buffer testing // GL_BLEND must be enabled for the GUI } diff --git a/src/render/text.cc b/src/render/text.cc index 7c1ae8e..f5c221f 100644 --- a/src/render/text.cc +++ b/src/render/text.cc @@ -98,16 +98,16 @@ void Text::draw(float x, float y, const char ascii) gl::begin(gl::Quads); glTexCoord2f(fcol, frow); - gl::vertex(x,y,1); + gl::vertex(x,y, 0); glTexCoord2f(fcol + 0.0625f, frow); - gl::vertex(x+text_fontwidth,y,1); + gl::vertex(x+text_fontwidth,y, 0); glTexCoord2f(fcol +0.0625f, frow + 0.0625f); - gl::vertex(x+text_fontwidth,y+text_fontheight,1); + gl::vertex(x+text_fontwidth,y+text_fontheight, 0); glTexCoord2f(fcol, frow+0.0625f); - gl::vertex(x,y+text_fontheight,1); + gl::vertex(x,y+text_fontheight, 0); gl::end(); } -- cgit v1.2.3