Add minetest.swap_node

This commit is contained in:
Novatux 2013-11-23 15:35:49 +01:00
parent 752e11e114
commit d879a539cd
12 changed files with 82 additions and 29 deletions

@ -1318,18 +1318,13 @@ minetest.register_node("default:furnace_active", {
end, end,
}) })
function hacky_swap_node(pos,name) function swap_node(pos,name)
local node = minetest.get_node(pos) local node = minetest.get_node(pos)
local meta = minetest.get_meta(pos)
local meta0 = meta:to_table()
if node.name == name then if node.name == name then
return return
end end
node.name = name node.name = name
local meta0 = meta:to_table() minetest.swap_node(pos, node)
minetest.set_node(pos,node)
meta = minetest.get_meta(pos)
meta:from_table(meta0)
end end
minetest.register_abm({ minetest.register_abm({
@ -1384,7 +1379,7 @@ minetest.register_abm({
local percent = math.floor(meta:get_float("fuel_time") / local percent = math.floor(meta:get_float("fuel_time") /
meta:get_float("fuel_totaltime") * 100) meta:get_float("fuel_totaltime") * 100)
meta:set_string("infotext","Furnace active: "..percent.."%") meta:set_string("infotext","Furnace active: "..percent.."%")
hacky_swap_node(pos,"default:furnace_active") swap_node(pos,"default:furnace_active")
meta:set_string("formspec", meta:set_string("formspec",
"size[8,9]".. "size[8,9]"..
"image[2,2;1,1;default_furnace_fire_bg.png^[lowpart:".. "image[2,2;1,1;default_furnace_fire_bg.png^[lowpart:"..
@ -1410,7 +1405,7 @@ minetest.register_abm({
if fuel.time <= 0 then if fuel.time <= 0 then
meta:set_string("infotext","Furnace out of fuel") meta:set_string("infotext","Furnace out of fuel")
hacky_swap_node(pos,"default:furnace") swap_node(pos,"default:furnace")
meta:set_string("formspec", default.furnace_inactive_formspec) meta:set_string("formspec", default.furnace_inactive_formspec)
return return
end end
@ -1418,7 +1413,7 @@ minetest.register_abm({
if cooked.item:is_empty() then if cooked.item:is_empty() then
if was_active then if was_active then
meta:set_string("infotext","Furnace is empty") meta:set_string("infotext","Furnace is empty")
hacky_swap_node(pos,"default:furnace") swap_node(pos,"default:furnace")
meta:set_string("formspec", default.furnace_inactive_formspec) meta:set_string("formspec", default.furnace_inactive_formspec)
end end
return return

@ -1262,7 +1262,13 @@ void Client::ProcessData(u8 *data, u32 datasize, u16 sender_peer_id)
MapNode n; MapNode n;
n.deSerialize(&data[8], ser_version); n.deSerialize(&data[8], ser_version);
addNode(p, n); bool remove_metadata = true;
u32 index = 8 + MapNode::serializedLength(ser_version);
if ((datasize >= index+1) && data[index]){
remove_metadata = false;
}
addNode(p, n, remove_metadata);
} }
else if(command == TOCLIENT_BLOCKDATA) else if(command == TOCLIENT_BLOCKDATA)
{ {
@ -2514,7 +2520,7 @@ void Client::removeNode(v3s16 p)
} }
} }
void Client::addNode(v3s16 p, MapNode n) void Client::addNode(v3s16 p, MapNode n, bool remove_metadata)
{ {
TimeTaker timer1("Client::addNode()"); TimeTaker timer1("Client::addNode()");
@ -2523,7 +2529,7 @@ void Client::addNode(v3s16 p, MapNode n)
try try
{ {
//TimeTaker timer3("Client::addNode(): addNodeAndUpdate"); //TimeTaker timer3("Client::addNode(): addNodeAndUpdate");
m_env.getMap().addNodeAndUpdate(p, n, modified_blocks); m_env.getMap().addNodeAndUpdate(p, n, modified_blocks, remove_metadata);
} }
catch(InvalidPositionException &e) catch(InvalidPositionException &e)
{} {}

@ -365,7 +365,7 @@ public:
// Causes urgent mesh updates (unlike Map::add/removeNodeWithEvent) // Causes urgent mesh updates (unlike Map::add/removeNodeWithEvent)
void removeNode(v3s16 p); void removeNode(v3s16 p);
void addNode(v3s16 p, MapNode n); void addNode(v3s16 p, MapNode n, bool remove_metadata = true);
void setPlayerControl(PlayerControl &control); void setPlayerControl(PlayerControl &control);

@ -102,7 +102,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
added to object properties added to object properties
*/ */
#define LATEST_PROTOCOL_VERSION 21 #define LATEST_PROTOCOL_VERSION 22
// Server's supported network protocol range // Server's supported network protocol range
#define SERVER_PROTOCOL_VERSION_MIN 13 #define SERVER_PROTOCOL_VERSION_MIN 13
@ -139,6 +139,12 @@ enum ToClientCommand
TOCLIENT_BLOCKDATA = 0x20, //TODO: Multiple blocks TOCLIENT_BLOCKDATA = 0x20, //TODO: Multiple blocks
TOCLIENT_ADDNODE = 0x21, TOCLIENT_ADDNODE = 0x21,
/*
u16 command
v3s16 position
serialized mapnode
u8 keep_metadata // Added in protocol version 22
*/
TOCLIENT_REMOVENODE = 0x22, TOCLIENT_REMOVENODE = 0x22,
TOCLIENT_PLAYERPOS = 0x23, // Obsolete TOCLIENT_PLAYERPOS = 0x23, // Obsolete

@ -874,6 +874,11 @@ bool ServerEnvironment::removeNode(v3s16 p)
return true; return true;
} }
bool ServerEnvironment::swapNode(v3s16 p, const MapNode &n)
{
return m_map->addNodeWithEvent(p, n, false);
}
std::set<u16> ServerEnvironment::getObjectsInsideRadius(v3f pos, float radius) std::set<u16> ServerEnvironment::getObjectsInsideRadius(v3f pos, float radius)
{ {
std::set<u16> objects; std::set<u16> objects;

@ -283,6 +283,7 @@ public:
// Script-aware node setters // Script-aware node setters
bool setNode(v3s16 p, const MapNode &n); bool setNode(v3s16 p, const MapNode &n);
bool removeNode(v3s16 p); bool removeNode(v3s16 p);
bool swapNode(v3s16 p, const MapNode &n);
// Find all active objects inside a radius around a point // Find all active objects inside a radius around a point
std::set<u16> getObjectsInsideRadius(v3f pos, float radius); std::set<u16> getObjectsInsideRadius(v3f pos, float radius);

@ -931,7 +931,8 @@ void Map::updateLighting(std::map<v3s16, MapBlock*> & a_blocks,
/* /*
*/ */
void Map::addNodeAndUpdate(v3s16 p, MapNode n, void Map::addNodeAndUpdate(v3s16 p, MapNode n,
std::map<v3s16, MapBlock*> &modified_blocks) std::map<v3s16, MapBlock*> &modified_blocks,
bool remove_metadata)
{ {
INodeDefManager *ndef = m_gamedef->ndef(); INodeDefManager *ndef = m_gamedef->ndef();
@ -1018,8 +1019,9 @@ void Map::addNodeAndUpdate(v3s16 p, MapNode n,
/* /*
Remove node metadata Remove node metadata
*/ */
if (remove_metadata) {
removeNodeMetadata(p); removeNodeMetadata(p);
}
/* /*
Set the node on the map Set the node on the map
@ -1319,17 +1321,17 @@ void Map::removeNodeAndUpdate(v3s16 p,
} }
} }
bool Map::addNodeWithEvent(v3s16 p, MapNode n) bool Map::addNodeWithEvent(v3s16 p, MapNode n, bool remove_metadata)
{ {
MapEditEvent event; MapEditEvent event;
event.type = MEET_ADDNODE; event.type = remove_metadata ? MEET_ADDNODE : MEET_SWAPNODE;
event.p = p; event.p = p;
event.n = n; event.n = n;
bool succeeded = true; bool succeeded = true;
try{ try{
std::map<v3s16, MapBlock*> modified_blocks; std::map<v3s16, MapBlock*> modified_blocks;
addNodeAndUpdate(p, n, modified_blocks); addNodeAndUpdate(p, n, modified_blocks, remove_metadata);
// Copy modified_blocks to event // Copy modified_blocks to event
for(std::map<v3s16, MapBlock*>::iterator for(std::map<v3s16, MapBlock*>::iterator

@ -61,6 +61,8 @@ enum MapEditEventType{
MEET_ADDNODE, MEET_ADDNODE,
// Node removed (changed to air) // Node removed (changed to air)
MEET_REMOVENODE, MEET_REMOVENODE,
// Node swapped (changed without metadata change)
MEET_SWAPNODE,
// Node metadata of block changed (not knowing which node exactly) // Node metadata of block changed (not knowing which node exactly)
// p stores block coordinate // p stores block coordinate
MEET_BLOCK_NODE_METADATA_CHANGED, MEET_BLOCK_NODE_METADATA_CHANGED,
@ -99,6 +101,8 @@ struct MapEditEvent
return VoxelArea(p); return VoxelArea(p);
case MEET_REMOVENODE: case MEET_REMOVENODE:
return VoxelArea(p); return VoxelArea(p);
case MEET_SWAPNODE:
return VoxelArea(p);
case MEET_BLOCK_NODE_METADATA_CHANGED: case MEET_BLOCK_NODE_METADATA_CHANGED:
{ {
v3s16 np1 = p*MAP_BLOCKSIZE; v3s16 np1 = p*MAP_BLOCKSIZE;
@ -236,7 +240,8 @@ public:
These handle lighting but not faces. These handle lighting but not faces.
*/ */
void addNodeAndUpdate(v3s16 p, MapNode n, void addNodeAndUpdate(v3s16 p, MapNode n,
std::map<v3s16, MapBlock*> &modified_blocks); std::map<v3s16, MapBlock*> &modified_blocks,
bool remove_metadata = true);
void removeNodeAndUpdate(v3s16 p, void removeNodeAndUpdate(v3s16 p,
std::map<v3s16, MapBlock*> &modified_blocks); std::map<v3s16, MapBlock*> &modified_blocks);
@ -245,7 +250,7 @@ public:
These emit events. These emit events.
Return true if succeeded, false if not. Return true if succeeded, false if not.
*/ */
bool addNodeWithEvent(v3s16 p, MapNode n); bool addNodeWithEvent(v3s16 p, MapNode n, bool remove_metadata = true);
bool removeNodeWithEvent(v3s16 p); bool removeNodeWithEvent(v3s16 p);
/* /*

@ -120,6 +120,22 @@ int ModApiEnvMod::l_remove_node(lua_State *L)
return 1; return 1;
} }
// minetest.swap_node(pos, node)
// pos = {x=num, y=num, z=num}
int ModApiEnvMod::l_swap_node(lua_State *L)
{
GET_ENV_PTR;
INodeDefManager *ndef = env->getGameDef()->ndef();
// parameters
v3s16 pos = read_v3s16(L, 1);
MapNode n = readnode(L, 2, ndef);
// Do it
bool succeeded = env->swapNode(pos, n);
lua_pushboolean(L, succeeded);
return 1;
}
// minetest.get_node(pos) // minetest.get_node(pos)
// pos = {x=num, y=num, z=num} // pos = {x=num, y=num, z=num}
int ModApiEnvMod::l_get_node(lua_State *L) int ModApiEnvMod::l_get_node(lua_State *L)
@ -798,6 +814,7 @@ void ModApiEnvMod::Initialize(lua_State *L, int top)
{ {
API_FCT(set_node); API_FCT(set_node);
API_FCT(add_node); API_FCT(add_node);
API_FCT(swap_node);
API_FCT(add_item); API_FCT(add_item);
API_FCT(remove_node); API_FCT(remove_node);
API_FCT(get_node); API_FCT(get_node);

@ -35,6 +35,10 @@ private:
// pos = {x=num, y=num, z=num} // pos = {x=num, y=num, z=num}
static int l_remove_node(lua_State *L); static int l_remove_node(lua_State *L);
// minetest.swap_node(pos, node)
// pos = {x=num, y=num, z=num}
static int l_swap_node(lua_State *L);
// minetest.get_node(pos) // minetest.get_node(pos)
// pos = {x=num, y=num, z=num} // pos = {x=num, y=num, z=num}
static int l_get_node(lua_State *L); static int l_get_node(lua_State *L);

@ -1582,16 +1582,16 @@ void Server::AsyncRunStep()
// for them. // for them.
std::list<u16> far_players; std::list<u16> far_players;
if(event->type == MEET_ADDNODE) if(event->type == MEET_ADDNODE || event->type == MEET_SWAPNODE)
{ {
//infostream<<"Server: MEET_ADDNODE"<<std::endl; //infostream<<"Server: MEET_ADDNODE"<<std::endl;
prof.add("MEET_ADDNODE", 1); prof.add("MEET_ADDNODE", 1);
if(disable_single_change_sending) if(disable_single_change_sending)
sendAddNode(event->p, event->n, event->already_known_by_peer, sendAddNode(event->p, event->n, event->already_known_by_peer,
&far_players, 5); &far_players, 5, event->type == MEET_ADDNODE);
else else
sendAddNode(event->p, event->n, event->already_known_by_peer, sendAddNode(event->p, event->n, event->already_known_by_peer,
&far_players, 30); &far_players, 30, event->type == MEET_ADDNODE);
} }
else if(event->type == MEET_REMOVENODE) else if(event->type == MEET_REMOVENODE)
{ {
@ -4070,7 +4070,8 @@ void Server::sendRemoveNode(v3s16 p, u16 ignore_id,
} }
void Server::sendAddNode(v3s16 p, MapNode n, u16 ignore_id, void Server::sendAddNode(v3s16 p, MapNode n, u16 ignore_id,
std::list<u16> *far_players, float far_d_nodes) std::list<u16> *far_players, float far_d_nodes,
bool remove_metadata)
{ {
float maxd = far_d_nodes*BS; float maxd = far_d_nodes*BS;
v3f p_f = intToFloat(p, BS); v3f p_f = intToFloat(p, BS);
@ -4106,13 +4107,23 @@ void Server::sendAddNode(v3s16 p, MapNode n, u16 ignore_id,
} }
// Create packet // Create packet
u32 replysize = 8 + MapNode::serializedLength(client->serialization_version); u32 replysize = 9 + MapNode::serializedLength(client->serialization_version);
SharedBuffer<u8> reply(replysize); SharedBuffer<u8> reply(replysize);
writeU16(&reply[0], TOCLIENT_ADDNODE); writeU16(&reply[0], TOCLIENT_ADDNODE);
writeS16(&reply[2], p.X); writeS16(&reply[2], p.X);
writeS16(&reply[4], p.Y); writeS16(&reply[4], p.Y);
writeS16(&reply[6], p.Z); writeS16(&reply[6], p.Z);
n.serialize(&reply[8], client->serialization_version); n.serialize(&reply[8], client->serialization_version);
u32 index = 8 + MapNode::serializedLength(client->serialization_version);
writeU8(&reply[index], remove_metadata ? 0 : 1);
if (!remove_metadata) {
if (client->net_proto_version <= 21) {
// Old clients always clear metadata; fix it
// by sending the full block again.
client->SetBlockNotSent(p);
}
}
// Send as reliable // Send as reliable
m_con.Send(client->peer_id, 0, reply, true); m_con.Send(client->peer_id, 0, reply, true);

@ -556,7 +556,8 @@ private:
void sendRemoveNode(v3s16 p, u16 ignore_id=0, void sendRemoveNode(v3s16 p, u16 ignore_id=0,
std::list<u16> *far_players=NULL, float far_d_nodes=100); std::list<u16> *far_players=NULL, float far_d_nodes=100);
void sendAddNode(v3s16 p, MapNode n, u16 ignore_id=0, void sendAddNode(v3s16 p, MapNode n, u16 ignore_id=0,
std::list<u16> *far_players=NULL, float far_d_nodes=100); std::list<u16> *far_players=NULL, float far_d_nodes=100,
bool remove_metadata=true);
void setBlockNotSent(v3s16 p); void setBlockNotSent(v3s16 p);
// Environment and Connection must be locked when called // Environment and Connection must be locked when called