191 lines
5.1 KiB
Lua
191 lines
5.1 KiB
Lua
if not whosit then
|
|
print("define `whosit` global first")
|
|
--return
|
|
end
|
|
|
|
whosit = whosit or {} -- this will become snippet's "global" if not defined as a real one
|
|
|
|
local chunk_map = whosit.chunk_map or {}
|
|
whosit.chunk_map = chunk_map
|
|
|
|
local jobs = chunk_map.jobs or {}
|
|
chunk_map.jobs = jobs
|
|
|
|
local FORMNAME = "whosit:chunk_map"
|
|
|
|
chunk_map._contexts = chunk_map._contexts or {}
|
|
|
|
local function get_context(player_name, create_new)
|
|
local context = chunk_map._contexts[player_name] or (create_new and {})
|
|
if context then
|
|
chunk_map._contexts[player_name] = context
|
|
context.player_name = player_name
|
|
end
|
|
return context
|
|
end
|
|
|
|
|
|
local function round_to_mapblock(pos)
|
|
return vector.apply(pos/16, math.floor) * 16
|
|
end
|
|
|
|
|
|
local function is_pos_emerged(pos)
|
|
core.load_area(pos,pos)
|
|
local node = core.get_node(pos)
|
|
if node and node.name ~= 'ignore' then
|
|
return true
|
|
end
|
|
return false
|
|
end
|
|
|
|
chunk_map.show_map = function(playername, pos)
|
|
if type(playername) ~= "string" or (not vector.check(pos)) then
|
|
return
|
|
end
|
|
|
|
local context = get_context(playername, true)
|
|
context.pos = pos or context.pos
|
|
if not pos then
|
|
return
|
|
end
|
|
|
|
|
|
local map_display_width = 11
|
|
local map_display_height = 10
|
|
local map_display_cell_size = 0.5
|
|
|
|
local formspec = [[
|
|
formspec_version[6]
|
|
size[16,10]
|
|
box[0.1,0.1;13.0,10.0;grey]
|
|
button[13.9,0.8;0.8,0.8;north;N]
|
|
button[14.8,1.7;0.8,0.8;east;E]
|
|
button[13.9,2.6;0.8,0.8;south;S]
|
|
button[13,1.7;0.8,0.8;west;W]
|
|
button[12.9,0.7;0.8,0.8;down;D]
|
|
button[14.9,0.7;0.8,0.8;up;U]
|
|
box[0.2,0.2;0.5,0.5;yellow]
|
|
]]
|
|
|
|
local cells = {}
|
|
local template = string.format("box[%%s,%%s;%s,%s;%%s]", map_display_cell_size, map_display_cell_size)
|
|
|
|
local center = pos
|
|
local map_display_width_blocks = map_display_width/map_display_cell_size
|
|
local map_display_height_blocks = map_display_height/map_display_cell_size
|
|
local top_left_x = pos.x - (map_display_width_blocks*16/2)
|
|
local top_left_z = pos.z - (map_display_height_blocks*16/2)
|
|
local query_pos = vector.new(top_left_x, pos.y, top_left_z)
|
|
for idx_x = 0, map_display_width_blocks do
|
|
for idx_z = 0, map_display_height_blocks do
|
|
local emerged = is_pos_emerged(query_pos)
|
|
table.insert(cells, string.format(template,
|
|
idx_x * map_display_cell_size,
|
|
idx_z * map_display_cell_size,
|
|
emerged and "blue" or "white"))
|
|
query_pos.z = query_pos.z + 16
|
|
end
|
|
query_pos.x = query_pos.x + 16
|
|
end
|
|
|
|
table.insert(cells, string.format("label[13.1,4;%s]", dump(pos)))
|
|
|
|
core.show_formspec(playername, FORMNAME, formspec .. table.concat(cells,''))
|
|
end
|
|
|
|
|
|
chunk_map.map_on_player_receive_fields = function(playername, formname, fields)
|
|
if formname ~= FORMNAME then
|
|
return
|
|
end
|
|
|
|
local context = get_context(playername, false)
|
|
if not context or not context.pos then
|
|
return
|
|
end
|
|
|
|
if fields.quit then
|
|
return
|
|
end
|
|
|
|
local pos = context.pos
|
|
if fields.north then
|
|
pos.z = pos.z + 16
|
|
elseif fields.south then
|
|
pos.z = pos.z - 16
|
|
elseif fields.east then
|
|
pos.x = pos.x + 16
|
|
elseif fields.west then
|
|
pos.x = pos.x - 16
|
|
elseif fields.up then
|
|
-- FIXME use 16 here
|
|
pos.y = pos.y + 1
|
|
elseif fields.down then
|
|
-- FIXME use 16 here
|
|
pos.y = pos.y - 1
|
|
end
|
|
chunk_map.show_map(playername, pos)
|
|
end
|
|
|
|
|
|
chunk_map.step_jobs = function(dtime)
|
|
--print(dtime)
|
|
local jobs = chunk_map.jobs
|
|
for i=#jobs,1,-1 do
|
|
local job = jobs[i]
|
|
if job.coro and coroutine.status(job.coro) == "supended" then
|
|
coroutine.resume(job.coro)
|
|
else
|
|
print(string.format("job %s done", job))
|
|
jobs[i] = nil
|
|
end
|
|
end
|
|
|
|
end
|
|
|
|
|
|
chunk_map.cmd_show_map = function(playername, params)
|
|
local params = params:split(" ")
|
|
local x,y,z = table.unpack(params)
|
|
x,y,z = tonumber(x), tonumber(y), tonumber(z)
|
|
|
|
local pos
|
|
if (type(x) == "number" and type(y) == "number" and type(z) == "number") then
|
|
pos = vector.new(x,y,z)
|
|
else
|
|
local context = get_context(playername)
|
|
pos = context and context.pos
|
|
end
|
|
|
|
if not pos then
|
|
return false, "please provide x y z"
|
|
end
|
|
chunk_map.show_map(playername, pos)
|
|
end
|
|
|
|
|
|
if not chunk_map.callbacks_registered then
|
|
core.register_on_player_receive_fields(
|
|
chunk_map.map_on_player_receive_fields
|
|
)
|
|
|
|
core.register_on_leaveplayer(function(player)
|
|
local player_name = player:get_player_name()
|
|
chunk_map._contexts[player_name] = nil
|
|
end)
|
|
|
|
-- core.register_globalstep(function(dtime)
|
|
-- chunk_map.step_jobs(dtime)
|
|
-- end)
|
|
|
|
|
|
core.register_chatcommand("whosit_chunk_map",
|
|
{
|
|
func = chunk_map.cmd_show_map,
|
|
}
|
|
)
|
|
|
|
chunk_map.callbacks_registered = true
|
|
end
|