diff options
-rw-r--r-- | data/sign.png | bin | 1378 -> 1374 bytes | |||
-rw-r--r-- | src/client.cpp | 123 | ||||
-rw-r--r-- | src/client.h | 34 | ||||
-rw-r--r-- | src/inventory.cpp | 21 | ||||
-rw-r--r-- | src/inventory.h | 72 | ||||
-rw-r--r-- | src/main.cpp | 128 | ||||
-rw-r--r-- | src/mapblockobject.cpp | 97 | ||||
-rw-r--r-- | src/mapblockobject.h | 177 | ||||
-rw-r--r-- | src/server.cpp | 113 |
9 files changed, 577 insertions, 188 deletions
diff --git a/data/sign.png b/data/sign.png Binary files differindex fc9081adf..2e0b3cbef 100644 --- a/data/sign.png +++ b/data/sign.png diff --git a/src/client.cpp b/src/client.cpp index ff40f674f..f9cccd855 100644 --- a/src/client.cpp +++ b/src/client.cpp @@ -568,6 +568,39 @@ void Client::ProcessData(u8 *data, u32 datasize, u16 sender_peer_id) // 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" @@ -1023,7 +1056,7 @@ void Client::ProcessData(u8 *data, u32 datasize, u16 sender_peer_id) /* Returns true if there was something in queue */ -bool Client::AsyncProcessPacket(LazyMeshUpdater &mesh_updater) +bool Client::AsyncProcessPacket() { DSTACK(__FUNCTION_NAME); @@ -1053,40 +1086,7 @@ bool Client::AsyncProcessPacket(LazyMeshUpdater &mesh_updater) 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) @@ -1226,24 +1226,11 @@ bool Client::AsyncProcessData() { 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) @@ -1252,42 +1239,6 @@ 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); @@ -1369,7 +1320,7 @@ void Client::clickObject(u8 button, v3s16 blockpos, s16 id, u16 item) } /* - [0] u16 command + [0] u16 command=TOSERVER_CLICK_OBJECT [2] u8 button (0=left, 1=right) [3] v3s16 block [9] s16 id diff --git a/src/client.h b/src/client.h index 6fb608b84..b29358d93 100644 --- a/src/client.h +++ b/src/client.h @@ -101,38 +101,6 @@ struct IncomingPacket 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: @@ -175,7 +143,7 @@ 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); diff --git a/src/inventory.cpp b/src/inventory.cpp index 073477dde..332f9d999 100644 --- a/src/inventory.cpp +++ b/src/inventory.cpp @@ -66,6 +66,14 @@ InventoryItem* InventoryItem::deSerialize(std::istream &is) 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; @@ -126,6 +134,19 @@ MapBlockObject * MapBlockObjectItem::createObject 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; diff --git a/src/inventory.h b/src/inventory.h index ad3b297e8..e97db8ffb 100644 --- a/src/inventory.h +++ b/src/inventory.h @@ -196,6 +196,78 @@ private: 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: diff --git a/src/main.cpp b/src/main.cpp index cfc47bbb2..29ff2748c 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -105,6 +105,10 @@ SUGG: Make the amount of blocks sending to client and the total main network eater of this system, so it is the one that has
to be throttled so that RTTs stay low.
+SUGG: Meshes of blocks could be split into 6 meshes facing into
+ different directions and then only those drawn that need to be
+ - Also an 1-dimensional tile map would be nice probably
+
TODO: Untie client network operations from framerate
- Needs some input queues or something
- Not really necessary?
@@ -173,7 +177,9 @@ TODO: Check if the usage of Client::isFetchingBlocks() in Doing now:
======================================================================
-TODO: Convert the text input system to use a modal menu... or something
+TODO: Tool items
+
+- Actually, tool items should be just a little special MapBlockItems
======================================================================
@@ -269,9 +275,6 @@ extern void set_default_settings(); Random stuff
*/
-//u16 g_selected_material = 0;
-u16 g_selected_item = 0;
-
IrrlichtDevice *g_device = NULL;
Client *g_client = NULL;
@@ -292,6 +295,8 @@ Queue<InventoryAction*> inventory_action_queue; // This is a copy of the inventory that the client's environment has
Inventory local_inventory;
+u16 g_selected_item = 0;
+
/*
Debug streams
*/
@@ -1833,6 +1838,10 @@ int main(int argc, char *argv[]) MapBlockObject *selected_object = client.getSelectedObject
(d*BS, camera_position, shootline);
+ /*
+ If it's pointing to a MapBlockObject
+ */
+
if(selected_object != NULL)
{
//dstream<<"Client returned selected_object != NULL"<<std::endl;
@@ -2041,6 +2050,8 @@ int main(int argc, char *argv[]) } // regular block
} // for coords
+ static float nodig_delay_counter = 0.0;
+
if(nodefound)
{
static v3s16 nodepos_old(-32768,-32768,-32768);
@@ -2048,18 +2059,6 @@ int main(int argc, char *argv[]) static float dig_time = 0.0;
static u16 dig_index = 0;
- if(nodepos != nodepos_old)
- {
- std::cout<<DTIME<<"Pointing at ("<<nodepos.X<<","
- <<nodepos.Y<<","<<nodepos.Z<<")"<<std::endl;
-
- if(nodepos_old != v3s16(-32768,-32768,-32768))
- {
- client.clearTempMod(nodepos_old);
- dig_time = 0.0;
- }
- }
-
hilightboxes.push_back(nodefacebox);
if(g_input->getLeftReleased())
@@ -2067,42 +2066,87 @@ int main(int argc, char *argv[]) client.clearTempMod(nodepos);
dig_time = 0.0;
}
- if(g_input->getLeftClicked() ||
- (g_input->getLeftState() && nodepos != nodepos_old))
- {
- dstream<<DTIME<<"Started digging"<<std::endl;
- client.groundAction(0, nodepos, neighbourpos, g_selected_item);
- }
- if(g_input->getLeftClicked())
+
+ if(nodig_delay_counter > 0.0)
{
- client.setTempMod(nodepos, NodeMod(NODEMOD_CRACK, 0));
+ nodig_delay_counter -= dtime;
}
- if(g_input->getLeftState())
+ else
{
- MapNode n = client.getNode(nodepos);
+ if(nodepos != nodepos_old)
+ {
+ std::cout<<DTIME<<"Pointing at ("<<nodepos.X<<","
+ <<nodepos.Y<<","<<nodepos.Z<<")"<<std::endl;
- // TODO: Get this from some table that is sent by server
- float dig_time_complete = 0.5;
- if(n.d == CONTENT_STONE)
- dig_time_complete = 1.5;
-
- dig_index = (u16)((float)CRACK_ANIMATION_LENGTH
- * dig_time/dig_time_complete);
+ if(nodepos_old != v3s16(-32768,-32768,-32768))
+ {
+ client.clearTempMod(nodepos_old);
+ dig_time = 0.0;
+ }
+ }
- if(dig_index < CRACK_ANIMATION_LENGTH)
+ if(g_input->getLeftClicked() ||
+ (g_input->getLeftState() && nodepos != nodepos_old))
{
- //dstream<<"dig_index="<<dig_index<<std::endl;
- client.setTempMod(nodepos, NodeMod(NODEMOD_CRACK, dig_index));
+ dstream<<DTIME<<"Started digging"<<std::endl;
+ client.groundAction(0, nodepos, neighbourpos, g_selected_item);
}
- else
+ if(g_input->getLeftClicked())
{
- dstream<<DTIME<<"Digging completed"<<std::endl;
- client.groundAction(3, nodepos, neighbourpos, g_selected_item);
- client.clearTempMod(nodepos);
- client.removeNode(nodepos);
+ client.setTempMod(nodepos, NodeMod(NODEMOD_CRACK, 0));
}
+ if(g_input->getLeftState())
+ {
+ MapNode n = client.getNode(nodepos);
+
+ // TODO: Get this from some table that is sent by server
+ float dig_time_complete = 0.5;
+ if(n.d == CONTENT_STONE || n.d == CONTENT_COALSTONE)
+ {
+ dig_time_complete = 10.0;
+
+ InventoryList *mlist = local_inventory.getList("main");
+ if(mlist != NULL)
+ {
+ InventoryItem *item = mlist->getItem(g_selected_item);
+ if((std::string)item->getName() == "ToolItem")
+ {
+ ToolItem *titem = (ToolItem*)item;
+ if(titem->getToolName() == "WPick")
+ {
+ dig_time_complete = 1.2;
+ }
+ else if(titem->getToolName() == "STPick")
+ {
+ dig_time_complete = 0.6;
+ }
+ }
+ }
+ }
+
+ dig_index = (u16)((float)CRACK_ANIMATION_LENGTH
+ * dig_time/dig_time_complete);
- dig_time += dtime;
+ if(dig_index < CRACK_ANIMATION_LENGTH)
+ {
+ //dstream<<"dig_index="<<dig_index<<std::endl;
+ client.setTempMod(nodepos, NodeMod(NODEMOD_CRACK, dig_index));
+ }
+ else
+ {
+ dstream<<DTIME<<"Digging completed"<<std::endl;
+ client.groundAction(3, nodepos, neighbourpos, g_selected_item);
+ client.clearTempMod(nodepos);
+ client.removeNode(nodepos);
+
+ dig_time = 0;
+
+ nodig_delay_counter = dig_time_complete
+ / (float)CRACK_ANIMATION_LENGTH;
+ }
+
+ dig_time += dtime;
+ }
}
if(g_input->getRightClicked())
diff --git a/src/mapblockobject.cpp b/src/mapblockobject.cpp index d5c9c997a..653dbc332 100644 --- a/src/mapblockobject.cpp +++ b/src/mapblockobject.cpp @@ -21,6 +21,8 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "mapblock.h" // Only for ::getNodeBox, TODO: Get rid of this #include "map.h" +#include "inventory.h" +#include "irrlichtwrapper.h" /* MapBlockObject @@ -293,10 +295,101 @@ void RatObject::addToScene(scene::ISceneManager *smgr) } #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) @@ -480,6 +573,10 @@ void MapBlockObjectList::update(std::istream &is, u8 version, { 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 diff --git a/src/mapblockobject.h b/src/mapblockobject.h index a65ffd8e8..05d522901 100644 --- a/src/mapblockobject.h +++ b/src/mapblockobject.h @@ -31,6 +31,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #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 @@ -720,6 +721,182 @@ protected: }; /* + 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. */ class PlayerObject : public MovingObject diff --git a/src/server.cpp b/src/server.cpp index d7bd22668..db4e04228 100644 --- a/src/server.cpp +++ b/src/server.cpp @@ -1635,7 +1635,7 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id) } catch(InvalidPositionException &e) { - derr_server<<"PICK_OBJECT block not found"<<std::endl; + derr_server<<"CLICK_OBJECT block not found"<<std::endl; return; } @@ -1643,7 +1643,7 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id) if(obj == NULL) { - derr_server<<"PICK_OBJECT object not found"<<std::endl; + derr_server<<"CLICK_OBJECT object not found"<<std::endl; return; } @@ -1662,10 +1662,24 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id) 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); } @@ -2021,17 +2035,10 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 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; @@ -2056,25 +2063,61 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id) <<"("<<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); + } } } @@ -2445,6 +2488,12 @@ void Server::peerAdded(con::Peer *peer) 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++) @@ -2471,6 +2520,16 @@ void Server::peerAdded(con::Peer *peer) } 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); |