X-Git-Url: https://git.lizzy.rs/?a=blobdiff_plain;f=src%2Fserver.cpp;h=6d34a0fac1dd89f323f5775463714385f11a661f;hb=61ffe1eac4565bbb74b79677a618e7f4dd894d3c;hp=14c019d52fc8e6e944756e11d672d20e9e4daed9;hpb=2419d0029ac36952aaa74b685d529a3592adb6aa;p=dragonfireclient.git diff --git a/src/server.cpp b/src/server.cpp index 14c019d52..6d34a0fac 100644 --- a/src/server.cpp +++ b/src/server.cpp @@ -39,6 +39,11 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "settings.h" #include "profiler.h" #include "log.h" +#include "script.h" +#include "scriptapi.h" +#include "nodedef.h" +#include "tooldef.h" +#include "craftdef.h" #define PP(x) "("<<(x).X<<","<<(x).Y<<","<<(x).Z<<")" @@ -185,7 +190,7 @@ void * EmergeThread::Thread() <<"("<m_env.getPlayer(peer_id); + Player *player = server->m_env->getPlayer(peer_id); assert(player != NULL); @@ -410,17 +414,13 @@ void RemoteClient::GetNextBlocks(Server *server, float dtime, /*infostream<<"m_nearest_unsent_reset_timer=" < 10.0) + // Reset periodically to workaround for some bugs or stuff + if(m_nearest_unsent_reset_timer > 20.0) { m_nearest_unsent_reset_timer = 0; m_nearest_unsent_d = 0; - /*infostream<<"Resetting m_nearest_unsent_d for " - <getPlayerName(peer_id)<getPlayerName(peer_id)<getS16("max_block_generate_distance"); // Don't loop very much at a time - if(d_max > d_start+1) - d_max = d_start+1; + s16 max_d_increment_at_time = 2; + if(d_max > d_start + max_d_increment_at_time) + d_max = d_start + max_d_increment_at_time; /*if(d_max_gen > d_start+2) d_max_gen = d_start+2;*/ //infostream<<"Starting from "<getPlayerName(peer_id)<m_emerge_queue.addBlock(peer_id, p, flags); server->m_emergethread.trigger(); + + if(nearest_emerged_d == -1) + nearest_emerged_d = d; + } else { + if(nearest_emergefull_d == -1) + nearest_emergefull_d = d; } // get next one. continue; } + if(nearest_sent_d == -1) + nearest_sent_d = d; + /* Add block to send queue */ + /*errorstream<<"sending from d="<getPlayerName(peer_id)< g_settings->getS16("max_block_send_distance")){ + new_nearest_unsent_d = 0; + m_nothing_to_send_pause_timer = 2.0; + /*infostream<<"GetNextBlocks(): d wrapped around for " + <getPlayerName(peer_id) + <<"; setting to 0 and pausing"<= - g_settings->getS16("max_block_send_distance")) - { - // Pause time in seconds - m_nothing_to_send_pause_timer = 1.0; - /*infostream<<"nothing to send to " - <getPlayerName(peer_id) - <<" (d="< players = server->m_env.getPlayers(true); + core::list players = server->m_env->getPlayers(true); // Write player count u16 playercount = players.size(); @@ -946,6 +949,35 @@ u32 PIChecksum(core::list &l) return checksum; } +struct ModSpec +{ + std::string name; + std::string path; + + ModSpec(const std::string &name_="", const std::string path_=""): + name(name_), + path(path_) + {} +}; + +static core::list getMods(core::list &modspaths) +{ + core::list mods; + for(core::list::Iterator i = modspaths.begin(); + i != modspaths.end(); i++){ + std::string modspath = *i; + std::vector dirlist = fs::GetDirListing(modspath); + for(u32 j=0; j mods = getMods(m_modspaths); + for(core::list::Iterator i = mods.begin(); + i != mods.end(); i++){ + ModSpec mod = *i; + infostream<<"Server: Loading mod \""<getMap().addEventReceiver(this); // If file exists, load environment metadata - if(fs::PathExists(m_mapsavedir+"/env_meta.txt")) + if(fs::PathExists(m_mapsavedir+DIR_DELIM+"env_meta.txt")) { infostream<<"Server: Loading environment metadata"<loadMeta(m_mapsavedir); } // Load players infostream<<"Server: Loading players"<deSerializePlayers(m_mapsavedir); } Server::~Server() @@ -1035,13 +1122,13 @@ Server::~Server() Save players */ infostream<<"Server: Saving players"<serializePlayers(m_mapsavedir); /* Save environment metadata */ infostream<<"Server: Saving environment metadata"<saveMeta(m_mapsavedir); } /* @@ -1064,13 +1151,23 @@ Server::~Server() { u16 peer_id = i.getNode()->getKey(); JMutexAutoLock envlock(m_env_mutex); - m_env.removePlayer(peer_id); + m_env->removePlayer(peer_id); }*/ // Delete client delete i.getNode()->getValue(); } } + + // Delete Environment + delete m_env; + + delete m_toolmgr; + delete m_nodedef; + + // Deinitialize scripting + infostream<<"Server: Deinitializing scripting"<setTimeOfDay((m_env->getTimeOfDay() + units) % 24000); //infostream<<"Server: m_time_of_day = "<getValue(); - //Player *player = m_env.getPlayer(client->peer_id); + //Player *player = m_env->getPlayer(client->peer_id); SharedBuffer data = makePacket_TOCLIENT_TIME_OF_DAY( - m_env.getTimeOfDay()); + m_env->getTimeOfDay()); // Send as reliable m_con.Send(client->peer_id, 0, data, true); } @@ -1215,16 +1312,16 @@ void Server::AsyncRunStep() // Step environment ScopeProfiler sp(g_profiler, "SEnv step"); ScopeProfiler sp2(g_profiler, "SEnv step avg", SPT_AVG); - m_env.step(dtime); + m_env->step(dtime); } - const float map_timer_and_unload_dtime = 5.15; + const float map_timer_and_unload_dtime = 2.92; if(m_map_timer_and_unload_interval.step(dtime, map_timer_and_unload_dtime)) { JMutexAutoLock lock(m_env_mutex); // Run Map's timers and unload unused data ScopeProfiler sp(g_profiler, "Server: map timer and unload"); - m_env.getMap().timerUpdate(map_timer_and_unload_dtime, + m_env->getMap().timerUpdate(map_timer_and_unload_dtime, g_settings->getFloat("server_unload_unused_data_timeout")); } @@ -1245,13 +1342,13 @@ void Server::AsyncRunStep() ScopeProfiler sp(g_profiler, "Server: liquid transform"); core::map modified_blocks; - m_env.getMap().transformLiquids(modified_blocks); + m_env->getMap().transformLiquids(modified_blocks); #if 0 /* Update lighting */ core::map lighting_modified_blocks; - ServerMap &map = ((ServerMap&)m_env.getMap()); + ServerMap &map = ((ServerMap&)m_env->getMap()); map.updateLighting(modified_blocks, lighting_modified_blocks); // Add blocks modified by lighting to modified_blocks @@ -1301,7 +1398,7 @@ void Server::AsyncRunStep() { //u16 peer_id = i.getNode()->getKey(); RemoteClient *client = i.getNode()->getValue(); - Player *player = m_env.getPlayer(client->peer_id); + Player *player = m_env->getPlayer(client->peer_id); if(player==NULL) continue; infostream<<"* "<getName()<<"\t"; @@ -1332,7 +1429,7 @@ void Server::AsyncRunStep() i.atEnd() == false; i++) { RemoteClient *client = i.getNode()->getValue(); - Player *player = m_env.getPlayer(client->peer_id); + Player *player = m_env->getPlayer(client->peer_id); if(player==NULL) { // This can happen if the client timeouts somehow @@ -1345,9 +1442,9 @@ void Server::AsyncRunStep() core::map removed_objects; core::map added_objects; - m_env.getRemovedActiveObjects(pos, radius, + m_env->getRemovedActiveObjects(pos, radius, client->m_known_objects, removed_objects); - m_env.getAddedActiveObjects(pos, radius, + m_env->getAddedActiveObjects(pos, radius, client->m_known_objects, added_objects); // Ignore if nothing happened @@ -1370,7 +1467,7 @@ void Server::AsyncRunStep() { // Get object u16 id = i.getNode()->getKey(); - ServerActiveObject* obj = m_env.getActiveObject(id); + ServerActiveObject* obj = m_env->getActiveObject(id); // Add to data buffer for sending writeU16((u8*)buf, i.getNode()->getKey()); @@ -1392,7 +1489,7 @@ void Server::AsyncRunStep() { // Get object u16 id = i.getNode()->getKey(); - ServerActiveObject* obj = m_env.getActiveObject(id); + ServerActiveObject* obj = m_env->getActiveObject(id); // Get object type u8 type = ACTIVEOBJECT_TYPE_INVALID; @@ -1458,7 +1555,7 @@ void Server::AsyncRunStep() } } - m_env.setKnownActiveObjects(whatever); + m_env->setKnownActiveObjects(whatever); #endif } @@ -1470,7 +1567,7 @@ void Server::AsyncRunStep() JMutexAutoLock envlock(m_env_mutex); JMutexAutoLock conlock(m_con_mutex); - ScopeProfiler sp(g_profiler, "Server: sending object messages"); + //ScopeProfiler sp(g_profiler, "Server: sending object messages"); // Key = object id // Value = data sent by object @@ -1479,7 +1576,7 @@ void Server::AsyncRunStep() // Get active object messages from environment for(;;) { - ActiveObjectMessage aom = m_env.getActiveObjectMessage(); + ActiveObjectMessage aom = m_env->getActiveObjectMessage(); if(aom.id == 0) break; @@ -1668,7 +1765,7 @@ void Server::AsyncRunStep() { v3s16 p = i.getNode()->getKey(); modified_blocks2.insert(p, - m_env.getMap().getBlockNoCreateNoEx(p)); + m_env->getMap().getBlockNoCreateNoEx(p)); } // Set blocks not sent for(core::list::Iterator @@ -1710,7 +1807,7 @@ void Server::AsyncRunStep() JMutexAutoLock lock1(m_env_mutex); JMutexAutoLock lock2(m_con_mutex); - ScopeProfiler sp(g_profiler, "Server: sending player positions"); + //ScopeProfiler sp(g_profiler, "Server: sending player positions"); SendObjectData(counter); @@ -1755,15 +1852,15 @@ void Server::AsyncRunStep() JMutexAutoLock lock(m_env_mutex); /*// Unload unused data (delete from memory) - m_env.getMap().unloadUnusedData( + m_env->getMap().unloadUnusedData( g_settings->getFloat("server_unload_unused_sectors_timeout")); */ - /*u32 deleted_count = m_env.getMap().unloadUnusedData( + /*u32 deleted_count = m_env->getMap().unloadUnusedData( g_settings->getFloat("server_unload_unused_sectors_timeout")); */ // Save only changed parts - m_env.getMap().save(true); + m_env->getMap().save(true); /*if(deleted_count > 0) { @@ -1772,10 +1869,10 @@ void Server::AsyncRunStep() }*/ // Save players - m_env.serializePlayers(m_mapsavedir); + m_env->serializePlayers(m_mapsavedir); // Save environment metadata - m_env.saveMeta(m_mapsavedir); + m_env->saveMeta(m_mapsavedir); } } } @@ -1783,14 +1880,13 @@ void Server::AsyncRunStep() void Server::Receive() { DSTACK(__FUNCTION_NAME); - u32 data_maxsize = 10000; - Buffer data(data_maxsize); + SharedBuffer data; u16 peer_id; u32 datasize; try{ { JMutexAutoLock conlock(m_con_mutex); - datasize = m_con.Receive(peer_id, *data, data_maxsize); + datasize = m_con.Receive(peer_id, data); } // This has to be called so that the client list gets synced @@ -1818,7 +1914,7 @@ void Server::Receive() <<" has apparently closed connection. " <<"Removing player."<removePlayer(peer_id);*/ } } @@ -1829,9 +1925,18 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id) JMutexAutoLock envlock(m_env_mutex); JMutexAutoLock conlock(m_con_mutex); - con::Peer *peer; try{ - peer = m_con.GetPeer(peer_id); + Address address = m_con.GetPeerAddress(peer_id); + + // drop player if is ip is banned + if(m_banmanager.isIpBanned(address.serializeString())){ + SendAccessDenied(m_con, peer_id, + L"Your ip is banned. Banned name was " + +narrow_to_wide(m_banmanager.getBanName( + address.serializeString()))); + m_con.DeletePeer(peer_id); + return; + } } catch(con::PeerNotFoundException &e) { @@ -1840,17 +1945,7 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id) return; } - // drop player if is ip is banned - if(m_banmanager.isIpBanned(peer->address.serializeString())){ - SendAccessDenied(m_con, peer_id, - L"Your ip is banned. Banned name was " - +narrow_to_wide(m_banmanager.getBanName( - peer->address.serializeString()))); - m_con.deletePeer(peer_id, false); - return; - } - - u8 peer_ser_ver = getClient(peer->id)->serialization_version; + u8 peer_ser_ver = getClient(peer_id)->serialization_version; try { @@ -1871,7 +1966,7 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id) return; infostream<<"Server: Got TOSERVER_INIT from " - <id<serialization_version = deployed; - getClient(peer->id)->pending_serialization_version = deployed; + getClient(peer_id)->pending_serialization_version = deployed; if(deployed == SER_FMT_VER_INVALID) { @@ -1906,7 +2001,7 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id) net_proto_version = readU16(&data[2+1+PLAYERNAME_SIZE+PASSWORD_SIZE]); } - getClient(peer->id)->net_proto_version = net_proto_version; + getClient(peer_id)->net_proto_version = net_proto_version; if(net_proto_version == 0) { @@ -2034,7 +2129,7 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id) writeU16(&reply[0], TOCLIENT_INIT); writeU8(&reply[2], deployed); writeV3S16(&reply[2+1], floatToInt(player->getPosition()+v3f(0,BS/2,0), BS)); - writeU64(&reply[2+1+6], m_env.getServerMap().getSeed()); + writeU64(&reply[2+1+6], m_env->getServerMap().getSeed()); // Send as reliable m_con.Send(peer_id, 0, reply, true); @@ -2051,27 +2146,36 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id) if(command == TOSERVER_INIT2) { infostream<<"Server: Got TOSERVER_INIT2 from " - <id<id)->serialization_version - = getClient(peer->id)->pending_serialization_version; + getClient(peer_id)->serialization_version + = getClient(peer_id)->pending_serialization_version; /* Send some initialization data */ + + // Send tool definitions + SendToolDef(m_con, peer_id, m_toolmgr); + + // Send node definitions + SendNodeDef(m_con, peer_id, m_nodedef); + + // Send textures + SendTextures(peer_id); // Send player info to all players SendPlayerInfos(); // Send inventory to player - UpdateCrafting(peer->id); - SendInventory(peer->id); + UpdateCrafting(peer_id); + SendInventory(peer_id); // Send player items to all players SendPlayerItems(); - Player *player = m_env.getPlayer(peer_id); + Player *player = m_env->getPlayer(peer_id); // Send HP SendPlayerHP(player); @@ -2079,8 +2183,8 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id) // Send time of day { SharedBuffer data = makePacket_TOCLIENT_TIME_OF_DAY( - m_env.getTimeOfDay()); - m_con.Send(peer->id, 0, data, true); + m_env->getTimeOfDay()); + m_con.Send(peer_id, 0, data, true); } // Send information about server to player in chat @@ -2089,7 +2193,7 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id) // Send information about joining in chat { std::wstring name = L"unknown"; - Player *player = m_env.getPlayer(peer_id); + Player *player = m_env->getPlayer(peer_id); if(player != NULL) name = narrow_to_wide(player->getName()); @@ -2101,7 +2205,7 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id) } // Warnings about protocol version can be issued here - if(getClient(peer->id)->net_proto_version < PROTOCOL_VERSION) + if(getClient(peer_id)->net_proto_version < PROTOCOL_VERSION) { SendChatMessage(peer_id, L"# Server: WARNING: YOUR CLIENT IS OLD AND MAY WORK PROPERLY WITH THIS SERVER"); } @@ -2125,7 +2229,7 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id) if(client->serialization_version == SER_FMT_VER_INVALID) continue; // Get player - Player *player = m_env.getPlayer(client->peer_id); + Player *player = m_env->getPlayer(client->peer_id); if(!player) continue; // Get name of player @@ -2147,7 +2251,7 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id) return; } - Player *player = m_env.getPlayer(peer_id); + Player *player = m_env->getPlayer(peer_id); if(player == NULL){ infostream<<"Server::ProcessData(): Cancelling: " @@ -2255,7 +2359,7 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id) u16 id = readS16(&data[3]); u16 item_i = readU16(&data[5]); - ServerActiveObject *obj = m_env.getActiveObject(id); + ServerActiveObject *obj = m_env->getActiveObject(id); if(obj == NULL) { @@ -2269,10 +2373,23 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id) return; //TODO: Check that object is reasonably close + + // Get ServerRemotePlayer + ServerRemotePlayer *srp = (ServerRemotePlayer*)player; + + // Update wielded item + srp->wieldItem(item_i); - // Left click, pick object up (usually) + // Left click, pick/punch if(button == 0) { + actionstream<getName()<<" punches object " + <getId()<punch(srp); + +#if 0 /* Try creating inventory item */ @@ -2341,6 +2458,7 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id) SendInventory(player->peer_id); } } +#endif } // Right click, do something with object if(button == 1) @@ -2348,18 +2466,16 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id) actionstream<getName()<<" right clicks object " <getId()<hp; - // Do stuff - obj->rightClick(player); - - // Send back stuff - if(player->hp != oldhp) - { - SendPlayerHP(player); - } + obj->rightClick(srp); } + + /* + Update player state to client + */ + SendPlayerHP(player); + UpdateCrafting(player->peer_id); + SendInventory(player->peer_id); } else if(command == TOSERVER_GROUND_ACTION) { @@ -2400,6 +2516,33 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id) NOTE: This can be used in the future to check if somebody is cheating, by checking the timing. */ + bool cannot_punch_node = false; + + MapNode n(CONTENT_IGNORE); + + try + { + n = m_env->getMap().getNode(p_under); + } + catch(InvalidPositionException &e) + { + infostream<<"Server: Not punching: Node not found." + <<" Adding block to emerge queue." + <id); + RemoteClient *client = getClient(peer_id); JMutexAutoLock digmutex(client->m_dig_mutex); client->m_dig_tool_item = -1; #endif @@ -2426,19 +2569,20 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id) u8 mineral = MINERAL_NONE; bool cannot_remove_node = false; - + + MapNode n(CONTENT_IGNORE); try { - MapNode n = m_env.getMap().getNode(p_under); + n = m_env->getMap().getNode(p_under); // Get mineral - mineral = n.getMineral(); + mineral = n.getMineral(m_nodedef); // Get material at position material = n.getContent(); // If not yet cancelled if(cannot_remove_node == false) { // If it's not diggable, do nothing - if(content_diggable(material) == false) + if(m_nodedef->get(material).diggable == false) { infostream<<"Server: Not finishing digging: " <<"Node not diggable" @@ -2450,7 +2594,7 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id) if(cannot_remove_node == false) { // Get node metadata - NodeMetadata *meta = m_env.getMap().getNodeMetadata(p_under); + NodeMetadata *meta = m_env->getMap().getNodeMetadata(p_under); if(meta && meta->nodeRemovalDisabled() == true) { infostream<<"Server: Not finishing digging: " @@ -2531,8 +2675,10 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id) std::string toolname = titem->getToolName(); // Get digging properties for material and tool + ToolDiggingProperties tp = + m_toolmgr->getDiggingProperties(toolname); DiggingProperties prop = - getDiggingProperties(material, toolname); + getDiggingProperties(material, &tp, m_nodedef); if(prop.diggable == false) { @@ -2557,16 +2703,16 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id) InventoryItem *item = NULL; if(mineral != MINERAL_NONE) - item = getDiggedMineralItem(mineral); + item = getDiggedMineralItem(mineral, this); // If not mineral if(item == NULL) { - std::string &dug_s = content_features(material).dug_item; + const std::string &dug_s = m_nodedef->get(material).dug_item; if(dug_s != "") { std::istringstream is(dug_s, std::ios::binary); - item = InventoryItem::deSerialize(is); + item = InventoryItem::deSerialize(is, this); } } @@ -2583,25 +2729,25 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id) item = NULL; if(mineral != MINERAL_NONE) - item = getDiggedMineralItem(mineral); + item = getDiggedMineralItem(mineral, this); // 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; + const std::string &extra_dug_s = m_nodedef->get(material).extra_dug_item; + s32 extra_rarity = m_nodedef->get(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); + std::istringstream is(extra_dug_s, std::ios::binary); + item = InventoryItem::deSerialize(is, this); } } if(item != NULL) { - // Add a item to inventory - player->inventory.addItem("main", item); + // Add a item to inventory + player->inventory.addItem("main", item); // Send inventory UpdateCrafting(player->peer_id); @@ -2616,7 +2762,7 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id) { MapEditEventIgnorer ign(&m_ignore_map_edit_events); - m_env.getMap().removeNodeAndUpdate(p_under, modified_blocks); + m_env->getMap().removeNodeAndUpdate(p_under, modified_blocks); } /* Set blocks not sent to far players @@ -2631,6 +2777,12 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id) continue; client->SetBlocksNotSent(modified_blocks); } + + /* + Run script hook + */ + ServerRemotePlayer *srp = (ServerRemotePlayer*)player; + scriptapi_environment_on_dignode(m_lua, p_under, n, srp); } /* @@ -2657,7 +2809,7 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id) { try{ // Don't add a node if this is not a free space - MapNode n2 = m_env.getMap().getNode(p_over); + MapNode n2 = m_env->getMap().getNode(p_over); bool no_enough_privs = ((getPlayerPrivs(player) & PRIV_BUILD)==0); if(no_enough_privs) @@ -2665,7 +2817,7 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id) <<" because privileges are "<get(n2).buildable_to == false || no_enough_privs) { // Client probably has wrong data. @@ -2691,7 +2843,7 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id) } // Reset build time counter - getClient(peer->id)->m_time_from_building = 0.0; + getClient(peer_id)->m_time_from_building = 0.0; // Create node data MaterialItem *mitem = (MaterialItem*)item; @@ -2703,11 +2855,11 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id) <<" at "<get(n).wall_mounted) n.param2 = packDir(p_under - p_over); // Calculate the direction for furnaces and chests and stuff - if(content_features(n).param_type == CPT_FACEDIR_SIMPLE) + if(m_nodedef->get(n).param_type == CPT_FACEDIR_SIMPLE) { v3f playerpos = player->getPosition(); v3f blockpos = intToFloat(p_over, BS) - playerpos; @@ -2758,7 +2910,7 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id) MapEditEventIgnorer ign(&m_ignore_map_edit_events); std::string p_name = std::string(player->getName()); - m_env.getMap().addNodeAndUpdate(p_over, n, modified_blocks, p_name); + m_env->getMap().addNodeAndUpdate(p_over, n, modified_blocks, p_name); } /* Set blocks not sent to far players @@ -2774,11 +2926,17 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id) client->SetBlocksNotSent(modified_blocks); } + /* + Run script hook + */ + ServerRemotePlayer *srp = (ServerRemotePlayer*)player; + scriptapi_environment_on_placenode(m_lua, p_over, n, srp); + /* Calculate special events */ - /*if(n.d == CONTENT_MESE) + /*if(n.d == LEGN(m_nodedef, "CONTENT_MESE")) { u32 count = 0; for(s16 z=-1; z<=1; z++) @@ -2800,7 +2958,7 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id) Check that the block is loaded so that the item can properly be added to the static list too */ - MapBlock *block = m_env.getMap().getBlockNoCreateNoEx(blockpos); + MapBlock *block = m_env->getMap().getBlockNoCreateNoEx(blockpos); if(block==NULL) { infostream<<"Error while placing object: " @@ -2823,15 +2981,15 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id) // Calculate a position for it v3f pos = intToFloat(p_over, BS); //pos.Y -= BS*0.45; - pos.Y -= BS*0.25; // let it drop a bit + /*pos.Y -= BS*0.25; // let it drop a bit // Randomize a bit pos.X += BS*0.2*(float)myrand_range(-1000,1000)/1000.0; - pos.Z += BS*0.2*(float)myrand_range(-1000,1000)/1000.0; + pos.Z += BS*0.2*(float)myrand_range(-1000,1000)/1000.0;*/ /* Create the object */ - ServerActiveObject *obj = item->createSAO(&m_env, 0, pos); + ServerActiveObject *obj = item->createSAO(m_env, 0, pos); if(obj == NULL) { @@ -2845,7 +3003,7 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id) <<" at "<addActiveObject(obj); infostream<<"Placed object"<getMap().getNodeMetadata(p); if(!meta) return; - if(meta->typeId() != CONTENT_SIGN_WALL) + if(meta->typeId() != LEGN(m_nodedef, "CONTENT_SIGN_WALL")) return; SignNodeMetadata *signmeta = (SignNodeMetadata*)meta; signmeta->setText(text); @@ -2944,19 +3102,14 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id) <<" at "<getMap().getBlockNoCreateNoEx(blockpos); if(block) { - block->setChangedFlag(); + block->raiseModified(MOD_STATE_WRITE_NEEDED, + "sign node text"); } - for(core::map::Iterator - i = m_clients.getIterator(); - i.atEnd()==false; i++) - { - RemoteClient *client = i.getNode()->getValue(); - client->SetBlockNotSent(blockpos); - } + setBlockNotSent(blockpos); } else if(command == TOSERVER_INVENTORY_ACTION) { @@ -3060,8 +3213,8 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id) 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) { + NodeMetadata *meta = m_env->getMap().getNodeMetadata(p); + if(meta && meta->typeId() == LEGN(m_nodedef, "CONTENT_LOCKABLE_CHEST")) { LockingChestNodeMetadata *lcm = (LockingChestNodeMetadata*)meta; if (lcm->getOwner() != player->getName()) return; @@ -3078,8 +3231,8 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id) 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) { + NodeMetadata *meta = m_env->getMap().getNodeMetadata(p); + if(meta && meta->typeId() == LEGN(m_nodedef, "CONTENT_LOCKABLE_CHEST")) { LockingChestNodeMetadata *lcm = (LockingChestNodeMetadata*)meta; if (lcm->getOwner() != player->getName()) return; @@ -3161,7 +3314,7 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id) str_split(message, L' '), paramstring, this, - &m_env, + m_env, player, privs); @@ -3364,7 +3517,7 @@ Inventory* Server::getInventory(InventoryContext *c, std::string id) p.X = stoi(fn.next(",")); p.Y = stoi(fn.next(",")); p.Z = stoi(fn.next(",")); - NodeMetadata *meta = m_env.getMap().getNodeMetadata(p); + NodeMetadata *meta = m_env->getMap().getNodeMetadata(p); if(meta) return meta->getInventory(); infostream<<"nodemeta at ("<getMap().getNodeMetadata(p); if(meta) meta->inventoryModified(); - - for(core::map::Iterator - i = m_clients.getIterator(); - i.atEnd()==false; i++) - { - RemoteClient *client = i.getNode()->getValue(); - client->SetBlockNotSent(blockpos); - } + + MapBlock *block = m_env->getMap().getBlockNoCreateNoEx(blockpos); + if(block) + block->raiseModified(MOD_STATE_WRITE_NEEDED); + + setBlockNotSent(blockpos); return; } @@ -3423,7 +3574,7 @@ core::list Server::getPlayerInfo() core::list list; - core::list players = m_env.getPlayers(); + core::list players = m_env->getPlayers(); core::list::Iterator i; for(i = players.begin(); @@ -3434,11 +3585,10 @@ core::list Server::getPlayerInfo() Player *player = *i; try{ - con::Peer *peer = m_con.GetPeer(player->peer_id); - // Copy info from peer to info struct - info.id = peer->id; - info.address = peer->address; - info.avg_rtt = peer->avg_rtt; + // Copy info from connection to info struct + info.id = player->peer_id; + info.address = m_con.GetPeerAddress(player->peer_id); + info.avg_rtt = m_con.GetPeerAvgRTT(player->peer_id); } catch(con::PeerNotFoundException &e) { @@ -3536,6 +3686,56 @@ void Server::SendDeathscreen(con::Connection &con, u16 peer_id, con.Send(peer_id, 0, data, true); } +void Server::SendToolDef(con::Connection &con, u16 peer_id, + IToolDefManager *tooldef) +{ + DSTACK(__FUNCTION_NAME); + std::ostringstream os(std::ios_base::binary); + + /* + u16 command + u32 length of the next item + serialized ToolDefManager + */ + writeU16(os, TOCLIENT_TOOLDEF); + std::ostringstream tmp_os(std::ios::binary); + tooldef->serialize(tmp_os); + os< > texture_bunches; + texture_bunches.push_back(core::list()); + + u32 texture_size_bunch_total = 0; + core::list mods = getMods(m_modspaths); + for(core::list::Iterator i = mods.begin(); + i != mods.end(); i++){ + ModSpec mod = *i; + std::string texturepath = mod.path + DIR_DELIM + "textures"; + std::vector dirlist = fs::GetDirListing(texturepath); + for(u32 j=0; j= bytes_per_bunch){ + texture_bunches.push_back(core::list()); + texture_size_bunch_total = 0; + } + } + } + + /* Create and send packets */ + + u32 num_bunches = texture_bunches.size(); + for(u32 i=0; i::Iterator + j = texture_bunches[i].begin(); + j != texture_bunches[i].end(); j++){ + os<name); + os<data); + } + + // Make data buffer + std::string s = os.str(); + infostream<<"Server::SendTextures(): bunch "<isSavingEnabled() == false) + if(((ServerMap*)(&m_env->getMap()))->isSavingEnabled() == false) os<get("motd") != "") os<get("motd")); @@ -4130,18 +4458,58 @@ void Server::saveConfig() void Server::notifyPlayer(const char *name, const std::wstring msg) { - Player *player = m_env.getPlayer(name); + Player *player = m_env->getPlayer(name); if(!player) return; SendChatMessage(player->peer_id, std::wstring(L"Server: -!- ")+msg); } +void Server::notifyPlayers(const std::wstring msg) +{ + BroadcastChatMessage(msg); +} + +// IGameDef interface +// Under envlock +IToolDefManager* Server::getToolDefManager() +{ + return m_toolmgr; +} +INodeDefManager* Server::getNodeDefManager() +{ + return m_nodedef; +} +ICraftDefManager* Server::getCraftDefManager() +{ + return m_craftdef; +} +ITextureSource* Server::getTextureSource() +{ + return NULL; +} +u16 Server::allocateUnknownNodeId(const std::string &name) +{ + return m_nodedef->allocateDummy(name); +} + +IWritableToolDefManager* Server::getWritableToolDefManager() +{ + return m_toolmgr; +} +IWritableNodeDefManager* Server::getWritableNodeDefManager() +{ + return m_nodedef; +} +IWritableCraftDefManager* Server::getWritableCraftDefManager() +{ + return m_craftdef; +} + v3f findSpawnPos(ServerMap &map) { //return v3f(50,50,50)*BS; - v2s16 nodepos; - s16 groundheight = 0; + v3s16 nodepos; #if 0 nodepos = v2s16(0,0); @@ -4154,13 +4522,11 @@ v3f findSpawnPos(ServerMap &map) { s32 range = 1 + i; // We're going to try to throw the player to this position - nodepos = v2s16(-range + (myrand()%(range*2)), + v2s16 nodepos2d = v2s16(-range + (myrand()%(range*2)), -range + (myrand()%(range*2))); - v2s16 sectorpos = getNodeSectorPos(nodepos); - // Get sector (NOTE: Don't get because it's slow) - //m_env.getMap().emergeSector(sectorpos); + //v2s16 sectorpos = getNodeSectorPos(nodepos2d); // Get ground height at point (fallbacks to heightmap function) - groundheight = map.findGroundLevel(nodepos); + s16 groundheight = map.findGroundLevel(nodepos2d); // Don't go underwater if(groundheight < WATER_LEVEL) { @@ -4173,22 +4539,33 @@ v3f findSpawnPos(ServerMap &map) //infostream<<"-> Underwater"<= 2){ + is_good = true; + nodepos.Y -= 1; + break; + } + } + nodepos.Y++; + } + if(is_good){ + // Found a good place + //infostream<<"Searched through "<getPlayer(name); if(player != NULL) { // If player is already connected, cancel @@ -4217,7 +4594,7 @@ Player *Server::emergePlayer(const char *name, const char *password, u16 peer_id player->inventory_backup = new Inventory(); *(player->inventory_backup) = player->inventory; // Set creative inventory - craft_set_creative_inventory(player); + craft_set_creative_inventory(player, this); } return player; @@ -4226,7 +4603,7 @@ Player *Server::emergePlayer(const char *name, const char *password, u16 peer_id /* If player with the wanted peer_id already exists, cancel. */ - if(m_env.getPlayer(peer_id) != NULL) + if(m_env->getPlayer(peer_id) != NULL) { infostream<<"emergePlayer(): Player with wrong name but same" " peer_id already exists"<peer_id = c.peer_id; - //player->peer_id = PEER_ID_INEXISTENT; - player->peer_id = peer_id; - player->updateName(name); + // Add authentication stuff m_authmanager.add(name); m_authmanager.setPassword(name, password); m_authmanager.setPrivs(name, @@ -4252,17 +4625,17 @@ Player *Server::emergePlayer(const char *name, const char *password, u16 peer_id */ infostream<<"Server: Finding spawn place for player \"" - <getName()<<"\""<getServerMap()); - player->setPosition(pos); + player = new ServerRemotePlayer(m_env, pos, peer_id, name); /* Add player to environment */ - m_env.addPlayer(player); + m_env->addPlayer(player); /* Add stuff to inventory @@ -4275,11 +4648,11 @@ Player *Server::emergePlayer(const char *name, const char *password, u16 peer_id player->inventory_backup = new Inventory(); *(player->inventory_backup) = player->inventory; // Set creative inventory - craft_set_creative_inventory(player); + craft_set_creative_inventory(player, this); } else if(g_settings->getBool("give_initial_stuff")) { - craft_give_initial_stuff(player); + craft_give_initial_stuff(player, this); } return player; @@ -4333,7 +4706,7 @@ void Server::handlePeerChange(PeerChange &c) { // Get object u16 id = i.getNode()->getKey(); - ServerActiveObject* obj = m_env.getActiveObject(id); + ServerActiveObject* obj = m_env->getActiveObject(id); if(obj && obj->m_known_by_count > 0) obj->m_known_by_count--; @@ -4342,7 +4715,7 @@ void Server::handlePeerChange(PeerChange &c) // Collect information about leaving in chat std::wstring message; { - Player *player = m_env.getPlayer(c.peer_id); + Player *player = m_env->getPlayer(c.peer_id); if(player != NULL) { std::wstring name = narrow_to_wide(player->getName()); @@ -4356,12 +4729,12 @@ void Server::handlePeerChange(PeerChange &c) /*// Delete player { - m_env.removePlayer(c.peer_id); + m_env->removePlayer(c.peer_id); }*/ // Set player client disconnected { - Player *player = m_env.getPlayer(c.peer_id); + Player *player = m_env->getPlayer(c.peer_id); if(player != NULL) player->peer_id = 0; @@ -4380,7 +4753,7 @@ void Server::handlePeerChange(PeerChange &c) if(client->serialization_version == SER_FMT_VER_INVALID) continue; // Get player - Player *player = m_env.getPlayer(client->peer_id); + Player *player = m_env->getPlayer(client->peer_id); if(!player) continue; // Get name of player