From ca0c1d3e6f8b5fa4eb2e0a86fcf47b12fb600786 Mon Sep 17 00:00:00 2001 From: Stijn Buys Date: Sat, 27 Sep 2008 17:16:15 +0000 Subject: mission targets, texture unloading, private messages --- src/core/Makefile.am | 3 +- src/core/application.cc | 29 ++++++- src/core/application.h | 6 +- src/core/commandbuffer.cc | 24 +++++- src/core/core.h | 1 + src/core/gameconnection.cc | 10 +++ src/core/gameconnection.h | 3 + src/core/gameinterface.cc | 44 ++++++++-- src/core/gameinterface.h | 11 +++ src/core/gameserver.cc | 196 +++++++++++++++++++++++++++++---------------- src/core/gameserver.h | 37 ++++----- src/core/message.h | 23 ++++++ src/core/net.h | 2 +- src/core/netconnection.cc | 91 ++++++++++++++------- src/core/netconnection.h | 3 + src/core/netserver.cc | 11 ++- src/core/player.cc | 28 ++++++- src/core/player.h | 9 ++- 18 files changed, 391 insertions(+), 140 deletions(-) create mode 100644 src/core/message.h (limited to 'src/core') diff --git a/src/core/Makefile.am b/src/core/Makefile.am index 802234e..8c44d13 100644 --- a/src/core/Makefile.am +++ b/src/core/Makefile.am @@ -12,6 +12,5 @@ libcore_la_LIBADD = $(top_builddir)/src/model/libmodel.la \ noinst_LTLIBRARIES = libcore.la noinst_HEADERS = application.h clientstate.h commandbuffer.h core.h cvar.h \ - entity.h func.h gameconnection.h gameinterface.h gameserver.h module.h net.h \ + entity.h func.h gameconnection.h gameinterface.h gameserver.h message.h module.h net.h \ netclient.h netconnection.h netserver.h player.h range.h stats.h timer.h - diff --git a/src/core/application.cc b/src/core/application.cc index 21d5e50..6207a0d 100644 --- a/src/core/application.cc +++ b/src/core/application.cc @@ -70,6 +70,16 @@ void func_say(std::string const &args) } } +void func_msg(std::string const &args) +{ + if (connection()) { + connection()->private_message(args); + } else if (server()) { + server()->private_message(localplayer(), args); + } else { + con_print << "Not connected." << std::endl; + } +} // --------------- signal_handler ----------------------------------- #ifndef _WIN32 @@ -222,6 +232,9 @@ void Application::init(int count, char **arguments) func = Func::add("say",func_say); func->set_info("say [text] say something on the public chat"); + + func = Func::add("msg",func_msg); + func->set_info("msg [player] [text] send a private message to another player"); } void Application::shutdown() @@ -299,6 +312,7 @@ void Application::connect(std::string const &host) void Application::disconnect() { if(application_game) { + notify_disconnect(); delete application_game; application_game = 0; con_print << "^BDisconnected.\n"; @@ -446,6 +460,11 @@ void Application::load_commandline(int count, char **arguments) cmd() << '\n'; } +void Application::notify_message(Message::Channel const channel, std::string const message) +{ + con_print << message << std::endl; +} + void Application::notify_sound(const char *name) { // the default implementation does nothing. @@ -458,15 +477,17 @@ void Application::notify_remove_sound(size_t source) // Dedicated servers don't need sounds } -void Application::notify_message(std::string const & message) +void Application::notify_zoneclear(Zone *zone) { - con_print << message << std::endl; + // the default implementation does nothing. + // The client uses this to clear old zones } -void Application::notify_zoneclear(Zone *zone) +void Application::notify_disconnect() { // the default implementation does nothing. - // The client uses this to clear old zones + // The client uses this to clear game data + } } diff --git a/src/core/application.h b/src/core/application.h index ef89e70..0dfa652 100644 --- a/src/core/application.h +++ b/src/core/application.h @@ -9,6 +9,7 @@ #include "sys/sys.h" #include "core/commandbuffer.h" +#include "core/message.h" #include "core/netserver.h" #include "core/netconnection.h" #include "core/gameinterface.h" @@ -62,7 +63,7 @@ public: virtual void notify_sound(const char * name); /// text notifications from the core to the application - virtual void notify_message(std::string const & message); + virtual void notify_message(Message::Channel const channel, std::string const message); /// remove sound source notification virtual void notify_remove_sound(size_t source); @@ -70,6 +71,9 @@ public: /// zone clear notification virtual void notify_zoneclear(Zone *zone); + /// disconnect notification + virtual void notify_disconnect(); + /*----- static --------------------------------------------------- */ /// a pointer to the current application instance diff --git a/src/core/commandbuffer.cc b/src/core/commandbuffer.cc index c111e17..5ed3787 100644 --- a/src/core/commandbuffer.cc +++ b/src/core/commandbuffer.cc @@ -64,6 +64,11 @@ void func_list_zone(std::string const &args) } } +void func_list_model(std::string const &args) +{ + model::Model::list(); +} + void func_set(std::string const &args) { std::istringstream argstream(args); @@ -160,6 +165,9 @@ void CommandBuffer::init() func = Func::add("list_zone", (FuncPtr)func_list_zone); func->set_info("list zones"); + Func::add("list_model", (FuncPtr) func_list_model); + func->set_info("list models"); + func = Func::add("set", (FuncPtr)func_set); func->set_info("[variable] [str] set variable value"); @@ -185,6 +193,7 @@ void CommandBuffer::shutdown() Func::remove("list_var"); Func::remove("list_func"); Func::remove("list_ent"); + Func::remove("list_model"); Func::remove("list_zone"); Func::remove("print"); Func::remove("print_file"); @@ -205,6 +214,10 @@ void CommandBuffer::exec(std::string const &cmdline) aux::to_lowercase(command); //con_debug << "Executing '" << cmdline << "'\n"; + if ((command[0] == '\\') || (command[0] == '/')) { + command.erase(0, 1); + } + // is it a function Func *f = Func::find(command); if (f) { @@ -248,10 +261,15 @@ void CommandBuffer::exec(std::string const &cmdline) } // this gets forwarded to the server - if (connection()) - connection()->forward(cmdline); - else + if (connection()) { + if ((cmdline[0] == '\\') || (cmdline[0] == '/')) { + connection()->forward(cmdline.substr(1, cmdline.size()-1)); + } else { + connection()->forward(cmdline); + } + } else { con_print << "Unknown command '" << command << "^N'\n"; + } } void CommandBuffer::exec() diff --git a/src/core/core.h b/src/core/core.h index feca5fd..80f6d54 100644 --- a/src/core/core.h +++ b/src/core/core.h @@ -18,6 +18,7 @@ #include "core/module.h" #include "core/player.h" #include "core/range.h" +#include "core/stats.h" #include "core/zone.h" /// core contains the basic functionality of the engine diff --git a/src/core/gameconnection.cc b/src/core/gameconnection.cc index ef998e6..114931c 100644 --- a/src/core/gameconnection.cc +++ b/src/core/gameconnection.cc @@ -57,6 +57,8 @@ GameConnection::GameConnection(std::string const &connectionstr) return; } + game_players.push_back(localplayer()); + connection_running = true; } @@ -91,6 +93,14 @@ void GameConnection::say(std::string const &args) connection_network->send_say(args); } +void GameConnection::private_message(std::string const &args) +{ + if (!connection_network->connected()) + return; + + connection_network->send_private_message(args); +} + void GameConnection::frame(float seconds) { if (!running()) diff --git a/src/core/gameconnection.h b/src/core/gameconnection.h index d0da18e..ecf50f2 100644 --- a/src/core/gameconnection.h +++ b/src/core/gameconnection.h @@ -39,6 +39,9 @@ public: /// localplayer sends a chat message to the public channel void say(std::string const &args); + /// localplayer sends a private message to another player + void private_message(std::string const &args); + /*----- static ---------------------------------------------------- */ /// return the current game connection diff --git a/src/core/gameinterface.cc b/src/core/gameinterface.cc index 70224b0..17623f2 100644 --- a/src/core/gameinterface.cc +++ b/src/core/gameinterface.cc @@ -4,9 +4,11 @@ the terms of the GNU General Public License version 2 */ -#include +#include #include +#include +#include "auxiliary/functions.h" #include "core/application.h" #include "core/cvar.h" #include "core/func.h" @@ -19,13 +21,13 @@ namespace core { -const float MIN_DELTA = 10e-10; - -void func_list_model(std::string const &args) +void func_list_players(std::string const &args) { - model::Model::list(); + game()->list_players(); } +const float MIN_DELTA = 10e-10; + Player GameInterface::game_localplayer; EntityControlable *localcontrol() @@ -52,13 +54,14 @@ GameInterface::GameInterface() game_localplayer.player_name.assign("Player"); game_localplayer.update_info(); } - - Func::add("list_model", (FuncPtr) func_list_model); + + Func *func = Func::add("list_players", func_list_players); + func->set_info("get the local list of connected players"); } GameInterface::~GameInterface() { - Func::remove("list_model"); + Func::remove("list_players"); game_localplayer.clear(); @@ -105,6 +108,16 @@ void GameInterface::clear() // remove all models model::Model::clear(); + // clear player list + for (Players::iterator it = game_players.begin(); it != game_players.end(); it++) { + Player *player = (*it); + if (player != localplayer()) { + delete player; + } + } + + game_players.clear(); + game_previousframetime = 0; game_serverframetime = 0; game_clientframetime = 0; @@ -220,4 +233,19 @@ float GameInterface::timeoffset() { return t/d; } +void GameInterface::list_players() +{ + using namespace std; + stringstream msgstr; + int count = 0; + + for (Players::iterator it = game_players.begin(); it != game_players.end(); it++) { + msgstr.str(""); + con_print << setw(3) << (*it)->id() << aux::pad_left((*it)->name(), 24) << std::endl; + count++; + } + + con_print << count << " connected " << aux::plural("player", count) << std::endl; +} + } diff --git a/src/core/gameinterface.h b/src/core/gameinterface.h index ef51545..69cd588 100644 --- a/src/core/gameinterface.h +++ b/src/core/gameinterface.h @@ -22,6 +22,9 @@ public: /// destroy the game virtual ~GameInterface(); + /// type definition for the Players collection + typedef std::list Players; + /*----- inspectors ---------------------------------------------- */ /// return the local player @@ -41,6 +44,11 @@ public: inline float timestep() const { return game_timestep; } + inline Players & players() { return game_players; } + + /// show a list of connected players + void list_players(); + /*----- virtual inspectors --------------------------------------- */ /// returns true if the game server can run a time frime @@ -68,6 +76,9 @@ public: protected: /// the local player static Player game_localplayer; + + /// all the players + Players game_players; float game_serverframetime; float game_previousframetime; diff --git a/src/core/gameserver.cc b/src/core/gameserver.cc index 14f97bb..f251b75 100644 --- a/src/core/gameserver.cc +++ b/src/core/gameserver.cc @@ -4,17 +4,17 @@ the terms of the GNU General Public License version 2 */ -#include #include +#include #include "auxiliary/functions.h" -#include "sys/sys.h" #include "core/application.h" #include "core/cvar.h" #include "core/func.h" #include "core/gameserver.h" #include "core/netserver.h" #include "filesystem/filesystem.h" +#include "sys/sys.h" namespace core { @@ -174,8 +174,6 @@ GameServer::GameServer() : GameInterface() func = Func::add("who", func_who, Func::Shared); func->set_info("get a list of connected players"); - server_players.clear(); - if (!Cvar::sv_dedicated->value()) { player_connect(localplayer()); } @@ -218,8 +216,6 @@ GameServer::~GameServer() Func::remove("who"); server_instance = 0; - - server_players.clear(); } void GameServer::abort() @@ -227,21 +223,6 @@ void GameServer::abort() server_running = false; } -void GameServer::list_players() -{ - using namespace std; - stringstream msgstr; - int count = 0; - - for (Players::iterator it = server_players.begin(); it != server_players.end(); it++) { - msgstr.str(""); - con_print << setw(3) << (*it)->id() << aux::pad_left((*it)->name(), 24) << std::endl; - count++; - } - - con_print << count << " connected " << aux::plural("player", count) << std::endl; -} - void GameServer::showtime() { using namespace std; @@ -265,7 +246,7 @@ Player *GameServer::find_player(std::string const search) std::istringstream searchstr(search); int id = 0; if (searchstr >> id) { - for (std::list:: iterator it = server_players.begin(); it != server_players.end(); it++) { + for (std::list:: iterator it = game_players.begin(); it != game_players.end(); it++) { if ((*it)->id() == id) { return (*it); } @@ -275,7 +256,7 @@ Player *GameServer::find_player(std::string const search) if (search.size() <3) return 0; - for (std::list:: iterator it = server_players.begin(); it != server_players.end(); it++) { + for (std::list:: iterator it = game_players.begin(); it != game_players.end(); it++) { if (aux::text_strip_lowercase((*it)->name()).find(lowercase(search)) != std::string::npos) return (*it); } @@ -298,14 +279,35 @@ void GameServer::say(Player *player, std::string const &message) notification.append("^F:^B "); notification.append(message); - // send to application - application()->notify_message(notification); - application()->notify_sound("com/chat"); - - // broadcast to remote clients - if (server_network) { - server_network->broadcast_message("public", notification); + broadcast_message(Message::Public, notification); +} + +void GameServer::private_message(Player *player, std::string const &args) +{ + if (!args.size()) + return; + + if (player->mute()) { + send(player, "^BYou have been muted."); + return; + } + + std::string target; + std::stringstream argstr(args); + if (!(argstr >> target)) { + return; } + + core::Player *targetplayer = core::server()->find_player(target); + if (!targetplayer) { + send(player, "^BPlayer " + target + "^B not found."); + return; + } + + + std::string message(args.substr(target.size())); + send_message(Message::Private, player, "^FTo ^B" + targetplayer->name() + "^F:" + message); + send_message(Message::Private, targetplayer, "^FFrom ^B" + player->name() + "^F:" + message); } // FIXME kicked by @@ -327,44 +329,114 @@ 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) +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) { - server_network->broadcast_message("info", message, ignore_player); - } + broadcast_message(Message::Info, message, ignore_player); } // send and "info" message to a single player -void GameServer::send(Player *player, std::string message) +void GameServer::send(Player *player, std::string const message) +{ + send_message(Message::Info, player, message); +} + +// send an rcon message to a single player +void GameServer::send_rcon(Player *player, std::string const message) +{ + send_message(Message::RCon, player, message); +} + +void GameServer::send_message(Message::Channel const channel, Player *player, std::string const message) { if (!message.size()) return; - // send to application if (player == localplayer()) { - application()->notify_message(message); + application()->notify_message(channel, message); return; + } else { + if (server_network) { + std::string msg_channel; + switch(channel) { + case core::Message::Info: // Info message + msg_channel.assign("info"); + break; + + case core::Message::Local: // Chat message in the local zone + msg_channel.assign("local"); + break; + + case core::Message::Public: // Public chat message + msg_channel.assign("public"); + break; + + case core::Message::Private: // Private chat message + msg_channel.assign("private"); + break; + + case core::Message::RCon: // RCon message + msg_channel.assign("rcon"); + break; + + default: + con_warn << "message on unknown channel " << channel << "!" << std::endl; + return; + break; + } + + NetClient *client = server_network->find_client(player); + if (client) { + server_network->send_message(client, msg_channel.c_str(), message); + } + } } +} + +// broadcast a message on a specified channel to all players +void GameServer::broadcast_message(Message::Channel const channel, std::string const message, Player *ignore_player) +{ + if (!message.size()) + return; - // send to remote clients + // send to application + if (ignore_player != game()->localplayer()) + application()->notify_message(channel, message); + + // broadcast to remote clients if (server_network) { - NetClient *client = server_network->find_client(player); - if (client) { - server_network->send_message(client, "info", message); + std::string msg_channel; + switch(channel) { + case core::Message::Info: // Info message + msg_channel.assign("info"); + break; + + case core::Message::Local: // Chat message in the local zone + msg_channel.assign("local"); + break; + + case core::Message::RCon: // RCon message + msg_channel.assign("rcon"); + break; + + case core::Message::Public: // Public chat message + msg_channel.assign("public"); + break; + + default: + con_warn << "message on unknown channel " << channel << "!" << std::endl; + return; + break; } + + server_network->broadcast_message(msg_channel.c_str(), message); } } // broadcast a sound event to all players -void GameServer::broadcast_sound(std::string const & sound, Player *ignore_player) +void GameServer::broadcast_sound(std::string const sound, Player *ignore_player) { if (!sound.size()) return; @@ -381,7 +453,7 @@ void GameServer::broadcast_sound(std::string const & sound, Player *ignore_playe } // send a sound event to a single player -void GameServer::send_sound(Player *player, std::string sound) +void GameServer::send_sound(Player *player, std::string const sound) { if (!sound.size()) return; @@ -401,24 +473,6 @@ 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) -{ - // 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) { - server_network->send_message(client, "rcon", message); - } - } -} - // execute a command for a remote player void GameServer::exec(Player *player, std::string const & cmdline) { @@ -478,7 +532,7 @@ void GameServer::player_connect(Player *player) server_module->player_connect(player); // manage player list - server_players.push_back(player); + game_players.push_back(player); } void GameServer::player_disconnect(Player *player) @@ -495,12 +549,12 @@ void GameServer::player_disconnect(Player *player) server_module->player_disconnect(player); // manage player list - std::list:: iterator it = server_players.begin(); - while (((*it)->id() != player->id()) && (it != server_players.end())) { + std::list:: iterator it = game_players.begin(); + while (((*it)->id() != player->id()) && (it != game_players.end())) { it++; } - if (it != server_players.end()) { - server_players.erase(it); + if (it != game_players.end()) { + game_players.erase(it); } } diff --git a/src/core/gameserver.h b/src/core/gameserver.h index 1f6d8cc..b25f1a0 100644 --- a/src/core/gameserver.h +++ b/src/core/gameserver.h @@ -8,6 +8,7 @@ #define __INCLUDED_CORE_GAMESERVER_H__ #include "core/gameinterface.h" +#include "core/message.h" #include "core/module.h" #include "core/netserver.h" @@ -21,8 +22,6 @@ namespace core class GameServer : public GameInterface { public: - typedef std::list Players; - GameServer(); ~GameServer(); @@ -34,9 +33,6 @@ public: /// returns true if the game server can not run a time frime inline bool error() { return !server_running; } - /// show a list of connected players - void list_players(); - /// show the current time void showtime(); @@ -57,23 +53,32 @@ public: /// a player sends a chat message to the public channel void say(Player *player, std::string const &args); + /// a player sends a private message to another player + void private_message(Player *player, std::string const &args); + /// kick a player from the server void kick(Player *player, std::string const &reason); - /// broadcast a message to all players - void broadcast(std::string const & message, Player *ignore_player = 0); + /// broadcast an Info message to all players + void broadcast(std::string const message, Player *ignore_player = 0); + + /// broadcast a message to all players on a specified channel + void broadcast_message(Message::Channel const channel, std::string const message, Player *ignore_player = 0); + + /// send an Info message to a single player + void send(Player *player, std::string const message); - /// send a message to a single player - void send(Player *player, std::string message); + /// send a RCon message to a single player + void send_rcon(Player *player, std::string const message); + + /// send a message on the specific channel to the specified Player + void send_message(Message::Channel const channel, Player *player, std::string const message); /// broadcast a sound to all players - void broadcast_sound(std::string const & sound, Player *ignore_player = 0); + 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); - - /// send a rcon message to a single player - void send_rcon(Player *player, std::string message); + void send_sound(Player *player, std::string const sound); /// a player sends a command to the game server void exec(Player *player, std::string const &cmdline); @@ -81,8 +86,6 @@ public: /// find the first player who's id or name matches the search string Player *find_player(std::string const search); - inline Players & players() { return server_players; } - /*----- static ---------------------------------------------------- */ /// return the current game server @@ -104,8 +107,6 @@ private: float server_frametime; float server_time; float server_previoustime; - - Players server_players; }; inline GameServer *server() { return GameServer::instance(); } diff --git a/src/core/message.h b/src/core/message.h new file mode 100644 index 0000000..53d24be --- /dev/null +++ b/src/core/message.h @@ -0,0 +1,23 @@ +/* + core/message.h + This file is part of the Osirion project and is distributed under + the terms of the GNU General Public License version 2 +*/ + +#ifndef __INCLUDED_CORE_MESSAGE_H__ +#define __INCLUDED_CORE_MESSAGE_H__ + +namespace core +{ + +class Message { + +public: + /// indicates the type of message + enum Channel {Info=0, Public=1, Local=2, Private=3, RCon=4 }; +}; + +} + +#endif // __INCLUDED_CORE_MESSAGE_H__ + diff --git a/src/core/net.h b/src/core/net.h index f3f976b..4909136 100644 --- a/src/core/net.h +++ b/src/core/net.h @@ -11,7 +11,7 @@ namespace core { /// network protocol version -const unsigned int PROTOCOLVERSION = 9; +const unsigned int PROTOCOLVERSION = 10; /// maximum lenght of a (compressed) network message block const unsigned int FRAMESIZE = 1152; diff --git a/src/core/netconnection.cc b/src/core/netconnection.cc index ed1a91b..9268447 100644 --- a/src/core/netconnection.cc +++ b/src/core/netconnection.cc @@ -328,6 +328,7 @@ void NetConnection::send_raw(std::string const &msg) * cup * cmd * say + * priv */ // send a "connect" message to the server @@ -380,6 +381,15 @@ void NetConnection::send_say(std::string const &text) this->send_raw(msg); } +// send a "priv" private message to the server +void NetConnection::send_private_message(std::string const &text) +{ + std::string msg("priv "); + msg.append(text); + msg += '\n'; + this->send_raw(msg); +} + // parse incoming client messages /** * The following incoming messages are parsed; @@ -388,13 +398,14 @@ void NetConnection::send_say(std::string const &text) * disconnect * msg info * msg public + * msg private * msg rcon * msg snd - * die - * ent + * die + * ent * frame - * sup - * pif + * sup + * pif * zone */ void NetConnection::parse_incoming_message(const std::string & message) @@ -409,19 +420,22 @@ void NetConnection::parse_incoming_message(const std::string & message) if (msgstream >> level) { if (level =="info") { if (message.size() > 9) { - application()->notify_message(message.substr(9)); + application()->notify_message(Message::Info, message.substr(9)); } } else if (level =="rcon") { if (message.size() > 9) { - con_print << message.substr(9) << std::endl; + application()->notify_message(Message::RCon, message.substr(9)); } } else if (level == "public") { // FIXME - separate sender nickname if (message.size() > 11) { - application()->notify_message(message.substr(11)); - application()->notify_sound("com/chat"); + application()->notify_message(Message::Public, message.substr(11)); } - + } else if (level == "private") { + // FIXME - separate sender nickname + if (message.size() > 12) { + application()->notify_message(Message::Private, message.substr(12)); + } } else if (level == "snd") { if (message.size() > 8) { application()->notify_sound(message.substr(8).c_str()); @@ -527,29 +541,50 @@ void NetConnection::parse_incoming_message(const std::string & message) } else if (command == "pif") { //con_debug << "Received update player info" << std::endl; - - Zone *oldzone = connection()->localplayer()->zone(); - connection()->localplayer()->receive_server_update(msgstream); - - //con_debug << "zone " << ( connection()->localplayer()->zone() ? connection()->localplayer()->zone()->id() : 0) << std::endl; - if (connection()->localplayer()->zonechange() && oldzone && (oldzone != connection()->localplayer()->zone())) { - - // notify the applciation to clear none-core zone assets (textures etc) - application()->notify_zoneclear(oldzone); - - // delete all entities in the old zone - for (Entity::Registry::iterator it=Entity::registry().begin(); it != Entity::registry().end(); ) { - Entity *entity = (*it).second; + int player_id; + if (!(msgstream >> player_id)) { + con_warn << "Received illegal update player info for player!" << std::endl; + return; + } - if ((entity->zone() == oldzone)) { - delete entity; - Entity::registry().erase(it++); - } else { - ++it; + if (!player_id) { + Zone *oldzone = connection()->localplayer()->zone(); + connection()->localplayer()->receive_server_update(msgstream); + + //con_debug << "zone " << ( connection()->localplayer()->zone() ? connection()->localplayer()->zone()->id() : 0) << std::endl; + + if (connection()->localplayer()->zonechange() && oldzone && (oldzone != connection()->localplayer()->zone())) { + + // notify the applciation to clear none-core zone assets (textures etc) + application()->notify_zoneclear(oldzone); + + // delete all entities in the old zone + for (Entity::Registry::iterator it=Entity::registry().begin(); it != Entity::registry().end(); ) { + Entity *entity = (*it).second; + + if ((entity->zone() == oldzone)) { + delete entity; + Entity::registry().erase(it++); + } else { + ++it; + } + } + oldzone->content().clear(); + } + } else { + // FIXME find player + Player *player = 0; + for (GameInterface::Players::iterator it = game()->players().begin(); it != game()->players().end() && !player; it++) { + if( (*it)->id() == player_id) { + player = (*it); } } - oldzone->content().clear(); + if (!player) { + player = new Player(); + game()->players().push_back(player); + } + player->receive_server_update(msgstream); } } else if (command == "sup") { diff --git a/src/core/netconnection.h b/src/core/netconnection.h index da683f5..cb04ce2 100644 --- a/src/core/netconnection.h +++ b/src/core/netconnection.h @@ -62,6 +62,9 @@ public: /// send a chat message void send_say(std::string const &text); + /// send a private message + void send_private_message(std::string const &text); + /// send a command line to the remote server void send_command(std::string const &cmdline); diff --git a/src/core/netserver.cc b/src/core/netserver.cc index 93d4682..e1bd41a 100644 --- a/src/core/netserver.cc +++ b/src/core/netserver.cc @@ -514,7 +514,7 @@ void NetServer::send_zone_update(NetClient *client, Zone *zone) void NetServer::send_player_update(NetClient *client) { std::ostringstream msg; - msg << "pif "; + msg << "pif 0 "; client->player()->serialize_server_update(msg); msg << '\n'; client->send_raw(msg.str()); @@ -531,6 +531,7 @@ void NetServer::send_player_update(NetClient *client) * pif * ping * say + * priv * */ void NetServer::parse_incoming_message(NetClient *client, const std::string & message) @@ -653,6 +654,14 @@ void NetServer::parse_incoming_message(NetClient *client, const std::string & me } return; } + + // priv + if (command == "priv") { + if (message.size() > command.size()+1) { + server()->private_message(client->player(), message.substr(command.size()+1)); + } + return; + } } diff --git a/src/core/player.cc b/src/core/player.cc index 1a610ca..26ea070 100644 --- a/src/core/player.cc +++ b/src/core/player.cc @@ -6,6 +6,7 @@ #include +#include "auxiliary/functions.h" #include "sys/sys.h" #include "core/player.h" #include "core/cvar.h" @@ -33,6 +34,7 @@ void Player::clear() player_zonechange = false; player_rcon = false; player_mute = false; + player_mission_target = 0; clear_assets(); player_control = 0; @@ -56,12 +58,23 @@ void Player::set_zone(Zone *zone) } } +void Player::set_mission_target(Entity *new_mission_target) +{ + if (new_mission_target != player_mission_target) { + player_mission_target = new_mission_target; + player_dirty = true; + } +} + void Player::update_info() { Cvar *cl_name = Cvar::find("cl_name"); if (cl_name) { - if (cl_name->str().size()) + if (cl_name->str().size()) { player_name = cl_name->str(); + aux::strip_quotes(player_name); + (*cl_name) = player_name; + } } Cvar *cl_color = Cvar::find("cl_color"); @@ -105,8 +118,9 @@ void Player::serialize_server_update(std::ostream & os) const { unsigned int zo = (zone() ? zone()->id() : 0); unsigned int co = (player_control ? player_control->id() : 0); + unsigned int mission = (player_mission_target ? player_mission_target->id() : 0); - os << player_id << " " << zo << " " << co << " " << player_color << " \"" << player_name << "\""; + os << player_id << " " << zo << " " << co << " " << mission << " " << player_color << " \"" << player_name << "\""; } void Player::receive_server_update(std::istream &is) @@ -131,6 +145,16 @@ void Player::receive_server_update(std::istream &is) player_control = 0; } + unsigned int mission = 0; + is >> mission; + if (mission) { + player_mission_target = Entity::find(mission); + if (!player_mission_target) { + con_warn << "mission target set to unknown entity " << co << "\n"; + } + } else { + player_mission_target = 0; + } is >> player_color; std::string n; diff --git a/src/core/player.h b/src/core/player.h index 7bf533c..aa31a35 100644 --- a/src/core/player.h +++ b/src/core/player.h @@ -67,6 +67,9 @@ public: /// player has been muted by admin or console inline bool mute() const { return player_mute; } + /// mission target + inline Entity *mission_target() { return player_mission_target; } + /*----- mutators -------------------------------------------------- */ /// serialize player info to a stream @@ -99,6 +102,8 @@ public: /// update player info from client variables void update_info(); + void set_mission_target(Entity *new_mission_target); + /* -- should actually not be public --*/ /// dirty state @@ -131,10 +136,12 @@ private: // the entity the Player is currently controling EntityControlable *player_control; + Entity *player_mission_target; + // the zone the player is currently in Zone *player_zone; - + float player_credits; }; } -- cgit v1.2.3