From fd7a0735c9aeaa7978190049319e3cdfe48920a4 Mon Sep 17 00:00:00 2001 From: Perttu Ahola Date: Sun, 10 Apr 2011 04:15:10 +0300 Subject: [PATCH] new object system --- src/client.cpp | 29 +++++- src/client.h | 1 + src/clientobject.cpp | 22 +++-- src/clientobject.h | 12 ++- src/clientserver.h | 9 ++ src/environment.cpp | 208 +++++++++++++++++++++++++++++++++++++++---- src/main.cpp | 26 +----- src/map.cpp | 16 ++++ src/mapblock.h | 2 + src/nodemetadata.h | 2 +- src/serialization.h | 3 +- src/server.cpp | 190 +++++++++++++++++++++++---------------- src/serverobject.cpp | 91 +++++++++++++++++++ src/serverobject.h | 70 +++++++++------ src/utility.h | 14 +-- 15 files changed, 535 insertions(+), 160 deletions(-) diff --git a/src/client.cpp b/src/client.cpp index 1f2f7e1e8..fca7b1b02 100644 --- a/src/client.cpp +++ b/src/client.cpp @@ -1193,7 +1193,7 @@ void Client::ProcessData(u8 *data, u32 datasize, u16 sender_peer_id) } else if(command == TOCLIENT_ACTIVE_OBJECT_REMOVE_ADD) { - if(g_settings.getBool("enable_experimental")) + //if(g_settings.getBool("enable_experimental")) { /* u16 command @@ -1252,7 +1252,7 @@ void Client::ProcessData(u8 *data, u32 datasize, u16 sender_peer_id) } else if(command == TOCLIENT_ACTIVE_OBJECT_MESSAGES) { - if(g_settings.getBool("enable_experimental")) + //if(g_settings.getBool("enable_experimental")) { /* u16 command @@ -1594,6 +1594,31 @@ void Client::clickObject(u8 button, v3s16 blockpos, s16 id, u16 item) Send(0, data, true); } +void Client::clickActiveObject(u8 button, u16 id, u16 item) +{ + if(connectedAndInitialized() == false){ + dout_client< data(datasize); + writeU16(&data[0], TOSERVER_CLICK_ACTIVEOBJECT); + writeU8(&data[2], button); + writeU16(&data[3], id); + writeU16(&data[5], item); + Send(0, data, true); +} + void Client::sendSignText(v3s16 blockpos, s16 id, std::string text) { /* diff --git a/src/client.h b/src/client.h index 0616cc914..ef3dd435a 100644 --- a/src/client.h +++ b/src/client.h @@ -275,6 +275,7 @@ public: void groundAction(u8 action, v3s16 nodepos_undersurface, v3s16 nodepos_oversurface, u16 item); void clickObject(u8 button, v3s16 blockpos, s16 id, u16 item); + void clickActiveObject(u8 button, u16 id, u16 item); void sendSignText(v3s16 blockpos, s16 id, std::string text); void sendSignNodeText(v3s16 p, std::string text); diff --git a/src/clientobject.cpp b/src/clientobject.cpp index d95862d1d..a6aa033ef 100644 --- a/src/clientobject.cpp +++ b/src/clientobject.cpp @@ -22,6 +22,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "porting.h" #include "constants.h" #include "utility.h" +#include "environment.h" core::map ClientActiveObject::m_types; @@ -148,7 +149,7 @@ void TestCAO::updateNodePos() //m_node->setRotation(v3f(0, 45, 0)); } -void TestCAO::step(float dtime) +void TestCAO::step(float dtime, ClientEnvironment *env) { if(m_node) { @@ -187,7 +188,7 @@ ItemCAO proto_ItemCAO; ItemCAO::ItemCAO(): ClientActiveObject(0), - m_selection_box(-BS*0.4,0.0,-BS*0.4, BS*0.4,BS*0.8,BS*0.4), + m_selection_box(-BS/3.,0.0,-BS/3., BS/3.,BS*2./3.,BS/3.), m_node(NULL), m_position(v3f(0,10*BS,0)) { @@ -219,10 +220,10 @@ void ItemCAO::addToScene(scene::ISceneManager *smgr) video::S3DVertex(BS/2,-BS/4,0, 0,0,0, c, 1,1), video::S3DVertex(BS/2,BS/4,0, 0,0,0, c, 1,0), video::S3DVertex(-BS/2,BS/4,0, 0,0,0, c, 0,0),*/ - video::S3DVertex(BS/3,0,0, 0,0,0, c, 0,1), - video::S3DVertex(-BS/3,0,0, 0,0,0, c, 1,1), - video::S3DVertex(-BS/3,0+BS*2/3,0, 0,0,0, c, 1,0), - video::S3DVertex(BS/3,0+BS*2/3,0, 0,0,0, c, 0,0), + video::S3DVertex(BS/3.,0,0, 0,0,0, c, 0,1), + video::S3DVertex(-BS/3.,0,0, 0,0,0, c, 1,1), + video::S3DVertex(-BS/3.,0+BS*2./3.,0, 0,0,0, c, 1,0), + video::S3DVertex(BS/3.,0+BS*2./3.,0, 0,0,0, c, 0,0), }; u16 indices[] = {0,1,2,2,3,0}; buf->append(vertices, 4, indices, 6); @@ -272,12 +273,17 @@ void ItemCAO::updateNodePos() m_node->setPosition(m_position); } -void ItemCAO::step(float dtime) +void ItemCAO::step(float dtime, ClientEnvironment *env) { if(m_node) { - v3f rot = m_node->getRotation(); + /*v3f rot = m_node->getRotation(); rot.Y += dtime * 120; + m_node->setRotation(rot);*/ + LocalPlayer *player = env->getLocalPlayer(); + assert(player); + v3f rot = m_node->getRotation(); + rot.Y = 180.0 - (player->getYaw()); m_node->setRotation(rot); } } diff --git a/src/clientobject.h b/src/clientobject.h index ebdcb948e..50fae67c2 100644 --- a/src/clientobject.h +++ b/src/clientobject.h @@ -35,6 +35,8 @@ Some planning */ +class ClientEnvironment; + class ClientActiveObject : public ActiveObject { public: @@ -51,11 +53,13 @@ public: virtual v3f getPosition(){return v3f(0,0,0);} // Step object in time - virtual void step(float dtime){} + virtual void step(float dtime, ClientEnvironment *env){} // Process a message sent by the server side object virtual void processMessage(const std::string &data){} + virtual std::string infoText() {return "";} + /* This takes the return value of ServerActiveObject::getClientInitializationData @@ -66,9 +70,11 @@ public: static ClientActiveObject* create(u8 type); protected: + // Used for creating objects based on type typedef ClientActiveObject* (*Factory)(); static void registerType(u16 type, Factory f); private: + // Used for creating objects based on type static core::map m_types; }; @@ -112,7 +118,7 @@ public: v3s16 getLightPosition(); void updateNodePos(); - void step(float dtime); + void step(float dtime, ClientEnvironment *env); void processMessage(const std::string &data); @@ -144,7 +150,7 @@ public: v3s16 getLightPosition(); void updateNodePos(); - void step(float dtime); + void step(float dtime, ClientEnvironment *env); void processMessage(const std::string &data); diff --git a/src/clientserver.h b/src/clientserver.h index 7baa79fa6..fadafed5f 100644 --- a/src/clientserver.h +++ b/src/clientserver.h @@ -249,6 +249,15 @@ enum ToServerCommand textdata */ + TOSERVER_CLICK_ACTIVEOBJECT = 0x34, + /* + length: 7 + [0] u16 command + [2] u8 button (0=left, 1=right) + [3] u16 id + [5] u16 item + */ + }; inline SharedBuffer makePacket_TOCLIENT_TIME_OF_DAY(u16 time) diff --git a/src/environment.cpp b/src/environment.cpp index f4afb28bf..7e1d268df 100644 --- a/src/environment.cpp +++ b/src/environment.cpp @@ -189,7 +189,7 @@ u32 Environment::getDayNightRatio() ServerEnvironment::ServerEnvironment(ServerMap *map, Server *server): m_map(map), m_server(server), - m_random_spawn_timer(0) + m_random_spawn_timer(3) { } @@ -422,7 +422,7 @@ void ServerEnvironment::step(float dtime) } } - if(g_settings.getBool("enable_experimental")) + //if(g_settings.getBool("enable_experimental")) { /* @@ -438,7 +438,7 @@ void ServerEnvironment::step(float dtime) } /* - Remove (m_removed && m_known_by_count==0) objects + Remove objects that satisfy (m_removed && m_known_by_count==0) */ { core::list objects_to_remove; @@ -457,16 +457,173 @@ void ServerEnvironment::step(float dtime) objects_to_remove.push_back(id); continue; } - else + // If not m_removed, don't remove. + if(obj->m_removed == false) + continue; + // Delete + delete obj; + // Id to be removed from m_active_objects + objects_to_remove.push_back(id); + } + // Remove references from m_active_objects + for(core::list::Iterator i = objects_to_remove.begin(); + i != objects_to_remove.end(); i++) + { + m_active_objects.remove(*i); + } + } + + + const s16 to_active_max_blocks = 3; + const f32 to_static_max_f = (to_active_max_blocks+1)*MAP_BLOCKSIZE*BS; + + /* + Convert stored objects from blocks near the players to active. + */ + for(core::list::Iterator i = m_players.begin(); + i != m_players.end(); i++) + { + Player *player = *i; + v3f playerpos = player->getPosition(); + + v3s16 blockpos0 = getNodeBlockPos(floatToInt(playerpos, BS)); + v3s16 bpmin = blockpos0 - v3s16(1,1,1)*to_active_max_blocks; + v3s16 bpmax = blockpos0 + v3s16(1,1,1)*to_active_max_blocks; + // Loop through all nearby blocks + for(s16 x=bpmin.X; x<=bpmax.X; x++) + for(s16 y=bpmin.Y; y<=bpmax.Y; y++) + for(s16 z=bpmin.Z; z<=bpmax.Z; z++) + { + v3s16 blockpos(x,y,z); + MapBlock *block = m_map->getBlockNoCreateNoEx(blockpos); + if(block==NULL) + continue; + // Ignore if no stored objects (to not set changed flag) + if(block->m_static_objects.m_stored.size() == 0) + continue; + // This will contain the leftovers of the stored list + core::list new_stored; + // Loop through stored static objects + for(core::list::Iterator + i = block->m_static_objects.m_stored.begin(); + i != block->m_static_objects.m_stored.end(); i++) { - // If not m_removed, don't remove. - if(obj->m_removed == false) + dstream<<"INFO: Server: Creating an active object from " + <<"static data"<m_static_objects.m_stored.clear(); + // Add leftover stuff to stored list + for(core::list::Iterator + i = new_stored.begin(); + i != new_stored.end(); i++) + { + StaticObject &s_obj = *i; + block->m_static_objects.m_stored.push_back(s_obj); + } + block->setChangedFlag(); + } + } + + /* + Convert objects that are far away from all the players to static. + */ + { + core::list objects_to_remove; + for(core::map::Iterator + i = m_active_objects.getIterator(); + i.atEnd()==false; i++) + { + ServerActiveObject* obj = i.getNode()->getValue(); + u16 id = i.getNode()->getKey(); + v3f objectpos = obj->getBasePosition(); + + // This shouldn't happen but check it + if(obj == NULL) + { + dstream<<"WARNING: NULL object found in ServerEnvironment" + <m_known_by_count > 0) + continue; + + // If close to some player, don't convert to static. + bool close_to_player = false; + for(core::list::Iterator i = m_players.begin(); + i != m_players.end(); i++) + { + Player *player = *i; + v3f playerpos = player->getPosition(); + f32 d = playerpos.getDistanceFrom(objectpos); + if(d < to_static_max_f) + { + close_to_player = true; + break; + } + } + + if(close_to_player) + continue; + + /* + Update the static data and remove the active object. + */ + + // Delete old static object + MapBlock *oldblock = NULL; + if(obj->m_static_exists) + { + MapBlock *block = m_map->getBlockNoCreateNoEx(obj->m_static_block); + if(block) + { + block->m_static_objects.remove(id); + oldblock = block; + } + } + // Add new static object + std::string staticdata = obj->getStaticData(); + StaticObject s_obj(obj->getType(), objectpos, staticdata); + // Add to the block where the object is located in + v3s16 blockpos = getNodeBlockPos(floatToInt(objectpos, BS)); + MapBlock *block = m_map->getBlockNoCreateNoEx(blockpos); + if(block) + { + block->m_static_objects.insert(0, s_obj); + block->setChangedFlag(); + } + // If not possible, add back to previous block + else if(oldblock) + { + oldblock->m_static_objects.insert(0, s_obj); + oldblock->setChangedFlag(); + } + else{ + dstream<<"WARNING: Server: Could not find a block for " + <<"storing static object"<::Iterator i = objects_to_remove.begin(); @@ -479,11 +636,13 @@ void ServerEnvironment::step(float dtime) /* TEST CODE */ +#if 1 m_random_spawn_timer -= dtime; if(m_random_spawn_timer < 0) { //m_random_spawn_timer += myrand_range(2.0, 20.0); - m_random_spawn_timer += 2.0; + //m_random_spawn_timer += 2.0; + m_random_spawn_timer += 200.0; /* Find some position @@ -508,11 +667,10 @@ void ServerEnvironment::step(float dtime) */ //TestSAO *obj = new TestSAO(this, 0, pos); - ServerActiveObject *obj = new ItemSAO(this, 0, pos, "CraftItem Stick 1"); - - // Add the object to the environment - addActiveObject(obj); + //ServerActiveObject *obj = new ItemSAO(this, 0, pos, "CraftItem Stick 1"); + //addActiveObject(obj); } +#endif } // enable_experimental } @@ -582,7 +740,25 @@ u16 ServerEnvironment::addActiveObject(ServerActiveObject *object) } dstream<<"INGO: ServerEnvironment::addActiveObject(): " <<"added (id="<getId()<<")"<getId(), object); + + // Add static object to active static list of the block + v3f objectpos = object->getBasePosition(); + std::string staticdata = object->getStaticData(); + StaticObject s_obj(object->getType(), objectpos, staticdata); + // Add to the block where the object is located in + v3s16 blockpos = getNodeBlockPos(floatToInt(objectpos, BS)); + MapBlock *block = m_map->getBlockNoCreateNoEx(blockpos); + if(block) + { + block->m_static_objects.m_active.insert(object->getId(), s_obj); + } + else{ + dstream<<"WARNING: Server: Could not find a block for " + <<"storing newly added static active object"<getId(); } @@ -912,7 +1088,7 @@ void ClientEnvironment::step(float dtime) { ClientActiveObject* obj = i.getNode()->getValue(); // Step object - obj->step(dtime); + obj->step(dtime, this); } } diff --git a/src/main.cpp b/src/main.cpp index d3f979cac..7749266d9 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -2620,10 +2620,8 @@ int main(int argc, char *argv[]) if(g_input->getLeftClicked()) { std::cout<getBlock()->getPos(), - selected_object->getId(), g_selected_item); -#endif + client.clickActiveObject(0, + selected_active_object->getId(), g_selected_item); } else if(g_input->getRightClicked()) { @@ -2634,26 +2632,6 @@ int main(int argc, char *argv[]) */ if(selected_object->getTypeId() == MAPBLOCKOBJECT_TYPE_SIGN) { - dstream<<"Sign object right-clicked"<getBlock()->getPos(), - selected_object->getId(), - &client); - - SignObject *sign_object = (SignObject*)selected_object; - - std::wstring wtext = - narrow_to_wide(sign_object->getText()); - - (new GUITextInputMenu(guienv, guiroot, -1, - &g_menumgr, dest, - wtext))->drop(); - } } /* Otherwise pass the event to the server as-is diff --git a/src/map.cpp b/src/map.cpp index 49ed2f5fe..59cf937c0 100644 --- a/src/map.cpp +++ b/src/map.cpp @@ -5239,6 +5239,14 @@ void ServerMap::saveBlock(MapBlock *block) block->serializeObjects(o, version); } + /* + Versions up from 15 have static objects. + */ + if(version >= 15) + { + block->m_static_objects.serialize(o); + } + // We just wrote it to the disk block->resetChangedFlag(); } @@ -5296,6 +5304,14 @@ void ServerMap::loadBlock(std::string sectordir, std::string blockfile, MapSecto block->updateObjects(is, version, NULL, 0); } + /* + Versions up from 15 have static objects. + */ + if(version >= 15) + { + block->m_static_objects.deSerialize(is); + } + if(created_new) sector->insertBlock(block); diff --git a/src/mapblock.h b/src/mapblock.h index a77bf40c0..ce5682568 100644 --- a/src/mapblock.h +++ b/src/mapblock.h @@ -32,6 +32,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "mapblockobject.h" #include "voxel.h" #include "nodemetadata.h" +#include "staticobject.h" // Named by looking towards z+ @@ -681,6 +682,7 @@ public: #endif NodeMetadataList m_node_metadata; + StaticObjectList m_static_objects; private: /* diff --git a/src/nodemetadata.h b/src/nodemetadata.h index e56bff17f..ae02cfc3c 100644 --- a/src/nodemetadata.h +++ b/src/nodemetadata.h @@ -54,7 +54,7 @@ public: virtual u16 typeId() const = 0; virtual NodeMetadata* clone() = 0; virtual void serializeBody(std::ostream &os) = 0; - virtual std::string infoText() {return "";} + virtual std::string infoText() {return "";} virtual Inventory* getInventory() {return NULL;} // This is called always after the inventory is modified, before // the changes are copied elsewhere diff --git a/src/serialization.h b/src/serialization.h index fed5bb522..7b5c7d418 100644 --- a/src/serialization.h +++ b/src/serialization.h @@ -47,11 +47,12 @@ with this program; if not, write to the Free Software Foundation, Inc., 12: (dev) UnlimitedHeightmap now uses interpolated areas 13: (dev) Mapgen v2 14: (dev) NodeMetadata + 15: (dev) StaticObjects */ // This represents an uninitialized or invalid format #define SER_FMT_VER_INVALID 255 // Highest supported serialization version -#define SER_FMT_VER_HIGHEST 14 +#define SER_FMT_VER_HIGHEST 15 // Lowest supported serialization version #define SER_FMT_VER_LOWEST 2 diff --git a/src/server.cpp b/src/server.cpp index 20a6a21c3..ab4032743 100644 --- a/src/server.cpp +++ b/src/server.cpp @@ -1228,7 +1228,7 @@ void Server::AsyncRunStep() } } - if(g_settings.getBool("enable_experimental")) + //if(g_settings.getBool("enable_experimental")) { /* @@ -1345,6 +1345,33 @@ void Server::AsyncRunStep() < all_known_objects; + + for(core::map::Iterator + i = m_clients.getIterator(); + i.atEnd() == false; i++) + { + RemoteClient *client = i.getNode()->getValue(); + // Go through all known objects of client + for(core::map::Iterator + i = client->m_known_objects.getIterator(); + i.atEnd()==false; i++) + { + u16 id = i.getNode()->getKey(); + all_known_objects[id] = true; + } + } + + m_env.setKnownActiveObjects(whatever); +#endif + } /* @@ -1978,6 +2005,70 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id) block->removeObject(id); } } + else if(command == TOSERVER_CLICK_ACTIVEOBJECT) + { + if(datasize < 7) + return; + + /* + length: 7 + [0] u16 command + [2] u8 button (0=left, 1=right) + [3] u16 id + [5] u16 item + */ + u8 button = readU8(&data[2]); + u16 id = readS16(&data[3]); + //u16 item_i = readU16(&data[11]); + + ServerActiveObject *obj = m_env.getActiveObject(id); + + if(obj == NULL) + { + derr_server<<"Server: CLICK_ACTIVEOBJECT: object not found" + <inventory.getList("main"); + if(g_settings.getBool("creative_mode") == false && ilist != NULL) + { + + // Skip if inventory has no free space + if(ilist->getUsedSlots() == ilist->getSize()) + { + dout_server<<"Player inventory has no free space"<getType() == ACTIVEOBJECT_TYPE_ITEM + && obj->m_removed == false) + { + item = ((ItemSAO*)obj)->createInventoryItem(); + } + + if(item) + { + // Add to inventory and send inventory + ilist->addItem(item); + SendInventory(player->peer_id); + } + } + + // Remove object from environment + obj->m_removed = true; + } + } else if(command == TOSERVER_GROUND_ACTION) { if(datasize < 17) @@ -2327,68 +2418,40 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id) }*/ } /* - Handle other items + Place other item (not a block) */ else { v3s16 blockpos = getNodeBlockPos(p_over); - - MapBlock *block = NULL; - try - { - block = m_env.getMap().getBlockNoCreate(blockpos); - } - catch(InvalidPositionException &e) + + /* + Check that the block is loaded so that the item + can properly be added to the static list too + */ + MapBlock *block = m_env.getMap().getBlockNoCreateNoEx(blockpos); + if(block==NULL) { derr_server<<"Error while placing object: " "block not found"<getPosRelative(); - v3f block_pos_f_on_map = intToFloat(block_pos_i_on_map, BS); - v3f pos = intToFloat(p_over, BS); - pos -= block_pos_f_on_map; - - /*dout_server<<"pos=" - <<"("<getName()) - { - MapBlockObjectItem *oitem = (MapBlockObjectItem*)item; - - /*dout_server<<"Trying to place a MapBlockObjectItem: " - "inventorystring=\"" - <getInventoryString() - <<"\""<createObject - (pos, player->getYaw(), player->getPitch()); - } - /* - Handle other items - */ - else - { - dout_server<<"Placing a miscellaneous item on map" - <serialize(os); - dout_server<<"Item string is \""<setItemString(os.str()); - obj = iobj; - } + // Get item string + std::ostringstream os(std::ios_base::binary); + item->serialize(os); + dout_server<<"Item string is \""<addObject(obj); - + // Add the object to the environment + m_env.addActiveObject(obj); + dout_server<<"Placed object"<inventory.getList("main"); @@ -3874,30 +3938,6 @@ Player *Server::emergePlayer(const char *name, const char *password, } // create new player } -#if 0 -void Server::UpdateBlockWaterPressure(MapBlock *block, - core::map &modified_blocks) -{ - MapVoxelManipulator v(&m_env.getMap()); - v.m_disable_water_climb = - g_settings.getBool("disable_water_climb"); - - VoxelArea area(block->getPosRelative(), - block->getPosRelative() + v3s16(1,1,1)*(MAP_BLOCKSIZE-1)); - - try - { - v.updateAreaWaterPressure(area, m_flow_active_nodes); - } - catch(ProcessingLimitException &e) - { - dstream<<"Processing limit reached (1)"< #include "environment.h" +#include "inventory.h" + +core::map ServerActiveObject::m_types; ServerActiveObject::ServerActiveObject(ServerEnvironment *env, u16 id, v3f pos): ActiveObject(id), m_known_by_count(0), m_removed(false), + m_static_exists(false), + m_static_block(1337,1337,1337), m_env(env), m_base_position(pos) { @@ -34,15 +39,55 @@ ServerActiveObject::~ServerActiveObject() { } +ServerActiveObject* ServerActiveObject::create(u8 type, + ServerEnvironment *env, u16 id, v3f pos, + const std::string &data) +{ + // Find factory function + core::map::Node *n; + n = m_types.find(type); + if(n == NULL) + { + // If factory is not found, just return. + dstream<<"WARNING: ServerActiveObject: No factory for type=" + <getValue(); + ServerActiveObject *object = (*f)(env, id, pos, data); + return object; +} + +void ServerActiveObject::registerType(u16 type, Factory f) +{ + core::map::Node *n; + n = m_types.find(type); + if(n) + return; + m_types.insert(type, f); +} + + /* TestSAO */ +// Prototype +TestSAO proto_TestSAO(NULL, 0, v3f(0,0,0)); + TestSAO::TestSAO(ServerEnvironment *env, u16 id, v3f pos): ServerActiveObject(env, id, pos), m_timer1(0), m_age(0) { + ServerActiveObject::registerType(getType(), create); +} + +ServerActiveObject* TestSAO::create(ServerEnvironment *env, u16 id, v3f pos, + const std::string &data) +{ + return new TestSAO(env, id, pos); } void TestSAO::step(float dtime, Queue &messages) @@ -84,6 +129,9 @@ void TestSAO::step(float dtime, Queue &messages) ItemSAO */ +// Prototype +ItemSAO proto_ItemSAO(NULL, 0, v3f(0,0,0), ""); + ItemSAO::ItemSAO(ServerEnvironment *env, u16 id, v3f pos, const std::string inventorystring): ServerActiveObject(env, id, pos), @@ -91,6 +139,19 @@ ItemSAO::ItemSAO(ServerEnvironment *env, u16 id, v3f pos, { dstream<<"Server: ItemSAO created with inventorystring=\"" < &messages) @@ -111,4 +172,34 @@ std::string ItemSAO::getClientInitializationData() return data; } +std::string ItemSAO::getStaticData() +{ + dstream<<__FUNCTION_NAME< item="< m_types; }; class TestSAO : public ServerActiveObject @@ -106,9 +124,9 @@ class TestSAO : public ServerActiveObject public: TestSAO(ServerEnvironment *env, u16 id, v3f pos); u8 getType() const - { - return ACTIVEOBJECT_TYPE_TEST; - } + {return ACTIVEOBJECT_TYPE_TEST;} + static ServerActiveObject* create(ServerEnvironment *env, u16 id, v3f pos, + const std::string &data); void step(float dtime, Queue &messages); private: float m_timer1; @@ -121,11 +139,13 @@ public: ItemSAO(ServerEnvironment *env, u16 id, v3f pos, const std::string inventorystring); u8 getType() const - { - return ACTIVEOBJECT_TYPE_ITEM; - } + {return ACTIVEOBJECT_TYPE_ITEM;} + static ServerActiveObject* create(ServerEnvironment *env, u16 id, v3f pos, + const std::string &data); void step(float dtime, Queue &messages); std::string getClientInitializationData(); + std::string getStaticData(); + InventoryItem* createInventoryItem(); private: std::string m_inventorystring; }; diff --git a/src/utility.h b/src/utility.h index 3640b4b51..2b143f0ba 100644 --- a/src/utility.h +++ b/src/utility.h @@ -1839,15 +1839,17 @@ inline std::string serializeString(const std::string plain) return s; } -// Reads a string with the length as the first two bytes +/*// Reads a string with the length as the first two bytes inline std::string deSerializeString(const std::string encoded) { u16 s_size = readU16((u8*)&encoded.c_str()[0]); + if(s_size > encoded.length() - 2) + return ""; std::string s; s.reserve(s_size); s.append(&encoded.c_str()[2], s_size); return s; -} +}*/ // Reads a string with the length as the first two bytes inline std::string deSerializeString(std::istream &is) @@ -1878,15 +1880,17 @@ inline std::string serializeLongString(const std::string plain) return s; } -// Reads a string with the length as the first four bytes +/*// Reads a string with the length as the first four bytes inline std::string deSerializeLongString(const std::string encoded) { u32 s_size = readU32((u8*)&encoded.c_str()[0]); + if(s_size > encoded.length() - 4) + return ""; std::string s; s.reserve(s_size); - s.append(&encoded.c_str()[2], s_size); + s.append(&encoded.c_str()[4], s_size); return s; -} +}*/ // Reads a string with the length as the first four bytes inline std::string deSerializeLongString(std::istream &is)