/* core/gameconnection.cc This file is part of the Osirion project and is distributed under the terms of the GNU General Public License version 2 */ #include #include #include "sys/sys.h" #include "filesystem/filesystem.h" #include "core/cvar.h" #include "core/gameconnection.h" #include "core/net.h" namespace core { const unsigned long INFOTIMEOUT = 2500; // 2500ms info request timeout GameConnection* GameConnection::connection_instance = 0; GameConnection::GameConnection(std::string const &connectionstr) { connection_instance = this; connection_network = 0; connection_netframe = 0; unsigned int port = DEFAULTPORT; std::string host(connectionstr); size_t found = host.find(':'); if (found != std::string::npos) { std::istringstream str(host.substr(found + 1)); if (str >> port) { host.erase(found, std::string::npos); } else { con_print << "Invalid hostname '" << host << "'\n"; abort(); return; } } connection_network = new NetConnection(); connection_network->connect(host, port); if (!connection_network->connected()) { abort(); return; } // send connect request connection_network->send_connect(); connection_network->transmit(); if (!connection_network->connected()) { abort(); return; } game_players.push_back(localplayer()); set_playerlist_timestamp(timestamp()); // generate player GUID // we do it here because offline play doesn't require it if (!localplayer()->guid().size()) { // read keys.ini // write keys.ini std::string filename(filesystem::homedir()); filename.append("keys.ini"); std::ofstream ofs(filename.c_str()); if (!ofs.is_open()) { con_warn << "Could not write " << filename << std::endl; } else { ofs << "; keys.ini - osirion client identification" << std::endl; ofs << "; DO NOT EDIT OR DELETE THIS FILE" << std::endl; ofs << "; If you do you will not be able to use existing characters on a remote server" << std::endl; ofs.close(); } } set_interactive(true); set_running(true); } GameConnection::~GameConnection() { if (connection_network) { connection_network->disconnect(); delete connection_network; } connection_instance = 0; } Info *GameConnection::request_info(const unsigned int id) { if (!id) { con_warn << "Information requested for illegal id 0!" << std::endl; return 0; } // find the info record Info *info = Info::find(id); if (!info) { info = new Info(id); } if (info->type() || (timestamp() < info->timestamp() + INFOTIMEOUT) ) return info; // send an information request to the server if (connection_network) { connection_network->send_info_request(info); connection_network->transmit(); } else { info->add_text("^RNot connected."); info->set_timestamp(0); } return info; } Inventory *GameConnection::request_inventory(Entity *entity) { if (!entity) { con_warn << "Inventory request for NULL entity" << std::endl; return 0; } if (entity->inventory() && connection_network) { connection_network->send_inventory_request(entity); connection_network->transmit(); } return (entity->inventory()); } void GameConnection::forward(std::string const &cmdline) { if (!connection_network->connected()) return; connection_network->send_command(cmdline); } void GameConnection::rcon(std::string const &cmdline) { if (!connection_network->connected()) return; connection_network->send_rcon(cmdline); } void GameConnection::say(std::string const &args) { if (!connection_network->connected()) return; connection_network->send_say(args); } void GameConnection::shout(std::string const &args) { if (!connection_network->connected()) return; connection_network->send_shout(args); } void GameConnection::private_message(std::string const &args) { if (!connection_network->connected()) return; connection_network->send_private_message(args); } void GameConnection::frame(unsigned long timestamp) { if (!running()) return; if (!connection_network->connected()) { abort(); return; } //update_clientstate(); // get incoming messages connection_network->frame(); float f = 0; if (core::Cvar::net_framerate->value()) { f = 1000.0f / core::Cvar::net_framerate->value(); if (connection_netframe + f > timestamp) { return; } } connection_netframe = timestamp; if (connection_network->state() == NetConnection::Connected) { if (localcontrol() && localcontrol()->dirty()) { connection_network->send_client_update(localcontrol()); localcontrol()->set_dirty(false); } if (localplayer()->dirty()) { connection_network->send_playerinfo(); } } set_timestamp(connection_network->timestamp()); connection_network->transmit(); } }