edit-cd2025/open.lua
2023-09-08 12:30:23 -05:00

187 lines
5.4 KiB
Lua

local function delete_schematics_dialog(player)
local path = minetest.get_worldpath() .. "/schems"
local dir_list = minetest.get_dir_list(path)
if #path > 40 then path = "..." .. path:sub(#path - 40, #path) end
local formspec = "formspec_version[4]size[10,10]" ..
"label[0.5,1;Delete Schematics from:\n" ..
minetest.formspec_escape(path) .. "]button_exit[8.8,0.2;1,1;quit;X]" ..
"textlist[0.5,2;9,7;schems;" .. table.concat(dir_list, ",") .. "]"
edit.reliable_show_formspec(player, "edit:delete_schem", formspec)
end
local function open_on_place(itemstack, player, pointed_thing)
if not edit.on_place_checks(player) then return end
local path = minetest.get_worldpath() .. "/schems"
local dir_list = minetest.get_dir_list(path)
if #path > 40 then path = "..." .. path:sub(#path - 40, #path) end
local formspec = "formspec_version[4]size[10,11]" ..
"label[0.5,1;Load a schematic from:\n" ..
minetest.formspec_escape(path) .. "]button_exit[8.8,0.2;1,1;quit;X]" ..
"textlist[0.5,2;9,7;schems;" .. table.concat(dir_list, ",") .. "]" ..
"button_exit[2,9.5;6,1;delete;Delete schematics...]"
minetest.show_formspec(player:get_player_name(), "edit:open", formspec)
end
minetest.register_tool("edit:open",{
description = "Edit Open",
inventory_image = "edit_open.png",
range = 10,
on_place = open_on_place,
on_secondary_use = open_on_place
})
local function read_minetest_schematic(file_path)
local schematic = minetest.read_schematic(file_path, {})
if schematic then
schematic._meta = {}
schematic._timers = {}
schematic._rotation = 0
end
return schematic
end
local function read_world_edit_schematic(file_path)
local f = io.open(file_path)
if not f then return false end
local data = f:read("*all")
f:close()
if not data then return false end
data = data:gsub("^[^:]*:", "")
data = minetest.deserialize(data)
if not data then return false end
-- Get the schematic size
local x_max, y_max, z_max = 0, 0, 0
for i, node in pairs(data) do
local x, y, z = node.x, node.y, node.z
if x > x_max then x_max = x end
if y > y_max then y_max = y end
if z > z_max then z_max = z end
end
local schem_data = {}
local meta = {}
local timers = {}
local size = vector.new(x_max + 1, y_max + 1, z_max + 1)
local start = vector.new(1, 1, 1)
local voxel_area = VoxelArea:new({MinEdge = start, MaxEdge = size})
for i, node in pairs(data) do
local x, y, z = node.x + 1, node.y + 1, node.z + 1
local index = voxel_area:index(x, y, z)
schem_data[index] = {}
schem_data[index].name = node.name
schem_data[index].param2 = node.param2
if node.meta then
local key = minetest.hash_node_position(vector.new(x, y, z))
meta[key] = node.meta
end
if node.timer then
local key = minetest.hash_node_position(vector.new(x, y, z))
timers[key] = node.timer
end
end
-- Replace empty space with air nodes
for i in voxel_area:iterp(start, size) do
if not schem_data[i] then
schem_data[i] = { name = "air" }
end
end
return {
size = size,
data = schem_data,
_meta = meta,
_timers = timers,
_rotation = 0,
}
end
minetest.register_on_player_receive_fields(function(player, formname, fields)
if formname == "edit:open" then
minetest.close_formspec(player:get_player_name(), "edit:open")
if
fields.cancel
or not edit.has_privilege(player)
then return true end
if fields.delete then
delete_schematics_dialog(player)
return true
end
if not fields.schems then return end
local index = tonumber(fields.schems:sub(5, #(fields.schems)))
if not index then return true end
index = math.floor(index)
local path = minetest.get_worldpath() .. "/schems"
local dir_list = minetest.get_dir_list(path)
if index > 0 and index <= #dir_list then
local file_path = path .. "/" .. dir_list[index]
local schematic
if file_path:sub(-4, -1) == ".mts" then
schematic = read_minetest_schematic(file_path)
elseif file_path:sub(-3, -1) == ".we" then
schematic = read_world_edit_schematic(file_path)
end
if not schematic then
minetest.chat_send_player(player:get_player_name(),
"\"" .. dir_list[index] .. "\" failed to load" )
return true
end
edit.player_data[player].schematic = schematic
minetest.chat_send_player(player:get_player_name(),
"\"" .. dir_list[index] .. "\" loaded." )
edit.delete_paste_preview(player)
end
return true
elseif formname == "edit:delete_schem" then
if
fields.cancel
or not edit.has_privilege(player)
then return true end
if not fields.schems then return end
local index = tonumber(fields.schems:sub(5, #(fields.schems)))
if not index then return true end
index = math.floor(index)
local path = minetest.get_worldpath() .. "/schems"
local dir_list = minetest.get_dir_list(path)
if index > 0 and index <= #dir_list then
edit.player_data[player].schem_for_delete = path .. "/" .. dir_list[index]
formspec = "formspec_version[4]size[8,3.5]label[0.6,1;Confirm delete \"" ..
dir_list[index] .. "\"]" ..
"button_exit[0.5,2;3,1;delete;Delete]" ..
"button_exit[4.5,2;3,1;quit;Cancel]"
edit.reliable_show_formspec(player, "edit:confirm_delete_schem", formspec)
end
return true
elseif formname == "edit:confirm_delete_schem" then
if not edit.has_privilege(player) then return end
if fields.delete then
os.remove(edit.player_data[player].schem_for_delete)
end
edit.player_data[player].schem_for_delete = nil
delete_schematics_dialog(player)
return true
end
return false
end)