telemosaic/api.lua

420 lines
14 KiB
Lua

local enable_particles = minetest.settings:get_bool("enable_particles")
telemosaic = {}
telemosaic.extender_ranges = {
-- not adding beacons here, since they don"t extend
["telemosaic:extender_one"] = 5,
["telemosaic:extender_two"] = 20,
["telemosaic:extender_three"] = 80
}
telemosaic.strengths = { "one", "two", "three" }
function telemosaic.effect_departure(pos)
minetest.sound_play("telemosaic_set", {
pos = pos,
max_hear_distance = 8,
gain = 1
})
if not enable_particles then return end
minetest.add_particlespawner({
amount = 100,
time = 0.25,
minpos = {x=pos.x, y=pos.y+0.3, z=pos.z},
maxpos = {x=pos.x, y=pos.y+2, z=pos.z},
minvel = {x = 1, y = -6, z = 1},
maxvel = {x = -1, y = -1, z = -1},
minacc = {x = 0, y = -2, z = 0},
maxacc = {x = 0, y = -6, z = 0},
minexptime = 0.1,
maxexptime = 1,
minsize = 0.5,
maxsize = 1.5,
texture = "telemosaic_particle_departure.png^[transform"..math.random(0,3),
glow = 15,
})
end
function telemosaic.effect_arrival(pos)
minetest.sound_play("telemosaic_teleport", {
pos = pos,
max_hear_distance = 8,
gain = 1
})
if not enable_particles then return end
minetest.add_particlespawner({
amount = 100,
time = 0.25,
minpos = {x=pos.x, y=pos.y+0.3, z=pos.z},
maxpos = {x=pos.x, y=pos.y+2, z=pos.z},
minvel = {x = -1, y = 1, z = -1},
maxvel = {x = 1, y = 6, z = 1},
minacc = {x = 0, y = -2, z = 0},
maxacc = {x = 0, y = -6, z = 0},
minexptime = 0.1,
maxexptime = 1,
minsize = 0.5,
maxsize = 1.5,
texture = "telemosaic_particle_arrival.png^[transform"..math.random(0,3),
glow = 15,
})
end
function telemosaic.get_formspec(pos, table)
local meta = minetest.get_meta(pos)
local arrivals_tbl = meta:get_string("arrivals_tbl")
local pos2_str = meta:get_string("dest_pos")
local pos2 = minetest.string_to_pos(pos2_str)
arrivals_tbl = minetest.deserialize(arrivals_tbl)
if not arrivals_tbl then arrivals_tbl = {} end
local range = table.range or 0
local bname = meta:get_string("bname")
if not bname or bname == "" then
bname = "beacon at: "..minetest.formspec_escape(minetest.pos_to_string(pos))
end
local textlist = ""
for ipos, ival in pairs(arrivals_tbl) do
textlist = textlist..minetest.formspec_escape(ipos)..": "..ival..","
end
local button_teleport = ""
local pos2_colorize = minetest.colorize("#ff0000", pos2_str)
if pos2 then
local meta2 = minetest.get_meta(pos2)
local bname2 = meta2:get_string("bname")
pos2_colorize = minetest.colorize("#00ff00", bname2)
button_teleport = "button_exit[0.1,7.5;2.4,1.5;teleport;Teleport Now]"
end
-- dynamic formspec
local formspec = "size[12,8.5]"..
default.gui_bg..
default.gui_bg_img..
default.gui_slots..
"label[0,0.5;beacon position: "..minetest.pos_to_string(pos).."]"..
"label[0,1;destinaton: "..pos2_colorize.."]"..
"label[0,1.5;range: "..range.." blocks]"..
"field[0.34,2.7;4,1;bname;beacon name:;"..bname.."]"..
button_teleport..
"button_exit[2.5,7.5;2.4,1.5;saveandclose;Save & Close]"..
"label[5,0;Arrivals from ( x | y | z ):]"..
"textlist[5,0.5;6.7,8;arrivals;"..textlist..";1;false]"
return formspec
end
minetest.register_on_player_receive_fields(function(player, formname, fields)
local mod_pos_pos2 = formname:split(":")
if fields.bname and mod_pos_pos2[1] == "telemosaic" then
local bname = fields.bname
local pos = minetest.string_to_pos(mod_pos_pos2[2])
local meta = minetest.get_meta(pos)
local pos2 = minetest.string_to_pos(mod_pos_pos2[3])
meta:set_string("bname", bname)
if pos2 then
local meta2 = minetest.get_meta(pos2)
local arrivals_tbl2 = meta2:get_string("arrivals_tbl")
arrivals_tbl2 = minetest.deserialize(arrivals_tbl2)
if not arrivals_tbl2 then arrivals_tbl2 = {} end
arrivals_tbl2[minetest.pos_to_string(pos)] = minetest.formspec_escape(bname)
meta2:set_string("arrivals_tbl", minetest.serialize(arrivals_tbl2))
end
if fields.teleport then
local range = meta:get_int("range")
if pos2 then
if math.floor(vector.distance(pos, pos2)) <= range then
pos2 = {x = pos2.x, y = pos2.y + 1, z = pos2.z}
-- attempt to emerge the target area before the player gets there
local vpos = vector.new(pos2)
minetest.get_voxel_manip():read_from_map(vpos, vpos)
if not minetest.get_node_or_nil(pos2) then
print("emerge area")
minetest.emerge_area(vector.subtract(vpos, 80), vector.add(vpos, 80))
end
minetest.after(5, function()
player:setpos(pos2)
telemosaic.effect_arrival(pos2)
telemosaic.effect_departure(pos)
end)
else
minetest.chat_send_player(player:get_player_name(), "Not enough power, destination is too far. Beacon needs "..math.floor(vector.distance(pos, pos2)) - range.." more power.")
end
end
end
end
end)
-- extenders
function telemosaic.extender_after_place(pos, placer, itemstack, pointed_thing)
local positions = minetest.find_nodes_in_area_under_air(
{x = pos.x - 3, y = pos.y, z = pos.z - 3},
{x = pos.x + 3, y = pos.y, z = pos.z + 3},
{"telemosaic:beacon_off", "telemosaic:beacon", "telemosaic:beacon_err"})
local meta = minetest.get_meta(pos)
local playername = placer:get_player_name()
local nodename = itemstack:get_name()
if not minetest.registered_nodes[nodename] then return end
local description = minetest.registered_nodes[nodename]["description"]
local power = telemosaic.extender_ranges[nodename]
for i, bpos in ipairs(positions) do
local bnode = minetest.get_node(bpos)
local bmeta = minetest.get_meta(bpos)
if not bnode then return end
local bnodename = bnode.name
if not minetest.registered_nodes[bnodename] then return end
local bdescription = minetest.registered_nodes[bnodename]["description"]
local bowner = bmeta:get_string("owner")
local brange = bmeta:get_int("range")
brange = brange + power
bmeta:set_int("range", brange)
telemosaic.set_status(bpos, placer)
bmeta:set_string("infotext", bdescription.."\nowner: "..bowner.."\nrange: "..brange.." blocks\nright-click to update info or with mese crystal fragment setup departure position")
end
meta:set_string("owner", playername)
meta:set_string("infotext", description.."\nowner: "..playername)
end
function telemosaic.extender_on_destruct(pos)
local node = minetest.get_node(pos)
if not node then return end
local meta = minetest.get_meta(pos)
local nodename = node.name
if not minetest.registered_nodes[nodename] then return end
local power = telemosaic.extender_ranges[nodename]
local positions = minetest.find_nodes_in_area_under_air(
{x = pos.x - 3, y = pos.y, z = pos.z - 3},
{x = pos.x + 3, y = pos.y, z = pos.z + 3},
{"telemosaic:beacon_off", "telemosaic:beacon", "telemosaic:beacon_err"})
for i, bpos in ipairs(positions) do
local bnode = minetest.get_node(bpos)
local bmeta = minetest.get_meta(bpos)
if not bmeta or not bnode then return end
local bnodename = bnode.name
if not minetest.registered_nodes[bnodename] then return end
local bdescription = minetest.registered_nodes[bnodename]["description"]
local bowner = bmeta:get_string("owner")
local brange = bmeta:get_int("range")
brange = brange - power
if brange < 0 then brange = 0 end
bmeta:set_int("range", brange)
telemosaic.set_status(bpos)
bmeta:set_string("infotext", bdescription.."\nowner: "..bowner.."\nrange: "..brange.." blocks\nright-click to update info or with mese crystal fragment setup departure position")
end
end
-- beacons
function telemosaic.get_range_from_extenders(be_pos)
local positions = minetest.find_nodes_in_area_under_air(
{x = be_pos.x - 3, y = be_pos.y, z = be_pos.z - 3},
{x = be_pos.x + 3, y = be_pos.y, z = be_pos.z + 3},
{"telemosaic:extender_one", "telemosaic:extender_two", "telemosaic:extender_three"})
local range = 0
for i, ex_pos in ipairs(positions) do
local inode = minetest.get_node(ex_pos)
if not inode then return end
range = range + telemosaic.extender_ranges[inode.name]
end
return range
end
function telemosaic.set_status(pos)
local meta = minetest.get_meta(pos)
if not meta then return end
local range = meta:get_int("range")
local pos2 = meta:get_string("dest_pos")
local state = meta:get_string("state")
local arrivals_tbl = meta:get_string("arrivals_tbl")
arrivals_tbl = minetest.deserialize(arrivals_tbl)
if not arrivals_tbl then arrivals_tbl = {} end
-- not enough energy (err)
if range <= 0 and
state ~= "err" then
minetest.swap_node(pos, { name = "telemosaic:beacon_err" })
meta:set_string("state", "err")
-- configured beacon (off)
elseif range > 0 and
pos2 == "not configured" and
state ~= "off" and
#arrivals_tbl == 0 then
minetest.swap_node(pos, { name = "telemosaic:beacon_off" })
meta:set_string("state", "off")
-- not configured beacon (on)
elseif range > 0 and
pos2 ~= "not configured" and
state ~= "on" then
minetest.swap_node(pos, { name = "telemosaic:beacon" })
meta:set_string("state", "on")
end
end
function telemosaic.beacon_after_place(pos, placer, itemstack, pointed_thing)
local meta = minetest.get_meta(pos)
local nodename = itemstack:get_name()
local playername = placer:get_player_name()
local range = telemosaic.get_range_from_extenders(pos)
if not minetest.registered_nodes[nodename] then return end
local bname = "beacon at: "..minetest.formspec_escape(minetest.pos_to_string(pos))
local description = minetest.registered_nodes[nodename]["description"]
meta:set_int("range", range)
meta:set_string("bname", bname)
meta:set_string("owner", playername)
meta:set_string("state", "off")
meta:set_string("dep_pos", "")
meta:set_string("dest_pos", "not configured")
meta:set_string("arrivals_tbl", "{}")
meta:set_string("infotext", description.."\nowner: "..playername.."\nrange: "..range.." blocks\nright-click to update info or with mese crystal fragment setup departure position")
telemosaic.set_status(pos)
end
function telemosaic.beacon_rightclick(pos, node, clicker, itemstack, pointed_thing)
local meta = minetest.get_meta(pos)
local meta_stack = itemstack:get_meta()
local ownername = meta:get_string("owner") or "unknown"
local clickername = clicker:get_player_name()
local nodename = node.name
local stackname = itemstack:get_name()
local range = telemosaic.get_range_from_extenders(pos)
local state = meta:get_string("state")
if not minetest.registered_nodes[nodename] then return end
local description = minetest.registered_nodes[nodename]["description"]
meta:set_int("range", range)
-- departure
if stackname == "default:mese_crystal_fragment" and itemstack:get_count() == 1 then
itemstack:replace("telemosaic:key")
meta_stack:set_string("dep_pos", minetest.pos_to_string(pos))
meta:set_string("infotext", description.."\nowner: "..ownername.."\nrange: "..range.." blocks\nstart pos: "..minetest.pos_to_string(pos).."\nright-click to update info")
-- destination
elseif stackname == "telemosaic:key" then
-- get deprature position from item
local pos_stack = meta_stack:get_string("dep_pos")
pos_stack = minetest.string_to_pos(pos_stack)
if math.floor(vector.distance(pos_stack, pos)) == 0 then
minetest.chat_send_player(clickername, "This is marked as your departure position, you have to mark your destination position now!")
return
elseif minetest.is_protected(pos, clickername) then
minetest.chat_send_player(clickername, "You cannot configure protected beacons!")
return
end
-- enough extenders / range
-- if math.floor(vector.distance(pos_stack, pos)) <= range then
minetest.swap_node(pos, { name = "telemosaic:beacon" })
meta:set_string("state", "on")
itemstack:replace("default:mese_crystal_fragment")
-- set arrival pos to departure pos node
local meta2 = minetest.get_meta(pos_stack)
local bname2 = meta2:get_string("bname")
local pos3 = meta2:get_string("dest_pos")
pos3 = minetest.string_to_pos(pos3)
if pos3 and math.floor(vector.distance(pos3, pos)) ~= 0 then
local meta3 = minetest.get_meta(pos3)
local arrivals_tbl3 = meta3:get_string("arrivals_tbl")
arrivals_tbl3 = minetest.deserialize(arrivals_tbl3)
if not arrivals_tbl3 then arrivals_tbl3 = {} end
arrivals_tbl3[minetest.pos_to_string(pos_stack)] = nil
meta3:set_string('arrivals_tbl', arrivals_tbl3)
telemosaic.set_status(pos3)
end
local arrivals_tbl = meta:get_string("arrivals_tbl")
arrivals_tbl = minetest.deserialize(arrivals_tbl)
if not arrivals_tbl then arrivals_tbl = {} end
arrivals_tbl[minetest.pos_to_string(pos_stack)] = bname2
arrivals_tbl = minetest.serialize(arrivals_tbl)
meta2:set_string("dest_pos", minetest.pos_to_string(pos))
meta:set_string("arrivals_tbl", arrivals_tbl)
telemosaic.set_status(pos_stack)
meta:set_string("infotext", description.."\nowner: "..ownername.."\nrange: "..range.." blocks\nend pos: "..minetest.pos_to_string(pos).."\nright-click to update info")
-- default place_node callback
elseif itemstack:get_definition().type == "node" then
itemstack = minetest.item_place_node(itemstack, clicker, pointed_thing)
else
-- mod : pos : pos2
-- - pos2 is from itemstack so not always set
local formspec = telemosaic.get_formspec(pos, {
range = range
})
local pos2 = meta:get_string("dest_pos")
minetest.show_formspec(clickername, "telemosaic:"..minetest.pos_to_string(pos)..":"..pos2, formspec)
meta:set_string("infotext", description.."\nowner: "..ownername.."\nrange: "..range.." blocks\nright-click to update info")
end
return itemstack
end
function telemosaic.beacon_on_destruct(pos)
local meta = minetest.get_meta(pos)
local pos2 = meta:get_string("dest_pos")
pos2 = minetest.string_to_pos(pos2)
local arrivals_tbl = meta:get_string("arrivals_tbl")
arrivals_tbl = minetest.deserialize(arrivals_tbl)
if not arrivals_tbl then arrivals_tbl = {} end
-- found destination position, will update the meta in destination
if pos2 then
local meta2 = minetest.get_meta(pos2)
local arrivals_tbl2 = meta2:get_string("arrivals_tbl")
arrivals_tbl2 = minetest.deserialize(arrivals_tbl2)
if not arrivals_tbl2 then arrivals_tbl2 = {} end
if arrivals_tbl2[minetest.pos_to_string(pos)] then
arrivals_tbl2[minetest.pos_to_string(pos)] = nil
arrivals_tbl2 = minetest.serialize(arrivals_tbl2)
meta2:set_string("arrivals_tbl", arrivals_tbl2)
end
meta2:set_string("dest_pos", "not configured")
telemosaic.set_status(pos2)
end
for k, v in pairs(arrivals_tbl) do
local ipos = minetest.string_to_pos(k)
local imeta = minetest.get_meta(ipos)
imeta:set_string("dest_pos", "not configured")
telemosaic.set_status(ipos)
end
end