diff options
-rw-r--r-- | src/activeobject.h | 1 | ||||
-rw-r--r-- | src/client.cpp | 42 | ||||
-rw-r--r-- | src/client.h | 8 | ||||
-rw-r--r-- | src/clientobject.cpp | 230 | ||||
-rw-r--r-- | src/clientobject.h | 77 | ||||
-rw-r--r-- | src/environment.cpp | 30 | ||||
-rw-r--r-- | src/environment.h | 6 | ||||
-rw-r--r-- | src/main.cpp | 90 | ||||
-rw-r--r-- | src/nodemetadata.cpp | 9 | ||||
-rw-r--r-- | src/server.cpp | 11 | ||||
-rw-r--r-- | src/server.h | 2 | ||||
-rw-r--r-- | src/serverobject.cpp | 31 | ||||
-rw-r--r-- | src/serverobject.h | 25 |
13 files changed, 522 insertions, 40 deletions
diff --git a/src/activeobject.h b/src/activeobject.h index 1a16aa0c4..041be0778 100644 --- a/src/activeobject.h +++ b/src/activeobject.h @@ -38,6 +38,7 @@ struct ActiveObjectMessage #define ACTIVEOBJECT_TYPE_INVALID 0 #define ACTIVEOBJECT_TYPE_TEST 1 +#define ACTIVEOBJECT_TYPE_ITEM 2 /* Parent class for ServerActiveObject and ClientActiveObject diff --git a/src/client.cpp b/src/client.cpp index d22f93ac2..1f2f7e1e8 100644 --- a/src/client.cpp +++ b/src/client.cpp @@ -1970,6 +1970,48 @@ MapBlockObject * Client::getSelectedObject( return NULL; } +ClientActiveObject * Client::getSelectedActiveObject( + f32 max_d, + v3f from_pos_f_on_map, + core::line3d<f32> shootline_on_map + ) +{ + core::array<DistanceSortedActiveObject> objects; + + m_env.getActiveObjects(from_pos_f_on_map, max_d, objects); + + //dstream<<"Collected "<<objects.size()<<" nearby objects"<<std::endl; + + // Sort them. + // After this, the closest object is the first in the array. + objects.sort(); + + for(u32 i=0; i<objects.size(); i++) + { + ClientActiveObject *obj = objects[i].obj; + + core::aabbox3d<f32> *selection_box = obj->getSelectionBox(); + if(selection_box == NULL) + continue; + + v3f pos = obj->getPosition(); + + core::aabbox3d<f32> offsetted_box( + selection_box->MinEdge + pos, + selection_box->MaxEdge + pos + ); + + if(offsetted_box.intersectsWithLine(shootline_on_map)) + { + //dstream<<"Returning selected object"<<std::endl; + return obj; + } + } + + //dstream<<"No object selected; returning NULL."<<std::endl; + return NULL; +} + void Client::printDebugInfo(std::ostream &os) { //JMutexAutoLock lock1(m_fetchblock_mutex); diff --git a/src/client.h b/src/client.h index 611116d45..0616cc914 100644 --- a/src/client.h +++ b/src/client.h @@ -316,6 +316,14 @@ public: core::line3d<f32> shootline_on_map ); + // Gets closest object pointed by the shootline + // Returns NULL if not found + ClientActiveObject * getSelectedActiveObject( + f32 max_d, + v3f from_pos_f_on_map, + core::line3d<f32> shootline_on_map + ); + // Prints a line or two of info void printDebugInfo(std::ostream &os); diff --git a/src/clientobject.cpp b/src/clientobject.cpp index 61ceefbe3..d95862d1d 100644 --- a/src/clientobject.cpp +++ b/src/clientobject.cpp @@ -23,6 +23,8 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "constants.h" #include "utility.h" +core::map<u16, ClientActiveObject::Factory> ClientActiveObject::m_types; + ClientActiveObject::ClientActiveObject(u16 id): ActiveObject(id) { @@ -35,41 +37,55 @@ ClientActiveObject::~ClientActiveObject() ClientActiveObject* ClientActiveObject::create(u8 type) { - if(type == ACTIVEOBJECT_TYPE_INVALID) + // Find factory function + core::map<u16, Factory>::Node *n; + n = m_types.find(type); + if(n == NULL) { - dstream<<"ClientActiveObject::create(): passed " - <<"ACTIVEOBJECT_TYPE_INVALID"<<std::endl; - return NULL; - } - else if(type == ACTIVEOBJECT_TYPE_TEST) - { - dstream<<"ClientActiveObject::create(): passed " - <<"ACTIVEOBJECT_TYPE_TEST"<<std::endl; - return new TestCAO(0); - } - else - { - dstream<<"ClientActiveObject::create(): passed " - <<"unknown type="<<type<<std::endl; + // If factory is not found, just return. + dstream<<"WARNING: ClientActiveObject: No factory for type=" + <<type<<std::endl; return NULL; } + + Factory f = n->getValue(); + ClientActiveObject *object = (*f)(); + return object; +} + +void ClientActiveObject::registerType(u16 type, Factory f) +{ + core::map<u16, Factory>::Node *n; + n = m_types.find(type); + if(n) + return; + m_types.insert(type, f); } /* TestCAO */ -TestCAO::TestCAO(u16 id): - ClientActiveObject(id), +// Prototype +TestCAO proto_TestCAO; + +TestCAO::TestCAO(): + ClientActiveObject(0), m_node(NULL), m_position(v3f(0,10*BS,0)) { + ClientActiveObject::registerType(getType(), create); } TestCAO::~TestCAO() { } +ClientActiveObject* TestCAO::create() +{ + return new TestCAO(); +} + void TestCAO::addToScene(scene::ISceneManager *smgr) { if(m_node != NULL) @@ -160,4 +176,184 @@ void TestCAO::processMessage(const std::string &data) } } +/* + ItemCAO +*/ + +#include "inventory.h" + +// Prototype +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_node(NULL), + m_position(v3f(0,10*BS,0)) +{ + ClientActiveObject::registerType(getType(), create); +} + +ItemCAO::~ItemCAO() +{ +} + +ClientActiveObject* ItemCAO::create() +{ + return new ItemCAO(); +} + +void ItemCAO::addToScene(scene::ISceneManager *smgr) +{ + if(m_node != NULL) + return; + + video::IVideoDriver* driver = smgr->getVideoDriver(); + + scene::SMesh *mesh = new scene::SMesh(); + scene::IMeshBuffer *buf = new scene::SMeshBuffer(); + video::SColor c(255,255,255,255); + video::S3DVertex vertices[4] = + { + /*video::S3DVertex(-BS/2,-BS/4,0, 0,0,0, c, 0,1), + 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), + }; + u16 indices[] = {0,1,2,2,3,0}; + buf->append(vertices, 4, indices, 6); + // Set material + buf->getMaterial().setFlag(video::EMF_LIGHTING, false); + buf->getMaterial().setFlag(video::EMF_BACK_FACE_CULLING, false); + //buf->getMaterial().setTexture(0, NULL); + buf->getMaterial().setTexture + (0, driver->getTexture(porting::getDataPath("rat.png").c_str())); + buf->getMaterial().setFlag(video::EMF_BILINEAR_FILTER, false); + buf->getMaterial().setFlag(video::EMF_FOG_ENABLE, true); + buf->getMaterial().MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL; + // Add to mesh + mesh->addMeshBuffer(buf); + buf->drop(); + m_node = smgr->addMeshSceneNode(mesh, NULL); + mesh->drop(); + // Set it to use the materials of the meshbuffers directly. + // This is needed for changing the texture in the future + m_node->setReadOnlyMaterials(true); + updateNodePos(); +} + +void ItemCAO::removeFromScene() +{ + if(m_node == NULL) + return; + + m_node->remove(); + m_node = NULL; +} + +void ItemCAO::updateLight(u8 light_at_pos) +{ +} + +v3s16 ItemCAO::getLightPosition() +{ + return floatToInt(m_position, BS); +} + +void ItemCAO::updateNodePos() +{ + if(m_node == NULL) + return; + + m_node->setPosition(m_position); +} + +void ItemCAO::step(float dtime) +{ + if(m_node) + { + v3f rot = m_node->getRotation(); + rot.Y += dtime * 120; + m_node->setRotation(rot); + } +} + +void ItemCAO::processMessage(const std::string &data) +{ + dstream<<"ItemCAO: Got data: "<<data<<std::endl; + std::istringstream is(data, std::ios::binary); + u16 cmd; + is>>cmd; + if(cmd == 0) + { + v3f newpos; + is>>newpos.X; + is>>newpos.Y; + is>>newpos.Z; + m_position = newpos; + updateNodePos(); + } +} + +void ItemCAO::initialize(const std::string &data) +{ + dstream<<"ItemCAO: Got init data: "<<data<<std::endl; + + Strfnd fn(data); + + v3f newpos; + newpos.X = stoi(fn.next(",")); + newpos.Y = stoi(fn.next(",")); + newpos.Z = stoi(fn.next(":")); + m_position = newpos; + updateNodePos(); + + m_inventorystring = fn.next(""); + + if(m_node == NULL) + return; + + scene::IMesh *mesh = m_node->getMesh(); + + if(mesh == NULL) + return; + + scene::IMeshBuffer *buf = mesh->getMeshBuffer(0); + + if(buf == NULL) + return; + + /* + Create an inventory item to see what is its image + */ + std::istringstream is(m_inventorystring, std::ios_base::binary); + video::ITexture *texture = NULL; + try{ + InventoryItem *item = NULL; + item = InventoryItem::deSerialize(is); + dstream<<__FUNCTION_NAME<<": m_inventorystring=\"" + <<m_inventorystring<<"\" -> item="<<item + <<std::endl; + if(item) + { + texture = item->getImage(); + delete item; + } + } + catch(SerializationError &e) + { + dstream<<"WARNING: "<<__FUNCTION_NAME + <<": error deSerializing inventorystring \"" + <<m_inventorystring<<"\""<<std::endl; + } + + // Set meshbuffer texture + buf->getMaterial().setTexture(0, texture); + +} + diff --git a/src/clientobject.h b/src/clientobject.h index 226d2f337..ebdcb948e 100644 --- a/src/clientobject.h +++ b/src/clientobject.h @@ -46,6 +46,9 @@ public: // 0 <= light_at_pos <= LIGHT_SUN virtual void updateLight(u8 light_at_pos){} virtual v3s16 getLightPosition(){return v3s16(0,0,0);} + virtual core::aabbox3d<f32>* getSelectionBox(){return NULL;} + virtual core::aabbox3d<f32>* getCollisionBox(){return NULL;} + virtual v3f getPosition(){return v3f(0,0,0);} // Step object in time virtual void step(float dtime){} @@ -54,8 +57,8 @@ public: virtual void processMessage(const std::string &data){} /* - This takes the return value of getClientInitializationData - TODO: Usage of this + This takes the return value of + ServerActiveObject::getClientInitializationData */ virtual void initialize(const std::string &data){} @@ -63,12 +66,37 @@ public: static ClientActiveObject* create(u8 type); protected: + typedef ClientActiveObject* (*Factory)(); + static void registerType(u16 type, Factory f); +private: + static core::map<u16, Factory> m_types; }; +struct DistanceSortedActiveObject +{ + ClientActiveObject *obj; + f32 d; + + DistanceSortedActiveObject(ClientActiveObject *a_obj, f32 a_d) + { + obj = a_obj; + d = a_d; + } + + bool operator < (DistanceSortedActiveObject &other) + { + return d < other.d; + } +}; + +/* + TestCAO +*/ + class TestCAO : public ClientActiveObject { public: - TestCAO(u16 id); + TestCAO(); virtual ~TestCAO(); u8 getType() const @@ -76,6 +104,40 @@ public: return ACTIVEOBJECT_TYPE_TEST; } + static ClientActiveObject* create(); + + void addToScene(scene::ISceneManager *smgr); + void removeFromScene(); + void updateLight(u8 light_at_pos); + v3s16 getLightPosition(); + void updateNodePos(); + + void step(float dtime); + + void processMessage(const std::string &data); + +private: + scene::IMeshSceneNode *m_node; + v3f m_position; +}; + +/* + ItemCAO +*/ + +class ItemCAO : public ClientActiveObject +{ +public: + ItemCAO(); + virtual ~ItemCAO(); + + u8 getType() const + { + return ACTIVEOBJECT_TYPE_ITEM; + } + + static ClientActiveObject* create(); + void addToScene(scene::ISceneManager *smgr); void removeFromScene(); void updateLight(u8 light_at_pos); @@ -86,9 +148,18 @@ public: void processMessage(const std::string &data); + void initialize(const std::string &data); + + core::aabbox3d<f32>* getSelectionBox() + {return &m_selection_box;} + v3f getPosition() + {return m_position;} + private: + core::aabbox3d<f32> m_selection_box; scene::IMeshSceneNode *m_node; v3f m_position; + std::string m_inventorystring; }; #endif diff --git a/src/environment.cpp b/src/environment.cpp index d144baeef..f4afb28bf 100644 --- a/src/environment.cpp +++ b/src/environment.cpp @@ -482,7 +482,8 @@ void ServerEnvironment::step(float dtime) 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 += myrand_range(2.0, 20.0); + m_random_spawn_timer += 2.0; /* Find some position @@ -503,11 +504,11 @@ void ServerEnvironment::step(float dtime) ); /* - Create a TestSAO object + Create a ServerActiveObject */ - TestSAO *obj = new TestSAO(this, 0, - v3f(myrand_range(-2*BS,2*BS), BS*5, myrand_range(-2*BS,2*BS))); + //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); @@ -1044,6 +1045,27 @@ void ClientEnvironment::processActiveObjectMessage(u16 id, obj->processMessage(data); } +void ClientEnvironment::getActiveObjects(v3f origin, f32 max_d, + core::array<DistanceSortedActiveObject> &dest) +{ + for(core::map<u16, ClientActiveObject*>::Iterator + i = m_active_objects.getIterator(); + i.atEnd()==false; i++) + { + ClientActiveObject* obj = i.getNode()->getValue(); + + f32 d = (obj->getPosition() - origin).getLength(); + + if(d > max_d) + continue; + + DistanceSortedActiveObject dso(obj, d); + + dest.push_back(dso); + } +} + + #endif // #ifndef SERVER diff --git a/src/environment.h b/src/environment.h index b4159372a..9532271bb 100644 --- a/src/environment.h +++ b/src/environment.h @@ -211,7 +211,11 @@ public: void removeActiveObject(u16 id); void processActiveObjectMessage(u16 id, const std::string &data); - + + // Get all nearby objects + void getActiveObjects(v3f origin, f32 max_d, + core::array<DistanceSortedActiveObject> &dest); + private: ClientMap *m_map; scene::ISceneManager *m_smgr; diff --git a/src/main.cpp b/src/main.cpp index 46d685ae3..d3f979cac 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -109,17 +109,19 @@ Gaming ideas: Game content:
-------------
- When furnace is destroyed, move items to player's inventory
-- Add lots of stuff, no matter if they have really no real purpose.
+- Add lots of stuff
- Glass blocks
- Growing grass, decaying leaves
- - This can be done in the active blocks I guess.
- - Lots of stuff can be done in the active blocks.
- - Uh, is there an active block list somewhere?
+ - This can be done in the active blocks I guess.
+ - Lots of stuff can be done in the active blocks.
+ - Uh, is there an active block list somewhere? I think not. Add it.
- Player health points
- - When player dies, throw items on map
+ - When player dies, throw items on map (needs better item-on-map
+ implementation)
- Cobble to get mossy if near water
- More slots in furnace source list, so that multiple ingredients
are possible.
+- Keys to chests?
Documentation:
--------------
@@ -200,7 +202,7 @@ FIXME: If something is removed from craftresult with a right click, Objects:
--------
-TODO: Get rid of MapBlockObjects
+TODO: Get rid of MapBlockObjects and use ActiveObjects
Map:
----
@@ -2534,9 +2536,9 @@ int main(int argc, char *argv[]) MapBlockObject *selected_object = client.getSelectedObject
(d*BS, camera_position, shootline);
- /*
- If it's pointing to a MapBlockObject
- */
+ ClientActiveObject *selected_active_object
+ = client.getSelectedActiveObject
+ (d*BS, camera_position, shootline);
if(selected_object != NULL)
{
@@ -2594,6 +2596,76 @@ int main(int argc, char *argv[]) }
}
}
+ else if(selected_active_object != NULL)
+ {
+ //dstream<<"Client returned selected_active_object != NULL"<<std::endl;
+
+ core::aabbox3d<f32> *selection_box
+ = selected_active_object->getSelectionBox();
+ // Box should exist because it was returned in the first place
+ assert(selection_box);
+
+ v3f pos = selected_active_object->getPosition();
+
+ core::aabbox3d<f32> box_on_map(
+ selection_box->MinEdge + pos,
+ selection_box->MaxEdge + pos
+ );
+
+ hilightboxes.push_back(box_on_map);
+
+ infotext = narrow_to_wide("A ClientActiveObject");
+ //infotext = narrow_to_wide(selected_object->infoText());
+
+ 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
+ }
+ else if(g_input->getRightClicked())
+ {
+ std::cout<<DTIME<<"Right-clicked object"<<std::endl;
+#if 0
+ /*
+ Check if we want to modify the object ourselves
+ */
+ 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
+ */
+ else
+ {
+ client.clickObject(1, selected_object->getBlock()->getPos(),
+ selected_object->getId(), g_selected_item);
+ }
+#endif
+ }
+ }
else // selected_object == NULL
{
diff --git a/src/nodemetadata.cpp b/src/nodemetadata.cpp index be21622d3..308a33854 100644 --- a/src/nodemetadata.cpp +++ b/src/nodemetadata.cpp @@ -99,6 +99,9 @@ void NodeMetadata::registerType(u16 id, Factory f) SignNodeMetadata */ +// Prototype +SignNodeMetadata proto_SignNodeMetadata(""); + SignNodeMetadata::SignNodeMetadata(std::string text): m_text(text) { @@ -130,6 +133,9 @@ std::string SignNodeMetadata::infoText() ChestNodeMetadata */ +// Prototype +ChestNodeMetadata proto_ChestNodeMetadata; + ChestNodeMetadata::ChestNodeMetadata() { NodeMetadata::registerType(typeId(), create); @@ -182,6 +188,9 @@ bool ChestNodeMetadata::nodeRemovalDisabled() FurnaceNodeMetadata */ +// Prototype +FurnaceNodeMetadata proto_FurnaceNodeMetadata; + FurnaceNodeMetadata::FurnaceNodeMetadata() { NodeMetadata::registerType(typeId(), create); diff --git a/src/server.cpp b/src/server.cpp index d25c4a9d6..20a6a21c3 100644 --- a/src/server.cpp +++ b/src/server.cpp @@ -1222,7 +1222,7 @@ void Server::AsyncRunStep() //u16 peer_id = i.getNode()->getKey(); RemoteClient *client = i.getNode()->getValue(); Player *player = m_env.getPlayer(client->peer_id); - std::cout<<player->getName()<<" "; + std::cout<<player->getName()<<"\t"; client->PrintInfo(std::cout); } } @@ -1235,6 +1235,8 @@ void Server::AsyncRunStep() Check added and deleted active objects */ { + //dstream<<"Server: Checking added and deleted active objects"<<std::endl; + JMutexAutoLock envlock(m_env_mutex); JMutexAutoLock conlock(m_con_mutex); @@ -1248,7 +1250,11 @@ void Server::AsyncRunStep() RemoteClient *client = i.getNode()->getValue(); Player *player = m_env.getPlayer(client->peer_id); if(player==NULL) + { + dstream<<"WARNING: "<<__FUNCTION_NAME<<": Client "<<client->peer_id + <<" has no associated player"<<std::endl; continue; + } v3s16 pos = floatToInt(player->getPosition(), BS); core::map<u16, bool> removed_objects; @@ -1260,7 +1266,10 @@ void Server::AsyncRunStep() // Ignore if nothing happened if(removed_objects.size() == 0 && added_objects.size() == 0) + { + //dstream<<"INFO: active objects: none changed"<<std::endl; continue; + } std::string data_buffer; diff --git a/src/server.h b/src/server.h index 4a757ad73..9059e91b8 100644 --- a/src/server.h +++ b/src/server.h @@ -285,7 +285,7 @@ public: void PrintInfo(std::ostream &o) { o<<"RemoteClient "<<peer_id<<": " - <<", m_blocks_sent.size()="<<m_blocks_sent.size() + <<"m_blocks_sent.size()="<<m_blocks_sent.size() <<", m_blocks_sending.size()="<<m_blocks_sending.size() <<", m_nearest_unsent_d="<<m_nearest_unsent_d <<", m_excess_gotblocks="<<m_excess_gotblocks diff --git a/src/serverobject.cpp b/src/serverobject.cpp index 48d487ab0..3645f7666 100644 --- a/src/serverobject.cpp +++ b/src/serverobject.cpp @@ -80,4 +80,35 @@ void TestSAO::step(float dtime, Queue<ActiveObjectMessage> &messages) } +/* + ItemSAO +*/ + +ItemSAO::ItemSAO(ServerEnvironment *env, u16 id, v3f pos, + const std::string inventorystring): + ServerActiveObject(env, id, pos), + m_inventorystring(inventorystring) +{ + dstream<<"Server: ItemSAO created with inventorystring=\"" + <<m_inventorystring<<"\""<<std::endl; +} + +void ItemSAO::step(float dtime, Queue<ActiveObjectMessage> &messages) +{ +} + +std::string ItemSAO::getClientInitializationData() +{ + dstream<<__FUNCTION_NAME<<std::endl; + std::string data; + data += itos(m_base_position.X); + data += ","; + data += itos(m_base_position.Y); + data += ","; + data += itos(m_base_position.Z); + data += ":"; + data += m_inventorystring; + return data; +} + diff --git a/src/serverobject.h b/src/serverobject.h index 1d1888580..241458193 100644 --- a/src/serverobject.h +++ b/src/serverobject.h @@ -87,10 +87,12 @@ public: // Number of players which know about this object u16 m_known_by_count; /* - Whether this object is to be removed when nobody knows about - it anymore. - Removal is delayed to preserve the id for the time during which - it could be confused to some other object by some client. + - Whether this object is to be removed when nobody knows about + it anymore. + - Removal is delayed to preserve the id for the time during which + 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. */ bool m_removed; @@ -113,5 +115,20 @@ private: float m_age; }; +class ItemSAO : public ServerActiveObject +{ +public: + ItemSAO(ServerEnvironment *env, u16 id, v3f pos, + const std::string inventorystring); + u8 getType() const + { + return ACTIVEOBJECT_TYPE_ITEM; + } + void step(float dtime, Queue<ActiveObjectMessage> &messages); + std::string getClientInitializationData(); +private: + std::string m_inventorystring; +}; + #endif |