added PlayerSAO and RemotePlayer, removed ServerRemotePlayer
parent
072c265c30
commit
f8c3743991
|
@ -159,7 +159,6 @@ set(common_SRCS
|
||||||
subgame.cpp
|
subgame.cpp
|
||||||
inventorymanager.cpp
|
inventorymanager.cpp
|
||||||
mods.cpp
|
mods.cpp
|
||||||
serverremoteplayer.cpp
|
|
||||||
content_abm.cpp
|
content_abm.cpp
|
||||||
craftdef.cpp
|
craftdef.cpp
|
||||||
nameidmapping.cpp
|
nameidmapping.cpp
|
||||||
|
|
|
@ -1397,45 +1397,7 @@ void Client::ProcessData(u8 *data, u32 datasize, u16 sender_peer_id)
|
||||||
}
|
}
|
||||||
else if(command == TOCLIENT_PLAYERITEM)
|
else if(command == TOCLIENT_PLAYERITEM)
|
||||||
{
|
{
|
||||||
std::string datastring((char*)&data[2], datasize-2);
|
infostream<<"Client: WARNING: Ignoring TOCLIENT_PLAYERITEM"<<std::endl;
|
||||||
std::istringstream is(datastring, std::ios_base::binary);
|
|
||||||
|
|
||||||
u16 count = readU16(is);
|
|
||||||
|
|
||||||
for (u16 i = 0; i < count; ++i) {
|
|
||||||
u16 peer_id = readU16(is);
|
|
||||||
Player *player = m_env.getPlayer(peer_id);
|
|
||||||
|
|
||||||
if (player == NULL)
|
|
||||||
{
|
|
||||||
infostream<<"Client: ignoring player item "
|
|
||||||
<< deSerializeString(is)
|
|
||||||
<< " for non-existing peer id " << peer_id
|
|
||||||
<< std::endl;
|
|
||||||
continue;
|
|
||||||
} else if (player->isLocal()) {
|
|
||||||
infostream<<"Client: ignoring player item "
|
|
||||||
<< deSerializeString(is)
|
|
||||||
<< " for local player" << std::endl;
|
|
||||||
continue;
|
|
||||||
} else {
|
|
||||||
InventoryList *inv = player->inventory.getList("main");
|
|
||||||
std::string itemstring(deSerializeString(is));
|
|
||||||
ItemStack item;
|
|
||||||
item.deSerialize(itemstring, m_itemdef);
|
|
||||||
inv->changeItem(0, item);
|
|
||||||
if(itemstring.empty())
|
|
||||||
{
|
|
||||||
infostream<<"Client: empty player item for peer "
|
|
||||||
<<peer_id<<std::endl;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
infostream<<"Client: player item for peer "
|
|
||||||
<<peer_id<<": "<<itemstring<<std::endl;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else if(command == TOCLIENT_DEATHSCREEN)
|
else if(command == TOCLIENT_DEATHSCREEN)
|
||||||
{
|
{
|
||||||
|
|
|
@ -200,7 +200,7 @@ enum ToClientCommand
|
||||||
wstring reason
|
wstring reason
|
||||||
*/
|
*/
|
||||||
|
|
||||||
TOCLIENT_PLAYERITEM = 0x36,
|
TOCLIENT_PLAYERITEM = 0x36, // Obsolete
|
||||||
/*
|
/*
|
||||||
u16 command
|
u16 command
|
||||||
u16 count of player items
|
u16 count of player items
|
||||||
|
|
|
@ -99,9 +99,8 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
// Length of cracking animation in count of images
|
// Length of cracking animation in count of images
|
||||||
#define CRACK_ANIMATION_LENGTH 5
|
#define CRACK_ANIMATION_LENGTH 5
|
||||||
|
|
||||||
// Some stuff needed by old code moved to here from heightmap.h
|
// Maximum hit points of a player
|
||||||
#define GROUNDHEIGHT_NOTFOUND_SETVALUE (-10e6)
|
#define PLAYER_MAX_HP 20
|
||||||
#define GROUNDHEIGHT_VALID_MINVALUE ( -9e6)
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -1011,6 +1011,7 @@ private:
|
||||||
float m_damage_visual_timer;
|
float m_damage_visual_timer;
|
||||||
bool m_dead;
|
bool m_dead;
|
||||||
float m_step_distance_counter;
|
float m_step_distance_counter;
|
||||||
|
std::string m_wielded_item;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
PlayerCAO(IGameDef *gamedef, ClientEnvironment *env):
|
PlayerCAO(IGameDef *gamedef, ClientEnvironment *env):
|
||||||
|
@ -1024,7 +1025,8 @@ public:
|
||||||
m_local_player(NULL),
|
m_local_player(NULL),
|
||||||
m_damage_visual_timer(0),
|
m_damage_visual_timer(0),
|
||||||
m_dead(false),
|
m_dead(false),
|
||||||
m_step_distance_counter(0)
|
m_step_distance_counter(0),
|
||||||
|
m_wielded_item("")
|
||||||
{
|
{
|
||||||
if(gamedef == NULL)
|
if(gamedef == NULL)
|
||||||
ClientActiveObject::registerType(getType(), create);
|
ClientActiveObject::registerType(getType(), create);
|
||||||
|
@ -1048,6 +1050,11 @@ public:
|
||||||
m_yaw = readF1000(is);
|
m_yaw = readF1000(is);
|
||||||
// dead
|
// dead
|
||||||
m_dead = readU8(is);
|
m_dead = readU8(is);
|
||||||
|
// wielded item
|
||||||
|
try{
|
||||||
|
m_wielded_item = deSerializeString(is);
|
||||||
|
}
|
||||||
|
catch(SerializationError &e){}
|
||||||
|
|
||||||
pos_translator.init(m_position);
|
pos_translator.init(m_position);
|
||||||
|
|
||||||
|
@ -1263,6 +1270,11 @@ public:
|
||||||
m_dead = readU8(is);
|
m_dead = readU8(is);
|
||||||
updateVisibility();
|
updateVisibility();
|
||||||
}
|
}
|
||||||
|
else if(cmd == 3) // wielded item
|
||||||
|
{
|
||||||
|
m_wielded_item = deSerializeString(is);
|
||||||
|
updateWieldedItem();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void updateTextures(const std::string &mod)
|
void updateTextures(const std::string &mod)
|
||||||
|
@ -1288,6 +1300,50 @@ public:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void updateWieldedItem()
|
||||||
|
{
|
||||||
|
if(m_is_local_player)
|
||||||
|
{
|
||||||
|
// ignoring player item for local player
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ItemStack item;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
item.deSerialize(m_wielded_item, m_gamedef->idef());
|
||||||
|
}
|
||||||
|
catch(SerializationError &e)
|
||||||
|
{
|
||||||
|
errorstream<<"PlayerCAO: SerializationError "
|
||||||
|
"while reading wielded item: "
|
||||||
|
<<m_wielded_item<<std::endl;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// do something with the item, for example:
|
||||||
|
Player *player = m_env->getPlayer(m_name.c_str());
|
||||||
|
if(player)
|
||||||
|
{
|
||||||
|
InventoryList *inv = player->inventory.getList("main");
|
||||||
|
assert(inv);
|
||||||
|
inv->changeItem(0, item);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(item.empty())
|
||||||
|
{
|
||||||
|
infostream<<"PlayerCAO: empty player item for player "
|
||||||
|
<<m_name<<std::endl;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
infostream<<"PlayerCAO: player item for player "
|
||||||
|
<<m_name<<": "
|
||||||
|
<<item.getItemString()<<std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Prototype
|
// Prototype
|
||||||
|
|
|
@ -26,6 +26,8 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
#include "serialization.h" // For compressZlib
|
#include "serialization.h" // For compressZlib
|
||||||
#include "tool.h" // For ToolCapabilities
|
#include "tool.h" // For ToolCapabilities
|
||||||
#include "gamedef.h"
|
#include "gamedef.h"
|
||||||
|
#include "player.h"
|
||||||
|
#include "scriptapi.h"
|
||||||
|
|
||||||
core::map<u16, ServerActiveObject::Factory> ServerActiveObject::m_types;
|
core::map<u16, ServerActiveObject::Factory> ServerActiveObject::m_types;
|
||||||
|
|
||||||
|
@ -333,7 +335,6 @@ ServerActiveObject* createItemSAO(ServerEnvironment *env, v3f pos,
|
||||||
LuaEntitySAO
|
LuaEntitySAO
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "scriptapi.h"
|
|
||||||
#include "luaentity_common.h"
|
#include "luaentity_common.h"
|
||||||
|
|
||||||
// Prototype (registers item for deserialization)
|
// Prototype (registers item for deserialization)
|
||||||
|
@ -610,7 +611,7 @@ void LuaEntitySAO::setHP(s16 hp)
|
||||||
m_hp = hp;
|
m_hp = hp;
|
||||||
}
|
}
|
||||||
|
|
||||||
s16 LuaEntitySAO::getHP()
|
s16 LuaEntitySAO::getHP() const
|
||||||
{
|
{
|
||||||
return m_hp;
|
return m_hp;
|
||||||
}
|
}
|
||||||
|
@ -749,3 +750,345 @@ void LuaEntitySAO::sendPosition(bool do_interpolate, bool is_movement_end)
|
||||||
m_messages_out.push_back(aom);
|
m_messages_out.push_back(aom);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
PlayerSAO
|
||||||
|
*/
|
||||||
|
|
||||||
|
// No prototype, PlayerSAO does not need to be deserialized
|
||||||
|
|
||||||
|
PlayerSAO::PlayerSAO(ServerEnvironment *env_, Player *player_, u16 peer_id_):
|
||||||
|
ServerActiveObject(env_, v3f(0,0,0)),
|
||||||
|
m_player(player_),
|
||||||
|
m_peer_id(peer_id_),
|
||||||
|
m_inventory(NULL),
|
||||||
|
m_last_good_position(0,0,0),
|
||||||
|
m_last_good_position_age(0),
|
||||||
|
m_time_from_last_punch(0),
|
||||||
|
m_wield_index(0),
|
||||||
|
m_position_not_sent(false),
|
||||||
|
m_teleported(false),
|
||||||
|
m_inventory_not_sent(false),
|
||||||
|
m_hp_not_sent(false),
|
||||||
|
m_wielded_item_not_sent(false)
|
||||||
|
{
|
||||||
|
assert(m_player);
|
||||||
|
assert(m_peer_id != 0);
|
||||||
|
setBasePosition(m_player->getPosition());
|
||||||
|
m_inventory = &m_player->inventory;
|
||||||
|
}
|
||||||
|
|
||||||
|
PlayerSAO::~PlayerSAO()
|
||||||
|
{
|
||||||
|
if(m_inventory != &m_player->inventory)
|
||||||
|
delete m_inventory;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string PlayerSAO::getDescription()
|
||||||
|
{
|
||||||
|
return std::string("player ") + m_player->getName();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Called after id has been set and has been inserted in environment
|
||||||
|
void PlayerSAO::addedToEnvironment()
|
||||||
|
{
|
||||||
|
ServerActiveObject::addedToEnvironment();
|
||||||
|
ServerActiveObject::setBasePosition(m_player->getPosition());
|
||||||
|
m_player->setPlayerSAO(this);
|
||||||
|
m_player->peer_id = m_peer_id;
|
||||||
|
m_last_good_position = m_player->getPosition();
|
||||||
|
m_last_good_position_age = 0.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Called before removing from environment
|
||||||
|
void PlayerSAO::removingFromEnvironment()
|
||||||
|
{
|
||||||
|
ServerActiveObject::removingFromEnvironment();
|
||||||
|
if(m_player->getPlayerSAO() == this)
|
||||||
|
{
|
||||||
|
m_player->setPlayerSAO(NULL);
|
||||||
|
m_player->peer_id = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool PlayerSAO::isStaticAllowed() const
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool PlayerSAO::unlimitedTransferDistance() const
|
||||||
|
{
|
||||||
|
return g_settings->getBool("unlimited_player_transfer_distance");
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string PlayerSAO::getClientInitializationData()
|
||||||
|
{
|
||||||
|
std::ostringstream os(std::ios::binary);
|
||||||
|
// version
|
||||||
|
writeU8(os, 0);
|
||||||
|
// name
|
||||||
|
os<<serializeString(m_player->getName());
|
||||||
|
// pos
|
||||||
|
writeV3F1000(os, m_player->getPosition());
|
||||||
|
// yaw
|
||||||
|
writeF1000(os, m_player->getYaw());
|
||||||
|
// dead
|
||||||
|
writeU8(os, getHP() == 0);
|
||||||
|
// wielded item
|
||||||
|
os<<serializeString(getWieldedItem().getItemString());
|
||||||
|
return os.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string PlayerSAO::getStaticData()
|
||||||
|
{
|
||||||
|
assert(0);
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
void PlayerSAO::step(float dtime, bool send_recommended)
|
||||||
|
{
|
||||||
|
m_time_from_last_punch += dtime;
|
||||||
|
|
||||||
|
/*
|
||||||
|
Check player movements
|
||||||
|
|
||||||
|
NOTE: Actually the server should handle player physics like the
|
||||||
|
client does and compare player's position to what is calculated
|
||||||
|
on our side. This is required when eg. players fly due to an
|
||||||
|
explosion.
|
||||||
|
*/
|
||||||
|
|
||||||
|
//float player_max_speed = BS * 4.0; // Normal speed
|
||||||
|
float player_max_speed = BS * 20; // Fast speed
|
||||||
|
float player_max_speed_up = BS * 20;
|
||||||
|
player_max_speed *= 2.5; // Tolerance
|
||||||
|
player_max_speed_up *= 2.5;
|
||||||
|
|
||||||
|
m_last_good_position_age += dtime;
|
||||||
|
if(m_last_good_position_age >= 1.0){
|
||||||
|
float age = m_last_good_position_age;
|
||||||
|
v3f diff = (m_player->getPosition() - m_last_good_position);
|
||||||
|
float d_vert = diff.Y;
|
||||||
|
diff.Y = 0;
|
||||||
|
float d_horiz = diff.getLength();
|
||||||
|
/*infostream<<m_player->getName()<<"'s horizontal speed is "
|
||||||
|
<<(d_horiz/age)<<std::endl;*/
|
||||||
|
if(d_horiz <= age * player_max_speed &&
|
||||||
|
(d_vert < 0 || d_vert < age * player_max_speed_up)){
|
||||||
|
m_last_good_position = m_player->getPosition();
|
||||||
|
} else {
|
||||||
|
actionstream<<"Player "<<m_player->getName()
|
||||||
|
<<" moved too fast; resetting position"
|
||||||
|
<<std::endl;
|
||||||
|
m_player->setPosition(m_last_good_position);
|
||||||
|
m_teleported = true;
|
||||||
|
}
|
||||||
|
m_last_good_position_age = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(send_recommended == false)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if(m_position_not_sent)
|
||||||
|
{
|
||||||
|
m_position_not_sent = false;
|
||||||
|
|
||||||
|
std::ostringstream os(std::ios::binary);
|
||||||
|
// command (0 = update position)
|
||||||
|
writeU8(os, 0);
|
||||||
|
// pos
|
||||||
|
writeV3F1000(os, m_player->getPosition());
|
||||||
|
// yaw
|
||||||
|
writeF1000(os, m_player->getYaw());
|
||||||
|
// create message and add to list
|
||||||
|
ActiveObjectMessage aom(getId(), false, os.str());
|
||||||
|
m_messages_out.push_back(aom);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(m_wielded_item_not_sent)
|
||||||
|
{
|
||||||
|
m_wielded_item_not_sent = false;
|
||||||
|
|
||||||
|
std::ostringstream os(std::ios::binary);
|
||||||
|
// command (3 = wielded item)
|
||||||
|
writeU8(os, 3);
|
||||||
|
// wielded item
|
||||||
|
os<<serializeString(getWieldedItem().getItemString());
|
||||||
|
// create message and add to list
|
||||||
|
ActiveObjectMessage aom(getId(), false, os.str());
|
||||||
|
m_messages_out.push_back(aom);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void PlayerSAO::setBasePosition(const v3f &position)
|
||||||
|
{
|
||||||
|
ServerActiveObject::setBasePosition(position);
|
||||||
|
m_position_not_sent = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PlayerSAO::setPos(v3f pos)
|
||||||
|
{
|
||||||
|
m_player->setPosition(pos);
|
||||||
|
// Movement caused by this command is always valid
|
||||||
|
m_last_good_position = pos;
|
||||||
|
m_last_good_position_age = 0;
|
||||||
|
// Force position change on client
|
||||||
|
m_teleported = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PlayerSAO::moveTo(v3f pos, bool continuous)
|
||||||
|
{
|
||||||
|
m_player->setPosition(pos);
|
||||||
|
// Movement caused by this command is always valid
|
||||||
|
m_last_good_position = pos;
|
||||||
|
m_last_good_position_age = 0;
|
||||||
|
// Force position change on client
|
||||||
|
m_teleported = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
int PlayerSAO::punch(v3f dir,
|
||||||
|
const ToolCapabilities *toolcap,
|
||||||
|
ServerActiveObject *puncher,
|
||||||
|
float time_from_last_punch)
|
||||||
|
{
|
||||||
|
if(!toolcap)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
// No effect if PvP disabled
|
||||||
|
if(g_settings->getBool("enable_pvp") == false){
|
||||||
|
if(puncher->getType() == ACTIVEOBJECT_TYPE_PLAYER)
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// "Material" groups of the player
|
||||||
|
ItemGroupList groups;
|
||||||
|
groups["choppy"] = 2;
|
||||||
|
groups["fleshy"] = 3;
|
||||||
|
|
||||||
|
HitParams hitparams = getHitParams(groups, toolcap, time_from_last_punch);
|
||||||
|
|
||||||
|
actionstream<<"Player "<<m_player->getName()<<" punched by "
|
||||||
|
<<puncher->getDescription()<<", damage "<<hitparams.hp
|
||||||
|
<<" HP"<<std::endl;
|
||||||
|
|
||||||
|
setHP(getHP() - hitparams.hp);
|
||||||
|
|
||||||
|
if(hitparams.hp != 0)
|
||||||
|
{
|
||||||
|
std::ostringstream os(std::ios::binary);
|
||||||
|
// command (1 = punched)
|
||||||
|
writeU8(os, 1);
|
||||||
|
// damage
|
||||||
|
writeS16(os, hitparams.hp);
|
||||||
|
// create message and add to list
|
||||||
|
ActiveObjectMessage aom(getId(), false, os.str());
|
||||||
|
m_messages_out.push_back(aom);
|
||||||
|
}
|
||||||
|
|
||||||
|
return hitparams.wear;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PlayerSAO::rightClick(ServerActiveObject *clicker)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
s16 PlayerSAO::getHP() const
|
||||||
|
{
|
||||||
|
return m_player->hp;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PlayerSAO::setHP(s16 hp)
|
||||||
|
{
|
||||||
|
s16 oldhp = m_player->hp;
|
||||||
|
|
||||||
|
if(hp < 0)
|
||||||
|
hp = 0;
|
||||||
|
else if(hp > PLAYER_MAX_HP)
|
||||||
|
hp = PLAYER_MAX_HP;
|
||||||
|
|
||||||
|
if(hp < oldhp && g_settings->getBool("enable_damage") == false)
|
||||||
|
{
|
||||||
|
m_hp_not_sent = true; // fix wrong prediction on client
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_player->hp = hp;
|
||||||
|
|
||||||
|
if(hp != oldhp)
|
||||||
|
m_hp_not_sent = true;
|
||||||
|
|
||||||
|
// On death or reincarnation send an active object message
|
||||||
|
if((hp == 0) != (oldhp == 0))
|
||||||
|
{
|
||||||
|
std::ostringstream os(std::ios::binary);
|
||||||
|
// command (2 = update death state)
|
||||||
|
writeU8(os, 2);
|
||||||
|
// dead?
|
||||||
|
writeU8(os, hp == 0);
|
||||||
|
// create message and add to list
|
||||||
|
ActiveObjectMessage aom(getId(), false, os.str());
|
||||||
|
m_messages_out.push_back(aom);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Inventory* PlayerSAO::getInventory()
|
||||||
|
{
|
||||||
|
return m_inventory;
|
||||||
|
}
|
||||||
|
const Inventory* PlayerSAO::getInventory() const
|
||||||
|
{
|
||||||
|
return m_inventory;
|
||||||
|
}
|
||||||
|
|
||||||
|
InventoryLocation PlayerSAO::getInventoryLocation() const
|
||||||
|
{
|
||||||
|
InventoryLocation loc;
|
||||||
|
loc.setPlayer(m_player->getName());
|
||||||
|
return loc;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PlayerSAO::setInventoryModified()
|
||||||
|
{
|
||||||
|
m_inventory_not_sent = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string PlayerSAO::getWieldList() const
|
||||||
|
{
|
||||||
|
return "main";
|
||||||
|
}
|
||||||
|
|
||||||
|
int PlayerSAO::getWieldIndex() const
|
||||||
|
{
|
||||||
|
return m_wield_index;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PlayerSAO::setWieldIndex(int i)
|
||||||
|
{
|
||||||
|
if(i != m_wield_index)
|
||||||
|
{
|
||||||
|
m_wield_index = i;
|
||||||
|
m_wielded_item_not_sent = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void PlayerSAO::disconnected()
|
||||||
|
{
|
||||||
|
m_peer_id = 0;
|
||||||
|
m_removed = true;
|
||||||
|
if(m_player->getPlayerSAO() == this)
|
||||||
|
{
|
||||||
|
m_player->setPlayerSAO(NULL);
|
||||||
|
m_player->peer_id = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void PlayerSAO::createCreativeInventory()
|
||||||
|
{
|
||||||
|
if(m_inventory != &m_player->inventory)
|
||||||
|
delete m_inventory;
|
||||||
|
|
||||||
|
m_inventory = new Inventory(m_player->inventory);
|
||||||
|
m_inventory->clearContents();
|
||||||
|
scriptapi_get_creative_inventory(m_env->getLua(), this);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -23,14 +23,13 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
#include "serverobject.h"
|
#include "serverobject.h"
|
||||||
#include "content_object.h"
|
#include "content_object.h"
|
||||||
#include "itemgroup.h"
|
#include "itemgroup.h"
|
||||||
|
#include "player.h"
|
||||||
|
|
||||||
ServerActiveObject* createItemSAO(ServerEnvironment *env, v3f pos,
|
ServerActiveObject* createItemSAO(ServerEnvironment *env, v3f pos,
|
||||||
const std::string itemstring);
|
const std::string itemstring);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
LuaEntitySAO
|
LuaEntitySAO needs some internals exposed.
|
||||||
|
|
||||||
This is the only SAO that needs to have a bunch of it's internals exposed.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
struct LuaEntityProperties;
|
struct LuaEntityProperties;
|
||||||
|
@ -59,7 +58,7 @@ public:
|
||||||
float getMinimumSavedMovement();
|
float getMinimumSavedMovement();
|
||||||
std::string getDescription();
|
std::string getDescription();
|
||||||
void setHP(s16 hp);
|
void setHP(s16 hp);
|
||||||
s16 getHP();
|
s16 getHP() const;
|
||||||
/* LuaEntitySAO-specific */
|
/* LuaEntitySAO-specific */
|
||||||
void setVelocity(v3f velocity);
|
void setVelocity(v3f velocity);
|
||||||
v3f getVelocity();
|
v3f getVelocity();
|
||||||
|
@ -94,5 +93,102 @@ private:
|
||||||
bool m_armor_groups_sent;
|
bool m_armor_groups_sent;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
PlayerSAO needs some internals exposed.
|
||||||
|
*/
|
||||||
|
|
||||||
|
class PlayerSAO : public ServerActiveObject
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
PlayerSAO(ServerEnvironment *env_, Player *player_, u16 peer_id_);
|
||||||
|
~PlayerSAO();
|
||||||
|
u8 getType() const
|
||||||
|
{return ACTIVEOBJECT_TYPE_PLAYER;}
|
||||||
|
std::string getDescription();
|
||||||
|
|
||||||
|
/*
|
||||||
|
Active object <-> environment interface
|
||||||
|
*/
|
||||||
|
|
||||||
|
void addedToEnvironment();
|
||||||
|
void removingFromEnvironment();
|
||||||
|
bool isStaticAllowed() const;
|
||||||
|
bool unlimitedTransferDistance() const;
|
||||||
|
std::string getClientInitializationData();
|
||||||
|
std::string getStaticData();
|
||||||
|
void step(float dtime, bool send_recommended);
|
||||||
|
void setBasePosition(const v3f &position);
|
||||||
|
void setPos(v3f pos);
|
||||||
|
void moveTo(v3f pos, bool continuous);
|
||||||
|
|
||||||
|
/*
|
||||||
|
Interaction interface
|
||||||
|
*/
|
||||||
|
|
||||||
|
int punch(v3f dir,
|
||||||
|
const ToolCapabilities *toolcap,
|
||||||
|
ServerActiveObject *puncher,
|
||||||
|
float time_from_last_punch);
|
||||||
|
void rightClick(ServerActiveObject *clicker);
|
||||||
|
s16 getHP() const;
|
||||||
|
void setHP(s16 hp);
|
||||||
|
|
||||||
|
/*
|
||||||
|
Inventory interface
|
||||||
|
*/
|
||||||
|
|
||||||
|
Inventory* getInventory();
|
||||||
|
const Inventory* getInventory() const;
|
||||||
|
InventoryLocation getInventoryLocation() const;
|
||||||
|
void setInventoryModified();
|
||||||
|
std::string getWieldList() const;
|
||||||
|
int getWieldIndex() const;
|
||||||
|
void setWieldIndex(int i);
|
||||||
|
|
||||||
|
/*
|
||||||
|
PlayerSAO-specific
|
||||||
|
*/
|
||||||
|
|
||||||
|
void disconnected();
|
||||||
|
|
||||||
|
void createCreativeInventory();
|
||||||
|
|
||||||
|
Player* getPlayer()
|
||||||
|
{
|
||||||
|
return m_player;
|
||||||
|
}
|
||||||
|
u16 getPeerID() const
|
||||||
|
{
|
||||||
|
return m_peer_id;
|
||||||
|
}
|
||||||
|
v3f getLastGoodPosition() const
|
||||||
|
{
|
||||||
|
return m_last_good_position;
|
||||||
|
}
|
||||||
|
float resetTimeFromLastPunch()
|
||||||
|
{
|
||||||
|
float r = m_time_from_last_punch;
|
||||||
|
m_time_from_last_punch = 0.0;
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
Player *m_player;
|
||||||
|
u16 m_peer_id;
|
||||||
|
Inventory *m_inventory;
|
||||||
|
v3f m_last_good_position;
|
||||||
|
float m_last_good_position_age;
|
||||||
|
float m_time_from_last_punch;
|
||||||
|
int m_wield_index;
|
||||||
|
bool m_position_not_sent;
|
||||||
|
|
||||||
|
public:
|
||||||
|
// Some flags used by Server
|
||||||
|
bool m_teleported;
|
||||||
|
bool m_inventory_not_sent;
|
||||||
|
bool m_hp_not_sent;
|
||||||
|
bool m_wielded_item_not_sent;
|
||||||
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -37,7 +37,6 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
#include "nodemetadata.h"
|
#include "nodemetadata.h"
|
||||||
#include "main.h" // For g_settings, g_profiler
|
#include "main.h" // For g_settings, g_profiler
|
||||||
#include "gamedef.h"
|
#include "gamedef.h"
|
||||||
#include "serverremoteplayer.h"
|
|
||||||
#ifndef SERVER
|
#ifndef SERVER
|
||||||
#include "clientmap.h"
|
#include "clientmap.h"
|
||||||
#endif
|
#endif
|
||||||
|
@ -368,7 +367,7 @@ void ServerEnvironment::serializePlayers(const std::string &savedir)
|
||||||
//infostream<<"Checking player file "<<path<<std::endl;
|
//infostream<<"Checking player file "<<path<<std::endl;
|
||||||
|
|
||||||
// Load player to see what is its name
|
// Load player to see what is its name
|
||||||
ServerRemotePlayer testplayer(this);
|
RemotePlayer testplayer(m_gamedef);
|
||||||
{
|
{
|
||||||
// Open file and deserialize
|
// Open file and deserialize
|
||||||
std::ifstream is(path.c_str(), std::ios_base::binary);
|
std::ifstream is(path.c_str(), std::ios_base::binary);
|
||||||
|
@ -482,7 +481,7 @@ void ServerEnvironment::deSerializePlayers(const std::string &savedir)
|
||||||
//infostream<<"Checking player file "<<path<<std::endl;
|
//infostream<<"Checking player file "<<path<<std::endl;
|
||||||
|
|
||||||
// Load player to see what is its name
|
// Load player to see what is its name
|
||||||
ServerRemotePlayer testplayer(this);
|
RemotePlayer testplayer(m_gamedef);
|
||||||
{
|
{
|
||||||
// Open file and deserialize
|
// Open file and deserialize
|
||||||
std::ifstream is(path.c_str(), std::ios_base::binary);
|
std::ifstream is(path.c_str(), std::ios_base::binary);
|
||||||
|
@ -510,12 +509,10 @@ void ServerEnvironment::deSerializePlayers(const std::string &savedir)
|
||||||
if(player == NULL)
|
if(player == NULL)
|
||||||
{
|
{
|
||||||
//infostream<<"Is a new player"<<std::endl;
|
//infostream<<"Is a new player"<<std::endl;
|
||||||
player = new ServerRemotePlayer(this);
|
player = new RemotePlayer(m_gamedef);
|
||||||
newplayer = true;
|
newplayer = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
ServerRemotePlayer *srp = static_cast<ServerRemotePlayer*>(player);
|
|
||||||
|
|
||||||
// Load player
|
// Load player
|
||||||
{
|
{
|
||||||
verbosestream<<"Reading player "<<testplayer.getName()<<" from "
|
verbosestream<<"Reading player "<<testplayer.getName()<<" from "
|
||||||
|
@ -527,9 +524,7 @@ void ServerEnvironment::deSerializePlayers(const std::string &savedir)
|
||||||
infostream<<"Failed to read "<<path<<std::endl;
|
infostream<<"Failed to read "<<path<<std::endl;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
srp->deSerialize(is);
|
player->deSerialize(is);
|
||||||
srp->m_last_good_position = srp->getBasePosition();
|
|
||||||
srp->m_last_good_position_age = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(newplayer)
|
if(newplayer)
|
||||||
|
@ -2074,7 +2069,7 @@ void ClientEnvironment::step(float dtime)
|
||||||
catch(InvalidPositionException &e){
|
catch(InvalidPositionException &e){
|
||||||
light = blend_light(getDayNightRatio(), LIGHT_SUN, 0);
|
light = blend_light(getDayNightRatio(), LIGHT_SUN, 0);
|
||||||
}
|
}
|
||||||
player->updateLight(light);
|
player->light = light;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -2226,8 +2221,19 @@ void ClientEnvironment::addActiveObject(u16 id, u8 type,
|
||||||
|
|
||||||
obj->setId(id);
|
obj->setId(id);
|
||||||
|
|
||||||
obj->initialize(init_data);
|
try
|
||||||
|
{
|
||||||
|
obj->initialize(init_data);
|
||||||
|
}
|
||||||
|
catch(SerializationError &e)
|
||||||
|
{
|
||||||
|
errorstream<<"ClientEnvironment::addActiveObject():"
|
||||||
|
<<" id="<<id<<" type="<<type
|
||||||
|
<<": SerializationError in initialize(),"
|
||||||
|
<<" init_data="<<serializeJsonString(init_data)
|
||||||
|
<<std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
addActiveObject(obj);
|
addActiveObject(obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2258,7 +2264,18 @@ void ClientEnvironment::processActiveObjectMessage(u16 id,
|
||||||
<<std::endl;
|
<<std::endl;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
obj->processMessage(data);
|
try
|
||||||
|
{
|
||||||
|
obj->processMessage(data);
|
||||||
|
}
|
||||||
|
catch(SerializationError &e)
|
||||||
|
{
|
||||||
|
errorstream<<"ClientEnvironment::processActiveObjectMessage():"
|
||||||
|
<<" id="<<id<<" type="<<obj->getType()
|
||||||
|
<<" SerializationError in processMessage(),"
|
||||||
|
<<" message="<<serializeJsonString(data)
|
||||||
|
<<std::endl;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -795,6 +795,18 @@ void Inventory::clear()
|
||||||
m_lists.clear();
|
m_lists.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Inventory::clearContents()
|
||||||
|
{
|
||||||
|
for(u32 i=0; i<m_lists.size(); i++)
|
||||||
|
{
|
||||||
|
InventoryList *list = m_lists[i];
|
||||||
|
for(u32 j=0; j<list->getSize(); j++)
|
||||||
|
{
|
||||||
|
list->deleteItem(j);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Inventory::Inventory(IItemDefManager *itemdef)
|
Inventory::Inventory(IItemDefManager *itemdef)
|
||||||
{
|
{
|
||||||
m_itemdef = itemdef;
|
m_itemdef = itemdef;
|
||||||
|
|
|
@ -250,6 +250,7 @@ public:
|
||||||
~Inventory();
|
~Inventory();
|
||||||
|
|
||||||
void clear();
|
void clear();
|
||||||
|
void clearContents();
|
||||||
|
|
||||||
Inventory(IItemDefManager *itemdef);
|
Inventory(IItemDefManager *itemdef);
|
||||||
Inventory(const Inventory &other);
|
Inventory(const Inventory &other);
|
||||||
|
|
|
@ -32,6 +32,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
#include "environment.h"
|
#include "environment.h"
|
||||||
#include "gamedef.h"
|
#include "gamedef.h"
|
||||||
#include "event.h"
|
#include "event.h"
|
||||||
|
#include "content_sao.h"
|
||||||
|
|
||||||
Player::Player(IGameDef *gamedef):
|
Player::Player(IGameDef *gamedef):
|
||||||
touching_ground(false),
|
touching_ground(false),
|
||||||
|
@ -40,8 +41,7 @@ Player::Player(IGameDef *gamedef):
|
||||||
is_climbing(false),
|
is_climbing(false),
|
||||||
swimming_up(false),
|
swimming_up(false),
|
||||||
inventory(gamedef->idef()),
|
inventory(gamedef->idef()),
|
||||||
inventory_backup(NULL),
|
hp(PLAYER_MAX_HP),
|
||||||
hp(20),
|
|
||||||
peer_id(PEER_ID_INEXISTENT),
|
peer_id(PEER_ID_INEXISTENT),
|
||||||
// protected
|
// protected
|
||||||
m_gamedef(gamedef),
|
m_gamedef(gamedef),
|
||||||
|
@ -51,16 +51,6 @@ Player::Player(IGameDef *gamedef):
|
||||||
m_position(0,0,0)
|
m_position(0,0,0)
|
||||||
{
|
{
|
||||||
updateName("<not set>");
|
updateName("<not set>");
|
||||||
resetInventory();
|
|
||||||
}
|
|
||||||
|
|
||||||
Player::~Player()
|
|
||||||
{
|
|
||||||
delete inventory_backup;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Player::resetInventory()
|
|
||||||
{
|
|
||||||
inventory.clear();
|
inventory.clear();
|
||||||
inventory.addList("main", PLAYER_INVENTORY_SIZE);
|
inventory.addList("main", PLAYER_INVENTORY_SIZE);
|
||||||
inventory.addList("craft", 9);
|
inventory.addList("craft", 9);
|
||||||
|
@ -68,6 +58,10 @@ void Player::resetInventory()
|
||||||
inventory.addList("craftresult", 1);
|
inventory.addList("craftresult", 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Player::~Player()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
// Y direction is ignored
|
// Y direction is ignored
|
||||||
void Player::accelerate(v3f target_speed, f32 max_increase)
|
void Player::accelerate(v3f target_speed, f32 max_increase)
|
||||||
{
|
{
|
||||||
|
@ -126,12 +120,7 @@ void Player::serialize(std::ostream &os)
|
||||||
|
|
||||||
os<<"PlayerArgsEnd\n";
|
os<<"PlayerArgsEnd\n";
|
||||||
|
|
||||||
// If actual inventory is backed up due to creative mode, save it
|
inventory.serialize(os);
|
||||||
// instead of the dummy creative mode inventory
|
|
||||||
if(inventory_backup)
|
|
||||||
inventory_backup->serialize(os);
|
|
||||||
else
|
|
||||||
inventory.serialize(os);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Player::deSerialize(std::istream &is)
|
void Player::deSerialize(std::istream &is)
|
||||||
|
@ -779,3 +768,13 @@ v3s16 LocalPlayer::getStandingNodePos()
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
RemotePlayer
|
||||||
|
*/
|
||||||
|
|
||||||
|
void RemotePlayer::setPosition(const v3f &position)
|
||||||
|
{
|
||||||
|
Player::setPosition(position);
|
||||||
|
if(m_sao)
|
||||||
|
m_sao->setBasePosition(position);
|
||||||
|
}
|
||||||
|
|
52
src/player.h
52
src/player.h
|
@ -31,18 +31,17 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
class Map;
|
class Map;
|
||||||
class IGameDef;
|
class IGameDef;
|
||||||
struct CollisionInfo;
|
struct CollisionInfo;
|
||||||
|
class PlayerSAO;
|
||||||
|
|
||||||
class Player
|
class Player
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
Player(IGameDef *gamedef);
|
Player(IGameDef *gamedef);
|
||||||
virtual ~Player();
|
virtual ~Player() = 0;
|
||||||
|
|
||||||
void resetInventory();
|
virtual void move(f32 dtime, Map &map, f32 pos_max_d)
|
||||||
|
{}
|
||||||
//void move(f32 dtime, Map &map);
|
|
||||||
virtual void move(f32 dtime, Map &map, f32 pos_max_d) = 0;
|
|
||||||
|
|
||||||
v3f getSpeed()
|
v3f getSpeed()
|
||||||
{
|
{
|
||||||
|
@ -112,7 +111,7 @@ public:
|
||||||
return (m_yaw + 90.) * core::DEGTORAD;
|
return (m_yaw + 90.) * core::DEGTORAD;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void updateName(const char *name)
|
void updateName(const char *name)
|
||||||
{
|
{
|
||||||
snprintf(m_name, PLAYERNAME_SIZE, "%s", name);
|
snprintf(m_name, PLAYERNAME_SIZE, "%s", name);
|
||||||
}
|
}
|
||||||
|
@ -122,17 +121,13 @@ public:
|
||||||
return m_name;
|
return m_name;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual bool isLocal() const = 0;
|
virtual bool isLocal() const
|
||||||
|
{ return false; }
|
||||||
|
virtual PlayerSAO *getPlayerSAO()
|
||||||
|
{ return NULL; }
|
||||||
|
virtual void setPlayerSAO(PlayerSAO *sao)
|
||||||
|
{ assert(0); }
|
||||||
|
|
||||||
virtual void updateLight(u8 light_at_pos)
|
|
||||||
{
|
|
||||||
light = light_at_pos;
|
|
||||||
}
|
|
||||||
|
|
||||||
// NOTE: Use peer_id == 0 for disconnected
|
|
||||||
/*virtual bool isClientConnected() { return false; }
|
|
||||||
virtual void setClientConnected(bool) {}*/
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
serialize() writes a bunch of text that can contain
|
serialize() writes a bunch of text that can contain
|
||||||
any characters except a '\0', and such an ending that
|
any characters except a '\0', and such an ending that
|
||||||
|
@ -151,9 +146,8 @@ public:
|
||||||
|
|
||||||
u8 light;
|
u8 light;
|
||||||
|
|
||||||
|
// In creative mode, this is the invisible backup inventory
|
||||||
Inventory inventory;
|
Inventory inventory;
|
||||||
// Actual inventory is backed up here when creative mode is used
|
|
||||||
Inventory *inventory_backup;
|
|
||||||
|
|
||||||
u16 hp;
|
u16 hp;
|
||||||
|
|
||||||
|
@ -167,9 +161,6 @@ protected:
|
||||||
f32 m_yaw;
|
f32 m_yaw;
|
||||||
v3f m_speed;
|
v3f m_speed;
|
||||||
v3f m_position;
|
v3f m_position;
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifndef SERVER
|
#ifndef SERVER
|
||||||
|
@ -249,5 +240,24 @@ private:
|
||||||
};
|
};
|
||||||
#endif // !SERVER
|
#endif // !SERVER
|
||||||
|
|
||||||
|
/*
|
||||||
|
Player on the server
|
||||||
|
*/
|
||||||
|
class RemotePlayer : public Player
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
RemotePlayer(IGameDef *gamedef): Player(gamedef), m_sao(0) {}
|
||||||
|
virtual ~RemotePlayer() {}
|
||||||
|
|
||||||
|
PlayerSAO *getPlayerSAO()
|
||||||
|
{ return m_sao; }
|
||||||
|
void setPlayerSAO(PlayerSAO *sao)
|
||||||
|
{ m_sao = sao; }
|
||||||
|
void setPosition(const v3f &position);
|
||||||
|
|
||||||
|
private:
|
||||||
|
PlayerSAO *m_sao;
|
||||||
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -35,7 +35,7 @@ extern "C" {
|
||||||
#include "script.h"
|
#include "script.h"
|
||||||
//#include "luna.h"
|
//#include "luna.h"
|
||||||
#include "luaentity_common.h"
|
#include "luaentity_common.h"
|
||||||
#include "content_sao.h" // For LuaEntitySAO
|
#include "content_sao.h" // For LuaEntitySAO and PlayerSAO
|
||||||
#include "itemdef.h"
|
#include "itemdef.h"
|
||||||
#include "nodedef.h"
|
#include "nodedef.h"
|
||||||
#include "craftdef.h"
|
#include "craftdef.h"
|
||||||
|
@ -1095,7 +1095,6 @@ static ItemStack read_item(lua_State *L, int index);
|
||||||
static void inventory_set_list_from_lua(Inventory *inv, const char *name,
|
static void inventory_set_list_from_lua(Inventory *inv, const char *name,
|
||||||
lua_State *L, int tableindex, int forcesize=-1)
|
lua_State *L, int tableindex, int forcesize=-1)
|
||||||
{
|
{
|
||||||
dstream<<"inventory_set_list_from_lua\n";
|
|
||||||
if(tableindex < 0)
|
if(tableindex < 0)
|
||||||
tableindex = lua_gettop(L) + 1 + tableindex;
|
tableindex = lua_gettop(L) + 1 + tableindex;
|
||||||
// If nil, delete list
|
// If nil, delete list
|
||||||
|
@ -1127,7 +1126,6 @@ static void inventory_set_list_from_lua(Inventory *inv, const char *name,
|
||||||
invlist->deleteItem(index);
|
invlist->deleteItem(index);
|
||||||
index++;
|
index++;
|
||||||
}
|
}
|
||||||
dstream<<"inventory_set_list_from_lua done\n";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void inventory_get_list_to_lua(Inventory *inv, const char *name,
|
static void inventory_get_list_to_lua(Inventory *inv, const char *name,
|
||||||
|
@ -2259,14 +2257,22 @@ private:
|
||||||
return (LuaEntitySAO*)obj;
|
return (LuaEntitySAO*)obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
static ServerRemotePlayer* getplayer(ObjectRef *ref)
|
static PlayerSAO* getplayersao(ObjectRef *ref)
|
||||||
{
|
{
|
||||||
ServerActiveObject *obj = getobject(ref);
|
ServerActiveObject *obj = getobject(ref);
|
||||||
if(obj == NULL)
|
if(obj == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
if(obj->getType() != ACTIVEOBJECT_TYPE_PLAYER)
|
if(obj->getType() != ACTIVEOBJECT_TYPE_PLAYER)
|
||||||
return NULL;
|
return NULL;
|
||||||
return static_cast<ServerRemotePlayer*>(obj);
|
return (PlayerSAO*)obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Player* getplayer(ObjectRef *ref)
|
||||||
|
{
|
||||||
|
PlayerSAO *playersao = getplayersao(ref);
|
||||||
|
if(playersao == NULL)
|
||||||
|
return NULL;
|
||||||
|
return playersao->getPlayer();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Exported functions
|
// Exported functions
|
||||||
|
@ -2319,10 +2325,6 @@ private:
|
||||||
v3f pos = checkFloatPos(L, 2);
|
v3f pos = checkFloatPos(L, 2);
|
||||||
// Do it
|
// Do it
|
||||||
co->setPos(pos);
|
co->setPos(pos);
|
||||||
// Move player if applicable
|
|
||||||
ServerRemotePlayer *player = getplayer(ref);
|
|
||||||
if(player != NULL)
|
|
||||||
get_server(L)->SendMovePlayer(player);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2626,7 +2628,7 @@ private:
|
||||||
static int l_get_player_name(lua_State *L)
|
static int l_get_player_name(lua_State *L)
|
||||||
{
|
{
|
||||||
ObjectRef *ref = checkobject(L, 1);
|
ObjectRef *ref = checkobject(L, 1);
|
||||||
ServerRemotePlayer *player = getplayer(ref);
|
Player *player = getplayer(ref);
|
||||||
if(player == NULL){
|
if(player == NULL){
|
||||||
lua_pushnil(L);
|
lua_pushnil(L);
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -2640,7 +2642,7 @@ private:
|
||||||
static int l_get_look_dir(lua_State *L)
|
static int l_get_look_dir(lua_State *L)
|
||||||
{
|
{
|
||||||
ObjectRef *ref = checkobject(L, 1);
|
ObjectRef *ref = checkobject(L, 1);
|
||||||
ServerRemotePlayer *player = getplayer(ref);
|
Player *player = getplayer(ref);
|
||||||
if(player == NULL) return 0;
|
if(player == NULL) return 0;
|
||||||
// Do it
|
// Do it
|
||||||
float pitch = player->getRadPitch();
|
float pitch = player->getRadPitch();
|
||||||
|
@ -2654,7 +2656,7 @@ private:
|
||||||
static int l_get_look_pitch(lua_State *L)
|
static int l_get_look_pitch(lua_State *L)
|
||||||
{
|
{
|
||||||
ObjectRef *ref = checkobject(L, 1);
|
ObjectRef *ref = checkobject(L, 1);
|
||||||
ServerRemotePlayer *player = getplayer(ref);
|
Player *player = getplayer(ref);
|
||||||
if(player == NULL) return 0;
|
if(player == NULL) return 0;
|
||||||
// Do it
|
// Do it
|
||||||
lua_pushnumber(L, player->getRadPitch());
|
lua_pushnumber(L, player->getRadPitch());
|
||||||
|
@ -2665,7 +2667,7 @@ private:
|
||||||
static int l_get_look_yaw(lua_State *L)
|
static int l_get_look_yaw(lua_State *L)
|
||||||
{
|
{
|
||||||
ObjectRef *ref = checkobject(L, 1);
|
ObjectRef *ref = checkobject(L, 1);
|
||||||
ServerRemotePlayer *player = getplayer(ref);
|
Player *player = getplayer(ref);
|
||||||
if(player == NULL) return 0;
|
if(player == NULL) return 0;
|
||||||
// Do it
|
// Do it
|
||||||
lua_pushnumber(L, player->getRadYaw());
|
lua_pushnumber(L, player->getRadYaw());
|
||||||
|
@ -2996,14 +2998,18 @@ private:
|
||||||
if(env == NULL) return 0;
|
if(env == NULL) return 0;
|
||||||
// Do it
|
// Do it
|
||||||
const char *name = luaL_checkstring(L, 2);
|
const char *name = luaL_checkstring(L, 2);
|
||||||
ServerRemotePlayer *player =
|
Player *player = env->getPlayer(name);
|
||||||
static_cast<ServerRemotePlayer*>(env->getPlayer(name));
|
|
||||||
if(player == NULL){
|
if(player == NULL){
|
||||||
lua_pushnil(L);
|
lua_pushnil(L);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
PlayerSAO *sao = player->getPlayerSAO();
|
||||||
|
if(sao == NULL){
|
||||||
|
lua_pushnil(L);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
// Put player on stack
|
// Put player on stack
|
||||||
objectref_get_or_create(L, player);
|
objectref_get_or_create(L, sao);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4211,8 +4217,6 @@ bool scriptapi_on_respawnplayer(lua_State *L, ServerActiveObject *player)
|
||||||
assert(lua_checkstack(L, 20));
|
assert(lua_checkstack(L, 20));
|
||||||
StackUnroller stack_unroller(L);
|
StackUnroller stack_unroller(L);
|
||||||
|
|
||||||
dstream<<"player: "<<player<<" id: "<<player->getId()<<std::endl;
|
|
||||||
|
|
||||||
bool positioning_handled_by_some = false;
|
bool positioning_handled_by_some = false;
|
||||||
|
|
||||||
// Get minetest.registered_on_respawnplayers
|
// Get minetest.registered_on_respawnplayers
|
||||||
|
@ -4238,13 +4242,15 @@ bool scriptapi_on_respawnplayer(lua_State *L, ServerActiveObject *player)
|
||||||
return positioning_handled_by_some;
|
return positioning_handled_by_some;
|
||||||
}
|
}
|
||||||
|
|
||||||
void scriptapi_get_creative_inventory(lua_State *L, ServerRemotePlayer *player)
|
void scriptapi_get_creative_inventory(lua_State *L, ServerActiveObject *player)
|
||||||
{
|
{
|
||||||
|
Inventory *inv = player->getInventory();
|
||||||
|
assert(inv);
|
||||||
|
|
||||||
lua_getglobal(L, "minetest");
|
lua_getglobal(L, "minetest");
|
||||||
lua_getfield(L, -1, "creative_inventory");
|
lua_getfield(L, -1, "creative_inventory");
|
||||||
luaL_checktype(L, -1, LUA_TTABLE);
|
luaL_checktype(L, -1, LUA_TTABLE);
|
||||||
inventory_set_list_from_lua(&player->inventory, "main", L, -1,
|
inventory_set_list_from_lua(inv, "main", L, -1, PLAYER_INVENTORY_SIZE);
|
||||||
PLAYER_INVENTORY_SIZE);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -27,7 +27,6 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
class Server;
|
class Server;
|
||||||
class ServerEnvironment;
|
class ServerEnvironment;
|
||||||
class ServerActiveObject;
|
class ServerActiveObject;
|
||||||
class ServerRemotePlayer;
|
|
||||||
typedef struct lua_State lua_State;
|
typedef struct lua_State lua_State;
|
||||||
struct LuaEntityProperties;
|
struct LuaEntityProperties;
|
||||||
struct ItemStack;
|
struct ItemStack;
|
||||||
|
@ -58,7 +57,7 @@ void scriptapi_environment_on_generated(lua_State *L, v3s16 minp, v3s16 maxp,
|
||||||
void scriptapi_on_newplayer(lua_State *L, ServerActiveObject *player);
|
void scriptapi_on_newplayer(lua_State *L, ServerActiveObject *player);
|
||||||
void scriptapi_on_dieplayer(lua_State *L, ServerActiveObject *player);
|
void scriptapi_on_dieplayer(lua_State *L, ServerActiveObject *player);
|
||||||
bool scriptapi_on_respawnplayer(lua_State *L, ServerActiveObject *player);
|
bool scriptapi_on_respawnplayer(lua_State *L, ServerActiveObject *player);
|
||||||
void scriptapi_get_creative_inventory(lua_State *L, ServerRemotePlayer *player);
|
void scriptapi_get_creative_inventory(lua_State *L, ServerActiveObject *player);
|
||||||
|
|
||||||
/* item callbacks */
|
/* item callbacks */
|
||||||
bool scriptapi_item_on_drop(lua_State *L, ItemStack &item,
|
bool scriptapi_item_on_drop(lua_State *L, ItemStack &item,
|
||||||
|
|
447
src/server.cpp
447
src/server.cpp
|
@ -30,8 +30,6 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "servercommand.h"
|
#include "servercommand.h"
|
||||||
#include "filesys.h"
|
#include "filesys.h"
|
||||||
#include "content_mapnode.h"
|
|
||||||
#include "content_nodemeta.h"
|
|
||||||
#include "mapblock.h"
|
#include "mapblock.h"
|
||||||
#include "serverobject.h"
|
#include "serverobject.h"
|
||||||
#include "settings.h"
|
#include "settings.h"
|
||||||
|
@ -43,7 +41,10 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
#include "itemdef.h"
|
#include "itemdef.h"
|
||||||
#include "craftdef.h"
|
#include "craftdef.h"
|
||||||
#include "mapgen.h"
|
#include "mapgen.h"
|
||||||
|
#include "content_mapnode.h"
|
||||||
|
#include "content_nodemeta.h"
|
||||||
#include "content_abm.h"
|
#include "content_abm.h"
|
||||||
|
#include "content_sao.h"
|
||||||
#include "mods.h"
|
#include "mods.h"
|
||||||
#include "sha1.h"
|
#include "sha1.h"
|
||||||
#include "base64.h"
|
#include "base64.h"
|
||||||
|
@ -379,6 +380,27 @@ void * EmergeThread::Thread()
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
v3f ServerSoundParams::getPos(ServerEnvironment *env, bool *pos_exists) const
|
||||||
|
{
|
||||||
|
if(pos_exists) *pos_exists = false;
|
||||||
|
switch(type){
|
||||||
|
case SSP_LOCAL:
|
||||||
|
return v3f(0,0,0);
|
||||||
|
case SSP_POSITIONAL:
|
||||||
|
if(pos_exists) *pos_exists = true;
|
||||||
|
return pos;
|
||||||
|
case SSP_OBJECT: {
|
||||||
|
if(object == 0)
|
||||||
|
return v3f(0,0,0);
|
||||||
|
ServerActiveObject *sao = env->getActiveObject(object);
|
||||||
|
if(!sao)
|
||||||
|
return v3f(0,0,0);
|
||||||
|
if(pos_exists) *pos_exists = true;
|
||||||
|
return sao->getBasePosition(); }
|
||||||
|
}
|
||||||
|
return v3f(0,0,0);
|
||||||
|
}
|
||||||
|
|
||||||
void RemoteClient::GetNextBlocks(Server *server, float dtime,
|
void RemoteClient::GetNextBlocks(Server *server, float dtime,
|
||||||
core::array<PrioritySortedBlockTransfer> &dest)
|
core::array<PrioritySortedBlockTransfer> &dest)
|
||||||
{
|
{
|
||||||
|
@ -1250,8 +1272,6 @@ void Server::AsyncRunStep()
|
||||||
i.atEnd() == false; i++)
|
i.atEnd() == false; i++)
|
||||||
{
|
{
|
||||||
RemoteClient *client = i.getNode()->getValue();
|
RemoteClient *client = i.getNode()->getValue();
|
||||||
//Player *player = m_env->getPlayer(client->peer_id);
|
|
||||||
|
|
||||||
SharedBuffer<u8> data = makePacket_TOCLIENT_TIME_OF_DAY(
|
SharedBuffer<u8> data = makePacket_TOCLIENT_TIME_OF_DAY(
|
||||||
m_env->getTimeOfDay(), g_settings->getFloat("time_speed"));
|
m_env->getTimeOfDay(), g_settings->getFloat("time_speed"));
|
||||||
// Send as reliable
|
// Send as reliable
|
||||||
|
@ -1291,78 +1311,36 @@ void Server::AsyncRunStep()
|
||||||
|
|
||||||
ScopeProfiler sp(g_profiler, "Server: handle players");
|
ScopeProfiler sp(g_profiler, "Server: handle players");
|
||||||
|
|
||||||
//float player_max_speed = BS * 4.0; // Normal speed
|
|
||||||
float player_max_speed = BS * 20; // Fast speed
|
|
||||||
float player_max_speed_up = BS * 20;
|
|
||||||
|
|
||||||
player_max_speed *= 2.5; // Tolerance
|
|
||||||
player_max_speed_up *= 2.5;
|
|
||||||
|
|
||||||
for(core::map<u16, RemoteClient*>::Iterator
|
for(core::map<u16, RemoteClient*>::Iterator
|
||||||
i = m_clients.getIterator();
|
i = m_clients.getIterator();
|
||||||
i.atEnd() == false; i++)
|
i.atEnd() == false; i++)
|
||||||
{
|
{
|
||||||
RemoteClient *client = i.getNode()->getValue();
|
RemoteClient *client = i.getNode()->getValue();
|
||||||
ServerRemotePlayer *player =
|
PlayerSAO *playersao = getPlayerSAO(client->peer_id);
|
||||||
static_cast<ServerRemotePlayer*>
|
if(playersao == NULL){
|
||||||
(m_env->getPlayer(client->peer_id));
|
errorstream<<"Handling client without PlayerSAO, peer_id="<<client->peer_id<<std::endl;
|
||||||
if(player==NULL)
|
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
/*
|
|
||||||
Check player movements
|
|
||||||
|
|
||||||
NOTE: Actually the server should handle player physics like the
|
|
||||||
client does and compare player's position to what is calculated
|
|
||||||
on our side. This is required when eg. players fly due to an
|
|
||||||
explosion.
|
|
||||||
*/
|
|
||||||
player->m_last_good_position_age += dtime;
|
|
||||||
if(player->m_last_good_position_age >= 1.0){
|
|
||||||
float age = player->m_last_good_position_age;
|
|
||||||
v3f diff = (player->getPosition() - player->m_last_good_position);
|
|
||||||
float d_vert = diff.Y;
|
|
||||||
diff.Y = 0;
|
|
||||||
float d_horiz = diff.getLength();
|
|
||||||
/*infostream<<player->getName()<<"'s horizontal speed is "
|
|
||||||
<<(d_horiz/age)<<std::endl;*/
|
|
||||||
if(d_horiz <= age * player_max_speed &&
|
|
||||||
(d_vert < 0 || d_vert < age * player_max_speed_up)){
|
|
||||||
player->m_last_good_position = player->getPosition();
|
|
||||||
} else {
|
|
||||||
actionstream<<"Player "<<player->getName()
|
|
||||||
<<" moved too fast; resetting position"
|
|
||||||
<<std::endl;
|
|
||||||
player->setPosition(player->m_last_good_position);
|
|
||||||
SendMovePlayer(player);
|
|
||||||
}
|
|
||||||
player->m_last_good_position_age = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Handle player HPs (die if hp=0)
|
Handle player HPs (die if hp=0)
|
||||||
*/
|
*/
|
||||||
if(player->hp == 0 && player->m_hp_not_sent)
|
if(playersao->getHP() == 0 && playersao->m_hp_not_sent)
|
||||||
DiePlayer(player);
|
DiePlayer(client->peer_id);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Send player inventories and HPs if necessary
|
Send player inventories and HPs if necessary
|
||||||
*/
|
*/
|
||||||
if(player->m_inventory_not_sent){
|
if(playersao->m_teleported){
|
||||||
UpdateCrafting(player->peer_id);
|
SendMovePlayer(client->peer_id);
|
||||||
SendInventory(player->peer_id);
|
playersao->m_teleported = false;
|
||||||
}
|
}
|
||||||
if(player->m_hp_not_sent){
|
if(playersao->m_inventory_not_sent){
|
||||||
SendPlayerHP(player);
|
UpdateCrafting(client->peer_id);
|
||||||
|
SendInventory(client->peer_id);
|
||||||
}
|
}
|
||||||
|
if(playersao->m_hp_not_sent){
|
||||||
/*
|
SendPlayerHP(client->peer_id);
|
||||||
Add to environment
|
|
||||||
*/
|
|
||||||
if(!player->m_is_in_environment){
|
|
||||||
player->m_removed = false;
|
|
||||||
player->setId(0);
|
|
||||||
m_env->addActiveObject(player);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2167,10 +2145,10 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get player
|
// Get player
|
||||||
ServerRemotePlayer *player = emergePlayer(playername, peer_id);
|
PlayerSAO *playersao = emergePlayer(playername, peer_id);
|
||||||
|
|
||||||
// If failed, cancel
|
// If failed, cancel
|
||||||
if(player == NULL)
|
if(playersao == NULL)
|
||||||
{
|
{
|
||||||
errorstream<<"Server: peer_id="<<peer_id
|
errorstream<<"Server: peer_id="<<peer_id
|
||||||
<<": failed to emerge player"<<std::endl;
|
<<": failed to emerge player"<<std::endl;
|
||||||
|
@ -2184,7 +2162,7 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
|
||||||
SharedBuffer<u8> reply(2+1+6+8);
|
SharedBuffer<u8> reply(2+1+6+8);
|
||||||
writeU16(&reply[0], TOCLIENT_INIT);
|
writeU16(&reply[0], TOCLIENT_INIT);
|
||||||
writeU8(&reply[2], deployed);
|
writeU8(&reply[2], deployed);
|
||||||
writeV3S16(&reply[2+1], floatToInt(player->getPosition()+v3f(0,BS/2,0), BS));
|
writeV3S16(&reply[2+1], floatToInt(playersao->getPlayer()->getPosition()+v3f(0,BS/2,0), BS));
|
||||||
writeU64(&reply[2+1+6], m_env->getServerMap().getSeed());
|
writeU64(&reply[2+1+6], m_env->getServerMap().getSeed());
|
||||||
|
|
||||||
// Send as reliable
|
// Send as reliable
|
||||||
|
@ -2194,7 +2172,7 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
|
||||||
/*
|
/*
|
||||||
Send complete position information
|
Send complete position information
|
||||||
*/
|
*/
|
||||||
SendMovePlayer(player);
|
SendMovePlayer(peer_id);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -2231,17 +2209,14 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
|
||||||
UpdateCrafting(peer_id);
|
UpdateCrafting(peer_id);
|
||||||
SendInventory(peer_id);
|
SendInventory(peer_id);
|
||||||
|
|
||||||
// Send player items to all players
|
|
||||||
SendPlayerItems();
|
|
||||||
|
|
||||||
Player *player = m_env->getPlayer(peer_id);
|
Player *player = m_env->getPlayer(peer_id);
|
||||||
|
|
||||||
// Send HP
|
// Send HP
|
||||||
SendPlayerHP(player);
|
SendPlayerHP(peer_id);
|
||||||
|
|
||||||
// Show death screen if necessary
|
// Show death screen if necessary
|
||||||
if(player->hp == 0)
|
if(player->hp == 0)
|
||||||
SendDeathscreen(m_con, player->peer_id, false, v3f(0,0,0));
|
SendDeathscreen(m_con, peer_id, false, v3f(0,0,0));
|
||||||
|
|
||||||
// Send time of day
|
// Send time of day
|
||||||
{
|
{
|
||||||
|
@ -2314,14 +2289,21 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
|
||||||
}
|
}
|
||||||
|
|
||||||
Player *player = m_env->getPlayer(peer_id);
|
Player *player = m_env->getPlayer(peer_id);
|
||||||
ServerRemotePlayer *srp = static_cast<ServerRemotePlayer*>(player);
|
|
||||||
|
|
||||||
if(player == NULL){
|
if(player == NULL){
|
||||||
infostream<<"Server::ProcessData(): Cancelling: "
|
infostream<<"Server::ProcessData(): Cancelling: "
|
||||||
"No player for peer_id="<<peer_id
|
"No player for peer_id="<<peer_id
|
||||||
<<std::endl;
|
<<std::endl;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PlayerSAO *playersao = player->getPlayerSAO();
|
||||||
|
if(playersao == NULL){
|
||||||
|
infostream<<"Server::ProcessData(): Cancelling: "
|
||||||
|
"No player object for peer_id="<<peer_id
|
||||||
|
<<std::endl;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if(command == TOSERVER_PLAYERPOS)
|
if(command == TOSERVER_PLAYERPOS)
|
||||||
{
|
{
|
||||||
if(datasize < 2+12+12+4+4)
|
if(datasize < 2+12+12+4+4)
|
||||||
|
@ -2644,7 +2626,7 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Do the action
|
// Do the action
|
||||||
a->apply(this, srp, this);
|
a->apply(this, playersao, this);
|
||||||
// Eat the action
|
// Eat the action
|
||||||
delete a;
|
delete a;
|
||||||
}
|
}
|
||||||
|
@ -2775,27 +2757,17 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
|
||||||
std::istringstream is(datastring, std::ios_base::binary);
|
std::istringstream is(datastring, std::ios_base::binary);
|
||||||
u8 damage = readU8(is);
|
u8 damage = readU8(is);
|
||||||
|
|
||||||
ServerRemotePlayer *srp = static_cast<ServerRemotePlayer*>(player);
|
actionstream<<player->getName()<<" damaged by "
|
||||||
|
<<(int)damage<<" hp at "<<PP(player->getPosition()/BS)
|
||||||
|
<<std::endl;
|
||||||
|
|
||||||
if(g_settings->getBool("enable_damage"))
|
playersao->setHP(playersao->getHP() - damage);
|
||||||
{
|
|
||||||
actionstream<<player->getName()<<" damaged by "
|
|
||||||
<<(int)damage<<" hp at "<<PP(player->getPosition()/BS)
|
|
||||||
<<std::endl;
|
|
||||||
|
|
||||||
srp->setHP(srp->getHP() - damage);
|
if(playersao->getHP() == 0 && playersao->m_hp_not_sent)
|
||||||
|
DiePlayer(peer_id);
|
||||||
|
|
||||||
if(srp->getHP() == 0 && srp->m_hp_not_sent)
|
if(playersao->m_hp_not_sent)
|
||||||
DiePlayer(srp);
|
SendPlayerHP(peer_id);
|
||||||
|
|
||||||
if(srp->m_hp_not_sent)
|
|
||||||
SendPlayerHP(player);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Force send (to correct the client's predicted HP)
|
|
||||||
SendPlayerHP(player);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else if(command == TOSERVER_PASSWORD)
|
else if(command == TOSERVER_PASSWORD)
|
||||||
{
|
{
|
||||||
|
@ -2865,15 +2837,14 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
u16 item = readU16(&data[2]);
|
u16 item = readU16(&data[2]);
|
||||||
srp->setWieldIndex(item);
|
playersao->setWieldIndex(item);
|
||||||
SendWieldedItem(srp);
|
|
||||||
}
|
}
|
||||||
else if(command == TOSERVER_RESPAWN)
|
else if(command == TOSERVER_RESPAWN)
|
||||||
{
|
{
|
||||||
if(player->hp != 0)
|
if(player->hp != 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
RespawnPlayer(player);
|
RespawnPlayer(peer_id);
|
||||||
|
|
||||||
actionstream<<player->getName()<<" respawns at "
|
actionstream<<player->getName()<<" respawns at "
|
||||||
<<PP(player->getPosition()/BS)<<std::endl;
|
<<PP(player->getPosition()/BS)<<std::endl;
|
||||||
|
@ -2934,19 +2905,15 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
|
||||||
|
|
||||||
if(player->hp == 0)
|
if(player->hp == 0)
|
||||||
{
|
{
|
||||||
verbosestream<<"TOSERVER_INTERACT: "<<srp->getName()
|
verbosestream<<"TOSERVER_INTERACT: "<<player->getName()
|
||||||
<<" tried to interact, but is dead!"<<std::endl;
|
<<" tried to interact, but is dead!"<<std::endl;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
v3f player_pos = srp->m_last_good_position;
|
v3f player_pos = playersao->getLastGoodPosition();
|
||||||
|
|
||||||
// Update wielded item
|
// Update wielded item
|
||||||
if(srp->getWieldIndex() != item_i)
|
playersao->setWieldIndex(item_i);
|
||||||
{
|
|
||||||
srp->setWieldIndex(item_i);
|
|
||||||
SendWieldedItem(srp);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get pointed to node (undefined if not POINTEDTYPE_NODE)
|
// Get pointed to node (undefined if not POINTEDTYPE_NODE)
|
||||||
v3s16 p_under = pointed.node_undersurface;
|
v3s16 p_under = pointed.node_undersurface;
|
||||||
|
@ -3038,7 +3005,7 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
|
||||||
getNodeBlockPos(p_above), BLOCK_EMERGE_FLAG_FROMDISK);
|
getNodeBlockPos(p_above), BLOCK_EMERGE_FLAG_FROMDISK);
|
||||||
}
|
}
|
||||||
if(n.getContent() != CONTENT_IGNORE)
|
if(n.getContent() != CONTENT_IGNORE)
|
||||||
scriptapi_node_on_punch(m_lua, p_under, n, srp);
|
scriptapi_node_on_punch(m_lua, p_under, n, playersao);
|
||||||
}
|
}
|
||||||
else if(pointed.type == POINTEDTHING_OBJECT)
|
else if(pointed.type == POINTEDTHING_OBJECT)
|
||||||
{
|
{
|
||||||
|
@ -3050,15 +3017,16 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
|
||||||
<<pointed.object_id<<": "
|
<<pointed.object_id<<": "
|
||||||
<<pointed_object->getDescription()<<std::endl;
|
<<pointed_object->getDescription()<<std::endl;
|
||||||
|
|
||||||
ItemStack punchitem = srp->getWieldedItem();
|
ItemStack punchitem = playersao->getWieldedItem();
|
||||||
ToolCapabilities toolcap =
|
ToolCapabilities toolcap =
|
||||||
punchitem.getToolCapabilities(m_itemdef);
|
punchitem.getToolCapabilities(m_itemdef);
|
||||||
v3f dir = (pointed_object->getBasePosition() -
|
v3f dir = (pointed_object->getBasePosition() -
|
||||||
(srp->getPosition() + srp->getEyeOffset())
|
(player->getPosition() + player->getEyeOffset())
|
||||||
).normalize();
|
).normalize();
|
||||||
pointed_object->punch(dir, &toolcap, srp,
|
float time_from_last_punch =
|
||||||
srp->m_time_from_last_punch);
|
playersao->resetTimeFromLastPunch();
|
||||||
srp->m_time_from_last_punch = 0;
|
pointed_object->punch(dir, &toolcap, playersao,
|
||||||
|
time_from_last_punch);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // action == 0
|
} // action == 0
|
||||||
|
@ -3092,7 +3060,7 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
|
||||||
getNodeBlockPos(p_above), BLOCK_EMERGE_FLAG_FROMDISK);
|
getNodeBlockPos(p_above), BLOCK_EMERGE_FLAG_FROMDISK);
|
||||||
}
|
}
|
||||||
if(n.getContent() != CONTENT_IGNORE)
|
if(n.getContent() != CONTENT_IGNORE)
|
||||||
scriptapi_node_on_dig(m_lua, p_under, n, srp);
|
scriptapi_node_on_dig(m_lua, p_under, n, playersao);
|
||||||
}
|
}
|
||||||
} // action == 2
|
} // action == 2
|
||||||
|
|
||||||
|
@ -3101,7 +3069,7 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
|
||||||
*/
|
*/
|
||||||
else if(action == 3)
|
else if(action == 3)
|
||||||
{
|
{
|
||||||
ItemStack item = srp->getWieldedItem();
|
ItemStack item = playersao->getWieldedItem();
|
||||||
|
|
||||||
// Reset build time counter
|
// Reset build time counter
|
||||||
if(pointed.type == POINTEDTHING_NODE &&
|
if(pointed.type == POINTEDTHING_NODE &&
|
||||||
|
@ -3121,16 +3089,16 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
|
||||||
<<pointed_object->getDescription()<<std::endl;
|
<<pointed_object->getDescription()<<std::endl;
|
||||||
|
|
||||||
// Do stuff
|
// Do stuff
|
||||||
pointed_object->rightClick(srp);
|
pointed_object->rightClick(playersao);
|
||||||
}
|
}
|
||||||
else if(scriptapi_item_on_place(m_lua,
|
else if(scriptapi_item_on_place(m_lua,
|
||||||
item, srp, pointed))
|
item, playersao, pointed))
|
||||||
{
|
{
|
||||||
// Placement was handled in lua
|
// Placement was handled in lua
|
||||||
|
|
||||||
// Apply returned ItemStack
|
// Apply returned ItemStack
|
||||||
if(g_settings->getBool("creative_mode") == false)
|
if(g_settings->getBool("creative_mode") == false)
|
||||||
srp->setWieldedItem(item);
|
playersao->setWieldedItem(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // action == 3
|
} // action == 3
|
||||||
|
@ -3140,17 +3108,17 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
|
||||||
*/
|
*/
|
||||||
else if(action == 4)
|
else if(action == 4)
|
||||||
{
|
{
|
||||||
ItemStack item = srp->getWieldedItem();
|
ItemStack item = playersao->getWieldedItem();
|
||||||
|
|
||||||
actionstream<<player->getName()<<" uses "<<item.name
|
actionstream<<player->getName()<<" uses "<<item.name
|
||||||
<<", pointing at "<<pointed.dump()<<std::endl;
|
<<", pointing at "<<pointed.dump()<<std::endl;
|
||||||
|
|
||||||
if(scriptapi_item_on_use(m_lua,
|
if(scriptapi_item_on_use(m_lua,
|
||||||
item, srp, pointed))
|
item, playersao, pointed))
|
||||||
{
|
{
|
||||||
// Apply returned ItemStack
|
// Apply returned ItemStack
|
||||||
if(g_settings->getBool("creative_mode") == false)
|
if(g_settings->getBool("creative_mode") == false)
|
||||||
srp->setWieldedItem(item);
|
playersao->setWieldedItem(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // action == 4
|
} // action == 4
|
||||||
|
@ -3222,7 +3190,10 @@ Inventory* Server::getInventory(const InventoryLocation &loc)
|
||||||
Player *player = m_env->getPlayer(loc.name.c_str());
|
Player *player = m_env->getPlayer(loc.name.c_str());
|
||||||
if(!player)
|
if(!player)
|
||||||
return NULL;
|
return NULL;
|
||||||
return &player->inventory;
|
PlayerSAO *playersao = player->getPlayerSAO();
|
||||||
|
if(!playersao)
|
||||||
|
return NULL;
|
||||||
|
return playersao->getInventory();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case InventoryLocation::NODEMETA:
|
case InventoryLocation::NODEMETA:
|
||||||
|
@ -3273,11 +3244,14 @@ void Server::setInventoryModified(const InventoryLocation &loc)
|
||||||
break;
|
break;
|
||||||
case InventoryLocation::PLAYER:
|
case InventoryLocation::PLAYER:
|
||||||
{
|
{
|
||||||
ServerRemotePlayer *srp = static_cast<ServerRemotePlayer*>
|
Player *player = m_env->getPlayer(loc.name.c_str());
|
||||||
(m_env->getPlayer(loc.name.c_str()));
|
if(!player)
|
||||||
if(!srp)
|
|
||||||
return;
|
return;
|
||||||
srp->m_inventory_not_sent = true;
|
PlayerSAO *playersao = player->getPlayerSAO();
|
||||||
|
if(!playersao)
|
||||||
|
return;
|
||||||
|
playersao->m_inventory_not_sent = true;
|
||||||
|
playersao->m_wielded_item_not_sent = true;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case InventoryLocation::NODEMETA:
|
case InventoryLocation::NODEMETA:
|
||||||
|
@ -3482,20 +3456,17 @@ void Server::SendInventory(u16 peer_id)
|
||||||
{
|
{
|
||||||
DSTACK(__FUNCTION_NAME);
|
DSTACK(__FUNCTION_NAME);
|
||||||
|
|
||||||
ServerRemotePlayer* player =
|
PlayerSAO *playersao = getPlayerSAO(peer_id);
|
||||||
static_cast<ServerRemotePlayer*>(m_env->getPlayer(peer_id));
|
assert(playersao);
|
||||||
assert(player);
|
|
||||||
|
|
||||||
player->m_inventory_not_sent = false;
|
playersao->m_inventory_not_sent = false;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Serialize it
|
Serialize it
|
||||||
*/
|
*/
|
||||||
|
|
||||||
std::ostringstream os;
|
std::ostringstream os;
|
||||||
//os.imbue(std::locale("C"));
|
playersao->getInventory()->serialize(os);
|
||||||
|
|
||||||
player->inventory.serialize(os);
|
|
||||||
|
|
||||||
std::string s = os.str();
|
std::string s = os.str();
|
||||||
|
|
||||||
|
@ -3507,52 +3478,6 @@ void Server::SendInventory(u16 peer_id)
|
||||||
m_con.Send(peer_id, 0, data, true);
|
m_con.Send(peer_id, 0, data, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Server::SendWieldedItem(const ServerRemotePlayer* srp)
|
|
||||||
{
|
|
||||||
DSTACK(__FUNCTION_NAME);
|
|
||||||
|
|
||||||
assert(srp);
|
|
||||||
|
|
||||||
std::ostringstream os(std::ios_base::binary);
|
|
||||||
|
|
||||||
writeU16(os, TOCLIENT_PLAYERITEM);
|
|
||||||
writeU16(os, 1);
|
|
||||||
writeU16(os, srp->peer_id);
|
|
||||||
os<<serializeString(srp->getWieldedItem().getItemString());
|
|
||||||
|
|
||||||
// Make data buffer
|
|
||||||
std::string s = os.str();
|
|
||||||
SharedBuffer<u8> data((u8*)s.c_str(), s.size());
|
|
||||||
|
|
||||||
m_con.SendToAll(0, data, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Server::SendPlayerItems()
|
|
||||||
{
|
|
||||||
DSTACK(__FUNCTION_NAME);
|
|
||||||
|
|
||||||
std::ostringstream os(std::ios_base::binary);
|
|
||||||
core::list<Player *> players = m_env->getPlayers(true);
|
|
||||||
|
|
||||||
writeU16(os, TOCLIENT_PLAYERITEM);
|
|
||||||
writeU16(os, players.size());
|
|
||||||
core::list<Player *>::Iterator i;
|
|
||||||
for(i = players.begin(); i != players.end(); ++i)
|
|
||||||
{
|
|
||||||
Player *p = *i;
|
|
||||||
ServerRemotePlayer *srp =
|
|
||||||
static_cast<ServerRemotePlayer*>(p);
|
|
||||||
writeU16(os, p->peer_id);
|
|
||||||
os<<serializeString(srp->getWieldedItem().getItemString());
|
|
||||||
}
|
|
||||||
|
|
||||||
// Make data buffer
|
|
||||||
std::string s = os.str();
|
|
||||||
SharedBuffer<u8> data((u8*)s.c_str(), s.size());
|
|
||||||
|
|
||||||
m_con.SendToAll(0, data, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Server::SendChatMessage(u16 peer_id, const std::wstring &message)
|
void Server::SendChatMessage(u16 peer_id, const std::wstring &message)
|
||||||
{
|
{
|
||||||
DSTACK(__FUNCTION_NAME);
|
DSTACK(__FUNCTION_NAME);
|
||||||
|
@ -3599,17 +3524,22 @@ void Server::BroadcastChatMessage(const std::wstring &message)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Server::SendPlayerHP(Player *player)
|
void Server::SendPlayerHP(u16 peer_id)
|
||||||
{
|
|
||||||
SendHP(m_con, player->peer_id, player->hp);
|
|
||||||
static_cast<ServerRemotePlayer*>(player)->m_hp_not_sent = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Server::SendMovePlayer(Player *player)
|
|
||||||
{
|
{
|
||||||
DSTACK(__FUNCTION_NAME);
|
DSTACK(__FUNCTION_NAME);
|
||||||
std::ostringstream os(std::ios_base::binary);
|
PlayerSAO *playersao = getPlayerSAO(peer_id);
|
||||||
|
assert(playersao);
|
||||||
|
playersao->m_hp_not_sent = false;
|
||||||
|
SendHP(m_con, peer_id, playersao->getHP());
|
||||||
|
}
|
||||||
|
|
||||||
|
void Server::SendMovePlayer(u16 peer_id)
|
||||||
|
{
|
||||||
|
DSTACK(__FUNCTION_NAME);
|
||||||
|
Player *player = m_env->getPlayer(peer_id);
|
||||||
|
assert(player);
|
||||||
|
|
||||||
|
std::ostringstream os(std::ios_base::binary);
|
||||||
writeU16(os, TOCLIENT_MOVE_PLAYER);
|
writeU16(os, TOCLIENT_MOVE_PLAYER);
|
||||||
writeV3F1000(os, player->getPosition());
|
writeV3F1000(os, player->getPosition());
|
||||||
writeF1000(os, player->getPitch());
|
writeF1000(os, player->getPitch());
|
||||||
|
@ -3630,7 +3560,7 @@ void Server::SendMovePlayer(Player *player)
|
||||||
std::string s = os.str();
|
std::string s = os.str();
|
||||||
SharedBuffer<u8> data((u8*)s.c_str(), s.size());
|
SharedBuffer<u8> data((u8*)s.c_str(), s.size());
|
||||||
// Send as reliable
|
// Send as reliable
|
||||||
m_con.Send(player->peer_id, 0, data, true);
|
m_con.Send(peer_id, 0, data, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
s32 Server::playSound(const SimpleSoundSpec &spec,
|
s32 Server::playSound(const SimpleSoundSpec &spec,
|
||||||
|
@ -4242,41 +4172,44 @@ void Server::sendRequestedMedia(u16 peer_id,
|
||||||
Something random
|
Something random
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void Server::DiePlayer(Player *player)
|
void Server::DiePlayer(u16 peer_id)
|
||||||
{
|
{
|
||||||
ServerRemotePlayer *srp = static_cast<ServerRemotePlayer*>(player);
|
DSTACK(__FUNCTION_NAME);
|
||||||
|
|
||||||
|
PlayerSAO *playersao = getPlayerSAO(peer_id);
|
||||||
|
assert(playersao);
|
||||||
|
|
||||||
infostream<<"Server::DiePlayer(): Player "
|
infostream<<"Server::DiePlayer(): Player "
|
||||||
<<player->getName()<<" dies"<<std::endl;
|
<<playersao->getPlayer()->getName()
|
||||||
|
<<" dies"<<std::endl;
|
||||||
srp->setHP(0);
|
|
||||||
|
|
||||||
// Trigger scripted stuff
|
|
||||||
scriptapi_on_dieplayer(m_lua, srp);
|
|
||||||
|
|
||||||
// Handle players that are not connected
|
|
||||||
if(player->peer_id == PEER_ID_INEXISTENT){
|
|
||||||
RespawnPlayer(player);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
SendPlayerHP(player);
|
playersao->setHP(0);
|
||||||
SendDeathscreen(m_con, player->peer_id, false, v3f(0,0,0));
|
|
||||||
|
// Trigger scripted stuff
|
||||||
|
scriptapi_on_dieplayer(m_lua, playersao);
|
||||||
|
|
||||||
|
SendPlayerHP(peer_id);
|
||||||
|
SendDeathscreen(m_con, peer_id, false, v3f(0,0,0));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Server::RespawnPlayer(Player *player)
|
void Server::RespawnPlayer(u16 peer_id)
|
||||||
{
|
{
|
||||||
ServerRemotePlayer *srp = static_cast<ServerRemotePlayer*>(player);
|
DSTACK(__FUNCTION_NAME);
|
||||||
srp->setHP(20);
|
|
||||||
bool repositioned = scriptapi_on_respawnplayer(m_lua, srp);
|
PlayerSAO *playersao = getPlayerSAO(peer_id);
|
||||||
|
assert(playersao);
|
||||||
|
|
||||||
|
infostream<<"Server::RespawnPlayer(): Player "
|
||||||
|
<<playersao->getPlayer()->getName()
|
||||||
|
<<" respawns"<<std::endl;
|
||||||
|
|
||||||
|
playersao->setHP(PLAYER_MAX_HP);
|
||||||
|
|
||||||
|
bool repositioned = scriptapi_on_respawnplayer(m_lua, playersao);
|
||||||
if(!repositioned){
|
if(!repositioned){
|
||||||
v3f pos = findSpawnPos(m_env->getServerMap());
|
v3f pos = findSpawnPos(m_env->getServerMap());
|
||||||
player->setPosition(pos);
|
playersao->setPos(pos);
|
||||||
srp->m_last_good_position = pos;
|
|
||||||
srp->m_last_good_position_age = 0;
|
|
||||||
}
|
}
|
||||||
SendMovePlayer(player);
|
|
||||||
SendPlayerHP(player);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Server::UpdateCrafting(u16 peer_id)
|
void Server::UpdateCrafting(u16 peer_id)
|
||||||
|
@ -4542,46 +4475,21 @@ v3f findSpawnPos(ServerMap &map)
|
||||||
return intToFloat(nodepos, BS);
|
return intToFloat(nodepos, BS);
|
||||||
}
|
}
|
||||||
|
|
||||||
ServerRemotePlayer *Server::emergePlayer(const char *name, u16 peer_id)
|
PlayerSAO* Server::emergePlayer(const char *name, u16 peer_id)
|
||||||
{
|
{
|
||||||
|
RemotePlayer *player = NULL;
|
||||||
|
bool newplayer = false;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Try to get an existing player
|
Try to get an existing player
|
||||||
*/
|
*/
|
||||||
ServerRemotePlayer *player =
|
player = static_cast<RemotePlayer*>(m_env->getPlayer(name));
|
||||||
static_cast<ServerRemotePlayer*>(m_env->getPlayer(name));
|
|
||||||
if(player != NULL)
|
// If player is already connected, cancel
|
||||||
|
if(player != NULL && player->peer_id != 0)
|
||||||
{
|
{
|
||||||
// If player is already connected, cancel
|
infostream<<"emergePlayer(): Player already connected"<<std::endl;
|
||||||
if(player->peer_id != 0)
|
return NULL;
|
||||||
{
|
|
||||||
infostream<<"emergePlayer(): Player already connected"<<std::endl;
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Got one.
|
|
||||||
player->peer_id = peer_id;
|
|
||||||
|
|
||||||
// Re-add player to environment
|
|
||||||
if(player->m_removed)
|
|
||||||
{
|
|
||||||
player->m_removed = false;
|
|
||||||
player->setId(0);
|
|
||||||
m_env->addActiveObject(player);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Reset inventory to creative if in creative mode
|
|
||||||
if(g_settings->getBool("creative_mode"))
|
|
||||||
{
|
|
||||||
// Warning: double code below
|
|
||||||
// Backup actual inventory
|
|
||||||
player->inventory_backup = new Inventory(m_itemdef);
|
|
||||||
*(player->inventory_backup) = player->inventory;
|
|
||||||
// Set creative inventory
|
|
||||||
player->resetInventory();
|
|
||||||
scriptapi_get_creative_inventory(m_lua, player);
|
|
||||||
}
|
|
||||||
|
|
||||||
return player;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -4593,43 +4501,43 @@ ServerRemotePlayer *Server::emergePlayer(const char *name, u16 peer_id)
|
||||||
" peer_id already exists"<<std::endl;
|
" peer_id already exists"<<std::endl;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Create a new player
|
Create a new player if it doesn't exist yet
|
||||||
*/
|
*/
|
||||||
|
if(player == NULL)
|
||||||
{
|
{
|
||||||
|
newplayer = true;
|
||||||
|
player = new RemotePlayer(this);
|
||||||
|
player->updateName(name);
|
||||||
|
|
||||||
/* Set player position */
|
/* Set player position */
|
||||||
|
|
||||||
infostream<<"Server: Finding spawn place for player \""
|
infostream<<"Server: Finding spawn place for player \""
|
||||||
<<name<<"\""<<std::endl;
|
<<name<<"\""<<std::endl;
|
||||||
|
|
||||||
v3f pos = findSpawnPos(m_env->getServerMap());
|
v3f pos = findSpawnPos(m_env->getServerMap());
|
||||||
|
player->setPosition(pos);
|
||||||
player = new ServerRemotePlayer(m_env, pos, peer_id, name);
|
|
||||||
ServerRemotePlayer *srp = static_cast<ServerRemotePlayer*>(player);
|
|
||||||
|
|
||||||
/* Add player to environment */
|
/* Add player to environment */
|
||||||
m_env->addPlayer(player);
|
m_env->addPlayer(player);
|
||||||
m_env->addActiveObject(srp);
|
}
|
||||||
|
|
||||||
/* Run scripts */
|
/*
|
||||||
scriptapi_on_newplayer(m_lua, srp);
|
Create a new player active object
|
||||||
|
*/
|
||||||
|
PlayerSAO *playersao = new PlayerSAO(m_env, player, peer_id);
|
||||||
|
|
||||||
/* Add stuff to inventory */
|
/* Add object to environment */
|
||||||
if(g_settings->getBool("creative_mode"))
|
m_env->addActiveObject(playersao);
|
||||||
{
|
|
||||||
// Warning: double code above
|
|
||||||
// Backup actual inventory
|
|
||||||
player->inventory_backup = new Inventory(m_itemdef);
|
|
||||||
*(player->inventory_backup) = player->inventory;
|
|
||||||
// Set creative inventory
|
|
||||||
player->resetInventory();
|
|
||||||
scriptapi_get_creative_inventory(m_lua, player);
|
|
||||||
}
|
|
||||||
|
|
||||||
return player;
|
/* Run scripts */
|
||||||
|
if(newplayer)
|
||||||
} // create new player
|
scriptapi_on_newplayer(m_lua, playersao);
|
||||||
|
|
||||||
|
/* Creative mode */
|
||||||
|
if(g_settings->getBool("creative_mode"))
|
||||||
|
playersao->createCreativeInventory();
|
||||||
|
|
||||||
|
return playersao;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Server::handlePeerChange(PeerChange &c)
|
void Server::handlePeerChange(PeerChange &c)
|
||||||
|
@ -4699,8 +4607,7 @@ void Server::handlePeerChange(PeerChange &c)
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
|
|
||||||
ServerRemotePlayer* player =
|
Player *player = m_env->getPlayer(c.peer_id);
|
||||||
static_cast<ServerRemotePlayer*>(m_env->getPlayer(c.peer_id));
|
|
||||||
|
|
||||||
// Collect information about leaving in chat
|
// Collect information about leaving in chat
|
||||||
std::wstring message;
|
std::wstring message;
|
||||||
|
@ -4717,12 +4624,8 @@ void Server::handlePeerChange(PeerChange &c)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove from environment
|
// Remove from environment
|
||||||
if(player != NULL)
|
if(player->getPlayerSAO())
|
||||||
player->m_removed = true;
|
player->getPlayerSAO()->disconnected();
|
||||||
|
|
||||||
// Set player client disconnected
|
|
||||||
if(player != NULL)
|
|
||||||
player->peer_id = 0;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Print out action
|
Print out action
|
||||||
|
|
48
src/server.h
48
src/server.h
|
@ -31,7 +31,6 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
#include "ban.h"
|
#include "ban.h"
|
||||||
#include "gamedef.h"
|
#include "gamedef.h"
|
||||||
#include "serialization.h" // For SER_FMT_VER_INVALID
|
#include "serialization.h" // For SER_FMT_VER_INVALID
|
||||||
#include "serverremoteplayer.h"
|
|
||||||
#include "mods.h"
|
#include "mods.h"
|
||||||
#include "inventorymanager.h"
|
#include "inventorymanager.h"
|
||||||
#include "subgame.h"
|
#include "subgame.h"
|
||||||
|
@ -42,6 +41,7 @@ class IWritableItemDefManager;
|
||||||
class IWritableNodeDefManager;
|
class IWritableNodeDefManager;
|
||||||
class IWritableCraftDefManager;
|
class IWritableCraftDefManager;
|
||||||
class EventManager;
|
class EventManager;
|
||||||
|
class PlayerSAO;
|
||||||
|
|
||||||
class ServerError : public std::exception
|
class ServerError : public std::exception
|
||||||
{
|
{
|
||||||
|
@ -299,26 +299,7 @@ struct ServerSoundParams
|
||||||
loop(false)
|
loop(false)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
v3f getPos(ServerEnvironment *env, bool *pos_exists) const
|
v3f getPos(ServerEnvironment *env, bool *pos_exists) const;
|
||||||
{
|
|
||||||
if(pos_exists) *pos_exists = false;
|
|
||||||
switch(type){
|
|
||||||
case SSP_LOCAL:
|
|
||||||
return v3f(0,0,0);
|
|
||||||
case SSP_POSITIONAL:
|
|
||||||
if(pos_exists) *pos_exists = true;
|
|
||||||
return pos;
|
|
||||||
case SSP_OBJECT: {
|
|
||||||
if(object == 0)
|
|
||||||
return v3f(0,0,0);
|
|
||||||
ServerActiveObject *sao = env->getActiveObject(object);
|
|
||||||
if(!sao)
|
|
||||||
return v3f(0,0,0);
|
|
||||||
if(pos_exists) *pos_exists = true;
|
|
||||||
return sao->getBasePosition(); }
|
|
||||||
}
|
|
||||||
return v3f(0,0,0);
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ServerPlayingSound
|
struct ServerPlayingSound
|
||||||
|
@ -514,9 +495,6 @@ public:
|
||||||
m_shutdown_requested = true;
|
m_shutdown_requested = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Envlock and conlock should be locked when calling this
|
|
||||||
void SendMovePlayer(Player *player);
|
|
||||||
|
|
||||||
// Returns -1 if failed, sound handle on success
|
// Returns -1 if failed, sound handle on success
|
||||||
// Envlock + conlock
|
// Envlock + conlock
|
||||||
s32 playSound(const SimpleSoundSpec &spec, const ServerSoundParams ¶ms);
|
s32 playSound(const SimpleSoundSpec &spec, const ServerSoundParams ¶ms);
|
||||||
|
@ -620,14 +598,11 @@ private:
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// Envlock and conlock should be locked when calling these
|
// Envlock and conlock should be locked when calling these
|
||||||
|
void SendMovePlayer(u16 peer_id);
|
||||||
void SendInventory(u16 peer_id);
|
void SendInventory(u16 peer_id);
|
||||||
// send wielded item info about player to all
|
|
||||||
void SendWieldedItem(const ServerRemotePlayer *srp);
|
|
||||||
// send wielded item info about all players to all players
|
|
||||||
void SendPlayerItems();
|
|
||||||
void SendChatMessage(u16 peer_id, const std::wstring &message);
|
void SendChatMessage(u16 peer_id, const std::wstring &message);
|
||||||
void BroadcastChatMessage(const std::wstring &message);
|
void BroadcastChatMessage(const std::wstring &message);
|
||||||
void SendPlayerHP(Player *player);
|
void SendPlayerHP(u16 peer_id);
|
||||||
/*
|
/*
|
||||||
Send a node removal/addition event to all clients except ignore_id.
|
Send a node removal/addition event to all clients except ignore_id.
|
||||||
Additionally, if far_players!=NULL, players further away than
|
Additionally, if far_players!=NULL, players further away than
|
||||||
|
@ -655,8 +630,8 @@ private:
|
||||||
Something random
|
Something random
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void DiePlayer(Player *player);
|
void DiePlayer(u16 peer_id);
|
||||||
void RespawnPlayer(Player *player);
|
void RespawnPlayer(u16 peer_id);
|
||||||
|
|
||||||
void UpdateCrafting(u16 peer_id);
|
void UpdateCrafting(u16 peer_id);
|
||||||
|
|
||||||
|
@ -672,6 +647,15 @@ private:
|
||||||
return player->getName();
|
return player->getName();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// When called, environment mutex should be locked
|
||||||
|
PlayerSAO* getPlayerSAO(u16 peer_id)
|
||||||
|
{
|
||||||
|
Player *player = m_env->getPlayer(peer_id);
|
||||||
|
if(player == NULL)
|
||||||
|
return NULL;
|
||||||
|
return player->getPlayerSAO();
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Get a player from memory or creates one.
|
Get a player from memory or creates one.
|
||||||
If player is already connected, return NULL
|
If player is already connected, return NULL
|
||||||
|
@ -679,7 +663,7 @@ private:
|
||||||
|
|
||||||
Call with env and con locked.
|
Call with env and con locked.
|
||||||
*/
|
*/
|
||||||
ServerRemotePlayer *emergePlayer(const char *name, u16 peer_id);
|
PlayerSAO *emergePlayer(const char *name, u16 peer_id);
|
||||||
|
|
||||||
// Locks environment and connection by its own
|
// Locks environment and connection by its own
|
||||||
struct PeerChange;
|
struct PeerChange;
|
||||||
|
|
|
@ -20,6 +20,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
#include "utility.h"
|
#include "utility.h"
|
||||||
#include "settings.h"
|
#include "settings.h"
|
||||||
#include "main.h" // For g_settings
|
#include "main.h" // For g_settings
|
||||||
|
#include "content_sao.h"
|
||||||
|
|
||||||
#define PP(x) "("<<(x).X<<","<<(x).Y<<","<<(x).Z<<")"
|
#define PP(x) "("<<(x).X<<","<<(x).Y<<","<<(x).Z<<")"
|
||||||
|
|
||||||
|
@ -216,20 +217,26 @@ void cmd_teleport(std::wostringstream &os,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
v3f dest(stoi(coords[0])*10, stoi(coords[1])*10, stoi(coords[2])*10);
|
v3f dest(stoi(coords[0])*BS, stoi(coords[1])*BS, stoi(coords[2])*BS);
|
||||||
|
|
||||||
actionstream<<ctx->player->getName()<<" teleports from "
|
actionstream<<ctx->player->getName()<<" teleports from "
|
||||||
<<PP(ctx->player->getPosition()/BS)<<" to "
|
<<PP(ctx->player->getPosition()/BS)<<" to "
|
||||||
<<PP(dest/BS)<<std::endl;
|
<<PP(dest/BS)<<std::endl;
|
||||||
|
|
||||||
//ctx->player->setPosition(dest);
|
// Use the ServerActiveObject interface of RemotePlayer
|
||||||
|
// This forces a position change on the client
|
||||||
// Use the ServerActiveObject interface of ServerRemotePlayer
|
ServerActiveObject *sao = ctx->player->getPlayerSAO();
|
||||||
ServerRemotePlayer *srp = static_cast<ServerRemotePlayer*>(ctx->player);
|
if(sao)
|
||||||
srp->setPos(dest);
|
{
|
||||||
ctx->server->SendMovePlayer(ctx->player);
|
sao->setPos(dest);
|
||||||
|
os<< L"-!- Teleported.";
|
||||||
os<< L"-!- Teleported.";
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
errorstream<<"Teleport failed, player object not found!"
|
||||||
|
<<std::endl;
|
||||||
|
os<< L"-!- Teleport failed.";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void cmd_banunban(std::wostringstream &os, ServerCommandContext *ctx)
|
void cmd_banunban(std::wostringstream &os, ServerCommandContext *ctx)
|
||||||
|
|
|
@ -143,7 +143,7 @@ public:
|
||||||
{}
|
{}
|
||||||
virtual void setHP(s16 hp)
|
virtual void setHP(s16 hp)
|
||||||
{}
|
{}
|
||||||
virtual s16 getHP()
|
virtual s16 getHP() const
|
||||||
{ return 0; }
|
{ return 0; }
|
||||||
|
|
||||||
// Inventory and wielded item
|
// Inventory and wielded item
|
||||||
|
|
|
@ -1,265 +0,0 @@
|
||||||
/*
|
|
||||||
Minetest-c55
|
|
||||||
Copyright (C) 2010-2011 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 General Public License as published by
|
|
||||||
the Free Software Foundation; either version 2 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 General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU 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 "serverremoteplayer.h"
|
|
||||||
#include "main.h" // For g_settings
|
|
||||||
#include "settings.h"
|
|
||||||
#include "log.h"
|
|
||||||
#include "gamedef.h"
|
|
||||||
#include "inventory.h"
|
|
||||||
#include "environment.h"
|
|
||||||
#include "tool.h"
|
|
||||||
|
|
||||||
ServerRemotePlayer::ServerRemotePlayer(ServerEnvironment *env):
|
|
||||||
Player(env->getGameDef()),
|
|
||||||
ServerActiveObject(env, v3f(0,0,0)),
|
|
||||||
m_last_good_position(0,0,0),
|
|
||||||
m_last_good_position_age(0),
|
|
||||||
m_wield_index(0),
|
|
||||||
m_inventory_not_sent(false),
|
|
||||||
m_hp_not_sent(false),
|
|
||||||
m_is_in_environment(false),
|
|
||||||
m_time_from_last_punch(0),
|
|
||||||
m_position_not_sent(false)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
ServerRemotePlayer::ServerRemotePlayer(ServerEnvironment *env, v3f pos_, u16 peer_id_,
|
|
||||||
const char *name_):
|
|
||||||
Player(env->getGameDef()),
|
|
||||||
ServerActiveObject(env, pos_),
|
|
||||||
m_last_good_position(0,0,0),
|
|
||||||
m_last_good_position_age(0),
|
|
||||||
m_wield_index(0),
|
|
||||||
m_inventory_not_sent(false),
|
|
||||||
m_hp_not_sent(false),
|
|
||||||
m_is_in_environment(false),
|
|
||||||
m_time_from_last_punch(0),
|
|
||||||
m_position_not_sent(false)
|
|
||||||
{
|
|
||||||
setPosition(pos_);
|
|
||||||
peer_id = peer_id_;
|
|
||||||
updateName(name_);
|
|
||||||
}
|
|
||||||
ServerRemotePlayer::~ServerRemotePlayer()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void ServerRemotePlayer::setPosition(const v3f &position)
|
|
||||||
{
|
|
||||||
Player::setPosition(position);
|
|
||||||
ServerActiveObject::setBasePosition(position);
|
|
||||||
m_position_not_sent = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
Inventory* ServerRemotePlayer::getInventory()
|
|
||||||
{
|
|
||||||
return &inventory;
|
|
||||||
}
|
|
||||||
|
|
||||||
const Inventory* ServerRemotePlayer::getInventory() const
|
|
||||||
{
|
|
||||||
return &inventory;
|
|
||||||
}
|
|
||||||
|
|
||||||
InventoryLocation ServerRemotePlayer::getInventoryLocation() const
|
|
||||||
{
|
|
||||||
InventoryLocation loc;
|
|
||||||
loc.setPlayer(getName());
|
|
||||||
return loc;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ServerRemotePlayer::setInventoryModified()
|
|
||||||
{
|
|
||||||
m_inventory_not_sent = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string ServerRemotePlayer::getWieldList() const
|
|
||||||
{
|
|
||||||
return "main";
|
|
||||||
}
|
|
||||||
|
|
||||||
int ServerRemotePlayer::getWieldIndex() const
|
|
||||||
{
|
|
||||||
return m_wield_index;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ServerRemotePlayer::setWieldIndex(int i)
|
|
||||||
{
|
|
||||||
m_wield_index = i;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ServerActiveObject interface */
|
|
||||||
|
|
||||||
void ServerRemotePlayer::addedToEnvironment()
|
|
||||||
{
|
|
||||||
assert(!m_is_in_environment);
|
|
||||||
m_is_in_environment = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ServerRemotePlayer::removingFromEnvironment()
|
|
||||||
{
|
|
||||||
assert(m_is_in_environment);
|
|
||||||
m_is_in_environment = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ServerRemotePlayer::unlimitedTransferDistance() const
|
|
||||||
{
|
|
||||||
return g_settings->getBool("unlimited_player_transfer_distance");
|
|
||||||
}
|
|
||||||
|
|
||||||
void ServerRemotePlayer::step(float dtime, bool send_recommended)
|
|
||||||
{
|
|
||||||
m_time_from_last_punch += dtime;
|
|
||||||
|
|
||||||
if(send_recommended == false)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if(m_position_not_sent)
|
|
||||||
{
|
|
||||||
m_position_not_sent = false;
|
|
||||||
|
|
||||||
std::ostringstream os(std::ios::binary);
|
|
||||||
// command (0 = update position)
|
|
||||||
writeU8(os, 0);
|
|
||||||
// pos
|
|
||||||
writeV3F1000(os, getPosition());
|
|
||||||
// yaw
|
|
||||||
writeF1000(os, getYaw());
|
|
||||||
// create message and add to list
|
|
||||||
ActiveObjectMessage aom(getId(), false, os.str());
|
|
||||||
m_messages_out.push_back(aom);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string ServerRemotePlayer::getClientInitializationData()
|
|
||||||
{
|
|
||||||
std::ostringstream os(std::ios::binary);
|
|
||||||
// version
|
|
||||||
writeU8(os, 0);
|
|
||||||
// name
|
|
||||||
os<<serializeString(getName());
|
|
||||||
// pos
|
|
||||||
writeV3F1000(os, getPosition());
|
|
||||||
// yaw
|
|
||||||
writeF1000(os, getYaw());
|
|
||||||
// dead
|
|
||||||
writeU8(os, getHP() == 0);
|
|
||||||
return os.str();
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string ServerRemotePlayer::getStaticData()
|
|
||||||
{
|
|
||||||
assert(0);
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
|
|
||||||
int ServerRemotePlayer::punch(v3f dir,
|
|
||||||
const ToolCapabilities *toolcap,
|
|
||||||
ServerActiveObject *puncher,
|
|
||||||
float time_from_last_punch)
|
|
||||||
{
|
|
||||||
if(!toolcap)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
// No effect if PvP disabled
|
|
||||||
if(g_settings->getBool("enable_pvp") == false){
|
|
||||||
if(puncher->getType() == ACTIVEOBJECT_TYPE_PLAYER)
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// "Material" groups of the player
|
|
||||||
ItemGroupList groups;
|
|
||||||
groups["choppy"] = 2;
|
|
||||||
groups["fleshy"] = 3;
|
|
||||||
|
|
||||||
HitParams hitparams = getHitParams(groups, toolcap, time_from_last_punch);
|
|
||||||
|
|
||||||
actionstream<<"Player "<<getName()<<" punched by "
|
|
||||||
<<puncher->getDescription()<<", damage "<<hitparams.hp
|
|
||||||
<<" HP"<<std::endl;
|
|
||||||
|
|
||||||
setHP(getHP() - hitparams.hp);
|
|
||||||
|
|
||||||
if(hitparams.hp != 0)
|
|
||||||
{
|
|
||||||
std::ostringstream os(std::ios::binary);
|
|
||||||
// command (1 = punched)
|
|
||||||
writeU8(os, 1);
|
|
||||||
// damage
|
|
||||||
writeS16(os, hitparams.hp);
|
|
||||||
// create message and add to list
|
|
||||||
ActiveObjectMessage aom(getId(), false, os.str());
|
|
||||||
m_messages_out.push_back(aom);
|
|
||||||
}
|
|
||||||
|
|
||||||
return hitparams.wear;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ServerRemotePlayer::rightClick(ServerActiveObject *clicker)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void ServerRemotePlayer::setPos(v3f pos)
|
|
||||||
{
|
|
||||||
setPosition(pos);
|
|
||||||
// Movement caused by this command is always valid
|
|
||||||
m_last_good_position = pos;
|
|
||||||
m_last_good_position_age = 0;
|
|
||||||
}
|
|
||||||
void ServerRemotePlayer::moveTo(v3f pos, bool continuous)
|
|
||||||
{
|
|
||||||
setPosition(pos);
|
|
||||||
// Movement caused by this command is always valid
|
|
||||||
m_last_good_position = pos;
|
|
||||||
m_last_good_position_age = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ServerRemotePlayer::setHP(s16 hp_)
|
|
||||||
{
|
|
||||||
s16 oldhp = hp;
|
|
||||||
|
|
||||||
// FIXME: don't hardcode maximum HP, make configurable per object
|
|
||||||
if(hp_ < 0)
|
|
||||||
hp_ = 0;
|
|
||||||
else if(hp_ > 20)
|
|
||||||
hp_ = 20;
|
|
||||||
hp = hp_;
|
|
||||||
|
|
||||||
if(hp != oldhp)
|
|
||||||
m_hp_not_sent = true;
|
|
||||||
|
|
||||||
// On death or reincarnation send an active object message
|
|
||||||
if((hp == 0) != (oldhp == 0))
|
|
||||||
{
|
|
||||||
std::ostringstream os(std::ios::binary);
|
|
||||||
// command (2 = update death state)
|
|
||||||
writeU8(os, 2);
|
|
||||||
// dead?
|
|
||||||
writeU8(os, hp == 0);
|
|
||||||
// create message and add to list
|
|
||||||
ActiveObjectMessage aom(getId(), false, os.str());
|
|
||||||
m_messages_out.push_back(aom);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
s16 ServerRemotePlayer::getHP()
|
|
||||||
{
|
|
||||||
return hp;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
|
@ -1,105 +0,0 @@
|
||||||
/*
|
|
||||||
Minetest-c55
|
|
||||||
Copyright (C) 2010-2011 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 General Public License as published by
|
|
||||||
the Free Software Foundation; either version 2 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 General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU 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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef SERVERREMOTEPLAYER_HEADER
|
|
||||||
#define SERVERREMOTEPLAYER_HEADER
|
|
||||||
|
|
||||||
#include "player.h"
|
|
||||||
#include "serverobject.h"
|
|
||||||
#include "content_object.h" // Object type IDs
|
|
||||||
|
|
||||||
/*
|
|
||||||
Player on the server
|
|
||||||
*/
|
|
||||||
|
|
||||||
class ServerRemotePlayer : public Player, public ServerActiveObject
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
ServerRemotePlayer(ServerEnvironment *env);
|
|
||||||
ServerRemotePlayer(ServerEnvironment *env, v3f pos_, u16 peer_id_,
|
|
||||||
const char *name_);
|
|
||||||
|
|
||||||
virtual ~ServerRemotePlayer();
|
|
||||||
|
|
||||||
virtual bool isLocal() const
|
|
||||||
{ return false; }
|
|
||||||
|
|
||||||
virtual void move(f32 dtime, Map &map, f32 pos_max_d)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual void setPosition(const v3f &position);
|
|
||||||
|
|
||||||
/* ServerActiveObject interface */
|
|
||||||
|
|
||||||
u8 getType() const
|
|
||||||
{return ACTIVEOBJECT_TYPE_PLAYER;}
|
|
||||||
|
|
||||||
// Called after id has been set and has been inserted in environment
|
|
||||||
void addedToEnvironment();
|
|
||||||
// Called before removing from environment
|
|
||||||
void removingFromEnvironment();
|
|
||||||
|
|
||||||
bool environmentDeletes() const
|
|
||||||
{ return false; }
|
|
||||||
|
|
||||||
virtual bool unlimitedTransferDistance() const;
|
|
||||||
|
|
||||||
bool isStaticAllowed() const
|
|
||||||
{ return false; }
|
|
||||||
|
|
||||||
void step(float dtime, bool send_recommended);
|
|
||||||
std::string getClientInitializationData();
|
|
||||||
std::string getStaticData();
|
|
||||||
int punch(v3f dir,
|
|
||||||
const ToolCapabilities *toolcap,
|
|
||||||
ServerActiveObject *puncher,
|
|
||||||
float time_from_last_punch);
|
|
||||||
void rightClick(ServerActiveObject *clicker);
|
|
||||||
void setPos(v3f pos);
|
|
||||||
void moveTo(v3f pos, bool continuous);
|
|
||||||
virtual std::string getDescription()
|
|
||||||
{return std::string("player ")+getName();}
|
|
||||||
|
|
||||||
virtual Inventory* getInventory();
|
|
||||||
virtual const Inventory* getInventory() const;
|
|
||||||
virtual InventoryLocation getInventoryLocation() const;
|
|
||||||
virtual void setInventoryModified();
|
|
||||||
virtual std::string getWieldList() const;
|
|
||||||
virtual int getWieldIndex() const;
|
|
||||||
virtual void setWieldIndex(int i);
|
|
||||||
|
|
||||||
virtual void setHP(s16 hp_);
|
|
||||||
virtual s16 getHP();
|
|
||||||
|
|
||||||
v3f m_last_good_position;
|
|
||||||
float m_last_good_position_age;
|
|
||||||
int m_wield_index;
|
|
||||||
bool m_inventory_not_sent;
|
|
||||||
bool m_hp_not_sent;
|
|
||||||
bool m_is_in_environment;
|
|
||||||
// Incremented by step(), read and reset by Server
|
|
||||||
float m_time_from_last_punch;
|
|
||||||
|
|
||||||
private:
|
|
||||||
bool m_position_not_sent;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
Loading…
Reference in New Issue