157 changes: 146 additions & 11 deletions src/script/lua_api/l_object.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "server/luaentity_sao.h"
#include "server/player_sao.h"
#include "server/serverinventorymgr.h"
#include "server/unit_sao.h"

/*
ObjectRef
Expand Down Expand Up @@ -512,37 +513,168 @@ int ObjectRef::l_set_animation_frame_speed(lua_State *L)
int ObjectRef::l_set_bone_position(lua_State *L)
{
NO_MAP_LOCK_REQUIRED;

log_deprecated(L,"Deprecated call to set_bone_position, use set_bone_override instead");

ObjectRef *ref = checkObject<ObjectRef>(L, 1);
ServerActiveObject *sao = getobject(ref);
if (sao == nullptr)
return 0;

std::string bone = readParam<std::string>(L, 2, "");
v3f position = readParam<v3f>(L, 3, v3f(0, 0, 0));
v3f rotation = readParam<v3f>(L, 4, v3f(0, 0, 0));

sao->setBonePosition(bone, position, rotation);
std::string bone;
appgurueu marked this conversation as resolved.
Show resolved Hide resolved
if (!lua_isnil(L, 2))
bone = readParam<std::string>(L, 2);
BoneOverride props;
if (!lua_isnil(L, 3))
props.position.vector = check_v3f(L, 3);
if (!lua_isnil(L, 4))
props.rotation.next = core::quaternion(check_v3f(L, 4) * core::DEGTORAD);
props.position.absolute = true;
props.rotation.absolute = true;
sao->setBoneOverride(bone, props);
return 0;
}

// get_bone_position(self, bone)
int ObjectRef::l_get_bone_position(lua_State *L)
{
NO_MAP_LOCK_REQUIRED;

log_deprecated(L,"Deprecated call to get_bone_position, use get_bone_override instead");

ObjectRef *ref = checkObject<ObjectRef>(L, 1);
ServerActiveObject *sao = getobject(ref);
if (sao == nullptr)
return 0;

std::string bone = readParam<std::string>(L, 2, "");
BoneOverride props = sao->getBoneOverride(bone);
push_v3f(L, props.position.vector);
v3f euler_rot;
props.rotation.next.toEuler(euler_rot);
push_v3f(L, euler_rot * core::RADTODEG);
return 2;
}

// set_bone_override(self, bone, override)
int ObjectRef::l_set_bone_override(lua_State *L)
{
NO_MAP_LOCK_REQUIRED;
ObjectRef *ref = checkObject<ObjectRef>(L, 1);
ServerActiveObject *sao = getobject(ref);
if (sao == NULL)
return 0;

v3f position = v3f(0, 0, 0);
v3f rotation = v3f(0, 0, 0);
sao->getBonePosition(bone, &position, &rotation);
std::string bone = readParam<std::string>(L, 2);

push_v3f(L, position);
push_v3f(L, rotation);
return 2;
BoneOverride props;
if (lua_isnoneornil(L, 3)) {
sao->setBoneOverride(bone, props);
return 0;
}

auto read_prop_attrs = [L](auto &prop) {
lua_getfield(L, -1, "absolute");
prop.absolute = lua_toboolean(L, -1);
lua_pop(L, 1);

lua_getfield(L, -1, "interpolate");
if (lua_isnumber(L, -1))
prop.interp_timer = lua_tonumber(L, -1);
lua_pop(L, 1);
};

lua_getfield(L, 3, "position");
if (!lua_isnil(L, -1)) {
lua_getfield(L, -1, "vec");
if (!lua_isnil(L, -1))
props.position.vector = check_v3f(L, -1);
lua_pop(L, 1);

read_prop_attrs(props.position);
}
lua_pop(L, 1);

lua_getfield(L, 3, "rotation");
if (!lua_isnil(L, -1)) {
lua_getfield(L, -1, "vec");
if (!lua_isnil(L, -1))
props.rotation.next = core::quaternion(check_v3f(L, -1));
lua_pop(L, 1);

read_prop_attrs(props.rotation);
}
lua_pop(L, 1);

lua_getfield(L, 3, "scale");
if (!lua_isnil(L, -1)) {
lua_getfield(L, -1, "vec");
props.scale.vector = lua_isnil(L, -1) ? v3f(1) : check_v3f(L, -1);
lua_pop(L, 1);

read_prop_attrs(props.scale);
}
lua_pop(L, 1);

sao->setBoneOverride(bone, props);
return 0;
}

static void push_bone_override(lua_State *L, const BoneOverride &props)
{
lua_newtable(L);

auto push_prop = [L](const char *name, const auto &prop, v3f vec) {
lua_newtable(L);
push_v3f(L, vec);
lua_setfield(L, -2, "vec");
lua_pushnumber(L, prop.interp_timer);
lua_setfield(L, -2, "interpolate");
lua_pushboolean(L, prop.absolute);
lua_setfield(L, -2, "absolute");
lua_setfield(L, -2, name);
};

push_prop("position", props.position, props.position.vector);

v3f euler_rot;
props.rotation.next.toEuler(euler_rot);
push_prop("rotation", props.rotation, euler_rot);

push_prop("scale", props.scale, props.scale.vector);

// leave only override table on top of the stack
}

// get_bone_override(self, bone)
int ObjectRef::l_get_bone_override(lua_State *L)
{
NO_MAP_LOCK_REQUIRED;
ObjectRef *ref = checkObject<ObjectRef>(L, 1);
ServerActiveObject *sao = getobject(ref);
if (sao == NULL)
return 0;

std::string bone = readParam<std::string>(L, 2);

push_bone_override(L, sao->getBoneOverride(bone));
appgurueu marked this conversation as resolved.
Show resolved Hide resolved
return 1;
}

// get_bone_overrides(self)
int ObjectRef::l_get_bone_overrides(lua_State *L)
{
NO_MAP_LOCK_REQUIRED;
ObjectRef *ref = checkObject<ObjectRef>(L, 1);
ServerActiveObject *co = getobject(ref);
if (co == NULL)
return 0;
lua_newtable(L);
for (const auto &bone_pos : co->getBoneOverrides()) {
push_bone_override(L, bone_pos.second);
appgurueu marked this conversation as resolved.
Show resolved Hide resolved
lua_setfield(L, -2, bone_pos.first.c_str());
}
return 1;
}

// set_attach(self, parent, bone, position, rotation, force_visible)
Expand Down Expand Up @@ -2465,6 +2597,9 @@ luaL_Reg ObjectRef::methods[] = {
luamethod(ObjectRef, set_animation_frame_speed),
luamethod(ObjectRef, set_bone_position),
luamethod(ObjectRef, get_bone_position),
luamethod(ObjectRef, set_bone_override),
luamethod(ObjectRef, get_bone_override),
luamethod(ObjectRef, get_bone_overrides),
luamethod(ObjectRef, set_attach),
luamethod(ObjectRef, get_attach),
luamethod(ObjectRef, get_children),
Expand Down
9 changes: 9 additions & 0 deletions src/script/lua_api/l_object.h
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,15 @@ class ObjectRef : public ModApiBase {
// get_bone_position(self, bone)
static int l_get_bone_position(lua_State *L);

// set_bone_override(self, bone)
static int l_set_bone_override(lua_State *L);

// get_bone_override(self, bone)
static int l_get_bone_override(lua_State *L);

// get_bone_override(self)
static int l_get_bone_overrides(lua_State *L);

// set_attach(self, parent, bone, position, rotation)
static int l_set_attach(lua_State *L);

Expand Down
10 changes: 5 additions & 5 deletions src/server/luaentity_sao.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -256,13 +256,13 @@ std::string LuaEntitySAO::getClientInitializationData(u16 protocol_version)
msg_os << serializeString32(getPropertyPacket()); // message 1
msg_os << serializeString32(generateUpdateArmorGroupsCommand()); // 2
msg_os << serializeString32(generateUpdateAnimationCommand()); // 3
for (const auto &bone_pos : m_bone_position) {
msg_os << serializeString32(generateUpdateBonePositionCommand(
bone_pos.first, bone_pos.second.X, bone_pos.second.Y)); // 3 + N
for (const auto &bone_override : m_bone_override) {
msg_os << serializeString32(generateUpdateBoneOverrideCommand(
bone_override.first, bone_override.second)); // 3 + N
}
msg_os << serializeString32(generateUpdateAttachmentCommand()); // 4 + m_bone_position.size
msg_os << serializeString32(generateUpdateAttachmentCommand()); // 4 + m_bone_override.size

int message_count = 4 + m_bone_position.size();
int message_count = 4 + m_bone_override.size();

for (const auto &id : getAttachmentChildIds()) {
if (ServerActiveObject *obj = m_env->getActiveObject(id)) {
Expand Down
12 changes: 6 additions & 6 deletions src/server/player_sao.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -121,14 +121,14 @@ std::string PlayerSAO::getClientInitializationData(u16 protocol_version)
msg_os << serializeString32(getPropertyPacket()); // message 1
msg_os << serializeString32(generateUpdateArmorGroupsCommand()); // 2
msg_os << serializeString32(generateUpdateAnimationCommand()); // 3
for (const auto &bone_pos : m_bone_position) {
msg_os << serializeString32(generateUpdateBonePositionCommand(
bone_pos.first, bone_pos.second.X, bone_pos.second.Y)); // 3 + N
for (const auto &it : m_bone_override) {
msg_os << serializeString32(generateUpdateBoneOverrideCommand(
it.first, it.second)); // 3 + N
}
msg_os << serializeString32(generateUpdateAttachmentCommand()); // 4 + m_bone_position.size
msg_os << serializeString32(generateUpdatePhysicsOverrideCommand()); // 5 + m_bone_position.size
msg_os << serializeString32(generateUpdateAttachmentCommand()); // 4 + m_bone_override.size
msg_os << serializeString32(generateUpdatePhysicsOverrideCommand()); // 5 + m_bone_override.size

int message_count = 5 + m_bone_position.size();
int message_count = 5 + m_bone_override.size();

for (const auto &id : getAttachmentChildIds()) {
if (ServerActiveObject *obj = m_env->getActiveObject(id)) {
Expand Down
11 changes: 7 additions & 4 deletions src/server/serveractiveobject.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "itemgroup.h"
#include "util/container.h"


/*
Some planning
Expand Down Expand Up @@ -171,14 +172,16 @@ class ServerActiveObject : public ActiveObject
{}
virtual void setAnimationSpeed(float frame_speed)
{}
virtual void setBonePosition(const std::string &bone, v3f position, v3f rotation)
{}
virtual void getBonePosition(const std::string &bone, v3f *position, v3f *lotation)
virtual void setBoneOverride(const std::string &bone, const BoneOverride &props)
{}
virtual BoneOverride getBoneOverride(const std::string &bone)
{ BoneOverride props; return props; }
virtual const BoneOverrideMap &getBoneOverrides() const
{ static BoneOverrideMap rv; return rv; }
virtual const std::unordered_set<int> &getAttachmentChildIds() const
{ static std::unordered_set<int> rv; return rv; }
virtual ServerActiveObject *getParent() const { return nullptr; }
virtual ObjectProperties* accessObjectProperties()
virtual ObjectProperties *accessObjectProperties()
{ return NULL; }
virtual void notifyObjectPropertiesModified()
{}
Expand Down
45 changes: 27 additions & 18 deletions src/server/unit_sao.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -76,20 +76,20 @@ void UnitSAO::setAnimationSpeed(float frame_speed)
m_animation_speed_sent = false;
}

void UnitSAO::setBonePosition(const std::string &bone, v3f position, v3f rotation)
void UnitSAO::setBoneOverride(const std::string &bone, const BoneOverride &props)
{
// store these so they can be updated to clients
m_bone_position[bone] = core::vector2d<v3f>(position, rotation);
m_bone_position_sent = false;
m_bone_override[bone] = props;
m_bone_override_sent = false;
}

void UnitSAO::getBonePosition(const std::string &bone, v3f *position, v3f *rotation)
BoneOverride UnitSAO::getBoneOverride(const std::string &bone)
{
auto it = m_bone_position.find(bone);
if (it != m_bone_position.end()) {
*position = it->second.X;
*rotation = it->second.Y;
}
auto it = m_bone_override.find(bone);
BoneOverride props;
if (it != m_bone_override.end())
props = it->second;
return props;
}

// clang-format off
Expand All @@ -110,11 +110,11 @@ void UnitSAO::sendOutdatedData()
m_messages_out.emplace(getId(), true, generateUpdateAnimationSpeedCommand());
}

if (!m_bone_position_sent) {
m_bone_position_sent = true;
for (const auto &bone_pos : m_bone_position) {
m_messages_out.emplace(getId(), true, generateUpdateBonePositionCommand(
bone_pos.first, bone_pos.second.X, bone_pos.second.Y));
if (!m_bone_override_sent) {
m_bone_override_sent = true;
for (const auto &bone_pos : m_bone_override) {
m_messages_out.emplace(getId(), true, generateUpdateBoneOverrideCommand(
bone_pos.first, bone_pos.second));
}
}

Expand Down Expand Up @@ -277,16 +277,25 @@ std::string UnitSAO::generateUpdateAttachmentCommand() const
return os.str();
}

std::string UnitSAO::generateUpdateBonePositionCommand(
const std::string &bone, const v3f &position, const v3f &rotation)
std::string UnitSAO::generateUpdateBoneOverrideCommand(
const std::string &bone, const BoneOverride &props)
{
std::ostringstream os(std::ios::binary);
// command
writeU8(os, AO_CMD_SET_BONE_POSITION);
// parameters
os << serializeString16(bone);
writeV3F32(os, position);
writeV3F32(os, rotation);
writeV3F32(os, props.position.vector);
v3f euler_rot;
props.rotation.next.toEuler(euler_rot);
writeV3F32(os, euler_rot * core::RADTODEG);
SmallJoker marked this conversation as resolved.
Show resolved Hide resolved
writeV3F32(os, props.scale.vector);
writeF32(os, props.position.interp_timer);
writeF32(os, props.rotation.interp_timer);
writeF32(os, props.scale.interp_timer);
writeU8(os, (props.position.absolute & 1) << 0
| (props.rotation.absolute & 1) << 1
| (props.scale.absolute & 1) << 2);
return os.str();
}

Expand Down
14 changes: 8 additions & 6 deletions src/server/unit_sao.h
Original file line number Diff line number Diff line change
Expand Up @@ -70,8 +70,10 @@ class UnitSAO : public ServerActiveObject
void setAnimationSpeed(float frame_speed);

// Bone position
void setBonePosition(const std::string &bone, v3f position, v3f rotation);
void getBonePosition(const std::string &bone, v3f *position, v3f *rotation);
void setBoneOverride(const std::string &bone, const BoneOverride &props);
BoneOverride getBoneOverride(const std::string &bone);
const std::unordered_map<std::string, BoneOverride>
&getBoneOverrides() const { return m_bone_override; };

// Attachments
ServerActiveObject *getParent() const;
Expand Down Expand Up @@ -100,8 +102,8 @@ class UnitSAO : public ServerActiveObject
const v3f &velocity, const v3f &acceleration, const v3f &rotation,
bool do_interpolate, bool is_movement_end, f32 update_interval);
std::string generateSetPropertiesCommand(const ObjectProperties &prop) const;
static std::string generateUpdateBonePositionCommand(const std::string &bone,
const v3f &position, const v3f &rotation);
static std::string generateUpdateBoneOverrideCommand(
const std::string &bone, const BoneOverride &props);
void sendPunchCommand();

protected:
Expand All @@ -117,7 +119,7 @@ class UnitSAO : public ServerActiveObject
ObjectProperties m_prop;

// Stores position and rotation for each bone name
std::unordered_map<std::string, core::vector2d<v3f>> m_bone_position;
std::unordered_map<std::string, BoneOverride> m_bone_override;

int m_attachment_parent_id = 0;

Expand All @@ -139,7 +141,7 @@ class UnitSAO : public ServerActiveObject
bool m_animation_speed_sent = false;

// Bone positions
bool m_bone_position_sent = false;
bool m_bone_override_sent = false;

// Attachments
std::unordered_set<int> m_attachment_child_ids;
Expand Down