diff options
-rw-r--r-- | src/client.cpp | 29 | ||||
-rw-r--r-- | src/client.h | 1 | ||||
-rw-r--r-- | src/clientobject.cpp | 22 | ||||
-rw-r--r-- | src/clientobject.h | 12 | ||||
-rw-r--r-- | src/clientserver.h | 9 | ||||
-rw-r--r-- | src/environment.cpp | 208 | ||||
-rw-r--r-- | src/main.cpp | 26 | ||||
-rw-r--r-- | src/map.cpp | 16 | ||||
-rw-r--r-- | src/mapblock.h | 2 | ||||
-rw-r--r-- | src/nodemetadata.h | 2 | ||||
-rw-r--r-- | src/serialization.h | 3 | ||||
-rw-r--r-- | src/server.cpp | 190 | ||||
-rw-r--r-- | src/serverobject.cpp | 91 | ||||
-rw-r--r-- | src/serverobject.h | 70 | ||||
-rw-r--r-- | 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<<DTIME<<"Client::clickActiveObject() " + "cancelled (not connected)" + <<std::endl; + return; + } + + /* + length: 7 + [0] u16 command + [2] u8 button (0=left, 1=right) + [3] u16 id + [5] u16 item + */ + u8 datasize = 2 + 1 + 6 + 2 + 2; + SharedBuffer<u8> 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<u16, ClientActiveObject::Factory> 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<u16, Factory> 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<u8> 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<u16> 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<u16>::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<Player*>::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<StaticObject> new_stored; + // Loop through stored static objects + for(core::list<StaticObject>::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"<<std::endl; + StaticObject &s_obj = *i; + // Create an active object from the data + ServerActiveObject *obj = ServerActiveObject::create + (s_obj.type, this, 0, s_obj.pos, s_obj.data); + if(obj==NULL) + { + // This is necessary to preserve stuff during bugs + // and errors + new_stored.push_back(s_obj); continue; - // Delete - delete obj; - // Id to be removed from m_active_objects - objects_to_remove.push_back(id); + } + // This will also add the object to the active static list + addActiveObject(obj); + //u16 id = addActiveObject(obj); + } + // Clear stored list + block->m_static_objects.m_stored.clear(); + // Add leftover stuff to stored list + for(core::list<StaticObject>::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<u16> objects_to_remove; + for(core::map<u16, ServerActiveObject*>::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" + <<std::endl; + continue; } + // If known by some client, don't convert to static. + if(obj->m_known_by_count > 0) + continue; + + // If close to some player, don't convert to static. + bool close_to_player = false; + for(core::list<Player*>::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"<<std::endl; + continue; + } + // Delete active object + dstream<<"INFO: Server: Stored static data. Deleting object." + <<std::endl; + 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<u16>::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="<<object->getId()<<")"<<std::endl; + m_active_objects.insert(object->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"<<std::endl; + } + return 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<<DTIME<<"Left-clicked object"<<std::endl;
-#if 0
- client.clickObject(0, selected_object->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"<<std::endl;
-
- if(random_input == false)
- {
- // Get a new text for it
-
- TextDest *dest = new TextDestSign(
- selected_object->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 "<todo: remove this text>";} + 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() <<added_objects.size()<<" added, " <<"packet size is "<<reply.getSize()<<std::endl; } + +#if 0 + /* + Collect a list of all the objects known by the clients + and report it back to the environment. + */ + + core::map<u16, bool> all_known_objects; + + for(core::map<u16, RemoteClient*>::Iterator + i = m_clients.getIterator(); + i.atEnd() == false; i++) + { + RemoteClient *client = i.getNode()->getValue(); + // Go through all known objects of client + for(core::map<u16, bool>::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" + <<std::endl; + return; + } + + //TODO: Check that object is reasonably close + + // Left click, pick object up (usually) + if(button == 0) + { + InventoryList *ilist = player->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"<<std::endl; + return; + } + + /* + Create the inventory item + */ + InventoryItem *item = NULL; + // If it is an item-object, take the item from it + if(obj->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"<<std::endl; return; } - v3s16 block_pos_i_on_map = block->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=" - <<"("<<pos.X<<","<<pos.Y<<","<<pos.Z<<")" - <<std::endl;*/ + pos.Y -= BS*0.45; - MapBlockObject *obj = NULL; - - /* - Handle block object items - */ - if(std::string("MBOItem") == item->getName()) - { - MapBlockObjectItem *oitem = (MapBlockObjectItem*)item; - - /*dout_server<<"Trying to place a MapBlockObjectItem: " - "inventorystring=\"" - <<oitem->getInventoryString() - <<"\""<<std::endl;*/ - - obj = oitem->createObject - (pos, player->getYaw(), player->getPitch()); - } + dout_server<<"Placing a miscellaneous item on map" + <<std::endl; + /* - Handle other items + Create an ItemSAO */ - else - { - dout_server<<"Placing a miscellaneous item on map" - <<std::endl; - /* - Create an ItemObject that contains the item. - */ - ItemObject *iobj = new ItemObject(NULL, -1, pos); - std::ostringstream os(std::ios_base::binary); - item->serialize(os); - dout_server<<"Item string is \""<<os.str()<<"\""<<std::endl; - iobj->setItemString(os.str()); - obj = iobj; - } + // Get item string + std::ostringstream os(std::ios_base::binary); + item->serialize(os); + dout_server<<"Item string is \""<<os.str()<<"\""<<std::endl; + // Create object + ServerActiveObject *obj = new ItemSAO + (&m_env, 0, pos, os.str()); if(obj == NULL) { @@ -2398,8 +2461,9 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id) } else { - block->addObject(obj); - + // Add the object to the environment + m_env.addActiveObject(obj); + dout_server<<"Placed object"<<std::endl; InventoryList *ilist = player->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<v3s16, MapBlock*> &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)"<<std::endl; - } - - v.blitBack(modified_blocks); -} -#endif - void Server::handlePeerChange(PeerChange &c) { JMutexAutoLock envlock(m_env_mutex); diff --git a/src/serverobject.cpp b/src/serverobject.cpp index 3645f7666..f0ef7d8d6 100644 --- a/src/serverobject.cpp +++ b/src/serverobject.cpp @@ -20,11 +20,16 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "serverobject.h" #include <fstream> #include "environment.h" +#include "inventory.h" + +core::map<u16, ServerActiveObject::Factory> 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<u16, Factory>::Node *n; + n = m_types.find(type); + if(n == NULL) + { + // If factory is not found, just return. + dstream<<"WARNING: ServerActiveObject: No factory for type=" + <<type<<std::endl; + return NULL; + } + + Factory f = n->getValue(); + ServerActiveObject *object = (*f)(env, id, pos, data); + return object; +} + +void ServerActiveObject::registerType(u16 type, Factory f) +{ + core::map<u16, Factory>::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<ActiveObjectMessage> &messages) @@ -84,6 +129,9 @@ void TestSAO::step(float dtime, Queue<ActiveObjectMessage> &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=\"" <<m_inventorystring<<"\""<<std::endl; + ServerActiveObject::registerType(getType(), create); +} + +ServerActiveObject* ItemSAO::create(ServerEnvironment *env, u16 id, v3f pos, + const std::string &data) +{ + std::istringstream is(data, std::ios::binary); + char buf[1]; + is.read(buf, 1); // read version + std::string inventorystring = deSerializeString(is); + dstream<<"ItemSAO::create(): Creating item \"" + <<inventorystring<<"\""<<std::endl; + return new ItemSAO(env, id, pos, inventorystring); } void ItemSAO::step(float dtime, Queue<ActiveObjectMessage> &messages) @@ -111,4 +172,34 @@ std::string ItemSAO::getClientInitializationData() return data; } +std::string ItemSAO::getStaticData() +{ + dstream<<__FUNCTION_NAME<<std::endl; + std::ostringstream os(std::ios::binary); + char buf[1]; + buf[0] = 0; //version + os.write(buf, 1); + os<<serializeString(m_inventorystring); + return os.str(); +} + +InventoryItem * ItemSAO::createInventoryItem() +{ + try{ + std::istringstream is(m_inventorystring, std::ios_base::binary); + InventoryItem *item = InventoryItem::deSerialize(is); + dstream<<__FUNCTION_NAME<<": m_inventorystring=\"" + <<m_inventorystring<<"\" -> item="<<item + <<std::endl; + return item; + } + catch(SerializationError &e) + { + dstream<<__FUNCTION_NAME<<": serialization error: " + <<"m_inventorystring=\""<<m_inventorystring<<"\""<<std::endl; + return NULL; + } +} + + diff --git a/src/serverobject.h b/src/serverobject.h index 241458193..a307c421f 100644 --- a/src/serverobject.h +++ b/src/serverobject.h @@ -39,27 +39,28 @@ Some planning */ class ServerEnvironment; +class InventoryItem; class ServerActiveObject : public ActiveObject { public: - ServerActiveObject(ServerEnvironment *env, u16 id, v3f pos=v3f(0,0,0)); + ServerActiveObject(ServerEnvironment *env, u16 id, v3f pos); virtual ~ServerActiveObject(); - v3f getBasePosition() - { - return m_base_position; - } + // Create a certain type of ServerActiveObject + static ServerActiveObject* create(u8 type, + ServerEnvironment *env, u16 id, v3f pos, + const std::string &data); + /* + Some simple getters/setters + */ + v3f getBasePosition() + {return m_base_position;} void setBasePosition(v3f pos) - { - m_base_position = pos; - } - + {m_base_position = pos;} ServerEnvironment* getEnv() - { - return m_env; - } + {return m_env;} /* Step object in time. @@ -75,14 +76,10 @@ public: /* The return value of this is passed to the server-side object - when it is loaded from disk or from a static object - */ - virtual std::string getServerInitializationData(){return "";} - - /* - This takes the return value of getServerInitializationData + when it is created (converted from static to active - actually + the data is the static form) */ - virtual void initialize(const std::string &data){} + virtual std::string getStaticData(){return "";} // Number of players which know about this object u16 m_known_by_count; @@ -93,12 +90,33 @@ public: it could be confused to some other object by some client. - This is set to true by the step() method when the object wants to be deleted. + - This can be set to true by anything else too. */ bool m_removed; + /* + Whether the object's static data has been stored to a block + */ + bool m_static_exists; + /* + The block from which the object was loaded from, and in which + a copy of the static data resides. + */ + v3s16 m_static_block; + protected: + // Used for creating objects based on type + typedef ServerActiveObject* (*Factory) + (ServerEnvironment *env, u16 id, v3f pos, + const std::string &data); + static void registerType(u16 type, Factory f); + ServerEnvironment *m_env; v3f m_base_position; + +private: + // Used for creating objects based on type + static core::map<u16, Factory> 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<ActiveObjectMessage> &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<ActiveObjectMessage> &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) |