mirror of
git://repo.or.cz/minetest_schemedit.git
synced 2025-07-04 17:10:24 +02:00
Compare commits
13 Commits
Author | SHA1 | Date | |
---|---|---|---|
e19d5e0bfa | |||
b6e4d2f7f0 | |||
abfd913862 | |||
01a3a970d2 | |||
e389fcc041 | |||
05ca8d90be | |||
84d6dc3c69 | |||
fedc4c51fa | |||
4199f645f3 | |||
a639c2b9c0 | |||
7f279bbd7a | |||
54aa7f35df | |||
bbed49e365 |
15
README.md
15
README.md
@ -1,11 +1,14 @@
|
||||
# Schematic Editor [`schemedit`]
|
||||
|
||||
## Version
|
||||
1.2.0
|
||||
1.4.0
|
||||
|
||||
## Description
|
||||
This is a mod which allows you to edit and export schematics (`.mts` files).
|
||||
|
||||
This mod works in Minetest 5.0.0 or later, but recommended is version 5.1.0
|
||||
or later.
|
||||
|
||||
It supports node probabilities, forced node placement and slice probabilities.
|
||||
|
||||
It adds 3 items:
|
||||
@ -14,10 +17,18 @@ It adds 3 items:
|
||||
* Schematic Void: Marks a position in a schematic which should not replace anything when placed as a schematic
|
||||
* Schematic Node Probability Tool: Set per-node probabilities and forced node placement
|
||||
|
||||
It also adds the server command `placeschem` to place a schematic.
|
||||
Note: The import feature requires Minetest 5.1.0 or later.
|
||||
|
||||
It also adds these server commands:
|
||||
|
||||
* `placeschem` to place a schematic
|
||||
* `mts2lua` to convert .mts files to .lua files (Lua code)
|
||||
|
||||
There's also a setting `schemedit_export_lua` to enable automatic export to .lua files.
|
||||
|
||||
## Usage help
|
||||
Usage help can be found when you use the optional Help modpack (mods `doc` and `doc_items`).
|
||||
The “server” privilege is required for most features.
|
||||
|
||||
You should also refer to the Minetest Lua API documentation to understand more about schematics.
|
||||
|
||||
|
180
init.lua
180
init.lua
@ -3,10 +3,8 @@ local F = minetest.formspec_escape
|
||||
|
||||
local schemedit = {}
|
||||
|
||||
-- Directory delimeter fallback (normally comes from builtin)
|
||||
if not DIR_DELIM then
|
||||
DIR_DELIM = "/"
|
||||
end
|
||||
local DIR_DELIM = "/"
|
||||
|
||||
local export_path_full = table.concat({minetest.get_worldpath(), "schems"}, DIR_DELIM)
|
||||
|
||||
-- truncated export path so the server directory structure is not exposed publicly
|
||||
@ -28,6 +26,38 @@ local function renumber(t)
|
||||
return res
|
||||
end
|
||||
|
||||
local NEEDED_PRIV = "server"
|
||||
local function check_priv(player_name, quit)
|
||||
local privs = minetest.get_player_privs(player_name)
|
||||
if privs[NEEDED_PRIV] then
|
||||
return true
|
||||
else
|
||||
if not quit then
|
||||
minetest.chat_send_player(player_name, minetest.colorize("red",
|
||||
S("Insufficient privileges! You need the “@1” privilege to use this.", NEEDED_PRIV)))
|
||||
end
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
-- Lua export
|
||||
local export_schematic_to_lua
|
||||
if can_import then
|
||||
export_schematic_to_lua = function(schematic, filepath, options)
|
||||
if not options then options = {} end
|
||||
local str = minetest.serialize_schematic(schematic, "lua", options)
|
||||
local file = io.open(filepath, "w")
|
||||
if file and str then
|
||||
file:write(str)
|
||||
file:flush()
|
||||
file:close()
|
||||
return true
|
||||
else
|
||||
return false
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
---
|
||||
--- Formspec API
|
||||
---
|
||||
@ -112,7 +142,8 @@ function schemedit.show_formspec(pos, player, tab, show, ...)
|
||||
|
||||
-- Update player attribute
|
||||
if forms[tab].cache_name ~= false then
|
||||
player:set_attribute("schemedit:tab", tab)
|
||||
local pmeta = player:get_meta()
|
||||
pmeta:set_string("schemedit:tab", tab)
|
||||
end
|
||||
else
|
||||
minetest.close_formspec(pname, "schemedit:"..tab)
|
||||
@ -254,30 +285,34 @@ schemedit.add_form("main", {
|
||||
|
||||
local xs, ys, zs = meta.x_size or 1, meta.y_size or 1, meta.z_size or 1
|
||||
local size = {x=xs, y=ys, z=zs}
|
||||
local schem_name = meta.schem_name or ""
|
||||
|
||||
local form = [[
|
||||
size[7,8]
|
||||
label[0.5,-0.1;]]..F(S("Position: @1", strpos))..[[]
|
||||
label[3,-0.1;]]..F(S("Owner: @1", name))..[[]
|
||||
label[0.5,0.4;]]..F(S("Schematic name: @1", meta.schem_name))..[[]
|
||||
label[0.5,0.4;]]..F(S("Schematic name: @1", F(schem_name)))..[[]
|
||||
label[0.5,0.9;]]..F(S("Size: @1", minetest.pos_to_string(size)))..[[]
|
||||
|
||||
field[0.8,2;5,1;name;]]..F(S("Schematic name:"))..[[;]]..F(meta.schem_name or "")..[[]
|
||||
field[0.8,2;5,1;name;]]..F(S("Schematic name:"))..[[;]]..F(schem_name or "")..[[]
|
||||
button[5.3,1.69;1.2,1;save_name;]]..F(S("OK"))..[[]
|
||||
tooltip[save_name;]]..F(S("Save schematic name"))..[[]
|
||||
field_close_on_enter[name;false]
|
||||
|
||||
button[0.5,3.5;6,1;export;]]..F(S("Export schematic")).."]"..
|
||||
import_btn..[[
|
||||
textarea[0.8,4.5;6.2,5;;]]..F(S("Export/import path:\n@1",
|
||||
textarea[0.8,4.5;6.2,1;;]]..F(S("Export/import path:\n@1",
|
||||
export_path_trunc .. DIR_DELIM .. F(S("<name>"))..".mts"))..[[;]
|
||||
button[0.5,5.5;3,1;air2void;]]..F(S("Air to voids"))..[[]
|
||||
button[3.5,5.5;3,1;void2air;]]..F(S("Voids to air"))..[[]
|
||||
tooltip[air2void;]]..F(S("Turn all air nodes into schematic void nodes"))..[[]
|
||||
tooltip[void2air;]]..F(S("Turn all schematic void nodes into air nodes"))..[[]
|
||||
field[0.8,7;2,1;x;]]..F(S("X size:"))..[[;]]..xs..[[]
|
||||
field[2.8,7;2,1;y;]]..F(S("Y size:"))..[[;]]..ys..[[]
|
||||
field[4.8,7;2,1;z;]]..F(S("Z size:"))..[[;]]..zs..[[]
|
||||
field_close_on_enter[x;false]
|
||||
field_close_on_enter[y;false]
|
||||
field_close_on_enter[z;false]
|
||||
|
||||
button[0.5,7.5;3,1;save;]]..F(S("Save size"))..[[]
|
||||
]]..
|
||||
border_button
|
||||
@ -288,6 +323,15 @@ schemedit.add_form("main", {
|
||||
return form
|
||||
end,
|
||||
handle = function(self, pos, name, fields)
|
||||
if fields.doc then
|
||||
doc.show_entry(name, "nodes", "schemedit:creator", true)
|
||||
return
|
||||
end
|
||||
|
||||
if not check_priv(name, fields.quit) then
|
||||
return
|
||||
end
|
||||
|
||||
local realmeta = minetest.get_meta(pos)
|
||||
local meta = realmeta:to_table().fields
|
||||
local hashpos = minetest.hash_node_position(pos)
|
||||
@ -317,8 +361,18 @@ schemedit.add_form("main", {
|
||||
meta.schem_name = fields.name
|
||||
end
|
||||
|
||||
if fields.doc then
|
||||
doc.show_entry(name, "nodes", "schemedit:creator", true)
|
||||
-- Node conversion
|
||||
if (fields.air2void) then
|
||||
local pos1, pos2 = schemedit.size(pos)
|
||||
pos1, pos2 = schemedit.sort_pos(pos1, pos2)
|
||||
local nodes = minetest.find_nodes_in_area(pos1, pos2, {"air"})
|
||||
minetest.bulk_set_node(nodes, {name="schemedit:void"})
|
||||
return
|
||||
elseif (fields.void2air) then
|
||||
local pos1, pos2 = schemedit.size(pos)
|
||||
pos1, pos2 = schemedit.sort_pos(pos1, pos2)
|
||||
local nodes = minetest.find_nodes_in_area(pos1, pos2, {"schemedit:void"})
|
||||
minetest.bulk_set_node(nodes, {name="air"})
|
||||
return
|
||||
end
|
||||
|
||||
@ -369,6 +423,16 @@ schemedit.add_form("main", {
|
||||
if res then
|
||||
minetest.chat_send_player(name, minetest.colorize("#00ff00",
|
||||
S("Exported schematic to @1", filepath)))
|
||||
-- Additional export to Lua file if MTS export was successful
|
||||
local schematic = minetest.read_schematic(filepath, {})
|
||||
if schematic and minetest.settings:get_bool("schemedit_export_lua") then
|
||||
local filepath_lua = path..meta.schem_name..".lua"
|
||||
res = export_schematic_to_lua(schematic, filepath_lua)
|
||||
if res then
|
||||
minetest.chat_send_player(name, minetest.colorize("#00ff00",
|
||||
S("Exported schematic to @1", filepath_lua)))
|
||||
end
|
||||
end
|
||||
else
|
||||
minetest.chat_send_player(name, minetest.colorize("red",
|
||||
S("Failed to export schematic to @1", filepath)))
|
||||
@ -377,12 +441,6 @@ schemedit.add_form("main", {
|
||||
|
||||
-- Import schematic
|
||||
if fields.import and meta.schem_name and meta.schem_name ~= "" then
|
||||
if not minetest.get_player_privs(name).debug then
|
||||
minetest.chat_send_player(name, minetest.colorize("red",
|
||||
S("Insufficient privileges! You need the “debug” privilege to do this.")))
|
||||
return
|
||||
end
|
||||
|
||||
if not can_import then
|
||||
return
|
||||
end
|
||||
@ -402,10 +460,12 @@ schemedit.add_form("main", {
|
||||
|
||||
if node.param2 == 1 then
|
||||
pos1 = vector.add(pos, {x=1,y=0,z=-meta.z_size+1})
|
||||
meta.x_size, meta.z_size = meta.z_size, meta.x_size
|
||||
elseif node.param2 == 2 then
|
||||
pos1 = vector.add(pos, {x=-meta.x_size+1,y=0,z=-meta.z_size})
|
||||
elseif node.param2 == 3 then
|
||||
pos1 = vector.add(pos, {x=-meta.x_size,y=0,z=0})
|
||||
meta.x_size, meta.z_size = meta.z_size, meta.x_size
|
||||
else
|
||||
pos1 = vector.add(pos, {x=0,y=0,z=1})
|
||||
end
|
||||
@ -537,6 +597,10 @@ schemedit.add_form("slice", {
|
||||
return form
|
||||
end,
|
||||
handle = function(self, pos, name, fields)
|
||||
if not check_priv(name, fields.quit) then
|
||||
return
|
||||
end
|
||||
|
||||
local meta = minetest.get_meta(pos)
|
||||
local player = minetest.get_player_by_name(name)
|
||||
|
||||
@ -632,6 +696,10 @@ schemedit.add_form("probtool", {
|
||||
return form
|
||||
end,
|
||||
handle = function(self, pos, name, fields)
|
||||
if not check_priv(name, fields.quit) then
|
||||
return
|
||||
end
|
||||
|
||||
if fields.submit then
|
||||
local prob = tonumber(fields.prob)
|
||||
if prob then
|
||||
@ -999,7 +1067,8 @@ S("With a schematic node probability tool, you can set a probability for each no
|
||||
if meta:get_string("owner") == name or
|
||||
minetest.check_player_privs(player, "schematic_override") == true then
|
||||
-- Get player attribute
|
||||
local tab = player:get_attribute("schemedit:tab")
|
||||
local pmeta = player:get_meta()
|
||||
local tab = pmeta:get_string("schemedit:tab")
|
||||
if not forms[tab] or not tab then
|
||||
tab = "main"
|
||||
end
|
||||
@ -1036,6 +1105,11 @@ S("The node HUD is not updated automatically and may be outdated. The node HUD o
|
||||
liquids_pointable = true,
|
||||
groups = { disable_repair = 1 },
|
||||
on_use = function(itemstack, user, pointed_thing)
|
||||
local uname = user:get_player_name()
|
||||
if uname and not check_priv(uname) then
|
||||
return
|
||||
end
|
||||
|
||||
local ctrl = user:get_player_control()
|
||||
-- Simple use
|
||||
if not ctrl.sneak then
|
||||
@ -1065,10 +1139,20 @@ S("The node HUD is not updated automatically and may be outdated. The node HUD o
|
||||
end
|
||||
end,
|
||||
on_secondary_use = function(itemstack, user, pointed_thing)
|
||||
local uname = user:get_player_name()
|
||||
if uname and not check_priv(uname) then
|
||||
return
|
||||
end
|
||||
|
||||
schemedit.clear_displayed_node_probs(user)
|
||||
end,
|
||||
-- Set note probability and force_place and enable node probability display
|
||||
on_place = function(itemstack, placer, pointed_thing)
|
||||
local pname = placer:get_player_name()
|
||||
if pname and not check_priv(pname) then
|
||||
return
|
||||
end
|
||||
|
||||
-- Use pointed node's on_rightclick function first, if present
|
||||
local node = minetest.get_node(pointed_thing.under)
|
||||
if placer and not placer:get_player_control().sneak then
|
||||
@ -1160,10 +1244,23 @@ minetest.register_lbm({
|
||||
end,
|
||||
})
|
||||
|
||||
local function add_suffix(schem)
|
||||
-- Automatically add file name suffix if omitted
|
||||
local schem_full, schem_lua
|
||||
if string.sub(schem, string.len(schem)-3, string.len(schem)) == ".mts" then
|
||||
schem_full = schem
|
||||
schem_lua = string.sub(schem, 1, -5) .. ".lua"
|
||||
else
|
||||
schem_full = schem .. ".mts"
|
||||
schem_lua = schem .. ".lua"
|
||||
end
|
||||
return schem_full, schem_lua
|
||||
end
|
||||
|
||||
-- [chatcommand] Place schematic
|
||||
minetest.register_chatcommand("placeschem", {
|
||||
description = S("Place schematic at the position specified or the current player position (loaded from @1)", export_path_trunc),
|
||||
privs = {debug = true},
|
||||
privs = {server = true},
|
||||
params = S("<schematic name>[.mts] [<x> <y> <z>]"),
|
||||
func = function(name, param)
|
||||
local schem, p = string.match(param, "^([^ ]+) *(.*)$")
|
||||
@ -1177,14 +1274,7 @@ minetest.register_chatcommand("placeschem", {
|
||||
pos = minetest.get_player_by_name(name):get_pos()
|
||||
end
|
||||
|
||||
-- Automatically add file name suffix if omitted
|
||||
local schem_full
|
||||
if string.sub(schem, string.len(schem)-3, string.len(schem)) == ".mts" then
|
||||
schem_full = schem
|
||||
else
|
||||
schem_full = schem .. ".mts"
|
||||
end
|
||||
|
||||
local schem_full, schem_lua = add_suffix(schem)
|
||||
local success = false
|
||||
local schem_path = export_path_full .. DIR_DELIM .. schem_full
|
||||
if minetest.read_schematic then
|
||||
@ -1208,3 +1298,39 @@ minetest.register_chatcommand("placeschem", {
|
||||
end,
|
||||
})
|
||||
|
||||
if can_import then
|
||||
-- [chatcommand] Convert MTS schematic file to .lua file
|
||||
minetest.register_chatcommand("mts2lua", {
|
||||
description = S("Convert .mts schematic file to .lua file (loaded from @1)", export_path_trunc),
|
||||
privs = {server = true},
|
||||
params = S("<schematic name>[.mts] [comments]"),
|
||||
func = function(name, param)
|
||||
local schem, comments_str = string.match(param, "^([^ ]+) *(.*)$")
|
||||
|
||||
if not schem then
|
||||
return false, S("No schematic file specified.")
|
||||
end
|
||||
|
||||
local comments = comments_str == "comments"
|
||||
|
||||
-- Automatically add file name suffix if omitted
|
||||
local schem_full, schem_lua = add_suffix(schem)
|
||||
local schem_path = export_path_full .. DIR_DELIM .. schem_full
|
||||
local schematic = minetest.read_schematic(schem_path, {})
|
||||
|
||||
if schematic then
|
||||
local str = minetest.serialize_schematic(schematic, "lua", {lua_use_comments=comments})
|
||||
local lua_path = export_path_full .. DIR_DELIM .. schem_lua
|
||||
local file = io.open(lua_path, "w")
|
||||
if file and str then
|
||||
file:write(str)
|
||||
file:flush()
|
||||
file:close()
|
||||
return true, S("Exported schematic to @1", lua_path)
|
||||
else
|
||||
return false, S("Failed!")
|
||||
end
|
||||
end
|
||||
end,
|
||||
})
|
||||
end
|
||||
|
@ -70,4 +70,12 @@ Main=Grundeinstellungen
|
||||
X size:=X-Größe:
|
||||
Y size:=Y-Größe:
|
||||
Z size:=Z-Größe:
|
||||
Insufficient privileges! You need the “debug” privilege to do this.=Unzureichende Privilegien! Sie benötigen das „debug“-Privileg, um dies tun zu können.
|
||||
Insufficient privileges! You need the “@1” privilege to use this.=Unzureichende Privilegien! Sie benötigen das „@1“-Privileg, um dies benutzen zu können.
|
||||
Convert .mts schematic file to .lua file (loaded from @1)=„.mts“-Schematicdatei zu „.lua“-Datei konvertieren (geladen von @1)
|
||||
<schematic name>[.mts] [comments]=<Schematic-Name>[.mts] [comments]
|
||||
Failed.=Fehlgeschlagen.
|
||||
Air to voids=Luft zu Lücken
|
||||
Voids to air=Lücken zu Luft
|
||||
Turn all air nodes into schematic void nodes=Alle Luft-Nodes zu Schematic-Lücken umwandeln
|
||||
Turn all schematic void nodes into air nodes=Alle Schematic-Lücken zu Luft-Nodes umwandeln
|
||||
|
||||
|
@ -68,4 +68,11 @@ Main=
|
||||
X size:=
|
||||
Y size:=
|
||||
Z size:=
|
||||
Insufficient privileges! You need the “debug” privilege to do this.=
|
||||
Insufficient privileges! You need the “@1” privilege to use this.=
|
||||
Convert .mts schematic file to .lua file (loaded from @1)=
|
||||
<schematic name>[.mts] [comments]=
|
||||
Failed.=
|
||||
Air to voids=
|
||||
Voids to air=
|
||||
Turn all air nodes into schematic void nodes=
|
||||
Turn all schematic void nodes into air nodes=
|
||||
|
3
settingtypes.txt
Normal file
3
settingtypes.txt
Normal file
@ -0,0 +1,3 @@
|
||||
# If enabled, exporting a schematic will also create a .lua file
|
||||
# in addition to the .mts file.
|
||||
schemedit_export_lua (.lua file schematic export) bool false
|
Reference in New Issue
Block a user