minetest_ltool/init.lua

748 lines
26 KiB
Lua
Raw Normal View History

2014-07-19 14:32:35 -07:00
ltool = {}
ltool.playerinfos = {}
ltool.default_edit_fields = {
2014-07-19 14:32:35 -07:00
axiom="",
rules_a="",
rules_b="",
rules_c="",
rules_d="",
trunk="",
leaves="",
leaves2="",
leaves2_chance="",
fruit="",
fruit_chance="",
angle="",
iterations="",
random_level="",
trunk_type="",
thin_branches="",
name = "",
2014-07-19 14:32:35 -07:00
}
--[[ This registers the sapling for planting the trees ]]
2014-07-25 07:30:17 -07:00
minetest.register_node("ltool:sapling", {
description = "custom L-system tree sapling",
stack_max = 1,
drawtype = "plantlike",
tiles = { "ltool_sapling.png" },
inventory_image = "ltool_sapling.png",
wield_image = "ltool_sapling.png",
paramtype = "light",
paramtype2= "wallmounted",
walkable = false,
buildable_to = true,
groups = { dig_immediate = 3, not_in_creative_inventory=1 },
drop = "",
2014-07-25 07:30:17 -07:00
after_place_node = function(pos, placer, itemstack, pointed_thing)
-- Transfer metadata and start timer
local nodemeta = minetest.get_meta(pos)
local itemmeta = itemstack:get_metadata()
nodemeta:set_string("treedef", itemmeta)
local timer = minetest.get_node_timer(pos)
timer:start(5)
end,
on_timer = function(pos, elapsed)
-- Place tree
local meta = minetest.get_meta(pos)
local treedef = minetest.deserialize(meta:get_string("treedef"))
minetest.remove_node(pos)
minetest.spawn_tree(pos, treedef)
end,
})
--[[ Load previously saved data from file or initialize an empty tree table ]]
do
local filepath = minetest.get_worldpath().."/ltool.mt"
local file = io.open(filepath, "r")
if(file) then
local string = file:read()
io.close(file)
if(string ~= nil) then
local savetable = minetest.deserialize(string)
2014-07-25 18:18:31 -07:00
if(savetable ~= nil) then
ltool.trees = savetable.trees
2014-07-25 18:18:31 -07:00
ltool.next_tree_id = savetable.next_tree_id
ltool.number_of_trees = savetable.number_of_trees
minetest.log("action", "[ltool] Tree data loaded from "..filepath..".")
else
minetest.log("error", "[ltool] Failed to load tree data from "..filepath..".")
end
2014-07-25 18:18:31 -07:00
else
minetest.log("error", "[ltool] Failed to load tree data from "..filepath..".")
end
2014-07-25 18:18:31 -07:00
else
--[[ table of all trees ]]
2014-07-25 18:18:31 -07:00
ltool.trees = {}
--[[ helper variables to ensure unique IDs ]]
2014-07-25 18:18:31 -07:00
ltool.number_of_trees = 0
ltool.next_tree_id = 1
end
end
--[[ Adds a tree to the tree table.
name: The trees name.
author: The authors / owners name
treedef: The full tree definition, see lua_api.txt
returns the tree ID of the new tree
]]
2014-07-25 18:18:31 -07:00
function ltool.add_tree(name, author, treedef)
local id = ltool.next_tree_id
ltool.trees[id] = {name = name, author = author, treedef = treedef}
ltool.next_tree_id = ltool.next_tree_id + 1
ltool.number_of_trees = ltool.number_of_trees + 1
return id
end
--[[ Removes a tree from the database
tree_id: ID of the tree to be removed
returns nil
]]
function ltool.remove_tree(tree_id)
ltool.trees[tree_id] = nil
ltool.number_of_trees = ltool.number_of_trees - 1
for k,v in pairs(ltool.playerinfos) do
if(v.dbsel ~= nil) then
if(v.dbsel > ltool.number_of_trees) then
v.dbsel = ltool.number_of_trees
end
if(v.dbsel < 1) then
v.dbsel = 1
end
end
end
end
2014-07-19 14:32:35 -07:00
ltool.seed = os.time()
--[=[ Here come the functions to build the main formspec.
They do not build the entire formspec ]=]
2014-07-19 14:32:35 -07:00
ltool.loadtreeform = "size[6,7]"
--[[ This is a part of the main formspec: Tab header ]]
2014-07-19 14:32:35 -07:00
function ltool.header(index)
2014-07-22 08:49:50 -07:00
return "tabheader[0,0;ltool_tab;Edit,Database,Plant,Cheat sheet;"..tostring(index)..";true;false]"
2014-07-19 14:32:35 -07:00
end
--[[ This creates the edit tab of the formspec
fields: A template used to fill the default values of the formspec. ]]
function ltool.edit(fields)
if(fields==nil) then
fields = ltool.default_edit_fields
2014-07-19 14:32:35 -07:00
end
local s = function(input)
if(input==nil) then
ret = ""
else
ret = minetest.formspec_escape(tostring(input))
end
return ret
end
return ""..
"field[0.2,-4;6,10;axiom;Axiom;"..s(fields.axiom).."]"..
"field[0.2,-3.4;6,10;rules_a;Rules set A;"..s(fields.rules_a).."]"..
"field[0.2,-2.7;6,10;rules_b;Rules set B;"..s(fields.rules_b).."]"..
"field[0.2,-2.1;6,10;rules_c;Rules set C;"..s(fields.rules_c).."]"..
"field[0.2,-1.5;6,10;rules_d;Rules set D;"..s(fields.rules_d).."]"..
"field[0.2,-0.9;3,10;trunk;Trunk node name;"..s(fields.trunk).."]"..
"field[0.2,-0.3;3,10;leaves;Leaves node name;"..s(fields.leaves).."]"..
"field[0.2,0.3;3,10;leaves2;Secondary leaves node name;"..s(fields.leaves2).."]"..
"field[0.2,0.9;3,10;leaves2_chance;Secondary leaves chance (in percent);"..s(fields.leaves2_chance).."]"..
"field[0.2,1.5;3,10;fruit;Fruit node name;"..s(fields.fruit).."]"..
"field[0.2,2.1;3,10;fruit_chance;Fruit chance (in percent);"..s(fields.fruit_chance).."]"..
"field[3.2,-0.9;3,10;angle;Angle (in degrees);"..s(fields.angle).."]"..
"field[3.2,-0.3;3,10;iterations;Iterations;"..s(fields.iterations).."]"..
"field[3.2,0.3;3,10;random_level;Randomness level;"..s(fields.random_level).."]"..
"field[3.2,0.9;3,10;trunk_type;Trunk type (single/double/crossed);"..s(fields.trunk_type).."]"..
"field[3.2,1.5;3,10;thin_branches;Thin branches? (true/false);"..s(fields.thin_branches).."]"..
"field[3.2,2.1;3,10;name;Name;"..s(fields.name).."]"..
"button[0,6.5;2,1;edit_save;Save]"
2014-07-19 14:32:35 -07:00
end
--[[ This creates the database tab of the formspec.
index: Selected index of the textlist
playername: To whom the formspec is shown
]]
2014-07-23 17:41:39 -07:00
function ltool.database(index, playername)
2014-07-25 18:18:31 -07:00
local treestr, tree_ids = ltool.build_tree_textlist(index, playername)
if(treestr ~= nil) then
2014-07-25 18:18:31 -07:00
local indexstr
if(index == nil) then
indexstr = ""
else
indexstr = tostring(index)
end
ltool.playerinfos[playername].treeform.database.textlist = tree_ids
return ""..
"textlist[0,0;5,6;treelist;"..treestr..";"..tostring(index)..";false]"..
2014-07-25 19:18:04 -07:00
"button[0,6;2,1;database_rename;Rename tree]"..
"button[2.1,6;2,1;database_delete;Delete tree]"..
"button[0,6.5;2,1;database_copy;Copy to editor]"..
2014-07-25 07:42:46 -07:00
"button[2.1,6.5;2,1;database_update;Reload database]"
else
return "label[0,0;The tree database is empty.]"..
2014-07-25 07:42:46 -07:00
"button[2.1,6.5;2,1;database_update;Reload database]"
end
2014-07-19 14:32:35 -07:00
end
--[[ This creates the "Plant" tab part of the main formspec ]]
function ltool.plant(tree, fields)
if(tree ~= nil) then
if(fields==nil) then
fields = {}
end
local s = function(i)
if(i==nil) then return ""
else return tostring(minetest.formspec_escape(i))
end
end
local seed
if(fields.seed == nil) then
seed = tostring(ltool.seed)
else
seed = fields.seed
end
local dropdownindex
if(fields.plantmode == "Absolute coordinates") then
dropdownindex = 1
elseif(fields.plantmode == "Relative coordinates") then
dropdownindex = 2
else
dropdownindex = 1
end
return ""..
"label[0,-0.2;Selected tree: "..minetest.formspec_escape(tree.name).."]"..
"dropdown[-0.1,0.5;5;plantmode;Absolute coordinates,Relative coordinates;"..dropdownindex.."]"..
"field[0.2,-2.7;6,10;x;x;"..s(fields.x).."]"..
"field[0.2,-2.1;6,10;y;y;"..s(fields.y).."]"..
"field[0.2,-1.5;6,10;z;z;"..s(fields.z).."]"..
"field[0.2,0;6,10;seed;Seed;"..seed.."]"..
"button[0,6.5;2,1;plant_plant;Plant]"..
"button[2.1,6.5;2,1;sapling;Give me a sapling]"
else
return "label[0,0;No tree in database selected or database is empty.]"
end
end
--[[ This creates the cheat sheet tab ]]
2014-07-22 08:49:50 -07:00
function ltool.cheat_sheet()
return ""..
"tablecolumns[text;text]"..
"tableoptions[background=#000000;highlight=#000000;border=false]"..
"table[0,0;6,7;cheat_sheet;"..
"Symbol,Action,"..
"G,Move forward one unit with the pen up,"..
"F,Move forward one unit with the pen down drawing trunks and branches,"..
"f,Move forward one unit with the pen down drawing leaves (100% chance),"..
"T,Move forward one unit with the pen down drawing trunks only,"..
"R,Move forward one unit with the pen down placing fruit,"..
"A,Replace with rules set A,"..
"B,Replace with rules set B,"..
"C,Replace with rules set C,"..
"D,Replace with rules set D,"..
"a,Replace with rules set A\\, chance 90%,"..
"b,Replace with rules set B\\, chance 80%,"..
"c,Replace with rules set C\\, chance 70%,"..
"d,Replace with rules set D\\, chance 60%,"..
"+,Yaw the turtle right by angle parameter,"..
"-,Yaw the turtle left by angle parameter,"..
"&,Pitch the turtle down by angle parameter,"..
"^,Pitch the turtle up by angle parameter,"..
"/,Roll the turtle to the right by angle parameter,"..
"*,Roll the turtle to the left by angle parameter,"..
"\\[,Save in stack current state info,"..
"\\],Recover from stack state info]"
end
--[[ creates the content of a textlist which contains all trees.
index: Selected entry
playername: To which the main formspec is shown to. Used for highlighting owned trees
returns (string to be used in the text list, table of tree IDs)
]]
function ltool.build_tree_textlist(index, playername)
local string = ""
local colorstring
if(ltool.number_of_trees == 0) then
return nil
end
local tree_ids = ltool.get_tree_ids()
for i=1,#tree_ids do
local tree_id = tree_ids[i]
local tree = ltool.trees[tree_id]
if(tree.author == playername) then
colorstring = "#FFFF00"
else
colorstring = ""
end
string = string .. colorstring .. tostring(tree_id) .. ": " .. minetest.formspec_escape(tree.name)
if(i~=#tree_ids) then
string = string .. ","
end
end
return string, tree_ids
end
--[=[ Here come functions which show formspecs to players ]=]
--[[ Shows the main tree formular to the given player, starting with the "Edit" tab ]]
function ltool.show_treeform(playername)
local formspec = ltool.loadtreeform..ltool.header(1)..ltool.edit(ltool.playerinfos[playername].treeform.edit.fields)
minetest.show_formspec(playername, "ltool:treeform_edit", formspec)
end
--[[ spawns a simple dialog formspec to a player ]]
function ltool.show_dialog(playername, formname, message)
local formspec = "size[6,2;]label[0,0.2;"..message.."]"..
"button[2,1.5;2,1;okay;OK]"
minetest.show_formspec(playername, formname, formspec)
end
--[=[ End of formspec-relatec functions ]=]
--[[ This function does a lot of parameter checks and returns (tree, tree_name) on success.
If ANY parameter check fails, the whole function fails.
On failure, it returns (nil, <error message string>).]]
2014-07-22 07:34:42 -07:00
function ltool.evaluate_edit_fields(fields)
local treedef = {}
-- Validation helper: Checks for invalid characters for the fields “axiom” and the 4 rule sets
local v = function(str)
local match = string.match(str, "[^][abcdfABCDFGTR+-/*&^]")
if(match==nil) then
return true
else
return false
end
end
if(v(fields.axiom) and v(fields.rules_a) and v(fields.rules_b) and v(fields.rules_c) and v(fields.rules_d)) then
treedef.rules_a = fields.rules_a
treedef.rules_b = fields.rules_b
treedef.rules_c = fields.rules_c
treedef.rules_d = fields.rules_d
treedef.axiom = fields.axiom
else
return nil, "The axiom or one of the rule sets contains at least one invalid character.\nSee the cheat sheet for a list of allowed characters."
end
2014-07-22 07:34:42 -07:00
treedef.trunk = fields.trunk
treedef.leaves = fields.leaves
treedef.leaves2 = fields.leaves2
treedef.leaves2_chance = fields.leaves2_chance
treedef.angle = tonumber(fields.angle)
2014-07-22 07:55:32 -07:00
if(treedef.angle == nil) then
return nil, "The field \"Angle\" must contain a number."
end
2014-07-22 07:34:42 -07:00
treedef.iterations = tonumber(fields.iterations)
2014-07-22 07:55:32 -07:00
if(treedef.iterations == nil) then
return nil, "The field \"Iterations\" must contain a natural number greater or equal to 0."
elseif(treedef.iterations < 0) then
return nil, "The field \"Iterations\" must contain a natural number greater or equal to 0."
end
2014-07-22 07:34:42 -07:00
treedef.random_level = tonumber(fields.random_level)
2014-07-22 07:55:32 -07:00
if(treedef.random_level == nil) then
return nil, "The field \"Randomness level\" must contain a number."
end
treedef.fruit = fields.fruit
treedef.fruit_chance = tonumber(fields.fruit_chance)
if(treedef.fruit_chance == nil) then
return nil, "The field \"Fruit chance\" must contain a number."
elseif(treedef.fruit_chance > 100 or treedef.fruit_chance < 0) then
return nil, "Fruit chance must be between 0% and 100%."
end
2014-07-22 07:34:42 -07:00
if(fields.trunk_type == "single" or fields.trunk_type == "double" or fields.trunk_type == "crossed") then
treedef.trunk_type = fields.trunk_type
else
return nil, "Trunk type must be \"single\", \"double\" or \"crossed\"."
end
treedef.thin_branches = fields.thin_branches
if(fields.thin_branches == "true") then
treedef.thin_branches = true
elseif(fields.thin_branches == "false") then
treedef.thin_branches = false
else
return nil, "Field \"Thin branches?\" must be \"true\" or \"false\"."
end
local name = fields.name
if(name == "") then
return nil, "Name is empty."
end
return treedef, name
end
--[=[ Here come several utility functions ]=]
--[[ converts a given tree to field names, as if they were given to a
minetest.register_on_plyer_receive_fields callback function ]]
function ltool.tree_to_fields(tree)
local s = function(i)
if(i==nil) then
return ""
else
return tostring(i)
end
end
local fields = {}
fields.axiom = s(tree.treedef.axiom)
fields.rules_a = s(tree.treedef.rules_a)
fields.rules_b = s(tree.treedef.rules_b)
fields.rules_c = s(tree.treedef.rules_c)
fields.rules_d = s(tree.treedef.rules_d)
fields.trunk = s(tree.treedef.trunk)
fields.leaves = s(tree.treedef.leaves)
fields.leaves2 = s(tree.treedef.leaves2)
fields.leaves2_chance = s(tree.treedef.leaves2)
fields.fruit = s(tree.treedef.leaves2)
fields.fruit_chance = s(tree.treedef.fruit_chance)
fields.angle = s(tree.treedef.angle)
fields.iterations = s(tree.treedef.iterations)
fields.random_level = s(tree.treedef.random_level)
fields.trunk_type = s(tree.treedef.trunk_type)
fields.thin_branches = s(tree.treedef.thin_branches)
fields.name = s(tree.name)
return fields
end
2014-07-19 14:32:35 -07:00
2014-07-25 18:18:31 -07:00
-- returns a simple table of all the tree IDs
function ltool.get_tree_ids()
local ids = {}
for tree_id, _ in pairs(ltool.trees) do
table.insert(ids, tree_id)
end
return ids
end
--[[ In a table of tree IDs (returned by ltool.get_tree_ids, parameter tree_ids), this function
searches for the first occourance of the value searched_tree_id and returns its index.
This is basically a reverse lookup utility. ]]
function ltool.get_tree_id_index(searched_tree_id, tree_ids)
for i=1, #tree_ids do
local table_tree_id = tree_ids[i]
if(searched_tree_id == table_tree_id) then
return i
end
end
end
2014-07-19 14:32:35 -07:00
2014-07-25 18:18:31 -07:00
-- Returns the selected tree of the given player
function ltool.get_selected_tree(playername)
local sel = ltool.playerinfos[playername].dbsel
if(sel ~= nil) then
local tree_id = ltool.playerinfos[playername].treeform.database.textlist[sel]
if(tree_id ~= nil) then
return ltool.trees[tree_id]
end
end
return nil
end
-- Returns the ID of the selected tree of the given player
2014-07-25 18:18:31 -07:00
function ltool.get_selected_tree_id(playername)
local sel = ltool.playerinfos[playername].dbsel
if(sel ~= nil) then
return ltool.playerinfos[playername].treeform.database.textlist[sel]
end
return nil
end
2014-07-19 14:32:35 -07:00
2014-07-19 14:32:35 -07:00
ltool.treeform = ltool.loadtreeform..ltool.header(1)..ltool.edit()
minetest.register_chatcommand("treeform",
{
params = "",
description = "Open L-system tree builder formular.",
privs = {},
func = function(playername, param)
ltool.show_treeform(playername)
2014-07-19 14:32:35 -07:00
end
})
2014-07-25 18:18:31 -07:00
function ltool.dbsel_to_tree(dbsel, playername)
return ltool.trees[ltool.playerinfos[playername].treeform.database.textlist[dbsel]]
end
function ltool.save_fields(playername,formname,fields)
if(formname=="ltool:treeform_edit") then
ltool.playerinfos[playername].treeform.edit.fields = fields
elseif(formname=="ltool:treeform_database") then
ltool.playerinfos[playername].treeform.database.fields = fields
elseif(formname=="ltool:treeform_plant") then
ltool.playerinfos[playername].treeform.plant.fields = fields
end
end
--[=[ Callback functions start here ]=]
2014-07-19 14:32:35 -07:00
function ltool.process_form(player,formname,fields)
2014-07-22 07:34:42 -07:00
local playername = player:get_player_name()
2014-07-25 18:18:31 -07:00
local seltree = ltool.get_selected_tree(playername)
--[[ process clicks on the tab header ]]
2014-07-26 05:58:12 -07:00
if(formname == "ltool:treeform_edit" or formname == "ltool:treeform_database" or formname == "ltool:treeform_plant" or formname == "ltool:treeform_cheat_sheet") then
2014-07-19 14:32:35 -07:00
if fields.ltool_tab ~= nil then
ltool.save_fields(playername, formname, fields)
2014-07-19 14:32:35 -07:00
local tab = tonumber(fields.ltool_tab)
2014-07-26 05:58:12 -07:00
local formspec, subformname, contents
2014-07-19 14:32:35 -07:00
if(tab==1) then
contents = ltool.edit(ltool.playerinfos[playername].treeform.edit.fields)
2014-07-26 05:58:12 -07:00
subformname = "edit"
2014-07-19 14:32:35 -07:00
elseif(tab==2) then
2014-07-23 17:41:39 -07:00
contents = ltool.database(ltool.playerinfos[playername].dbsel, playername)
2014-07-26 05:58:12 -07:00
subformname = "database"
2014-07-19 14:32:35 -07:00
elseif(tab==3) then
if(ltool.number_of_trees > 0) then
contents = ltool.plant(seltree, ltool.playerinfos[playername].treeform.plant.fields)
else
contents = ltool.plant(nil)
end
2014-07-26 05:58:12 -07:00
subformname = "plant"
2014-07-22 08:49:50 -07:00
elseif(tab==4) then
contents = ltool.cheat_sheet()
2014-07-26 05:58:12 -07:00
subformname = "cheat_sheet"
2014-07-19 14:32:35 -07:00
end
2014-07-22 08:49:50 -07:00
formspec = ltool.loadtreeform..ltool.header(tab)..contents
2014-07-26 05:58:12 -07:00
minetest.show_formspec(playername, "ltool:treeform_" .. subformname, formspec)
2014-07-19 14:32:35 -07:00
return
end
2014-07-26 05:58:12 -07:00
end
--[[ "Plant" tab ]]
2014-07-26 05:58:12 -07:00
if(formname == "ltool:treeform_plant") then
if(fields.plant_plant) then
2014-07-25 18:18:31 -07:00
if(seltree ~= nil) then
minetest.log("action","[ltool] Planting tree")
local treedef = seltree.treedef
local x,y,z = tonumber(fields.x), tonumber(fields.y), tonumber(fields.z)
local tree_pos
local fail = function()
ltool.save_fields(playername, formname, fields)
ltool.show_dialog(playername, "ltool:treeform_error_badplantfields", "Error: The coordinates must be numbers.")
2014-07-23 07:14:03 -07:00
end
2014-07-25 18:18:31 -07:00
if(fields.plantmode == "Absolute coordinates") then
if(type(x)~="number" or type(y) ~= "number" or type(z) ~= "number") then
fail()
return
end
tree_pos = {x=fields.x, y=fields.y, z=fields.z}
elseif(fields.plantmode == "Relative coordinates") then
if(type(x)~="number" or type(y) ~= "number" or type(z) ~= "number") then
fail()
return
end
tree_pos = player:getpos()
tree_pos.x = tree_pos.x + fields.x
tree_pos.y = tree_pos.y + fields.y
tree_pos.z = tree_pos.z + fields.z
else
minetest.log("error", "[ltool] fields.plantmode = "..tostring(fields.plantmode))
2014-07-23 07:14:03 -07:00
end
2014-07-25 18:18:31 -07:00
if(tonumber(fields.seed)~=nil) then
treedef.seed = tonumber(fields.seed)
end
minetest.spawn_tree(tree_pos, treedef)
treedef.seed = nil
2014-07-23 07:14:03 -07:00
end
2014-07-25 07:30:17 -07:00
elseif(fields.sapling) then
2014-07-25 18:18:31 -07:00
if(seltree ~= nil) then
local sapling = ItemStack("ltool:sapling")
-- TODO: Copy the seed into the sapling, too.
sapling:set_metadata(minetest.serialize(seltree.treedef))
local leftover = player:get_inventory():add_item("main", sapling)
if(not leftover:is_empty()) then
ltool.save_fields(playername, formname, fields)
ltool.show_dialog(playername, "ltool:treeform_error_sapling", "Error: The sapling could not be given to you. Probably your inventory is full.")
end
2014-07-25 18:18:31 -07:00
end
2014-07-26 05:58:12 -07:00
end
--[[ "Edit" tab ]]
2014-07-26 05:58:12 -07:00
elseif(formname == "ltool:treeform_edit") then
if(fields.edit_save) then
2014-07-22 07:34:42 -07:00
local param1, param2
param1, param2 = ltool.evaluate_edit_fields(fields)
2014-07-22 07:55:32 -07:00
if(param1 ~= nil) then
2014-07-22 07:34:42 -07:00
local treedef = param1
local name = param2
local add = true
for k,v in pairs(ltool.trees) do
if(v.name == name) then
ltool.save_fields(playername, formname, fields)
if(v.author == playername) then
local formspec = "size[6,2;]label[0,0.2;You already have a tree with this name. Do you want to replace it?]"..
"button[0,1.5;2,1;replace_yes;Yes]"..
"button[2,1.5;2,1;replace_no;No]"
minetest.show_formspec(playername, "ltool:treeform_replace", formspec)
else
ltool.show_dialog(playername, "ltool:treeform_error_nameclash", "Error: This name is already taken by someone else.\nPlease choose a different name.")
end
add = false
end
end
if(add == true) then
ltool.add_tree(name, playername, treedef)
end
2014-07-19 14:32:35 -07:00
else
ltool.save_fields(playername, formname, fields)
2014-07-22 07:34:42 -07:00
local formspec = "size[6,2;]label[0,0.2;Error: The tree definition is invalid.]"..
"label[0,0.4;"..minetest.formspec_escape(param2).."]"..
"button[2,1.5;2,1;okay;OK]"
minetest.show_formspec(playername, "ltool:treeform_error_badtreedef", formspec)
2014-07-19 14:32:35 -07:00
end
2014-07-26 05:58:12 -07:00
end
--[[ "Database" tab ]]
2014-07-26 05:58:12 -07:00
elseif(formname == "ltool:treeform_database") then
if(fields.treelist) then
local event = minetest.explode_textlist_event(fields.treelist)
if(event.type == "CHG") then
ltool.playerinfos[playername].dbsel = event.index
2014-07-23 17:41:39 -07:00
local formspec = ltool.loadtreeform..ltool.header(2)..ltool.database(event.index, playername)
2014-07-26 05:58:12 -07:00
minetest.show_formspec(playername, "ltool:treeform_database", formspec)
end
2014-07-19 14:32:35 -07:00
elseif(fields.database_copy) then
2014-07-25 18:18:31 -07:00
if(seltree ~= nil) then
if(ltool.playerinfos[playername] ~= nil) then
local formspec = ltool.loadtreeform..ltool.header(1)..ltool.edit(ltool.tree_to_fields(seltree))
2014-07-26 05:58:12 -07:00
minetest.show_formspec(playername, "ltool:treeform_edit", formspec)
2014-07-25 18:18:31 -07:00
end
else
ltool.show_dialog(playername, "ltool:treeform_error_nodbsel", "Error: No tree is selected.")
end
2014-07-21 17:08:07 -07:00
elseif(fields.database_update) then
2014-07-23 17:41:39 -07:00
local formspec = ltool.loadtreeform..ltool.header(2)..ltool.database(ltool.playerinfos[playername].dbsel, playername)
2014-07-26 05:58:12 -07:00
minetest.show_formspec(playername, "ltool:treeform_database", formspec)
elseif(fields.database_delete) then
2014-07-25 18:18:31 -07:00
if(seltree ~= nil) then
if(playername == seltree.author) then
local remove_id = ltool.get_selected_tree_id(playername)
if(remove_id ~= nil) then
ltool.remove_tree(remove_id)
2014-07-25 18:18:31 -07:00
local formspec = ltool.loadtreeform..ltool.header(2)..ltool.database(ltool.playerinfos[playername].dbsel, playername)
2014-07-26 05:58:12 -07:00
minetest.show_formspec(playername, "ltool:treeform_database", formspec)
end
2014-07-25 18:18:31 -07:00
else
ltool.show_dialog(playername, "ltool:treeform_error_delete", "Error: This tree is not your own. You may only delete your own trees.")
end
else
ltool.show_dialog(playername, "ltool:treeform_error_nodbsel", "Error: No tree is selected.")
end
2014-07-25 19:18:04 -07:00
elseif(fields.database_rename) then
if(seltree ~= nil) then
if(playername == seltree.author) then
local formspec = "field[newname;New name:;"..minetest.formspec_escape(seltree.name).."]"
minetest.show_formspec(playername, "ltool:treeform_rename", formspec)
else
ltool.show_dialog(playername, "ltool:treeform_error_rename_forbidden", "Error: This tree is not your own. You may only rename your own trees.")
2014-07-25 19:18:04 -07:00
end
else
ltool.show_dialog(playername, "ltool:treeform_error_nodbsel", "Error: No tree is selected.")
2014-07-25 19:18:04 -07:00
end
end
--[[ Process "Do you want to replace this tree?" dialog ]]
elseif(formname == "ltool:treeform_replace") then
local editfields = ltool.playerinfos[playername].treeform.edit.fields
local newtreedef, newname = ltool.evaluate_edit_fields(editfields)
if(fields.replace_yes) then
for tree_id,tree in pairs(ltool.trees) do
if(tree.name == newname) then
--[[ The old tree is deleted and a
new one with a new ID is created ]]
local new_tree_id = ltool.next_tree_id
ltool.trees[new_tree_id] = {}
ltool.trees[new_tree_id].treedef = newtreedef
ltool.trees[new_tree_id].name = newname
ltool.trees[new_tree_id].author = tree.author
ltool.next_tree_id = ltool.next_tree_id + 1
ltool.trees[tree_id] = nil
end
end
end
local formspec = ltool.loadtreeform..ltool.header(1)..ltool.edit(editfields)
minetest.show_formspec(playername, "ltool:treeform_edit", formspec)
--[[ Tree renaming dialog ]]
2014-07-25 19:18:04 -07:00
elseif(formname == "ltool:treeform_rename") then
if(fields.newname ~= "") then
seltree.name = fields.newname
local formspec = ltool.loadtreeform..ltool.header(2)..ltool.database(ltool.playerinfos[playername].dbsel, playername)
2014-07-26 05:58:12 -07:00
minetest.show_formspec(playername, "ltool:treeform_database", formspec)
2014-07-25 19:18:04 -07:00
else
ltool.show_dialog(playername, "ltool:treeform_error_bad_rename", "Error: This name is empty. The tree name must be non-empty.")
2014-07-19 14:32:35 -07:00
end
--[[ Here come various error messages to handle ]]
elseif(formname == "ltool:treeform_error_badtreedef" or formname == "ltool:treeform_error_nameclash") then
local formspec = ltool.loadtreeform..ltool.header(1)..ltool.edit(ltool.playerinfos[playername].treeform.edit.fields)
2014-07-26 05:58:12 -07:00
minetest.show_formspec(playername, "ltool:treeform_edit", formspec)
elseif(formname == "ltool:treeform_error_badplantfields" or formname == "ltool:treeform_error_sapling") then
local formspec = ltool.loadtreeform..ltool.header(3)..ltool.plant(seltree, ltool.playerinfos[playername].treeform.plant.fields)
2014-07-26 05:58:12 -07:00
minetest.show_formspec(playername, "ltool:treeform_plant", formspec)
elseif(formname == "ltool:treeform_error_delete" or formname == "ltool:treeform_error_rename_forbidden" or formname == "ltool:treeform_error_nodbsel") then
local formspec = ltool.loadtreeform..ltool.header(2)..ltool.database(ltool.playerinfos[playername].dbsel, playername)
2014-07-26 05:58:12 -07:00
minetest.show_formspec(playername, "ltool:treeform_database", formspec)
elseif(formname == "ltool:treeform_error_bad_rename") then
local formspec = "field[newname;New name:;"..minetest.formspec_escape(seltree.name).."]"
minetest.show_formspec(playername, "ltool:treeform_rename", formspec)
2014-07-19 14:32:35 -07:00
end
end
--[[ These 2 functions are basically just table initializions and cleanups ]]
2014-07-19 14:32:35 -07:00
function ltool.leave(player)
ltool.playerinfos[player:get_player_name()] = nil
end
function ltool.join(player)
2014-07-25 18:18:31 -07:00
local infotable = {}
infotable.dbsel = nil
infotable.treeform = {}
infotable.treeform.database = {}
--[[ This table stores a mapping of the textlist IDs in the database formspec and the tree IDs.
It is updated each time ltool.database is called. ]]
infotable.treeform.database.textlist = nil
--[[ the “fields” tables store the values of the input fields of a formspec. It is updated
whenever the formspec is changed, i.e. on tab change ]]
infotable.treeform.database.fields = {}
infotable.treeform.plant = {}
infotable.treeform.plant.fields = {}
infotable.treeform.edit = {}
infotable.treeform.edit.fields = {}
2014-07-25 18:18:31 -07:00
ltool.playerinfos[player:get_player_name()] = infotable
2014-07-19 14:32:35 -07:00
end
function ltool.save_to_file()
local savetable = {}
savetable.trees = ltool.trees
2014-07-25 18:18:31 -07:00
savetable.number_of_trees = ltool.number_of_trees
savetable.next_tree_id = ltool.next_tree_id
local savestring = minetest.serialize(savetable)
local filepath = minetest.get_worldpath().."/ltool.mt"
local file = io.open(filepath, "w")
if(file) then
file:write(savestring)
io.close(file)
minetest.log("action", "[ltool] Tree data saved to "..filepath..".")
else
minetest.log("error", "[ltool] Failed to write ltool data to "..filepath".")
end
end
2014-07-19 14:32:35 -07:00
minetest.register_on_player_receive_fields(ltool.process_form)
minetest.register_on_leaveplayer(ltool.leave)
minetest.register_on_joinplayer(ltool.join)
minetest.register_on_shutdown(ltool.save_to_file)