aboutsummaryrefslogtreecommitdiff
path: root/src/server.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/server.cpp')
-rw-r--r--src/server.cpp289
1 files changed, 178 insertions, 111 deletions
diff --git a/src/server.cpp b/src/server.cpp
index 9f6b755fb..76fa23a93 100644
--- a/src/server.cpp
+++ b/src/server.cpp
@@ -893,7 +893,7 @@ u32 PIChecksum(core::list<PlayerInfo> &l)
Server::Server(
std::string mapsavedir
):
- m_env(new ServerMap(mapsavedir)),
+ m_env(new ServerMap(mapsavedir), this),
m_con(PROTOCOL_ID, 512, CONNECTION_TIMEOUT, this),
m_thread(this),
m_emergethread(this),
@@ -902,9 +902,10 @@ Server::Server(
m_time_of_day_send_timer(0),
m_uptime(0),
m_mapsavedir(mapsavedir),
- m_shutdown_requested(false)
+ m_shutdown_requested(false),
+ m_ignore_map_edit_events(false),
+ m_ignore_map_edit_events_peer_id(0)
{
- //m_flowwater_timer = 0.0;
m_liquid_transform_timer = 0.0;
m_print_info_timer = 0.0;
m_objectdata_timer = 0.0;
@@ -916,6 +917,8 @@ Server::Server(
m_step_dtime_mutex.Init();
m_step_dtime = 0.0;
+ m_env.getMap().addEventReceiver(this);
+
// Load players
m_env.deSerializePlayers(m_mapsavedir);
}
@@ -1191,12 +1194,18 @@ void Server::AsyncRunStep()
}
}
+ if(g_settings.getBool("enable_experimental"))
+ {
+
/*
Check added and deleted active objects
*/
{
JMutexAutoLock envlock(m_env_mutex);
JMutexAutoLock conlock(m_con_mutex);
+
+ // Radius inside which objects are active
+ s16 radius = 32;
for(core::map<u16, RemoteClient*>::Iterator
i = m_clients.getIterator();
@@ -1204,8 +1213,9 @@ void Server::AsyncRunStep()
{
RemoteClient *client = i.getNode()->getValue();
Player *player = m_env.getPlayer(client->peer_id);
+ if(player==NULL)
+ continue;
v3s16 pos = floatToInt(player->getPosition(), BS);
- s16 radius = 32;
core::map<u16, bool> removed_objects;
core::map<u16, bool> added_objects;
@@ -1407,8 +1417,44 @@ void Server::AsyncRunStep()
}
}
+ } // enable_experimental
+
+ /*
+ Send queued-for-sending map edit events.
+ */
+ {
+ while(m_unsent_map_edit_queue.size() != 0)
+ {
+ MapEditEvent* event = m_unsent_map_edit_queue.pop_front();
+
+ if(event->type == MEET_ADDNODE)
+ {
+ dstream<<"Server: MEET_ADDNODE"<<std::endl;
+ sendAddNode(event->p, event->n, event->already_known_by_peer);
+ }
+ else if(event->type == MEET_REMOVENODE)
+ {
+ dstream<<"Server: MEET_REMOVENODE"<<std::endl;
+ sendRemoveNode(event->p, event->already_known_by_peer);
+ }
+ else if(event->type == MEET_OTHER)
+ {
+ dstream<<"WARNING: Server: MEET_OTHER not implemented"
+ <<std::endl;
+ }
+ else
+ {
+ dstream<<"WARNING: Server: Unknown MapEditEvent "
+ <<((u32)event->type)<<std::endl;
+ }
+
+ delete event;
+ }
+ }
+
/*
Send object positions
+ TODO: Get rid of MapBlockObjects
*/
{
float &counter = m_objectdata_timer;
@@ -1964,32 +2010,7 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
/*
Send the removal to all other clients
*/
-
- // Create packet
- u32 replysize = 8;
- SharedBuffer<u8> reply(replysize);
- writeU16(&reply[0], TOCLIENT_REMOVENODE);
- writeS16(&reply[2], p_under.X);
- writeS16(&reply[4], p_under.Y);
- writeS16(&reply[6], p_under.Z);
-
- for(core::map<u16, RemoteClient*>::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;
-
- // Don't send if it's the same one
- if(peer_id == client->peer_id)
- continue;
-
- // Send as reliable
- m_con.Send(client->peer_id, 0, reply, true);
- }
+ sendRemoveNode(p_over, peer_id);
/*
Update and send inventory
@@ -2063,33 +2084,9 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
Remove the node
(this takes some time so it is done after the quick stuff)
*/
+ m_ignore_map_edit_events = true;
m_env.getMap().removeNodeAndUpdate(p_under, modified_blocks);
-
-#if 0
- /*
- Update water
- */
-
- // Update water pressure around modification
- // This also adds it to m_flow_active_nodes if appropriate
-
- MapVoxelManipulator v(&m_env.getMap());
- v.m_disable_water_climb =
- g_settings.getBool("disable_water_climb");
-
- VoxelArea area(p_under-v3s16(1,1,1), p_under+v3s16(1,1,1));
-
- try
- {
- v.updateAreaWaterPressure(area, m_flow_active_nodes);
- }
- catch(ProcessingLimitException &e)
- {
- dstream<<"Processing limit reached (1)"<<std::endl;
- }
-
- v.blitBack(modified_blocks);
-#endif
+ m_ignore_map_edit_events = false;
}
/*
@@ -2150,17 +2147,11 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
n.d = mitem->getMaterial();
if(content_features(n.d).wall_mounted)
n.dir = packDir(p_under - p_over);
-
- // Create packet
- u32 replysize = 8 + MapNode::serializedLength(peer_ser_ver);
- SharedBuffer<u8> reply(replysize);
- writeU16(&reply[0], TOCLIENT_ADDNODE);
- writeS16(&reply[2], p_over.X);
- writeS16(&reply[4], p_over.Y);
- writeS16(&reply[6], p_over.Z);
- n.serialize(&reply[8], peer_ser_ver);
- // Send as reliable
- m_con.SendToAll(0, reply, true);
+
+ /*
+ Send to all players
+ */
+ sendAddNode(p_over, n, 0);
/*
Handle inventory
@@ -2183,7 +2174,9 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
This takes some time so it is done after the quick stuff
*/
core::map<v3s16, MapBlock*> modified_blocks;
+ m_ignore_map_edit_events = true;
m_env.getMap().addNodeAndUpdate(p_over, n, modified_blocks);
+ m_ignore_map_edit_events = false;
/*
Calculate special events
@@ -2595,41 +2588,13 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
}
}
-/*void Server::Send(u16 peer_id, u16 channelnum,
- SharedBuffer<u8> data, bool reliable)
+void Server::onMapEditEvent(MapEditEvent *event)
{
- JMutexAutoLock lock(m_con_mutex);
- m_con.Send(peer_id, channelnum, data, reliable);
-}*/
-
-void Server::SendBlockNoLock(u16 peer_id, MapBlock *block, u8 ver)
-{
- DSTACK(__FUNCTION_NAME);
- /*
- Create a packet with the block in the right format
- */
-
- std::ostringstream os(std::ios_base::binary);
- block->serialize(os, ver);
- std::string s = os.str();
- SharedBuffer<u8> blockdata((u8*)s.c_str(), s.size());
-
- u32 replysize = 8 + blockdata.getSize();
- SharedBuffer<u8> reply(replysize);
- v3s16 p = block->getPos();
- writeU16(&reply[0], TOCLIENT_BLOCKDATA);
- writeS16(&reply[2], p.X);
- writeS16(&reply[4], p.Y);
- writeS16(&reply[6], p.Z);
- memcpy(&reply[8], *blockdata, blockdata.getSize());
-
- /*dstream<<"Sending block ("<<p.X<<","<<p.Y<<","<<p.Z<<")"
- <<": \tpacket size: "<<replysize<<std::endl;*/
-
- /*
- Send packet
- */
- m_con.Send(peer_id, 1, reply, true);
+ dstream<<"Server::onMapEditEvent()"<<std::endl;
+ if(m_ignore_map_edit_events)
+ return;
+ MapEditEvent *e = event->clone();
+ m_unsent_map_edit_queue.push_back(e);
}
core::list<PlayerInfo> Server::getPlayerInfo()
@@ -2759,6 +2724,10 @@ void Server::SendPlayerInfos()
m_con.SendToAll(0, data, true);
}
+/*
+ Craft checking system
+*/
+
enum ItemSpecType
{
ITEM_NONE,
@@ -3109,6 +3078,97 @@ void Server::BroadcastChatMessage(const std::wstring &message)
}
}
+void Server::sendRemoveNode(v3s16 p, u16 ignore_id)
+{
+ JMutexAutoLock conlock(m_con_mutex);
+
+ // Create packet
+ u32 replysize = 8;
+ SharedBuffer<u8> reply(replysize);
+ writeU16(&reply[0], TOCLIENT_REMOVENODE);
+ writeS16(&reply[2], p.X);
+ writeS16(&reply[4], p.Y);
+ writeS16(&reply[6], p.Z);
+
+ for(core::map<u16, RemoteClient*>::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;
+
+ // Don't send if it's the same one
+ if(client->peer_id == ignore_id)
+ continue;
+
+ // Send as reliable
+ m_con.Send(client->peer_id, 0, reply, true);
+ }
+}
+
+void Server::sendAddNode(v3s16 p, MapNode n, u16 ignore_id)
+{
+ for(core::map<u16, RemoteClient*>::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;
+
+ // Don't send if it's the same one
+ if(client->peer_id == ignore_id)
+ continue;
+
+ // Create packet
+ u32 replysize = 8 + MapNode::serializedLength(client->serialization_version);
+ SharedBuffer<u8> reply(replysize);
+ writeU16(&reply[0], TOCLIENT_ADDNODE);
+ writeS16(&reply[2], p.X);
+ writeS16(&reply[4], p.Y);
+ writeS16(&reply[6], p.Z);
+ n.serialize(&reply[8], client->serialization_version);
+
+ // Send as reliable
+ m_con.Send(client->peer_id, 0, reply, true);
+ }
+}
+
+void Server::SendBlockNoLock(u16 peer_id, MapBlock *block, u8 ver)
+{
+ DSTACK(__FUNCTION_NAME);
+ /*
+ Create a packet with the block in the right format
+ */
+
+ std::ostringstream os(std::ios_base::binary);
+ block->serialize(os, ver);
+ std::string s = os.str();
+ SharedBuffer<u8> blockdata((u8*)s.c_str(), s.size());
+
+ u32 replysize = 8 + blockdata.getSize();
+ SharedBuffer<u8> reply(replysize);
+ v3s16 p = block->getPos();
+ writeU16(&reply[0], TOCLIENT_BLOCKDATA);
+ writeS16(&reply[2], p.X);
+ writeS16(&reply[4], p.Y);
+ writeS16(&reply[6], p.Z);
+ memcpy(&reply[8], *blockdata, blockdata.getSize());
+
+ /*dstream<<"Sending block ("<<p.X<<","<<p.Y<<","<<p.Z<<")"
+ <<": \tpacket size: "<<replysize<<std::endl;*/
+
+ /*
+ Send packet
+ */
+ m_con.Send(peer_id, 1, reply, true);
+}
+
void Server::SendBlocks(float dtime)
{
DSTACK(__FUNCTION_NAME);
@@ -3316,16 +3376,16 @@ Player *Server::emergePlayer(const char *name, const char *password,
<<player->getName()<<"\""<<std::endl;
v2s16 nodepos;
-#if 1
+#if 0
player->setPosition(intToFloat(v3s16(
0,
45, //64,
0
), BS));
#endif
-#if 0
- f32 groundheight = 0;
-#if 0
+#if 1
+ s16 groundheight = 0;
+#if 1
// Try to find a good place a few times
for(s32 i=0; i<500; i++)
{
@@ -3334,12 +3394,20 @@ Player *Server::emergePlayer(const char *name, const char *password,
nodepos = v2s16(-range + (myrand()%(range*2)),
-range + (myrand()%(range*2)));
v2s16 sectorpos = getNodeSectorPos(nodepos);
+ /*
+ Ignore position if it is near a chunk edge.
+ Otherwise it would cause excessive loading time at
+ initial generation
+ */
+ {
+ if(m_env.getServerMap().sector_to_chunk(sectorpos+v2s16(1,1))
+ != m_env.getServerMap().sector_to_chunk(sectorpos+v2s16(-1,-1)))
+ continue;
+ }
// Get sector
m_env.getMap().emergeSector(sectorpos);
// Get ground height at point
- groundheight = m_env.getMap().getGroundHeight(nodepos, true);
- // The sector should have been generated -> groundheight exists
- assert(groundheight > GROUNDHEIGHT_VALID_MINVALUE);
+ groundheight = m_env.getServerMap().findGroundLevel(nodepos);
// Don't go underwater
if(groundheight < WATER_LEVEL)
{
@@ -3384,10 +3452,9 @@ Player *Server::emergePlayer(const char *name, const char *password,
player->setPosition(intToFloat(v3s16(
nodepos.X,
- //groundheight + 1,
- groundheight + 15,
+ groundheight + 1,
nodepos.Y
- )));
+ ), BS));
#endif
/*