v3s16 center = getNodeBlockPos(center_nodepos);
// Camera position and direction
- v3f camera_pos =
- playerpos + v3f(0, BS+BS/2, 0);
+ v3f camera_pos = player->getEyePosition();
v3f camera_dir = v3f(0,0,1);
camera_dir.rotateYZBy(player->getPitch());
camera_dir.rotateXZBy(player->getYaw());
Don't generate or send if not in sight
*/
- if(isBlockInSight(p, camera_pos, camera_dir, 10000*BS) == false)
+ if(isBlockInSight(p, camera_pos, camera_dir, M_PI, 10000*BS) == false)
{
continue;
}
u16 command
u16 number of player positions
for each player:
+ u16 peer_id
v3s32 position*100
v3s32 speed*100
s32 pitch*100
m_env(new ServerMap(mapsavedir), this),
m_con(PROTOCOL_ID, 512, CONNECTION_TIMEOUT, this),
m_authmanager(mapsavedir+"/auth.txt"),
+ m_banmanager(mapsavedir+"/ipban.txt"),
m_thread(this),
m_emergethread(this),
m_time_counter(0),
m_uptime.set(m_uptime.get() + dtime);
}
+ {
+ // 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();
+ }
+
/*
Update m_time_of_day and overall game time
*/
}
}
- {
- // 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
}
else if(event->type == MEET_OTHER)
{
+ dstream<<"Server: MEET_OTHER"<<std::endl;
prof.add("MEET_OTHER", 1);
- dstream<<"WARNING: Server: MEET_OTHER not implemented"
- <<std::endl;
+ for(core::map<v3s16, bool>::Iterator
+ i = event->modified_blocks.getIterator();
+ i.atEnd()==false; i++)
+ {
+ v3s16 p = i.getNode()->getKey();
+ setBlockNotSent(p);
+ }
}
else
{
// Auth stuff
if(m_authmanager.isModified())
m_authmanager.save();
+
+ //Bann stuff
+ if(m_banmanager.isModified())
+ m_banmanager.save();
// Map
JMutexAutoLock lock(m_env_mutex);
<<peer_id<<" not found"<<std::endl;
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;
//peer->serialization_version = deployed;
getClient(peer->id)->pending_serialization_version = deployed;
-
+
if(deployed == SER_FMT_VER_INVALID)
{
derr_server<<DTIME<<"Server: Cannot negotiate "
}
/*
- Check network protocol version
+ Read and check network protocol version
*/
+
u16 net_proto_version = 0;
if(datasize >= 2+1+PLAYERNAME_SIZE+PASSWORD_SIZE+2)
{
net_proto_version = readU16(&data[2+1+PLAYERNAME_SIZE+PASSWORD_SIZE]);
}
+
+ getClient(peer->id)->net_proto_version = net_proto_version;
+
if(net_proto_version == 0)
{
- /*SendAccessDenied(m_con, peer_id,
- L"Your client is too old (network protocol)");
- return;*/
- SendChatMessage(peer_id, L"# Server: NOTE: YOUR CLIENT IS OLD AND DOES NOT WORK PROPERLY WITH THIS SERVER");
+ SendAccessDenied(m_con, peer_id,
+ L"Your client is too old. Please upgrade.");
+ return;
}
/*
// Get password
char password[PASSWORD_SIZE];
- if(datasize >= 2+1+PLAYERNAME_SIZE)
+ if(datasize < 2+1+PLAYERNAME_SIZE+PASSWORD_SIZE)
{
// old version - assume blank password
password[0] = 0;
checkpwd = g_settings.get("default_password");
}
- if(password != checkpwd && checkpwd != "")
+ /*dstream<<"Server: Client gave password '"<<password
+ <<"', the correct one is '"<<checkpwd<<"'"<<std::endl;*/
+
+ if(password != checkpwd && m_authmanager.exists(playername))
{
derr_server<<DTIME<<"Server: peer_id="<<peer_id
<<": supplied invalid password for "
UpdateCrafting(peer->id);
SendInventory(peer->id);
+ // Send player items to all players
+ SendPlayerItems();
+
// Send HP
{
Player *player = m_env.getPlayer(peer_id);
message += L" joined game";
BroadcastChatMessage(message);
}
+
+ // Warnings about protocol version can be issued here
+ /*if(getClient(peer->id)->net_proto_version == 0)
+ {
+ SendChatMessage(peer_id, L"# Server: NOTE: YOUR CLIENT IS OLD AND DOES NOT WORK PROPERLY WITH THIS SERVER");
+ }*/
return;
}
if(g_settings.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"<<std::endl;
return;
return;
}
+ /*
+ If in creative mode, item dropping is disabled unless
+ player has build privileges
+ */
+ if(g_settings.getBool("creative_mode") &&
+ (getPlayerPrivs(player) & PRIV_BUILD) == 0)
+ {
+ derr_server<<"Not allowing player to drop item: "
+ "creative mode and no build privs"<<std::endl;
+ return;
+ }
+
dout_server<<"Placing a miscellaneous item on map"
<<std::endl;
mlist->addItem(item1);
}
}
+ // Disallow moving items if not allowed to build
+ else if((getPlayerPrivs(player) & PRIV_BUILD) == 0)
+ return;
}
if(disable_action == false)
u64 privs = getPlayerPrivs(player);
// Parse commands
- std::wstring commandprefix = L"/#";
- if(message.substr(0, commandprefix.size()) == commandprefix)
+ if(message[0] == L'/')
{
- line += L"Server: ";
+ size_t strip_size = 1;
+ if (message[1] == L'#') // support old-style commans
+ ++strip_size;
+ message = message.substr(strip_size);
- message = message.substr(commandprefix.size());
-
WStrfnd f1(message);
f1.next(L" "); // Skip over /#whatever
std::wstring paramstring = f1.next(L"");
player,
privs);
- line += processServerCommand(ctx);
- send_to_sender = ctx->flags & 1;
- send_to_others = ctx->flags & 2;
+ std::wstring reply(processServerCommand(ctx));
+ send_to_sender = ctx->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;
}
newpwd += c;
}
+ dstream<<"Server: Client requests a password change from "
+ <<"'"<<oldpwd<<"' to '"<<newpwd<<"'"<<std::endl;
+
std::string playername = player->getName();
if(m_authmanager.exists(playername) == false)
}
std::string checkpwd = m_authmanager.getPassword(playername);
-
+
if(oldpwd != checkpwd)
{
dstream<<"Server: invalid old password"<<std::endl;
<<std::endl;
SendChatMessage(peer_id, L"Password change successful");
}
+ else if (command == TOSERVER_PLAYERITEM)
+ {
+ if (datasize < 2+2)
+ return;
+
+ u16 item = readU16(&data[2]);
+ player->wieldItem(item);
+ SendWieldedItem(player);
+ }
else
{
derr_server<<"WARNING: Server::ProcessData(): Ignoring "
m_con.Send(peer_id, 0, data, true);
}
+std::string getWieldedItemString(const Player *player)
+{
+ const InventoryItem *item = player->getWieldItem();
+ if (item == NULL)
+ return std::string("");
+ std::ostringstream os(std::ios_base::binary);
+ item->serialize(os);
+ return os.str();
+}
+
+void Server::SendWieldedItem(const Player* player)
+{
+ DSTACK(__FUNCTION_NAME);
+
+ assert(player);
+
+ std::ostringstream os(std::ios_base::binary);
+
+ writeU16(os, TOCLIENT_PLAYERITEM);
+ writeU16(os, 1);
+ writeU16(os, player->peer_id);
+ os<<serializeString(getWieldedItemString(player));
+
+ // Make data buffer
+ std::string s = os.str();
+ SharedBuffer<u8> data((u8*)s.c_str(), s.size());
+
+ m_con.SendToAll(0, data, true);
+}
+
+void Server::SendPlayerItems()
+{
+ DSTACK(__FUNCTION_NAME);
+
+ std::ostringstream os(std::ios_base::binary);
+ core::list<Player *> players = m_env.getPlayers(true);
+
+ writeU16(os, TOCLIENT_PLAYERITEM);
+ writeU16(os, players.size());
+ core::list<Player *>::Iterator i;
+ for(i = players.begin(); i != players.end(); ++i)
+ {
+ Player *p = *i;
+ writeU16(os, p->peer_id);
+ os<<serializeString(getWieldedItemString(p));
+ }
+
+ // Make data buffer
+ std::string s = os.str();
+ SharedBuffer<u8> data((u8*)s.c_str(), s.size());
+
+ m_con.SendToAll(0, data, true);
+}
+
void Server::SendChatMessage(u16 peer_id, const std::wstring &message)
{
DSTACK(__FUNCTION_NAME);
// Reset inventory to creative if in creative mode
if(g_settings.getBool("creative_mode"))
{
+ // Warning: double code below
+ // Backup actual inventory
+ player->inventory_backup = new Inventory();
+ *(player->inventory_backup) = player->inventory;
+ // Set creative inventory
craft_set_creative_inventory(player);
}
if(g_settings.getBool("creative_mode"))
{
+ // Warning: double code above
+ // Backup actual inventory
+ player->inventory_backup = new Inventory();
+ *(player->inventory_backup) = player->inventory;
+ // Set creative inventory
craft_set_creative_inventory(player);
}
else if(g_settings.getBool("give_initial_stuff"))