Implement land page

Fixes #21 and #20
master
rubenwardy 2018-12-04 01:27:03 +00:00
parent 42d792c4c3
commit 96e9ae7df2
6 changed files with 199 additions and 80 deletions

View File

@ -1,3 +1,8 @@
company.register_snippet("balance", function(comp)
return "Balance: " .. banking.get_balance(comp)
end)
company.register_panel({
title = "Finance",
bgcolor = "#DAA520",

View File

@ -185,6 +185,15 @@ function company.register_panel(def)
table.insert(company.registered_panels, def)
end
company.registered_snippets = {}
function company.register_snippet(name, func)
assert(type(name) == "string")
assert(type(func) == "function")
assert(not company.registered_snippets[name])
company.registered_snippets[name] = func
end
-- Minetest won't be available in tests
if minetest then
local storage = minetest.get_mod_storage()

View File

@ -55,22 +55,18 @@ company.show_company_select_dialog = lib_quickfs.register("company:set_company",
end,
})
function company.get_company_header(pname, width, mode)
local comp = company.get_active(pname)
local second = ""
if comp and mode == "balance" then
second = "Balance: " .. banking.get_balance(comp)
elseif comp then
second = "CEO: " .. comp:get_ceo_name()
end
function company.get_company_header(pname, width, snippet)
local comp = company.get_active(pname)
local func = company.registered_snippets[snippet or "ceo"]
assert(func, "Unable to find snippet " .. (snippet or "ceo"))
return table.concat({
"label[0.1,0.0;",
minetest.formspec_escape(comp and comp.title or "No active company"),
"]",
"label[0.1,0.4;",
minetest.formspec_escape(second),
minetest.formspec_escape(func(comp)),
"]",
"button[",
tostring(width - 2),
@ -142,6 +138,11 @@ sfinv.register_page("company:company", {
table.insert(sfinv.pages_unordered, 1, sfinv.pages["company:company"])
table.remove(sfinv.pages_unordered, #sfinv.pages_unordered)
company.register_snippet("ceo", function(comp)
return "CEO: " .. comp:get_ceo_name()
end)
company.register_panel({
title = "Company House",
bgcolor = "#369",

View File

@ -2,7 +2,10 @@ land.valid_types = { commercial = true, residential = true, industrial = true }
local adt = audit("land")
function land.get_area_tree(list)
function land.get_area_tree(list, owner)
assert(list == nil or type(list) == "table")
assert(owner == nil or type(owner) == "string")
list = list or areas.areas
list = table.copy(list)
@ -10,30 +13,44 @@ function land.get_area_tree(list)
local item_by_id = {}
local pending_by_id = {}
if owner then
for i=1, #list do
if not list[i].marked and list[i].owner == owner then
local ptr = i
while ptr and not list[ptr].marked do
list[ptr].marked = true
ptr = list[ptr].parent
end
end
end
end
for i=1, #list do
local area = list[i]
area.id = i
area.children = {}
if not area.parent then
root[#root + 1] = area
if owner == nil or list[i].marked then
if not area.parent then
root[#root + 1] = area
if pending_by_id[i] then
area.children = pending_by_id
pending_by_id[i] = nil
if pending_by_id[i] then
area.children = pending_by_id
pending_by_id[i] = nil
end
elseif item_by_id[area.parent] then
local children = item_by_id[area.parent].children
children[#children + 1] = area
else
pending_by_id[area.parent] = pending_by_id[area.parent] or {}
local pending = pending_by_id[area.parent]
pending[#pending + 1] = area
end
elseif item_by_id[area.parent] then
local children = item_by_id[area.parent].children
children[#children + 1] = area
else
pending_by_id[area.parent] = pending_by_id[area.parent] or {}
local pending = pending_by_id[area.parent]
pending[#pending + 1] = area
item_by_id[i] = area
end
item_by_id[i] = area
end
return root, item_by_id
@ -243,3 +260,42 @@ function land.buy(area, pname)
return true
end
function land.can_teleport_to(area, pname)
if type(pname) == "userdata" then
pname = pname:get_player_name()
end
assert(type(area) == "table")
assert(type(pname) == "string")
local comp = company.get_active(pname)
local owner = comp and comp.name or pname
if area.owner ~= owner and not area.land_open then
return false, "Attempted to teleport to land (" ..
area.name .. " [" .. dump(area.id) .. "]), which is not " ..
"open and is owned by someone else (owner=" .. area.owner ..
", teleporter=" .. owner .. ")"
end
if not area.spawn_point then
return false, "No spawn point for area: " ..
area.name .. " [" .. dump(area.id) .. "]"
end
return true
end
function land.teleport_to(area, player)
assert(type(area) == "table")
assert(type(player) == "userdata")
local suc, msg = land.can_teleport_to(area, player:get_player_name())
if suc then
player:set_pos(area.spawn_point)
end
if msg then
minetest.log("warning", msg)
end
return suc, msg
end

View File

@ -52,20 +52,13 @@ land.show_debug_to = lib_quickfs.register("land:debug", {
fs[#fs + 1] = ","
end
local lnd = land.get_by_area_id(area.id)
local p_lnd = area.parent and land.get_by_area_id(area.parent)
if lnd then
if lnd.land_type == "commercial" then
fs[#fs + 1] = "#69f,"
elseif lnd.land_type == "industrial" then
fs[#fs + 1] = "#f96,"
elseif lnd.land_type == "residential" then
fs[#fs + 1] = "#6f6,"
else
fs[#fs + 1] = "#000,"
end
elseif p_lnd then
if area.land_type == "commercial" then
fs[#fs + 1] = "#69f,"
elseif area.land_type == "industrial" then
fs[#fs + 1] = "#f96,"
elseif area.land_type == "residential" then
fs[#fs + 1] = "#6f6,"
elseif area.parent and land.get_by_area_id(area.parent) then
fs[#fs + 1] = ","
else
fs[#fs + 1] = "#999,"
@ -218,67 +211,118 @@ land.show_buy_to = lib_quickfs.register("land:buy", {
})
sfinv.register_page("land:places", {
title = "Places",
sfinv.register_page("land:land", {
title = "Land",
get = function(self, player, context)
local pname = player:get_player_name()
local comp = company.get_active(pname)
local owner = comp and comp.name or pname
-- Using an array to build a formspec is considerably faster
local formspec = {
company.get_company_header(pname, 8)
local fs = {
company.get_company_header(pname, 8, "land"),
"tablecolumns[color;tree;text,width=10;text]",
-- "tableoptions[background=#00000000;border=false]",
"table[0,1;5.8,7.65;list_areas;"
}
if comp then
local i = 0
for _, panel in pairs(company.registered_panels) do
if not panel.show_to or panel:show_to(player, comp, context) then
formspec[#formspec + 1] = "container["
formspec[#formspec + 1] = tostring((i % 2) * 4)
formspec[#formspec + 1] = ","
formspec[#formspec + 1] = tostring(math.floor(i / 2) * 2 + 1)
formspec[#formspec + 1] = ".3]"
local tree = land.get_area_tree(nil, owner)
local list = flatten_list(tree)
context.list = list
formspec[#formspec + 1] = "label[1.5,-0.3;"
formspec[#formspec + 1] = panel.title
formspec[#formspec + 1] = "]"
formspec[#formspec + 1] = "box[0,-0.3;3.8,1.8;"
formspec[#formspec + 1] = panel.bgcolor
formspec[#formspec + 1] = "]"
formspec[#formspec + 1] = panel:get(player, comp, context)
formspec[#formspec + 1] = "container_end[]"
i = i + 1
end
end
while i < 2*4 do
formspec[#formspec + 1] = "box["
formspec[#formspec + 1] = tostring((i % 2) * 4)
formspec[#formspec + 1] = ","
formspec[#formspec + 1] = tostring(math.floor(i / 2) * 2 + 1)
formspec[#formspec + 1] = ";3.8,1.8;#111]"
i = i + 1
end
if not context.selected then
context.selected = 1
elseif context.selected > #list then
context.selected = #list
end
for i=1, #list do
local area = list[i]
if i > 1 then
fs[#fs + 1] = ","
end
if area.owner ~= owner then
fs[#fs + 1] = "#999,"
elseif area.land_type == "commercial" then
fs[#fs + 1] = "#69f,"
elseif area.land_type == "industrial" then
fs[#fs + 1] = "#f96,"
elseif area.land_type == "residential" then
fs[#fs + 1] = "#6f6,"
elseif area.parent and land.get_by_area_id(area.parent) then
fs[#fs + 1] = ","
else
fs[#fs + 1] = "#999,"
end
fs[#fs + 1] = area.level .. "," ..
minetest.formspec_escape(area.name .. " [id=" .. area.id .. "]") .. "," ..
minetest.formspec_escape(area.owner)
end
fs[#fs + 1] = ";"
if context.selected then
fs[#fs + 1] = tostring(context.selected)
end
fs[#fs + 1] = "]"
if context.selected then
-- local area = list[context.selected]
fs[#fs + 1] = "container[0,-0.2]"
fs[#fs + 1] = "button[6,1;2,1;teleport;Teleport]"
fs[#fs + 1] = "box[6,2;1.8,0.8;#222]"
fs[#fs + 1] = "box[6,3;1.8,0.8;#222]"
fs[#fs + 1] = "box[6,4;1.8,0.8;#222]"
fs[#fs + 1] = "box[6,5;1.8,0.8;#222]"
fs[#fs + 1] = "box[6,6;1.8,0.8;#222]"
fs[#fs + 1] = "box[6,7;1.8,0.8;#222]"
fs[#fs + 1] = "box[6,8;1.8,0.8;#222]"
fs[#fs + 1] = "container_end[]"
else
fs[#fs + 1] = "label[0.1,6.1;No area selected]"
end
-- Wrap the formspec in sfinv's layout (ie: adds the tabs and background)
return sfinv.make_formspec(player, context,
table.concat(formspec, ""), false)
table.concat(fs, ""), false)
end,
on_player_receive_fields = function(self, player, context, fields)
if fields.switch then
company.show_company_select_dialog(player:get_player_name(), function(player2)
sfinv.set_page_and_show(player2, "company:company")
sfinv.set_page_and_show(player2, "land:land")
end)
end
if fields.list_areas then
local evt = minetest.explode_table_event(fields.list_areas)
context.selected = evt.row
return true
end
if fields.teleport then
if not context.selected or not context.list then
minetest.log("warning", "teleport, but no selected or list")
return
end
local area = context.list[context.selected]
assert(area)
if land.teleport_to(area, player) then
minetest.close_formspec(player:get_player_name(), "")
else
sfinv.set_page_and_show(player, "land:land")
end
end
end,
})
company.register_snippet("land", function(comp)
local areas = land.get_all(comp.name)
return "Land: " .. #areas
end)
company.register_panel({
title = "Land",
bgcolor = "#A0522D",

View File

@ -33,6 +33,8 @@ minetest.register_node("land:for_sale", {
local suc, msg = land.set_price(area, pname, 1000000)
if suc then
area.land_postpos = vector.new(pos)
area.spawn_point = area.spawn_point or area.land_postpos
areas:save()
minetest.set_node(vector.add(pos, {x=0,y=1,z=0}),
{ name = "land:for_sale_top" })
@ -60,6 +62,8 @@ minetest.register_node("land:for_sale", {
end
area.land_postpos = vector.new(pos)
area.spawn_point = area.spawn_point or area.land_postpos
areas:save()
if land.can_set_price(area, pname) then
land.show_set_price_to(pname, area, pos)