Re-add protocol v25-33 support for servers.
This commit is contained in:
parent
205893620c
commit
7b37f2c1d8
@ -195,8 +195,12 @@ core.register_entity(":__builtin:item", {
|
||||
return -- Don't do anything
|
||||
end
|
||||
|
||||
assert(moveresult,
|
||||
"Collision info missing, this is caused by an out-of-date/buggy mod or game")
|
||||
-- assert(moveresult,
|
||||
-- "Collision info missing, this is caused by an out-of-date/buggy mod or game")
|
||||
if not moveresult then
|
||||
self.object:set_velocity({x=0, y=0, z=0})
|
||||
return
|
||||
end
|
||||
|
||||
if not moveresult.collides then
|
||||
-- future TODO: items should probably decelerate in air
|
||||
|
BIN
builtin/game/models/mc_compat_character.b3d
Normal file
BIN
builtin/game/models/mc_compat_character.b3d
Normal file
Binary file not shown.
@ -44,15 +44,18 @@ enum ActiveObjectType {
|
||||
|
||||
struct ActiveObjectMessage
|
||||
{
|
||||
ActiveObjectMessage(u16 id_, bool reliable_=true, const std::string &data_ = "") :
|
||||
ActiveObjectMessage(u16 id_, bool reliable_ = true,
|
||||
const std::string &data_ = "", const std::string legacy_ = "") :
|
||||
id(id_),
|
||||
reliable(reliable_),
|
||||
datastring(data_)
|
||||
datastring(data_),
|
||||
legacystring(legacy_)
|
||||
{}
|
||||
|
||||
u16 id;
|
||||
bool reliable;
|
||||
std::string datastring;
|
||||
std::string legacystring;
|
||||
};
|
||||
|
||||
enum ActiveObjectCommand {
|
||||
|
@ -750,8 +750,8 @@ void ClientInterface::sendToAllCompat(NetworkPacket *pkt, NetworkPacket *legacyp
|
||||
} else if (client->net_proto_version != 0) {
|
||||
pkt_to_send = legacypkt;
|
||||
} else {
|
||||
warningstream << "Client with unhandled version to handle: '"
|
||||
<< client->net_proto_version << "'";
|
||||
// This will happen if a client is connecting when sendToAllCompat
|
||||
// is called, this can safely be ignored.
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -762,6 +762,34 @@ void ClientInterface::sendToAllCompat(NetworkPacket *pkt, NetworkPacket *legacyp
|
||||
}
|
||||
}
|
||||
|
||||
void ClientInterface::oldSendToAll(NetworkPacket *pkt)
|
||||
{
|
||||
RecursiveMutexAutoLock clientslock(m_clients_mutex);
|
||||
for (auto &client_it : m_clients) {
|
||||
RemoteClient *client = client_it.second;
|
||||
|
||||
if (client->net_proto_version != 0 && client->net_proto_version < 37) {
|
||||
m_con->Send(client->peer_id,
|
||||
clientCommandFactoryTable[pkt->getCommand()].channel, pkt,
|
||||
clientCommandFactoryTable[pkt->getCommand()].reliable);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ClientInterface::newSendToAll(NetworkPacket *pkt)
|
||||
{
|
||||
RecursiveMutexAutoLock clientslock(m_clients_mutex);
|
||||
for (auto &client_it : m_clients) {
|
||||
RemoteClient *client = client_it.second;
|
||||
|
||||
if (client->net_proto_version > 36) {
|
||||
m_con->Send(client->peer_id,
|
||||
clientCommandFactoryTable[pkt->getCommand()].channel, pkt,
|
||||
clientCommandFactoryTable[pkt->getCommand()].reliable);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
RemoteClient* ClientInterface::getClientNoEx(session_t peer_id, ClientState state_min)
|
||||
{
|
||||
RecursiveMutexAutoLock clientslock(m_clients_mutex);
|
||||
|
@ -458,6 +458,8 @@ public:
|
||||
/* send to all clients */
|
||||
void sendToAll(NetworkPacket *pkt);
|
||||
void sendToAllCompat(NetworkPacket *pkt, NetworkPacket *legacypkt, u16 min_proto_ver);
|
||||
void oldSendToAll(NetworkPacket *pkt);
|
||||
void newSendToAll(NetworkPacket *pkt);
|
||||
|
||||
/* delete a client */
|
||||
void DeleteClient(session_t peer_id);
|
||||
|
@ -126,6 +126,11 @@ void ItemDefinition::serialize(std::ostream &os, u16 protocol_version) const
|
||||
{
|
||||
// protocol_version >= 37
|
||||
u8 version = 6;
|
||||
|
||||
// protocol_version < 37
|
||||
if (protocol_version < 37)
|
||||
version = 3;
|
||||
|
||||
writeU8(os, version);
|
||||
writeU8(os, type);
|
||||
os << serializeString(name);
|
||||
@ -153,13 +158,25 @@ void ItemDefinition::serialize(std::ostream &os, u16 protocol_version) const
|
||||
|
||||
os << serializeString(node_placement_prediction);
|
||||
|
||||
// Version from ContentFeatures::serialize to keep in sync
|
||||
sound_place.serialize(os, CONTENTFEATURES_VERSION);
|
||||
sound_place_failed.serialize(os, CONTENTFEATURES_VERSION);
|
||||
if (version == 3) {
|
||||
os << serializeString(sound_place.name);
|
||||
writeF1000(os, sound_place.gain);
|
||||
writeF1000(os, range);
|
||||
os << serializeString(sound_place_failed.name);
|
||||
writeF1000(os, sound_place_failed.gain);
|
||||
} else {
|
||||
// Version from ContentFeatures::serialize to keep in sync
|
||||
sound_place.serialize(os, CONTENTFEATURES_VERSION);
|
||||
sound_place_failed.serialize(os, CONTENTFEATURES_VERSION);
|
||||
writeF32(os, range);
|
||||
}
|
||||
|
||||
writeF(os, range, protocol_version);
|
||||
os << serializeString(palette_image);
|
||||
writeARGB8(os, color);
|
||||
|
||||
if (version == 3)
|
||||
return;
|
||||
|
||||
os << serializeString(inventory_overlay);
|
||||
os << serializeString(wield_overlay);
|
||||
}
|
||||
|
@ -355,7 +355,7 @@ static void correctBlockNodeIds(const NameIdMapping *nimap, MapNode *nodes,
|
||||
}
|
||||
}
|
||||
|
||||
void MapBlock::serialize(std::ostream &os, u8 version, bool disk)
|
||||
void MapBlock::serialize(std::ostream &os, u8 version, bool disk, std::string formspec_prepend)
|
||||
{
|
||||
if(!ser_ver_supported(version))
|
||||
throw VersionMismatchException("ERROR: MapBlock format not supported");
|
||||
@ -411,7 +411,7 @@ void MapBlock::serialize(std::ostream &os, u8 version, bool disk)
|
||||
Node metadata
|
||||
*/
|
||||
std::ostringstream oss(std::ios_base::binary);
|
||||
m_node_metadata.serialize(oss, version, disk);
|
||||
m_node_metadata.serialize(oss, version, disk, false, formspec_prepend);
|
||||
compressZlib(oss.str(), os);
|
||||
|
||||
/*
|
||||
|
@ -482,7 +482,8 @@ public:
|
||||
// These don't write or read version by itself
|
||||
// Set disk to true for on-disk format, false for over-the-network format
|
||||
// Precondition: version >= SER_FMT_VER_LOWEST_WRITE
|
||||
void serialize(std::ostream &os, u8 version, bool disk);
|
||||
void serialize(std::ostream &os, u8 version, bool disk,
|
||||
std::string formspec_prepend="");
|
||||
// If disk == true: In addition to doing other things, will add
|
||||
// unknown blocks from id-name mapping to wndef
|
||||
void deSerialize(std::istream &is, u8 version, bool disk);
|
||||
|
@ -44,6 +44,7 @@ public:
|
||||
u16 getCommand() { return m_command; }
|
||||
const u32 getRemainingBytes() const { return m_datasize - m_read_offset; }
|
||||
const char *getRemainingString() { return getString(m_read_offset); }
|
||||
u16 getProtocolVersion() const { return m_protocol_version; }
|
||||
|
||||
// Returns a c-string without copying.
|
||||
// A better name for this would be getRawString()
|
||||
|
@ -210,7 +210,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#define LATEST_PROTOCOL_VERSION_STRING TOSTRING(LATEST_PROTOCOL_VERSION)
|
||||
|
||||
// Server's supported network protocol range
|
||||
#define SERVER_PROTOCOL_VERSION_MIN 37
|
||||
#define SERVER_PROTOCOL_VERSION_MIN 25
|
||||
#define SERVER_PROTOCOL_VERSION_MAX LATEST_PROTOCOL_VERSION
|
||||
|
||||
// Client's supported network protocol range
|
||||
|
@ -89,7 +89,7 @@ const ToServerCommandHandler toServerCommandTable[TOSERVER_NUM_MSG_TYPES] =
|
||||
null_command_handler, // 0x3e
|
||||
null_command_handler, // 0x3f
|
||||
{ "TOSERVER_REQUEST_MEDIA", TOSERVER_STATE_STARTUP, &Server::handleCommand_RequestMedia }, // 0x40
|
||||
null_command_handler, // 0x41
|
||||
{ "TOSERVER_RECEIVED_MEDIA", TOSERVER_STATE_STARTUP, &Server::handleCommand_Deprecated }, // 0x41 not used by the server since protocol version 23
|
||||
null_command_handler, // 0x42
|
||||
{ "TOSERVER_CLIENT_READY", TOSERVER_STATE_STARTUP, &Server::handleCommand_ClientReady }, // 0x43
|
||||
null_command_handler, // 0x44
|
||||
|
@ -324,7 +324,7 @@ void Server::handleCommand_Init2(NetworkPacket* pkt)
|
||||
sendDetachedInventories(peer_id, false);
|
||||
|
||||
// Send player movement settings
|
||||
SendMovement(peer_id);
|
||||
SendMovement(peer_id, protocol_version);
|
||||
|
||||
// Send time of day
|
||||
u16 time = m_env->getTimeOfDay();
|
||||
@ -454,7 +454,7 @@ void Server::handleCommand_GotBlocks(NetworkPacket* pkt)
|
||||
void Server::process_PlayerPos(RemotePlayer *player, PlayerSAO *playersao,
|
||||
NetworkPacket *pkt)
|
||||
{
|
||||
if (pkt->getRemainingBytes() < 12 + 12 + 4 + 4 + 4 + 1 + 1)
|
||||
if (pkt->getRemainingBytes() < 12 + 12 + 4 + 4)
|
||||
return;
|
||||
|
||||
v3s32 ps, ss;
|
||||
@ -474,10 +474,14 @@ void Server::process_PlayerPos(RemotePlayer *player, PlayerSAO *playersao,
|
||||
f32 fov = 0;
|
||||
u8 wanted_range = 0;
|
||||
|
||||
*pkt >> keyPressed;
|
||||
*pkt >> f32fov;
|
||||
fov = (f32)f32fov / 80.0f;
|
||||
*pkt >> wanted_range;
|
||||
if (pkt->getRemainingBytes() >= 4)
|
||||
*pkt >> keyPressed;
|
||||
if (pkt->getRemainingBytes() >= 1) {
|
||||
*pkt >> f32fov;
|
||||
fov = (f32)f32fov / 80.0f;
|
||||
if (pkt->getRemainingBytes() >= 1)
|
||||
*pkt >> wanted_range;
|
||||
}
|
||||
|
||||
v3f position((f32)ps.X / 100.0f, (f32)ps.Y / 100.0f, (f32)ps.Z / 100.0f);
|
||||
v3f speed((f32)ss.X / 100.0f, (f32)ss.Y / 100.0f, (f32)ss.Z / 100.0f);
|
||||
@ -791,9 +795,6 @@ void Server::handleCommand_ChatMessage(NetworkPacket* pkt)
|
||||
|
||||
void Server::handleCommand_Damage(NetworkPacket* pkt)
|
||||
{
|
||||
u16 damage;
|
||||
|
||||
*pkt >> damage;
|
||||
|
||||
session_t peer_id = pkt->getPeerId();
|
||||
RemotePlayer *player = m_env->getPlayer(peer_id);
|
||||
@ -806,6 +807,17 @@ void Server::handleCommand_Damage(NetworkPacket* pkt)
|
||||
return;
|
||||
}
|
||||
|
||||
u16 damage;
|
||||
|
||||
// Minetest 0.4 uses 8-bit integers for damage.
|
||||
if (player->protocol_version >= 37) {
|
||||
*pkt >> damage;
|
||||
} else {
|
||||
u8 raw_damage;
|
||||
*pkt >> raw_damage;
|
||||
damage = raw_damage;
|
||||
}
|
||||
|
||||
PlayerSAO *playersao = player->getPlayerSAO();
|
||||
if (playersao == NULL) {
|
||||
errorstream <<
|
||||
@ -1670,7 +1682,7 @@ void Server::handleCommand_SrpBytesM(NetworkPacket* pkt)
|
||||
if (client->chosen_mech != AUTH_MECHANISM_SRP &&
|
||||
client->chosen_mech != AUTH_MECHANISM_LEGACY_PASSWORD) {
|
||||
actionstream << "Server: got SRP _M packet, while auth"
|
||||
<< "is going on with mech " << client->chosen_mech << " from "
|
||||
<< "is going on with mech " << client->chosen_mech << " from "
|
||||
<< addr_s << " (wantSudo=" << wantSudo << "). Denying." << std::endl;
|
||||
if (wantSudo) {
|
||||
DenySudoAccess(peer_id);
|
||||
|
200
src/nodedef.cpp
200
src/nodedef.cpp
@ -74,7 +74,13 @@ void NodeBox::reset()
|
||||
void NodeBox::serialize(std::ostream &os, u16 protocol_version) const
|
||||
{
|
||||
// Protocol >= 36
|
||||
const u8 version = 6;
|
||||
u8 version;
|
||||
if (protocol_version >= 36)
|
||||
version = 6;
|
||||
else if (protocol_version >= 27)
|
||||
version = 3;
|
||||
else
|
||||
version = 2;
|
||||
writeU8(os, version);
|
||||
|
||||
switch (type) {
|
||||
@ -84,28 +90,38 @@ void NodeBox::serialize(std::ostream &os, u16 protocol_version) const
|
||||
|
||||
writeU16(os, fixed.size());
|
||||
for (const aabb3f &nodebox : fixed) {
|
||||
writeV3F32(os, nodebox.MinEdge);
|
||||
writeV3F32(os, nodebox.MaxEdge);
|
||||
writeV3F(os, nodebox.MinEdge, protocol_version);
|
||||
writeV3F(os, nodebox.MaxEdge, protocol_version);
|
||||
}
|
||||
break;
|
||||
case NODEBOX_WALLMOUNTED:
|
||||
writeU8(os, type);
|
||||
|
||||
writeV3F32(os, wall_top.MinEdge);
|
||||
writeV3F32(os, wall_top.MaxEdge);
|
||||
writeV3F32(os, wall_bottom.MinEdge);
|
||||
writeV3F32(os, wall_bottom.MaxEdge);
|
||||
writeV3F32(os, wall_side.MinEdge);
|
||||
writeV3F32(os, wall_side.MaxEdge);
|
||||
writeV3F(os, wall_top.MinEdge, protocol_version);
|
||||
writeV3F(os, wall_top.MaxEdge, protocol_version);
|
||||
writeV3F(os, wall_bottom.MinEdge, protocol_version);
|
||||
writeV3F(os, wall_bottom.MaxEdge, protocol_version);
|
||||
writeV3F(os, wall_side.MinEdge, protocol_version);
|
||||
writeV3F(os, wall_side.MaxEdge, protocol_version);
|
||||
break;
|
||||
case NODEBOX_CONNECTED:
|
||||
if (version <= 2) {
|
||||
// send old clients nodes that can't be walked through
|
||||
// to prevent abuse
|
||||
writeU8(os, NODEBOX_FIXED);
|
||||
|
||||
writeU16(os, 1);
|
||||
writeV3F1000(os, v3f(-BS/2, -BS/2, -BS/2));
|
||||
writeV3F1000(os, v3f(BS/2, BS/2, BS/2));
|
||||
break;
|
||||
}
|
||||
writeU8(os, type);
|
||||
|
||||
#define WRITEBOX(box) \
|
||||
writeU16(os, (box).size()); \
|
||||
for (const aabb3f &i: (box)) { \
|
||||
writeV3F32(os, i.MinEdge); \
|
||||
writeV3F32(os, i.MaxEdge); \
|
||||
writeV3F(os, i.MinEdge, protocol_version); \
|
||||
writeV3F(os, i.MaxEdge, protocol_version); \
|
||||
};
|
||||
|
||||
WRITEBOX(fixed);
|
||||
@ -115,14 +131,17 @@ void NodeBox::serialize(std::ostream &os, u16 protocol_version) const
|
||||
WRITEBOX(connect_left);
|
||||
WRITEBOX(connect_back);
|
||||
WRITEBOX(connect_right);
|
||||
WRITEBOX(disconnected_top);
|
||||
WRITEBOX(disconnected_bottom);
|
||||
WRITEBOX(disconnected_front);
|
||||
WRITEBOX(disconnected_left);
|
||||
WRITEBOX(disconnected_back);
|
||||
WRITEBOX(disconnected_right);
|
||||
WRITEBOX(disconnected);
|
||||
WRITEBOX(disconnected_sides);
|
||||
|
||||
if (version > 5) {
|
||||
WRITEBOX(disconnected_top);
|
||||
WRITEBOX(disconnected_bottom);
|
||||
WRITEBOX(disconnected_front);
|
||||
WRITEBOX(disconnected_left);
|
||||
WRITEBOX(disconnected_back);
|
||||
WRITEBOX(disconnected_right);
|
||||
WRITEBOX(disconnected);
|
||||
WRITEBOX(disconnected_sides);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
writeU8(os, type);
|
||||
@ -207,12 +226,41 @@ void NodeBox::deSerialize(std::istream &is)
|
||||
|
||||
void TileDef::serialize(std::ostream &os, u16 protocol_version) const
|
||||
{
|
||||
// protocol_version >= 36
|
||||
u8 version = 6;
|
||||
u8 version;
|
||||
if (protocol_version >= 37)
|
||||
version = 6;
|
||||
else if (protocol_version >= 30)
|
||||
version = 4;
|
||||
else if (protocol_version >= 29)
|
||||
version = 3;
|
||||
else if (protocol_version >= 26)
|
||||
version = 2;
|
||||
else
|
||||
version = 1;
|
||||
|
||||
writeU8(os, version);
|
||||
|
||||
os << serializeString(name);
|
||||
animation.serialize(os, version);
|
||||
|
||||
// Compatibility with Minetest 0.4.
|
||||
if (version < 6) {
|
||||
writeU8(os, backface_culling);
|
||||
if (version < 2)
|
||||
return;
|
||||
writeU8(os, tileable_horizontal);
|
||||
writeU8(os, tileable_vertical);
|
||||
if (version < 3)
|
||||
return;
|
||||
writeU8(os, has_color);
|
||||
if (has_color) {
|
||||
writeU8(os, color.getRed());
|
||||
writeU8(os, color.getGreen());
|
||||
writeU8(os, color.getBlue());
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
bool has_scale = scale > 0;
|
||||
u16 flags = 0;
|
||||
if (backface_culling)
|
||||
@ -424,7 +472,14 @@ void ContentFeatures::reset()
|
||||
|
||||
void ContentFeatures::serialize(std::ostream &os, u16 protocol_version) const
|
||||
{
|
||||
const u8 version = CONTENTFEATURES_VERSION;
|
||||
if (protocol_version < 31) {
|
||||
serializeOld(os, protocol_version);
|
||||
return;
|
||||
}
|
||||
|
||||
u8 version = CONTENTFEATURES_VERSION;
|
||||
if (protocol_version < 37)
|
||||
version = 10;
|
||||
writeU8(os, version);
|
||||
|
||||
// general
|
||||
@ -440,7 +495,7 @@ void ContentFeatures::serialize(std::ostream &os, u16 protocol_version) const
|
||||
// visual
|
||||
writeU8(os, drawtype);
|
||||
os << serializeString(mesh);
|
||||
writeF32(os, visual_scale);
|
||||
writeF(os, visual_scale, protocol_version);
|
||||
writeU8(os, 6);
|
||||
for (const TileDef &td : tiledef)
|
||||
td.serialize(os, protocol_version);
|
||||
@ -1125,6 +1180,105 @@ void ContentFeatures::updateTextures(ITextureSource *tsrc, IShaderSource *shdsrc
|
||||
}
|
||||
#endif
|
||||
|
||||
//// Serialization of old ContentFeatures formats
|
||||
void ContentFeatures::serializeOld(std::ostream &os, u16 protocol_version) const
|
||||
{
|
||||
u8 compatible_param_type_2 = param_type_2;
|
||||
if ((protocol_version < 28)
|
||||
&& (compatible_param_type_2 == CPT2_MESHOPTIONS))
|
||||
compatible_param_type_2 = CPT2_NONE;
|
||||
else if (protocol_version < 30) {
|
||||
if (compatible_param_type_2 == CPT2_COLOR)
|
||||
compatible_param_type_2 = CPT2_NONE;
|
||||
else if (compatible_param_type_2 == CPT2_COLORED_FACEDIR)
|
||||
compatible_param_type_2 = CPT2_FACEDIR;
|
||||
else if (compatible_param_type_2 == CPT2_COLORED_WALLMOUNTED)
|
||||
compatible_param_type_2 = CPT2_WALLMOUNTED;
|
||||
}
|
||||
|
||||
float compatible_visual_scale = visual_scale;
|
||||
if (protocol_version < 30 && drawtype == NDT_PLANTLIKE)
|
||||
compatible_visual_scale = sqrt(visual_scale);
|
||||
|
||||
TileDef compatible_tiles[6];
|
||||
for (u8 i = 0; i < 6; i++) {
|
||||
compatible_tiles[i] = tiledef[i];
|
||||
if (tiledef_overlay[i].name != "") {
|
||||
std::stringstream s;
|
||||
s << "(" << tiledef[i].name << ")^(" << tiledef_overlay[i].name
|
||||
<< ")";
|
||||
compatible_tiles[i].name = s.str();
|
||||
}
|
||||
}
|
||||
|
||||
// Protocol >= 24
|
||||
if (protocol_version < 31) {
|
||||
const u8 version = protocol_version < 27 ? 7 : 8;
|
||||
writeU8(os, version);
|
||||
|
||||
os << serializeString(name);
|
||||
writeU16(os, groups.size());
|
||||
for (ItemGroupList::const_iterator i = groups.begin();
|
||||
i != groups.end(); ++i) {
|
||||
os << serializeString(i->first);
|
||||
writeS16(os, i->second);
|
||||
}
|
||||
writeU8(os, drawtype);
|
||||
writeF1000(os, compatible_visual_scale);
|
||||
writeU8(os, 6);
|
||||
for (u32 i = 0; i < 6; i++)
|
||||
compatible_tiles[i].serialize(os, protocol_version);
|
||||
writeU8(os, CF_SPECIAL_COUNT);
|
||||
for (u32 i = 0; i < CF_SPECIAL_COUNT; i++)
|
||||
tiledef_special[i].serialize(os, protocol_version);
|
||||
writeU8(os, alpha);
|
||||
writeU8(os, post_effect_color.getAlpha());
|
||||
writeU8(os, post_effect_color.getRed());
|
||||
writeU8(os, post_effect_color.getGreen());
|
||||
writeU8(os, post_effect_color.getBlue());
|
||||
writeU8(os, param_type);
|
||||
writeU8(os, compatible_param_type_2);
|
||||
writeU8(os, is_ground_content);
|
||||
writeU8(os, light_propagates);
|
||||
writeU8(os, sunlight_propagates);
|
||||
writeU8(os, walkable);
|
||||
writeU8(os, pointable);
|
||||
writeU8(os, diggable);
|
||||
writeU8(os, climbable);
|
||||
writeU8(os, buildable_to);
|
||||
os << serializeString(""); // legacy: used to be metadata_name
|
||||
writeU8(os, liquid_type);
|
||||
os << serializeString(liquid_alternative_flowing);
|
||||
os << serializeString(liquid_alternative_source);
|
||||
writeU8(os, liquid_viscosity);
|
||||
writeU8(os, liquid_renewable);
|
||||
writeU8(os, light_source);
|
||||
writeU32(os, damage_per_second);
|
||||
node_box.serialize(os, protocol_version);
|
||||
selection_box.serialize(os, protocol_version);
|
||||
writeU8(os, legacy_facedir_simple);
|
||||
writeU8(os, legacy_wallmounted);
|
||||
sound_footstep.serialize(os, version);
|
||||
sound_dig.serialize(os, version);
|
||||
sound_dug.serialize(os, version);
|
||||
writeU8(os, rightclickable);
|
||||
writeU8(os, drowning);
|
||||
writeU8(os, leveled);
|
||||
writeU8(os, liquid_range);
|
||||
writeU8(os, waving);
|
||||
os << serializeString(mesh);
|
||||
collision_box.serialize(os, protocol_version);
|
||||
writeU8(os, floodable);
|
||||
writeU16(os, connects_to_ids.size());
|
||||
for (u16 connects_to_id : connects_to_ids)
|
||||
writeU16(os, connects_to_id);
|
||||
writeU8(os, connect_sides);
|
||||
} else {
|
||||
throw SerializationError("ContentFeatures::serialize(): "
|
||||
"Unsupported version requested");
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
NodeDefManager
|
||||
*/
|
||||
|
@ -414,6 +414,7 @@ struct ContentFeatures
|
||||
void serialize(std::ostream &os, u16 protocol_version) const;
|
||||
void deSerialize(std::istream &is);
|
||||
void deSerializeOld(std::istream &is, int version);
|
||||
void serializeOld(std::ostream &os, u16 protocol_version) const;
|
||||
/*!
|
||||
* Since vertex alpha is no longer supported, this method
|
||||
* adds opacity directly to the texture pixels.
|
||||
|
@ -40,7 +40,8 @@ NodeMetadata::~NodeMetadata()
|
||||
delete m_inventory;
|
||||
}
|
||||
|
||||
void NodeMetadata::serialize(std::ostream &os, u8 version, bool disk) const
|
||||
void NodeMetadata::serialize(std::ostream &os, u8 version, bool disk,
|
||||
std::string formspec_prepend) const
|
||||
{
|
||||
int num_vars = disk ? m_stringvars.size() : countNonPrivate();
|
||||
writeU32(os, num_vars);
|
||||
@ -50,7 +51,11 @@ void NodeMetadata::serialize(std::ostream &os, u8 version, bool disk) const
|
||||
continue;
|
||||
|
||||
os << serializeString(sv.first);
|
||||
os << serializeLongString(sv.second);
|
||||
if (!formspec_prepend.empty() && sv.first == "formspec" &&
|
||||
sv.second.find("no_prepend[]") == std::string::npos)
|
||||
os << serializeLongString(sv.second + formspec_prepend);
|
||||
else
|
||||
os << serializeLongString(sv.second);
|
||||
if (version >= 2)
|
||||
writeU8(os, (priv) ? 1 : 0);
|
||||
}
|
||||
@ -113,7 +118,7 @@ int NodeMetadata::countNonPrivate() const
|
||||
*/
|
||||
|
||||
void NodeMetadataList::serialize(std::ostream &os, u8 blockver, bool disk,
|
||||
bool absolute_pos) const
|
||||
bool absolute_pos, std::string formspec_prepend) const
|
||||
{
|
||||
/*
|
||||
Version 0 is a placeholder for "nothing to see here; go away."
|
||||
@ -146,7 +151,7 @@ void NodeMetadataList::serialize(std::ostream &os, u8 blockver, bool disk,
|
||||
u16 p16 = (p.Z * MAP_BLOCKSIZE + p.Y) * MAP_BLOCKSIZE + p.X;
|
||||
writeU16(os, p16);
|
||||
}
|
||||
data->serialize(os, version, disk);
|
||||
data->serialize(os, version, disk, formspec_prepend);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -40,7 +40,8 @@ public:
|
||||
NodeMetadata(IItemDefManager *item_def_mgr);
|
||||
~NodeMetadata();
|
||||
|
||||
void serialize(std::ostream &os, u8 version, bool disk=true) const;
|
||||
void serialize(std::ostream &os, u8 version, bool disk=true,
|
||||
std::string formspec_prepend="") const;
|
||||
void deSerialize(std::istream &is, u8 version);
|
||||
|
||||
void clear();
|
||||
@ -82,7 +83,7 @@ public:
|
||||
~NodeMetadataList();
|
||||
|
||||
void serialize(std::ostream &os, u8 blockver, bool disk = true,
|
||||
bool absolute_pos = false) const;
|
||||
bool absolute_pos = false, std::string formspec_prepend = "") const;
|
||||
void deSerialize(std::istream &is, IItemDefManager *item_def_mgr,
|
||||
bool absolute_pos = false);
|
||||
|
||||
|
@ -73,28 +73,62 @@ std::string ObjectProperties::dump()
|
||||
return os.str();
|
||||
}
|
||||
|
||||
void ObjectProperties::serialize(std::ostream &os) const
|
||||
void ObjectProperties::serialize(std::ostream &os, u16 protocol_version) const
|
||||
{
|
||||
writeU8(os, 4); // PROTOCOL_VERSION >= 37
|
||||
if (protocol_version > 36)
|
||||
writeU8(os, 4); // PROTOCOL_VERSION >= 37
|
||||
else
|
||||
writeU8(os, 1);
|
||||
writeU16(os, hp_max);
|
||||
writeU8(os, physical);
|
||||
writeF32(os, 0.f); // Removed property (weight)
|
||||
writeV3F32(os, collisionbox.MinEdge);
|
||||
writeV3F32(os, collisionbox.MaxEdge);
|
||||
writeV3F32(os, selectionbox.MinEdge);
|
||||
writeV3F32(os, selectionbox.MaxEdge);
|
||||
writeU8(os, pointable);
|
||||
os << serializeString(visual);
|
||||
writeV3F32(os, visual_size);
|
||||
writeU16(os, textures.size());
|
||||
for (const std::string &texture : textures) {
|
||||
os << serializeString(texture);
|
||||
writeF(os, 0.f, protocol_version); // Removed property (weight)
|
||||
if (protocol_version > 36) {
|
||||
writeV3F32(os, collisionbox.MinEdge);
|
||||
writeV3F32(os, collisionbox.MaxEdge);
|
||||
writeV3F32(os, selectionbox.MinEdge);
|
||||
writeV3F32(os, selectionbox.MaxEdge);
|
||||
writeU8(os, pointable);
|
||||
} else if (pointable) {
|
||||
writeV3F1000(os, selectionbox.MinEdge);
|
||||
writeV3F1000(os, selectionbox.MaxEdge);
|
||||
} else {
|
||||
// A hack to emulate unpointable objects
|
||||
for (u8 i = 0; i < 6; i++)
|
||||
writeF1000(os, 0);
|
||||
}
|
||||
|
||||
// The "wielditem" type isn't exactly the same as "item", however this
|
||||
// is the most similar compatible option
|
||||
if (visual == "item" && protocol_version < 37)
|
||||
os << serializeString("wielditem");
|
||||
else
|
||||
os << serializeString(visual);
|
||||
|
||||
if (protocol_version > 36) {
|
||||
writeV3F32(os, visual_size);
|
||||
} else {
|
||||
writeF1000(os, visual_size.X);
|
||||
writeF1000(os, visual_size.Y);
|
||||
}
|
||||
|
||||
// MT 0.4.15 and below don't have the wield_item property and expect
|
||||
// wield_item to be in textures[0].
|
||||
if (protocol_version < 37 && (visual == "item" || visual == "wielditem") &&
|
||||
!wield_item.empty()) {
|
||||
writeU16(os, 1);
|
||||
os << serializeString(wield_item);
|
||||
} else {
|
||||
writeU16(os, textures.size());
|
||||
for (const std::string &texture : textures) {
|
||||
os << serializeString(texture);
|
||||
}
|
||||
}
|
||||
|
||||
writeV2S16(os, spritediv);
|
||||
writeV2S16(os, initial_sprite_basepos);
|
||||
writeU8(os, is_visible);
|
||||
writeU8(os, makes_footstep_sound);
|
||||
writeF32(os, automatic_rotate);
|
||||
writeF(os, automatic_rotate, protocol_version);
|
||||
// Added in protocol version 14
|
||||
os << serializeString(mesh);
|
||||
writeU16(os, colors.size());
|
||||
@ -102,16 +136,21 @@ void ObjectProperties::serialize(std::ostream &os) const
|
||||
writeARGB8(os, color);
|
||||
}
|
||||
writeU8(os, collideWithObjects);
|
||||
writeF32(os, stepheight);
|
||||
writeF(os, stepheight, protocol_version);
|
||||
writeU8(os, automatic_face_movement_dir);
|
||||
writeF32(os, automatic_face_movement_dir_offset);
|
||||
writeF(os, automatic_face_movement_dir_offset, protocol_version);
|
||||
writeU8(os, backface_culling);
|
||||
os << serializeString(nametag);
|
||||
writeARGB8(os, nametag_color);
|
||||
writeF32(os, automatic_face_movement_max_rotation_per_sec);
|
||||
writeF(os, automatic_face_movement_max_rotation_per_sec, protocol_version);
|
||||
os << serializeString(infotext);
|
||||
os << serializeString(wield_item);
|
||||
writeS8(os, glow);
|
||||
|
||||
// Everything after this can use writeF32().
|
||||
if (protocol_version < 37)
|
||||
return;
|
||||
|
||||
writeU16(os, breath_max);
|
||||
writeF32(os, eye_height);
|
||||
writeF32(os, zoom_fov);
|
||||
|
@ -65,6 +65,6 @@ struct ObjectProperties
|
||||
|
||||
ObjectProperties();
|
||||
std::string dump();
|
||||
void serialize(std::ostream &os) const;
|
||||
void serialize(std::ostream &os, u16 protocol_version) const;
|
||||
void deSerialize(std::istream &is);
|
||||
};
|
||||
|
147
src/server.cpp
147
src/server.cpp
@ -771,7 +771,11 @@ void Server::AsyncRunStep(bool initial_step)
|
||||
// u16 id
|
||||
// std::string data
|
||||
buffer.append(idbuf, sizeof(idbuf));
|
||||
buffer.append(serializeString(aom.datastring));
|
||||
if (client->net_proto_version >= 37 ||
|
||||
aom.legacystring.empty())
|
||||
buffer.append(serializeString(aom.datastring));
|
||||
else
|
||||
buffer.append(serializeString(aom.legacystring));
|
||||
}
|
||||
}
|
||||
/*
|
||||
@ -1147,6 +1151,9 @@ void Server::ProcessData(NetworkPacket *pkt)
|
||||
return;
|
||||
}
|
||||
|
||||
RemoteClient *client = getClient(peer_id);
|
||||
if (client)
|
||||
pkt->setProtocolVersion(client->net_proto_version);
|
||||
handleCommand(pkt);
|
||||
} catch (SendFailedException &e) {
|
||||
errorstream << "Server::ProcessData(): SendFailedException: "
|
||||
@ -1154,7 +1161,7 @@ void Server::ProcessData(NetworkPacket *pkt)
|
||||
<< std::endl;
|
||||
} catch (PacketError &e) {
|
||||
actionstream << "Server::ProcessData(): PacketError: "
|
||||
<< "what=" << e.what()
|
||||
<< "what=" << e.what() << ", command=" << pkt->getCommand() // TODO: REMOVE COMMAND=
|
||||
<< std::endl;
|
||||
}
|
||||
}
|
||||
@ -1296,11 +1303,11 @@ void Server::Send(session_t peer_id, NetworkPacket *pkt)
|
||||
clientCommandFactoryTable[pkt->getCommand()].reliable);
|
||||
}
|
||||
|
||||
void Server::SendMovement(session_t peer_id)
|
||||
void Server::SendMovement(session_t peer_id, u16 protocol_version)
|
||||
{
|
||||
std::ostringstream os(std::ios_base::binary);
|
||||
|
||||
NetworkPacket pkt(TOCLIENT_MOVEMENT, 12 * sizeof(float), peer_id);
|
||||
NetworkPacket pkt(TOCLIENT_MOVEMENT, 12 * sizeof(float), peer_id, protocol_version);
|
||||
|
||||
pkt << g_settings->getFloat("movement_acceleration_default");
|
||||
pkt << g_settings->getFloat("movement_acceleration_air");
|
||||
@ -1335,7 +1342,13 @@ void Server::SendPlayerHPOrDie(PlayerSAO *playersao, const PlayerHPChangeReason
|
||||
void Server::SendHP(session_t peer_id, u16 hp)
|
||||
{
|
||||
NetworkPacket pkt(TOCLIENT_HP, 1, peer_id);
|
||||
pkt << hp;
|
||||
// Minetest 0.4 uses 8-bit integers for HPP.
|
||||
if (m_clients.getProtocolVersion(peer_id) >= 37) {
|
||||
pkt << hp;
|
||||
} else {
|
||||
u8 raw_hp = hp & 0xFF;
|
||||
pkt << raw_hp;
|
||||
}
|
||||
Send(&pkt);
|
||||
}
|
||||
|
||||
@ -1454,6 +1467,9 @@ void Server::SendInventory(PlayerSAO *sao, bool incremental)
|
||||
|
||||
void Server::SendChatMessage(session_t peer_id, const ChatMessage &message)
|
||||
{
|
||||
NetworkPacket legacypkt(TOCLIENT_CHAT_MESSAGE_OLD, 0, peer_id);
|
||||
legacypkt << message.message;
|
||||
|
||||
NetworkPacket pkt(TOCLIENT_CHAT_MESSAGE, 0, peer_id);
|
||||
u8 version = 1;
|
||||
u8 type = message.type;
|
||||
@ -1464,9 +1480,12 @@ void Server::SendChatMessage(session_t peer_id, const ChatMessage &message)
|
||||
if (!player)
|
||||
return;
|
||||
|
||||
Send(&pkt);
|
||||
if (player->protocol_version < 35)
|
||||
Send(&legacypkt);
|
||||
else
|
||||
Send(&pkt);
|
||||
} else {
|
||||
m_clients.sendToAll(&pkt);
|
||||
m_clients.sendToAllCompat(&pkt, &legacypkt, 35);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1484,7 +1503,12 @@ void Server::SendShowFormspecMessage(session_t peer_id, const std::string &forms
|
||||
pkt.putLongString("");
|
||||
} else {
|
||||
m_formspec_state_data[peer_id] = formname;
|
||||
pkt.putLongString(formspec);
|
||||
RemotePlayer *player = m_env->getPlayer(peer_id);
|
||||
if (player && player->protocol_version < 37 &&
|
||||
formspec.find("no_prepend[]") == std::string::npos)
|
||||
pkt.putLongString(formspec + player->formspec_prepend);
|
||||
else
|
||||
pkt.putLongString(formspec);
|
||||
}
|
||||
pkt << formname;
|
||||
|
||||
@ -1522,7 +1546,7 @@ void Server::SendSpawnParticle(session_t peer_id, u16 protocol_version,
|
||||
}
|
||||
assert(protocol_version != 0);
|
||||
|
||||
NetworkPacket pkt(TOCLIENT_SPAWN_PARTICLE, 0, peer_id);
|
||||
NetworkPacket pkt(TOCLIENT_SPAWN_PARTICLE, 0, peer_id, protocol_version);
|
||||
|
||||
{
|
||||
// NetworkPacket and iostreams are incompatible...
|
||||
@ -1569,7 +1593,7 @@ void Server::SendAddParticleSpawner(session_t peer_id, u16 protocol_version,
|
||||
}
|
||||
assert(protocol_version != 0);
|
||||
|
||||
NetworkPacket pkt(TOCLIENT_ADD_PARTICLESPAWNER, 100, peer_id);
|
||||
NetworkPacket pkt(TOCLIENT_ADD_PARTICLESPAWNER, 100, peer_id, protocol_version);
|
||||
|
||||
pkt << p.amount << p.time << p.minpos << p.maxpos << p.minvel
|
||||
<< p.maxvel << p.minacc << p.maxacc << p.minexptime << p.maxexptime
|
||||
@ -1604,7 +1628,7 @@ void Server::SendDeleteParticleSpawner(session_t peer_id, u32 id)
|
||||
|
||||
void Server::SendHUDAdd(session_t peer_id, u32 id, HudElement *form)
|
||||
{
|
||||
NetworkPacket pkt(TOCLIENT_HUDADD, 0 , peer_id);
|
||||
NetworkPacket pkt(TOCLIENT_HUDADD, 0 , peer_id, m_clients.getProtocolVersion(peer_id));
|
||||
|
||||
pkt << id << (u8) form->type << form->pos << form->name << form->scale
|
||||
<< form->text << form->number << form->item << form->dir
|
||||
@ -1623,7 +1647,7 @@ void Server::SendHUDRemove(session_t peer_id, u32 id)
|
||||
|
||||
void Server::SendHUDChange(session_t peer_id, u32 id, HudElementStat stat, void *value)
|
||||
{
|
||||
NetworkPacket pkt(TOCLIENT_HUDCHANGE, 0, peer_id);
|
||||
NetworkPacket pkt(TOCLIENT_HUDCHANGE, 0, peer_id, m_clients.getProtocolVersion(peer_id));
|
||||
pkt << id << (u8) stat;
|
||||
|
||||
switch (stat) {
|
||||
@ -1735,7 +1759,8 @@ void Server::SendSetStars(session_t peer_id, const StarParams ¶ms)
|
||||
|
||||
void Server::SendCloudParams(session_t peer_id, const CloudParams ¶ms)
|
||||
{
|
||||
NetworkPacket pkt(TOCLIENT_CLOUD_PARAMS, 0, peer_id);
|
||||
NetworkPacket pkt(TOCLIENT_CLOUD_PARAMS, 0, peer_id,
|
||||
m_clients.getProtocolVersion(peer_id));
|
||||
pkt << params.density << params.color_bright << params.color_ambient
|
||||
<< params.height << params.thickness << params.speed;
|
||||
Send(&pkt);
|
||||
@ -1754,15 +1779,20 @@ void Server::SendOverrideDayNightRatio(session_t peer_id, bool do_override,
|
||||
|
||||
void Server::SendTimeOfDay(session_t peer_id, u16 time, f32 time_speed)
|
||||
{
|
||||
NetworkPacket pkt(TOCLIENT_TIME_OF_DAY, 0, peer_id);
|
||||
pkt << time << time_speed;
|
||||
if (peer_id != PEER_ID_INEXISTENT) {
|
||||
NetworkPacket pkt(TOCLIENT_TIME_OF_DAY, 0, peer_id,
|
||||
m_clients.getProtocolVersion(peer_id));
|
||||
pkt << time << time_speed;
|
||||
|
||||
if (peer_id == PEER_ID_INEXISTENT) {
|
||||
m_clients.sendToAll(&pkt);
|
||||
}
|
||||
else {
|
||||
Send(&pkt);
|
||||
return;
|
||||
}
|
||||
|
||||
NetworkPacket pkt(TOCLIENT_TIME_OF_DAY, 0, peer_id, 37);
|
||||
NetworkPacket legacypkt(TOCLIENT_TIME_OF_DAY, 0, peer_id, 32);
|
||||
pkt << time << time_speed;
|
||||
legacypkt << time << time_speed;
|
||||
m_clients.sendToAllCompat(&pkt, &legacypkt, 37);
|
||||
}
|
||||
|
||||
void Server::SendPlayerHP(session_t peer_id)
|
||||
@ -1792,7 +1822,7 @@ void Server::SendMovePlayer(session_t peer_id)
|
||||
PlayerSAO *sao = player->getPlayerSAO();
|
||||
assert(sao);
|
||||
|
||||
NetworkPacket pkt(TOCLIENT_MOVE_PLAYER, sizeof(v3f) + sizeof(f32) * 2, peer_id);
|
||||
NetworkPacket pkt(TOCLIENT_MOVE_PLAYER, sizeof(v3f) + sizeof(f32) * 2, peer_id, player->protocol_version);
|
||||
pkt << sao->getBasePosition() << sao->getLookPitch() << sao->getRotation().Y;
|
||||
|
||||
{
|
||||
@ -1821,7 +1851,7 @@ void Server::SendLocalPlayerAnimations(session_t peer_id, v2s32 animation_frames
|
||||
f32 animation_speed)
|
||||
{
|
||||
NetworkPacket pkt(TOCLIENT_LOCAL_PLAYER_ANIMATIONS, 0,
|
||||
peer_id);
|
||||
peer_id, m_clients.getProtocolVersion(peer_id));
|
||||
|
||||
pkt << animation_frames[0] << animation_frames[1] << animation_frames[2]
|
||||
<< animation_frames[3] << animation_speed;
|
||||
@ -1831,7 +1861,7 @@ void Server::SendLocalPlayerAnimations(session_t peer_id, v2s32 animation_frames
|
||||
|
||||
void Server::SendEyeOffset(session_t peer_id, v3f first, v3f third)
|
||||
{
|
||||
NetworkPacket pkt(TOCLIENT_EYE_OFFSET, 0, peer_id);
|
||||
NetworkPacket pkt(TOCLIENT_EYE_OFFSET, 0, peer_id, m_clients.getProtocolVersion(peer_id));
|
||||
pkt << first << third;
|
||||
Send(&pkt);
|
||||
}
|
||||
@ -1864,7 +1894,12 @@ void Server::SendPlayerInventoryFormspec(session_t peer_id)
|
||||
return;
|
||||
|
||||
NetworkPacket pkt(TOCLIENT_INVENTORY_FORMSPEC, 0, peer_id);
|
||||
pkt.putLongString(player->inventory_formspec);
|
||||
if (player->protocol_version < 37 && player->inventory_formspec.find(
|
||||
"no_prepend[]") == std::string::npos)
|
||||
pkt.putLongString(player->inventory_formspec +
|
||||
player->formspec_prepend);
|
||||
else
|
||||
pkt.putLongString(player->inventory_formspec);
|
||||
|
||||
Send(&pkt);
|
||||
}
|
||||
@ -1875,6 +1910,10 @@ void Server::SendPlayerFormspecPrepend(session_t peer_id)
|
||||
assert(player);
|
||||
if (player->getPeerId() == PEER_ID_INEXISTENT)
|
||||
return;
|
||||
if (player->protocol_version < 37) {
|
||||
SendPlayerInventoryFormspec(peer_id);
|
||||
return;
|
||||
}
|
||||
|
||||
NetworkPacket pkt(TOCLIENT_FORMSPEC_PREPEND, 0, peer_id);
|
||||
pkt << player->formspec_prepend;
|
||||
@ -1995,6 +2034,10 @@ void Server::SendActiveObjectMessages(session_t peer_id, const std::string &data
|
||||
|
||||
void Server::SendCSMRestrictionFlags(session_t peer_id)
|
||||
{
|
||||
const u16 protocol_version = m_clients.getProtocolVersion(peer_id);
|
||||
if (protocol_version < 35 && protocol_version != 0)
|
||||
return;
|
||||
|
||||
NetworkPacket pkt(TOCLIENT_CSM_RESTRICTION_FLAGS,
|
||||
sizeof(m_csm_restriction_flags) + sizeof(m_csm_restriction_noderange), peer_id);
|
||||
pkt << m_csm_restriction_flags << m_csm_restriction_noderange;
|
||||
@ -2086,17 +2129,29 @@ s32 Server::playSound(const SimpleSoundSpec &spec,
|
||||
|
||||
float gain = params.gain * spec.gain;
|
||||
NetworkPacket pkt(TOCLIENT_PLAY_SOUND, 0);
|
||||
NetworkPacket legacypkt(TOCLIENT_PLAY_SOUND, 0, PEER_ID_INEXISTENT, 32);
|
||||
pkt << id << spec.name << gain
|
||||
<< (u8) params.type << pos << params.object
|
||||
<< params.loop << params.fade << params.pitch
|
||||
<< ephemeral;
|
||||
legacypkt << id << spec.name << gain
|
||||
<< (u8) params.type << pos << params.object
|
||||
<< params.loop << params.fade;
|
||||
|
||||
bool as_reliable = !ephemeral;
|
||||
bool play_sound = gain > 0;
|
||||
|
||||
for (const u16 dst_client : dst_clients) {
|
||||
const u16 protocol_version = m_clients.getProtocolVersion(dst_client);
|
||||
if (!play_sound && protocol_version < 32)
|
||||
continue;
|
||||
if (psound)
|
||||
psound->clients.insert(dst_client);
|
||||
m_clients.send(dst_client, 0, &pkt, as_reliable);
|
||||
|
||||
if (protocol_version >= 37)
|
||||
m_clients.send(dst_client, 0, &pkt, as_reliable);
|
||||
else
|
||||
m_clients.send(dst_client, 0, &legacypkt, as_reliable);
|
||||
}
|
||||
return id;
|
||||
}
|
||||
@ -2257,6 +2312,13 @@ void Server::sendMetadataChanged(const std::list<v3s16> &meta_updates, float far
|
||||
if (!client)
|
||||
continue;
|
||||
|
||||
if (client->net_proto_version < 37) {
|
||||
for (const v3s16 &pos : meta_updates) {
|
||||
client->SetBlockNotSent(getNodeBlockPos(pos));
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
ServerActiveObject *player = m_env->getActiveObject(i);
|
||||
v3f player_pos = player ? player->getBasePosition() : v3f();
|
||||
|
||||
@ -2303,7 +2365,12 @@ void Server::SendBlockNoLock(session_t peer_id, MapBlock *block, u8 ver,
|
||||
*/
|
||||
|
||||
std::ostringstream os(std::ios_base::binary);
|
||||
block->serialize(os, ver, false);
|
||||
|
||||
RemotePlayer *player = m_env->getPlayer(peer_id);
|
||||
if (player && player->protocol_version < 37)
|
||||
block->serialize(os, ver, false, player->formspec_prepend);
|
||||
else
|
||||
block->serialize(os, ver, false);
|
||||
block->serializeNetworkSpecific(os);
|
||||
std::string s = os.str();
|
||||
|
||||
@ -2483,7 +2550,10 @@ void Server::fillMediaCache()
|
||||
std::vector<std::string> paths;
|
||||
m_modmgr->getModsMediaPaths(paths);
|
||||
fs::GetRecursiveDirs(paths, m_gamespec.path + DIR_DELIM + "textures");
|
||||
fs::GetRecursiveDirs(paths, porting::path_user + DIR_DELIM + "textures" + DIR_DELIM + "server");
|
||||
fs::GetRecursiveDirs(paths, porting::path_user + DIR_DELIM + "textures" +
|
||||
DIR_DELIM + "server");
|
||||
fs::GetRecursiveDirs(paths, porting::path_share + DIR_DELIM + "builtin" +
|
||||
DIR_DELIM + "game" + DIR_DELIM + "models");
|
||||
|
||||
// Collect media file information from paths into cache
|
||||
for (const std::string &mediapath : paths) {
|
||||
@ -2645,7 +2715,9 @@ void Server::sendRequestedMedia(session_t peer_id,
|
||||
void Server::sendDetachedInventory(Inventory *inventory, const std::string &name, session_t peer_id)
|
||||
{
|
||||
NetworkPacket pkt(TOCLIENT_DETACHED_INVENTORY, 0, peer_id);
|
||||
NetworkPacket legacy_pkt(TOCLIENT_DETACHED_INVENTORY, 0, peer_id);
|
||||
pkt << name;
|
||||
legacy_pkt << name;
|
||||
|
||||
if (!inventory) {
|
||||
pkt << false; // Remove inventory
|
||||
@ -2660,12 +2732,25 @@ void Server::sendDetachedInventory(Inventory *inventory, const std::string &name
|
||||
const std::string &os_str = os.str();
|
||||
pkt << static_cast<u16>(os_str.size()); // HACK: to keep compatibility with 5.0.0 clients
|
||||
pkt.putRawString(os_str);
|
||||
legacy_pkt.putRawString(os_str);
|
||||
}
|
||||
|
||||
if (peer_id == PEER_ID_INEXISTENT)
|
||||
m_clients.sendToAll(&pkt);
|
||||
else
|
||||
Send(&pkt);
|
||||
if (peer_id == PEER_ID_INEXISTENT) {
|
||||
m_clients.newSendToAll(&pkt);
|
||||
if (inventory)
|
||||
m_clients.oldSendToAll(&legacy_pkt);
|
||||
} else {
|
||||
RemoteClient *client = getClientNoEx(peer_id, CS_Created);
|
||||
if (!client) {
|
||||
warningstream << "Could not get client in sendDetachedInventory!"
|
||||
<< std::endl;
|
||||
}
|
||||
|
||||
if (!client || client->net_proto_version >= 37)
|
||||
Send(&pkt);
|
||||
else if (inventory)
|
||||
Send(&legacy_pkt);
|
||||
}
|
||||
}
|
||||
|
||||
void Server::sendDetachedInventories(session_t peer_id, bool incremental)
|
||||
@ -2774,7 +2859,7 @@ void Server::acceptAuth(session_t peer_id, bool forSudoMode)
|
||||
if (!forSudoMode) {
|
||||
RemoteClient* client = getClient(peer_id, CS_Invalid);
|
||||
|
||||
NetworkPacket resp_pkt(TOCLIENT_AUTH_ACCEPT, 1 + 6 + 8 + 4, peer_id);
|
||||
NetworkPacket resp_pkt(TOCLIENT_AUTH_ACCEPT, 1 + 6 + 8 + 4, peer_id, client->net_proto_version);
|
||||
|
||||
// Right now, the auth mechs don't change between login and sudo mode.
|
||||
u32 sudo_auth_mechs = client->allowed_auth_mechs;
|
||||
|
@ -374,7 +374,7 @@ private:
|
||||
|
||||
void init();
|
||||
|
||||
void SendMovement(session_t peer_id);
|
||||
void SendMovement(session_t peer_id, u16 protocol_version);
|
||||
void SendHP(session_t peer_id, u16 hp);
|
||||
void SendBreath(session_t peer_id, u16 breath);
|
||||
void SendAccessDenied(session_t peer_id, AccessDeniedCode reason,
|
||||
|
@ -117,9 +117,10 @@ void LuaEntitySAO::step(float dtime, bool send_recommended)
|
||||
if(!m_properties_sent)
|
||||
{
|
||||
m_properties_sent = true;
|
||||
std::string str = getPropertyPacket();
|
||||
std::string str = getPropertyPacket(37);
|
||||
std::string legacy_str = getPropertyPacket(32);
|
||||
// create message and add to list
|
||||
m_messages_out.emplace(getId(), true, str);
|
||||
m_messages_out.emplace(getId(), true, str, legacy_str);
|
||||
}
|
||||
|
||||
// If attached, check that our parent is still there. If it isn't, detach.
|
||||
@ -228,19 +229,26 @@ std::string LuaEntitySAO::getClientInitializationData(u16 protocol_version)
|
||||
os << serializeString(""); // name
|
||||
writeU8(os, 0); // is_player
|
||||
writeU16(os, getId()); //id
|
||||
writeV3F32(os, m_base_position);
|
||||
writeV3F32(os, m_rotation);
|
||||
writeV3F(os, m_base_position, protocol_version);
|
||||
if (protocol_version >= 37)
|
||||
writeV3F32(os, m_rotation);
|
||||
else
|
||||
writeF1000(os, m_rotation.Y);
|
||||
writeU16(os, m_hp);
|
||||
|
||||
std::ostringstream msg_os(std::ios::binary);
|
||||
msg_os << serializeLongString(getPropertyPacket()); // message 1
|
||||
msg_os << serializeLongString(getPropertyPacket(
|
||||
protocol_version)); // message 1
|
||||
msg_os << serializeLongString(generateUpdateArmorGroupsCommand()); // 2
|
||||
msg_os << serializeLongString(generateUpdateAnimationCommand()); // 3
|
||||
msg_os << serializeLongString(generateUpdateAnimationCommand(
|
||||
protocol_version)); // 3
|
||||
for (const auto &bone_pos : m_bone_position) {
|
||||
msg_os << serializeLongString(generateUpdateBonePositionCommand(
|
||||
bone_pos.first, bone_pos.second.X, bone_pos.second.Y)); // m_bone_position.size
|
||||
bone_pos.first, bone_pos.second.X, bone_pos.second.Y,
|
||||
protocol_version)); // m_bone_position.size
|
||||
}
|
||||
msg_os << serializeLongString(generateUpdateAttachmentCommand()); // 4
|
||||
msg_os << serializeLongString(generateUpdateAttachmentCommand(
|
||||
protocol_version)); // 4
|
||||
|
||||
int message_count = 4 + m_bone_position.size();
|
||||
|
||||
@ -472,9 +480,9 @@ std::string LuaEntitySAO::getName()
|
||||
return m_init_name;
|
||||
}
|
||||
|
||||
std::string LuaEntitySAO::getPropertyPacket()
|
||||
std::string LuaEntitySAO::getPropertyPacket(const u16 protocol_version)
|
||||
{
|
||||
return generateSetPropertiesCommand(m_prop);
|
||||
return generateSetPropertiesCommand(m_prop, protocol_version);
|
||||
}
|
||||
|
||||
void LuaEntitySAO::sendPosition(bool do_interpolate, bool is_movement_end)
|
||||
@ -500,10 +508,23 @@ void LuaEntitySAO::sendPosition(bool do_interpolate, bool is_movement_end)
|
||||
m_rotation,
|
||||
do_interpolate,
|
||||
is_movement_end,
|
||||
update_interval
|
||||
update_interval,
|
||||
37
|
||||
);
|
||||
|
||||
std::string legacy_str = generateUpdatePositionCommand(
|
||||
m_base_position,
|
||||
m_velocity,
|
||||
m_acceleration,
|
||||
m_rotation,
|
||||
do_interpolate,
|
||||
is_movement_end,
|
||||
update_interval,
|
||||
32
|
||||
);
|
||||
|
||||
// create message and add to list
|
||||
m_messages_out.emplace(getId(), false, str);
|
||||
m_messages_out.emplace(getId(), false, str, legacy_str);
|
||||
}
|
||||
|
||||
bool LuaEntitySAO::getCollisionBox(aabb3f *toset) const
|
||||
|
@ -71,7 +71,7 @@ public:
|
||||
bool collideWithObjects() const;
|
||||
|
||||
private:
|
||||
std::string getPropertyPacket();
|
||||
std::string getPropertyPacket(const u16 protocol_version);
|
||||
void sendPosition(bool do_interpolate, bool is_movement_end);
|
||||
std::string generateSetTextureModCommand() const;
|
||||
static std::string generateSetSpriteCommand(v2s16 p, u16 num_frames,
|
||||
|
@ -112,20 +112,37 @@ std::string PlayerSAO::getClientInitializationData(u16 protocol_version)
|
||||
os << serializeString(m_player->getName()); // name
|
||||
writeU8(os, 1); // is_player
|
||||
writeS16(os, getId()); // id
|
||||
writeV3F32(os, m_base_position);
|
||||
writeV3F32(os, m_rotation);
|
||||
writeU16(os, getHP());
|
||||
if (protocol_version >= 37) {
|
||||
writeV3F32(os, m_base_position);
|
||||
writeV3F32(os, m_rotation);
|
||||
writeU16(os, getHP());
|
||||
} else {
|
||||
writeV3F1000(os, m_base_position + v3f(0, BS, 0));
|
||||
writeF1000(os, m_rotation.Y);
|
||||
|
||||
// HP is sent as a signed integer
|
||||
const u16 hp = getHP();
|
||||
if (hp > S16_MAX)
|
||||
writeS16(os, S16_MAX);
|
||||
else
|
||||
writeS16(os, static_cast<s16>(hp));
|
||||
}
|
||||
|
||||
std::ostringstream msg_os(std::ios::binary);
|
||||
msg_os << serializeLongString(getPropertyPacket()); // message 1
|
||||
msg_os << serializeLongString(getPropertyPacket(
|
||||
protocol_version)); // message 1
|
||||
msg_os << serializeLongString(generateUpdateArmorGroupsCommand()); // 2
|
||||
msg_os << serializeLongString(generateUpdateAnimationCommand()); // 3
|
||||
msg_os << serializeLongString(generateUpdateAnimationCommand(
|
||||
protocol_version)); // 3
|
||||
for (const auto &bone_pos : m_bone_position) {
|
||||
msg_os << serializeLongString(generateUpdateBonePositionCommand(
|
||||
bone_pos.first, bone_pos.second.X, bone_pos.second.Y)); // m_bone_position.size
|
||||
bone_pos.first, bone_pos.second.X, bone_pos.second.Y,
|
||||
protocol_version)); // m_bone_position.size
|
||||
}
|
||||
msg_os << serializeLongString(generateUpdateAttachmentCommand()); // 4
|
||||
msg_os << serializeLongString(generateUpdatePhysicsOverrideCommand()); // 5
|
||||
msg_os << serializeLongString(generateUpdateAttachmentCommand(
|
||||
protocol_version)); // 4
|
||||
msg_os << serializeLongString(generateUpdatePhysicsOverrideCommand(
|
||||
protocol_version)); // 5
|
||||
|
||||
int message_count = 5 + m_bone_position.size();
|
||||
|
||||
@ -221,9 +238,10 @@ void PlayerSAO::step(float dtime, bool send_recommended)
|
||||
|
||||
if (!m_properties_sent) {
|
||||
m_properties_sent = true;
|
||||
std::string str = getPropertyPacket();
|
||||
std::string str = getPropertyPacket(37);
|
||||
std::string legacy_str = getPropertyPacket(32);
|
||||
// create message and add to list
|
||||
m_messages_out.emplace(getId(), true, str);
|
||||
m_messages_out.emplace(getId(), true, str, legacy_str);
|
||||
m_env->getScriptIface()->player_event(this, "properties_changed");
|
||||
}
|
||||
|
||||
@ -286,30 +304,45 @@ void PlayerSAO::step(float dtime, bool send_recommended)
|
||||
m_rotation,
|
||||
true,
|
||||
false,
|
||||
update_interval
|
||||
update_interval,
|
||||
37
|
||||
);
|
||||
|
||||
std::string legacy_str = generateUpdatePositionCommand(
|
||||
pos + v3f(0.0f, BS, 0.0f),
|
||||
v3f(0.0f, 0.0f, 0.0f),
|
||||
v3f(0.0f, 0.0f, 0.0f),
|
||||
m_rotation,
|
||||
true,
|
||||
false,
|
||||
update_interval,
|
||||
32
|
||||
);
|
||||
|
||||
// create message and add to list
|
||||
m_messages_out.emplace(getId(), false, str);
|
||||
m_messages_out.emplace(getId(), false, str, legacy_str);
|
||||
}
|
||||
|
||||
if (!m_physics_override_sent) {
|
||||
m_physics_override_sent = true;
|
||||
// create message and add to list
|
||||
m_messages_out.emplace(getId(), true, generateUpdatePhysicsOverrideCommand());
|
||||
m_messages_out.emplace(getId(), true,
|
||||
generateUpdatePhysicsOverrideCommand(37),
|
||||
generateUpdatePhysicsOverrideCommand(32));
|
||||
}
|
||||
|
||||
sendOutdatedData();
|
||||
}
|
||||
|
||||
std::string PlayerSAO::generateUpdatePhysicsOverrideCommand() const
|
||||
std::string PlayerSAO::generateUpdatePhysicsOverrideCommand(const u16 protocol_version) const
|
||||
{
|
||||
std::ostringstream os(std::ios::binary);
|
||||
// command
|
||||
writeU8(os, AO_CMD_SET_PHYSICS_OVERRIDE);
|
||||
// parameters
|
||||
writeF32(os, m_physics_override_speed);
|
||||
writeF32(os, m_physics_override_jump);
|
||||
writeF32(os, m_physics_override_gravity);
|
||||
writeF(os, m_physics_override_speed, protocol_version);
|
||||
writeF(os, m_physics_override_jump, protocol_version);
|
||||
writeF(os, m_physics_override_gravity, protocol_version);
|
||||
// these are sent inverted so we get true when the server sends nothing
|
||||
writeU8(os, !m_physics_override_sneak);
|
||||
writeU8(os, !m_physics_override_sneak_glitch);
|
||||
@ -537,10 +570,26 @@ void PlayerSAO::unlinkPlayerSessionAndSave()
|
||||
m_env->removePlayer(m_player);
|
||||
}
|
||||
|
||||
std::string PlayerSAO::getPropertyPacket()
|
||||
std::string PlayerSAO::getPropertyPacket(const u16 protocol_version)
|
||||
{
|
||||
m_prop.is_visible = (true);
|
||||
return generateSetPropertiesCommand(m_prop);
|
||||
|
||||
ObjectProperties prop = m_prop;
|
||||
if (protocol_version < 37 && (m_prop.mesh == "3d_armor_character.b3d" ||
|
||||
m_prop.mesh == "character.b3d" ||
|
||||
m_prop.mesh == "skinsdb_3d_armor_character_5.b3d")) {
|
||||
prop.mesh = "mc_compat_character.b3d";
|
||||
for (u16 i = prop.textures.size(); i < 5; i++) {
|
||||
prop.textures.emplace_back("blank.png");
|
||||
}
|
||||
}
|
||||
|
||||
// Remove a one-node offset from a copy of the object properties for MT 0.4
|
||||
if (protocol_version < 37) {
|
||||
prop.selectionbox.MinEdge.Y -= 1.0f;
|
||||
prop.selectionbox.MaxEdge.Y -= 1.0f;
|
||||
}
|
||||
return generateSetPropertiesCommand(prop, protocol_version);
|
||||
}
|
||||
|
||||
void PlayerSAO::setMaxSpeedOverride(const v3f &vel)
|
||||
|
@ -180,9 +180,10 @@ public:
|
||||
inline Metadata &getMeta() { return m_meta; }
|
||||
|
||||
private:
|
||||
std::string getPropertyPacket();
|
||||
std::string getPropertyPacket(const u16 protocol_version);
|
||||
void unlinkPlayerSessionAndSave();
|
||||
std::string generateUpdatePhysicsOverrideCommand() const;
|
||||
std::string generateUpdatePhysicsOverrideCommand(
|
||||
const u16 protocol_version) const;
|
||||
|
||||
RemotePlayer *m_player = nullptr;
|
||||
session_t m_peer_id = 0;
|
||||
|
@ -99,24 +99,34 @@ void UnitSAO::sendOutdatedData()
|
||||
if (!m_animation_sent) {
|
||||
m_animation_sent = true;
|
||||
m_animation_speed_sent = true;
|
||||
m_messages_out.emplace(getId(), true, generateUpdateAnimationCommand());
|
||||
m_messages_out.emplace(getId(), true,
|
||||
generateUpdateAnimationCommand(37),
|
||||
generateUpdateAnimationCommand(32));
|
||||
} else if (!m_animation_speed_sent) {
|
||||
// Animation speed is also sent when 'm_animation_sent == false'
|
||||
m_animation_speed_sent = true;
|
||||
m_messages_out.emplace(getId(), true, generateUpdateAnimationSpeedCommand());
|
||||
m_messages_out.emplace(getId(), true,
|
||||
generateUpdateAnimationSpeedCommand(),
|
||||
// MT 0.4 has no update animation speed command
|
||||
generateUpdateAnimationCommand(32));
|
||||
}
|
||||
|
||||
if (!m_bone_position_sent) {
|
||||
m_bone_position_sent = true;
|
||||
for (const auto &bone_pos : m_bone_position) {
|
||||
m_messages_out.emplace(getId(), true, generateUpdateBonePositionCommand(
|
||||
bone_pos.first, bone_pos.second.X, bone_pos.second.Y));
|
||||
std::string str = generateUpdateBonePositionCommand(
|
||||
bone_pos.first, bone_pos.second.X, bone_pos.second.Y, 37);
|
||||
std::string legacy_str = generateUpdateBonePositionCommand(
|
||||
bone_pos.first, bone_pos.second.X, bone_pos.second.Y, 32);
|
||||
m_messages_out.emplace(getId(), true, str, legacy_str);
|
||||
}
|
||||
}
|
||||
|
||||
if (!m_attachment_sent) {
|
||||
m_attachment_sent = true;
|
||||
m_messages_out.emplace(getId(), true, generateUpdateAttachmentCommand());
|
||||
m_messages_out.emplace(getId(), true,
|
||||
generateUpdateAttachmentCommand(37),
|
||||
generateUpdateAttachmentCommand(32));
|
||||
}
|
||||
}
|
||||
// clang-format on
|
||||
@ -235,7 +245,7 @@ void UnitSAO::notifyObjectPropertiesModified()
|
||||
m_properties_sent = false;
|
||||
}
|
||||
|
||||
std::string UnitSAO::generateUpdateAttachmentCommand() const
|
||||
std::string UnitSAO::generateUpdateAttachmentCommand(const u16 protocol_version) const
|
||||
{
|
||||
std::ostringstream os(std::ios::binary);
|
||||
// command
|
||||
@ -243,21 +253,37 @@ std::string UnitSAO::generateUpdateAttachmentCommand() const
|
||||
// parameters
|
||||
writeS16(os, m_attachment_parent_id);
|
||||
os << serializeString(m_attachment_bone);
|
||||
writeV3F32(os, m_attachment_position);
|
||||
writeV3F32(os, m_attachment_rotation);
|
||||
|
||||
// Add/remove offsets to compensate for MT 0.4
|
||||
if (protocol_version >= 37) {
|
||||
writeV3F32(os, m_attachment_position);
|
||||
} else {
|
||||
v3f compat_attachment_position = m_attachment_position;
|
||||
if (getType() == ACTIVEOBJECT_TYPE_PLAYER) {
|
||||
compat_attachment_position.Y += BS;
|
||||
} else {
|
||||
ServerActiveObject *p =
|
||||
m_env->getActiveObject(m_attachment_parent_id);
|
||||
if (p && p->getType() == ACTIVEOBJECT_TYPE_PLAYER)
|
||||
compat_attachment_position.Y -= BS;
|
||||
}
|
||||
writeV3F1000(os, compat_attachment_position);
|
||||
}
|
||||
|
||||
writeV3F(os, m_attachment_rotation, protocol_version);
|
||||
return os.str();
|
||||
}
|
||||
|
||||
std::string UnitSAO::generateUpdateBonePositionCommand(
|
||||
const std::string &bone, const v3f &position, const v3f &rotation)
|
||||
std::string UnitSAO::generateUpdateBonePositionCommand(const std::string &bone,
|
||||
const v3f &position, const v3f &rotation, const u16 protocol_version)
|
||||
{
|
||||
std::ostringstream os(std::ios::binary);
|
||||
// command
|
||||
writeU8(os, AO_CMD_SET_BONE_POSITION);
|
||||
// parameters
|
||||
os << serializeString(bone);
|
||||
writeV3F32(os, position);
|
||||
writeV3F32(os, rotation);
|
||||
writeV3F(os, position, protocol_version);
|
||||
writeV3F(os, rotation, protocol_version);
|
||||
return os.str();
|
||||
}
|
||||
|
||||
@ -271,15 +297,15 @@ std::string UnitSAO::generateUpdateAnimationSpeedCommand() const
|
||||
return os.str();
|
||||
}
|
||||
|
||||
std::string UnitSAO::generateUpdateAnimationCommand() const
|
||||
std::string UnitSAO::generateUpdateAnimationCommand(const u16 protocol_version) const
|
||||
{
|
||||
std::ostringstream os(std::ios::binary);
|
||||
// command
|
||||
writeU8(os, AO_CMD_SET_ANIMATION);
|
||||
// parameters
|
||||
writeV2F32(os, m_animation_range);
|
||||
writeF32(os, m_animation_speed);
|
||||
writeF32(os, m_animation_blend);
|
||||
writeV2F(os, m_animation_range, protocol_version);
|
||||
writeF(os, m_animation_speed, protocol_version);
|
||||
writeF(os, m_animation_blend, protocol_version);
|
||||
// these are sent inverted so we get true when the server sends nothing
|
||||
writeU8(os, !m_animation_loop);
|
||||
return os.str();
|
||||
@ -299,33 +325,38 @@ std::string UnitSAO::generateUpdateArmorGroupsCommand() const
|
||||
|
||||
std::string UnitSAO::generateUpdatePositionCommand(const v3f &position,
|
||||
const v3f &velocity, const v3f &acceleration, const v3f &rotation,
|
||||
bool do_interpolate, bool is_movement_end, f32 update_interval)
|
||||
bool do_interpolate, bool is_movement_end, f32 update_interval,
|
||||
const u16 protocol_version)
|
||||
{
|
||||
std::ostringstream os(std::ios::binary);
|
||||
// command
|
||||
writeU8(os, AO_CMD_UPDATE_POSITION);
|
||||
// pos
|
||||
writeV3F32(os, position);
|
||||
writeV3F(os, position, protocol_version);
|
||||
// velocity
|
||||
writeV3F32(os, velocity);
|
||||
writeV3F(os, velocity, protocol_version);
|
||||
// acceleration
|
||||
writeV3F32(os, acceleration);
|
||||
writeV3F(os, acceleration, protocol_version);
|
||||
// rotation
|
||||
writeV3F32(os, rotation);
|
||||
if (protocol_version >= 37)
|
||||
writeV3F32(os, rotation);
|
||||
else
|
||||
writeF1000(os, rotation.Y);
|
||||
// do_interpolate
|
||||
writeU8(os, do_interpolate);
|
||||
// is_end_position (for interpolation)
|
||||
writeU8(os, is_movement_end);
|
||||
// update_interval (for interpolation)
|
||||
writeF32(os, update_interval);
|
||||
writeF(os, update_interval, protocol_version);
|
||||
return os.str();
|
||||
}
|
||||
|
||||
std::string UnitSAO::generateSetPropertiesCommand(const ObjectProperties &prop) const
|
||||
std::string UnitSAO::generateSetPropertiesCommand(
|
||||
const ObjectProperties &prop, const u16 protocol_version) const
|
||||
{
|
||||
std::ostringstream os(std::ios::binary);
|
||||
writeU8(os, AO_CMD_SET_PROPERTIES);
|
||||
prop.serialize(os);
|
||||
prop.serialize(os, protocol_version);
|
||||
return os.str();
|
||||
}
|
||||
|
||||
@ -339,7 +370,19 @@ std::string UnitSAO::generatePunchCommand(u16 result_hp) const
|
||||
return os.str();
|
||||
}
|
||||
|
||||
std::string UnitSAO::generateLegacyPunchCommand(u16 result_hp) const
|
||||
{
|
||||
std::ostringstream os(std::ios::binary);
|
||||
// command
|
||||
writeU8(os, AO_CMD_PUNCHED);
|
||||
// result_hp
|
||||
writeU16(os, result_hp);
|
||||
return os.str();
|
||||
}
|
||||
|
||||
void UnitSAO::sendPunchCommand()
|
||||
{
|
||||
m_messages_out.emplace(getId(), true, generatePunchCommand(getHP()));
|
||||
const u16 result_hp = getHP();
|
||||
m_messages_out.emplace(getId(), true, generatePunchCommand(result_hp),
|
||||
generateLegacyPunchCommand(result_hp));
|
||||
}
|
||||
|
@ -20,6 +20,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "constants.h"
|
||||
#include "object_properties.h"
|
||||
#include "serveractiveobject.h"
|
||||
|
||||
@ -79,16 +80,19 @@ public:
|
||||
void sendOutdatedData();
|
||||
|
||||
// Update packets
|
||||
std::string generateUpdateAttachmentCommand() const;
|
||||
std::string generateUpdateAttachmentCommand(const u16 protocol_version) const;
|
||||
std::string generateUpdateAnimationSpeedCommand() const;
|
||||
std::string generateUpdateAnimationCommand() const;
|
||||
std::string generateUpdateAnimationCommand(const u16 protocol_version) const;
|
||||
std::string generateUpdateArmorGroupsCommand() const;
|
||||
static std::string generateUpdatePositionCommand(const v3f &position,
|
||||
const v3f &velocity, const v3f &acceleration, const v3f &rotation,
|
||||
bool do_interpolate, bool is_movement_end, f32 update_interval);
|
||||
std::string generateSetPropertiesCommand(const ObjectProperties &prop) const;
|
||||
bool do_interpolate, bool is_movement_end, f32 update_interval,
|
||||
const u16 protocol_version);
|
||||
std::string generateSetPropertiesCommand(
|
||||
const ObjectProperties &prop, const u16 protocol_version) const;
|
||||
static std::string generateUpdateBonePositionCommand(const std::string &bone,
|
||||
const v3f &position, const v3f &rotation);
|
||||
const v3f &position, const v3f &rotation,
|
||||
const u16 protocol_version);
|
||||
void sendPunchCommand();
|
||||
|
||||
protected:
|
||||
@ -112,6 +116,7 @@ private:
|
||||
void onDetach(int parent_id);
|
||||
|
||||
std::string generatePunchCommand(u16 result_hp) const;
|
||||
std::string generateLegacyPunchCommand(u16 result_hp) const;
|
||||
|
||||
// Armor groups
|
||||
bool m_armor_groups_sent = false;
|
||||
|
@ -40,6 +40,12 @@ struct SimpleSoundSpec
|
||||
void serialize(std::ostream &os, u8 cf_version) const
|
||||
{
|
||||
os << serializeString(name);
|
||||
if (cf_version < 13) {
|
||||
writeF1000(os, gain);
|
||||
if (cf_version > 10)
|
||||
writeF1000(os, pitch);
|
||||
return;
|
||||
}
|
||||
writeF32(os, gain);
|
||||
writeF32(os, pitch);
|
||||
writeF32(os, fade);
|
||||
|
@ -21,15 +21,27 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
|
||||
void TileAnimationParams::serialize(std::ostream &os, u8 tiledef_version) const
|
||||
{
|
||||
if (tiledef_version < 3 && type != TAT_VERTICAL_FRAMES) {
|
||||
writeU8(os, TAT_NONE);
|
||||
writeU16(os, 1);
|
||||
writeU16(os, 1);
|
||||
writeF1000(os, 1.0f);
|
||||
return;
|
||||
}
|
||||
|
||||
writeU8(os, type);
|
||||
|
||||
// Approximate protocol version
|
||||
const u16 protocol_version = tiledef_version >= 6 ? 37 : 32;
|
||||
|
||||
if (type == TAT_VERTICAL_FRAMES) {
|
||||
writeU16(os, vertical_frames.aspect_w);
|
||||
writeU16(os, vertical_frames.aspect_h);
|
||||
writeF32(os, vertical_frames.length);
|
||||
writeF(os, vertical_frames.length, protocol_version);
|
||||
} else if (type == TAT_SHEET_2D) {
|
||||
writeU8(os, sheet_2d.frames_w);
|
||||
writeU8(os, sheet_2d.frames_h);
|
||||
writeF32(os, sheet_2d.frame_length);
|
||||
writeF(os, sheet_2d.frame_length, protocol_version);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -58,9 +58,11 @@ void ToolCapabilities::serialize(std::ostream &os, u16 protocol_version) const
|
||||
{
|
||||
if (protocol_version >= 38)
|
||||
writeU8(os, 5);
|
||||
else
|
||||
else if (protocol_version == 37)
|
||||
writeU8(os, 4); // proto == 37
|
||||
writeF32(os, full_punch_interval);
|
||||
else
|
||||
writeU8(os, 2); // proto >= 18
|
||||
writeF(os, full_punch_interval, protocol_version);
|
||||
writeS16(os, max_drop_level);
|
||||
writeU32(os, groupcaps.size());
|
||||
for (const auto &groupcap : groupcaps) {
|
||||
@ -72,7 +74,7 @@ void ToolCapabilities::serialize(std::ostream &os, u16 protocol_version) const
|
||||
writeU32(os, cap->times.size());
|
||||
for (const auto &time : cap->times) {
|
||||
writeS16(os, time.first);
|
||||
writeF32(os, time.second);
|
||||
writeF(os, time.second, protocol_version);
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user