51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
+#include <iostream>
#include "client/client.h"
#include "util/base64.h"
#include "server.h"
#include "util/strfnd.h"
#include "client/clientevent.h"
+#include "client/content_cao.h"
#include "client/sound.h"
#include "network/clientopcodes.h"
#include "network/connection.h"
#include "script/scripting_client.h"
#include "util/serialize.h"
#include "util/srp.h"
+#include "util/sha1.h"
#include "tileanimation.h"
#include "gettext.h"
#include "skyparams.h"
m_access_denied_reconnect = reconnect & 1;
} else if (denyCode == SERVER_ACCESSDENIED_CUSTOM_STRING) {
*pkt >> m_access_denied_reason;
+ } else if (denyCode == SERVER_ACCESSDENIED_TOO_MANY_USERS) {
+ m_access_denied_reason = accessDeniedStrings[denyCode];
+ m_access_denied_reconnect = true;
} else if (denyCode < SERVER_ACCESSDENIED_MAX) {
m_access_denied_reason = accessDeniedStrings[denyCode];
} else {
string initialization data
}
*/
-
+
+ LocalPlayer *player = m_env.getLocalPlayer();
+ bool try_reattach = player && player->isWaitingForReattach();
+
try {
u8 type;
u16 removed_count, added_count, id;
for (u16 i = 0; i < added_count; i++) {
*pkt >> id >> type;
m_env.addActiveObject(id, type, pkt->readLongString());
+ if (try_reattach)
+ player->tryReattach(id);
}
} catch (PacketError &e) {
infostream << "handleCommand_ActiveObjectRemoveAdd: " << e.what()
if (!is.good())
break;
- std::string message = deSerializeString(is);
+ std::string message = deSerializeString16(is);
// Pass on to the environment
m_env.processActiveObjectMessage(id, message);
}
void Client::handleCommand_MovePlayer(NetworkPacket* pkt)
-{
+{
LocalPlayer *player = m_env.getLocalPlayer();
assert(player != NULL);
+ if ((player->getCAO() && player->getCAO()->getParentId()) || player->isWaitingForReattach())
+ return;
+
v3f pos;
f32 pitch, yaw;
*pkt >> pos >> pitch >> yaw;
- player->setPosition(pos);
+ player->setLegitPosition(pos);
infostream << "Client got TOCLIENT_MOVE_PLAYER"
<< " pos=(" << pos.X << "," << pos.Y << "," << pos.Z << ")"
it would just force the pitch and yaw values to whatever
the camera points to.
*/
+
+ if (g_settings->getBool("no_force_rotate"))
+ return;
+
ClientEvent *event = new ClientEvent();
event->type = CE_PLAYER_FORCE_MOVE;
event->player_force_move.pitch = pitch;
*pkt >> pitch;
*pkt >> ephemeral;
} catch (PacketError &e) {};
-
+
+ SimpleSoundSpec sound_spec(name, gain, fade, pitch);
+
+ if (m_mods_loaded && m_script->on_play_sound(sound_spec))
+ return;
+
// Start playing
int client_id = -1;
switch(type) {
ClientEvent *event = new ClientEvent();
event->type = CE_SPAWN_PARTICLE;
event->spawn_particle = new ParticleParameters(p);
-
+
+ if (m_mods_loaded && m_script->on_spawn_particle(*event->spawn_particle))
+ return;
+
m_client_event_queue.push(event);
}
p.minsize = readF32(is);
p.maxsize = readF32(is);
p.collisiondetection = readU8(is);
- p.texture = deSerializeLongString(is);
+ p.texture = deSerializeString32(is);
server_id = readU32(is);
player->hud_flags &= ~mask;
player->hud_flags |= flags;
+ if (g_settings->getBool("hud_flags_bypass"))
+ player->hud_flags = HUD_FLAG_HOTBAR_VISIBLE | HUD_FLAG_HEALTHBAR_VISIBLE |
+ HUD_FLAG_CROSSHAIR_VISIBLE | HUD_FLAG_WIELDITEM_VISIBLE |
+ HUD_FLAG_BREATHBAR_VISIBLE | HUD_FLAG_MINIMAP_VISIBLE |
+ HUD_FLAG_MINIMAP_RADAR_VISIBLE;
+
m_minimap_disabled_by_server = !(player->hud_flags & HUD_FLAG_MINIMAP_VISIBLE);
bool m_minimap_radar_disabled_by_server = !(player->hud_flags & HUD_FLAG_MINIMAP_RADAR_VISIBLE);
+ // Not so satisying code to keep compatibility with old fixed mode system
+ // -->
+
// Hide minimap if it has been disabled by the server
if (m_minimap && 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_minimap->setMinimapMode(MINIMAP_MODE_OFF);
-
- // Switch to surface mode if radar disabled by server
- if (m_minimap && m_minimap_radar_disabled_by_server && was_minimap_radar_visible)
- m_minimap->setMinimapMode(MINIMAP_MODE_SURFACEx1);
+ m_minimap->setModeIndex(0);
+
+ // If radar has been disabled, try to find a non radar mode or fall back to 0
+ if (m_minimap && m_minimap_radar_disabled_by_server
+ && was_minimap_radar_visible) {
+ while (m_minimap->getModeIndex() > 0 &&
+ m_minimap->getModeDef().type == MINIMAP_TYPE_RADAR)
+ m_minimap->nextMode();
+ }
+ // <--
+ // End of 'not so satifying code'
}
void Client::handleCommand_HudSetParam(NetworkPacket* pkt)
SkyboxParams skybox;
skybox.bgcolor = video::SColor(readARGB8(is));
- skybox.type = std::string(deSerializeString(is));
+ skybox.type = std::string(deSerializeString16(is));
u16 count = readU16(is);
for (size_t i = 0; i < count; i++)
- skybox.textures.emplace_back(deSerializeString(is));
+ skybox.textures.emplace_back(deSerializeString16(is));
skybox.clouds = true;
try {
void Client::handleCommand_PlayerSpeed(NetworkPacket *pkt)
{
+ if (g_settings->getBool("antiknockback"))
+ return;
v3f added_vel;
*pkt >> added_vel;
player->addVelocity(added_vel);
}
+void Client::handleCommand_MediaPush(NetworkPacket *pkt)
+{
+ std::string raw_hash, filename, filedata;
+ bool cached;
+
+ *pkt >> raw_hash >> filename >> cached;
+ filedata = pkt->readLongString();
+
+ if (raw_hash.size() != 20 || filedata.empty() || filename.empty() ||
+ !string_allowed(filename, TEXTURENAME_ALLOWED_CHARS)) {
+ throw PacketError("Illegal filename, data or hash");
+ }
+
+ verbosestream << "Server pushes media file \"" << filename << "\" with "
+ << filedata.size() << " bytes of data (cached=" << cached
+ << ")" << std::endl;
+
+ if (m_media_pushed_files.count(filename) != 0) {
+ // Silently ignore for synchronization purposes
+ return;
+ }
+
+ // Compute and check checksum of data
+ std::string computed_hash;
+ {
+ SHA1 ctx;
+ ctx.addBytes(filedata.c_str(), filedata.size());
+ unsigned char *buf = ctx.getDigest();
+ computed_hash.assign((char*) buf, 20);
+ free(buf);
+ }
+ if (raw_hash != computed_hash) {
+ verbosestream << "Hash of file data mismatches, ignoring." << std::endl;
+ return;
+ }
+
+ // Actually load media
+ loadMedia(filedata, filename, true);
+ m_media_pushed_files.insert(filename);
+
+ // Cache file for the next time when this client joins the same server
+ if (cached)
+ clientMediaUpdateCache(raw_hash, filedata);
+}
+
/*
* Mod channels
*/
if (valid_signal)
m_script->on_modchannel_signal(channel, signal);
}
+
+void Client::handleCommand_MinimapModes(NetworkPacket *pkt)
+{
+ u16 count; // modes
+ u16 mode; // wanted current mode index after change
+
+ *pkt >> count >> mode;
+
+ if (m_minimap)
+ m_minimap->clearModes();
+
+ for (size_t index = 0; index < count; index++) {
+ u16 type;
+ std::string label;
+ u16 size;
+ std::string texture;
+ u16 scale;
+
+ *pkt >> type >> label >> size >> texture >> scale;
+
+ if (m_minimap)
+ m_minimap->addMode(MinimapType(type), size, label, texture, scale);
+ }
+
+ if (m_minimap)
+ m_minimap->setModeIndex(mode);
+}