X-Git-Url: https://git.lizzy.rs/?a=blobdiff_plain;f=src%2Fserver.cpp;h=2a0914e0a0c3047b2f4f8ecc496f6519b4792666;hb=b65a5aceb0d6552d8ba4878bed5326c614dd3046;hp=fabfbc84e31c42d11b1829da1d68fc032e27d1e3;hpb=d2c0b4905abd895b87d5ed9b8769b1a60d692970;p=dragonfireclient.git diff --git a/src/server.cpp b/src/server.cpp index fabfbc84e..2a0914e0a 100644 --- a/src/server.cpp +++ b/src/server.cpp @@ -36,6 +36,11 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "content_nodemeta.h" #include "mapblock.h" #include "serverobject.h" +#include "settings.h" +#include "profiler.h" +#include "log.h" + +#define PP(x) "("<<(x).X<<","<<(x).Y<<","<<(x).Z<<")" #define BLOCK_EMERGE_FLAG_FROMDISK (1<<0) @@ -68,6 +73,8 @@ void * ServerThread::Thread() { ThreadStarted(); + log_register_thread("ServerThread"); + DSTACK(__FUNCTION_NAME); BEGIN_DEBUG_EXCEPTION_HANDLER @@ -82,7 +89,7 @@ void * ServerThread::Thread() m_server->AsyncRunStep(); } - //dout_server<<"Running m_server->Receive()"<Receive()"<Receive(); } catch(con::NoIncomingDataException &e) @@ -90,11 +97,11 @@ void * ServerThread::Thread() } catch(con::PeerNotFoundException &e) { - dout_server<<"Server: PeerNotFoundException"<getBool("enable_mapgen_debug_info"); /* Get block info from queue, emerge them and send them @@ -137,7 +146,7 @@ void * EmergeThread::Thread() || p.Z > MAP_GENERATION_LIMIT / MAP_BLOCKSIZE) continue; - //derr_server<<"EmergeThread::Thread(): running"<isGenerated() == false) { if(enable_mapgen_debug_info) - dstream<<"EmergeThread: generating"< 0) { - /*dstream<<"lighting "<= g_settings.getU16 + if(m_blocks_sending.size() >= g_settings->getU16 ("max_simultaneous_block_sends_per_client")) { - //dstream<<"Not sending any blocks, Queue full."<getPitch()); camera_dir.rotateXZBy(player->getYaw()); - /*dstream<<"camera_dir=("<getPlayerName(peer_id)<getFloat( "full_block_send_enable_min_time_from_building")) { max_simul_sends_usually @@ -450,8 +459,8 @@ void RemoteClient::GetNextBlocks(Server *server, float dtime, */ s32 new_nearest_unsent_d = -1; - s16 d_max = g_settings.getS16("max_block_send_distance"); - s16 d_max_gen = g_settings.getS16("max_block_generate_distance"); + s16 d_max = g_settings->getS16("max_block_send_distance"); + s16 d_max_gen = g_settings->getS16("max_block_generate_distance"); // Don't loop very much at a time if(d_max > d_start+1) @@ -459,7 +468,7 @@ void RemoteClient::GetNextBlocks(Server *server, float dtime, /*if(d_max_gen > d_start+2) d_max_gen = d_start+2;*/ - //dstream<<"Starting from "<= - g_settings.getS16("max_block_send_distance")) + g_settings->getS16("max_block_send_distance")) { // Pause time in seconds m_nothing_to_send_pause_timer = 1.0; - /*dstream<<"nothing to send to " + /*infostream<<"nothing to send to " <getPlayerName(peer_id) <<" (d="< list; - getFacePositions(list, d); - - core::list::Iterator li; - for(li=list.begin(); li!=list.end(); li++) - { - v3s16 p = *li + center; - - /* - Ignore blocks that haven't been sent to the client - */ - { - if(m_blocks_sent.find(p) == NULL) - continue; - } - - // Try stepping block and add it to a send queue - try - { - - // Get block - MapBlock *block = server->m_env.getMap().getBlockNoCreate(p); - - /* - Step block if not in stepped_blocks and add to stepped_blocks. - */ - if(stepped_blocks.find(p) == NULL) - { - block->stepObjects(dtime, true, server->m_env.getDayNightRatio()); - stepped_blocks.insert(p, true); - block->setChangedFlag(); - } - - // Skip block if there are no objects - if(block->getObjectCount() == 0) - continue; - - /* - Write objects - */ - - // Write blockpos - writeV3S16(buf, p); - bos.write((char*)buf, 6); - - // Write objects - //block->serializeObjects(bos, serialization_version); // DEPRECATED - // count=0 - writeU16(bos, 0); - - blockcount++; - - /* - Stop collecting objects if data is already too big - */ - // Sum of player and object data sizes - s32 sum = (s32)os.tellp() + 2 + (s32)bos.tellp(); - // break out if data too big - if(sum > MAX_OBJECTDATA_SIZE) - { - goto skip_subsequent; - } - - } //try - catch(InvalidPositionException &e) - { - // Not in memory - // Add it to the emerge queue and trigger the thread. - // Fetch the block only if it is on disk. - - // Grab and increment counter - /*SharedPtr lock - (m_num_blocks_in_emerge_queue.getLock()); - m_num_blocks_in_emerge_queue.m_value++;*/ - - // Add to queue as an anonymous fetch from disk - u8 flags = BLOCK_EMERGE_FLAG_FROMDISK; - server->m_emerge_queue.addBlock(0, p, flags); - server->m_emergethread.trigger(); - } - } - } - -skip_subsequent: - // Write block count - writeU16(buf, blockcount); + writeU16(buf, 0); os.write((char*)buf, 2); - // Write block objects - os<getFloat("time_speed") * 24000./(24.*3600); u32 units = (u32)(m_time_counter*speed); m_time_counter -= (f32)units / speed; m_env.setTimeOfDay((m_env.getTimeOfDay() + units) % 24000); - //dstream<<"Server: m_time_of_day = "<getFloat("time_send_interval"); //JMutexAutoLock envlock(m_env_mutex); JMutexAutoLock conlock(m_con_mutex); @@ -1294,24 +1230,10 @@ void Server::AsyncRunStep() } } - { - // Process connection's timeouts - JMutexAutoLock lock2(m_con_mutex); - ScopeProfiler sp(&g_profiler, "Server: connection timeout processing"); - m_con.RunTimeouts(dtime); - } - - { - // This has to be called so that the client list gets synced - // with the peer list of the connection - ScopeProfiler sp(&g_profiler, "Server: peer change handling"); - handlePeerChanges(); - } - { JMutexAutoLock lock(m_env_mutex); // Step environment - ScopeProfiler sp(&g_profiler, "Server: environment step"); + ScopeProfiler sp(g_profiler, "Server: environment step"); m_env.step(dtime); } @@ -1320,9 +1242,9 @@ void Server::AsyncRunStep() { JMutexAutoLock lock(m_env_mutex); // Run Map's timers and unload unused data - ScopeProfiler sp(&g_profiler, "Server: map timer and unload"); + ScopeProfiler sp(g_profiler, "Server: map timer and unload"); m_env.getMap().timerUpdate(map_timer_and_unload_dtime, - g_settings.getFloat("server_unload_unused_data_timeout")); + g_settings->getFloat("server_unload_unused_data_timeout")); } /* @@ -1339,7 +1261,7 @@ void Server::AsyncRunStep() JMutexAutoLock lock(m_env_mutex); - ScopeProfiler sp(&g_profiler, "Server: liquid transform"); + ScopeProfiler sp(g_profiler, "Server: liquid transform"); core::map modified_blocks; m_env.getMap().transformLiquids(modified_blocks); @@ -1389,7 +1311,9 @@ void Server::AsyncRunStep() counter = 0.0; JMutexAutoLock lock2(m_con_mutex); - + + if(m_clients.size() != 0) + infostream<<"Players:"<::Iterator i = m_clients.getIterator(); i.atEnd() == false; i++) @@ -1399,27 +1323,28 @@ void Server::AsyncRunStep() Player *player = m_env.getPlayer(client->peer_id); if(player==NULL) continue; - std::cout<getName()<<"\t"; - client->PrintInfo(std::cout); + infostream<<"* "<getName()<<"\t"; + client->PrintInfo(infostream); } } } - //if(g_settings.getBool("enable_experimental")) + //if(g_settings->getBool("enable_experimental")) { /* Check added and deleted active objects */ { - //dstream<<"Server: Checking added and deleted active objects"<getS16("active_object_send_range_blocks"); + radius *= MAP_BLOCKSIZE; for(core::map::Iterator i = m_clients.getIterator(); @@ -1430,7 +1355,7 @@ void Server::AsyncRunStep() if(player==NULL) { // This can happen if the client timeouts somehow - /*dstream<<"WARNING: "<<__FUNCTION_NAME<<": Client " + /*infostream<<"WARNING: "<<__FUNCTION_NAME<<": Client " <peer_id <<" has no associated player"<getType(); @@ -1523,7 +1448,7 @@ void Server::AsyncRunStep() // Send as reliable m_con.Send(client->peer_id, 0, reply, true); - dstream<<"INFO: Server: Sent object remove/add: " + infostream<<"Server: Sent object remove/add: " < 0 || unreliable_data.size() > 0) { - dstream<<"INFO: Server: Size of object message data: " + infostream<<"Server: Size of object message data: " <<"reliable: "<type == MEET_ADDNODE) { - //dstream<<"Server: MEET_ADDNODE"<p, event->n, event->already_known_by_peer, @@ -1715,7 +1640,7 @@ void Server::AsyncRunStep() } else if(event->type == MEET_REMOVENODE) { - //dstream<<"Server: MEET_REMOVENODE"<p, event->already_known_by_peer, @@ -1726,13 +1651,13 @@ void Server::AsyncRunStep() } else if(event->type == MEET_BLOCK_NODE_METADATA_CHANGED) { - dstream<<"Server: MEET_BLOCK_NODE_METADATA_CHANGED"<p); } else if(event->type == MEET_OTHER) { - dstream<<"Server: MEET_OTHER"<::Iterator i = event->modified_blocks.getIterator(); @@ -1745,7 +1670,7 @@ void Server::AsyncRunStep() else { prof.add("unknown", 1); - dstream<<"WARNING: Server: Unknown MapEditEvent " + infostream<<"WARNING: Server: Unknown MapEditEvent " <<((u32)event->type)<= g_settings.getFloat("objectdata_interval")) + if(counter >= g_settings->getFloat("objectdata_interval")) { JMutexAutoLock lock1(m_env_mutex); JMutexAutoLock lock2(m_con_mutex); - ScopeProfiler sp(&g_profiler, "Server: sending mbo positions"); + ScopeProfiler sp(g_profiler, "Server: sending mbo positions"); SendObjectData(counter); @@ -1832,11 +1757,11 @@ void Server::AsyncRunStep() { float &counter = m_savemap_timer; counter += dtime; - if(counter >= g_settings.getFloat("server_map_save_interval")) + if(counter >= g_settings->getFloat("server_map_save_interval")) { counter = 0.0; - ScopeProfiler sp(&g_profiler, "Server: saving stuff"); + ScopeProfiler sp(g_profiler, "Server: saving stuff"); // Auth stuff if(m_authmanager.isModified()) @@ -1851,10 +1776,10 @@ void Server::AsyncRunStep() /*// Unload unused data (delete from memory) m_env.getMap().unloadUnusedData( - g_settings.getFloat("server_unload_unused_sectors_timeout")); + g_settings->getFloat("server_unload_unused_sectors_timeout")); */ /*u32 deleted_count = m_env.getMap().unloadUnusedData( - g_settings.getFloat("server_unload_unused_sectors_timeout")); + g_settings->getFloat("server_unload_unused_sectors_timeout")); */ // Save only changed parts @@ -1862,7 +1787,7 @@ void Server::AsyncRunStep() /*if(deleted_count > 0) { - dout_server<<"Server: Unloaded "<id<getBool("strict_protocol_version_checking")) + { + if(net_proto_version < PROTOCOL_VERSION) + { + SendAccessDenied(m_con, peer_id, + L"Your client is too old. Please upgrade."); + return; + } + } /* Set up player @@ -2024,7 +1960,7 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id) if(playername[0]=='\0') { - derr_server<get("default_password"); } - /*dstream<<"Server: Client gave password '"<get("default_privs"))); m_authmanager.save(); } + + // Enforce user limit. + // Don't enforce for users that have some admin right + if(m_clients.size() >= g_settings->getU16("max_users") && + (m_authmanager.getPrivs(playername) + & (PRIV_SERVER|PRIV_BAN|PRIV_PRIVS)) == 0 && + playername != g_settings->get("name")) + { + SendAccessDenied(m_con, peer_id, L"Too many users."); + return; + } // Get player Player *player = emergePlayer(playername, password, peer_id); - - /*{ - // DEBUG: Test serialization - std::ostringstream test_os; - player->serialize(test_os); - dstream<<"Player serialization test: \""<deSerialize(test_is); - }*/ - // If failed, cancel if(player == NULL) { - derr_server<peer_id != 0) - { - derr_server<peer_id = peer_id; - */ - - // Check if player doesn't exist - if(player == NULL) - throw con::InvalidIncomingDataException - ("Server::ProcessData(): INIT: Player doesn't exist"); - - /*// update name if it was supplied - if(datasize >= 20+3) - { - data[20+3-1] = 0; - player->updateName((const char*)&data[3]); - }*/ - /* Answer with a TOCLIENT_INIT */ @@ -2160,7 +2070,7 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id) if(command == TOSERVER_INIT2) { - derr_server<id<id)->net_proto_version == 0) + if(getClient(peer->id)->net_proto_version < PROTOCOL_VERSION) { - SendChatMessage(peer_id, L"# Server: NOTE: YOUR CLIENT IS OLD AND DOES NOT WORK PROPERLY WITH THIS SERVER"); - }*/ + SendChatMessage(peer_id, L"# Server: WARNING: YOUR CLIENT IS OLD AND MAY WORK PROPERLY WITH THIS SERVER"); + } + + /* + Check HP, respawn if necessary + */ + HandlePlayerHP(player, 0); + + /* + Print out action + */ + { + std::ostringstream os(std::ios_base::binary); + for(core::map::Iterator + i = m_clients.getIterator(); + i.atEnd() == false; i++) + { + RemoteClient *client = i.getNode()->getValue(); + assert(client->peer_id == i.getNode()->getKey()); + if(client->serialization_version == SER_FMT_VER_INVALID) + continue; + // Get player + Player *player = m_env.getPlayer(client->peer_id); + if(!player) + continue; + // Get name of player + os<getName()<<" "; + } + + actionstream<getName()<<" joins game. List of players: " + <GotBlock(p); @@ -2305,7 +2245,7 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id) throw con::InvalidIncomingDataException ("DELETEDBLOCKS length is too short"); v3s16 p = readV3S16(&data[2+1+i*6]); - /*dstream<<"Server: DELETEDBLOCKS (" + /*infostream<<"Server: DELETEDBLOCKS (" <SetBlockNotSent(p); @@ -2313,87 +2253,8 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id) } else if(command == TOSERVER_CLICK_OBJECT) { - if(datasize < 13) - return; - - if((getPlayerPrivs(player) & PRIV_BUILD) == 0) - return; - - /* - [0] u16 command - [2] u8 button (0=left, 1=right) - [3] v3s16 block - [9] s16 id - [11] u16 item - */ - u8 button = readU8(&data[2]); - v3s16 p; - p.X = readS16(&data[3]); - p.Y = readS16(&data[5]); - p.Z = readS16(&data[7]); - s16 id = readS16(&data[9]); - //u16 item_i = readU16(&data[11]); - - MapBlock *block = NULL; - try - { - block = m_env.getMap().getBlockNoCreate(p); - } - catch(InvalidPositionException &e) - { - derr_server<<"CLICK_OBJECT block not found"<getObject(id); - - if(obj == NULL) - { - derr_server<<"CLICK_OBJECT object not found"<inventory.getList("main"); - if(g_settings.getBool("creative_mode") == false && ilist != NULL) - { - - // Skip if inventory has no free space - if(ilist->getUsedSlots() == ilist->getSize()) - { - dout_server<<"Player inventory has no free space"<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 - ilist->addItem(item); - UpdateCrafting(player->peer_id); - SendInventory(player->peer_id); - } - - // Remove from block - block->removeObject(id); - } + infostream<<"Server: CLICK_OBJECT not supported anymore"<inventory.getList("main"); if(ilist != NULL) { - if(g_settings.getBool("creative_mode") == false) + actionstream<getName()<<" picked up " + <getName()<getBool("creative_mode") == false) { // Skip if inventory has no free space - if(ilist->getUsedSlots() == ilist->getSize()) + if(ilist->roomForItem(item) == false) { - dout_server<<"Player inventory has no free space"<getName()<<" punches object " + <getId()<getBasePosition(); v3f dir = (objpos - playerpos).normalize(); - u16 wear = obj->punch(toolname, dir); + u16 wear = obj->punch(toolname, dir, player->getName()); if(titem) { @@ -2499,6 +2365,9 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id) // Right click, do something with object if(button == 1) { + actionstream<getName()<<" right clicks object " + <getId()<hp; @@ -2591,7 +2460,7 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id) // If it's not diggable, do nothing if(content_diggable(material) == false) { - derr_server<<"Server: Not finishing digging: " + infostream<<"Server: Not finishing digging: " <<"Node not diggable" <nodeRemovalDisabled() == true) { - derr_server<<"Server: Not finishing digging: " + infostream<<"Server: Not finishing digging: " <<"Node metadata disables removal" <getName()<<" cannot remove node" + infostream<<"Player "<getName()<<" cannot remove node" <<" because privileges are "<getName()<<" digs "<getBool("creative_mode") == false) { /* Wear out tool @@ -2683,7 +2556,7 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id) if(prop.diggable == false) { - derr_server<<"Server: WARNING: Player digged" + infostream<<"Server: WARNING: Player digged" <<" with impossible material + tool" <<" combination"<peer_id); SendInventory(player->peer_id); } + + item = NULL; + + if(mineral != MINERAL_NONE) + item = getDiggedMineralItem(mineral); + + // If not mineral + if(item == NULL) + { + std::string &extra_dug_s = content_features(material).extra_dug_item; + s32 extra_rarity = content_features(material).extra_dug_item_rarity; + if(extra_dug_s != "" && extra_rarity != 0 + && myrand() % extra_rarity == 0) + { + std::istringstream is(extra_dug_s, std::ios::binary); + item = InventoryItem::deSerialize(is); + } + } + + if(item != NULL) + { + // Add a item to inventory + player->inventory.addItem("main", item); + + // Send inventory + UpdateCrafting(player->peer_id); + SendInventory(player->peer_id); + } } /* @@ -2780,7 +2681,7 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id) bool no_enough_privs = ((getPlayerPrivs(player) & PRIV_BUILD)==0); if(no_enough_privs) - dstream<<"Player "<getName()<<" cannot add node" + infostream<<"Player "<getName()<<" cannot add node" <<" because privileges are "<getMaterial()); + actionstream<getName()<<" places material " + <<(int)mitem->getMaterial() + <<" at "<inventory.getList("main"); - if(g_settings.getBool("creative_mode") == false && ilist) + if(g_settings->getBool("creative_mode") == false && ilist) { // Remove from inventory and send inventory if(mitem->getCount() == 1) @@ -2872,7 +2777,8 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id) { MapEditEventIgnorer ign(&m_ignore_map_edit_events); - m_env.getMap().addNodeAndUpdate(p_over, n, modified_blocks); + std::string p_name = std::string(player->getName()); + m_env.getMap().addNodeAndUpdate(p_over, n, modified_blocks, p_name); } /* Set blocks not sent to far players @@ -2917,14 +2823,23 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id) MapBlock *block = m_env.getMap().getBlockNoCreateNoEx(blockpos); if(block==NULL) { - derr_server<<"Error while placing object: " + infostream<<"Error while placing object: " "block not found"<getBool("creative_mode") && + (getPlayerPrivs(player) & PRIV_BUILD) == 0) + { + infostream<<"Not allowing player to drop item: " + "creative mode and no build privs"<getName()<<" places "<getName() + <<" at "<getBool("creative_mode") == false) { // Delete the right amount of items from the slot u16 dropcount = item->getDropCount(); @@ -2960,7 +2878,7 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id) if(item->getCount() <= dropcount) { if(item->getCount() < dropcount) - dstream<<"WARNING: Server: dropped more items" + infostream<<"WARNING: Server: dropped more items" <<" than the slot contains"<inventory.getList("main"); @@ -2986,7 +2904,7 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id) */ else { - derr_server<<"WARNING: Server: Invalid action " + infostream<<"WARNING: Server: Invalid action " <getObject(id); - if(obj == NULL) - { - derr_server<<"Error while setting sign text: " - "object not found"<getTypeId() != MAPBLOCKOBJECT_TYPE_SIGN) - { - derr_server<<"Error while setting sign text: " - "object is not a sign"<setText(text); - - obj->getBlock()->setChangedFlag(); + infostream<<"Server: TOSERVER_SIGNTEXT not supported anymore" + <setText(text); + actionstream<getName()<<" writes \""<getBool("creative_mode") == true) { - dstream<<"TOSERVER_INVENTORY_ACTION: ignoring in creative mode" + infostream<<"TOSERVER_INVENTORY_ACTION: ignoring in creative mode" <getBool("creative_mode") == false) { IMoveAction *ma = (IMoveAction*)a; if(ma->to_inv == "current_player" && @@ -3171,6 +3039,14 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id) { player->craftresult_is_preview = false; clist->decrementMaterials(1); + + /* Print out action */ + InventoryList *list = + player->inventory.getList("craftresult"); + assert(list); + InventoryItem *item = list->getItem(0); + actionstream<getName()<<" crafts " + <getName()<addItem(item1); } } + // Disallow moving items if not allowed to build + else if((getPlayerPrivs(player) & PRIV_BUILD) == 0) + { + return; + } + // if it's a locking chest, only allow the owner or server admins to move items + else if (ma->from_inv != "current_player" && (getPlayerPrivs(player) & PRIV_SERVER) == 0) + { + Strfnd fn(ma->from_inv); + std::string id0 = fn.next(":"); + if(id0 == "nodemeta") + { + v3s16 p; + p.X = stoi(fn.next(",")); + p.Y = stoi(fn.next(",")); + p.Z = stoi(fn.next(",")); + NodeMetadata *meta = m_env.getMap().getNodeMetadata(p); + if(meta && meta->typeId() == CONTENT_LOCKABLE_CHEST) { + LockingChestNodeMetadata *lcm = (LockingChestNodeMetadata*)meta; + if (lcm->getOwner() != player->getName()) + return; + } + } + } + else if (ma->to_inv != "current_player" && (getPlayerPrivs(player) & PRIV_SERVER) == 0) + { + Strfnd fn(ma->to_inv); + std::string id0 = fn.next(":"); + if(id0 == "nodemeta") + { + v3s16 p; + p.X = stoi(fn.next(",")); + p.Y = stoi(fn.next(",")); + p.Z = stoi(fn.next(",")); + NodeMetadata *meta = m_env.getMap().getNodeMetadata(p); + if(meta && meta->typeId() == CONTENT_LOCKABLE_CHEST) { + LockingChestNodeMetadata *lcm = (LockingChestNodeMetadata*)meta; + if (lcm->getOwner() != player->getName()) + return; + } + } + } } if(disable_action == false) @@ -3203,7 +3121,7 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id) } else { - dstream<<"TOSERVER_INVENTORY_ACTION: " + infostream<<"TOSERVER_INVENTORY_ACTION: " <<"InventoryAction::deSerialize() returned NULL" <flags & SEND_TO_SENDER; send_to_others = ctx->flags & SEND_TO_OTHERS; + + if (ctx->flags & SEND_NO_PREFIX) + line += reply; + else + line += L"Server: " + reply; + delete ctx; } @@ -3291,7 +3213,8 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id) if(line != L"") { - dstream<<"CHAT: "<hp > damage) - { - player->hp -= damage; - } - else - { - player->hp = 0; + std::string datastring((char*)&data[2], datasize-2); + std::istringstream is(datastring, std::ios_base::binary); + u8 damage = readU8(is); - dstream<<"TODO: Server: TOSERVER_HP_DECREMENT: Player dies" - <setPosition(pos); - player->hp = 20; - SendMovePlayer(player); - SendPlayerHP(player); + if(g_settings->getBool("enable_damage")) + { + actionstream<getName()<<" damaged by " + <<(int)damage<<" hp at "<getPosition()/BS) + <getName(); if(m_authmanager.exists(playername) == false) { - dstream<<"Server: playername not found in authmanager"<getName()<<" changes password"<wieldItem(item); SendWieldedItem(player); } + else if(command == TOSERVER_RESPAWN) + { + if(player->hp != 0) + return; + + RespawnPlayer(player); + + actionstream<getName()<<" respawns at " + <getPosition()/BS)<clone(); @@ -3460,12 +3384,12 @@ Inventory* Server::getInventory(InventoryContext *c, std::string id) NodeMetadata *meta = m_env.getMap().getNodeMetadata(p); if(meta) return meta->getInventory(); - dstream<<"nodemeta at ("< Server::getPlayerInfo() @@ -3554,7 +3478,7 @@ core::list Server::getPlayerInfo() void Server::peerAdded(con::Peer *peer) { DSTACK(__FUNCTION_NAME); - dout_server<<"Server::peerAdded(): peer->id=" + infostream<<"Server::peerAdded(): peer->id=" <id<id=" + infostream<<"Server::deletingPeer(): peer->id=" <id<<", timeout="< data((u8*)s.c_str(), s.size()); + // Send as reliable + con.Send(peer_id, 0, data, true); +} + /* Non-static send methods */ @@ -3659,7 +3600,7 @@ void Server::SendPlayerInfos() { Player *player = *i; - /*dstream<<"Server sending player info for player with " + /*infostream<<"Server sending player info for player with " "peer_id="<peer_id<peer_id); @@ -3819,7 +3760,7 @@ void Server::SendMovePlayer(Player *player) v3f pos = player->getPosition(); f32 pitch = player->getPitch(); f32 yaw = player->getYaw(); - dstream<<"Server sending TOCLIENT_MOVE_PLAYER" + infostream<<"Server sending TOCLIENT_MOVE_PLAYER" <<" pos=("<::Iterator i = m_clients.getIterator(); @@ -4036,7 +3977,7 @@ void Server::SendBlocks(float dtime) for(u32 i=0; i= g_settings.getS32 + if(total_sending >= g_settings->getS32 ("max_simultaneous_block_sends_server_total")) break; @@ -4066,6 +4007,51 @@ void Server::SendBlocks(float dtime) Something random */ +void Server::HandlePlayerHP(Player *player, s16 damage) +{ + if(player->hp > damage) + { + player->hp -= damage; + SendPlayerHP(player); + } + else + { + infostream<<"Server::HandlePlayerHP(): Player " + <getName()<<" dies"<hp = 0; + + //TODO: Throw items around + + // Handle players that are not connected + if(player->peer_id == PEER_ID_INEXISTENT){ + RespawnPlayer(player); + return; + } + + SendPlayerHP(player); + + RemoteClient *client = getClient(player->peer_id); + if(client->net_proto_version >= 3) + { + SendDeathscreen(m_con, player->peer_id, false, v3f(0,0,0)); + } + else + { + RespawnPlayer(player); + } + } +} + +void Server::RespawnPlayer(Player *player) +{ + v3f pos = findSpawnPos(m_env.getServerMap()); + player->setPosition(pos); + player->hp = 20; + SendMovePlayer(player); + SendPlayerHP(player); +} + void Server::UpdateCrafting(u16 peer_id) { DSTACK(__FUNCTION_NAME); @@ -4076,12 +4062,12 @@ void Server::UpdateCrafting(u16 peer_id) /* Calculate crafting stuff */ - if(g_settings.getBool("creative_mode") == false) + if(g_settings->getBool("creative_mode") == false) { InventoryList *clist = player->inventory.getList("craft"); InventoryList *rlist = player->inventory.getList("craftresult"); - if(rlist->getUsedSlots() == 0) + if(rlist && rlist->getUsedSlots() == 0) player->craftresult_is_preview = true; if(rlist && player->craftresult_is_preview) @@ -4147,11 +4133,18 @@ std::wstring Server::getStatusString() os<isSavingEnabled() == false) os<get("motd") != "") + os<get("motd")); return os.str(); } +// Saves g_settings to configpath given at initialization +void Server::saveConfig() +{ + if(m_configpath != "") + g_settings->updateConfigFile(m_configpath.c_str()); +} + v3f findSpawnPos(ServerMap &map) { //return v3f(50,50,50)*BS; @@ -4180,18 +4173,18 @@ v3f findSpawnPos(ServerMap &map) // Don't go underwater if(groundheight < WATER_LEVEL) { - //dstream<<"-> Underwater"< Underwater"< WATER_LEVEL + 4) { - //dstream<<"-> Underwater"< Underwater"<peer_id != 0) { - dstream<<"emergePlayer(): Player already connected"<peer_id = peer_id; // Reset inventory to creative if in creative mode - if(g_settings.getBool("creative_mode")) + if(g_settings->getBool("creative_mode")) { // Warning: double code below // Backup actual inventory @@ -4244,7 +4237,7 @@ Player *Server::emergePlayer(const char *name, const char *password, u16 peer_id */ if(m_env.getPlayer(peer_id) != NULL) { - dstream<<"emergePlayer(): Player with wrong name but same" + infostream<<"emergePlayer(): Player with wrong name but same" " peer_id already exists"<get("default_privs"))); /* Set player position */ - dstream<<"Server: Finding spawn place for player \"" + infostream<<"Server: Finding spawn place for player \"" <getName()<<"\""<getBool("creative_mode")) { // Warning: double code above // Backup actual inventory @@ -4293,7 +4286,7 @@ Player *Server::emergePlayer(const char *name, const char *password, u16 peer_id // Set creative inventory craft_set_creative_inventory(player); } - else if(g_settings.getBool("give_initial_stuff")) + else if(g_settings->getBool("give_initial_stuff")) { craft_give_initial_stuff(player); } @@ -4358,16 +4351,16 @@ void Server::handlePeerChange(PeerChange &c) // 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"; - if(c.timeout) - message += L" (timed out)"; + { + std::wstring name = narrow_to_wide(player->getName()); + message += L"*** "; + message += name; + message += L" left game"; + if(c.timeout) + message += L" (timed out)"; + } } /*// Delete player @@ -4380,6 +4373,32 @@ void Server::handlePeerChange(PeerChange &c) Player *player = m_env.getPlayer(c.peer_id); if(player != NULL) player->peer_id = 0; + + /* + Print out action + */ + { + std::ostringstream os(std::ios_base::binary); + for(core::map::Iterator + i = m_clients.getIterator(); + i.atEnd() == false; i++) + { + RemoteClient *client = i.getNode()->getValue(); + assert(client->peer_id == i.getNode()->getKey()); + if(client->serialization_version == SER_FMT_VER_INVALID) + continue; + // Get player + Player *player = m_env.getPlayer(client->peer_id); + if(!player) + continue; + // Get name of player + os<getName()<<" "; + } + + actionstream<getName() + <<" leaves game. List of players: " + <get("name") == playername) { return PRIV_ALL; } @@ -4434,11 +4453,11 @@ void dedicated_server_loop(Server &server, bool &kill) { DSTACK(__FUNCTION_NAME); - dstream<getFloat("profiler_print_interval"); if(profiler_print_interval != 0) { if(m_profiler_interval.step(0.030, profiler_print_interval)) { - dstream<<"Profiler:"<print(infostream); + g_profiler->clear(); } } @@ -4488,10 +4507,10 @@ void dedicated_server_loop(Server &server, bool &kill) u32 sum = PIChecksum(list); if(sum != sum_old) { - dstream<PrintLine(&dstream); + i->PrintLine(&infostream); } } sum_old = sum;