Some progress on transitioning from MapBlockObject to ActiveObject.

This commit is contained in:
Perttu Ahola 2011-04-08 00:47:14 +03:00
parent 2dba606e12
commit 4b54b291ae
13 changed files with 522 additions and 40 deletions

@ -38,6 +38,7 @@ struct ActiveObjectMessage
#define ACTIVEOBJECT_TYPE_INVALID 0 #define ACTIVEOBJECT_TYPE_INVALID 0
#define ACTIVEOBJECT_TYPE_TEST 1 #define ACTIVEOBJECT_TYPE_TEST 1
#define ACTIVEOBJECT_TYPE_ITEM 2
/* /*
Parent class for ServerActiveObject and ClientActiveObject Parent class for ServerActiveObject and ClientActiveObject

@ -1970,6 +1970,48 @@ MapBlockObject * Client::getSelectedObject(
return NULL; 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) void Client::printDebugInfo(std::ostream &os)
{ {
//JMutexAutoLock lock1(m_fetchblock_mutex); //JMutexAutoLock lock1(m_fetchblock_mutex);

@ -316,6 +316,14 @@ public:
core::line3d<f32> shootline_on_map 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 // Prints a line or two of info
void printDebugInfo(std::ostream &os); void printDebugInfo(std::ostream &os);

@ -23,6 +23,8 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "constants.h" #include "constants.h"
#include "utility.h" #include "utility.h"
core::map<u16, ClientActiveObject::Factory> ClientActiveObject::m_types;
ClientActiveObject::ClientActiveObject(u16 id): ClientActiveObject::ClientActiveObject(u16 id):
ActiveObject(id) ActiveObject(id)
{ {
@ -35,41 +37,55 @@ ClientActiveObject::~ClientActiveObject()
ClientActiveObject* ClientActiveObject::create(u8 type) 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 " // If factory is not found, just return.
<<"ACTIVEOBJECT_TYPE_INVALID"<<std::endl; dstream<<"WARNING: ClientActiveObject: No factory for type="
<<type<<std::endl;
return NULL; return NULL;
} }
else if(type == ACTIVEOBJECT_TYPE_TEST)
{ Factory f = n->getValue();
dstream<<"ClientActiveObject::create(): passed " ClientActiveObject *object = (*f)();
<<"ACTIVEOBJECT_TYPE_TEST"<<std::endl; return object;
return new TestCAO(0);
} }
else
void ClientActiveObject::registerType(u16 type, Factory f)
{ {
dstream<<"ClientActiveObject::create(): passed " core::map<u16, Factory>::Node *n;
<<"unknown type="<<type<<std::endl; n = m_types.find(type);
return NULL; if(n)
} return;
m_types.insert(type, f);
} }
/* /*
TestCAO TestCAO
*/ */
TestCAO::TestCAO(u16 id): // Prototype
ClientActiveObject(id), TestCAO proto_TestCAO;
TestCAO::TestCAO():
ClientActiveObject(0),
m_node(NULL), m_node(NULL),
m_position(v3f(0,10*BS,0)) m_position(v3f(0,10*BS,0))
{ {
ClientActiveObject::registerType(getType(), create);
} }
TestCAO::~TestCAO() TestCAO::~TestCAO()
{ {
} }
ClientActiveObject* TestCAO::create()
{
return new TestCAO();
}
void TestCAO::addToScene(scene::ISceneManager *smgr) void TestCAO::addToScene(scene::ISceneManager *smgr)
{ {
if(m_node != NULL) 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);
}

@ -46,6 +46,9 @@ public:
// 0 <= light_at_pos <= LIGHT_SUN // 0 <= light_at_pos <= LIGHT_SUN
virtual void updateLight(u8 light_at_pos){} virtual void updateLight(u8 light_at_pos){}
virtual v3s16 getLightPosition(){return v3s16(0,0,0);} 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 // Step object in time
virtual void step(float dtime){} virtual void step(float dtime){}
@ -54,8 +57,8 @@ public:
virtual void processMessage(const std::string &data){} virtual void processMessage(const std::string &data){}
/* /*
This takes the return value of getClientInitializationData This takes the return value of
TODO: Usage of this ServerActiveObject::getClientInitializationData
*/ */
virtual void initialize(const std::string &data){} virtual void initialize(const std::string &data){}
@ -63,12 +66,37 @@ public:
static ClientActiveObject* create(u8 type); static ClientActiveObject* create(u8 type);
protected: 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 class TestCAO : public ClientActiveObject
{ {
public: public:
TestCAO(u16 id); TestCAO();
virtual ~TestCAO(); virtual ~TestCAO();
u8 getType() const u8 getType() const
@ -76,6 +104,8 @@ public:
return ACTIVEOBJECT_TYPE_TEST; return ACTIVEOBJECT_TYPE_TEST;
} }
static ClientActiveObject* create();
void addToScene(scene::ISceneManager *smgr); void addToScene(scene::ISceneManager *smgr);
void removeFromScene(); void removeFromScene();
void updateLight(u8 light_at_pos); void updateLight(u8 light_at_pos);
@ -91,5 +121,46 @@ private:
v3f m_position; 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);
v3s16 getLightPosition();
void updateNodePos();
void step(float dtime);
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 #endif

@ -482,7 +482,8 @@ void ServerEnvironment::step(float dtime)
m_random_spawn_timer -= dtime; m_random_spawn_timer -= dtime;
if(m_random_spawn_timer < 0) 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 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, //TestSAO *obj = new TestSAO(this, 0, pos);
v3f(myrand_range(-2*BS,2*BS), BS*5, myrand_range(-2*BS,2*BS))); ServerActiveObject *obj = new ItemSAO(this, 0, pos, "CraftItem Stick 1");
// Add the object to the environment // Add the object to the environment
addActiveObject(obj); addActiveObject(obj);
@ -1044,6 +1045,27 @@ void ClientEnvironment::processActiveObjectMessage(u16 id,
obj->processMessage(data); 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 #endif // #ifndef SERVER

@ -212,6 +212,10 @@ public:
void processActiveObjectMessage(u16 id, const std::string &data); void processActiveObjectMessage(u16 id, const std::string &data);
// Get all nearby objects
void getActiveObjects(v3f origin, f32 max_d,
core::array<DistanceSortedActiveObject> &dest);
private: private:
ClientMap *m_map; ClientMap *m_map;
scene::ISceneManager *m_smgr; scene::ISceneManager *m_smgr;

@ -109,17 +109,19 @@ Gaming ideas:
Game content: Game content:
------------- -------------
- When furnace is destroyed, move items to player's inventory - 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 - Glass blocks
- Growing grass, decaying leaves - Growing grass, decaying leaves
- This can be done in the active blocks I guess. - This can be done in the active blocks I guess.
- Lots of stuff can be done in the active blocks. - Lots of stuff can be done in the active blocks.
- Uh, is there an active block list somewhere? - Uh, is there an active block list somewhere? I think not. Add it.
- Player health points - 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 - Cobble to get mossy if near water
- More slots in furnace source list, so that multiple ingredients - More slots in furnace source list, so that multiple ingredients
are possible. are possible.
- Keys to chests?
Documentation: Documentation:
-------------- --------------
@ -200,7 +202,7 @@ FIXME: If something is removed from craftresult with a right click,
Objects: Objects:
-------- --------
TODO: Get rid of MapBlockObjects TODO: Get rid of MapBlockObjects and use ActiveObjects
Map: Map:
---- ----
@ -2534,9 +2536,9 @@ int main(int argc, char *argv[])
MapBlockObject *selected_object = client.getSelectedObject MapBlockObject *selected_object = client.getSelectedObject
(d*BS, camera_position, shootline); (d*BS, camera_position, shootline);
/* ClientActiveObject *selected_active_object
If it's pointing to a MapBlockObject = client.getSelectedActiveObject
*/ (d*BS, camera_position, shootline);
if(selected_object != NULL) 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 else // selected_object == NULL
{ {

@ -99,6 +99,9 @@ void NodeMetadata::registerType(u16 id, Factory f)
SignNodeMetadata SignNodeMetadata
*/ */
// Prototype
SignNodeMetadata proto_SignNodeMetadata("");
SignNodeMetadata::SignNodeMetadata(std::string text): SignNodeMetadata::SignNodeMetadata(std::string text):
m_text(text) m_text(text)
{ {
@ -130,6 +133,9 @@ std::string SignNodeMetadata::infoText()
ChestNodeMetadata ChestNodeMetadata
*/ */
// Prototype
ChestNodeMetadata proto_ChestNodeMetadata;
ChestNodeMetadata::ChestNodeMetadata() ChestNodeMetadata::ChestNodeMetadata()
{ {
NodeMetadata::registerType(typeId(), create); NodeMetadata::registerType(typeId(), create);
@ -182,6 +188,9 @@ bool ChestNodeMetadata::nodeRemovalDisabled()
FurnaceNodeMetadata FurnaceNodeMetadata
*/ */
// Prototype
FurnaceNodeMetadata proto_FurnaceNodeMetadata;
FurnaceNodeMetadata::FurnaceNodeMetadata() FurnaceNodeMetadata::FurnaceNodeMetadata()
{ {
NodeMetadata::registerType(typeId(), create); NodeMetadata::registerType(typeId(), create);

@ -1222,7 +1222,7 @@ void Server::AsyncRunStep()
//u16 peer_id = i.getNode()->getKey(); //u16 peer_id = i.getNode()->getKey();
RemoteClient *client = i.getNode()->getValue(); RemoteClient *client = i.getNode()->getValue();
Player *player = m_env.getPlayer(client->peer_id); Player *player = m_env.getPlayer(client->peer_id);
std::cout<<player->getName()<<" "; std::cout<<player->getName()<<"\t";
client->PrintInfo(std::cout); client->PrintInfo(std::cout);
} }
} }
@ -1235,6 +1235,8 @@ void Server::AsyncRunStep()
Check added and deleted active objects Check added and deleted active objects
*/ */
{ {
//dstream<<"Server: Checking added and deleted active objects"<<std::endl;
JMutexAutoLock envlock(m_env_mutex); JMutexAutoLock envlock(m_env_mutex);
JMutexAutoLock conlock(m_con_mutex); JMutexAutoLock conlock(m_con_mutex);
@ -1248,7 +1250,11 @@ void Server::AsyncRunStep()
RemoteClient *client = i.getNode()->getValue(); RemoteClient *client = i.getNode()->getValue();
Player *player = m_env.getPlayer(client->peer_id); Player *player = m_env.getPlayer(client->peer_id);
if(player==NULL) if(player==NULL)
{
dstream<<"WARNING: "<<__FUNCTION_NAME<<": Client "<<client->peer_id
<<" has no associated player"<<std::endl;
continue; continue;
}
v3s16 pos = floatToInt(player->getPosition(), BS); v3s16 pos = floatToInt(player->getPosition(), BS);
core::map<u16, bool> removed_objects; core::map<u16, bool> removed_objects;
@ -1260,7 +1266,10 @@ void Server::AsyncRunStep()
// Ignore if nothing happened // Ignore if nothing happened
if(removed_objects.size() == 0 && added_objects.size() == 0) if(removed_objects.size() == 0 && added_objects.size() == 0)
{
//dstream<<"INFO: active objects: none changed"<<std::endl;
continue; continue;
}
std::string data_buffer; std::string data_buffer;

@ -285,7 +285,7 @@ public:
void PrintInfo(std::ostream &o) void PrintInfo(std::ostream &o)
{ {
o<<"RemoteClient "<<peer_id<<": " 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_blocks_sending.size()="<<m_blocks_sending.size()
<<", m_nearest_unsent_d="<<m_nearest_unsent_d <<", m_nearest_unsent_d="<<m_nearest_unsent_d
<<", m_excess_gotblocks="<<m_excess_gotblocks <<", m_excess_gotblocks="<<m_excess_gotblocks

@ -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;
}

@ -87,10 +87,12 @@ public:
// Number of players which know about this object // Number of players which know about this object
u16 m_known_by_count; u16 m_known_by_count;
/* /*
Whether this object is to be removed when nobody knows about - Whether this object is to be removed when nobody knows about
it anymore. it anymore.
Removal is delayed to preserve the id for the time during which - Removal is delayed to preserve the id for the time during which
it could be confused to some other object by some client. 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; bool m_removed;
@ -113,5 +115,20 @@ private:
float m_age; 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 #endif