Skip to content

Commit

Permalink
Add method set_node_visual and get_node_visual to player Lua object a…
Browse files Browse the repository at this point in the history
…nd needed logic around it to allow game to set variant_offset
  • Loading branch information
sfence committed Dec 29, 2023
1 parent 5b7b8fb commit 64e1726
Show file tree
Hide file tree
Showing 17 changed files with 241 additions and 9 deletions.
1 change: 1 addition & 0 deletions games/devtest/mods/testnodes/init.lua
Expand Up @@ -12,3 +12,4 @@ dofile(path.."/textures.lua")
dofile(path.."/overlays.lua")
dofile(path.."/variants.lua")
dofile(path.."/commands.lua")
dofile(path.."/node_visual.lua")
48 changes: 48 additions & 0 deletions games/devtest/mods/testnodes/node_visual.lua
@@ -0,0 +1,48 @@
-- add command to change node_visual

minetest.register_chatcommand("node_visual", {
params = "nodename field [value]",
description = "Change node_visual field of actual player to value or show value of field.",
func = function(name, param)
local player = minetest.get_player_by_name(name)
if not player then
return false, "No player."
end

local splits = string.split(param, " ", false, 3)

if #splits < 2 then
return false, "Expected node name and node_visual field as parameters."
end

local node_name = splits[1]
local field_name = splits[2]

if not minetest.registered_nodes[node_name] then
return false, "Unknown node "..node_name
end

local node_visual = player:get_node_visual(node_name)

if rawequal(node_visual[field_name], nil) then
return false, "Field "..field_name.." not found in node_visual."
end

if #splits > 2 then
if type(node_visual[field_name]) == "number" then
node_visual[field_name] = tonumber(splits[3])
elseif type(node_visual[field_name]) == "table" then
node_visual[field_name] = minetest.parse_json(splits[3])
if type(node_visual[field_name]) ~= "table" then
return false, "Table in json format is expected as value."
end
else
node_visual[field_name] = splits[3]
end
player:set_node_visual(node_name, node_visual)
return true, "Node "..node_name.." node_visual field "..field_name.." set to value: "..dump(node_visual[field_name])
else
return true, "Node "..node_name.." node_visual field "..field_name.." have value: "..dump(node_visual[field_name])
end
end
})
1 change: 1 addition & 0 deletions src/client/client.h
Expand Up @@ -234,6 +234,7 @@ class Client : public con::PeerHandler, public InventoryManager, public IGameDef
void handleCommand_MediaPush(NetworkPacket *pkt);
void handleCommand_MinimapModes(NetworkPacket *pkt);
void handleCommand_SetLighting(NetworkPacket *pkt);
void handleCommand_SetNodeVisual(NetworkPacket *pkt);

void ProcessData(NetworkPacket *pkt);

Expand Down
6 changes: 3 additions & 3 deletions src/database/database-files.cpp
Expand Up @@ -155,7 +155,7 @@ void PlayerDatabaseFiles::savePlayer(RemotePlayer *player)
std::string savedir = m_savedir + DIR_DELIM;
std::string path = savedir + player->getName();
bool path_found = false;
RemotePlayer testplayer("", NULL);
RemotePlayer testplayer("", NULL, NULL);

for (u32 i = 0; i < PLAYER_FILE_ALTERNATE_TRIES && !path_found; i++) {
if (!fs::PathExists(path)) {
Expand Down Expand Up @@ -201,7 +201,7 @@ bool PlayerDatabaseFiles::removePlayer(const std::string &name)
std::string players_path = m_savedir + DIR_DELIM;
std::string path = players_path + name;

RemotePlayer temp_player("", NULL);
RemotePlayer temp_player("", NULL, NULL);
for (u32 i = 0; i < PLAYER_FILE_ALTERNATE_TRIES; i++) {
// Open file and deserialize
std::ifstream is(path.c_str(), std::ios_base::binary);
Expand Down Expand Up @@ -263,7 +263,7 @@ void PlayerDatabaseFiles::listPlayers(std::vector<std::string> &res)
if (!is.good())
continue;

RemotePlayer player(filename.c_str(), NULL);
RemotePlayer player(filename.c_str(), NULL, NULL);
// Null env & dummy peer_id
PlayerSAO playerSAO(NULL, &player, 15789, false);

Expand Down
4 changes: 3 additions & 1 deletion src/mapnode.cpp
Expand Up @@ -55,7 +55,9 @@ void MapNode::getColor(const ContentFeatures &f, video::SColor *color) const

u16 MapNode::getVariant(const ContentFeatures &f) const
{
return f.variant_count > 1 ? f.param2_variant.get(param2) % f.variant_count : 0;
if (f.variant_count > 1)
return (f.param2_variant.get(param2) + f.variant_offset) % f.variant_count;
return 0;
}

u8 MapNode::getFaceDir(const NodeDefManager *nodemgr,
Expand Down
2 changes: 1 addition & 1 deletion src/network/clientopcodes.cpp
Expand Up @@ -118,7 +118,7 @@ const ToClientCommandHandler toClientCommandTable[TOCLIENT_NUM_MSG_TYPES] =
{ "TOCLIENT_SET_MOON", TOCLIENT_STATE_CONNECTED, &Client::handleCommand_HudSetMoon }, // 0x5b
{ "TOCLIENT_SET_STARS", TOCLIENT_STATE_CONNECTED, &Client::handleCommand_HudSetStars }, // 0x5c
null_command_handler,
null_command_handler,
{ "TOCLIENT_SET_NODE_VISUAL", TOCLIENT_STATE_CONNECTED, &Client::handleCommand_SetNodeVisual }, // 0x5e
null_command_handler,
{ "TOCLIENT_SRP_BYTES_S_B", TOCLIENT_STATE_NOT_CONNECTED, &Client::handleCommand_SrpBytesSandB }, // 0x60
{ "TOCLIENT_FORMSPEC_PREPEND", TOCLIENT_STATE_CONNECTED, &Client::handleCommand_FormspecPrepend }, // 0x61,
Expand Down
13 changes: 13 additions & 0 deletions src/network/clientpackethandler.cpp
Expand Up @@ -1805,3 +1805,16 @@ void Client::handleCommand_SetLighting(NetworkPacket *pkt)
>> lighting.exposure.center_weight_power;
}
}

void Client::handleCommand_SetNodeVisual(NetworkPacket *pkt)
{
std::string node_name;
NodeVisual node_visual;

*pkt >> node_name;

if (pkt->getRemainingBytes() >= 2)
*pkt >> node_visual.variant_offset;

m_nodedef->applyNodeVisual(node_name, node_visual);
}
6 changes: 6 additions & 0 deletions src/network/networkprotocol.h
Expand Up @@ -832,6 +832,12 @@ enum ToClientCommand
f32 day_opacity
*/

TOCLIENT_SET_NODE_VISUAL = 0x5e,
/*
std::string nodename
u16 variant_offset
*/

TOCLIENT_SRP_BYTES_S_B = 0x60,
/*
Belonging to AUTH_MECHANISM_SRP.
Expand Down
32 changes: 32 additions & 0 deletions src/nodedef.cpp
Expand Up @@ -380,6 +380,7 @@ void ContentFeatures::reset()
param_type = CPT_NONE;
param_type_2 = CPT2_NONE;
variant_count = 1;
variant_offset = 0;
param2_variant = BitField<u8>();
is_ground_content = false;
light_propagates = false;
Expand Down Expand Up @@ -1078,6 +1079,22 @@ void ContentFeatures::updateTextures(ITextureSource *tsrc, IShaderSource *shdsrc
}
#endif

/*
NodeVisual
*/

NodeVisual::NodeVisual() : variant_offset(0)
{
}
NodeVisual::NodeVisual(const ContentFeatures &f)
{
from_contentFeature(f);
}
void NodeVisual::from_contentFeature(const ContentFeatures &f)
{
variant_offset = f.variant_offset;
}

/*
NodeDefManager
*/
Expand Down Expand Up @@ -1230,6 +1247,21 @@ const ContentFeatures& NodeDefManager::get(const std::string &name) const
return get(id);
}

void NodeDefManager::getNodeVisual(const std::string &name, NodeVisual &node_visual) const
{
const ContentFeatures &f = get(name);
node_visual.from_contentFeature(f);
}

void NodeDefManager::applyNodeVisual(const std::string &name, const NodeVisual &node_visual)
{
content_t c = getId(name);
if (c < m_content_features.size() && !m_content_features[c].name.empty()) {
ContentFeatures& f = m_content_features[c];

f.variant_offset = node_visual.variant_offset;
}
}

// returns CONTENT_IGNORE if no free ID found
content_t NodeDefManager::allocateId()
Expand Down
25 changes: 25 additions & 0 deletions src/nodedef.h
Expand Up @@ -341,6 +341,8 @@ struct ContentFeatures
ContentParamType2 param_type_2;
// Number of node variants
u16 variant_count = 1;
// Node variant offset
u16 variant_offset = 0;
// Bit field for variant in param2
BitField<u8> param2_variant;

Expand Down Expand Up @@ -538,6 +540,15 @@ struct ContentFeatures
u8 getAlphaForLegacy() const;
};

struct NodeVisual {
u16 variant_offset = 0;

NodeVisual();
NodeVisual(const ContentFeatures &f);

void from_contentFeature(const ContentFeatures &f);
};

/*!
* @brief This class is for getting the actual properties of nodes from their
* content ID.
Expand Down Expand Up @@ -633,6 +644,20 @@ class NodeDefManager {
return m_selection_box_int_union;
}

/*!
* Get NodeVisual object of node
* @param name a node name
* @param node_visual NodeVisual object to be set
*/
void getNodeVisual(const std::string &name, NodeVisual &node_visual) const;

/*!
* Apply NodeVisual object to node
* @param name a node name
* @param node_visual NodeVisual object to be applied to node
*/
void applyNodeVisual(const std::string &name, const NodeVisual &node_visual);

/*!
* Checks whether a node connects to an adjacent node.
* @param from the node to be checked
Expand Down
22 changes: 21 additions & 1 deletion src/remoteplayer.cpp
Expand Up @@ -37,7 +37,7 @@ bool RemotePlayer::m_setting_cache_loaded = false;
float RemotePlayer::m_setting_chat_message_limit_per_10sec = 0.0f;
u16 RemotePlayer::m_setting_chat_message_limit_trigger_kick = 0;

RemotePlayer::RemotePlayer(const char *name, IItemDefManager *idef):
RemotePlayer::RemotePlayer(const char *name, IItemDefManager *idef, NodeDefManager *ndef):
Player(name, idef)
{
if (!RemotePlayer::m_setting_cache_loaded) {
Expand Down Expand Up @@ -67,6 +67,9 @@ RemotePlayer::RemotePlayer(const char *name, IItemDefManager *idef):
m_sun_params = SkyboxDefaults::getSunDefaults();
m_moon_params = SkyboxDefaults::getMoonDefaults();
m_star_params = SkyboxDefaults::getStarDefaults();

// NodeDefManager forNodeDefManager for NodeVisual
m_ndef = ndef;
}


Expand Down Expand Up @@ -109,6 +112,23 @@ RemotePlayerChatResult RemotePlayer::canSendChatMessage()
return RPLAYER_CHATRESULT_OK;
}

void RemotePlayer::setNodeVisual(const std::string &node_name, const NodeVisual &node_visual)
{
content_t c = m_ndef->getId(node_name);

m_node_visuals[c] = node_visual;
}

void RemotePlayer::getNodeVisual(const std::string &node_name, NodeVisual &node_visual)
{
content_t c = m_ndef->getId(node_name);

if (m_node_visuals.find(c) != m_node_visuals.end())
node_visual = m_node_visuals[c];
else
node_visual.from_contentFeature(m_ndef->get(c));
}

void RemotePlayer::onSuccessfulSave()
{
setModified(false);
Expand Down
10 changes: 9 additions & 1 deletion src/remoteplayer.h
Expand Up @@ -23,6 +23,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "player.h"
#include "skyparams.h"
#include "lighting.h"
#include "nodedef.h"

class PlayerSAO;

Expand All @@ -41,7 +42,7 @@ class RemotePlayer : public Player
friend class PlayerDatabaseFiles;

public:
RemotePlayer(const char *name, IItemDefManager *idef);
RemotePlayer(const char *name, IItemDefManager *idef, NodeDefManager *ndef);
virtual ~RemotePlayer() = default;

PlayerSAO *getPlayerSAO() { return m_sao; }
Expand Down Expand Up @@ -130,6 +131,10 @@ class RemotePlayer : public Player

const Lighting& getLighting() const { return m_lighting; }

void setNodeVisual(const std::string &node_name, const NodeVisual &node_visual);

void getNodeVisual(const std::string &node_name, NodeVisual &node_visual);

void setDirty(bool dirty) { m_dirty = true; }

u16 protocol_version = 0;
Expand Down Expand Up @@ -167,5 +172,8 @@ class RemotePlayer : public Player

Lighting m_lighting;

NodeDefManager *m_ndef;
std::map<content_t, NodeVisual> m_node_visuals;

session_t m_peer_id = PEER_ID_INEXISTENT;
};
47 changes: 47 additions & 0 deletions src/script/lua_api/l_object.cpp
Expand Up @@ -30,6 +30,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "remoteplayer.h"
#include "server.h"
#include "hud.h"
#include "nodedef.h"
#include "scripting_server.h"
#include "server/luaentity_sao.h"
#include "server/player_sao.h"
Expand Down Expand Up @@ -2404,6 +2405,50 @@ int ObjectRef::l_get_lighting(lua_State *L)
return 1;
}

// set_node_visual(self, node_name, node_visual)
int ObjectRef::l_set_node_visual(lua_State *L)
{
NO_MAP_LOCK_REQUIRED;
ObjectRef *ref = checkObject<ObjectRef>(L, 1);
RemotePlayer *player = getplayer(ref);
if (player == nullptr)
return 0;

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

NodeVisual node_visual;
player->getNodeVisual(node_name, node_visual);
NodeVisual new_visual = node_visual;

if (!lua_isnoneornil(L, 3)) {
luaL_checktype(L, 3, LUA_TTABLE);
new_visual.variant_offset = getfloatfield_default(L, -1, "variant_offset", node_visual.variant_offset);
}

getServer(L)->setNodeVisual(player, node_name, new_visual);
return 0;
}

// get_node_visual(self, node_name)
int ObjectRef::l_get_node_visual(lua_State *L)
{
NO_MAP_LOCK_REQUIRED;
ObjectRef *ref = checkObject<ObjectRef>(L, 1);
RemotePlayer *player = getplayer(ref);
if (player == nullptr)
return 0;

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

NodeVisual node_visual;
player->getNodeVisual(node_name, node_visual);

lua_newtable(L); // result
lua_pushnumber(L, node_visual.variant_offset);
lua_setfield(L, -2, "variant_offset");
return 1;
}

// respawn(self)
int ObjectRef::l_respawn(lua_State *L)
{
Expand Down Expand Up @@ -2558,6 +2603,8 @@ luaL_Reg ObjectRef::methods[] = {
luamethod(ObjectRef, set_minimap_modes),
luamethod(ObjectRef, set_lighting),
luamethod(ObjectRef, get_lighting),
luamethod(ObjectRef, set_node_visual),
luamethod(ObjectRef, get_node_visual),
luamethod(ObjectRef, respawn),

{0,0}
Expand Down
6 changes: 6 additions & 0 deletions src/script/lua_api/l_object.h
Expand Up @@ -382,6 +382,12 @@ class ObjectRef : public ModApiBase {
// get_lighting(self)
static int l_get_lighting(lua_State *L);

// set_node_visual(self, node_name, node_visual)
static int l_set_node_visual(lua_State *L);

// get_node_visual(self, node_name)
static int l_get_node_visual(lua_State *L);

// respawn(self)
static int l_respawn(lua_State *L);
};

0 comments on commit 64e1726

Please sign in to comment.