Project::OSiRiON - Git repositories
Project::OSiRiON
News . About . Screenshots . Downloads . Forum . Wiki . Tracker . Git
summaryrefslogtreecommitdiff
path: root/src/core
diff options
context:
space:
mode:
authorStijn Buys <ingar@osirion.org>2012-10-20 16:35:26 +0000
committerStijn Buys <ingar@osirion.org>2012-10-20 16:35:26 +0000
commit75274ebd6ba90784f5aa837b7e5ea97fc6bfb720 (patch)
treea5d51a87bf3f20833df18bc40a3254b946716afb /src/core
parentf01629dc14b1ee05b44d2e38b3dffbc1441fd85f (diff)
Item id based inventory, support for weapon dealers.
Diffstat (limited to 'src/core')
-rw-r--r--src/core/commandbuffer.cc9
-rw-r--r--src/core/entity.cc4
-rw-r--r--src/core/gameserver.cc4
-rw-r--r--src/core/info.cc4
-rw-r--r--src/core/inventory.cc48
-rw-r--r--src/core/inventory.h29
-rw-r--r--src/core/item.cc22
-rw-r--r--src/core/item.h41
-rw-r--r--src/core/netconnection.cc68
-rw-r--r--src/core/netserver.cc19
10 files changed, 197 insertions, 51 deletions
diff --git a/src/core/commandbuffer.cc b/src/core/commandbuffer.cc
index d46cc38..78b76af 100644
--- a/src/core/commandbuffer.cc
+++ b/src/core/commandbuffer.cc
@@ -49,10 +49,13 @@ void func_list_info(std::string const &args)
std::istringstream argstream(args);
if (!(argstream >> typestr)) {
- // no argument, list all info records
- Info::list();
+ // no arguments, list info types
+ InfoType::list();
+ con_print << " list_info [type] list all info records for a specified type" << std::endl;
return;
}
+
+ aux::to_label(typestr);
Info *info = 0;
InfoType *infotype = InfoType::find(typestr);
@@ -87,6 +90,8 @@ void func_list_info(std::string const &args)
return;
}
+ aux::to_label(labelstr);
+
// two arguments
info = Info::find(infotype, labelstr);
if (info) {
diff --git a/src/core/entity.cc b/src/core/entity.cc
index 825f9bf..78878f9 100644
--- a/src/core/entity.cc
+++ b/src/core/entity.cc
@@ -94,11 +94,11 @@ void Entity::list_inventory() const
return;
}
- con_print << " ^Nid type label amount" << std::endl;
+ con_print << " ^Nitem info infotype amount" << std::endl;
for (Inventory::Items::const_iterator it = entity_inventory->items().begin(); it != entity_inventory->items().end(); it++) {
Item *item = (*it);
con_print << " "
- << " ^B" << std::setw(4) << item->info()->id()
+ << " ^B" << std::setw(4) << item->id()
<< " ^N" << aux::pad_right((item->info()->type() ? item->info()->type()->label() : "NULL"), 8)
<< " ^N" << aux::pad_right(item->info()->label(), 24)
<< std::setw(5) << item->amount() << std::endl;
diff --git a/src/core/gameserver.cc b/src/core/gameserver.cc
index 579f65d..796b99f 100644
--- a/src/core/gameserver.cc
+++ b/src/core/gameserver.cc
@@ -717,11 +717,11 @@ void GameServer::frame(const unsigned long timestamp)
// send network updates
server_network->frame(this->timestamp());
}
-
+
// remove deleted entities and mark remaining entities as updated
for (Entity::Registry::iterator it = Entity::registry().begin(); it != Entity::registry().end();) {
// remove deleted entities
- if ((*it).second->entity_destroyed) {
+ if ((*it).second->destroyed()) {
delete (*it).second;
(*it).second = 0;
Entity::registry().erase(it++);
diff --git a/src/core/info.cc b/src/core/info.cc
index 8e286dc..dbe4c76 100644
--- a/src/core/info.cc
+++ b/src/core/info.cc
@@ -91,9 +91,9 @@ Info::Info(const unsigned int id)
info_type = 0;
info_registry.push_back(this);
- info_price = 0;
-
info_timestamp = 1;
+ info_price = 0;
+ info_volume = 0;
add_text("Requesting server information...");
}
diff --git a/src/core/inventory.cc b/src/core/inventory.cc
index 28327a3..c10e1c6 100644
--- a/src/core/inventory.cc
+++ b/src/core/inventory.cc
@@ -16,6 +16,7 @@ namespace core
Inventory::Inventory(const float capacity)
{
inventory_timestamp = 0;
+ inventory_timestamp_erase = 0;
inventory_capacity = capacity;
inventory_capacity_used = 0;
inventory_dirty = false;
@@ -25,6 +26,7 @@ Inventory::~Inventory()
{
clear();
inventory_timestamp = 0;
+ inventory_timestamp_erase = 0;
inventory_capacity = 0;
inventory_capacity_used = 0;
}
@@ -48,24 +50,45 @@ void Inventory::set_dirty(const bool dirty)
void Inventory::add(Item *item)
{
+ assert(item != (Item *) 0x81);
+
+ // assign an id
+ unsigned int id = 0;
for (Items::iterator it = inventory_items.begin(); it != inventory_items.end(); it++) {
- // check if the item was already added
- if ((*it) == item)
- return;
+ if ((*it)->id() > id) {
+ id = (*it)->id();
+ }
}
+ id++;
+ item->set_id(id);
+
inventory_items.push_back(item);
}
-void Inventory::remove(Item *item)
+void Inventory::erase(Item *item)
{
for (Items::iterator it = inventory_items.begin(); it != inventory_items.end(); it++) {
if ((*it) == item) {
+ delete (*it);
+ (*it) = 0;
+ inventory_items.erase(it);
+ inventory_timestamp_erase = (game() ? game()->timestamp() : 1);
+ return;
+ }
+ }
+}
+
+void Inventory::erase(const unsigned int id)
+{
+ for (Items::iterator it = inventory_items.begin(); it != inventory_items.end(); it++) {
+ if ((*it)->id() == id) {
+ delete (*it);
+ (*it) = 0;
inventory_items.erase(it);
- delete item;
+ inventory_timestamp_erase = (game() ? game()->timestamp() : 1);
return;
}
}
- // FIXME remove doesn't work over network
}
Item *Inventory::find(const Info *info) const
@@ -81,6 +104,19 @@ Item *Inventory::find(const Info *info) const
return 0;
}
+Item *Inventory::find(const unsigned int id) const
+{
+ // sarch the inventory for a specified item id
+ for (Items::const_iterator it = inventory_items.begin(); it != inventory_items.end(); it++) {
+ Item *item = (*it);
+ if (item->id() == id) {
+ return item;
+ }
+ }
+ // not found
+ return 0;
+}
+
void Inventory::clear()
{
for (Items::iterator it = inventory_items.begin(); it != inventory_items.end(); it++) {
diff --git a/src/core/inventory.h b/src/core/inventory.h
index 80dbde1..3c3adfa 100644
--- a/src/core/inventory.h
+++ b/src/core/inventory.h
@@ -23,7 +23,7 @@ public:
/**
* @brief type definition for items in the inventory
*/
- typedef std::vector<Item *> Items;
+ typedef std::list<Item *> Items;
/**
* @brief default constructor
@@ -45,14 +45,21 @@ public:
};
/**
- * @brief return the timestamp of the last server update
- * This is a client-side property and shoul not be used server-side
+ * @brief return the timestamp of the last client-side update
+ * This is a client-side property
*/
inline const unsigned long timestamp() const {
return inventory_timestamp;
}
/**
+ * @brief return the timestamp of the last item erase
+ * */
+ inline const unsigned long timestamp_erase() const {
+ return inventory_timestamp_erase;
+ }
+
+ /**
* @brief return the maximal inventory capacity, in cubic meters
*/
inline const float capacity() const {
@@ -89,6 +96,11 @@ public:
* @brief search the inventory for a specific item type
*/
Item *find(const Info *info) const;
+
+ /**
+ * @brief search the inventory for a specific item id
+ */
+ Item *find(const unsigned int id) const;
/* ---- mutators --------------------------------------------------- */
@@ -98,9 +110,12 @@ public:
void add(Item *item);
/**
- * @brief remove an item from the inventory and delete it
+ * @brief erase an item from the inventory
+ * This will call the Item's destructor
*/
- void remove(Item *item);
+ void erase(Item *item);
+
+ void erase(const unsigned int id);
/**
* @brief removes all items from the inventory and delete them
@@ -135,8 +150,10 @@ private:
// items in the inventory
Items inventory_items;
- // timestamp when inventory was last updated
+ // timestamp, last time the inventory was updated
unsigned long inventory_timestamp;
+ // timestamp, last time there was an item deleted from the inventory
+ unsigned long inventory_timestamp_erase;
// maximum inventory capacity, in cubic meters
float inventory_capacity;
diff --git a/src/core/item.cc b/src/core/item.cc
index f6e0382..b6e5bd8 100644
--- a/src/core/item.cc
+++ b/src/core/item.cc
@@ -24,27 +24,29 @@ Item::Item(const Info *info)
item_info = info;
item_amount = 0;
item_flags = 0;
+ item_id = 0;
item_price = info->price();
set_timestamp(game() ? game()->timestamp() : 1);
}
-Item::Item(const Item &other)
-{
- item_info = other.info();
- item_amount = other.amount();
- item_flags = other.flags();
- item_price = other.price();
- item_dirty = other.dirty();
- set_timestamp(game() ? game()->timestamp() : 1);
-}
-
Item::~Item()
{
item_info = 0;
item_amount = 0;
item_flags = 0;
item_price = 0;
+ item_id = 0;
+}
+
+void Item::set_info(const Info *info)
+{
+ item_info = info;
+}
+
+void Item::set_id(const unsigned int id)
+{
+ item_id = id;
}
void Item::set_amount(const long amount)
diff --git a/src/core/item.h b/src/core/item.h
index 6c99270..ec0d6be 100644
--- a/src/core/item.h
+++ b/src/core/item.h
@@ -23,14 +23,16 @@ public:
Item(const Info *info);
- /// copy constructor
- Item(const Item &other);
-
~Item();
/* ---- inspectors --------------------------------------------- */
/**
+ * @brief returns the item id
+ * */
+ inline unsigned int id() const { return item_id; }
+
+ /**
* @brief associated amount
*/
inline long amount() const { return item_amount; }
@@ -69,6 +71,13 @@ public:
}
/**
+ * @brief returns true if the Unique flag is set
+ */
+ inline const bool unique() const {
+ return ((item_flags & (unsigned int) Unique) == (unsigned int) Unique);
+ }
+
+ /**
* @brief return true if the dirty flag is set
* */
inline const bool dirty() const {
@@ -76,6 +85,21 @@ public:
}
/* ---- mutators ----------------------------------------------- */
+
+ /**
+ * @brief set item id
+ * This should never be called from within the game module,
+ * it is used by Inventory to keep track of unique items
+ */
+ void set_id(const unsigned int id);
+
+ /**
+ * @brief set item info
+ * This should never be called from within the game module,
+ * it essentially changes the item type and is used by NetConnection
+ * for inventory householding.
+ */
+ void set_info(const Info *info);
/**
* @brief set associated amount
@@ -98,6 +122,13 @@ public:
void set_price(const long price);
/**
+ * @brief set all item flags
+ */
+ inline void set_flags(const unsigned int flags) {
+ item_flags = flags;
+ }
+
+ /**
* @brief set item flag
*/
inline void set_flag(Flags flag) {
@@ -115,7 +146,7 @@ public:
* @brief set the dirty flag
* */
inline void set_dirty(const bool dirty = true) {
- item_dirty = true;
+ item_dirty = dirty;
}
/* ---- serializers -------------------------------------------- */
@@ -136,6 +167,8 @@ private:
unsigned int item_flags;
bool item_dirty;
+
+ unsigned int item_id;
};
} // namespace core
diff --git a/src/core/netconnection.cc b/src/core/netconnection.cc
index 3c68be9..24f6a3d 100644
--- a/src/core/netconnection.cc
+++ b/src/core/netconnection.cc
@@ -754,7 +754,7 @@ void NetConnection::parse_incoming_message(const std::string & message)
oldzone->content().clear();
}
- // short "pif" message about a different player
+ // short "pif" message about a different player
} else if (player_id != localplayer()->id()) {
// find player
@@ -895,49 +895,91 @@ void NetConnection::parse_incoming_message(const std::string & message)
} else if (command.compare("inv") == 0) {
// received inventory update
- unsigned int id = 0;
+ unsigned int entity_id = 0;
unsigned long server_timestamp;
- // read id
- if (!(msgstream >> id >> server_timestamp)) {
+ // read entity id and server timestamp
+ if (!(msgstream >> entity_id >> server_timestamp)) {
con_warn << "Received invalid inventory update message!" << std::endl;
return;
}
- Entity *entity = Entity::find(id);
+ Entity *entity = Entity::find(entity_id);
if (!entity) {
- con_warn << "Received inventory update for non-existing entity " << id << "!" << std::endl;
+ con_warn << "Received inventory update for non-existing entity " << entity_id << "!" << std::endl;
return;
}
if (!entity->inventory()) {
- con_warn << "Received inventory update for entity " << id << " without inventory!" << std::endl;
+ con_warn << "Received inventory update for entity " << entity_id << " without inventory!" << std::endl;
return;
}
- //con_debug << "CLIENT received inv message for entity " << id << " client timestamp " << entity->inventory()->timestamp() << " server timestamp " << server_timestamp << std::endl;
-
if (server_timestamp < entity->inventory()->timestamp())
return;
+ unsigned int item_id = 0;
+ unsigned int info_id = 0;
+
+ int full_update = 0;
+ if (!(msgstream >> full_update)) {
+ con_warn << "Received inventory update for entity " << entity_id << " without full update marker!" << std::endl;
+ return;
+ }
+
+ if (full_update == 1) {
+ // mark all items dirty
+ for (Inventory::Items::iterator it = entity->inventory()->items().begin(); it != entity->inventory()->items().end(); ++it) {
+ (*it)->set_dirty();
+ }
+ }
+
size_t nbitems = 0;
if (!(msgstream >> nbitems))
nbitems = 0;
//con_debug << "CLIENT number of items: " << nbitems << std::endl;
+ // receive item updates
for (size_t i = 0; i < nbitems; i++) {
- if (!(msgstream >> id)) {
- con_warn << "Received inventory update without info id for existing entity " << id << "!" << std::endl;
+ // read item id
+ if (!(msgstream >> item_id)) {
+ con_warn << "Received inventory item update for entity " << entity_id << " without item id!" << std::endl;
+ return;
+ }
+ // read info id
+ if (!(msgstream >> info_id)) {
+ con_warn << "Received inventory item update for entity " << entity_id << " without info id!" << std::endl;
return;
}
- Info *info = core::game()->request_info(id);
- Item *item = entity->inventory()->find(info);
+ Info *info = core::game()->request_info(info_id);
+ Item *item = entity->inventory()->find(item_id);
if (!item) {
item = new Item(info);
entity->inventory()->add(item);
+ item->set_id(item_id);
+ } else {
+ if (item->info() != info) {
+ item->set_info(info);
+ }
}
item->receive_server_update(msgstream);
+ item->set_dirty(false);
}
+
+ if (full_update == 1) {
+ // remove items for which no update was received
+ for (Inventory::Items::iterator it = entity->inventory()->items().begin(); it != entity->inventory()->items().end();) {
+ Item *item = (*it);
+ if (item->dirty()) {
+ delete (item);
+ (*it) = 0;
+ entity->inventory()->items().erase(it++);
+ } else {
+ ++it;
+ }
+ }
+ }
+
entity->inventory()->recalculate();
entity->inventory()->set_timestamp(server_timestamp);
diff --git a/src/core/netserver.cc b/src/core/netserver.cc
index 81bd303..9fb5f78 100644
--- a/src/core/netserver.cc
+++ b/src/core/netserver.cc
@@ -667,16 +667,27 @@ void NetServer::send_inventory_update(NetClient *client, Entity *entity, const u
if (!entity || !entity->inventory())
return;
+ // send message header
std::ostringstream msg;
msg << "inv " << entity->id() << " " << game()->timestamp() << " ";
- size_t nbitems = 0;
+ // send full update marker
+ bool send_full_update = false;
+ if (entity->inventory()->timestamp_erase() >= timestamp) {
+ send_full_update = true;
+ msg << "1 ";
+ } else {
+ send_full_update = false;
+ msg << "0 ";
+ }
+ // send items
+ size_t nbitems = 0;
std::ostringstream itemstr;
for (Inventory::Items::const_iterator it = entity->inventory()->items().begin(); it != entity->inventory()->items().end(); it++) {
const Item *item = (*it);
- if (item->timestamp() >= timestamp) {
- itemstr << item->info()->id() << " ";
+ if (send_full_update || (item->timestamp() >= timestamp)) {
+ itemstr << item->id() << " " << item->info()->id() << " ";
item->serialize_server_update(itemstr);
nbitems++;
}
@@ -733,7 +744,7 @@ void NetServer::parse_incoming_message(NetClient *client, const std::string & me
unsigned int protover;
if (msgstream >> protover) {
if (protover != PROTOCOLVERSION) {
- // set protocol version mismatch notification
+ // send protocol version mismatch notification
std::stringstream netmsgstream("");
netmsgstream << "^WProtocol version mismatch: ";
netmsgstream << "client " << protover << " server " << PROTOCOLVERSION << "!\n";