diff --git a/data/sign.png b/data/sign.png index fc9081adf..2e0b3cbef 100644 Binary files a/data/sign.png and b/data/sign.png differ 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 data, bool reliable) @@ -1252,42 +1239,6 @@ void Client::Send(u16 channelnum, SharedBuffer 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 (" - < 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::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 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 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=\""<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 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"<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)) + + if(nodig_delay_counter > 0.0) { - dstream<getLeftClicked()) + else { - 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) - dig_time_complete = 1.5; - - dig_index = (u16)((float)CRACK_ANIMATION_LENGTH - * dig_time/dig_time_complete); - - if(dig_index < CRACK_ANIMATION_LENGTH) + if(nodepos != nodepos_old) { - //dstream<<"dig_index="<getLeftClicked() || + (g_input->getLeftState() && nodepos != nodepos_old)) + { + dstream<getLeftClicked()) + { + 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); + + if(dig_index < CRACK_ANIMATION_LENGTH) + { + //dstream<<"dig_index="<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=\"" + < item="< + (-BS*0.4,-BS*0.5,-BS*0.4, BS*0.4,BS*0.5,BS*0.4);*/ + m_selection_box = new core::aabbox3d + (-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; igetMesh(); + if(mesh->getMeshBufferCount() >= 1) + { + scene::IMeshBuffer *buf = mesh->getMeshBuffer(0); + //dstream<<"Setting texture "<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; jgetMeshBuffer(j); + video::S3DVertex *vertices = (video::S3DVertex*)buf->getVertices(); + u16 vc = buf->getVertexCount(); + for(u16 i=0; isetPosition(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. */ 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"<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=\"" - <getInventoryString() - <<"\""<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=\"" + <getInventoryString() + <<"\""<createObject + (pos, player->getYaw(), player->getPitch()); + } + /* + Handle other items + */ + else + { + dout_server<<"Placing a miscellaneous item on map" + <serialize(os); + dout_server<<"Item string is \""<setItemString(os.str()); + obj = iobj; + } if(obj == NULL) - derr_server<<"WARNING: oitem created NULL object" - <addObject(obj); - - //dout_server<<"Placed object"<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); + derr_server<<"WARNING: item resulted in NULL object, " + <<"not placing onto map" + <addObject(obj); + + dout_server<<"Placed object"<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; iinventory.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);