// making some copypasta
{}
+ if(command == TOCLIENT_REMOVENODE)
+ {
+ if(datasize < 8)
+ return;
+ v3s16 p;
+ p.X = readS16(&data[2]);
+ p.Y = readS16(&data[4]);
+ p.Z = readS16(&data[6]);
+
+ //TimeTaker t1("TOCLIENT_REMOVENODE", g_device);
+
+ // This will clear the cracking animation after digging
+ ((ClientMap&)m_env.getMap()).clearTempMod(p);
+
+ removeNode(p);
+ }
+ else if(command == TOCLIENT_ADDNODE)
+ {
+ if(datasize < 8 + MapNode::serializedLength(ser_version))
+ return;
+
+ v3s16 p;
+ p.X = readS16(&data[2]);
+ p.Y = readS16(&data[4]);
+ p.Z = readS16(&data[6]);
+
+ //TimeTaker t1("TOCLIENT_ADDNODE", g_device);
+
+ MapNode n;
+ n.deSerialize(&data[8], ser_version);
+
+ addNode(p, n);
+ }
if(command == TOCLIENT_PLAYERPOS)
{
dstream<<"WARNING: Received deprecated TOCLIENT_PLAYERPOS"
/*
Returns true if there was something in queue
*/
-bool Client::AsyncProcessPacket(LazyMeshUpdater &mesh_updater)
+bool Client::AsyncProcessPacket()
{
DSTACK(__FUNCTION_NAME);
ToClientCommand command = (ToClientCommand)readU16(&data[0]);
- if(command == TOCLIENT_REMOVENODE)
- {
- if(datasize < 8)
- return true;
- v3s16 p;
- p.X = readS16(&data[2]);
- p.Y = readS16(&data[4]);
- p.Z = readS16(&data[6]);
-
- //TimeTaker t1("TOCLIENT_REMOVENODE", g_device);
-
- // This will clear the cracking animation after digging
- ((ClientMap&)m_env.getMap()).clearTempMod(p);
-
- removeNode(p);
- }
- else if(command == TOCLIENT_ADDNODE)
- {
- if(datasize < 8 + MapNode::serializedLength(ser_version))
- return true;
-
- v3s16 p;
- p.X = readS16(&data[2]);
- p.Y = readS16(&data[4]);
- p.Z = readS16(&data[6]);
-
- //TimeTaker t1("TOCLIENT_ADDNODE", g_device);
-
- MapNode n;
- n.deSerialize(&data[8], ser_version);
-
- addNode(p, n);
- }
- else if(command == TOCLIENT_BLOCKDATA)
+ if(command == TOCLIENT_BLOCKDATA)
{
// Ignore too small packet
if(datasize < 8)
{
for(;;)
{
- // We want to update the meshes as soon as a single packet has
- // been processed
- LazyMeshUpdater mesh_updater(&m_env);
- bool r = AsyncProcessPacket(mesh_updater);
+ bool r = AsyncProcessPacket();
if(r == false)
break;
}
return false;
-
- /*LazyMeshUpdater mesh_updater(&m_env);
- for(;;)
- {
- bool r = AsyncProcessPacket(mesh_updater);
- if(r == false)
- break;
- }
- return false;*/
-
}
void Client::Send(u16 channelnum, SharedBuffer<u8> data, bool reliable)
m_con.Send(PEER_ID_SERVER, channelnum, data, reliable);
}
-#if 0
-void Client::fetchBlock(v3s16 p, u8 flags)
-{
- if(connectedAndInitialized() == false)
- throw ClientNotReadyException
- ("ClientNotReadyException: connectedAndInitialized() == false");
-
- /*dstream<<"Client::fetchBlock(): Sending GETBLOCK for ("
- <<p.X<<","<<p.Y<<","<<p.Z<<")"<<std::endl;*/
-
- JMutexAutoLock conlock(m_con_mutex);
-
- SharedBuffer<u8> data(9);
- writeU16(&data[0], TOSERVER_GETBLOCK);
- writeS16(&data[2], p.X);
- writeS16(&data[4], p.Y);
- writeS16(&data[6], p.Z);
- writeU8(&data[8], flags);
- m_con.Send(PEER_ID_SERVER, 1, data, true);
-}
-
-/*
- Calls fetchBlock() on some nearby missing blocks.
-
- Returns when any of various network load indicators go over limit.
-
- Does nearly the same thing as the old updateChangedVisibleArea()
-*/
-void Client::fetchBlocks()
-{
- if(connectedAndInitialized() == false)
- throw ClientNotReadyException
- ("ClientNotReadyException: connectedAndInitialized() == false");
-}
-#endif
-
bool Client::isFetchingBlocks()
{
JMutexAutoLock conlock(m_con_mutex);
}
/*
- [0] u16 command
+ [0] u16 command=TOSERVER_CLICK_OBJECT
[2] u8 button (0=left, 1=right)
[3] v3s16 block
[9] s16 id
s32 *m_refcount;
};
-// TODO: Remove this. It is not used as supposed.
-class LazyMeshUpdater
-{
-public:
- LazyMeshUpdater(Environment *env)
- {
- m_env = env;
- }
- ~LazyMeshUpdater()
- {
- /*
- TODO: This could be optimized. It will currently
- double-update some blocks.
- */
- for(core::map<v3s16, bool>::Iterator
- i = m_blocks.getIterator();
- i.atEnd() == false; i++)
- {
- v3s16 p = i.getNode()->getKey();
- m_env->updateMeshes(p);
- }
- m_blocks.clear();
- }
- void add(v3s16 p)
- {
- m_blocks.insert(p, true);
- }
-private:
- Environment *m_env;
- core::map<v3s16, bool> m_blocks;
-};
-
class Client : public con::PeerHandler
{
public:
void ProcessData(u8 *data, u32 datasize, u16 sender_peer_id);
// Returns true if something was received
- bool AsyncProcessPacket(LazyMeshUpdater &mesh_updater);
+ bool AsyncProcessPacket();
bool AsyncProcessData();
void Send(u16 channelnum, SharedBuffer<u8> data, bool reliable);
std::getline(is, inventorystring, '|');
return new MapBlockObjectItem(inventorystring);
}
+ else if(name == "ToolItem")
+ {
+ std::string toolname;
+ std::getline(is, toolname, ' ');
+ u16 wear;
+ is>>wear;
+ return new ToolItem(toolname, wear);
+ }
else
{
dstream<<"Unknown InventoryItem name=\""<<name<<"\""<<std::endl;
RatObject *obj = new RatObject(NULL, -1, pos);
return obj;
}
+ else if(name == "ItemObj")
+ {
+ /*
+ Now we are an inventory item containing the serialization
+ string of an object that contains the serialization
+ string of an inventory item. Fuck this.
+ */
+ //assert(0);
+ dstream<<__FUNCTION_NAME<<": WARNING: Ignoring ItemObj "
+ <<"because an item-object should never be inside "
+ <<"an object-item."<<std::endl;
+ return NULL;
+ }
else
{
return NULL;
std::string m_inventorystring;
};
+class ToolItem : public InventoryItem
+{
+public:
+ ToolItem(std::string toolname, u16 wear)
+ {
+ m_toolname = toolname;
+ m_wear = wear;
+ }
+ /*
+ Implementation interface
+ */
+ virtual const char* getName() const
+ {
+ return "ToolItem";
+ }
+ virtual void serialize(std::ostream &os)
+ {
+ os<<getName();
+ os<<" ";
+ os<<m_toolname;
+ os<<" ";
+ os<<m_wear;
+ }
+ virtual InventoryItem* clone()
+ {
+ return new ToolItem(m_toolname, m_wear);
+ }
+#ifndef SERVER
+ video::ITexture * getImage()
+ {
+ if(m_toolname == "WPick")
+ return g_irrlicht->getTexture("../data/tool_wpick.png");
+ if(m_toolname == "STPick")
+ return g_irrlicht->getTexture("../data/tool_stpick.png");
+ // Default to cloud texture
+ return g_irrlicht->getTexture(tile_texture_path_get(TILE_CLOUD));
+ }
+#endif
+ std::string getText()
+ {
+ std::ostringstream os;
+ u16 f = 4;
+ u16 d = 65535/f;
+ u16 i;
+ for(i=0; i<(65535-m_wear)/d; i++)
+ os<<'X';
+ for(; i<f; i++)
+ os<<'-';
+ return os.str();
+
+ /*std::ostringstream os;
+ os<<m_toolname;
+ os<<" ";
+ os<<(m_wear/655);
+ return os.str();*/
+ }
+ /*
+ Special methods
+ */
+ std::string getToolName()
+ {
+ return m_toolname;
+ }
+ u16 getWear()
+ {
+ return m_wear;
+ }
+private:
+ std::string m_toolname;
+ u16 m_wear;
+};
+
class InventoryList
{
public:
main network eater of this system, so it is the one that has\r
to be throttled so that RTTs stay low.\r
\r
+SUGG: Meshes of blocks could be split into 6 meshes facing into\r
+ different directions and then only those drawn that need to be\r
+ - Also an 1-dimensional tile map would be nice probably\r
+\r
TODO: Untie client network operations from framerate\r
- Needs some input queues or something\r
- Not really necessary?\r
Doing now:\r
======================================================================\r
\r
-TODO: Convert the text input system to use a modal menu... or something\r
+TODO: Tool items\r
+\r
+- Actually, tool items should be just a little special MapBlockItems\r
\r
======================================================================\r
\r
Random stuff\r
*/\r
\r
-//u16 g_selected_material = 0;\r
-u16 g_selected_item = 0;\r
-\r
IrrlichtDevice *g_device = NULL;\r
Client *g_client = NULL;\r
\r
// This is a copy of the inventory that the client's environment has\r
Inventory local_inventory;\r
\r
+u16 g_selected_item = 0;\r
+\r
/*\r
Debug streams\r
*/\r
MapBlockObject *selected_object = client.getSelectedObject\r
(d*BS, camera_position, shootline);\r
\r
+ /*\r
+ If it's pointing to a MapBlockObject\r
+ */\r
+\r
if(selected_object != NULL)\r
{\r
//dstream<<"Client returned selected_object != NULL"<<std::endl;\r
} // regular block\r
} // for coords\r
\r
+ static float nodig_delay_counter = 0.0;\r
+\r
if(nodefound)\r
{\r
static v3s16 nodepos_old(-32768,-32768,-32768);\r
static float dig_time = 0.0;\r
static u16 dig_index = 0;\r
\r
- if(nodepos != nodepos_old)\r
- {\r
- std::cout<<DTIME<<"Pointing at ("<<nodepos.X<<","\r
- <<nodepos.Y<<","<<nodepos.Z<<")"<<std::endl;\r
-\r
- if(nodepos_old != v3s16(-32768,-32768,-32768))\r
- {\r
- client.clearTempMod(nodepos_old);\r
- dig_time = 0.0;\r
- }\r
- }\r
-\r
hilightboxes.push_back(nodefacebox);\r
\r
if(g_input->getLeftReleased())\r
client.clearTempMod(nodepos);\r
dig_time = 0.0;\r
}\r
- if(g_input->getLeftClicked() ||\r
- (g_input->getLeftState() && nodepos != nodepos_old))\r
- {\r
- dstream<<DTIME<<"Started digging"<<std::endl;\r
- client.groundAction(0, nodepos, neighbourpos, g_selected_item);\r
- }\r
- if(g_input->getLeftClicked())\r
+ \r
+ if(nodig_delay_counter > 0.0)\r
{\r
- client.setTempMod(nodepos, NodeMod(NODEMOD_CRACK, 0));\r
+ nodig_delay_counter -= dtime;\r
}\r
- if(g_input->getLeftState())\r
+ else\r
{\r
- MapNode n = client.getNode(nodepos);\r
+ if(nodepos != nodepos_old)\r
+ {\r
+ std::cout<<DTIME<<"Pointing at ("<<nodepos.X<<","\r
+ <<nodepos.Y<<","<<nodepos.Z<<")"<<std::endl;\r
\r
- // TODO: Get this from some table that is sent by server\r
- float dig_time_complete = 0.5;\r
- if(n.d == CONTENT_STONE)\r
- dig_time_complete = 1.5;\r
- \r
- dig_index = (u16)((float)CRACK_ANIMATION_LENGTH\r
- * dig_time/dig_time_complete);\r
+ if(nodepos_old != v3s16(-32768,-32768,-32768))\r
+ {\r
+ client.clearTempMod(nodepos_old);\r
+ dig_time = 0.0;\r
+ }\r
+ }\r
\r
- if(dig_index < CRACK_ANIMATION_LENGTH)\r
+ if(g_input->getLeftClicked() ||\r
+ (g_input->getLeftState() && nodepos != nodepos_old))\r
{\r
- //dstream<<"dig_index="<<dig_index<<std::endl;\r
- client.setTempMod(nodepos, NodeMod(NODEMOD_CRACK, dig_index));\r
+ dstream<<DTIME<<"Started digging"<<std::endl;\r
+ client.groundAction(0, nodepos, neighbourpos, g_selected_item);\r
}\r
- else\r
+ if(g_input->getLeftClicked())\r
{\r
- dstream<<DTIME<<"Digging completed"<<std::endl;\r
- client.groundAction(3, nodepos, neighbourpos, g_selected_item);\r
- client.clearTempMod(nodepos);\r
- client.removeNode(nodepos);\r
+ client.setTempMod(nodepos, NodeMod(NODEMOD_CRACK, 0));\r
}\r
+ if(g_input->getLeftState())\r
+ {\r
+ MapNode n = client.getNode(nodepos);\r
+\r
+ // TODO: Get this from some table that is sent by server\r
+ float dig_time_complete = 0.5;\r
+ if(n.d == CONTENT_STONE || n.d == CONTENT_COALSTONE)\r
+ {\r
+ dig_time_complete = 10.0;\r
+\r
+ InventoryList *mlist = local_inventory.getList("main");\r
+ if(mlist != NULL)\r
+ {\r
+ InventoryItem *item = mlist->getItem(g_selected_item);\r
+ if((std::string)item->getName() == "ToolItem")\r
+ {\r
+ ToolItem *titem = (ToolItem*)item;\r
+ if(titem->getToolName() == "WPick")\r
+ {\r
+ dig_time_complete = 1.2;\r
+ }\r
+ else if(titem->getToolName() == "STPick")\r
+ {\r
+ dig_time_complete = 0.6;\r
+ }\r
+ }\r
+ }\r
+ }\r
+ \r
+ dig_index = (u16)((float)CRACK_ANIMATION_LENGTH\r
+ * dig_time/dig_time_complete);\r
\r
- dig_time += dtime;\r
+ if(dig_index < CRACK_ANIMATION_LENGTH)\r
+ {\r
+ //dstream<<"dig_index="<<dig_index<<std::endl;\r
+ client.setTempMod(nodepos, NodeMod(NODEMOD_CRACK, dig_index));\r
+ }\r
+ else\r
+ {\r
+ dstream<<DTIME<<"Digging completed"<<std::endl;\r
+ client.groundAction(3, nodepos, neighbourpos, g_selected_item);\r
+ client.clearTempMod(nodepos);\r
+ client.removeNode(nodepos);\r
+\r
+ dig_time = 0;\r
+\r
+ nodig_delay_counter = dig_time_complete\r
+ / (float)CRACK_ANIMATION_LENGTH;\r
+ }\r
+\r
+ dig_time += dtime;\r
+ }\r
}\r
\r
if(g_input->getRightClicked())\r
#include "mapblock.h"
// Only for ::getNodeBox, TODO: Get rid of this
#include "map.h"
+#include "inventory.h"
+#include "irrlichtwrapper.h"
/*
MapBlockObject
}
#endif
+/*
+ ItemObject
+*/
#ifndef SERVER
+void ItemObject::addToScene(scene::ISceneManager *smgr)
+{
+ if(m_node != NULL)
+ return;
+
+ //video::IVideoDriver* driver = smgr->getVideoDriver();
+
+ // Get image of item for showing
+ video::ITexture *texture = getItemImage();
+
+ /*
+ Create a mesh
+ */
+
+ 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/2,0, 0,0,0, c, 0,1),
+ video::S3DVertex(-BS/2,-BS/2,0, 0,0,0, c, 1,1),
+ video::S3DVertex(-BS/2,BS/2,0, 0,0,0, c, 1,0),
+ video::S3DVertex(BS/2,BS/2,0, 0,0,0, c, 0,0),*/
+ video::S3DVertex(BS/3,-BS/2,0, 0,0,0, c, 0,1),
+ video::S3DVertex(-BS/3,-BS/2,0, 0,0,0, c, 1,1),
+ video::S3DVertex(-BS/3,-BS/2+BS*2/3,0, 0,0,0, c, 1,0),
+ video::S3DVertex(BS/3,-BS/2+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, texture);
+ buf->getMaterial().setFlag(video::EMF_BILINEAR_FILTER, false);
+ buf->getMaterial().setFlag(video::EMF_FOG_ENABLE, true);
+ buf->getMaterial().MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF;
+ // Add to mesh
+ mesh->addMeshBuffer(buf);
+ buf->drop();
+ }
+ m_node = smgr->addMeshSceneNode(mesh, NULL);
+ // Set it to use the materials of the meshbuffers directly.
+ // This is needed for changing the texture in the future
+ ((scene::IMeshSceneNode*)m_node)->setReadOnlyMaterials(true);
+ mesh->drop();
+
+ updateSceneNode();
+}
+
+video::ITexture * ItemObject::getItemImage()
+{
+ /*
+ Create an inventory item to see what is its image
+ */
+ video::ITexture *texture = NULL;
+ InventoryItem *item = createInventoryItem();
+ if(item)
+ texture = item->getImage();
+ /*else
+ texture = g_irrlicht->getTexture("../data/cloud.png");*/
+ if(item)
+ delete item;
+ return texture;
+}
+
+#endif
+
+InventoryItem * ItemObject::createInventoryItem()
+{
+ try{
+ std::istringstream is(m_itemstring, std::ios_base::binary);
+ InventoryItem *item = InventoryItem::deSerialize(is);
+ dstream<<__FUNCTION_NAME<<": m_itemstring=\""
+ <<m_itemstring<<"\" -> item="<<item
+ <<std::endl;
+ return item;
+ }
+ catch(SerializationError &e)
+ {
+ dstream<<__FUNCTION_NAME<<": serialization error: "
+ <<"m_itemstring=\""<<m_itemstring<<"\""<<std::endl;
+ return NULL;
+ }
+}
+
/*
PlayerObject
*/
+#ifndef SERVER
void PlayerObject::addToScene(scene::ISceneManager *smgr)
{
if(m_node != NULL)
{
obj = new RatObject(m_block, id, pos);
}
+ else if(type_id == MAPBLOCKOBJECT_TYPE_ITEM)
+ {
+ obj = new ItemObject(m_block, id, pos);
+ }
else
{
// This is fatal because we cannot know the length
#define MAPBLOCKOBJECT_TYPE_PLAYER 0
#define MAPBLOCKOBJECT_TYPE_SIGN 2
#define MAPBLOCKOBJECT_TYPE_RAT 3
+#define MAPBLOCKOBJECT_TYPE_ITEM 4
// Used for handling selecting special stuff
//#define MAPBLOCKOBJECT_TYPE_PSEUDO 1000
float m_age;
};
+/*
+ An object on the map that represents an inventory item
+*/
+
+class InventoryItem;
+
+class ItemObject : public MapBlockObject
+{
+public:
+ // The constructor of every MapBlockObject should be like this
+ ItemObject(MapBlock *block, s16 id, v3f pos):
+ MapBlockObject(block, id, pos),
+ m_node(NULL)
+ {
+ /*m_selection_box = new core::aabbox3d<f32>
+ (-BS*0.4,-BS*0.5,-BS*0.4, BS*0.4,BS*0.5,BS*0.4);*/
+ m_selection_box = new core::aabbox3d<f32>
+ (-BS/3,-BS/2,-BS/3, BS/3,-BS/2+BS*2/3,BS/3);
+ m_yaw = 0.0;
+ }
+ virtual ~ItemObject()
+ {
+ delete m_selection_box;
+ }
+
+ /*
+ Implementation interface
+ */
+ virtual u16 getTypeId() const
+ {
+ return MAPBLOCKOBJECT_TYPE_ITEM;
+ }
+ virtual void serialize(std::ostream &os, u8 version)
+ {
+ serializeBase(os, version);
+ u8 buf[2];
+
+ // Write text length
+ writeU16(buf, m_itemstring.size());
+ os.write((char*)buf, 2);
+
+ // Write text
+ os.write(m_itemstring.c_str(), m_itemstring.size());
+ }
+ virtual void update(std::istream &is, u8 version)
+ {
+ u8 buf[2];
+
+ // Read text length
+ is.read((char*)buf, 2);
+ u16 size = readU16(buf);
+
+ // Read text
+ std::string old_itemstring = m_itemstring;
+ m_itemstring.clear();
+ for(u16 i=0; i<size; i++)
+ {
+ is.read((char*)buf, 1);
+ m_itemstring += buf[0];
+ }
+
+#ifndef SERVER
+ if(m_itemstring != old_itemstring && m_node)
+ {
+ /*
+ Update texture
+ */
+ video::ITexture *texture = getItemImage();
+ scene::IMesh *mesh = m_node->getMesh();
+ if(mesh->getMeshBufferCount() >= 1)
+ {
+ scene::IMeshBuffer *buf = mesh->getMeshBuffer(0);
+ //dstream<<"Setting texture "<<texture<<std::endl;
+ buf->getMaterial().setTexture(0, texture);
+ }
+ }
+
+ updateSceneNode();
+#endif
+ }
+
+ virtual bool serverStep(float dtime, u32 daynight_ratio)
+ {
+ return false;
+ }
+
+#ifndef SERVER
+ virtual void clientStep(float dtime)
+ {
+ m_yaw += dtime * 90;
+ if(m_yaw >= 360.)
+ m_yaw -= 360.;
+
+ updateSceneNode();
+ }
+
+ virtual void addToScene(scene::ISceneManager *smgr);
+
+ virtual void removeFromScene()
+ {
+ if(m_node != NULL)
+ {
+ m_node->remove();
+ m_node = NULL;
+ }
+ }
+ virtual void updateLight(u8 light_at_pos)
+ {
+ if(m_node == NULL)
+ return;
+
+ u8 li = decode_light(light_at_pos);
+ video::SColor color(255,li,li,li);
+
+ scene::IMesh *mesh = m_node->getMesh();
+
+ u16 mc = mesh->getMeshBufferCount();
+ for(u16 j=0; j<mc; j++)
+ {
+ scene::IMeshBuffer *buf = mesh->getMeshBuffer(j);
+ video::S3DVertex *vertices = (video::S3DVertex*)buf->getVertices();
+ u16 vc = buf->getVertexCount();
+ for(u16 i=0; i<vc; i++)
+ {
+ vertices[i].Color = color;
+ }
+ }
+ }
+#endif
+
+ virtual std::string infoText()
+ {
+ return std::string("\"") + m_itemstring + "\"";
+ }
+
+ virtual std::string getInventoryString()
+ {
+ return std::string("ItemObj ")+m_itemstring;
+ }
+
+ /*
+ Special methods
+ */
+
+ InventoryItem * createInventoryItem();
+
+#ifndef SERVER
+ video::ITexture * getItemImage();
+
+ void updateSceneNode()
+ {
+ if(m_node != NULL)
+ {
+ m_node->setPosition(getAbsolutePos());
+ m_node->setRotation(v3f(0, m_yaw, 0));
+ }
+ }
+#endif
+
+ void setItemString(std::string inventorystring)
+ {
+ m_itemstring = inventorystring;
+ setBlockChanged();
+ }
+
+ std::string getItemString()
+ {
+ return m_itemstring;
+ }
+
+protected:
+ scene::IMeshSceneNode *m_node;
+ std::string m_itemstring;
+ f32 m_yaw;
+};
+
/*
NOTE: Not used.
*/
}
catch(InvalidPositionException &e)
{
- derr_server<<"PICK_OBJECT block not found"<<std::endl;
+ derr_server<<"CLICK_OBJECT block not found"<<std::endl;
return;
}
if(obj == NULL)
{
- derr_server<<"PICK_OBJECT object not found"<<std::endl;
+ derr_server<<"CLICK_OBJECT object not found"<<std::endl;
return;
}
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->getTypeId() == MAPBLOCKOBJECT_TYPE_ITEM)
+ {
+ item = ((ItemObject*)obj)->createInventoryItem();
+ }
+ // Else create an item of the object
+ else
+ {
+ item = new MapBlockObjectItem
+ (obj->getInventoryString());
+ }
+
// Add to inventory and send inventory
- InventoryItem *item = new MapBlockObjectItem
- (obj->getInventoryString());
ilist->addItem(item);
SendInventory(player->peer_id);
}
v.blitBack(modified_blocks);
}
/*
- Handle block object items
+ Handle other items
*/
- else if(std::string("MBOItem") == item->getName())
+ else
{
- MapBlockObjectItem *oitem = (MapBlockObjectItem*)item;
-
- /*dout_server<<"Trying to place a MapBlockObjectItem: "
- "inventorystring=\""
- <<oitem->getInventoryString()
- <<"\""<<std::endl;*/
-
v3s16 blockpos = getNodeBlockPos(p_over);
MapBlock *block = NULL;
<<"("<<pos.X<<","<<pos.Y<<","<<pos.Z<<")"
<<std::endl;*/
+ MapBlockObject *obj = NULL;
- MapBlockObject *obj = oitem->createObject
- (pos, player->getYaw(), player->getPitch());
+ /*
+ 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());
+ }
+ /*
+ Handle other items
+ */
+ 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;
+ }
if(obj == NULL)
- derr_server<<"WARNING: oitem created NULL object"
+ {
+ derr_server<<"WARNING: item resulted in NULL object, "
+ <<"not placing onto map"
<<std::endl;
+ }
+ else
+ {
+ block->addObject(obj);
- block->addObject(obj);
-
- //dout_server<<"Placed object"<<std::endl;
+ dout_server<<"Placed object"<<std::endl;
- InventoryList *ilist = player->inventory.getList("main");
- if(g_settings.getBool("creative_mode") == false && ilist)
- {
- // Remove from inventory and send inventory
- ilist->deleteItem(item_i);
- // Send inventory
- SendInventory(peer_id);
+ InventoryList *ilist = player->inventory.getList("main");
+ if(g_settings.getBool("creative_mode") == false && ilist)
+ {
+ // Remove from inventory and send inventory
+ ilist->deleteItem(item_i);
+ // Send inventory
+ SendInventory(peer_id);
+ }
}
}
if(g_settings.getBool("creative_mode"))
{
+ // Give a good pick
+ {
+ InventoryItem *item = new ToolItem("STPick", 32000);
+ bool r = player->inventory.addItem("main", item);
+ assert(r == true);
+ }
// Give all materials
assert(USEFUL_CONTENT_COUNT <= PLAYER_INVENTORY_SIZE);
for(u16 i=0; i<USEFUL_CONTENT_COUNT; i++)
}
else
{
+ {
+ InventoryItem *item = new ToolItem("WPick", 32000);
+ bool r = player->inventory.addItem("main", item);
+ assert(r == true);
+ }
+ {
+ InventoryItem *item = new ToolItem("STPick", 32000);
+ bool r = player->inventory.addItem("main", item);
+ assert(r == true);
+ }
/*// Give some lights
{
InventoryItem *item = new MaterialItem(CONTENT_TORCH, 999);