From a26c92d7dda327f2b1483fe7250cb27580a0a039 Mon Sep 17 00:00:00 2001 From: Perttu Ahola Date: Fri, 24 Dec 2010 17:08:50 +0200 Subject: disconnect method to connection to be used instead of just timing out --- src/client.cpp | 7 +- src/connection.cpp | 44 ++++- src/connection.h | 14 +- src/guiInventoryMenu.cpp | 16 +- src/inventory.cpp | 209 +++++++++++++----------- src/inventory.h | 196 +++++++++++++++++----- src/main.cpp | 10 +- src/server.cpp | 413 +++++++++++++++++++++++++++++++++++------------ src/server.h | 22 +++ 9 files changed, 688 insertions(+), 243 deletions(-) (limited to 'src') diff --git a/src/client.cpp b/src/client.cpp index f9cccd855..b0750cae6 100644 --- a/src/client.cpp +++ b/src/client.cpp @@ -117,6 +117,11 @@ Client::Client( Client::~Client() { + { + JMutexAutoLock conlock(m_con_mutex); + m_con.Disconnect(); + } + m_thread.setRun(false); while(m_thread.IsRunning()) sleep_ms(100); @@ -601,7 +606,7 @@ void Client::ProcessData(u8 *data, u32 datasize, u16 sender_peer_id) addNode(p, n); } - if(command == TOCLIENT_PLAYERPOS) + else if(command == TOCLIENT_PLAYERPOS) { dstream<<"WARNING: Received deprecated TOCLIENT_PLAYERPOS" < data(2); + writeU8(&data[0], TYPE_CONTROL); + writeU8(&data[1], CONTROLTYPE_DISCO); + + // Send to all + core::map::Iterator j; + j = m_peers.getIterator(); + for(; j.atEnd() == false; j++) + { + Peer *peer = j.getNode()->getValue(); + SendAsPacket(peer->id, 0, data, false); + } +} + bool Connection::Connected() { if(m_peers.size() != 1) @@ -645,7 +662,22 @@ SharedBuffer Channel::ProcessPacket( // the timeout counter con->PrintInfo(); dout_con<<"PING"<PrintInfo(); + dout_con<<"DISCO: Removing peer "<<(peer_id)<deletePeer(peer_id) == false) + { + con->PrintInfo(derr_con); + derr_con<<"DISCO: Peer not found"<PrintInfo(derr_con); @@ -1323,6 +1355,16 @@ core::list Connection::GetPeers() return list; } +bool Connection::deletePeer(u16 peer_id) +{ + if(m_peers.find(peer_id) == NULL) + return false; + m_peerhandler->deletingPeer(m_peers[peer_id], true); + delete m_peers[peer_id]; + m_peers.remove(peer_id); + return true; +} + void Connection::PrintInfo(std::ostream &out) { out< GetFromBuffers(u16 &peer_id); // The peer_id of sender is stored in peer_id // Return value: I guess this always throws an exception or // actually gets data + // May call PeerHandler methods u32 Receive(u16 &peer_id, u8 *data, u32 datasize); // These will automatically package the data as an original or split @@ -460,12 +466,18 @@ public: // Sends a raw packet void RawSend(const BufferedPacket &packet); + // May call PeerHandler methods void RunTimeouts(float dtime); + // Can throw a PeerNotFoundException Peer* GetPeer(u16 peer_id); // returns NULL if failed Peer* GetPeerNoEx(u16 peer_id); core::list GetPeers(); + + // Calls PeerHandler::deletingPeer + // Returns false if peer was not found + bool deletePeer(u16 peer_id); void SetPeerID(u16 id){ m_peer_id = id; } u16 GetPeerID(){ return m_peer_id; } diff --git a/src/guiInventoryMenu.cpp b/src/guiInventoryMenu.cpp index bba23e719..a1f7d02d0 100644 --- a/src/guiInventoryMenu.cpp +++ b/src/guiInventoryMenu.cpp @@ -228,8 +228,10 @@ bool GUIInventoryMenu::OnEvent(const SEvent& event) } if(event.EventType==EET_MOUSE_INPUT_EVENT) { - if(event.MouseInput.Event == EMIE_LMOUSE_PRESSED_DOWN) + if(event.MouseInput.Event == EMIE_LMOUSE_PRESSED_DOWN + || event.MouseInput.Event == EMIE_RMOUSE_PRESSED_DOWN) { + bool right = (event.MouseInput.Event == EMIE_RMOUSE_PRESSED_DOWN); v2s32 p(event.MouseInput.X, event.MouseInput.Y); //dstream<<"Mouse down at p=("<count = 1; + a->count = right ? 1 : 0; a->from_name = m_selected_item->listname; a->from_i = m_selected_item->i; a->to_name = s.listname; a->to_i = s.i; m_actions->push_back(a); } - delete m_selected_item; - m_selected_item = NULL; + bool source_empties = false; + if(list_from && list_from->getItem(m_selected_item->i)->getCount()==1) + source_empties = true; + if(right == false || source_empties) + { + delete m_selected_item; + m_selected_item = NULL; + } } else { diff --git a/src/inventory.cpp b/src/inventory.cpp index 332f9d999..a2aba311b 100644 --- a/src/inventory.cpp +++ b/src/inventory.cpp @@ -32,8 +32,9 @@ with this program; if not, write to the Free Software Foundation, Inc., InventoryItem */ -InventoryItem::InventoryItem() +InventoryItem::InventoryItem(u16 count) { + m_count = count; } InventoryItem::~InventoryItem() @@ -66,6 +67,14 @@ InventoryItem* InventoryItem::deSerialize(std::istream &is) std::getline(is, inventorystring, '|'); return new MapBlockObjectItem(inventorystring); } + else if(name == "CraftItem") + { + std::string subname; + std::getline(is, subname, ' '); + u16 count; + is>>count; + return new CraftItem(subname, count); + } else if(name == "ToolItem") { std::string toolname; @@ -325,83 +334,93 @@ void InventoryList::deleteItem(u32 i) delete item; } -bool InventoryList::addItem(InventoryItem *newitem) +InventoryItem * InventoryList::addItem(InventoryItem *newitem) { - // If it is a MaterialItem, try to find an already existing one - // and just increment the counter - if(std::string("MaterialItem") == newitem->getName()) + /* + First try to find if it could be added to some existing items + */ + for(u32 i=0; igetMaterial(); - u8 count = ((MaterialItem*)newitem)->getCount(); - for(u32 i=0; igetName()) - continue; - // Found one. Check if it is of the right material and has - // free space - MaterialItem *mitem2 = (MaterialItem*)item2; - if(mitem2->getMaterial() != material) - continue; - //TODO: Add all that can be added and add remaining part - // to another place - if(mitem2->freeSpace() < count) - continue; - // Add to the counter - mitem2->add(count); - // Dump the parameter - delete newitem; - return true; - } + // Ignore empty slots + if(m_items[i] == NULL) + continue; + // Try adding + newitem = addItem(i, newitem); + if(newitem == NULL) + return NULL; // All was eaten } - // Else find an empty position + + /* + Then try to add it to empty slots + */ for(u32 i=0; igetName()) + + // If not addable, return the item + if(newitem->addableTo(to_item) == false) + return newitem; + + // If the item fits fully in the slot, add counter and delete it + if(newitem->getCount() <= to_item->freeSpace()) + { + to_item->add(newitem->getCount()); + delete newitem; + return NULL; + } + // Else the item does not fit fully. Add all that fits and return + // the rest. + else { - u8 material = ((MaterialItem*)newitem)->getMaterial(); - u8 count = ((MaterialItem*)newitem)->getCount(); - InventoryItem *item2 = m_items[i]; + u16 freespace = to_item->freeSpace(); + to_item->add(freespace); + newitem->remove(freespace); + return newitem; + } +} - if(item2 != NULL - && std::string("MaterialItem") == item2->getName()) - { - // Check if it is of the right material and has free space - MaterialItem *mitem2 = (MaterialItem*)item2; - if(mitem2->getMaterial() == material - && mitem2->freeSpace() >= count) - { - // Add to the counter - mitem2->add(count); - // Dump the parameter - delete newitem; - // Done - return true; - } - } +InventoryItem * InventoryList::takeItem(u32 i, u32 count) +{ + if(count == 0) + return NULL; + + InventoryItem *item = m_items[i]; + // If it is an empty position, return NULL + if(item == NULL) + return NULL; + + if(count >= item->getCount()) + { + // Get the item by swapping NULL to its place + return changeItem(i, NULL); + } + else + { + InventoryItem *item2 = item->clone(); + item->remove(count); + item2->setCount(count); + return item2; } return false; @@ -411,26 +430,9 @@ void InventoryList::decrementMaterials(u16 count) { for(u32 i=0; igetName()) - { - MaterialItem *mitem = (MaterialItem*)item; - if(mitem->getCount() < count) - { - dstream<<__FUNCTION_NAME<<": decrementMaterials():" - <<" too small material count"<getCount() == count) - { - deleteItem(i); - } - else - { - mitem->remove(1); - } - } + InventoryItem *item = takeItem(i, count); + if(item) + delete item; } } @@ -607,6 +609,10 @@ void IMoveAction::apply(Inventory *inventory) dstream<<" list_to->getItem(to_i)="<getItem(to_i) <getItem(from_i) == NULL || (list_from == list_to && from_i == to_i)) { @@ -615,18 +621,39 @@ void IMoveAction::apply(Inventory *inventory) } // Take item from source list - InventoryItem *item1 = list_from->changeItem(from_i, NULL); + InventoryItem *item1 = NULL; + if(count == 0) + item1 = list_from->changeItem(from_i, NULL); + else + item1 = list_from->takeItem(from_i, count); + // Try to add the item to destination list - if(list_to->addItem(to_i, item1)) - { - // Done. + InventoryItem *olditem = item1; + item1 = list_to->addItem(to_i, item1); + + // If nothing is returned, the item was fully added + if(item1 == NULL) + return; + + // If olditem is returned, nothing was added. + bool nothing_added = (item1 == olditem); + + // If something else is returned, part of the item was left unadded. + // Add the other part back to the source item + list_from->addItem(from_i, item1); + + // If olditem is returned, nothing was added. + // Swap the items + if(nothing_added) + { + // Take item from source list + item1 = list_from->changeItem(from_i, NULL); + // Adding was not possible, swap the items. + InventoryItem *item2 = list_to->changeItem(to_i, item1); + // Put item from destination list to the source list + list_from->changeItem(from_i, item2); return; } - // Adding was not possible, switch it. - // Switch it to the destination list - InventoryItem *item2 = list_to->changeItem(to_i, item1); - // Put item from destination list to the source list - list_from->changeItem(from_i, item2); } //END diff --git a/src/inventory.h b/src/inventory.h index fd2cd8778..13bd27d8b 100644 --- a/src/inventory.h +++ b/src/inventory.h @@ -33,10 +33,12 @@ with this program; if not, write to the Free Software Foundation, Inc., // For g_materials #include "main.h" +#define QUANTITY_ITEM_MAX_COUNT 99 + class InventoryItem { public: - InventoryItem(); + InventoryItem(u16 count); virtual ~InventoryItem(); static InventoryItem* deSerialize(std::istream &is); @@ -53,18 +55,49 @@ public: // Shall return a text to show in the GUI virtual std::string getText() { return ""; } -private: -}; + // Shall return true if the item can be add()ed to the other + virtual bool addableTo(InventoryItem *other) + { + return false; + } + + /* + Quantity methods + */ + u16 getCount() + { + return m_count; + } + void setCount(u16 count) + { + m_count = count; + } + virtual u16 freeSpace() + { + return 0; + } + void add(u16 count) + { + assert(m_count + count <= QUANTITY_ITEM_MAX_COUNT); + m_count += count; + } + void remove(u16 count) + { + assert(m_count >= count); + m_count -= count; + } -#define MATERIAL_ITEM_MAX_COUNT 99 +protected: + u16 m_count; +}; class MaterialItem : public InventoryItem { public: - MaterialItem(u8 content, u16 count) + MaterialItem(u8 content, u16 count): + InventoryItem(count) { m_content = content; - m_count = count; } /* Implementation interface @@ -107,46 +140,38 @@ public: os<getName()) != "MaterialItem") + return false; + MaterialItem *m = (MaterialItem*)other; + if(m->getMaterial() != m_content) + return false; + return true; } u16 freeSpace() { - if(m_count > MATERIAL_ITEM_MAX_COUNT) + if(m_count > QUANTITY_ITEM_MAX_COUNT) return 0; - return MATERIAL_ITEM_MAX_COUNT - m_count; - } - void add(u16 count) - { - assert(m_count + count <= MATERIAL_ITEM_MAX_COUNT); - m_count += count; + return QUANTITY_ITEM_MAX_COUNT - m_count; } - void remove(u16 count) + /* + Special methods + */ + u8 getMaterial() { - assert(m_count >= count); - m_count -= count; + return m_content; } private: u8 m_content; - u16 m_count; }; class MapBlockObjectItem : public InventoryItem { public: - /*MapBlockObjectItem(MapBlockObject *obj) - { - m_inventorystring = obj->getInventoryString(); - }*/ - MapBlockObjectItem(std::string inventorystring) + MapBlockObjectItem(std::string inventorystring): + InventoryItem(1) { m_inventorystring = inventorystring; } @@ -196,10 +221,90 @@ private: std::string m_inventorystring; }; +/* + An item that is used as a mid-product when crafting. + Subnames: + - Stick +*/ +class CraftItem : public InventoryItem +{ +public: + CraftItem(std::string subname, u16 count): + InventoryItem(count) + { + m_subname = subname; + } + /* + Implementation interface + */ + virtual const char* getName() const + { + return "CraftItem"; + } + virtual void serialize(std::ostream &os) + { + os<getTexture(basename); + //return g_irrlicht->getTexture(TextureSpec(finalname, basename, mod)); + } +#endif + std::string getText() + { + std::ostringstream os; + os<getName()) != "CraftItem") + return false; + CraftItem *m = (CraftItem*)other; + if(m->m_subname != m_subname) + return false; + return true; + } + u16 freeSpace() + { + if(m_count > QUANTITY_ITEM_MAX_COUNT) + return 0; + return QUANTITY_ITEM_MAX_COUNT - m_count; + } + /* + Special methods + */ + std::string getSubName() + { + return m_subname; + } +private: + std::string m_subname; +}; + class ToolItem : public InventoryItem { public: - ToolItem(std::string toolname, u16 wear) + ToolItem(std::string toolname, u16 wear): + InventoryItem(1) { m_toolname = toolname; m_wear = wear; @@ -313,11 +418,20 @@ public: InventoryItem * changeItem(u32 i, InventoryItem *newitem); // Delete item void deleteItem(u32 i); - // Adds an item to a suitable place. Returns false if failed. - bool addItem(InventoryItem *newitem); - // If possible, adds item to given slot. Returns true on success. - // Fails when slot is populated by a different kind of item. - bool addItem(u32 i, InventoryItem *newitem); + // Adds an item to a suitable place. Returns leftover item. + // If all went into the list, returns NULL. + InventoryItem * addItem(InventoryItem *newitem); + + // If possible, adds item to given slot. + // If cannot be added at all, returns the item back. + // If can be added partly, decremented item is returned back. + // If can be added fully, NULL is returned. + InventoryItem * addItem(u32 i, InventoryItem *newitem); + + // Takes some items from a slot. + // If there are not enough, takes as many as it can. + // Returns NULL if couldn't take any. + InventoryItem * takeItem(u32 i, u32 count); // Decrements amount of every material item void decrementMaterials(u16 count); @@ -347,12 +461,13 @@ public: InventoryList * addList(const std::string &name, u32 size); InventoryList * getList(const std::string &name); bool deleteList(const std::string &name); - // A shorthand for adding items - bool addItem(const std::string &listname, InventoryItem *newitem) + // A shorthand for adding items. + // Returns NULL if the item was fully added, leftover otherwise. + InventoryItem * addItem(const std::string &listname, InventoryItem *newitem) { InventoryList *list = getList(listname); if(list == NULL) - return false; + return newitem; return list->addItem(newitem); } @@ -376,6 +491,7 @@ struct InventoryAction struct IMoveAction : public InventoryAction { + // count=0 means "everything" u16 count; std::string from_name; s16 from_i; diff --git a/src/main.cpp b/src/main.cpp index df335ad39..1a9379e41 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1513,6 +1513,10 @@ int main(int argc, char *argv[]) // Test the text input system /*(new GUITextInputMenu(guienv, guiroot, -1, &g_active_menu_count, NULL))->drop();*/ + + // Launch pause menu + (new GUIPauseMenu(guienv, guiroot, -1, g_device, + &g_active_menu_count))->drop(); // First line of debug text gui::IGUIStaticText *guitext = guienv->addStaticText( @@ -2164,9 +2168,11 @@ int main(int argc, char *argv[]) } // We want a slight delay to very little // time consuming nodes - if(nodig_delay_counter < 0.15) + //float mindelay = 0.15; + float mindelay = 0.20; + if(nodig_delay_counter < mindelay) { - nodig_delay_counter = 0.15; + nodig_delay_counter = mindelay; } } diff --git a/src/server.cpp b/src/server.cpp index 35f1f8a27..c0af61b98 100644 --- a/src/server.cpp +++ b/src/server.cpp @@ -849,40 +849,6 @@ void RemoteClient::SetBlocksNotSent(core::map &blocks) } } -/*void RemoteClient::BlockEmerged() -{ - SharedPtr lock(m_num_blocks_in_emerge_queue.getLock()); - assert(m_num_blocks_in_emerge_queue.m_value > 0); - m_num_blocks_in_emerge_queue.m_value--; -}*/ - -/*void RemoteClient::RunSendingTimeouts(float dtime, float timeout) -{ - JMutexAutoLock sendinglock(m_blocks_sending_mutex); - - core::list remove_queue; - for(core::map::Iterator - i = m_blocks_sending.getIterator(); - i.atEnd()==false; i++) - { - v3s16 p = i.getNode()->getKey(); - float t = i.getNode()->getValue(); - t += dtime; - i.getNode()->setValue(t); - - if(t > timeout) - { - remove_queue.push_back(p); - } - } - for(core::list::Iterator - i = remove_queue.begin(); - i != remove_queue.end(); i++) - { - m_blocks_sending.remove(*i); - } -}*/ - /* PlayerInfo */ @@ -931,7 +897,8 @@ Server::Server( m_emergethread(this), m_time_of_day(8000), m_time_counter(0), - m_time_of_day_send_timer(0) + m_time_of_day_send_timer(0), + m_uptime(0) { m_flowwater_timer = 0.0; m_print_info_timer = 0.0; @@ -1026,10 +993,20 @@ void Server::AsyncRunStep() if(dtime < 0.001) return; + //dstream<<"Server steps "<::Iterator + i = m_clients.getIterator(); + i.atEnd() == false; i++) + { + // Get client and check that it is valid + RemoteClient *client = i.getNode()->getValue(); + assert(client->peer_id == i.getNode()->getKey()); + if(client->serialization_version == SER_FMT_VER_INVALID) + continue; + // Get name of player + std::wstring name = L"unknown"; + Player *player = m_env.getPlayer(client->peer_id); + if(player != NULL) + name = narrow_to_wide(player->getName()); + // Add name to information string + os<id); - JMutexAutoLock(client->m_dig_mutex); - client->m_dig_tool_item = 0; - client->m_dig_position = p_under; - float dig_time = 0.5; - if(content == CONTENT_STONE) - { - dig_time = 1.5; - } - else if(content == CONTENT_TORCH) - { - dig_time = 0.0; - } - client->m_dig_time_remaining = dig_time; - - // Reset build time counter - getClient(peer->id)->m_time_from_building.set(0.0); -#endif } // action == 0 /* @@ -2240,7 +2212,10 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id) InventoryList *clist = player->inventory.getList("craft"); if(clist) { - clist->decrementMaterials(ma->count); + u16 count = ma->count; + if(count == 0) + count = 1; + clist->decrementMaterials(count); } // Do action // Feed action to player inventory @@ -2424,8 +2399,15 @@ void Server::peerAdded(con::Peer *peer) dout_server<<"Server::peerAdded(): peer->id=" <id<id; + c.timeout = false; + m_peer_change_queue.push_back(c); + +#if 0 + // NOTE: Connection is already locked when this is called. + // NOTE: Environment is already locked when this is called. // Error check core::map::Node *n; @@ -2440,9 +2422,6 @@ void Server::peerAdded(con::Peer *peer) // Create player { - // Already locked when called - //JMutexAutoLock envlock(m_env_mutex); - Player *player = m_env.getPlayer(peer->id); // The player shouldn't already exist @@ -2491,8 +2470,8 @@ void Server::peerAdded(con::Peer *peer) // Give a good pick { InventoryItem *item = new ToolItem("STPick", 32000); - bool r = player->inventory.addItem("main", item); - assert(r == true); + void* r = player->inventory.addItem("main", item); + assert(r == NULL); } // Give all materials assert(USEFUL_CONTENT_COUNT <= PLAYER_INVENTORY_SIZE); @@ -2508,8 +2487,8 @@ void Server::peerAdded(con::Peer *peer) // Sign { InventoryItem *item = new MapBlockObjectItem("Sign Example text"); - bool r = player->inventory.addItem("main", item); - assert(r == true); + void* r = player->inventory.addItem("main", item); + assert(r == NULL); } /*// Rat { @@ -2520,15 +2499,20 @@ void Server::peerAdded(con::Peer *peer) } else { + { + InventoryItem *item = new CraftItem("Stick", 4); + void* r = player->inventory.addItem("main", item); + assert(r == NULL); + } { InventoryItem *item = new ToolItem("WPick", 32000); - bool r = player->inventory.addItem("main", item); - assert(r == true); + void* r = player->inventory.addItem("main", item); + assert(r == NULL); } { InventoryItem *item = new ToolItem("STPick", 32000); - bool r = player->inventory.addItem("main", item); - assert(r == true); + void* r = player->inventory.addItem("main", item); + assert(r == NULL); } /*// Give some lights { @@ -2551,6 +2535,7 @@ void Server::peerAdded(con::Peer *peer) }*/ } } +#endif } void Server::deletingPeer(con::Peer *peer, bool timeout) @@ -2559,8 +2544,18 @@ void Server::deletingPeer(con::Peer *peer, bool timeout) dout_server<<"Server::deletingPeer(): peer->id=" <id<<", timeout="<id; + c.timeout = timeout; + m_peer_change_queue.push_back(c); + +#if 0 + // NOTE: Connection is already locked when this is called. + + // NOTE: Environment is already locked when this is called. + // NOTE: Locking environment cannot be moved here because connection + // is already locked and env has to be locked before // Error check core::map::Node *n; @@ -2568,10 +2563,22 @@ void Server::deletingPeer(con::Peer *peer, bool timeout) // The client should exist assert(n != NULL); + // Send information about leaving in chat + { + std::wstring name = L"unknown"; + Player *player = m_env.getPlayer(peer->id); + if(player != NULL) + name = narrow_to_wide(player->getName()); + + std::wstring message; + message += L"*** "; + message += name; + message += L" left game"; + BroadcastChatMessage(message); + } + // Delete player { - // Already locked when called - //JMutexAutoLock envlock(m_env_mutex); m_env.removePlayer(peer->id); } @@ -2581,6 +2588,7 @@ void Server::deletingPeer(con::Peer *peer, bool timeout) // Send player info to all clients SendPlayerInfos(); +#endif } void Server::SendObjectData(float dtime) @@ -2848,6 +2856,205 @@ void Server::UpdateBlockWaterPressure(MapBlock *block, v.blitBack(modified_blocks); } + +void Server::handlePeerChange(PeerChange &c) +{ + JMutexAutoLock envlock(m_env_mutex); + JMutexAutoLock conlock(m_con_mutex); + if(c.type == PEER_ADDED) + { + /* + Add + */ + + // Error check + core::map::Node *n; + n = m_clients.find(c.peer_id); + // The client shouldn't already exist + assert(n == NULL); + + // Create client + RemoteClient *client = new RemoteClient(); + client->peer_id = c.peer_id; + m_clients.insert(client->peer_id, client); + + // Create player + { + Player *player = m_env.getPlayer(c.peer_id); + + // The player shouldn't already exist + assert(player == NULL); + + player = new ServerRemotePlayer(); + player->peer_id = c.peer_id; + + /* + Set player position + */ + + // We're going to throw the player to this position + //v2s16 nodepos(29990,29990); + //v2s16 nodepos(9990,9990); + v2s16 nodepos(0,0); + v2s16 sectorpos = getNodeSectorPos(nodepos); + // Get zero sector (it could have been unloaded to disk) + m_env.getMap().emergeSector(sectorpos); + // Get ground height at origin + f32 groundheight = m_env.getMap().getGroundHeight(nodepos, true); + // The sector should have been generated -> groundheight exists + assert(groundheight > GROUNDHEIGHT_VALID_MINVALUE); + // Don't go underwater + if(groundheight < WATER_LEVEL) + groundheight = WATER_LEVEL; + + player->setPosition(intToFloat(v3s16( + nodepos.X, + groundheight + 1, + nodepos.Y + ))); + + /* + Add player to environment + */ + + m_env.addPlayer(player); + + /* + Add stuff to inventory + */ + + if(g_settings.getBool("creative_mode")) + { + // Give a good pick + { + InventoryItem *item = new ToolItem("STPick", 32000); + void* r = player->inventory.addItem("main", item); + assert(r == NULL); + } + // Give all materials + assert(USEFUL_CONTENT_COUNT <= PLAYER_INVENTORY_SIZE); + for(u16 i=0; iinventory.addItem("main", item); + } + // Sign + { + InventoryItem *item = new MapBlockObjectItem("Sign Example text"); + void* r = player->inventory.addItem("main", item); + assert(r == NULL); + } + /*// Rat + { + InventoryItem *item = new MapBlockObjectItem("Rat"); + bool r = player->inventory.addItem("main", item); + assert(r == true); + }*/ + } + else + { + { + InventoryItem *item = new CraftItem("Stick", 4); + void* r = player->inventory.addItem("main", item); + assert(r == NULL); + } + { + InventoryItem *item = new ToolItem("WPick", 32000); + void* r = player->inventory.addItem("main", item); + assert(r == NULL); + } + { + InventoryItem *item = new ToolItem("STPick", 32000); + void* r = player->inventory.addItem("main", item); + assert(r == NULL); + } + /*// Give some lights + { + InventoryItem *item = new MaterialItem(CONTENT_TORCH, 999); + bool r = player->inventory.addItem("main", item); + assert(r == true); + } + // and some signs + for(u16 i=0; i<4; i++) + { + InventoryItem *item = new MapBlockObjectItem("Sign Example text"); + bool r = player->inventory.addItem("main", item); + assert(r == true); + }*/ + /*// Give some other stuff + { + InventoryItem *item = new MaterialItem(CONTENT_TREE, 999); + bool r = player->inventory.addItem("main", item); + assert(r == true); + }*/ + } + } + + } // PEER_ADDED + else if(c.type == PEER_REMOVED) + { + /* + Delete + */ + + // Error check + core::map::Node *n; + n = m_clients.find(c.peer_id); + // The client should exist + assert(n != NULL); + + // Collect information about leaving in chat + std::wstring message; + { + std::wstring name = L"unknown"; + Player *player = m_env.getPlayer(c.peer_id); + if(player != NULL) + name = narrow_to_wide(player->getName()); + + message += L"*** "; + message += name; + message += L" left game"; + } + + // Delete player + { + m_env.removePlayer(c.peer_id); + } + + // Delete client + delete m_clients[c.peer_id]; + m_clients.remove(c.peer_id); + + // Send player info to all remaining clients + SendPlayerInfos(); + + // Send leave chat message to all remaining clients + BroadcastChatMessage(message); + + } // PEER_REMOVED + else + { + assert(0); + } +} + +void Server::handlePeerChanges() +{ + while(m_peer_change_queue.size() > 0) + { + PeerChange c = m_peer_change_queue.pop_front(); + + dout_server<<"Server: Handling peer change: " + <<"id="<