minetest_ltool/init.lua

398 lines
13 KiB
Lua
Raw Normal View History

2014-07-19 14:32:35 -07:00
ltool = {}
ltool.playerinfos = {}
2014-07-19 14:32:35 -07:00
ltool.trees = {}
ltool.emptytreedef = {
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="",
}
function ltool.add_tree(name, author, treedef)
table.insert(ltool.trees, {name = name, author = author, treedef = treedef})
end
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)
if(savetable.trees ~= nil) then
ltool.trees = savetable.trees
end
end
minetest.log("action", "[ltool] Tree data loaded from "..filepath..".")
end
end
2014-07-19 14:32:35 -07:00
ltool.seed = os.time()
ltool.loadtreeform = "size[6,7]"
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
2014-07-19 16:04:18 -07:00
function ltool.edit(tree)
local treedef, name
if(tree==nil) then
2014-07-19 14:32:35 -07:00
treedef = ltool.emptytreedef
2014-07-19 16:04:18 -07:00
name = ""
else
treedef = tree.treedef
name = tree.name
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(treedef.axiom).."]"..
"field[0.2,-3.4;6,10;rules_a;Rules set A;"..s(treedef.rules_a).."]"..
"field[0.2,-2.7;6,10;rules_b;Rules set B;"..s(treedef.rules_b).."]"..
"field[0.2,-2.1;6,10;rules_c;Rules set C;"..s(treedef.rules_c).."]"..
"field[0.2,-1.5;6,10;rules_d;Rules set D;"..s(treedef.rules_d).."]"..
"field[0.2,-0.9;3,10;trunk;Trunk node name;"..s(treedef.trunk).."]"..
"field[0.2,-0.3;3,10;leaves;Leaves node name;"..s(treedef.leaves).."]"..
"field[0.2,0.3;3,10;leaves2;Secondary leaves node name;"..s(treedef.leaves2).."]"..
2014-07-22 07:55:32 -07:00
"field[0.2,0.9;3,10;leaves2_chance;Secondary leaves chance (in percent);"..s(treedef.leaves2_chance).."]"..
2014-07-19 14:32:35 -07:00
"field[0.2,1.5;3,10;fruit;Fruit node name;"..s(treedef.fruit).."]"..
2014-07-22 07:55:32 -07:00
"field[0.2,2.1;3,10;fruit_chance;Fruit chance (in percent);"..s(treedef.fruit_chance).."]"..
2014-07-19 14:32:35 -07:00
2014-07-22 07:34:42 -07:00
"field[3.2,-0.9;3,10;angle;Angle (in degrees);"..s(treedef.angle).."]"..
2014-07-19 14:32:35 -07:00
"field[3.2,-0.3;3,10;iterations;Iterations;"..s(treedef.iterations).."]"..
"field[3.2,0.3;3,10;random_level;Randomness level;"..s(treedef.random_level).."]"..
"field[3.2,0.9;3,10;trunk_type;Trunk type (single/double/crossed);"..s(treedef.trunk_type).."]"..
"field[3.2,1.5;3,10;thin_branches;Thin branches? (true/false);"..s(treedef.thin_branches).."]"..
2014-07-19 16:04:18 -07:00
"field[3.2,2.1;3,10;name;Name;"..s(name).."]"..
"button[0,6.5;2,1;edit_save;Save]"
2014-07-19 14:32:35 -07:00
end
2014-07-23 17:41:39 -07:00
function ltool.database(index, playername)
local treestr = ltool.get_tree_names(index, playername)
if(treestr ~= nil) then
return ""..
"textlist[0,0;5,6;treelist;"..treestr..";"..tostring(index)..";false]"..
"button[0,6.5;2,1;database_copy;Copy to editor]"..
"button[2.1,6.5;2,1;database_update;Reload]"
else
return "label[0,0;The tree database is empty.]"..
"button[2.1,6.5;2,1;database_update;Reload]"
end
2014-07-19 14:32:35 -07:00
end
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
2014-07-22 07:34:42 -07:00
function ltool.evaluate_edit_fields(fields)
local treedef = {}
treedef.axiom = fields.axiom
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.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
function ltool.plant(tree)
if(tree ~= nil) then
return ""..
2014-07-23 07:14:03 -07:00
"label[0,-0.2;Selected tree: "..minetest.formspec_escape(tree.name).."]"..
"dropdown[-0.1,0.5;5;plantmode;Absolute coordinates,Relative coordinates;1]"..
"field[0.2,-2.7;6,10;x;x;]"..
"field[0.2,-2.1;6,10;y;y;]"..
"field[0.2,-1.5;6,10;z;z;]"..
"field[0.2,0;6,10;seed;Seed;"..ltool.seed.."]"..
"button[0,6.5;2,1;plant_plant;Plant]"
else
return "label[0,0;There are no trees to plant.]"
end
2014-07-19 14:32:35 -07:00
end
2014-07-23 17:41:39 -07:00
function ltool.get_tree_names(index, playername)
2014-07-19 14:32:35 -07:00
local string = ""
if(#ltool.trees == 0) then
return nil
end
2014-07-23 17:41:39 -07:00
local colorstring
2014-07-19 14:32:35 -07:00
for t=1,#ltool.trees do
2014-07-23 17:41:39 -07:00
if(ltool.trees[t].author == playername) then
colorstring = "#FFFF00"
else
colorstring = ""
end
string = string .. colorstring .. minetest.formspec_escape(ltool.trees[t].name)
2014-07-19 14:32:35 -07:00
if(t < #ltool.trees) then
string = string .. ","
end
end
return string
end
ltool.treeform = ltool.loadtreeform..ltool.header(1)..ltool.edit()
minetest.register_chatcommand("treeform",
{
params = "",
description = "Open L-system tree builder formular.",
privs = {privs=false},
func = function(player_name, param)
local player = minetest.get_player_by_name(player_name)
local formspec
-- if(ltool.playerinfos[player] == nil) then
formspec = ltool.treeform
--[[ else
local i = ltool.playerinfos[player]
formspec =
"size[6,7]"..
"field[0.2,-4;6,10;axiom;Axiom;"..i.axiom.."]"..
"field[0.2,-3.4;6,10;rules_a;Rules set A;"..i.rules_a.."]"..
"field[0.2,-2.7;6,10;rules_b;Rules set B;"..i.rules_b.."]"..
"field[0.2,-2.1;6,10;rules_c;Rules set C;"..i.rules_c.."]"..
"field[0.2,-1.5;6,10;rules_d;Rules set D;"..i.ruled_d.."]"..
"field[0.2,-0.9;3,10;trunk;Trunk node name;"..i.trunk.."]"..
"field[0.2,-0.3;3,10;leaves;Leaves node name;"..i.leaves.."]"..
"field[0.2,0.3;3,10;leaves2;Secondary leaves node name;"..i.leaves2.."]"..
"field[0.2,0.9;3,10;leaves2_chance;Secondary leaves chance;"..i.leaves2_chance.."]"..
"field[0.2,1.5;3,10;fruit;Fruit node name;"..i.fruit.."]"..
"field[0.2,2.1;3,10;fruit_chance;Fruit chance;"..i.fruit_chance.."]"..
"field[3.2,-0.9;3,10;angle;Angle;"..i.angle.."]"..
"field[3.2,-0.3;3,10;iterations;Iterations;"..i.iterations.."]"..
"field[3.2,0.3;3,10;random_level;Randomness level;"..i.random_level.."]"..
"field[3.2,0.9;3,10;trunk_type;Trunk type (single/double/crossed);"..i.trunk_type.."]"..
"field[3.2,1.5;3,10;thin_branches;Thin branches? (true/false);"..i.thin_branches.."]"..
"button[0.6,6.5;2,1;edit_save;Save]"..
2014-07-19 14:32:35 -07:00
end
]]
minetest.show_formspec(player_name, "ltool:treeform", formspec)
end
})
function ltool.process_form(player,formname,fields)
2014-07-22 07:34:42 -07:00
local playername = player:get_player_name()
2014-07-19 14:32:35 -07:00
if(formname == "ltool:treeform") then
if fields.ltool_tab ~= nil then
local tab = tonumber(fields.ltool_tab)
2014-07-22 08:49:50 -07:00
local formspec, contents
2014-07-19 14:32:35 -07:00
if(tab==1) then
2014-07-22 08:49:50 -07:00
contents = ltool.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-19 14:32:35 -07:00
elseif(tab==3) then
if(#ltool.trees > 0) then
contents = ltool.plant(ltool.trees[ltool.playerinfos[playername].dbsel])
else
contents = ltool.plant()
end
2014-07-22 08:49:50 -07:00
elseif(tab==4) then
contents = ltool.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
minetest.show_formspec(playername, "ltool:treeform", formspec)
2014-07-19 14:32:35 -07:00
return
end
if(fields.plant_plant) then
minetest.log("action","[ltool] Planting tree")
local tree = ltool.trees[ltool.playerinfos[playername].dbsel]
2014-07-22 09:42:49 -07:00
local treedef = tree.treedef
2014-07-19 14:32:35 -07:00
2014-07-23 07:14:03 -07:00
local x,y,z = tonumber(fields.x), tonumber(fields.y), tonumber(fields.z)
local tree_pos
local fail = function()
local formspec = "size[6,2;]label[0,0.2;Error: The coordinates must be numbers.]"..
"button[2,1.5;2,1;okay;OK]"
minetest.show_formspec(playername, "ltool:treeform_error_badplantfields", formspec)
end
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))
end
2014-07-19 14:32:35 -07:00
2014-07-23 07:14:03 -07:00
if(tonumber(fields.seed)~=nil) then
treedef.seed = tonumber(fields.seed)
end
2014-07-22 09:42:49 -07:00
minetest.spawn_tree(tree_pos, treedef)
treedef.seed = nil
2014-07-19 14:32:35 -07:00
elseif(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
ltool.add_tree(name, playername, treedef)
2014-07-19 14:32:35 -07:00
else
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
elseif(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)
minetest.show_formspec(playername, "ltool:treeform", formspec)
end
2014-07-19 14:32:35 -07:00
elseif(fields.database_copy) then
if(ltool.playerinfos[playername] ~= nil) then
sel = ltool.playerinfos[playername].dbsel
else
sel = 1
end
local formspec = ltool.loadtreeform..ltool.header(1)..ltool.edit(ltool.trees[sel])
minetest.show_formspec(playername, "ltool:treeform", formspec)
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-21 17:08:07 -07:00
minetest.show_formspec(playername, "ltool:treeform", formspec)
2014-07-19 14:32:35 -07:00
end
2014-07-22 07:34:42 -07:00
elseif(formname == "ltool:treeform_error_badtreedef") then
local formspec = ltool.loadtreeform..ltool.header(1)..ltool.edit()
minetest.show_formspec(playername, "ltool:treeform", formspec)
2014-07-23 07:14:03 -07:00
elseif(formname == "ltool:treeform_error_badplantfields") then
local formspec = ltool.loadtreeform..ltool.header(3)..ltool.plant(ltool.trees[ltool.playerinfos[playername].dbsel])
minetest.show_formspec(playername, "ltool:treeform", formspec)
2014-07-19 14:32:35 -07:00
end
end
function ltool.leave(player)
ltool.playerinfos[player:get_player_name()] = nil
end
function ltool.join(player)
ltool.playerinfos[player:get_player_name()] = { dbsel = 1 }
2014-07-19 14:32:35 -07:00
end
function ltool.save_to_file()
local savetable = {}
savetable.trees = ltool.trees
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)