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) --- 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 +++++++-- 11 files changed, 345 insertions(+), 153 deletions(-) (limited to 'src/core') 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; }; } -- cgit v1.2.3