From 89c0bc88bd4ebdc44dfb99235609c90e968af533 Mon Sep 17 00:00:00 2001 From: Stijn Buys Date: Sun, 15 Nov 2009 14:20:13 +0000 Subject: added core::Info id, changed network info message, updated entity network message to include the info id --- src/core/entity.cc | 69 ++++++++++++++++++++++++++++--------- src/core/entity.h | 14 ++++++++ src/core/gameconnection.cc | 21 ++++++++++++ src/core/gameconnection.h | 3 ++ src/core/gameinterface.cc | 43 +++++++++-------------- src/core/gameinterface.h | 3 ++ src/core/gameserver.cc | 5 +++ src/core/gameserver.h | 3 ++ src/core/info.cc | 85 +++++++++++++++++++++++++++++++++++++++------- src/core/info.h | 39 +++++++++++++++++---- src/core/netconnection.cc | 62 +++++++++++++++++++++++++++------ src/core/netserver.cc | 61 ++++++++++++++++++++++++--------- src/core/zone.cc | 9 ++--- src/dedicated/dedicated.cc | 4 +-- src/game/base/commodity.cc | 3 +- src/game/base/ship.cc | 1 + src/game/base/shipmodel.cc | 4 +-- src/game/intro/convoy.cc | 4 +-- 18 files changed, 328 insertions(+), 105 deletions(-) diff --git a/src/core/entity.cc b/src/core/entity.cc index 08fddbf..ece1e9b 100644 --- a/src/core/entity.cc +++ b/src/core/entity.cc @@ -13,6 +13,7 @@ #include "core/entity.h" #include "core/cvar.h" #include "core/application.h" +#include "core/gameinterface.h" namespace core { @@ -71,18 +72,42 @@ void Entity::erase(unsigned int id) } } +void Entity::clear() +{ + for (Entity::Registry::iterator it = Entity::registry().begin(); it != Entity::registry().end(); it++) { + delete(*it).second; + } + Entity::registry().clear(); + entity_nextid = 0; +} + +void Entity::list_header() +{ + con_print << " " + << " id " + << "type " + << "label " + << "name" << std::endl; +} + +void Entity::list(const Entity *entity) +{ + con_print << " " + << "^B" << std::setw(4) << entity->id() << " " + << "^B" << std::setfill('0') << std::setw(4) << entity->type() << ":" << std::setw(4) << entity->moduletype() << std::setfill(' ') << " " + << "^B" << aux::pad_right(entity->label(), 24) << " " + << "^N" << entity->name() << std::endl; +} + void Entity::list() { - Registry::iterator it; - for (it = entity_registry.begin(); it != entity_registry.end(); it++) { + list_header(); + for (Registry::iterator it = entity_registry.begin(); it != entity_registry.end(); it++) { std::string typeindicator; Entity *entity = (*it).second; - con_print << " id " << std::setw(4) << entity->id() - << " type " << std::setw(4) << entity->type() - << ":" << std::setw(4) << entity->moduletype() - << " " << entity->label() << std::endl; + list(entity); } - con_print << entity_registry.size() << " registered entities" << std::endl; + con_print << entity_registry.size() << " entities" << std::endl; } /* ---- class Entity ----------------------------------------------- */ @@ -241,9 +266,10 @@ void Entity::serialize_server_create(std::ostream & os) const << radius() << " " << std::setprecision(8) << entity_axis.forward() << " " << std::setprecision(8) << entity_axis.left() << " " - << label() << " " + << "\"" <name() : "") << "\" "; + << "\"" << (entity_model ? entity_model->name() : "") << "\" " + << (info() ? info()->id() : 0) << " "; } void Entity::receive_server_create(std::istream &is) @@ -252,6 +278,7 @@ void Entity::receive_server_create(std::istream &is) unsigned int zo; unsigned int o = 0; std::string n; + char c; is >> entity_moduletypeid; is >> entity_flags; @@ -284,24 +311,34 @@ void Entity::receive_server_create(std::istream &is) is >> entity_axis[1]; entity_axis[2] = math::crossproduct(entity_axis.forward(), entity_axis.left()); - char c; - is >> n; - set_label(n); + // read label n.clear(); - + while ((is.get(c)) && (c != '"')); + while ((is.get(c)) && (c != '"')) + n += c; + set_label(n); + // read name + n.clear(); while ((is.get(c)) && (c != '"')); while ((is.get(c)) && (c != '"')) n += c; set_name(n); - n.clear(); - + // read model name + n.clear(); while ((is.get(c)) && (c != '"')); while ((is.get(c)) && (c != '"')) n += c; - set_modelname(n); + + // read info id + is >> o; + if (o) + set_info(game()->info(o)); + else + set_info(0); + entity_dirty = false; } diff --git a/src/core/entity.h b/src/core/entity.h index 09839c8..ae2585d 100644 --- a/src/core/entity.h +++ b/src/core/entity.h @@ -165,6 +165,11 @@ public: inline Inventory *inventory() { return entity_inventory; } + + /// entity info + inline const Info *info() const { + return entity_info; + } /// entity menus inline Menus &menus() { @@ -333,9 +338,18 @@ public: /// erase an entity from the registry and delete it static void erase(unsigned int entity_id); + /// print the list header + static void list_header(); + + /// list the entity registry + static void list(const Entity *entity); + /// list the entity registry static void list(); + /// clear the entity registry + static void clear(); + /// the entity registry static inline Registry & registry() { return entity_registry; diff --git a/src/core/gameconnection.cc b/src/core/gameconnection.cc index 8910bca..f0dfbc6 100644 --- a/src/core/gameconnection.cc +++ b/src/core/gameconnection.cc @@ -90,6 +90,27 @@ bool GameConnection::interactive() const return true; } +Info *GameConnection::info(unsigned int id) +{ + // find the info record + Info *info = Info::find(id); + if (info) { + return info; + } + + info = new Info(id); + info->text().push_back("Requesting information..."); + + // send an information request to the server + if (connection_network) { + connection_network->send_info_request(info); + } else { + info->text().push_back("^RNot connected."); + } + return info; + +} + Info *GameConnection::info(const std::string &type, const std::string &label) { // find the info record type diff --git a/src/core/gameconnection.h b/src/core/gameconnection.h index 9c0b5a9..90b45a0 100644 --- a/src/core/gameconnection.h +++ b/src/core/gameconnection.h @@ -61,6 +61,9 @@ public: /// returns an info record virtual Info *info(const std::string &type, const std::string &label); + /// returns an info record + virtual Info *info(unsigned int id); + /*----- static ---------------------------------------------------- */ /// return the current game connection diff --git a/src/core/gameinterface.cc b/src/core/gameinterface.cc index b37f11a..5caa270 100644 --- a/src/core/gameinterface.cc +++ b/src/core/gameinterface.cc @@ -102,21 +102,26 @@ GameInterface::~GameInterface() // clear all game related objects void GameInterface::clear() { - //con_debug << "Clearing game data\n"; - // remove all entities - for (Entity::Registry::iterator it = Entity::registry().begin(); it != Entity::registry().end(); it++) { - delete(*it).second; - } - Entity::registry().clear(); + Entity::clear(); // remove all zones - for (Zone::Registry::iterator it = Zone::registry().begin(); it != Zone::registry().end(); it++) { - Zone *zone = (*it).second; - con_debug " removing zone " << zone->label() << std::endl; - delete zone; + Zone::clear(); + + // remove info records + Info::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; + } } - Zone::registry().clear(); + game_players.clear(); // remove all game functions for (Func::Registry::iterator it = Func::registry().begin(); it != Func::registry().end();) { @@ -137,22 +142,6 @@ void GameInterface::clear() ++it; } } - - // remove all models - model::Model::clear(); - - // remove infos - Info::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(); } diff --git a/src/core/gameinterface.h b/src/core/gameinterface.h index ef479b1..1460c45 100644 --- a/src/core/gameinterface.h +++ b/src/core/gameinterface.h @@ -65,6 +65,9 @@ public: /// returns an info record virtual Info *info(const std::string &type, const std::string &label) = 0; + /// returns an info record + virtual Info *info(unsigned int id) = 0; + /*----- mutators ------------------------------------------------- */ /// clear all game variables, game functions and entities diff --git a/src/core/gameserver.cc b/src/core/gameserver.cc index c0d7382..2e848e0 100644 --- a/src/core/gameserver.cc +++ b/src/core/gameserver.cc @@ -237,6 +237,11 @@ float GameServer::time() const return ((float)(server_timestamp) / 1000.0f); } +Info *GameServer::info(unsigned int id) +{ + return Info::find(id); +} + Info *GameServer::info(const std::string &type, const std::string &label) { // find the class diff --git a/src/core/gameserver.h b/src/core/gameserver.h index 2c82870..3f57a8b 100644 --- a/src/core/gameserver.h +++ b/src/core/gameserver.h @@ -91,6 +91,9 @@ public: /// returns an info record virtual Info *info(const std::string &type, const std::string &label); + /// returns an info record + virtual Info *info(unsigned int id); + /*----- static ---------------------------------------------------- */ /// return the current game server diff --git a/src/core/info.cc b/src/core/info.cc index ca23d79..dc7a8b3 100644 --- a/src/core/info.cc +++ b/src/core/info.cc @@ -56,19 +56,46 @@ InfoType *InfoType::find(const std::string & label) } /* ---- class Info ------------------------------------------------- */ +unsigned int info_id_counter = 0; -// server-side constructor, assigns id +// server-side constructor, assigns an id Info::Info(const InfoType *type) { + info_id_counter++; + info_id = info_id_counter; info_type = type; + info_registry.push_back(this); info_model = 0; info_timestamp = 0; info_price = 0; +} +// client-side constructor, does not assign an id +Info::Info(const InfoType *type, const std::string & label) +{ + info_id = 0; + info_type = type; info_registry.push_back(this); + + info_model = 0; + info_timestamp = 0; + info_price = 0; + + set_label(label); } +// client-side constructor, does not assign an id +Info::Info(const unsigned int id) +{ + info_id = id; + info_type = 0; + info_registry.push_back(this); + + info_model = 0; + info_timestamp = 0; + info_price = 0; +} Info::~Info() { @@ -80,6 +107,11 @@ Info::~Info() info_type = 0; } +void Info::set_id(const unsigned int id) +{ + info_id = id; +} + void Info::set_type(const InfoType *type) { info_type = type; @@ -179,13 +211,11 @@ void Info::receive_server_update(std::istream &is) void Info::print() const { - con_print << " type: ^B" << type()->label() << " ^Nlabel: ^B" << label() << " ^Nname: ^B" << name() << " ^Nmodel: ^B" << modelname() << "^N" << std::endl; + con_print << " id: ^B" << std::setw(4) << id() << " type: ^B" << (type() ? type()->label() : "NULL") << " ^Nlabel: ^B" << label() << " ^Nname: ^B" << name() << " ^Nmodel: ^B" << modelname() << "^N" << std::endl; if (info_text.size()) { for (Text::const_iterator it = info_text.begin(); it != info_text.end(); it++) { con_print << " " << (*it) << std::endl; } - } else { - con_print << " type: ^B" << type()->label() << " ^Nlabel: ^B" << label() << " ^Nname: ^B" << name() << " ^Nmodel: ^B" << modelname() << "^N" << std::endl; } } @@ -193,11 +223,25 @@ void Info::print() const Info::Registry Info::info_registry; +Info *Info::find(unsigned int id) +{ + if (!id) + return 0; + + for (Registry::iterator it = info_registry.begin(); it != info_registry.end(); it++) { + Info *info = (*it); + if (info->id() == id) { + return info; + } + } + return 0; +} + Info *Info::find(const char *label) { if (!label) return 0; - + for (Registry::iterator it = info_registry.begin(); it != info_registry.end(); it++) { Info *info = (*it); if (info->label().compare(label) == 0) { @@ -312,18 +356,34 @@ void Info::clear() delete info; } info_registry.clear(); + info_id_counter = 0; InfoType::clear(); } +void Info::list_header() +{ + con_print << " " + << " id " + << "type " + << "label " + << "name" << std::endl; +} +void Info::list(const Info *info) +{ + con_print << " " + << "^B" << std::setw(4) << info->id() << " " + << "^B" << (info->type() ? aux::pad_right(info->type()->label(), 8) : "NULL ") << " " + << "^B" << aux::pad_right(info->label(), 12) << " " + << "^N" << info->name() << std::endl; +} + void Info::list() { + list_header(); for (Registry::iterator it = info_registry.begin(); it != info_registry.end(); it++) { Info *info = (*it); - con_print << " " - << "^B" << aux::pad_right(info->type()->label(), 8) << "^N " - << "^B" << aux::pad_right(info->label(), 12) << "^N " - << info->name() << "^N" << std::endl; + list(info); } con_print << info_registry.size() << " info " << aux::plural("record", info_registry.size()) << std::endl; } @@ -331,13 +391,12 @@ void Info::list() void Info::list(const InfoType *type) { size_t count = 0; + list_header(); for (Registry::iterator it = info_registry.begin(); it != info_registry.end(); it++) { core::Info *info = (*it); if (info->type() == type) { - count++; - con_print << " " - << "^B" << aux::pad_right(info->label(), 12) << "^N " - << info->name() << "^N" << std::endl; + count++; + list(info); } } con_print << count << " " << type->label() << " info " << aux::plural("record", count) << std::endl; diff --git a/src/core/info.h b/src/core/info.h index 0296ec9..8b9a89b 100644 --- a/src/core/info.h +++ b/src/core/info.h @@ -61,16 +61,31 @@ public: typedef std::deque Text; /** - * @brief create a new information record - * The constructor automaticly adds the instance to the registry + * @brief create a new server-side information record + * This constructor assigns an id + */ + Info(const InfoType *type); + + /** + * @brief create a new client-side information record + * This constructor doesn not assign an id */ - Info(const InfoType *type = 0); + Info(const InfoType *type, const std::string & label); + + /** + * @brief create a new client-side information record + */ + Info(const unsigned int id); /// delete the information record virtual ~Info(); /* ---- inspectors ------------------------------------------------- */ + inline const unsigned int id() const { + return info_id; + } + inline const InfoType* type() const { return info_type; } @@ -98,6 +113,8 @@ public: /* ---- mutators --------------------------------------------------- */ + void set_id(const unsigned int); + void set_modelname(const std::string & modelname); void set_modelname(const char *modelname); @@ -124,11 +141,9 @@ public: /// clear the timestamp void clear_timestamp(); -protected: - - /// set the info class id + /// set the info class type void set_type(const InfoType *type); - + public: /* ---- serializers ------------------------------------------------ */ @@ -140,6 +155,7 @@ public: private: const InfoType* info_type; + unsigned int info_id; long info_price; unsigned long info_timestamp; @@ -160,6 +176,9 @@ public: return info_registry; } + /// search the info registry for a record with the specified id + static Info *find(const unsigned int id); + /// search the info registry for a labeled item static Info *find(const char * label); @@ -181,6 +200,12 @@ public: /// clear the info registry static void clear(); + /// print the list header + static void list_header(); + + /// list a single record + static void list(const Info *info); + /// list the info registry static void list(); diff --git a/src/core/netconnection.cc b/src/core/netconnection.cc index 2975bc5..1318467 100644 --- a/src/core/netconnection.cc +++ b/src/core/netconnection.cc @@ -416,7 +416,13 @@ void NetConnection::send_ping_reply(unsigned long timestamp) void NetConnection::send_info_request(Info *info) { std::ostringstream msg; - msg << "inf " << ' ' << info->type()->label() << ' ' << info->label() << '\n'; + if (info->id()) { + msg << "inf " << info->id() << " \"\" \"\"\n"; + } else { + if (!info->type()) + return; + msg << "inf " << info->id() << " \"" << info->type()->label() << "\" \"" << info->label() << "\"\n"; + } this->send_raw(msg.str()); info->set_timestamp(application()->timestamp()); @@ -690,30 +696,64 @@ void NetConnection::parse_incoming_message(const std::string & message) } } else if (command == "inf") { - // incoming info record + unsigned int id = 0; std::string typelabelstr; std::string infolabelstr; + std::string n; + char c; - if (!(msgstream >> typelabelstr)) { + // read id + if (!(msgstream >> id)) { con_warn << "Received invalid info record message!" << std::endl; return; } - InfoType *infotype = InfoType::find(typelabelstr); - if (!infotype) { - infotype = new InfoType(typelabelstr.c_str()); + + // read type label + n.clear(); + while ((msgstream.get(c)) && (c != '"')); + while ((msgstream.get(c)) && (c != '"')) + n +=c; + + typelabelstr.assign(n); + if (!typelabelstr.size()) { + con_warn << "Received invalid info record message!" << std::endl; + return; } - if (!(msgstream >> infolabelstr)) { + // read info label + n.clear(); + while ((msgstream.get(c)) && (c != '"')); + while ((msgstream.get(c)) && (c != '"')) + n +=c; + + infolabelstr.assign(n); + if (!infolabelstr.size()) { con_warn << "Received invalid info record message for type '" << typelabelstr << "'!" << std::endl; return; } - Info *info = Info::find(infotype, infolabelstr); + + // find the InfoType instance + InfoType *infotype = InfoType::find(typelabelstr); + if (!infotype) { + infotype = new InfoType(typelabelstr.c_str()); + } + + // find the Info instance + Info *info = Info::find(id); if (!info) { - info = new Info(infotype); - info->set_label(infolabelstr); + info = Info::find(infotype, infolabelstr); } - + + // create one if necessary + if (!info) { + info = new Info(id); + } + + info->set_type(infotype); + info->set_label(infolabelstr); + info->set_id(id); + info->receive_server_update(msgstream); info->clear_timestamp(); diff --git a/src/core/netserver.cc b/src/core/netserver.cc index 32b2d69..65388e8 100644 --- a/src/core/netserver.cc +++ b/src/core/netserver.cc @@ -562,10 +562,10 @@ void NetServer::send_player_disconnect_info(NetClient *client, Player *player) void NetServer::send_info_update(NetClient *client, Info *info) { if (!info || !info->type()) - return; + return; std::ostringstream msg; - msg << "inf " << info->type()->label() << ' ' << info->label() << ' '; + msg << "inf " << info->id() << " \"" << info->type()->label() << "\" \"" << info->label() << "\" "; info->serialize_server_update(msg); msg << '\n'; client->send_raw(msg.str()); @@ -675,24 +675,53 @@ void NetServer::parse_incoming_message(NetClient *client, const std::string & me } if (command == "inf") { - std::string typelabelstr; - std::string infolabelstr; + unsigned int id; - if (!(msgstream >> typelabelstr)) { - con_warn << "^B" << client->player()->name() << "^W invalid info record request" << std::endl; - return; - } - - InfoType *infotype = InfoType::find(typelabelstr); - if (!infotype) - return; - - if (!(msgstream >> infolabelstr)) { - con_warn << "^B" << client->player()->name() << "^W invalid info record request" << std::endl; + if (!(msgstream >> id)) { + con_warn << "^B" << client->player()->name() << "^W invalid info request" << std::endl; return; } - Info *info = Info::find(infotype, infolabelstr); + Info *info = 0; + if (id == 0) { + // the client is requesting an information record by type and label + std::string typelabelstr; + std::string infolabelstr; + std::string n; + char c; + + // read type label + n.clear(); + while ((msgstream.get(c)) && (c != '"')); + while ((msgstream.get(c)) && (c != '"')) + n +=c; + typelabelstr.assign(n); + if (!typelabelstr.size()) { + con_warn << "^B" << client->player()->name() << "^W invalid info request" << std::endl; + return; + } + + InfoType *infotype = InfoType::find(typelabelstr); + if (!infotype) + return; + + // read info label + n.clear(); + while ((msgstream.get(c)) && (c != '"')); + while ((msgstream.get(c)) && (c != '"')) + n +=c; + infolabelstr.assign(n); + if (!infolabelstr.size()) { + con_warn << "^B" << client->player()->name() << "^W invalid info request" << std::endl; + return; + } + + info = Info::find(infotype, infolabelstr); + } else { + // the client is requesting an information record by id + info = Info::find(id); + } + if (info) { send_info_update(client, info); client->transmit(); diff --git a/src/core/zone.cc b/src/core/zone.cc index 49b20d5..ab38b1b 100644 --- a/src/core/zone.cc +++ b/src/core/zone.cc @@ -135,14 +135,11 @@ Zone::~Zone() void Zone::print() { - con_print << "id: ^B" << id() << " ^Nlabel: ^B" << label() << " ^Nname: ^B" << name() << std::endl; + con_print << "id ^B" << id() << " ^Nlabel ^B" << label() << " ^Nname ^B" << name() << std::endl; + Entity::list_header(); for (Content::iterator it = zone_content.begin(); it != zone_content.end(); it++) { Entity *entity = (*it); - con_print << " id " << std::setw(4) << entity->id() - << " type " << std::setw(4) << entity->type() - << ":" << std::setw(4) << entity->moduletype() - << " " << std::setw(24) << entity->label() - << " ^B" << entity->name() << "^N" << std::endl; + Entity::list(entity); } con_print << zone_content.size() << " registered zone entities" << std::endl; } diff --git a/src/dedicated/dedicated.cc b/src/dedicated/dedicated.cc index 6812d63..be52875 100644 --- a/src/dedicated/dedicated.cc +++ b/src/dedicated/dedicated.cc @@ -35,14 +35,14 @@ void run(int count, char **arguments) void Dedicated::init(int count, char **arguments) { + Console::init(); + con_print << "^BInitializing dedicated server..." << std::endl; core::Cvar::set("sv_dedicated", "1", core::Cvar::ReadOnly); core::Application::init(count, arguments); - Console::init(); - // the command line is in the buffer, execute it core::CommandBuffer::exec(); diff --git a/src/game/base/commodity.cc b/src/game/base/commodity.cc index d41d370..4f238be 100644 --- a/src/game/base/commodity.cc +++ b/src/game/base/commodity.cc @@ -16,9 +16,8 @@ namespace game core::InfoType *Commodity::commodity_infotype = 0; -Commodity::Commodity() : core::Info() +Commodity::Commodity() : core::Info(commodity_infotype) { - set_type(commodity_infotype); } Commodity::~Commodity() diff --git a/src/game/base/ship.cc b/src/game/base/ship.cc index 7cdf2ca..f2bd703 100644 --- a/src/game/base/ship.cc +++ b/src/game/base/ship.cc @@ -30,6 +30,7 @@ Ship::Ship(core::Player *owner, ShipModel *shipmodel) : { set_modelname(shipmodel->modelname()); set_name(shipmodel->name()); + set_info(shipmodel); std::string str(aux::text_strip(owner->name())); aux::to_label(str); diff --git a/src/game/base/shipmodel.cc b/src/game/base/shipmodel.cc index 4f219eb..dacc5a6 100644 --- a/src/game/base/shipmodel.cc +++ b/src/game/base/shipmodel.cc @@ -16,10 +16,8 @@ namespace game core::InfoType *ShipModel::shipmodel_infotype = 0; -ShipModel::ShipModel() +ShipModel::ShipModel() : core::Info(shipmodel_infotype) { - set_type(shipmodel_infotype); - //default specifications shipmodel_acceleration = 1.0f; // thruster acceleration in game untits/second^2 shipmodel_maxspeed = 3.0f; // maximum thruster speed in game units/second diff --git a/src/game/intro/convoy.cc b/src/game/intro/convoy.cc index 4a21071..413e377 100644 --- a/src/game/intro/convoy.cc +++ b/src/game/intro/convoy.cc @@ -14,8 +14,8 @@ namespace intro Member::Member(std::string const &model) : core::EntityControlable(0, 1) { - set_name("Convoy member"); - set_label(model); + set_name("Convoy ship"); + set_label("ship"); set_modelname(model); -- cgit v1.2.3