+ Using hashes as keys to save changed nodes positions instead of serialized tables in the maps metadata

master
Giov4 2021-02-13 16:35:08 +01:00
parent 3e16ffb923
commit c924247079
5 changed files with 59 additions and 26 deletions

View File

@ -1,6 +1,8 @@
local function delete_drops() end local function delete_drops() end
local function async_reset_map() end local function async_reset_map() end
local function reset_node_inventory() end local function reset_node_inventory() end
local get_position_from_hash = minetest.get_position_from_hash
local hash_node_position = minetest.hash_node_position
local deserialize = minetest.deserialize local deserialize = minetest.deserialize
local add_node = minetest.add_node local add_node = minetest.add_node
local get_node = minetest.get_node local get_node = minetest.get_node
@ -61,9 +63,10 @@ function async_reset_map(arena, debug, recursive_data)
-- Resets a node if it hasn't been reset yet and if it resets more than "nodes_per_tick" -- Resets a node if it hasn't been reset yet and if it resets more than "nodes_per_tick"
-- nodes it invokes this function again after one step. -- nodes it invokes this function again after one step.
arena.is_resetting = true arena.is_resetting = true
for serialized_pos, node in pairs(original_nodes_to_reset) do for hash_pos, node in pairs(original_nodes_to_reset) do
if current_index > last_index then if current_index > last_index then
local pos = deserialize(serialized_pos) local pos = get_position_from_hash(hash_pos)
add_node(pos, node) add_node(pos, node)
reset_node_inventory(pos) reset_node_inventory(pos)
end end
@ -92,21 +95,22 @@ function async_reset_map(arena, debug, recursive_data)
end end
local current_nodes_to_reset = current_maps[arena.name].changed_nodes local current_nodes_to_reset = current_maps[arena.name].changed_nodes
for serialized_pos, node in pairs(current_nodes_to_reset) do for hash_pos, node in pairs(current_nodes_to_reset) do
local always_to_be_reset = original_maps[arena.name].always_to_be_reset_nodes[serialized_pos] local always_to_be_reset = original_maps[arena.name].always_to_be_reset_nodes[hash_pos]
if not original_nodes_to_reset[serialized_pos] or always_to_be_reset then if not original_nodes_to_reset[hash_pos] or always_to_be_reset then
goto continue goto continue
end end
local old_node = original_nodes_to_reset[serialized_pos] local old_node = original_nodes_to_reset[hash_pos]
local pos = deserialize(serialized_pos) local pos = get_position_from_hash(hash_pos)
local current_node = get_node(pos) local current_node = get_node(pos)
local is_old_node_still_reset = (current_node.name == old_node.name) local is_old_node_still_reset = (current_node.name == old_node.name)
-- Checking if the node was modified again DURING the reset process but -- Checking if the node was modified again DURING the reset process but
-- AFTER being reset already. -- AFTER being reset already.
if is_old_node_still_reset then if is_old_node_still_reset then
current_nodes_to_reset[serialized_pos] = nil current_nodes_to_reset[hash_pos] = nil
end end
::continue:: ::continue::

View File

@ -1,5 +1,6 @@
local function save_node() end local function save_node() end
local get_inventory = minetest.get_inventory local get_inventory = minetest.get_inventory
local hash_node_position = minetest.hash_node_position
minetest.register_on_placenode(function(pos, newnode, player, oldnode, itemstack, pointed_thing) minetest.register_on_placenode(function(pos, newnode, player, oldnode, itemstack, pointed_thing)
@ -37,9 +38,10 @@ end)
-- Minetest functions overrides. -- Minetest functions overrides.
local set_node = minetest.set_node local set_node = minetest.set_node
local get_node = minetest.get_node
function minetest.set_node(pos, node) function minetest.set_node(pos, node)
local arena = skywars.get_arena_by_pos(pos) local arena = skywars.get_arena_by_pos(pos)
local oldnode = minetest.get_node(pos) local oldnode = get_node(pos)
if arena and arena.enabled then if arena and arena.enabled then
save_node(arena, pos, oldnode) save_node(arena, pos, oldnode)
@ -76,26 +78,26 @@ function skywars.save_nodes_with_inventories(arena)
local emerged_pos1, emerged_pos2 = manip:read_from_map(arena.min_pos, arena.max_pos) local emerged_pos1, emerged_pos2 = manip:read_from_map(arena.min_pos, arena.max_pos)
local emerged_area = VoxelArea:new({MinEdge=emerged_pos1, MaxEdge=emerged_pos2}) local emerged_area = VoxelArea:new({MinEdge=emerged_pos1, MaxEdge=emerged_pos2})
local original_area = VoxelArea:new({MinEdge=arena.min_pos, MaxEdge=arena.max_pos}) local original_area = VoxelArea:new({MinEdge=arena.min_pos, MaxEdge=arena.max_pos})
local nodes = manip:get_data()
local get_inventory = minetest.get_inventory local get_inventory = minetest.get_inventory
local get_name_from_content_id = minetest.get_name_from_content_id local hash_node_position = minetest.hash_node_position
local serialize = minetest.serialize
local get_node = minetest.get_node local get_node = minetest.get_node
initialize_map_data(maps, arena) initialize_map_data(maps, arena)
maps[arena.name].always_to_be_reset_nodes = {} local map = maps[arena.name]
map.always_to_be_reset_nodes = {}
map.changed_nodes = {}
-- Saving every node with an inventory. -- Saving every node with an inventory.
for i in emerged_area:iterp(emerged_pos1, emerged_pos2) do for i in emerged_area:iterp(emerged_pos1, emerged_pos2) do
local node_pos = emerged_area:position(i) local node_pos = emerged_area:position(i)
local hash_pos = hash_node_position(node_pos)
local location = {type = "node", pos = node_pos} local location = {type = "node", pos = node_pos}
if original_area:containsp(node_pos) and get_inventory(location) then if original_area:containsp(node_pos) and get_inventory(location) then
local node = get_node(node_pos) local node = get_node(node_pos)
local serialized_pos = serialize(node_pos)
map.always_to_be_reset_nodes[hash_pos] = true
maps[arena.name].always_to_be_reset_nodes[serialized_pos] = true map.changed_nodes[hash_pos] = node
maps[arena.name].changed_nodes[serialized_pos] = node
end end
end end
@ -106,14 +108,14 @@ end
function save_node(arena, pos, node) function save_node(arena, pos, node)
local maps = skywars.load_table("maps") local maps = skywars.load_table("maps")
local serialized_pos = minetest.serialize(pos) local hash_pos = hash_node_position(vector.round(pos))
if not arena then return end if not arena then return end
initialize_map_data(maps, arena) initialize_map_data(maps, arena)
-- If this block has not been changed yet then save it. -- If this block has not been changed yet then save it.
if maps[arena.name].changed_nodes[serialized_pos] == nil then if not maps[arena.name].changed_nodes[hash_pos] then
maps[arena.name].changed_nodes[serialized_pos] = node maps[arena.name].changed_nodes[hash_pos] = node
skywars.overwrite_table("maps", maps) skywars.overwrite_table("maps", maps)
end end
end end
@ -125,4 +127,34 @@ function initialize_map_data(maps, arena)
if not maps[arena.name] then maps[arena.name] = {} end if not maps[arena.name] then maps[arena.name] = {} end
if not maps[arena.name].changed_nodes then maps[arena.name].changed_nodes = {} end if not maps[arena.name].changed_nodes then maps[arena.name].changed_nodes = {} end
if not maps[arena.name].always_to_be_reset_nodes then maps[arena.name].always_to_be_reset_nodes = {} end if not maps[arena.name].always_to_be_reset_nodes then maps[arena.name].always_to_be_reset_nodes = {} end
end end
--
-- ! LEGACY SUPPORT FOR SERIALIZED POSITIONS.
-- Converting all the serialized positions into
-- hashes.
--
local maps = skywars.load_table("maps")
for arena_name, map in pairs(maps) do
initialize_map_data(maps, {name = arena_name})
for pos, node in pairs(map.changed_nodes) do
if minetest.deserialize(pos) then
local hash_pos = minetest.hash_node_position()
map.changed_nodes[pos] = nil
map.changed_nodes[hash_pos] = node
end
end
for pos, bool in pairs(map.always_to_be_reset_nodes) do
if type(pos) == "string" then
local hash_pos = minetest.hash_node_position(minetest.deserialize(pos))
map.always_to_be_reset_nodes[pos] = nilf
map.always_to_be_reset_nodes[hash_pos] = bool
end
end
end
skywars.overwrite_table("maps", maps)

View File

@ -74,9 +74,6 @@ function place_nodes_at_arena_edges(arena)
minetest.set_node(arena.min_pos, {name="skywars:test_node"}) minetest.set_node(arena.min_pos, {name="skywars:test_node"})
minetest.set_node(arena.max_pos, {name="skywars:test_node"}) minetest.set_node(arena.max_pos, {name="skywars:test_node"})
node1 = minetest.get_node(arena.min_pos)
node2 = minetest.get_node(arena.max_pos)
end end

View File

@ -955,7 +955,7 @@ end, {
- pos2 <arena name> - pos2 <arena name>
- reset <arena name> - reset <arena name>
TREASURES: TREASURES:
- addtreasure <arena name> <item> <count> <preciousness> - addtreasure <arena name> <item> <count> <preciousness>

View File

@ -32,6 +32,7 @@ arena_lib.register_minigame("skywars", {
dofile(minetest.get_modpath("skywars") .. "/chatcmdbuilder.lua") dofile(minetest.get_modpath("skywars") .. "/chatcmdbuilder.lua")
dofile(minetest.get_modpath("skywars") .. "/_storage/storage_manager.lua")
dofile(minetest.get_modpath("skywars") .. "/nodes.lua") dofile(minetest.get_modpath("skywars") .. "/nodes.lua")
dofile(minetest.get_modpath("skywars") .. "/utils.lua") dofile(minetest.get_modpath("skywars") .. "/utils.lua")
dofile(minetest.get_modpath("skywars") .. "/_map_handler/map_utils.lua") dofile(minetest.get_modpath("skywars") .. "/_map_handler/map_utils.lua")
@ -42,7 +43,6 @@ dofile(minetest.get_modpath("skywars") .. "/_map_handler/chests/treasures.lua")
dofile(minetest.get_modpath("skywars") .. "/_tests/map_reset.lua") dofile(minetest.get_modpath("skywars") .. "/_tests/map_reset.lua")
dofile(minetest.get_modpath("skywars") .. "/_compatible_mods/enderpearl/init_enderpearl.lua") dofile(minetest.get_modpath("skywars") .. "/_compatible_mods/enderpearl/init_enderpearl.lua")
dofile(minetest.get_modpath("skywars") .. "/_compatible_mods/3d_armor/init_3d_armor.lua") dofile(minetest.get_modpath("skywars") .. "/_compatible_mods/3d_armor/init_3d_armor.lua")
dofile(minetest.get_modpath("skywars") .. "/_storage/storage_manager.lua")
dofile(minetest.get_modpath("skywars") .. "/_hud/hud_manager.lua") dofile(minetest.get_modpath("skywars") .. "/_hud/hud_manager.lua")
dofile(minetest.get_modpath("skywars") .. "/commands.lua") dofile(minetest.get_modpath("skywars") .. "/commands.lua")
dofile(minetest.get_modpath("skywars") .. "/_arena_lib/arena_callbacks.lua") dofile(minetest.get_modpath("skywars") .. "/_arena_lib/arena_callbacks.lua")