v3s16 center_nodepos = floatToInt(playerpos, BS);
v3s16 center = getNodeBlockPos(center_nodepos);
- s16 d_max = g_settings->getS16("active_object_range");
-
- // Number of blocks whose objects were written to bos
- u16 blockcount = 0;
-
- std::ostringstream bos(std::ios_base::binary);
-
- for(s16 d = 0; d <= d_max; d++)
- {
- core::list<v3s16> list;
- getFacePositions(list, d);
-
- core::list<v3s16>::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<JMutexAutoLock> 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<<bos.str();
-
/*
Send data
*/
ScopeProfiler sp(g_profiler, "Server: checking added and deleted objects");
// Radius inside which objects are active
- s16 radius = 32;
+ s16 radius = g_settings->getS16("active_object_send_range_blocks");
+ radius *= MAP_BLOCKSIZE;
for(core::map<u16, RemoteClient*>::Iterator
i = m_clients.getIterator();
}
/* Uhh... this should actually be a warning but let's do it like this */
- if(net_proto_version < 2)
+ if(g_settings->getBool("strict_protocol_version_checking"))
{
- SendAccessDenied(m_con, peer_id,
- L"Your client is too old. Please upgrade.");
- return;
+ if(net_proto_version < PROTOCOL_VERSION)
+ {
+ SendAccessDenied(m_con, peer_id,
+ L"Your client is too old. Please upgrade.");
+ 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: \""<<test_os.str()
- <<"\""<<std::endl;
- std::istringstream test_is(test_os.str());
- player->deSerialize(test_is);
- }*/
-
// If failed, cancel
if(player == NULL)
{
return;
}
- /*
- // If a client is already connected to the player, cancel
- if(player->peer_id != 0)
- {
- derr_server<<DTIME<<"Server: peer_id="<<peer_id
- <<" tried to connect to "
- "an already connected player (peer_id="
- <<player->peer_id<<")"<<std::endl;
- return;
- }
- // Set client of player
- player->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
*/
}
// Warnings about protocol version can be issued here
- /*if(getClient(peer->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
+ */
+ {
+ Player *player = m_env.getPlayer(peer_id);
+ HandlePlayerHP(player, 0);
+ }
return;
}
}
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"<<std::endl;
- return;
- }
-
- MapBlockObject *obj = block->getObject(id);
-
- if(obj == NULL)
- {
- derr_server<<"CLICK_OBJECT object not found"<<std::endl;
- return;
- }
-
- //TODO: Check that object is reasonably close
-
- // Left click
- if(button == 0)
- {
- InventoryList *ilist = player->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"<<std::endl;
- return;
- }
-
- /*
- Create the inventory item
- */
- InventoryItem *item = NULL;
- // If it is an item-object, take the item from it
- if(obj->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);
- }
+ derr_server<<"Server: CLICK_OBJECT not supported anymore"<<std::endl;
+ return;
}
else if(command == TOSERVER_CLICK_ACTIVEOBJECT)
{
*/
u8 button = readU8(&data[2]);
u16 id = readS16(&data[3]);
- u16 item_i = readU16(&data[11]);
+ u16 item_i = readU16(&data[5]);
ServerActiveObject *obj = m_env.getActiveObject(id);
v3f objpos = obj->getBasePosition();
v3f dir = (objpos - playerpos).normalize();
- u16 wear = obj->punch(toolname, dir);
+ u16 wear = obj->punch(toolname, dir, player->getName());
if(titem)
{
#endif
else if(command == TOSERVER_SIGNTEXT)
{
- if((getPlayerPrivs(player) & PRIV_BUILD) == 0)
- return;
- /*
- u16 command
- v3s16 blockpos
- s16 id
- u16 textlen
- textdata
- */
- std::string datastring((char*)&data[2], datasize-2);
- std::istringstream is(datastring, std::ios_base::binary);
- u8 buf[6];
- // Read stuff
- is.read((char*)buf, 6);
- v3s16 blockpos = readV3S16(buf);
- is.read((char*)buf, 2);
- s16 id = readS16(buf);
- is.read((char*)buf, 2);
- u16 textlen = readU16(buf);
- std::string text;
- for(u16 i=0; i<textlen; i++)
- {
- is.read((char*)buf, 1);
- text += (char)buf[0];
- }
-
- MapBlock *block = NULL;
- try
- {
- block = m_env.getMap().getBlockNoCreate(blockpos);
- }
- catch(InvalidPositionException &e)
- {
- derr_server<<"Error while setting sign text: "
- "block not found"<<std::endl;
- return;
- }
-
- MapBlockObject *obj = block->getObject(id);
- if(obj == NULL)
- {
- derr_server<<"Error while setting sign text: "
- "object not found"<<std::endl;
- return;
- }
-
- if(obj->getTypeId() != MAPBLOCKOBJECT_TYPE_SIGN)
- {
- derr_server<<"Error while setting sign text: "
- "object is not a sign"<<std::endl;
- return;
- }
-
- ((SignObject*)obj)->setText(text);
-
- obj->getBlock()->setChangedFlag();
+ derr_server<<"Server: TOSERVER_SIGNTEXT not supported anymore"
+ <<std::endl;
+ return;
}
else if(command == TOSERVER_SIGNNODETEXT)
{
}
else if(command == TOSERVER_DAMAGE)
{
+ std::string datastring((char*)&data[2], datasize-2);
+ std::istringstream is(datastring, std::ios_base::binary);
+ u8 damage = readU8(is);
+
if(g_settings->getBool("enable_damage"))
{
- std::string datastring((char*)&data[2], datasize-2);
- std::istringstream is(datastring, std::ios_base::binary);
- u8 damage = readU8(is);
- if(player->hp > damage)
- {
- player->hp -= damage;
- }
- else
- {
- player->hp = 0;
-
- dstream<<"TODO: Server: TOSERVER_HP_DECREMENT: Player dies"
- <<std::endl;
-
- v3f pos = findSpawnPos(m_env.getServerMap());
- player->setPosition(pos);
- player->hp = 20;
- SendMovePlayer(player);
- SendPlayerHP(player);
-
- //TODO: Throw items around
- }
+ HandlePlayerHP(player, damage);
+ }
+ else
+ {
+ SendPlayerHP(player);
}
-
- SendPlayerHP(player);
}
else if(command == TOSERVER_PASSWORD)
{
<<std::endl;
SendChatMessage(peer_id, L"Password change successful");
}
- else if (command == TOSERVER_PLAYERITEM)
+ else if(command == TOSERVER_PLAYERITEM)
{
if (datasize < 2+2)
return;
player->wieldItem(item);
SendWieldedItem(player);
}
+ else if(command == TOSERVER_RESPAWN)
+ {
+ if(player->hp != 0)
+ return;
+
+ RespawnPlayer(player);
+ }
else
{
derr_server<<"WARNING: Server::ProcessData(): Ignoring "
con.Send(peer_id, 0, data, true);
}
+void Server::SendDeathscreen(con::Connection &con, u16 peer_id,
+ bool set_camera_point_target, v3f camera_point_target)
+{
+ DSTACK(__FUNCTION_NAME);
+ std::ostringstream os(std::ios_base::binary);
+
+ writeU16(os, TOCLIENT_DEATHSCREEN);
+ writeU8(os, set_camera_point_target);
+ writeV3F1000(os, camera_point_target);
+
+ // Make data buffer
+ std::string s = os.str();
+ SharedBuffer<u8> data((u8*)s.c_str(), s.size());
+ // Send as reliable
+ con.Send(peer_id, 0, data, true);
+}
+
/*
Non-static send methods
*/
Something random
*/
+void Server::HandlePlayerHP(Player *player, s16 damage)
+{
+ if(player->hp > damage)
+ {
+ player->hp -= damage;
+ SendPlayerHP(player);
+ }
+ else
+ {
+ dstream<<"Server::HandlePlayerHP(): Player "
+ <<player->getName()<<" dies"<<std::endl;
+
+ player->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);