#include "log.h"
#include "map.h"
#include "mapsector.h"
+#include "minimap.h"
#include "nodedef.h"
#include "serialization.h"
#include "server.h"
-#include "strfnd.h"
+#include "util/strfnd.h"
#include "network/clientopcodes.h"
+#include "script/clientscripting.h"
#include "util/serialize.h"
#include "util/srp.h"
+#include "tileanimation.h"
void Client::handleCommand_Deprecated(NetworkPacket* pkt)
{
AuthMechanism chosen_auth_mechanism = choseAuthMech(auth_mechs);
infostream << "Client: TOCLIENT_HELLO received with "
- << "serialization_ver=" << serialization_ver
+ << "serialization_ver=" << (u32)serialization_ver
<< ", auth_mechs=" << auth_mechs
+ << ", proto_ver=" << proto_ver
<< ", compression_mode=" << compression_mode
<< ". Doing auth with mech " << chosen_auth_mechanism << std::endl;
void Client::handleCommand_AuthAccept(NetworkPacket* pkt)
{
- m_chosen_auth_mech = AUTH_MECHANISM_NONE;
deleteAuthData();
v3f playerpos;
playerpos -= v3f(0, BS / 2, 0);
// Set player position
- Player *player = m_env.getLocalPlayer();
+ LocalPlayer *player = m_env.getLocalPlayer();
assert(player != NULL);
player->setPosition(playerpos);
}
void Client::handleCommand_AcceptSudoMode(NetworkPacket* pkt)
{
- m_chosen_auth_mech = AUTH_MECHANISM_NONE;
deleteAuthData();
m_password = m_new_password;
}
void Client::handleCommand_DenySudoMode(NetworkPacket* pkt)
{
- m_chat_queue.push(L"Password change denied. Password NOT changed.");
+ pushToChatQueue(L"Password change denied. Password NOT changed.");
// reset everything and be sad
deleteAuthData();
- m_chosen_auth_mech = AUTH_MECHANISM_NONE;
}
void Client::handleCommand_InitLegacy(NetworkPacket* pkt)
{
if (pkt->getSize() < 1)
return;
- u8 deployed;
- *pkt >> deployed;
+ u8 server_ser_ver;
+ *pkt >> server_ser_ver;
infostream << "Client: TOCLIENT_INIT_LEGACY received with "
- "deployed=" << ((int)deployed & 0xff) << std::endl;
+ "server_ser_ver=" << ((int)server_ser_ver & 0xff) << std::endl;
- if (!ser_ver_supported(deployed)) {
+ if (!ser_ver_supported(server_ser_ver)) {
infostream << "Client: TOCLIENT_INIT_LEGACY: Server sent "
<< "unsupported ser_fmt_ver"<< std::endl;
return;
}
- m_server_ser_ver = deployed;
- m_proto_ver = deployed;
+ m_server_ser_ver = server_ser_ver;
+
+ // We can be totally wrong with this guess
+ // but we only need some value < 25.
+ m_proto_ver = 24;
// Get player position
v3s16 playerpos_s16(0, BS * 2 + BS * 20, 0);
// Set player position
- Player *player = m_env.getLocalPlayer();
+ LocalPlayer *player = m_env.getLocalPlayer();
assert(player != NULL);
player->setPosition(playerpos_f);
u8 denyCode = SERVER_ACCESSDENIED_UNEXPECTED_DATA;
*pkt >> denyCode;
- if (denyCode == SERVER_ACCESSDENIED_CUSTOM_STRING) {
+ if (denyCode == SERVER_ACCESSDENIED_SHUTDOWN ||
+ denyCode == SERVER_ACCESSDENIED_CRASH) {
*pkt >> m_access_denied_reason;
- }
- else if (denyCode < SERVER_ACCESSDENIED_MAX) {
+ if (m_access_denied_reason == "") {
+ m_access_denied_reason = accessDeniedStrings[denyCode];
+ }
+ u8 reconnect;
+ *pkt >> reconnect;
+ m_access_denied_reconnect = reconnect & 1;
+ } else if (denyCode == SERVER_ACCESSDENIED_CUSTOM_STRING) {
+ *pkt >> m_access_denied_reason;
+ } else if (denyCode < SERVER_ACCESSDENIED_MAX) {
m_access_denied_reason = accessDeniedStrings[denyCode];
+ } else {
+ // Allow us to add new error messages to the
+ // protocol without raising the protocol version, if we want to.
+ // Until then (which may be never), this is outside
+ // of the defined protocol.
+ *pkt >> m_access_denied_reason;
+ if (m_access_denied_reason == "") {
+ m_access_denied_reason = "Unknown";
+ }
}
}
// 13/03/15 Legacy code from 0.4.12 and lesser. must stay 1 year
if (pkt->getSize() >= 2) {
std::wstring wide_reason;
*pkt >> wide_reason;
- m_access_denied_reason = wide_to_narrow(wide_reason);
+ m_access_denied_reason = wide_to_utf8(wide_reason);
}
}
}
std::string datastring(pkt->getString(0), pkt->getSize());
std::istringstream is(datastring, std::ios_base::binary);
- Player *player = m_env.getLocalPlayer();
+ LocalPlayer *player = m_env.getLocalPlayer();
assert(player != NULL);
player->inventory.deSerialize(is);
message += (wchar_t)read_wchar;
}
- m_chat_queue.push(message);
+ // If chat message not consummed by client lua API
+ if (!m_script->on_receiving_message(wide_to_utf8(message))) {
+ pushToChatQueue(message);
+ }
}
void Client::handleCommand_ActiveObjectRemoveAdd(NetworkPacket* pkt)
string message
}
*/
- char buf[6];
- // Get all data except the command number
std::string datastring(pkt->getString(0), pkt->getSize());
- // Throw them in an istringstream
std::istringstream is(datastring, std::ios_base::binary);
try {
- while(is.eof() == false) {
- is.read(buf, 2);
- u16 id = readU16((u8*)buf);
- if (is.eof())
+ while (is.good()) {
+ u16 id = readU16(is);
+ if (!is.good())
break;
- is.read(buf, 2);
- size_t message_size = readU16((u8*)buf);
- std::string message;
- message.reserve(message_size);
- for (u32 i = 0; i < message_size; i++) {
- is.read(buf, 1);
- message.append(buf, 1);
- }
+
+ std::string message = deSerializeString(is);
+
// Pass on to the environment
m_env.processActiveObjectMessage(id, message);
}
- // Packet could be unreliable then ignore it
- } catch (PacketError &e) {
- infostream << "handleCommand_ActiveObjectMessages: " << e.what()
- << ". The packet is unreliable, ignoring" << std::endl;
+ } catch (SerializationError &e) {
+ errorstream << "Client::handleCommand_ActiveObjectMessages: "
+ << "caught SerializationError: " << e.what() << std::endl;
}
}
void Client::handleCommand_Movement(NetworkPacket* pkt)
{
- Player *player = m_env.getLocalPlayer();
+ LocalPlayer *player = m_env.getLocalPlayer();
assert(player != NULL);
float mad, maa, maf, msw, mscr, msf, mscl, msj, lf, lfs, ls, g;
void Client::handleCommand_HP(NetworkPacket* pkt)
{
- Player *player = m_env.getLocalPlayer();
+ LocalPlayer *player = m_env.getLocalPlayer();
assert(player != NULL);
u8 oldhp = player->hp;
void Client::handleCommand_Breath(NetworkPacket* pkt)
{
- Player *player = m_env.getLocalPlayer();
+ LocalPlayer *player = m_env.getLocalPlayer();
assert(player != NULL);
u16 breath;
void Client::handleCommand_MovePlayer(NetworkPacket* pkt)
{
- Player *player = m_env.getLocalPlayer();
+ LocalPlayer *player = m_env.getLocalPlayer();
assert(player != NULL);
v3f pos;
*pkt >> pos >> pitch >> yaw;
+ player->got_teleported = true;
player->setPosition(pos);
infostream << "Client got TOCLIENT_MOVE_PLAYER"
void Client::handleCommand_PlayerItem(NetworkPacket* pkt)
{
- infostream << "Client: WARNING: Ignoring TOCLIENT_PLAYERITEM" << std::endl;
+ warningstream << "Client: Ignoring TOCLIENT_PLAYERITEM" << std::endl;
}
void Client::handleCommand_DeathScreen(NetworkPacket* pkt)
// Mesh update thread must be stopped while
// updating content definitions
- sanity_check(!m_mesh_update_thread.IsRunning());
+ sanity_check(!m_mesh_update_thread.isRunning());
for (u16 i = 0; i < num_files; i++) {
std::string name, sha1_base64;
m_media_downloader->addFile(name, sha1_raw);
}
- std::vector<std::string> remote_media;
try {
std::string str;
*pkt >> str;
Strfnd sf(str);
- while(!sf.atend()) {
+ while(!sf.at_end()) {
std::string baseurl = trim(sf.next(","));
if (baseurl != "")
m_media_downloader->addRemoteServer(baseurl);
// Mesh update thread must be stopped while
// updating content definitions
- sanity_check(!m_mesh_update_thread.IsRunning());
+ sanity_check(!m_mesh_update_thread.isRunning());
for (u32 i=0; i < num_files; i++) {
std::string name;
void Client::handleCommand_ToolDef(NetworkPacket* pkt)
{
- infostream << "Client: WARNING: Ignoring TOCLIENT_TOOLDEF" << std::endl;
+ warningstream << "Client: Ignoring TOCLIENT_TOOLDEF" << std::endl;
}
void Client::handleCommand_NodeDef(NetworkPacket* pkt)
// Mesh update thread must be stopped while
// updating content definitions
- sanity_check(!m_mesh_update_thread.IsRunning());
+ sanity_check(!m_mesh_update_thread.isRunning());
// Decompress node definitions
std::string datastring(pkt->getString(0), pkt->getSize());
void Client::handleCommand_CraftItemDef(NetworkPacket* pkt)
{
- infostream << "Client: WARNING: Ignoring TOCLIENT_CRAFTITEMDEF" << std::endl;
+ warningstream << "Client: Ignoring TOCLIENT_CRAFTITEMDEF" << std::endl;
}
void Client::handleCommand_ItemDef(NetworkPacket* pkt)
// Mesh update thread must be stopped while
// updating content definitions
- sanity_check(!m_mesh_update_thread.IsRunning());
+ sanity_check(!m_mesh_update_thread.isRunning());
// Decompress item definitions
std::string datastring(pkt->getString(0), pkt->getSize());
*pkt >> server_id;
- std::map<s32, int>::iterator i =
- m_sounds_server_to_client.find(server_id);
-
+ UNORDERED_MAP<s32, int>::iterator i = m_sounds_server_to_client.find(server_id);
if (i != m_sounds_server_to_client.end()) {
int client_id = i->second;
m_sound->stopSound(client_id);
void Client::handleCommand_InventoryFormSpec(NetworkPacket* pkt)
{
- Player *player = m_env.getLocalPlayer();
+ LocalPlayer *player = m_env.getLocalPlayer();
assert(player != NULL);
// Store formspec in LocalPlayer
bool collisiondetection = readU8(is);
std::string texture = deSerializeLongString(is);
bool vertical = false;
+ bool collision_removal = false;
+ struct TileAnimationParams animation;
+ animation.type = TAT_NONE;
+ u8 glow = 0;
try {
vertical = readU8(is);
+ collision_removal = readU8(is);
+ animation.deSerialize(is, m_proto_ver);
+ glow = readU8(is);
} catch (...) {}
ClientEvent event;
event.spawn_particle.expirationtime = expirationtime;
event.spawn_particle.size = size;
event.spawn_particle.collisiondetection = collisiondetection;
+ event.spawn_particle.collision_removal = collision_removal;
event.spawn_particle.vertical = vertical;
event.spawn_particle.texture = new std::string(texture);
+ event.spawn_particle.animation = animation;
+ event.spawn_particle.glow = glow;
m_client_event_queue.push(event);
}
*pkt >> id;
bool vertical = false;
+ bool collision_removal = false;
+ struct TileAnimationParams animation;
+ animation.type = TAT_NONE;
+ u8 glow = 0;
+ u16 attached_id = 0;
try {
*pkt >> vertical;
+ *pkt >> collision_removal;
+ *pkt >> attached_id;
+
+ // This is horrible but required (why are there two ways to deserialize pkts?)
+ std::string datastring(pkt->getRemainingString(), pkt->getRemainingBytes());
+ std::istringstream is(datastring, std::ios_base::binary);
+ animation.deSerialize(is, m_proto_ver);
+ glow = readU8(is);
} catch (...) {}
ClientEvent event;
event.add_particlespawner.minsize = minsize;
event.add_particlespawner.maxsize = maxsize;
event.add_particlespawner.collisiondetection = collisiondetection;
+ event.add_particlespawner.collision_removal = collision_removal;
+ event.add_particlespawner.attached_id = attached_id;
event.add_particlespawner.vertical = vertical;
event.add_particlespawner.texture = new std::string(texture);
event.add_particlespawner.id = id;
+ event.add_particlespawner.animation = animation;
+ event.add_particlespawner.glow = glow;
m_client_event_queue.push(event);
}
*pkt >> flags >> mask;
- Player *player = m_env.getLocalPlayer();
+ LocalPlayer *player = m_env.getLocalPlayer();
assert(player != NULL);
+ bool was_minimap_visible = player->hud_flags & HUD_FLAG_MINIMAP_VISIBLE;
+
player->hud_flags &= ~mask;
player->hud_flags |= flags;
+
+ m_minimap_disabled_by_server = !(player->hud_flags & HUD_FLAG_MINIMAP_VISIBLE);
+
+ // Hide minimap if it has been disabled by the server
+ if (m_minimap_disabled_by_server && was_minimap_visible) {
+ // defers a minimap update, therefore only call it if really
+ // needed, by checking that minimap was visible before
+ m_mapper->setMinimapMode(MINIMAP_MODE_OFF);
+ }
}
void Client::handleCommand_HudSetParam(NetworkPacket* pkt)
*pkt >> param >> value;
- Player *player = m_env.getLocalPlayer();
+ LocalPlayer *player = m_env.getLocalPlayer();
assert(player != NULL);
if (param == HUD_PARAM_HOTBAR_ITEMCOUNT && value.size() == 4) {
player->hud_hotbar_itemcount = hotbar_itemcount;
}
else if (param == HUD_PARAM_HOTBAR_IMAGE) {
- ((LocalPlayer *) player)->hotbar_image = value;
+ player->hotbar_image = value;
}
else if (param == HUD_PARAM_HOTBAR_SELECTED_IMAGE) {
- ((LocalPlayer *) player)->hotbar_selected_image = value;
+ player->hotbar_selected_image = value;
}
}