mirror of https://github.com/minetest/minetest.git
Merge remote-tracking branch 'upstream/master'
This commit is contained in:
commit
c911ab2c17
|
@ -12,7 +12,7 @@ set(VERSION_EXTRA "" CACHE STRING "Stuff to append to version string")
|
|||
# Also remember to set PROTOCOL_VERSION in clientserver.h when releasing
|
||||
set(VERSION_MAJOR 0)
|
||||
set(VERSION_MINOR 4)
|
||||
set(VERSION_PATCH 3)
|
||||
set(VERSION_PATCH 4-dev)
|
||||
if(VERSION_EXTRA)
|
||||
set(VERSION_PATCH ${VERSION_PATCH}-${VERSION_EXTRA})
|
||||
endif()
|
||||
|
|
|
@ -138,6 +138,7 @@ minetest.register_chatcommand("grant", {
|
|||
return
|
||||
end
|
||||
minetest.set_player_privs(grantname, privs)
|
||||
minetest.log(name..' granted ('..minetest.privs_to_string(grantprivs, ', ')..') privileges to '..grantname)
|
||||
minetest.chat_send_player(name, "Privileges of "..grantname..": "..minetest.privs_to_string(minetest.get_player_privs(grantname), ' '))
|
||||
if grantname ~= name then
|
||||
minetest.chat_send_player(grantname, name.." granted you privileges: "..minetest.privs_to_string(grantprivs, ' '))
|
||||
|
@ -175,6 +176,7 @@ minetest.register_chatcommand("revoke", {
|
|||
end
|
||||
end
|
||||
minetest.set_player_privs(revokename, privs)
|
||||
minetest.log(name..' revoked ('..minetest.privs_to_string(revokeprivs, ', ')..') privileges from '..revokename)
|
||||
minetest.chat_send_player(name, "Privileges of "..revokename..": "..minetest.privs_to_string(minetest.get_player_privs(revokename), ' '))
|
||||
if revokename ~= name then
|
||||
minetest.chat_send_player(revokename, name.." revoked privileges from you: "..minetest.privs_to_string(revokeprivs, ' '))
|
||||
|
|
|
@ -303,6 +303,7 @@ end
|
|||
|
||||
minetest.registered_on_chat_messages, minetest.register_on_chat_message = make_registration()
|
||||
minetest.registered_globalsteps, minetest.register_globalstep = make_registration()
|
||||
minetest.registered_on_shutdown, minetest.register_on_shutdown = make_registration()
|
||||
minetest.registered_on_punchnodes, minetest.register_on_punchnode = make_registration()
|
||||
minetest.registered_on_placenodes, minetest.register_on_placenode = make_registration()
|
||||
minetest.registered_on_dignodes, minetest.register_on_dignode = make_registration()
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
Minetest Lua Modding API Reference 0.4.3
|
||||
Minetest Lua Modding API Reference 0.4.4
|
||||
==========================================
|
||||
More information at http://c55.me/minetest/
|
||||
|
||||
|
@ -792,6 +792,11 @@ minetest.register_craft(recipe)
|
|||
Global callback registration functions: (Call these only at load time)
|
||||
minetest.register_globalstep(func(dtime))
|
||||
^ Called every server step, usually interval of 0.05s
|
||||
minetest.register_on_shutdown(func())
|
||||
^ Called before server shutdown
|
||||
^ WARNING: If the server terminates abnormally (i.e. crashes), the registered
|
||||
callbacks WILL LIKELY NOT BE RUN. Data should be saved at
|
||||
semi-frequent intervals as well as on server shutdown.
|
||||
minetest.register_on_placenode(func(pos, newnode, placer, oldnode))
|
||||
^ Called when a node has been placed
|
||||
^ Deprecated: Use on_construct or after_place_node in node definition instead
|
||||
|
|
|
@ -139,8 +139,8 @@
|
|||
#motd = Welcome to this awesome Minetest server!
|
||||
# Maximum number of players connected simultaneously
|
||||
#max_users = 100
|
||||
# Set to false to allow old clients to connect
|
||||
#strict_protocol_version_checking = true
|
||||
# Set to true to disallow old clients from connecting
|
||||
#strict_protocol_version_checking = false
|
||||
# Set to true to enable creative mode (unlimited inventory)
|
||||
#creative_mode = false
|
||||
# Enable players getting damage and dying
|
||||
|
@ -194,7 +194,12 @@
|
|||
# To reduce lag, block transfers are slowed down when a player is building something.
|
||||
# This determines how long they are slowed down after placing or removing a node.
|
||||
#full_block_send_enable_min_time_from_building = 2.0
|
||||
# Length of a server tick in dedicated server
|
||||
#dedicated_server_step = 0.05
|
||||
# Length of a server tick and the interval at which objects are generally updated over network
|
||||
#dedicated_server_step = 0.1
|
||||
# Can be set to true to disable shutting down on invalid world data
|
||||
#ignore_world_load_errors = false
|
||||
# Congestion control parameters
|
||||
# time in seconds, rate in ~500B packets
|
||||
#congestion_control_aim_rtt = 0.2
|
||||
#congestion_control_max_rate = 400
|
||||
#congestion_control_min_rate = 10
|
||||
|
|
|
@ -202,6 +202,8 @@ set(common_SRCS
|
|||
sha1.cpp
|
||||
base64.cpp
|
||||
ban.cpp
|
||||
clientserver.cpp
|
||||
staticobject.cpp
|
||||
util/serialize.cpp
|
||||
util/directiontables.cpp
|
||||
util/numeric.cpp
|
||||
|
|
|
@ -42,6 +42,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||
#include "util/string.h"
|
||||
#include "hex.h"
|
||||
#include "IMeshCache.h"
|
||||
#include "util/serialize.h"
|
||||
|
||||
static std::string getMediaCacheDir()
|
||||
{
|
||||
|
@ -266,6 +267,7 @@ Client::Client(
|
|||
m_time_of_day_set(false),
|
||||
m_last_time_of_day_f(-1),
|
||||
m_time_of_day_update_timer(0),
|
||||
m_recommended_send_interval(0.1),
|
||||
m_removed_sounds_check_timer(0)
|
||||
{
|
||||
m_packetcounter_timer = 0.0;
|
||||
|
@ -499,8 +501,9 @@ void Client::step(float dtime)
|
|||
// [2] u8 SER_FMT_VER_HIGHEST
|
||||
// [3] u8[20] player_name
|
||||
// [23] u8[28] password (new in some version)
|
||||
// [51] u16 client network protocol version (new in some version)
|
||||
SharedBuffer<u8> data(2+1+PLAYERNAME_SIZE+PASSWORD_SIZE+2);
|
||||
// [51] u16 minimum supported network protocol version (added sometime)
|
||||
// [53] u16 maximum supported network protocol version (added later than the previous one)
|
||||
SharedBuffer<u8> data(2+1+PLAYERNAME_SIZE+PASSWORD_SIZE+2+2);
|
||||
writeU16(&data[0], TOSERVER_INIT);
|
||||
writeU8(&data[2], SER_FMT_VER_HIGHEST);
|
||||
|
||||
|
@ -513,8 +516,8 @@ void Client::step(float dtime)
|
|||
memset((char*)&data[23], 0, PASSWORD_SIZE);
|
||||
snprintf((char*)&data[23], PASSWORD_SIZE, "%s", m_password.c_str());
|
||||
|
||||
// This should be incremented in each version
|
||||
writeU16(&data[51], PROTOCOL_VERSION);
|
||||
writeU16(&data[51], CLIENT_PROTOCOL_VERSION_MIN);
|
||||
writeU16(&data[53], CLIENT_PROTOCOL_VERSION_MAX);
|
||||
|
||||
// Send as unreliable
|
||||
Send(0, data, false);
|
||||
|
@ -656,7 +659,7 @@ void Client::step(float dtime)
|
|||
{
|
||||
float &counter = m_playerpos_send_timer;
|
||||
counter += dtime;
|
||||
if(counter >= 0.2)
|
||||
if(counter >= m_recommended_send_interval)
|
||||
{
|
||||
counter = 0.0;
|
||||
sendPlayerPos();
|
||||
|
@ -1020,6 +1023,14 @@ void Client::ProcessData(u8 *data, u32 datasize, u16 sender_peer_id)
|
|||
m_map_seed = readU64(&data[2+1+6]);
|
||||
infostream<<"Client: received map seed: "<<m_map_seed<<std::endl;
|
||||
}
|
||||
|
||||
if(datasize >= 2+1+6+8+4)
|
||||
{
|
||||
// Get map seed
|
||||
m_recommended_send_interval = readF1000(&data[2+1+6+8]);
|
||||
infostream<<"Client: received recommended send interval "
|
||||
<<m_recommended_send_interval<<std::endl;
|
||||
}
|
||||
|
||||
// Reply to server
|
||||
u32 replysize = 2;
|
||||
|
|
|
@ -382,6 +382,9 @@ private:
|
|||
float m_last_time_of_day_f;
|
||||
float m_time_of_day_update_timer;
|
||||
|
||||
// An interval for generally sending object positions and stuff
|
||||
float m_recommended_send_interval;
|
||||
|
||||
// Sounds
|
||||
float m_removed_sounds_check_timer;
|
||||
// Mapping from server sound ids to our sound ids
|
||||
|
|
|
@ -0,0 +1,31 @@
|
|||
/*
|
||||
Minetest-c55
|
||||
Copyright (C) 2010-2012 celeron55, Perttu Ahola <celeron55@gmail.com>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include "clientserver.h"
|
||||
#include "util/serialize.h"
|
||||
|
||||
SharedBuffer<u8> makePacket_TOCLIENT_TIME_OF_DAY(u16 time, float time_speed)
|
||||
{
|
||||
SharedBuffer<u8> data(2+2+4);
|
||||
writeU16(&data[0], TOCLIENT_TIME_OF_DAY);
|
||||
writeU16(&data[2], time);
|
||||
writeF1000(&data[4], time_speed);
|
||||
return data;
|
||||
}
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
Minetest-c55
|
||||
Copyright (C) 2010 celeron55, Perttu Ahola <celeron55@gmail.com>
|
||||
Copyright (C) 2010-2012 celeron55, Perttu Ahola <celeron55@gmail.com>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
|
@ -20,7 +20,9 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||
#ifndef CLIENTSERVER_HEADER
|
||||
#define CLIENTSERVER_HEADER
|
||||
|
||||
#include "util/serialize.h"
|
||||
#include "util/pointer.h"
|
||||
|
||||
SharedBuffer<u8> makePacket_TOCLIENT_TIME_OF_DAY(u16 time, float time_speed);
|
||||
|
||||
/*
|
||||
changes by PROTOCOL_VERSION:
|
||||
|
@ -73,10 +75,21 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||
GENERIC_CMD_SET_ANIMATION
|
||||
GENERIC_CMD_SET_BONE_POSITION
|
||||
GENERIC_CMD_SET_ATTACHMENT
|
||||
PROTOCOL_VERSION 15:
|
||||
Serialization format changes
|
||||
*/
|
||||
|
||||
#define PROTOCOL_VERSION 14
|
||||
#define LATEST_PROTOCOL_VERSION 15
|
||||
|
||||
// Server's supported network protocol range
|
||||
#define SERVER_PROTOCOL_VERSION_MIN 13
|
||||
#define SERVER_PROTOCOL_VERSION_MAX LATEST_PROTOCOL_VERSION
|
||||
|
||||
// Client's supported network protocol range
|
||||
#define CLIENT_PROTOCOL_VERSION_MIN 13
|
||||
#define CLIENT_PROTOCOL_VERSION_MAX LATEST_PROTOCOL_VERSION
|
||||
|
||||
// Constant that differentiates the protocol from random data and other protocols
|
||||
#define PROTOCOL_ID 0x4f457403
|
||||
|
||||
#define PASSWORD_SIZE 28 // Maximum password length. Allows for
|
||||
|
@ -95,6 +108,7 @@ enum ToClientCommand
|
|||
[2] u8 deployed version
|
||||
[3] v3s16 player's position + v3f(0,BS/2,0) floatToInt'd
|
||||
[12] u64 map seed (new as of 2011-02-27)
|
||||
[20] f1000 recommended send interval (in seconds) (new as of 14)
|
||||
|
||||
NOTE: The position in here is deprecated; position is
|
||||
explicitly sent afterwards
|
||||
|
@ -350,7 +364,8 @@ enum ToServerCommand
|
|||
[2] u8 SER_FMT_VER_HIGHEST
|
||||
[3] u8[20] player_name
|
||||
[23] u8[28] password (new in some version)
|
||||
[51] u16 client network protocol version (new in some version)
|
||||
[51] u16 minimum supported network protocol version (added sometime)
|
||||
[53] u16 maximum supported network protocol version (added later than the previous one)
|
||||
*/
|
||||
|
||||
TOSERVER_INIT2 = 0x11,
|
||||
|
@ -558,14 +573,5 @@ enum ToServerCommand
|
|||
|
||||
};
|
||||
|
||||
inline SharedBuffer<u8> makePacket_TOCLIENT_TIME_OF_DAY(u16 time, float time_speed)
|
||||
{
|
||||
SharedBuffer<u8> data(2+2+4);
|
||||
writeU16(&data[0], TOCLIENT_TIME_OF_DAY);
|
||||
writeU16(&data[2], time);
|
||||
writeF1000(&data[4], time_speed);
|
||||
return data;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
@ -25,6 +25,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||
#include "util/serialize.h"
|
||||
#include "util/numeric.h"
|
||||
#include "util/string.h"
|
||||
#include "settings.h"
|
||||
|
||||
namespace con
|
||||
{
|
||||
|
@ -466,7 +467,10 @@ Peer::Peer(u16 a_id, Address a_address):
|
|||
m_sendtime_accu(0),
|
||||
m_max_packets_per_second(10),
|
||||
m_num_sent(0),
|
||||
m_max_num_sent(0)
|
||||
m_max_num_sent(0),
|
||||
congestion_control_aim_rtt(0.2),
|
||||
congestion_control_max_rate(400),
|
||||
congestion_control_min_rate(10)
|
||||
{
|
||||
}
|
||||
Peer::~Peer()
|
||||
|
@ -477,15 +481,15 @@ void Peer::reportRTT(float rtt)
|
|||
{
|
||||
if(rtt >= 0.0){
|
||||
if(rtt < 0.01){
|
||||
if(m_max_packets_per_second < 400)
|
||||
if(m_max_packets_per_second < congestion_control_max_rate)
|
||||
m_max_packets_per_second += 10;
|
||||
} else if(rtt < 0.2){
|
||||
if(m_max_packets_per_second < 100)
|
||||
} else if(rtt < congestion_control_aim_rtt){
|
||||
if(m_max_packets_per_second < congestion_control_max_rate)
|
||||
m_max_packets_per_second += 2;
|
||||
} else {
|
||||
m_max_packets_per_second *= 0.8;
|
||||
if(m_max_packets_per_second < 10)
|
||||
m_max_packets_per_second = 10;
|
||||
if(m_max_packets_per_second < congestion_control_min_rate)
|
||||
m_max_packets_per_second = congestion_control_min_rate;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -891,12 +895,24 @@ void Connection::receive()
|
|||
|
||||
void Connection::runTimeouts(float dtime)
|
||||
{
|
||||
float congestion_control_aim_rtt
|
||||
= g_settings->getFloat("congestion_control_aim_rtt");
|
||||
float congestion_control_max_rate
|
||||
= g_settings->getFloat("congestion_control_max_rate");
|
||||
float congestion_control_min_rate
|
||||
= g_settings->getFloat("congestion_control_min_rate");
|
||||
|
||||
core::list<u16> timeouted_peers;
|
||||
core::map<u16, Peer*>::Iterator j;
|
||||
j = m_peers.getIterator();
|
||||
for(; j.atEnd() == false; j++)
|
||||
{
|
||||
Peer *peer = j.getNode()->getValue();
|
||||
|
||||
// Update congestion control values
|
||||
peer->congestion_control_aim_rtt = congestion_control_aim_rtt;
|
||||
peer->congestion_control_max_rate = congestion_control_max_rate;
|
||||
peer->congestion_control_min_rate = congestion_control_min_rate;
|
||||
|
||||
/*
|
||||
Check peer timeout
|
||||
|
|
|
@ -394,7 +394,11 @@ public:
|
|||
float m_max_packets_per_second;
|
||||
int m_num_sent;
|
||||
int m_max_num_sent;
|
||||
|
||||
|
||||
// Updated from configuration by Connection
|
||||
float congestion_control_aim_rtt;
|
||||
float congestion_control_max_rate;
|
||||
float congestion_control_min_rate;
|
||||
private:
|
||||
};
|
||||
|
||||
|
|
|
@ -647,22 +647,36 @@ public:
|
|||
{
|
||||
infostream<<"GenericCAO: Got init data"<<std::endl;
|
||||
std::istringstream is(data, std::ios::binary);
|
||||
int num_messages = 0;
|
||||
// version
|
||||
u8 version = readU8(is);
|
||||
// check version
|
||||
if(version != 0){
|
||||
if(version == 1) // In PROTOCOL_VERSION 14
|
||||
{
|
||||
m_name = deSerializeString(is);
|
||||
m_is_player = readU8(is);
|
||||
m_id = readS16(is);
|
||||
m_position = readV3F1000(is);
|
||||
m_yaw = readF1000(is);
|
||||
m_hp = readS16(is);
|
||||
num_messages = readU8(is);
|
||||
}
|
||||
else if(version == 0) // In PROTOCOL_VERSION 13
|
||||
{
|
||||
m_name = deSerializeString(is);
|
||||
m_is_player = readU8(is);
|
||||
m_position = readV3F1000(is);
|
||||
m_yaw = readF1000(is);
|
||||
m_hp = readS16(is);
|
||||
num_messages = readU8(is);
|
||||
}
|
||||
else
|
||||
{
|
||||
errorstream<<"GenericCAO: Unsupported init data version"
|
||||
<<std::endl;
|
||||
return;
|
||||
}
|
||||
m_name = deSerializeString(is);
|
||||
m_is_player = readU8(is);
|
||||
m_id = readS16(is);
|
||||
m_position = readV3F1000(is);
|
||||
m_yaw = readF1000(is);
|
||||
m_hp = readS16(is);
|
||||
|
||||
int num_messages = readU8(is);
|
||||
|
||||
for(int i=0; i<num_messages; i++){
|
||||
std::string message = deSerializeLongString(is);
|
||||
processMessage(message);
|
||||
|
@ -909,6 +923,11 @@ public:
|
|||
m_prop.visual_size.X));
|
||||
u8 li = m_last_light;
|
||||
setMeshColor(m_meshnode->getMesh(), video::SColor(255,li,li,li));
|
||||
|
||||
m_meshnode->setMaterialFlag(video::EMF_LIGHTING, false);
|
||||
m_meshnode->setMaterialFlag(video::EMF_BILINEAR_FILTER, false);
|
||||
m_meshnode->setMaterialType(video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF);
|
||||
m_meshnode->setMaterialFlag(video::EMF_FOG_ENABLE, true);
|
||||
}
|
||||
else if(m_prop.visual == "mesh"){
|
||||
infostream<<"GenericCAO::addToScene(): mesh"<<std::endl;
|
||||
|
@ -922,6 +941,11 @@ public:
|
|||
m_prop.visual_size.X));
|
||||
u8 li = m_last_light;
|
||||
setMeshColor(m_animated_meshnode->getMesh(), video::SColor(255,li,li,li));
|
||||
|
||||
m_animated_meshnode->setMaterialFlag(video::EMF_LIGHTING, false);
|
||||
m_animated_meshnode->setMaterialFlag(video::EMF_BILINEAR_FILTER, false);
|
||||
m_animated_meshnode->setMaterialType(video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF);
|
||||
m_animated_meshnode->setMaterialFlag(video::EMF_FOG_ENABLE, true);
|
||||
}
|
||||
else
|
||||
errorstream<<"GenericCAO::addToScene(): Could not load mesh "<<m_prop.mesh<<std::endl;
|
||||
|
|
|
@ -26,7 +26,6 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||
#include "tile.h"
|
||||
#include "gamedef.h"
|
||||
#include "util/numeric.h"
|
||||
#include "util/serialize.h"
|
||||
#include "util/directiontables.h"
|
||||
|
||||
// Create a cuboid.
|
||||
|
|
|
@ -245,7 +245,7 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
std::string getClientInitializationData()
|
||||
std::string getClientInitializationData(u16 protocol_version)
|
||||
{
|
||||
std::ostringstream os(std::ios::binary);
|
||||
// version
|
||||
|
@ -564,25 +564,41 @@ void LuaEntitySAO::step(float dtime, bool send_recommended)
|
|||
}
|
||||
}
|
||||
|
||||
std::string LuaEntitySAO::getClientInitializationData()
|
||||
std::string LuaEntitySAO::getClientInitializationData(u16 protocol_version)
|
||||
{
|
||||
std::ostringstream os(std::ios::binary);
|
||||
writeU8(os, 0); // version
|
||||
os<<serializeString(""); // name
|
||||
writeS16(os, getId()); //id
|
||||
writeU8(os, 0); // is_player
|
||||
writeV3F1000(os, m_base_position);
|
||||
writeF1000(os, m_yaw);
|
||||
writeS16(os, m_hp);
|
||||
|
||||
writeU8(os, 4 + m_bone_position.size()); // number of messages stuffed in here
|
||||
os<<serializeLongString(getPropertyPacket()); // message 1
|
||||
os<<serializeLongString(gob_cmd_update_armor_groups(m_armor_groups)); // 2
|
||||
os<<serializeLongString(gob_cmd_update_animation(m_animation_range, m_animation_speed, m_animation_blend)); // 3
|
||||
for(std::map<std::string, core::vector2d<v3f> >::const_iterator ii = m_bone_position.begin(); ii != m_bone_position.end(); ++ii){
|
||||
os<<serializeLongString(gob_cmd_update_bone_position((*ii).first, (*ii).second.X, (*ii).second.Y)); // m_bone_position.size
|
||||
if(protocol_version >= 14)
|
||||
{
|
||||
writeU8(os, 1); // version
|
||||
os<<serializeString(""); // name
|
||||
writeU8(os, 0); // is_player
|
||||
writeS16(os, getId()); //id
|
||||
writeV3F1000(os, m_base_position);
|
||||
writeF1000(os, m_yaw);
|
||||
writeS16(os, m_hp);
|
||||
|
||||
writeU8(os, 4 + m_bone_position.size()); // number of messages stuffed in here
|
||||
os<<serializeLongString(getPropertyPacket()); // message 1
|
||||
os<<serializeLongString(gob_cmd_update_armor_groups(m_armor_groups)); // 2
|
||||
os<<serializeLongString(gob_cmd_update_animation(m_animation_range, m_animation_speed, m_animation_blend)); // 3
|
||||
for(std::map<std::string, core::vector2d<v3f> >::const_iterator ii = m_bone_position.begin(); ii != m_bone_position.end(); ++ii){
|
||||
os<<serializeLongString(gob_cmd_update_bone_position((*ii).first, (*ii).second.X, (*ii).second.Y)); // m_bone_position.size
|
||||
}
|
||||
os<<serializeLongString(gob_cmd_update_attachment(m_attachment_parent_id, m_attachment_bone, m_attachment_position, m_attachment_rotation)); // 4
|
||||
}
|
||||
else
|
||||
{
|
||||
writeU8(os, 0); // version
|
||||
os<<serializeString(""); // name
|
||||
writeU8(os, 0); // is_player
|
||||
writeV3F1000(os, m_base_position);
|
||||
writeF1000(os, m_yaw);
|
||||
writeS16(os, m_hp);
|
||||
writeU8(os, 2); // number of messages stuffed in here
|
||||
os<<serializeLongString(getPropertyPacket()); // message 1
|
||||
os<<serializeLongString(gob_cmd_update_armor_groups(m_armor_groups)); // 2
|
||||
}
|
||||
os<<serializeLongString(gob_cmd_update_attachment(m_attachment_parent_id, m_attachment_bone, m_attachment_position, m_attachment_rotation)); // 4
|
||||
|
||||
// return result
|
||||
return os.str();
|
||||
|
@ -962,25 +978,41 @@ bool PlayerSAO::unlimitedTransferDistance() const
|
|||
return g_settings->getBool("unlimited_player_transfer_distance");
|
||||
}
|
||||
|
||||
std::string PlayerSAO::getClientInitializationData()
|
||||
std::string PlayerSAO::getClientInitializationData(u16 protocol_version)
|
||||
{
|
||||
std::ostringstream os(std::ios::binary);
|
||||
writeU8(os, 0); // version
|
||||
os<<serializeString(m_player->getName()); // name
|
||||
writeU8(os, 1); // is_player
|
||||
writeS16(os, getId()); //id
|
||||
writeV3F1000(os, m_player->getPosition() + v3f(0,BS*1,0));
|
||||
writeF1000(os, m_player->getYaw());
|
||||
writeS16(os, getHP());
|
||||
|
||||
writeU8(os, 4 + m_bone_position.size()); // number of messages stuffed in here
|
||||
os<<serializeLongString(getPropertyPacket()); // message 1
|
||||
os<<serializeLongString(gob_cmd_update_armor_groups(m_armor_groups)); // 2
|
||||
os<<serializeLongString(gob_cmd_update_animation(m_animation_range, m_animation_speed, m_animation_blend)); // 3
|
||||
for(std::map<std::string, core::vector2d<v3f> >::const_iterator ii = m_bone_position.begin(); ii != m_bone_position.end(); ++ii){
|
||||
os<<serializeLongString(gob_cmd_update_bone_position((*ii).first, (*ii).second.X, (*ii).second.Y)); // m_bone_position.size
|
||||
if(protocol_version >= 15)
|
||||
{
|
||||
writeU8(os, 1); // version
|
||||
os<<serializeString(m_player->getName()); // name
|
||||
writeU8(os, 1); // is_player
|
||||
writeS16(os, getId()); //id
|
||||
writeV3F1000(os, m_player->getPosition() + v3f(0,BS*1,0));
|
||||
writeF1000(os, m_player->getYaw());
|
||||
writeS16(os, getHP());
|
||||
|
||||
writeU8(os, 4 + m_bone_position.size()); // number of messages stuffed in here
|
||||
os<<serializeLongString(getPropertyPacket()); // message 1
|
||||
os<<serializeLongString(gob_cmd_update_armor_groups(m_armor_groups)); // 2
|
||||
os<<serializeLongString(gob_cmd_update_animation(m_animation_range, m_animation_speed, m_animation_blend)); // 3
|
||||
for(std::map<std::string, core::vector2d<v3f> >::const_iterator ii = m_bone_position.begin(); ii != m_bone_position.end(); ++ii){
|
||||
os<<serializeLongString(gob_cmd_update_bone_position((*ii).first, (*ii).second.X, (*ii).second.Y)); // m_bone_position.size
|
||||
}
|
||||
os<<serializeLongString(gob_cmd_update_attachment(m_attachment_parent_id, m_attachment_bone, m_attachment_position, m_attachment_rotation)); // 4
|
||||
}
|
||||
else
|
||||
{
|
||||
writeU8(os, 0); // version
|
||||
os<<serializeString(m_player->getName()); // name
|
||||
writeU8(os, 1); // is_player
|
||||
writeV3F1000(os, m_player->getPosition() + v3f(0,BS*1,0));
|
||||
writeF1000(os, m_player->getYaw());
|
||||
writeS16(os, getHP());
|
||||
writeU8(os, 2); // number of messages stuffed in here
|
||||
os<<serializeLongString(getPropertyPacket()); // message 1
|
||||
os<<serializeLongString(gob_cmd_update_armor_groups(m_armor_groups)); // 2
|
||||
}
|
||||
os<<serializeLongString(gob_cmd_update_attachment(m_attachment_parent_id, m_attachment_bone, m_attachment_position, m_attachment_rotation)); // 4
|
||||
|
||||
// return result
|
||||
return os.str();
|
||||
|
|
|
@ -48,7 +48,7 @@ public:
|
|||
const std::string &data);
|
||||
bool isAttached();
|
||||
void step(float dtime, bool send_recommended);
|
||||
std::string getClientInitializationData();
|
||||
std::string getClientInitializationData(u16 protocol_version);
|
||||
std::string getStaticData();
|
||||
int punch(v3f dir,
|
||||
const ToolCapabilities *toolcap=NULL,
|
||||
|
@ -140,7 +140,7 @@ public:
|
|||
void removingFromEnvironment();
|
||||
bool isStaticAllowed() const;
|
||||
bool unlimitedTransferDistance() const;
|
||||
std::string getClientInitializationData();
|
||||
std::string getClientInitializationData(u16 protocol_version);
|
||||
std::string getStaticData();
|
||||
bool isAttached();
|
||||
void step(float dtime, bool send_recommended);
|
||||
|
|
|
@ -106,12 +106,17 @@ void set_default_settings(Settings *settings)
|
|||
settings->setDefault("sound_volume", "0.8");
|
||||
settings->setDefault("desynchronize_mapblock_texture_animation", "true");
|
||||
|
||||
settings->setDefault("mip_map", "false");
|
||||
settings->setDefault("anisotropic_filter", "false");
|
||||
settings->setDefault("bilinear_filter", "false");
|
||||
settings->setDefault("trilinear_filter", "false");
|
||||
|
||||
// Server stuff
|
||||
// "map-dir" doesn't exist by default.
|
||||
settings->setDefault("default_game", "minetest");
|
||||
settings->setDefault("motd", "");
|
||||
settings->setDefault("max_users", "100");
|
||||
settings->setDefault("strict_protocol_version_checking", "true");
|
||||
settings->setDefault("strict_protocol_version_checking", "false");
|
||||
settings->setDefault("creative_mode", "false");
|
||||
settings->setDefault("enable_damage", "true");
|
||||
settings->setDefault("only_peaceful_mobs", "false");
|
||||
|
@ -140,12 +145,10 @@ void set_default_settings(Settings *settings)
|
|||
settings->setDefault("server_unload_unused_data_timeout", "29");
|
||||
settings->setDefault("server_map_save_interval", "5.3");
|
||||
settings->setDefault("full_block_send_enable_min_time_from_building", "2.0");
|
||||
settings->setDefault("dedicated_server_step", "0.05");
|
||||
settings->setDefault("dedicated_server_step", "0.1");
|
||||
settings->setDefault("ignore_world_load_errors", "false");
|
||||
settings->setDefault("mip_map", "false");
|
||||
settings->setDefault("anisotropic_filter", "false");
|
||||
settings->setDefault("bilinear_filter", "false");
|
||||
settings->setDefault("trilinear_filter", "false");
|
||||
|
||||
settings->setDefault("congestion_control_aim_rtt", "0.2");
|
||||
settings->setDefault("congestion_control_max_rate", "400");
|
||||
settings->setDefault("congestion_control_min_rate", "10");
|
||||
}
|
||||
|
||||
|
|
|
@ -43,6 +43,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||
#endif
|
||||
#include "daynightratio.h"
|
||||
#include "map.h"
|
||||
#include "util/serialize.h"
|
||||
|
||||
#define PP(x) "("<<(x).X<<","<<(x).Y<<","<<(x).Z<<")"
|
||||
|
||||
|
@ -328,7 +329,8 @@ ServerEnvironment::ServerEnvironment(ServerMap *map, lua_State *L,
|
|||
m_send_recommended_timer(0),
|
||||
m_active_block_interval_overload_skip(0),
|
||||
m_game_time(0),
|
||||
m_game_time_fraction_counter(0)
|
||||
m_game_time_fraction_counter(0),
|
||||
m_recommended_send_interval(0.1)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -939,6 +941,11 @@ void ServerEnvironment::step(float dtime)
|
|||
/* Step time of day */
|
||||
stepTimeOfDay(dtime);
|
||||
|
||||
// Update this one
|
||||
// NOTE: This is kind of funny on a singleplayer game, but doesn't
|
||||
// really matter that much.
|
||||
m_recommended_send_interval = g_settings->getFloat("dedicated_server_step");
|
||||
|
||||
/*
|
||||
Increment game time
|
||||
*/
|
||||
|
@ -2296,8 +2303,9 @@ void ClientEnvironment::addActiveObject(u16 id, u8 type,
|
|||
{
|
||||
errorstream<<"ClientEnvironment::addActiveObject():"
|
||||
<<" id="<<id<<" type="<<type
|
||||
<<": SerializationError in initialize(),"
|
||||
<<" init_data="<<serializeJsonString(init_data)
|
||||
<<": SerializationError in initialize(): "
|
||||
<<e.what()
|
||||
<<": init_data="<<serializeJsonString(init_data)
|
||||
<<std::endl;
|
||||
}
|
||||
|
||||
|
|
|
@ -205,9 +205,7 @@ public:
|
|||
{ return m_gamedef; }
|
||||
|
||||
float getSendRecommendedInterval()
|
||||
{
|
||||
return 0.10;
|
||||
}
|
||||
{ return m_recommended_send_interval; }
|
||||
|
||||
/*
|
||||
Save players
|
||||
|
@ -367,6 +365,8 @@ private:
|
|||
// A helper variable for incrementing the latter
|
||||
float m_game_time_fraction_counter;
|
||||
core::list<ABMWithState> m_abms;
|
||||
// An interval for generally sending object positions and stuff
|
||||
float m_recommended_send_interval;
|
||||
};
|
||||
|
||||
#ifndef SERVER
|
||||
|
|
|
@ -1513,7 +1513,7 @@ void the_game(
|
|||
<<"Launching inventory"<<std::endl;
|
||||
|
||||
GUIFormSpecMenu *menu =
|
||||
new GUIFormSpecMenu(guienv, guiroot, -1,
|
||||
new GUIFormSpecMenu(device, guiroot, -1,
|
||||
&g_menumgr,
|
||||
&client, gamedef);
|
||||
|
||||
|
@ -2296,7 +2296,7 @@ void the_game(
|
|||
/* Create menu */
|
||||
|
||||
GUIFormSpecMenu *menu =
|
||||
new GUIFormSpecMenu(guienv, guiroot, -1,
|
||||
new GUIFormSpecMenu(device, guiroot, -1,
|
||||
&g_menumgr,
|
||||
&client, gamedef);
|
||||
menu->setFormSpec(meta->getString("formspec"),
|
||||
|
|
|
@ -92,6 +92,31 @@ std::string gob_cmd_set_sprite(
|
|||
return os.str();
|
||||
}
|
||||
|
||||
std::string gob_cmd_punched(s16 damage, s16 result_hp)
|
||||
{
|
||||
std::ostringstream os(std::ios::binary);
|
||||
// command
|
||||
writeU8(os, GENERIC_CMD_PUNCHED);
|
||||
// damage
|
||||
writeS16(os, damage);
|
||||
// result_hp
|
||||
writeS16(os, result_hp);
|
||||
return os.str();
|
||||
}
|
||||
|
||||
std::string gob_cmd_update_armor_groups(const ItemGroupList &armor_groups)
|
||||
{
|
||||
std::ostringstream os(std::ios::binary);
|
||||
writeU8(os, GENERIC_CMD_UPDATE_ARMOR_GROUPS);
|
||||
writeU16(os, armor_groups.size());
|
||||
for(ItemGroupList::const_iterator i = armor_groups.begin();
|
||||
i != armor_groups.end(); i++){
|
||||
os<<serializeString(i->first);
|
||||
writeS16(os, i->second);
|
||||
}
|
||||
return os.str();
|
||||
}
|
||||
|
||||
std::string gob_cmd_update_animation(v2f frames, float frame_speed, float frame_blend)
|
||||
{
|
||||
std::ostringstream os(std::ios::binary);
|
||||
|
@ -129,29 +154,3 @@ std::string gob_cmd_update_attachment(int parent_id, std::string bone, v3f posit
|
|||
return os.str();
|
||||
}
|
||||
|
||||
std::string gob_cmd_punched(s16 damage, s16 result_hp)
|
||||
{
|
||||
std::ostringstream os(std::ios::binary);
|
||||
// command
|
||||
writeU8(os, GENERIC_CMD_PUNCHED);
|
||||
// damage
|
||||
writeS16(os, damage);
|
||||
// result_hp
|
||||
writeS16(os, result_hp);
|
||||
return os.str();
|
||||
}
|
||||
|
||||
std::string gob_cmd_update_armor_groups(const ItemGroupList &armor_groups)
|
||||
{
|
||||
std::ostringstream os(std::ios::binary);
|
||||
writeU8(os, GENERIC_CMD_UPDATE_ARMOR_GROUPS);
|
||||
writeU16(os, armor_groups.size());
|
||||
for(ItemGroupList::const_iterator i = armor_groups.begin();
|
||||
i != armor_groups.end(); i++){
|
||||
os<<serializeString(i->first);
|
||||
writeS16(os, i->second);
|
||||
}
|
||||
return os.str();
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -28,11 +28,11 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||
#define GENERIC_CMD_UPDATE_POSITION 1
|
||||
#define GENERIC_CMD_SET_TEXTURE_MOD 2
|
||||
#define GENERIC_CMD_SET_SPRITE 3
|
||||
#define GENERIC_CMD_SET_ANIMATION 4
|
||||
#define GENERIC_CMD_SET_BONE_POSITION 5
|
||||
#define GENERIC_CMD_SET_ATTACHMENT 6
|
||||
#define GENERIC_CMD_PUNCHED 7
|
||||
#define GENERIC_CMD_UPDATE_ARMOR_GROUPS 8
|
||||
#define GENERIC_CMD_PUNCHED 4
|
||||
#define GENERIC_CMD_UPDATE_ARMOR_GROUPS 5
|
||||
#define GENERIC_CMD_SET_ANIMATION 6
|
||||
#define GENERIC_CMD_SET_BONE_POSITION 7
|
||||
#define GENERIC_CMD_SET_ATTACHMENT 8
|
||||
|
||||
#include "object_properties.h"
|
||||
std::string gob_cmd_set_properties(const ObjectProperties &prop);
|
||||
|
@ -57,16 +57,16 @@ std::string gob_cmd_set_sprite(
|
|||
bool select_horiz_by_yawpitch
|
||||
);
|
||||
|
||||
std::string gob_cmd_punched(s16 damage, s16 result_hp);
|
||||
|
||||
#include "itemgroup.h"
|
||||
std::string gob_cmd_update_armor_groups(const ItemGroupList &armor_groups);
|
||||
|
||||
std::string gob_cmd_update_animation(v2f frames, float frame_speed, float frame_blend);
|
||||
|
||||
std::string gob_cmd_update_bone_position(std::string bone, v3f position, v3f rotation);
|
||||
|
||||
std::string gob_cmd_update_attachment(int parent_id, std::string bone, v3f position, v3f rotation);
|
||||
|
||||
std::string gob_cmd_punched(s16 damage, s16 result_hp);
|
||||
|
||||
#include "itemgroup.h"
|
||||
std::string gob_cmd_update_armor_groups(const ItemGroupList &armor_groups);
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
@ -125,13 +125,14 @@ void drawItemStack(video::IVideoDriver *driver,
|
|||
GUIFormSpecMenu
|
||||
*/
|
||||
|
||||
GUIFormSpecMenu::GUIFormSpecMenu(gui::IGUIEnvironment* env,
|
||||
GUIFormSpecMenu::GUIFormSpecMenu(irr::IrrlichtDevice* dev,
|
||||
gui::IGUIElement* parent, s32 id,
|
||||
IMenuManager *menumgr,
|
||||
InventoryManager *invmgr,
|
||||
IGameDef *gamedef
|
||||
):
|
||||
GUIModalMenu(env, parent, id, menumgr),
|
||||
GUIModalMenu(dev->getGUIEnvironment(), parent, id, menumgr),
|
||||
m_device(dev),
|
||||
m_invmgr(invmgr),
|
||||
m_gamedef(gamedef),
|
||||
m_form_src(NULL),
|
||||
|
@ -698,6 +699,8 @@ void GUIFormSpecMenu::drawMenu()
|
|||
}
|
||||
}
|
||||
|
||||
m_pointer = m_device->getCursorControl()->getPosition();
|
||||
|
||||
updateSelectedItem();
|
||||
|
||||
gui::IGUISkin* skin = Environment->getSkin();
|
||||
|
@ -937,24 +940,15 @@ bool GUIFormSpecMenu::OnEvent(const SEvent& event)
|
|||
return true;
|
||||
}
|
||||
}
|
||||
if(event.EventType==EET_MOUSE_INPUT_EVENT
|
||||
&& event.MouseInput.Event == EMIE_MOUSE_MOVED)
|
||||
{
|
||||
// Mouse moved
|
||||
m_pointer = v2s32(event.MouseInput.X, event.MouseInput.Y);
|
||||
}
|
||||
if(event.EventType==EET_MOUSE_INPUT_EVENT
|
||||
&& event.MouseInput.Event != EMIE_MOUSE_MOVED)
|
||||
{
|
||||
// Mouse event other than movement
|
||||
|
||||
v2s32 p(event.MouseInput.X, event.MouseInput.Y);
|
||||
m_pointer = p;
|
||||
|
||||
// Get selected item and hovered/clicked item (s)
|
||||
|
||||
updateSelectedItem();
|
||||
ItemSpec s = getItemAtPos(p);
|
||||
ItemSpec s = getItemAtPos(m_pointer);
|
||||
|
||||
Inventory *inv_selected = NULL;
|
||||
Inventory *inv_s = NULL;
|
||||
|
|
|
@ -144,7 +144,7 @@ class GUIFormSpecMenu : public GUIModalMenu
|
|||
};
|
||||
|
||||
public:
|
||||
GUIFormSpecMenu(gui::IGUIEnvironment* env,
|
||||
GUIFormSpecMenu(irr::IrrlichtDevice* dev,
|
||||
gui::IGUIElement* parent, s32 id,
|
||||
IMenuManager *menumgr,
|
||||
InventoryManager *invmgr,
|
||||
|
@ -197,6 +197,7 @@ protected:
|
|||
v2s32 spacing;
|
||||
v2s32 imgsize;
|
||||
|
||||
irr::IrrlichtDevice* m_device;
|
||||
InventoryManager *m_invmgr;
|
||||
IGameDef *m_gamedef;
|
||||
|
||||
|
|
|
@ -323,7 +323,7 @@ void LocalPlayer::move(f32 dtime, Map &map, f32 pos_max_d,
|
|||
v3s16 camera_np = floatToInt(getEyePosition(), BS);
|
||||
MapNode n = map.getNodeNoEx(camera_np);
|
||||
if(n.getContent() != CONTENT_IGNORE){
|
||||
if(nodemgr->get(n).walkable){
|
||||
if(nodemgr->get(n).walkable && nodemgr->get(n).solidness == 2){
|
||||
camera_barely_in_ceiling = true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -35,6 +35,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||
#include "mapblock_mesh.h"
|
||||
#endif
|
||||
#include "util/string.h"
|
||||
#include "util/serialize.h"
|
||||
|
||||
#define PP(x) "("<<(x).X<<","<<(x).Y<<","<<(x).Z<<")"
|
||||
|
||||
|
|
|
@ -77,9 +77,9 @@ void MeshMakeData::fill(MapBlock *block)
|
|||
// Get map
|
||||
Map *map = block->getParent();
|
||||
|
||||
for(u16 i=0; i<6; i++)
|
||||
for(u16 i=0; i<26; i++)
|
||||
{
|
||||
const v3s16 &dir = g_6dirs[i];
|
||||
const v3s16 &dir = g_26dirs[i];
|
||||
v3s16 bp = m_blockpos + dir;
|
||||
MapBlock *b = map->getBlockNoCreateNoEx(bp);
|
||||
if(b)
|
||||
|
|
|
@ -39,6 +39,10 @@ static void collectMods(const std::string &modspath,
|
|||
if(!dirlist[j].dir)
|
||||
continue;
|
||||
std::string modname = dirlist[j].name;
|
||||
// Ignore all directories beginning with a ".", especially
|
||||
// VCS directories like ".git" or ".svn"
|
||||
if(modname[0] == '.')
|
||||
continue;
|
||||
std::string modpath = modspath + DIR_DELIM + modname;
|
||||
TRACESTREAM(<<indentation<<"collectMods: "<<modname<<" at \""<<modpath<<"\""<<std::endl);
|
||||
// Handle modpacks (defined by containing modpack.txt)
|
||||
|
|
137
src/nodedef.cpp
137
src/nodedef.cpp
|
@ -215,8 +215,13 @@ void ContentFeatures::reset()
|
|||
sound_dug = SimpleSoundSpec();
|
||||
}
|
||||
|
||||
void ContentFeatures::serialize(std::ostream &os)
|
||||
void ContentFeatures::serialize(std::ostream &os, u16 protocol_version)
|
||||
{
|
||||
if(protocol_version < 14){
|
||||
serializeOld(os, protocol_version);
|
||||
return;
|
||||
}
|
||||
|
||||
writeU8(os, 6); // version
|
||||
os<<serializeString(name);
|
||||
writeU16(os, groups.size());
|
||||
|
@ -271,8 +276,11 @@ void ContentFeatures::serialize(std::ostream &os)
|
|||
void ContentFeatures::deSerialize(std::istream &is)
|
||||
{
|
||||
int version = readU8(is);
|
||||
if(version != 6)
|
||||
throw SerializationError("unsupported ContentFeatures version");
|
||||
if(version != 6){
|
||||
deSerializeOld(is, version);
|
||||
return;
|
||||
}
|
||||
|
||||
name = deSerializeString(is);
|
||||
groups.clear();
|
||||
u32 groups_size = readU16(is);
|
||||
|
@ -693,7 +701,7 @@ public:
|
|||
}
|
||||
#endif
|
||||
}
|
||||
void serialize(std::ostream &os)
|
||||
void serialize(std::ostream &os, u16 protocol_version)
|
||||
{
|
||||
writeU8(os, 1); // version
|
||||
u16 count = 0;
|
||||
|
@ -709,7 +717,7 @@ public:
|
|||
// Wrap it in a string to allow different lengths without
|
||||
// strict version incompatibilities
|
||||
std::ostringstream wrapper_os(std::ios::binary);
|
||||
f->serialize(wrapper_os);
|
||||
f->serialize(wrapper_os, protocol_version);
|
||||
os2<<serializeString(wrapper_os.str());
|
||||
count++;
|
||||
}
|
||||
|
@ -766,3 +774,122 @@ IWritableNodeDefManager* createNodeDefManager()
|
|||
return new CNodeDefManager();
|
||||
}
|
||||
|
||||
/*
|
||||
Serialization of old ContentFeatures formats
|
||||
*/
|
||||
|
||||
void ContentFeatures::serializeOld(std::ostream &os, u16 protocol_version)
|
||||
{
|
||||
if(protocol_version == 13)
|
||||
{
|
||||
writeU8(os, 5); // 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, visual_scale);
|
||||
writeU8(os, 6);
|
||||
for(u32 i=0; i<6; i++)
|
||||
tiledef[i].serialize(os);
|
||||
writeU8(os, CF_SPECIAL_COUNT);
|
||||
for(u32 i=0; i<CF_SPECIAL_COUNT; i++){
|
||||
tiledef_special[i].serialize(os);
|
||||
}
|
||||
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, 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, light_source);
|
||||
writeU32(os, damage_per_second);
|
||||
node_box.serialize(os);
|
||||
selection_box.serialize(os);
|
||||
writeU8(os, legacy_facedir_simple);
|
||||
writeU8(os, legacy_wallmounted);
|
||||
serializeSimpleSoundSpec(sound_footstep, os);
|
||||
serializeSimpleSoundSpec(sound_dig, os);
|
||||
serializeSimpleSoundSpec(sound_dug, os);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw SerializationError("ContentFeatures::serialize(): Unsupported version requested");
|
||||
}
|
||||
}
|
||||
|
||||
void ContentFeatures::deSerializeOld(std::istream &is, int version)
|
||||
{
|
||||
if(version == 5) // In PROTOCOL_VERSION 13
|
||||
{
|
||||
name = deSerializeString(is);
|
||||
groups.clear();
|
||||
u32 groups_size = readU16(is);
|
||||
for(u32 i=0; i<groups_size; i++){
|
||||
std::string name = deSerializeString(is);
|
||||
int value = readS16(is);
|
||||
groups[name] = value;
|
||||
}
|
||||
drawtype = (enum NodeDrawType)readU8(is);
|
||||
visual_scale = readF1000(is);
|
||||
if(readU8(is) != 6)
|
||||
throw SerializationError("unsupported tile count");
|
||||
for(u32 i=0; i<6; i++)
|
||||
tiledef[i].deSerialize(is);
|
||||
if(readU8(is) != CF_SPECIAL_COUNT)
|
||||
throw SerializationError("unsupported CF_SPECIAL_COUNT");
|
||||
for(u32 i=0; i<CF_SPECIAL_COUNT; i++)
|
||||
tiledef_special[i].deSerialize(is);
|
||||
alpha = readU8(is);
|
||||
post_effect_color.setAlpha(readU8(is));
|
||||
post_effect_color.setRed(readU8(is));
|
||||
post_effect_color.setGreen(readU8(is));
|
||||
post_effect_color.setBlue(readU8(is));
|
||||
param_type = (enum ContentParamType)readU8(is);
|
||||
param_type_2 = (enum ContentParamType2)readU8(is);
|
||||
is_ground_content = readU8(is);
|
||||
light_propagates = readU8(is);
|
||||
sunlight_propagates = readU8(is);
|
||||
walkable = readU8(is);
|
||||
pointable = readU8(is);
|
||||
diggable = readU8(is);
|
||||
climbable = readU8(is);
|
||||
buildable_to = readU8(is);
|
||||
deSerializeString(is); // legacy: used to be metadata_name
|
||||
liquid_type = (enum LiquidType)readU8(is);
|
||||
liquid_alternative_flowing = deSerializeString(is);
|
||||
liquid_alternative_source = deSerializeString(is);
|
||||
liquid_viscosity = readU8(is);
|
||||
light_source = readU8(is);
|
||||
damage_per_second = readU32(is);
|
||||
node_box.deSerialize(is);
|
||||
selection_box.deSerialize(is);
|
||||
legacy_facedir_simple = readU8(is);
|
||||
legacy_wallmounted = readU8(is);
|
||||
deSerializeSimpleSoundSpec(sound_footstep, is);
|
||||
deSerializeSimpleSoundSpec(sound_dig, is);
|
||||
deSerializeSimpleSoundSpec(sound_dug, is);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw SerializationError("unsupported ContentFeatures version");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -234,8 +234,10 @@ struct ContentFeatures
|
|||
ContentFeatures();
|
||||
~ContentFeatures();
|
||||
void reset();
|
||||
void serialize(std::ostream &os);
|
||||
void serialize(std::ostream &os, u16 protocol_version);
|
||||
void deSerialize(std::istream &is);
|
||||
void serializeOld(std::ostream &os, u16 protocol_version);
|
||||
void deSerializeOld(std::istream &is, int version);
|
||||
|
||||
/*
|
||||
Some handy methods
|
||||
|
@ -264,7 +266,7 @@ public:
|
|||
const=0;
|
||||
virtual const ContentFeatures& get(const std::string &name) const=0;
|
||||
|
||||
virtual void serialize(std::ostream &os)=0;
|
||||
virtual void serialize(std::ostream &os, u16 protocol_version)=0;
|
||||
};
|
||||
|
||||
class IWritableNodeDefManager : public INodeDefManager
|
||||
|
@ -305,7 +307,7 @@ public:
|
|||
*/
|
||||
virtual void updateTextures(ITextureSource *tsrc)=0;
|
||||
|
||||
virtual void serialize(std::ostream &os)=0;
|
||||
virtual void serialize(std::ostream &os, u16 protocol_version)=0;
|
||||
virtual void deSerialize(std::istream &is)=0;
|
||||
};
|
||||
|
||||
|
|
|
@ -81,52 +81,59 @@ void ObjectProperties::serialize(std::ostream &os) const
|
|||
writeV3F1000(os, collisionbox.MinEdge);
|
||||
writeV3F1000(os, collisionbox.MaxEdge);
|
||||
os<<serializeString(visual);
|
||||
os<<serializeString(mesh);
|
||||
writeV2F1000(os, visual_size);
|
||||
writeU16(os, textures.size());
|
||||
for(u32 i=0; i<textures.size(); i++){
|
||||
os<<serializeString(textures[i]);
|
||||
}
|
||||
writeU16(os, colors.size());
|
||||
for(u32 i=0; i<colors.size(); i++){
|
||||
writeARGB8(os, colors[i]);
|
||||
}
|
||||
writeV2S16(os, spritediv);
|
||||
writeV2S16(os, initial_sprite_basepos);
|
||||
writeU8(os, is_visible);
|
||||
writeU8(os, makes_footstep_sound);
|
||||
writeF1000(os, automatic_rotate);
|
||||
// Added in protocol version 14
|
||||
os<<serializeString(mesh);
|
||||
writeU16(os, colors.size());
|
||||
for(u32 i=0; i<colors.size(); i++){
|
||||
writeARGB8(os, colors[i]);
|
||||
}
|
||||
// Add stuff only at the bottom.
|
||||
// Never remove anything, because we don't want new versions of this
|
||||
}
|
||||
|
||||
void ObjectProperties::deSerialize(std::istream &is)
|
||||
{
|
||||
int version = readU8(is);
|
||||
if(version != 1) throw SerializationError(
|
||||
"unsupported ObjectProperties version");
|
||||
hp_max = readS16(is);
|
||||
physical = readU8(is);
|
||||
weight = readF1000(is);
|
||||
collisionbox.MinEdge = readV3F1000(is);
|
||||
collisionbox.MaxEdge = readV3F1000(is);
|
||||
visual = deSerializeString(is);
|
||||
mesh = deSerializeString(is);
|
||||
visual_size = readV2F1000(is);
|
||||
textures.clear();
|
||||
u32 texture_count = readU16(is);
|
||||
for(u32 i=0; i<texture_count; i++){
|
||||
textures.push_back(deSerializeString(is));
|
||||
if(version == 1)
|
||||
{
|
||||
try{
|
||||
hp_max = readS16(is);
|
||||
physical = readU8(is);
|
||||
weight = readF1000(is);
|
||||
collisionbox.MinEdge = readV3F1000(is);
|
||||
collisionbox.MaxEdge = readV3F1000(is);
|
||||
visual = deSerializeString(is);
|
||||
visual_size = readV2F1000(is);
|
||||
textures.clear();
|
||||
u32 texture_count = readU16(is);
|
||||
for(u32 i=0; i<texture_count; i++){
|
||||
textures.push_back(deSerializeString(is));
|
||||
}
|
||||
spritediv = readV2S16(is);
|
||||
initial_sprite_basepos = readV2S16(is);
|
||||
is_visible = readU8(is);
|
||||
makes_footstep_sound = readU8(is);
|
||||
automatic_rotate = readF1000(is);
|
||||
mesh = deSerializeString(is);
|
||||
u32 color_count = readU16(is);
|
||||
for(u32 i=0; i<color_count; i++){
|
||||
colors.push_back(readARGB8(is));
|
||||
}
|
||||
}catch(SerializationError &e){}
|
||||
}
|
||||
u32 color_count = readU16(is);
|
||||
for(u32 i=0; i<color_count; i++){
|
||||
colors.push_back(readARGB8(is));
|
||||
else
|
||||
{
|
||||
throw SerializationError("unsupported ObjectProperties version");
|
||||
}
|
||||
spritediv = readV2S16(is);
|
||||
initial_sprite_basepos = readV2S16(is);
|
||||
is_visible = readU8(is);
|
||||
makes_footstep_sound = readU8(is);
|
||||
try{
|
||||
automatic_rotate = readF1000(is);
|
||||
}catch(SerializationError &e){}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -5576,6 +5576,19 @@ bool scriptapi_on_chat_message(lua_State *L, const std::string &name,
|
|||
return ate;
|
||||
}
|
||||
|
||||
void scriptapi_on_shutdown(lua_State *L)
|
||||
{
|
||||
realitycheck(L);
|
||||
assert(lua_checkstack(L, 20));
|
||||
StackUnroller stack_unroller(L);
|
||||
|
||||
// Get registered shutdown hooks
|
||||
lua_getglobal(L, "minetest");
|
||||
lua_getfield(L, -1, "registered_on_shutdown");
|
||||
// Call callbacks
|
||||
scriptapi_run_callbacks(L, 0, RUN_CALLBACKS_MODE_FIRST);
|
||||
}
|
||||
|
||||
void scriptapi_on_newplayer(lua_State *L, ServerActiveObject *player)
|
||||
{
|
||||
realitycheck(L);
|
||||
|
|
|
@ -55,6 +55,9 @@ void scriptapi_environment_step(lua_State *L, float dtime);
|
|||
void scriptapi_environment_on_generated(lua_State *L, v3s16 minp, v3s16 maxp,
|
||||
u32 blockseed);
|
||||
|
||||
/* server */
|
||||
void scriptapi_on_shutdown(lua_State *L);
|
||||
|
||||
/* misc */
|
||||
void scriptapi_on_newplayer(lua_State *L, ServerActiveObject *player);
|
||||
void scriptapi_on_dieplayer(lua_State *L, ServerActiveObject *player);
|
||||
|
|
104
src/server.cpp
104
src/server.cpp
|
@ -54,6 +54,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||
#include "util/pointedthing.h"
|
||||
#include "util/mathconstants.h"
|
||||
#include "rollback.h"
|
||||
#include "util/serialize.h"
|
||||
|
||||
#define PP(x) "("<<(x).X<<","<<(x).Y<<","<<(x).Z<<")"
|
||||
|
||||
|
@ -1111,7 +1112,17 @@ Server::~Server()
|
|||
{}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
{
|
||||
JMutexAutoLock envlock(m_env_mutex);
|
||||
JMutexAutoLock conlock(m_con_mutex);
|
||||
|
||||
/*
|
||||
Execute script shutdown hooks
|
||||
*/
|
||||
scriptapi_on_shutdown(m_lua);
|
||||
}
|
||||
|
||||
{
|
||||
JMutexAutoLock envlock(m_env_mutex);
|
||||
|
||||
|
@ -1143,14 +1154,6 @@ Server::~Server()
|
|||
i = m_clients.getIterator();
|
||||
i.atEnd() == false; i++)
|
||||
{
|
||||
/*// Delete player
|
||||
// NOTE: These are removed by env destructor
|
||||
{
|
||||
u16 peer_id = i.getNode()->getKey();
|
||||
JMutexAutoLock envlock(m_env_mutex);
|
||||
m_env->removePlayer(peer_id);
|
||||
}*/
|
||||
|
||||
// Delete client
|
||||
delete i.getNode()->getValue();
|
||||
}
|
||||
|
@ -1567,7 +1570,7 @@ void Server::AsyncRunStep()
|
|||
|
||||
if(obj)
|
||||
data_buffer.append(serializeLongString(
|
||||
obj->getClientInitializationData()));
|
||||
obj->getClientInitializationData(client->net_proto_version)));
|
||||
else
|
||||
data_buffer.append(serializeLongString(""));
|
||||
|
||||
|
@ -2037,40 +2040,74 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
|
|||
Read and check network protocol version
|
||||
*/
|
||||
|
||||
u16 net_proto_version = 0;
|
||||
u16 min_net_proto_version = 0;
|
||||
if(datasize >= 2+1+PLAYERNAME_SIZE+PASSWORD_SIZE+2)
|
||||
min_net_proto_version = readU16(&data[2+1+PLAYERNAME_SIZE+PASSWORD_SIZE]);
|
||||
|
||||
// Use same version as minimum and maximum if maximum version field
|
||||
// doesn't exist (backwards compatibility)
|
||||
u16 max_net_proto_version = min_net_proto_version;
|
||||
if(datasize >= 2+1+PLAYERNAME_SIZE+PASSWORD_SIZE+2+2)
|
||||
max_net_proto_version = readU16(&data[2+1+PLAYERNAME_SIZE+PASSWORD_SIZE+2]);
|
||||
|
||||
// Start with client's maximum version
|
||||
u16 net_proto_version = max_net_proto_version;
|
||||
|
||||
// Figure out a working version if it is possible at all
|
||||
if(max_net_proto_version >= SERVER_PROTOCOL_VERSION_MIN ||
|
||||
min_net_proto_version <= SERVER_PROTOCOL_VERSION_MAX)
|
||||
{
|
||||
net_proto_version = readU16(&data[2+1+PLAYERNAME_SIZE+PASSWORD_SIZE]);
|
||||
// If maximum is larger than our maximum, go with our maximum
|
||||
if(max_net_proto_version > SERVER_PROTOCOL_VERSION_MAX)
|
||||
net_proto_version = SERVER_PROTOCOL_VERSION_MAX;
|
||||
// Else go with client's maximum
|
||||
else
|
||||
net_proto_version = max_net_proto_version;
|
||||
}
|
||||
|
||||
verbosestream<<"Server: "<<peer_id<<" Protocol version: min: "
|
||||
<<min_net_proto_version<<", max: "<<max_net_proto_version
|
||||
<<", chosen: "<<net_proto_version<<std::endl;
|
||||
|
||||
getClient(peer_id)->net_proto_version = net_proto_version;
|
||||
|
||||
if(net_proto_version == 0)
|
||||
if(net_proto_version < SERVER_PROTOCOL_VERSION_MIN ||
|
||||
net_proto_version > SERVER_PROTOCOL_VERSION_MAX)
|
||||
{
|
||||
actionstream<<"Server: An old tried to connect from "<<addr_s
|
||||
actionstream<<"Server: A mismatched client tried to connect from "<<addr_s
|
||||
<<std::endl;
|
||||
SendAccessDenied(m_con, peer_id, std::wstring(
|
||||
L"Your client's version is not supported.\n"
|
||||
L"Server version is ")
|
||||
+ narrow_to_wide(VERSION_STRING) + L"."
|
||||
+ narrow_to_wide(VERSION_STRING) + L",\n"
|
||||
+ L"server's PROTOCOL_VERSION is "
|
||||
+ narrow_to_wide(itos(SERVER_PROTOCOL_VERSION_MIN))
|
||||
+ L"..."
|
||||
+ narrow_to_wide(itos(SERVER_PROTOCOL_VERSION_MAX))
|
||||
+ L", client's PROTOCOL_VERSION is "
|
||||
+ narrow_to_wide(itos(min_net_proto_version))
|
||||
+ L"..."
|
||||
+ narrow_to_wide(itos(max_net_proto_version))
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
if(g_settings->getBool("strict_protocol_version_checking"))
|
||||
{
|
||||
if(net_proto_version != PROTOCOL_VERSION)
|
||||
if(net_proto_version != LATEST_PROTOCOL_VERSION)
|
||||
{
|
||||
actionstream<<"Server: A mismatched client tried to connect"
|
||||
<<" from "<<addr_s<<std::endl;
|
||||
actionstream<<"Server: A mismatched (strict) client tried to "
|
||||
<<"connect from "<<addr_s<<std::endl;
|
||||
SendAccessDenied(m_con, peer_id, std::wstring(
|
||||
L"Your client's version is not supported.\n"
|
||||
L"Server version is ")
|
||||
+ narrow_to_wide(VERSION_STRING) + L",\n"
|
||||
+ L"server's PROTOCOL_VERSION is "
|
||||
+ narrow_to_wide(itos(PROTOCOL_VERSION))
|
||||
+ L"server's PROTOCOL_VERSION (strict) is "
|
||||
+ narrow_to_wide(itos(LATEST_PROTOCOL_VERSION))
|
||||
+ L", client's PROTOCOL_VERSION is "
|
||||
+ narrow_to_wide(itos(net_proto_version))
|
||||
+ narrow_to_wide(itos(min_net_proto_version))
|
||||
+ L"..."
|
||||
+ narrow_to_wide(itos(max_net_proto_version))
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
@ -2212,11 +2249,12 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
|
|||
Answer with a TOCLIENT_INIT
|
||||
*/
|
||||
{
|
||||
SharedBuffer<u8> reply(2+1+6+8);
|
||||
SharedBuffer<u8> reply(2+1+6+8+4);
|
||||
writeU16(&reply[0], TOCLIENT_INIT);
|
||||
writeU8(&reply[2], deployed);
|
||||
writeV3S16(&reply[2+1], floatToInt(playersao->getPlayer()->getPosition()+v3f(0,BS/2,0), BS));
|
||||
writeU64(&reply[2+1+6], m_env->getServerMap().getSeed());
|
||||
writeF1000(&reply[2+1+6+8], g_settings->getFloat("dedicated_server_step"));
|
||||
|
||||
// Send as reliable
|
||||
m_con.Send(peer_id, 0, reply, true);
|
||||
|
@ -2242,8 +2280,9 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
|
|||
return;
|
||||
}
|
||||
|
||||
getClient(peer_id)->serialization_version
|
||||
= getClient(peer_id)->pending_serialization_version;
|
||||
RemoteClient *client = getClient(peer_id);
|
||||
client->serialization_version =
|
||||
getClient(peer_id)->pending_serialization_version;
|
||||
|
||||
/*
|
||||
Send some initialization data
|
||||
|
@ -2256,7 +2295,7 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
|
|||
SendItemDef(m_con, peer_id, m_itemdef);
|
||||
|
||||
// Send node definitions
|
||||
SendNodeDef(m_con, peer_id, m_nodedef);
|
||||
SendNodeDef(m_con, peer_id, m_nodedef, client->net_proto_version);
|
||||
|
||||
// Send media announcement
|
||||
sendMediaAnnouncement(peer_id);
|
||||
|
@ -2310,9 +2349,10 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
|
|||
}
|
||||
|
||||
// Warnings about protocol version can be issued here
|
||||
if(getClient(peer_id)->net_proto_version < PROTOCOL_VERSION)
|
||||
if(getClient(peer_id)->net_proto_version < LATEST_PROTOCOL_VERSION)
|
||||
{
|
||||
SendChatMessage(peer_id, L"# Server: WARNING: YOUR CLIENT IS OLD AND MAY WORK PROPERLY WITH THIS SERVER!");
|
||||
SendChatMessage(peer_id, L"# Server: WARNING: YOUR CLIENT'S "
|
||||
L"VERSION MAY NOT BE FULLY COMPATIBLE WITH THIS SERVER!");
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -2369,7 +2409,7 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
|
|||
|
||||
if(command == TOSERVER_PLAYERPOS)
|
||||
{
|
||||
if(datasize < 2+12+12+4+4+4)
|
||||
if(datasize < 2+12+12+4+4)
|
||||
return;
|
||||
|
||||
u32 start = 0;
|
||||
|
@ -2377,7 +2417,9 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
|
|||
v3s32 ss = readV3S32(&data[start+2+12]);
|
||||
f32 pitch = (f32)readS32(&data[2+12+12]) / 100.0;
|
||||
f32 yaw = (f32)readS32(&data[2+12+12+4]) / 100.0;
|
||||
u32 keyPressed = (u32)readU32(&data[2+12+12+4+4]);
|
||||
u32 keyPressed = 0;
|
||||
if(datasize >= 2+12+12+4+4+4)
|
||||
keyPressed = (u32)readU32(&data[2+12+12+4+4]);
|
||||
v3f position((f32)ps.X/100., (f32)ps.Y/100., (f32)ps.Z/100.);
|
||||
v3f speed((f32)ss.X/100., (f32)ss.Y/100., (f32)ss.Z/100.);
|
||||
pitch = wrapDegrees(pitch);
|
||||
|
@ -3508,7 +3550,7 @@ void Server::SendItemDef(con::Connection &con, u16 peer_id,
|
|||
}
|
||||
|
||||
void Server::SendNodeDef(con::Connection &con, u16 peer_id,
|
||||
INodeDefManager *nodedef)
|
||||
INodeDefManager *nodedef, u16 protocol_version)
|
||||
{
|
||||
DSTACK(__FUNCTION_NAME);
|
||||
std::ostringstream os(std::ios_base::binary);
|
||||
|
@ -3520,7 +3562,7 @@ void Server::SendNodeDef(con::Connection &con, u16 peer_id,
|
|||
*/
|
||||
writeU16(os, TOCLIENT_NODEDEF);
|
||||
std::ostringstream tmp_os(std::ios::binary);
|
||||
nodedef->serialize(tmp_os);
|
||||
nodedef->serialize(tmp_os, protocol_version);
|
||||
std::ostringstream tmp_os2(std::ios::binary);
|
||||
compressZlib(tmp_os.str(), tmp_os2);
|
||||
os<<serializeLongString(tmp_os2.str());
|
||||
|
|
|
@ -602,7 +602,7 @@ private:
|
|||
static void SendItemDef(con::Connection &con, u16 peer_id,
|
||||
IItemDefManager *itemdef);
|
||||
static void SendNodeDef(con::Connection &con, u16 peer_id,
|
||||
INodeDefManager *nodedef);
|
||||
INodeDefManager *nodedef, u16 protocol_version);
|
||||
|
||||
/*
|
||||
Non-static send methods.
|
||||
|
|
|
@ -118,7 +118,7 @@ public:
|
|||
The return value of this is passed to the client-side object
|
||||
when it is created
|
||||
*/
|
||||
virtual std::string getClientInitializationData(){return "";}
|
||||
virtual std::string getClientInitializationData(u16 protocol_version){return "";}
|
||||
|
||||
/*
|
||||
The return value of this is passed to the server-side object
|
||||
|
|
|
@ -0,0 +1,92 @@
|
|||
/*
|
||||
Minetest-c55
|
||||
Copyright (C) 2010-2012 celeron55, Perttu Ahola <celeron55@gmail.com>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include "staticobject.h"
|
||||
#include "util/serialize.h"
|
||||
|
||||
void StaticObject::serialize(std::ostream &os)
|
||||
{
|
||||
char buf[12];
|
||||
// type
|
||||
buf[0] = type;
|
||||
os.write(buf, 1);
|
||||
// pos
|
||||
writeV3S32((u8*)buf, v3s32(pos.X*1000,pos.Y*1000,pos.Z*1000));
|
||||
os.write(buf, 12);
|
||||
// data
|
||||
os<<serializeString(data);
|
||||
}
|
||||
void StaticObject::deSerialize(std::istream &is, u8 version)
|
||||
{
|
||||
char buf[12];
|
||||
// type
|
||||
is.read(buf, 1);
|
||||
type = buf[0];
|
||||
// pos
|
||||
is.read(buf, 12);
|
||||
v3s32 intp = readV3S32((u8*)buf);
|
||||
pos.X = (f32)intp.X/1000;
|
||||
pos.Y = (f32)intp.Y/1000;
|
||||
pos.Z = (f32)intp.Z/1000;
|
||||
// data
|
||||
data = deSerializeString(is);
|
||||
}
|
||||
|
||||
void StaticObjectList::serialize(std::ostream &os)
|
||||
{
|
||||
char buf[12];
|
||||
// version
|
||||
buf[0] = 0;
|
||||
os.write(buf, 1);
|
||||
// count
|
||||
u16 count = m_stored.size() + m_active.size();
|
||||
writeU16((u8*)buf, count);
|
||||
os.write(buf, 2);
|
||||
for(core::list<StaticObject>::Iterator
|
||||
i = m_stored.begin();
|
||||
i != m_stored.end(); i++)
|
||||
{
|
||||
StaticObject &s_obj = *i;
|
||||
s_obj.serialize(os);
|
||||
}
|
||||
for(core::map<u16, StaticObject>::Iterator
|
||||
i = m_active.getIterator();
|
||||
i.atEnd()==false; i++)
|
||||
{
|
||||
StaticObject s_obj = i.getNode()->getValue();
|
||||
s_obj.serialize(os);
|
||||
}
|
||||
}
|
||||
void StaticObjectList::deSerialize(std::istream &is)
|
||||
{
|
||||
char buf[12];
|
||||
// version
|
||||
is.read(buf, 1);
|
||||
u8 version = buf[0];
|
||||
// count
|
||||
is.read(buf, 2);
|
||||
u16 count = readU16((u8*)buf);
|
||||
for(u16 i=0; i<count; i++)
|
||||
{
|
||||
StaticObject s_obj;
|
||||
s_obj.deSerialize(is, version);
|
||||
m_stored.push_back(s_obj);
|
||||
}
|
||||
}
|
||||
|
|
@ -23,7 +23,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||
#include "irrlichttypes_bloated.h"
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
#include "util/serialize.h"
|
||||
#include "debug.h"
|
||||
|
||||
struct StaticObject
|
||||
{
|
||||
|
@ -43,33 +43,8 @@ struct StaticObject
|
|||
{
|
||||
}
|
||||
|
||||
void serialize(std::ostream &os)
|
||||
{
|
||||
char buf[12];
|
||||
// type
|
||||
buf[0] = type;
|
||||
os.write(buf, 1);
|
||||
// pos
|
||||
writeV3S32((u8*)buf, v3s32(pos.X*1000,pos.Y*1000,pos.Z*1000));
|
||||
os.write(buf, 12);
|
||||
// data
|
||||
os<<serializeString(data);
|
||||
}
|
||||
void deSerialize(std::istream &is, u8 version)
|
||||
{
|
||||
char buf[12];
|
||||
// type
|
||||
is.read(buf, 1);
|
||||
type = buf[0];
|
||||
// pos
|
||||
is.read(buf, 12);
|
||||
v3s32 intp = readV3S32((u8*)buf);
|
||||
pos.X = (f32)intp.X/1000;
|
||||
pos.Y = (f32)intp.Y/1000;
|
||||
pos.Z = (f32)intp.Z/1000;
|
||||
// data
|
||||
data = deSerializeString(is);
|
||||
}
|
||||
void serialize(std::ostream &os);
|
||||
void deSerialize(std::istream &is, u8 version);
|
||||
};
|
||||
|
||||
class StaticObjectList
|
||||
|
@ -110,47 +85,8 @@ public:
|
|||
m_active.remove(id);
|
||||
}
|
||||
|
||||
void serialize(std::ostream &os)
|
||||
{
|
||||
char buf[12];
|
||||
// version
|
||||
buf[0] = 0;
|
||||
os.write(buf, 1);
|
||||
// count
|
||||
u16 count = m_stored.size() + m_active.size();
|
||||
writeU16((u8*)buf, count);
|
||||
os.write(buf, 2);
|
||||
for(core::list<StaticObject>::Iterator
|
||||
i = m_stored.begin();
|
||||
i != m_stored.end(); i++)
|
||||
{
|
||||
StaticObject &s_obj = *i;
|
||||
s_obj.serialize(os);
|
||||
}
|
||||
for(core::map<u16, StaticObject>::Iterator
|
||||
i = m_active.getIterator();
|
||||
i.atEnd()==false; i++)
|
||||
{
|
||||
StaticObject s_obj = i.getNode()->getValue();
|
||||
s_obj.serialize(os);
|
||||
}
|
||||
}
|
||||
void deSerialize(std::istream &is)
|
||||
{
|
||||
char buf[12];
|
||||
// version
|
||||
is.read(buf, 1);
|
||||
u8 version = buf[0];
|
||||
// count
|
||||
is.read(buf, 2);
|
||||
u16 count = readU16((u8*)buf);
|
||||
for(u16 i=0; i<count; i++)
|
||||
{
|
||||
StaticObject s_obj;
|
||||
s_obj.deSerialize(is, version);
|
||||
m_stored.push_back(s_obj);
|
||||
}
|
||||
}
|
||||
void serialize(std::ostream &os);
|
||||
void deSerialize(std::istream &is);
|
||||
|
||||
/*
|
||||
NOTE: When an object is transformed to active, it is removed
|
||||
|
|
22
src/test.cpp
22
src/test.cpp
|
@ -41,6 +41,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||
#include "util/numeric.h"
|
||||
#include "util/serialize.h"
|
||||
#include "noise.h" // PseudoRandom used for random data for compression
|
||||
#include "clientserver.h" // LATEST_PROTOCOL_VERSION
|
||||
|
||||
/*
|
||||
Asserts that the exception occurs
|
||||
|
@ -314,6 +315,26 @@ struct TestSerialization: public TestBase
|
|||
}
|
||||
};
|
||||
|
||||
struct TestNodedefSerialization: public TestBase
|
||||
{
|
||||
void Run()
|
||||
{
|
||||
ContentFeatures f;
|
||||
f.name = "default:stone";
|
||||
for(int i = 0; i < 6; i++)
|
||||
f.tiledef[i].name = "default_stone.png";
|
||||
f.is_ground_content = true;
|
||||
std::ostringstream os(std::ios::binary);
|
||||
f.serialize(os, LATEST_PROTOCOL_VERSION);
|
||||
verbosestream<<"Test ContentFeatures size: "<<os.str().size()<<std::endl;
|
||||
std::istringstream is(os.str(), std::ios::binary);
|
||||
ContentFeatures f2;
|
||||
f2.deSerialize(is);
|
||||
UASSERT(f.walkable == f2.walkable);
|
||||
UASSERT(f.node_box.type == f2.node_box.type);
|
||||
}
|
||||
};
|
||||
|
||||
struct TestCompress: public TestBase
|
||||
{
|
||||
void Run()
|
||||
|
@ -1736,6 +1757,7 @@ void run_tests()
|
|||
TEST(TestSettings);
|
||||
TEST(TestCompress);
|
||||
TEST(TestSerialization);
|
||||
TEST(TestNodedefSerialization);
|
||||
TESTPARAMS(TestMapNode, ndef);
|
||||
TESTPARAMS(TestVoxelManipulator, ndef);
|
||||
TESTPARAMS(TestVoxelAlgorithms, ndef);
|
||||
|
|
16
src/tile.cpp
16
src/tile.cpp
|
@ -372,6 +372,18 @@ public:
|
|||
// Update new texture pointer and texture coordinates to an
|
||||
// AtlasPointer based on it's texture id
|
||||
void updateAP(AtlasPointer &ap);
|
||||
|
||||
bool isKnownSourceImage(const std::string &name)
|
||||
{
|
||||
bool is_known = false;
|
||||
bool cache_found = m_source_image_existence.get(name, &is_known);
|
||||
if(cache_found)
|
||||
return is_known;
|
||||
// Not found in cache; find out if a local file exists
|
||||
is_known = (getTexturePath(name) != "");
|
||||
m_source_image_existence.set(name, is_known);
|
||||
return is_known;
|
||||
}
|
||||
|
||||
// Processes queued texture requests from other threads.
|
||||
// Shall be called from the main thread.
|
||||
|
@ -400,6 +412,9 @@ private:
|
|||
// This should be only accessed from the main thread
|
||||
SourceImageCache m_sourcecache;
|
||||
|
||||
// Thread-safe cache of what source images are known (true = known)
|
||||
MutexedMap<std::string, bool> m_source_image_existence;
|
||||
|
||||
// A texture id is index in this array.
|
||||
// The first position contains a NULL texture.
|
||||
core::array<SourceAtlasPointer> m_atlaspointer_cache;
|
||||
|
@ -781,6 +796,7 @@ void TextureSource::insertSourceImage(const std::string &name, video::IImage *im
|
|||
assert(get_current_thread_id() == m_main_thread);
|
||||
|
||||
m_sourcecache.insert(name, img, true, m_device->getVideoDriver());
|
||||
m_source_image_existence.set(name, true);
|
||||
}
|
||||
|
||||
void TextureSource::rebuildImagesAndTextures()
|
||||
|
|
|
@ -131,6 +131,7 @@ public:
|
|||
virtual IrrlichtDevice* getDevice()
|
||||
{return NULL;}
|
||||
virtual void updateAP(AtlasPointer &ap){};
|
||||
virtual bool isKnownSourceImage(const std::string &name)=0;
|
||||
};
|
||||
|
||||
class IWritableTextureSource : public ITextureSource
|
||||
|
@ -149,6 +150,7 @@ public:
|
|||
virtual IrrlichtDevice* getDevice()
|
||||
{return NULL;}
|
||||
virtual void updateAP(AtlasPointer &ap){};
|
||||
virtual bool isKnownSourceImage(const std::string &name)=0;
|
||||
|
||||
virtual void processQueue()=0;
|
||||
virtual void insertSourceImage(const std::string &name, video::IImage *img)=0;
|
||||
|
|
|
@ -222,7 +222,7 @@ public:
|
|||
/*
|
||||
Copies whole buffer
|
||||
*/
|
||||
SharedBuffer(T *t, unsigned int size)
|
||||
SharedBuffer(const T *t, unsigned int size)
|
||||
{
|
||||
m_size = size;
|
||||
if(m_size != 0)
|
||||
|
|
Loading…
Reference in New Issue