mirror of
https://github.com/minetest/minetest.git
synced 2024-08-20 05:24:15 +02:00
added PlayerSAO and RemotePlayer, removed ServerRemotePlayer
This commit is contained in:
parent
072c265c30
commit
f8c3743991
@ -159,7 +159,6 @@ set(common_SRCS
|
||||
subgame.cpp
|
||||
inventorymanager.cpp
|
||||
mods.cpp
|
||||
serverremoteplayer.cpp
|
||||
content_abm.cpp
|
||||
craftdef.cpp
|
||||
nameidmapping.cpp
|
||||
|
@ -1397,45 +1397,7 @@ void Client::ProcessData(u8 *data, u32 datasize, u16 sender_peer_id)
|
||||
}
|
||||
else if(command == TOCLIENT_PLAYERITEM)
|
||||
{
|
||||
std::string datastring((char*)&data[2], datasize-2);
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
infostream<<"Client: WARNING: Ignoring TOCLIENT_PLAYERITEM"<<std::endl;
|
||||
}
|
||||
else if(command == TOCLIENT_DEATHSCREEN)
|
||||
{
|
||||
|
@ -200,7 +200,7 @@ enum ToClientCommand
|
||||
wstring reason
|
||||
*/
|
||||
|
||||
TOCLIENT_PLAYERITEM = 0x36,
|
||||
TOCLIENT_PLAYERITEM = 0x36, // Obsolete
|
||||
/*
|
||||
u16 command
|
||||
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
|
||||
#define CRACK_ANIMATION_LENGTH 5
|
||||
|
||||
// Some stuff needed by old code moved to here from heightmap.h
|
||||
#define GROUNDHEIGHT_NOTFOUND_SETVALUE (-10e6)
|
||||
#define GROUNDHEIGHT_VALID_MINVALUE ( -9e6)
|
||||
// Maximum hit points of a player
|
||||
#define PLAYER_MAX_HP 20
|
||||
|
||||
#endif
|
||||
|
||||
|
@ -1011,6 +1011,7 @@ private:
|
||||
float m_damage_visual_timer;
|
||||
bool m_dead;
|
||||
float m_step_distance_counter;
|
||||
std::string m_wielded_item;
|
||||
|
||||
public:
|
||||
PlayerCAO(IGameDef *gamedef, ClientEnvironment *env):
|
||||
@ -1024,7 +1025,8 @@ public:
|
||||
m_local_player(NULL),
|
||||
m_damage_visual_timer(0),
|
||||
m_dead(false),
|
||||
m_step_distance_counter(0)
|
||||
m_step_distance_counter(0),
|
||||
m_wielded_item("")
|
||||
{
|
||||
if(gamedef == NULL)
|
||||
ClientActiveObject::registerType(getType(), create);
|
||||
@ -1048,6 +1050,11 @@ public:
|
||||
m_yaw = readF1000(is);
|
||||
// dead
|
||||
m_dead = readU8(is);
|
||||
// wielded item
|
||||
try{
|
||||
m_wielded_item = deSerializeString(is);
|
||||
}
|
||||
catch(SerializationError &e){}
|
||||
|
||||
pos_translator.init(m_position);
|
||||
|
||||
@ -1263,6 +1270,11 @@ public:
|
||||
m_dead = readU8(is);
|
||||
updateVisibility();
|
||||
}
|
||||
else if(cmd == 3) // wielded item
|
||||
{
|
||||
m_wielded_item = deSerializeString(is);
|
||||
updateWieldedItem();
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
|
@ -26,6 +26,8 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#include "serialization.h" // For compressZlib
|
||||
#include "tool.h" // For ToolCapabilities
|
||||
#include "gamedef.h"
|
||||
#include "player.h"
|
||||
#include "scriptapi.h"
|
||||
|
||||
core::map<u16, ServerActiveObject::Factory> ServerActiveObject::m_types;
|
||||
|
||||
@ -333,7 +335,6 @@ ServerActiveObject* createItemSAO(ServerEnvironment *env, v3f pos,
|
||||
LuaEntitySAO
|
||||
*/
|
||||
|
||||
#include "scriptapi.h"
|
||||
#include "luaentity_common.h"
|
||||
|
||||
// Prototype (registers item for deserialization)
|
||||
@ -610,7 +611,7 @@ void LuaEntitySAO::setHP(s16 hp)
|
||||
m_hp = hp;
|
||||
}
|
||||
|
||||
s16 LuaEntitySAO::getHP()
|
||||
s16 LuaEntitySAO::getHP() const
|
||||
{
|
||||
return m_hp;
|
||||
}
|
||||
@ -749,3 +750,345 @@ void LuaEntitySAO::sendPosition(bool do_interpolate, bool is_movement_end)
|
||||
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 "content_object.h"
|
||||
#include "itemgroup.h"
|
||||
#include "player.h"
|
||||
|
||||
ServerActiveObject* createItemSAO(ServerEnvironment *env, v3f pos,
|
||||
const std::string itemstring);
|
||||
|
||||
/*
|
||||
LuaEntitySAO
|
||||
|
||||
This is the only SAO that needs to have a bunch of it's internals exposed.
|
||||
LuaEntitySAO needs some internals exposed.
|
||||
*/
|
||||
|
||||
struct LuaEntityProperties;
|
||||
@ -59,7 +58,7 @@ public:
|
||||
float getMinimumSavedMovement();
|
||||
std::string getDescription();
|
||||
void setHP(s16 hp);
|
||||
s16 getHP();
|
||||
s16 getHP() const;
|
||||
/* LuaEntitySAO-specific */
|
||||
void setVelocity(v3f velocity);
|
||||
v3f getVelocity();
|
||||
@ -94,5 +93,102 @@ private:
|
||||
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
|
||||
|
||||
|
@ -37,7 +37,6 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#include "nodemetadata.h"
|
||||
#include "main.h" // For g_settings, g_profiler
|
||||
#include "gamedef.h"
|
||||
#include "serverremoteplayer.h"
|
||||
#ifndef SERVER
|
||||
#include "clientmap.h"
|
||||
#endif
|
||||
@ -368,7 +367,7 @@ void ServerEnvironment::serializePlayers(const std::string &savedir)
|
||||
//infostream<<"Checking player file "<<path<<std::endl;
|
||||
|
||||
// Load player to see what is its name
|
||||
ServerRemotePlayer testplayer(this);
|
||||
RemotePlayer testplayer(m_gamedef);
|
||||
{
|
||||
// Open file and deserialize
|
||||
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;
|
||||
|
||||
// Load player to see what is its name
|
||||
ServerRemotePlayer testplayer(this);
|
||||
RemotePlayer testplayer(m_gamedef);
|
||||
{
|
||||
// Open file and deserialize
|
||||
std::ifstream is(path.c_str(), std::ios_base::binary);
|
||||
@ -510,12 +509,10 @@ void ServerEnvironment::deSerializePlayers(const std::string &savedir)
|
||||
if(player == NULL)
|
||||
{
|
||||
//infostream<<"Is a new player"<<std::endl;
|
||||
player = new ServerRemotePlayer(this);
|
||||
player = new RemotePlayer(m_gamedef);
|
||||
newplayer = true;
|
||||
}
|
||||
|
||||
ServerRemotePlayer *srp = static_cast<ServerRemotePlayer*>(player);
|
||||
|
||||
// Load player
|
||||
{
|
||||
verbosestream<<"Reading player "<<testplayer.getName()<<" from "
|
||||
@ -527,9 +524,7 @@ void ServerEnvironment::deSerializePlayers(const std::string &savedir)
|
||||
infostream<<"Failed to read "<<path<<std::endl;
|
||||
continue;
|
||||
}
|
||||
srp->deSerialize(is);
|
||||
srp->m_last_good_position = srp->getBasePosition();
|
||||
srp->m_last_good_position_age = 0;
|
||||
player->deSerialize(is);
|
||||
}
|
||||
|
||||
if(newplayer)
|
||||
@ -2074,7 +2069,7 @@ void ClientEnvironment::step(float dtime)
|
||||
catch(InvalidPositionException &e){
|
||||
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->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);
|
||||
}
|
||||
|
||||
@ -2258,7 +2264,18 @@ void ClientEnvironment::processActiveObjectMessage(u16 id,
|
||||
<<std::endl;
|
||||
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();
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
m_itemdef = itemdef;
|
||||
|
@ -250,6 +250,7 @@ public:
|
||||
~Inventory();
|
||||
|
||||
void clear();
|
||||
void clearContents();
|
||||
|
||||
Inventory(IItemDefManager *itemdef);
|
||||
Inventory(const Inventory &other);
|
||||
|
@ -32,6 +32,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#include "environment.h"
|
||||
#include "gamedef.h"
|
||||
#include "event.h"
|
||||
#include "content_sao.h"
|
||||
|
||||
Player::Player(IGameDef *gamedef):
|
||||
touching_ground(false),
|
||||
@ -40,8 +41,7 @@ Player::Player(IGameDef *gamedef):
|
||||
is_climbing(false),
|
||||
swimming_up(false),
|
||||
inventory(gamedef->idef()),
|
||||
inventory_backup(NULL),
|
||||
hp(20),
|
||||
hp(PLAYER_MAX_HP),
|
||||
peer_id(PEER_ID_INEXISTENT),
|
||||
// protected
|
||||
m_gamedef(gamedef),
|
||||
@ -51,16 +51,6 @@ Player::Player(IGameDef *gamedef):
|
||||
m_position(0,0,0)
|
||||
{
|
||||
updateName("<not set>");
|
||||
resetInventory();
|
||||
}
|
||||
|
||||
Player::~Player()
|
||||
{
|
||||
delete inventory_backup;
|
||||
}
|
||||
|
||||
void Player::resetInventory()
|
||||
{
|
||||
inventory.clear();
|
||||
inventory.addList("main", PLAYER_INVENTORY_SIZE);
|
||||
inventory.addList("craft", 9);
|
||||
@ -68,6 +58,10 @@ void Player::resetInventory()
|
||||
inventory.addList("craftresult", 1);
|
||||
}
|
||||
|
||||
Player::~Player()
|
||||
{
|
||||
}
|
||||
|
||||
// Y direction is ignored
|
||||
void Player::accelerate(v3f target_speed, f32 max_increase)
|
||||
{
|
||||
@ -126,12 +120,7 @@ void Player::serialize(std::ostream &os)
|
||||
|
||||
os<<"PlayerArgsEnd\n";
|
||||
|
||||
// If actual inventory is backed up due to creative mode, save it
|
||||
// instead of the dummy creative mode inventory
|
||||
if(inventory_backup)
|
||||
inventory_backup->serialize(os);
|
||||
else
|
||||
inventory.serialize(os);
|
||||
inventory.serialize(os);
|
||||
}
|
||||
|
||||
void Player::deSerialize(std::istream &is)
|
||||
@ -779,3 +768,13 @@ v3s16 LocalPlayer::getStandingNodePos()
|
||||
|
||||
#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 IGameDef;
|
||||
struct CollisionInfo;
|
||||
class PlayerSAO;
|
||||
|
||||
class Player
|
||||
{
|
||||
public:
|
||||
|
||||
Player(IGameDef *gamedef);
|
||||
virtual ~Player();
|
||||
virtual ~Player() = 0;
|
||||
|
||||
void resetInventory();
|
||||
|
||||
//void move(f32 dtime, Map &map);
|
||||
virtual void move(f32 dtime, Map &map, f32 pos_max_d) = 0;
|
||||
virtual void move(f32 dtime, Map &map, f32 pos_max_d)
|
||||
{}
|
||||
|
||||
v3f getSpeed()
|
||||
{
|
||||
@ -112,7 +111,7 @@ public:
|
||||
return (m_yaw + 90.) * core::DEGTORAD;
|
||||
}
|
||||
|
||||
virtual void updateName(const char *name)
|
||||
void updateName(const char *name)
|
||||
{
|
||||
snprintf(m_name, PLAYERNAME_SIZE, "%s", name);
|
||||
}
|
||||
@ -122,17 +121,13 @@ public:
|
||||
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
|
||||
any characters except a '\0', and such an ending that
|
||||
@ -151,9 +146,8 @@ public:
|
||||
|
||||
u8 light;
|
||||
|
||||
// In creative mode, this is the invisible backup inventory
|
||||
Inventory inventory;
|
||||
// Actual inventory is backed up here when creative mode is used
|
||||
Inventory *inventory_backup;
|
||||
|
||||
u16 hp;
|
||||
|
||||
@ -167,9 +161,6 @@ protected:
|
||||
f32 m_yaw;
|
||||
v3f m_speed;
|
||||
v3f m_position;
|
||||
|
||||
public:
|
||||
|
||||
};
|
||||
|
||||
#ifndef SERVER
|
||||
@ -249,5 +240,24 @@ private:
|
||||
};
|
||||
#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
|
||||
|
||||
|
@ -35,7 +35,7 @@ extern "C" {
|
||||
#include "script.h"
|
||||
//#include "luna.h"
|
||||
#include "luaentity_common.h"
|
||||
#include "content_sao.h" // For LuaEntitySAO
|
||||
#include "content_sao.h" // For LuaEntitySAO and PlayerSAO
|
||||
#include "itemdef.h"
|
||||
#include "nodedef.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,
|
||||
lua_State *L, int tableindex, int forcesize=-1)
|
||||
{
|
||||
dstream<<"inventory_set_list_from_lua\n";
|
||||
if(tableindex < 0)
|
||||
tableindex = lua_gettop(L) + 1 + tableindex;
|
||||
// If nil, delete list
|
||||
@ -1127,7 +1126,6 @@ static void inventory_set_list_from_lua(Inventory *inv, const char *name,
|
||||
invlist->deleteItem(index);
|
||||
index++;
|
||||
}
|
||||
dstream<<"inventory_set_list_from_lua done\n";
|
||||
}
|
||||
|
||||
static void inventory_get_list_to_lua(Inventory *inv, const char *name,
|
||||
@ -2259,14 +2257,22 @@ private:
|
||||
return (LuaEntitySAO*)obj;
|
||||
}
|
||||
|
||||
static ServerRemotePlayer* getplayer(ObjectRef *ref)
|
||||
static PlayerSAO* getplayersao(ObjectRef *ref)
|
||||
{
|
||||
ServerActiveObject *obj = getobject(ref);
|
||||
if(obj == NULL)
|
||||
return NULL;
|
||||
if(obj->getType() != ACTIVEOBJECT_TYPE_PLAYER)
|
||||
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
|
||||
@ -2319,10 +2325,6 @@ private:
|
||||
v3f pos = checkFloatPos(L, 2);
|
||||
// Do it
|
||||
co->setPos(pos);
|
||||
// Move player if applicable
|
||||
ServerRemotePlayer *player = getplayer(ref);
|
||||
if(player != NULL)
|
||||
get_server(L)->SendMovePlayer(player);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -2626,7 +2628,7 @@ private:
|
||||
static int l_get_player_name(lua_State *L)
|
||||
{
|
||||
ObjectRef *ref = checkobject(L, 1);
|
||||
ServerRemotePlayer *player = getplayer(ref);
|
||||
Player *player = getplayer(ref);
|
||||
if(player == NULL){
|
||||
lua_pushnil(L);
|
||||
return 1;
|
||||
@ -2640,7 +2642,7 @@ private:
|
||||
static int l_get_look_dir(lua_State *L)
|
||||
{
|
||||
ObjectRef *ref = checkobject(L, 1);
|
||||
ServerRemotePlayer *player = getplayer(ref);
|
||||
Player *player = getplayer(ref);
|
||||
if(player == NULL) return 0;
|
||||
// Do it
|
||||
float pitch = player->getRadPitch();
|
||||
@ -2654,7 +2656,7 @@ private:
|
||||
static int l_get_look_pitch(lua_State *L)
|
||||
{
|
||||
ObjectRef *ref = checkobject(L, 1);
|
||||
ServerRemotePlayer *player = getplayer(ref);
|
||||
Player *player = getplayer(ref);
|
||||
if(player == NULL) return 0;
|
||||
// Do it
|
||||
lua_pushnumber(L, player->getRadPitch());
|
||||
@ -2665,7 +2667,7 @@ private:
|
||||
static int l_get_look_yaw(lua_State *L)
|
||||
{
|
||||
ObjectRef *ref = checkobject(L, 1);
|
||||
ServerRemotePlayer *player = getplayer(ref);
|
||||
Player *player = getplayer(ref);
|
||||
if(player == NULL) return 0;
|
||||
// Do it
|
||||
lua_pushnumber(L, player->getRadYaw());
|
||||
@ -2996,14 +2998,18 @@ private:
|
||||
if(env == NULL) return 0;
|
||||
// Do it
|
||||
const char *name = luaL_checkstring(L, 2);
|
||||
ServerRemotePlayer *player =
|
||||
static_cast<ServerRemotePlayer*>(env->getPlayer(name));
|
||||
Player *player = env->getPlayer(name);
|
||||
if(player == NULL){
|
||||
lua_pushnil(L);
|
||||
return 1;
|
||||
}
|
||||
PlayerSAO *sao = player->getPlayerSAO();
|
||||
if(sao == NULL){
|
||||
lua_pushnil(L);
|
||||
return 1;
|
||||
}
|
||||
// Put player on stack
|
||||
objectref_get_or_create(L, player);
|
||||
objectref_get_or_create(L, sao);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -4211,8 +4217,6 @@ bool scriptapi_on_respawnplayer(lua_State *L, ServerActiveObject *player)
|
||||
assert(lua_checkstack(L, 20));
|
||||
StackUnroller stack_unroller(L);
|
||||
|
||||
dstream<<"player: "<<player<<" id: "<<player->getId()<<std::endl;
|
||||
|
||||
bool positioning_handled_by_some = false;
|
||||
|
||||
// Get minetest.registered_on_respawnplayers
|
||||
@ -4238,13 +4242,15 @@ bool scriptapi_on_respawnplayer(lua_State *L, ServerActiveObject *player)
|
||||
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_getfield(L, -1, "creative_inventory");
|
||||
luaL_checktype(L, -1, LUA_TTABLE);
|
||||
inventory_set_list_from_lua(&player->inventory, "main", L, -1,
|
||||
PLAYER_INVENTORY_SIZE);
|
||||
inventory_set_list_from_lua(inv, "main", L, -1, PLAYER_INVENTORY_SIZE);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -27,7 +27,6 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
class Server;
|
||||
class ServerEnvironment;
|
||||
class ServerActiveObject;
|
||||
class ServerRemotePlayer;
|
||||
typedef struct lua_State lua_State;
|
||||
struct LuaEntityProperties;
|
||||
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_dieplayer(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 */
|
||||
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 "servercommand.h"
|
||||
#include "filesys.h"
|
||||
#include "content_mapnode.h"
|
||||
#include "content_nodemeta.h"
|
||||
#include "mapblock.h"
|
||||
#include "serverobject.h"
|
||||
#include "settings.h"
|
||||
@ -43,7 +41,10 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
#include "itemdef.h"
|
||||
#include "craftdef.h"
|
||||
#include "mapgen.h"
|
||||
#include "content_mapnode.h"
|
||||
#include "content_nodemeta.h"
|
||||
#include "content_abm.h"
|
||||
#include "content_sao.h"
|
||||
#include "mods.h"
|
||||
#include "sha1.h"
|
||||
#include "base64.h"
|
||||
@ -379,6 +380,27 @@ void * EmergeThread::Thread()
|
||||
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,
|
||||
core::array<PrioritySortedBlockTransfer> &dest)
|
||||
{
|
||||
@ -1250,8 +1272,6 @@ void Server::AsyncRunStep()
|
||||
i.atEnd() == false; i++)
|
||||
{
|
||||
RemoteClient *client = i.getNode()->getValue();
|
||||
//Player *player = m_env->getPlayer(client->peer_id);
|
||||
|
||||
SharedBuffer<u8> data = makePacket_TOCLIENT_TIME_OF_DAY(
|
||||
m_env->getTimeOfDay(), g_settings->getFloat("time_speed"));
|
||||
// Send as reliable
|
||||
@ -1291,78 +1311,36 @@ void Server::AsyncRunStep()
|
||||
|
||||
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
|
||||
i = m_clients.getIterator();
|
||||
i.atEnd() == false; i++)
|
||||
{
|
||||
RemoteClient *client = i.getNode()->getValue();
|
||||
ServerRemotePlayer *player =
|
||||
static_cast<ServerRemotePlayer*>
|
||||
(m_env->getPlayer(client->peer_id));
|
||||
if(player==NULL)
|
||||
PlayerSAO *playersao = getPlayerSAO(client->peer_id);
|
||||
if(playersao == NULL){
|
||||
errorstream<<"Handling client without PlayerSAO, peer_id="<<client->peer_id<<std::endl;
|
||||
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)
|
||||
*/
|
||||
if(player->hp == 0 && player->m_hp_not_sent)
|
||||
DiePlayer(player);
|
||||
if(playersao->getHP() == 0 && playersao->m_hp_not_sent)
|
||||
DiePlayer(client->peer_id);
|
||||
|
||||
/*
|
||||
Send player inventories and HPs if necessary
|
||||
*/
|
||||
if(player->m_inventory_not_sent){
|
||||
UpdateCrafting(player->peer_id);
|
||||
SendInventory(player->peer_id);
|
||||
if(playersao->m_teleported){
|
||||
SendMovePlayer(client->peer_id);
|
||||
playersao->m_teleported = false;
|
||||
}
|
||||
if(player->m_hp_not_sent){
|
||||
SendPlayerHP(player);
|
||||
if(playersao->m_inventory_not_sent){
|
||||
UpdateCrafting(client->peer_id);
|
||||
SendInventory(client->peer_id);
|
||||
}
|
||||
|
||||
/*
|
||||
Add to environment
|
||||
*/
|
||||
if(!player->m_is_in_environment){
|
||||
player->m_removed = false;
|
||||
player->setId(0);
|
||||
m_env->addActiveObject(player);
|
||||
if(playersao->m_hp_not_sent){
|
||||
SendPlayerHP(client->peer_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -2167,10 +2145,10 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
|
||||
}
|
||||
|
||||
// Get player
|
||||
ServerRemotePlayer *player = emergePlayer(playername, peer_id);
|
||||
PlayerSAO *playersao = emergePlayer(playername, peer_id);
|
||||
|
||||
// If failed, cancel
|
||||
if(player == NULL)
|
||||
if(playersao == NULL)
|
||||
{
|
||||
errorstream<<"Server: peer_id="<<peer_id
|
||||
<<": 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);
|
||||
writeU16(&reply[0], TOCLIENT_INIT);
|
||||
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());
|
||||
|
||||
// Send as reliable
|
||||
@ -2194,7 +2172,7 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
|
||||
/*
|
||||
Send complete position information
|
||||
*/
|
||||
SendMovePlayer(player);
|
||||
SendMovePlayer(peer_id);
|
||||
|
||||
return;
|
||||
}
|
||||
@ -2231,17 +2209,14 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
|
||||
UpdateCrafting(peer_id);
|
||||
SendInventory(peer_id);
|
||||
|
||||
// Send player items to all players
|
||||
SendPlayerItems();
|
||||
|
||||
Player *player = m_env->getPlayer(peer_id);
|
||||
|
||||
// Send HP
|
||||
SendPlayerHP(player);
|
||||
SendPlayerHP(peer_id);
|
||||
|
||||
// Show death screen if necessary
|
||||
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
|
||||
{
|
||||
@ -2314,14 +2289,21 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
|
||||
}
|
||||
|
||||
Player *player = m_env->getPlayer(peer_id);
|
||||
ServerRemotePlayer *srp = static_cast<ServerRemotePlayer*>(player);
|
||||
|
||||
if(player == NULL){
|
||||
infostream<<"Server::ProcessData(): Cancelling: "
|
||||
"No player for peer_id="<<peer_id
|
||||
<<std::endl;
|
||||
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(datasize < 2+12+12+4+4)
|
||||
@ -2644,7 +2626,7 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
|
||||
}
|
||||
|
||||
// Do the action
|
||||
a->apply(this, srp, this);
|
||||
a->apply(this, playersao, this);
|
||||
// Eat the action
|
||||
delete a;
|
||||
}
|
||||
@ -2775,27 +2757,17 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
|
||||
std::istringstream is(datastring, std::ios_base::binary);
|
||||
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"))
|
||||
{
|
||||
actionstream<<player->getName()<<" damaged by "
|
||||
<<(int)damage<<" hp at "<<PP(player->getPosition()/BS)
|
||||
<<std::endl;
|
||||
playersao->setHP(playersao->getHP() - damage);
|
||||
|
||||
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)
|
||||
DiePlayer(srp);
|
||||
|
||||
if(srp->m_hp_not_sent)
|
||||
SendPlayerHP(player);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Force send (to correct the client's predicted HP)
|
||||
SendPlayerHP(player);
|
||||
}
|
||||
if(playersao->m_hp_not_sent)
|
||||
SendPlayerHP(peer_id);
|
||||
}
|
||||
else if(command == TOSERVER_PASSWORD)
|
||||
{
|
||||
@ -2865,15 +2837,14 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
|
||||
return;
|
||||
|
||||
u16 item = readU16(&data[2]);
|
||||
srp->setWieldIndex(item);
|
||||
SendWieldedItem(srp);
|
||||
playersao->setWieldIndex(item);
|
||||
}
|
||||
else if(command == TOSERVER_RESPAWN)
|
||||
{
|
||||
if(player->hp != 0)
|
||||
return;
|
||||
|
||||
RespawnPlayer(player);
|
||||
RespawnPlayer(peer_id);
|
||||
|
||||
actionstream<<player->getName()<<" respawns at "
|
||||
<<PP(player->getPosition()/BS)<<std::endl;
|
||||
@ -2934,19 +2905,15 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
|
||||
|
||||
if(player->hp == 0)
|
||||
{
|
||||
verbosestream<<"TOSERVER_INTERACT: "<<srp->getName()
|
||||
verbosestream<<"TOSERVER_INTERACT: "<<player->getName()
|
||||
<<" tried to interact, but is dead!"<<std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
v3f player_pos = srp->m_last_good_position;
|
||||
v3f player_pos = playersao->getLastGoodPosition();
|
||||
|
||||
// Update wielded item
|
||||
if(srp->getWieldIndex() != item_i)
|
||||
{
|
||||
srp->setWieldIndex(item_i);
|
||||
SendWieldedItem(srp);
|
||||
}
|
||||
playersao->setWieldIndex(item_i);
|
||||
|
||||
// Get pointed to node (undefined if not POINTEDTYPE_NODE)
|
||||
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);
|
||||
}
|
||||
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)
|
||||
{
|
||||
@ -3050,15 +3017,16 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
|
||||
<<pointed.object_id<<": "
|
||||
<<pointed_object->getDescription()<<std::endl;
|
||||
|
||||
ItemStack punchitem = srp->getWieldedItem();
|
||||
ItemStack punchitem = playersao->getWieldedItem();
|
||||
ToolCapabilities toolcap =
|
||||
punchitem.getToolCapabilities(m_itemdef);
|
||||
v3f dir = (pointed_object->getBasePosition() -
|
||||
(srp->getPosition() + srp->getEyeOffset())
|
||||
(player->getPosition() + player->getEyeOffset())
|
||||
).normalize();
|
||||
pointed_object->punch(dir, &toolcap, srp,
|
||||
srp->m_time_from_last_punch);
|
||||
srp->m_time_from_last_punch = 0;
|
||||
float time_from_last_punch =
|
||||
playersao->resetTimeFromLastPunch();
|
||||
pointed_object->punch(dir, &toolcap, playersao,
|
||||
time_from_last_punch);
|
||||
}
|
||||
|
||||
} // action == 0
|
||||
@ -3092,7 +3060,7 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
|
||||
getNodeBlockPos(p_above), BLOCK_EMERGE_FLAG_FROMDISK);
|
||||
}
|
||||
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
|
||||
|
||||
@ -3101,7 +3069,7 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
|
||||
*/
|
||||
else if(action == 3)
|
||||
{
|
||||
ItemStack item = srp->getWieldedItem();
|
||||
ItemStack item = playersao->getWieldedItem();
|
||||
|
||||
// Reset build time counter
|
||||
if(pointed.type == POINTEDTHING_NODE &&
|
||||
@ -3121,16 +3089,16 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
|
||||
<<pointed_object->getDescription()<<std::endl;
|
||||
|
||||
// Do stuff
|
||||
pointed_object->rightClick(srp);
|
||||
pointed_object->rightClick(playersao);
|
||||
}
|
||||
else if(scriptapi_item_on_place(m_lua,
|
||||
item, srp, pointed))
|
||||
item, playersao, pointed))
|
||||
{
|
||||
// Placement was handled in lua
|
||||
|
||||
// Apply returned ItemStack
|
||||
if(g_settings->getBool("creative_mode") == false)
|
||||
srp->setWieldedItem(item);
|
||||
playersao->setWieldedItem(item);
|
||||
}
|
||||
|
||||
} // action == 3
|
||||
@ -3140,17 +3108,17 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
|
||||
*/
|
||||
else if(action == 4)
|
||||
{
|
||||
ItemStack item = srp->getWieldedItem();
|
||||
ItemStack item = playersao->getWieldedItem();
|
||||
|
||||
actionstream<<player->getName()<<" uses "<<item.name
|
||||
<<", pointing at "<<pointed.dump()<<std::endl;
|
||||
|
||||
if(scriptapi_item_on_use(m_lua,
|
||||
item, srp, pointed))
|
||||
item, playersao, pointed))
|
||||
{
|
||||
// Apply returned ItemStack
|
||||
if(g_settings->getBool("creative_mode") == false)
|
||||
srp->setWieldedItem(item);
|
||||
playersao->setWieldedItem(item);
|
||||
}
|
||||
|
||||
} // action == 4
|
||||
@ -3222,7 +3190,10 @@ Inventory* Server::getInventory(const InventoryLocation &loc)
|
||||
Player *player = m_env->getPlayer(loc.name.c_str());
|
||||
if(!player)
|
||||
return NULL;
|
||||
return &player->inventory;
|
||||
PlayerSAO *playersao = player->getPlayerSAO();
|
||||
if(!playersao)
|
||||
return NULL;
|
||||
return playersao->getInventory();
|
||||
}
|
||||
break;
|
||||
case InventoryLocation::NODEMETA:
|
||||
@ -3273,11 +3244,14 @@ void Server::setInventoryModified(const InventoryLocation &loc)
|
||||
break;
|
||||
case InventoryLocation::PLAYER:
|
||||
{
|
||||
ServerRemotePlayer *srp = static_cast<ServerRemotePlayer*>
|
||||
(m_env->getPlayer(loc.name.c_str()));
|
||||
if(!srp)
|
||||
Player *player = m_env->getPlayer(loc.name.c_str());
|
||||
if(!player)
|
||||
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;
|
||||
case InventoryLocation::NODEMETA:
|
||||
@ -3482,20 +3456,17 @@ void Server::SendInventory(u16 peer_id)
|
||||
{
|
||||
DSTACK(__FUNCTION_NAME);
|
||||
|
||||
ServerRemotePlayer* player =
|
||||
static_cast<ServerRemotePlayer*>(m_env->getPlayer(peer_id));
|
||||
assert(player);
|
||||
PlayerSAO *playersao = getPlayerSAO(peer_id);
|
||||
assert(playersao);
|
||||
|
||||
player->m_inventory_not_sent = false;
|
||||
playersao->m_inventory_not_sent = false;
|
||||
|
||||
/*
|
||||
Serialize it
|
||||
*/
|
||||
|
||||
std::ostringstream os;
|
||||
//os.imbue(std::locale("C"));
|
||||
|
||||
player->inventory.serialize(os);
|
||||
playersao->getInventory()->serialize(os);
|
||||
|
||||
std::string s = os.str();
|
||||
|
||||
@ -3507,52 +3478,6 @@ void Server::SendInventory(u16 peer_id)
|
||||
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)
|
||||
{
|
||||
DSTACK(__FUNCTION_NAME);
|
||||
@ -3599,17 +3524,22 @@ void Server::BroadcastChatMessage(const std::wstring &message)
|
||||
}
|
||||
}
|
||||
|
||||
void Server::SendPlayerHP(Player *player)
|
||||
{
|
||||
SendHP(m_con, player->peer_id, player->hp);
|
||||
static_cast<ServerRemotePlayer*>(player)->m_hp_not_sent = false;
|
||||
}
|
||||
|
||||
void Server::SendMovePlayer(Player *player)
|
||||
void Server::SendPlayerHP(u16 peer_id)
|
||||
{
|
||||
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);
|
||||
writeV3F1000(os, player->getPosition());
|
||||
writeF1000(os, player->getPitch());
|
||||
@ -3630,7 +3560,7 @@ void Server::SendMovePlayer(Player *player)
|
||||
std::string s = os.str();
|
||||
SharedBuffer<u8> data((u8*)s.c_str(), s.size());
|
||||
// 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,
|
||||
@ -4242,41 +4172,44 @@ void Server::sendRequestedMedia(u16 peer_id,
|
||||
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 "
|
||||
<<player->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;
|
||||
}
|
||||
<<playersao->getPlayer()->getName()
|
||||
<<" dies"<<std::endl;
|
||||
|
||||
SendPlayerHP(player);
|
||||
SendDeathscreen(m_con, player->peer_id, false, v3f(0,0,0));
|
||||
playersao->setHP(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);
|
||||
srp->setHP(20);
|
||||
bool repositioned = scriptapi_on_respawnplayer(m_lua, srp);
|
||||
DSTACK(__FUNCTION_NAME);
|
||||
|
||||
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){
|
||||
v3f pos = findSpawnPos(m_env->getServerMap());
|
||||
player->setPosition(pos);
|
||||
srp->m_last_good_position = pos;
|
||||
srp->m_last_good_position_age = 0;
|
||||
playersao->setPos(pos);
|
||||
}
|
||||
SendMovePlayer(player);
|
||||
SendPlayerHP(player);
|
||||
}
|
||||
|
||||
void Server::UpdateCrafting(u16 peer_id)
|
||||
@ -4542,46 +4475,21 @@ v3f findSpawnPos(ServerMap &map)
|
||||
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
|
||||
*/
|
||||
ServerRemotePlayer *player =
|
||||
static_cast<ServerRemotePlayer*>(m_env->getPlayer(name));
|
||||
if(player != NULL)
|
||||
player = static_cast<RemotePlayer*>(m_env->getPlayer(name));
|
||||
|
||||
// If player is already connected, cancel
|
||||
if(player != NULL && player->peer_id != 0)
|
||||
{
|
||||
// If player is already connected, cancel
|
||||
if(player->peer_id != 0)
|
||||
{
|
||||
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;
|
||||
infostream<<"emergePlayer(): Player already connected"<<std::endl;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -4593,43 +4501,43 @@ ServerRemotePlayer *Server::emergePlayer(const char *name, u16 peer_id)
|
||||
" peer_id already exists"<<std::endl;
|
||||
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 */
|
||||
|
||||
infostream<<"Server: Finding spawn place for player \""
|
||||
<<name<<"\""<<std::endl;
|
||||
|
||||
v3f pos = findSpawnPos(m_env->getServerMap());
|
||||
|
||||
player = new ServerRemotePlayer(m_env, pos, peer_id, name);
|
||||
ServerRemotePlayer *srp = static_cast<ServerRemotePlayer*>(player);
|
||||
player->setPosition(pos);
|
||||
|
||||
/* Add player to environment */
|
||||
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 */
|
||||
if(g_settings->getBool("creative_mode"))
|
||||
{
|
||||
// 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);
|
||||
}
|
||||
/* Add object to environment */
|
||||
m_env->addActiveObject(playersao);
|
||||
|
||||
return player;
|
||||
|
||||
} // create new player
|
||||
/* Run scripts */
|
||||
if(newplayer)
|
||||
scriptapi_on_newplayer(m_lua, playersao);
|
||||
|
||||
/* Creative mode */
|
||||
if(g_settings->getBool("creative_mode"))
|
||||
playersao->createCreativeInventory();
|
||||
|
||||
return playersao;
|
||||
}
|
||||
|
||||
void Server::handlePeerChange(PeerChange &c)
|
||||
@ -4699,8 +4607,7 @@ void Server::handlePeerChange(PeerChange &c)
|
||||
i++;
|
||||
}
|
||||
|
||||
ServerRemotePlayer* player =
|
||||
static_cast<ServerRemotePlayer*>(m_env->getPlayer(c.peer_id));
|
||||
Player *player = m_env->getPlayer(c.peer_id);
|
||||
|
||||
// Collect information about leaving in chat
|
||||
std::wstring message;
|
||||
@ -4717,12 +4624,8 @@ void Server::handlePeerChange(PeerChange &c)
|
||||
}
|
||||
|
||||
// Remove from environment
|
||||
if(player != NULL)
|
||||
player->m_removed = true;
|
||||
|
||||
// Set player client disconnected
|
||||
if(player != NULL)
|
||||
player->peer_id = 0;
|
||||
if(player->getPlayerSAO())
|
||||
player->getPlayerSAO()->disconnected();
|
||||
|
||||
/*
|
||||
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 "gamedef.h"
|
||||
#include "serialization.h" // For SER_FMT_VER_INVALID
|
||||
#include "serverremoteplayer.h"
|
||||
#include "mods.h"
|
||||
#include "inventorymanager.h"
|
||||
#include "subgame.h"
|
||||
@ -42,6 +41,7 @@ class IWritableItemDefManager;
|
||||
class IWritableNodeDefManager;
|
||||
class IWritableCraftDefManager;
|
||||
class EventManager;
|
||||
class PlayerSAO;
|
||||
|
||||
class ServerError : public std::exception
|
||||
{
|
||||
@ -299,26 +299,7 @@ struct ServerSoundParams
|
||||
loop(false)
|
||||
{}
|
||||
|
||||
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);
|
||||
}
|
||||
v3f getPos(ServerEnvironment *env, bool *pos_exists) const;
|
||||
};
|
||||
|
||||
struct ServerPlayingSound
|
||||
@ -514,9 +495,6 @@ public:
|
||||
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
|
||||
// Envlock + conlock
|
||||
s32 playSound(const SimpleSoundSpec &spec, const ServerSoundParams ¶ms);
|
||||
@ -620,14 +598,11 @@ private:
|
||||
*/
|
||||
|
||||
// Envlock and conlock should be locked when calling these
|
||||
void SendMovePlayer(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 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.
|
||||
Additionally, if far_players!=NULL, players further away than
|
||||
@ -655,8 +630,8 @@ private:
|
||||
Something random
|
||||
*/
|
||||
|
||||
void DiePlayer(Player *player);
|
||||
void RespawnPlayer(Player *player);
|
||||
void DiePlayer(u16 peer_id);
|
||||
void RespawnPlayer(u16 peer_id);
|
||||
|
||||
void UpdateCrafting(u16 peer_id);
|
||||
|
||||
@ -672,6 +647,15 @@ private:
|
||||
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.
|
||||
If player is already connected, return NULL
|
||||
@ -679,7 +663,7 @@ private:
|
||||
|
||||
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
|
||||
struct PeerChange;
|
||||
|
@ -20,6 +20,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
#include "utility.h"
|
||||
#include "settings.h"
|
||||
#include "main.h" // For g_settings
|
||||
#include "content_sao.h"
|
||||
|
||||
#define PP(x) "("<<(x).X<<","<<(x).Y<<","<<(x).Z<<")"
|
||||
|
||||
@ -216,20 +217,26 @@ void cmd_teleport(std::wostringstream &os,
|
||||
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 "
|
||||
<<PP(ctx->player->getPosition()/BS)<<" to "
|
||||
<<PP(dest/BS)<<std::endl;
|
||||
|
||||
//ctx->player->setPosition(dest);
|
||||
|
||||
// Use the ServerActiveObject interface of ServerRemotePlayer
|
||||
ServerRemotePlayer *srp = static_cast<ServerRemotePlayer*>(ctx->player);
|
||||
srp->setPos(dest);
|
||||
ctx->server->SendMovePlayer(ctx->player);
|
||||
|
||||
os<< L"-!- Teleported.";
|
||||
// Use the ServerActiveObject interface of RemotePlayer
|
||||
// This forces a position change on the client
|
||||
ServerActiveObject *sao = ctx->player->getPlayerSAO();
|
||||
if(sao)
|
||||
{
|
||||
sao->setPos(dest);
|
||||
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)
|
||||
|
@ -143,7 +143,7 @@ public:
|
||||
{}
|
||||
virtual void setHP(s16 hp)
|
||||
{}
|
||||
virtual s16 getHP()
|
||||
virtual s16 getHP() const
|
||||
{ return 0; }
|
||||
|
||||
// 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
Block a user