split into modules / allow stand- and rightclick-teleport
This commit is contained in:
parent
5ff1dd655a
commit
1840efeb3e
46
crafts.lua
Normal file
46
crafts.lua
Normal file
@ -0,0 +1,46 @@
|
||||
|
||||
|
||||
minetest.register_craft({
|
||||
output = 'telemosaic:beacon_off',
|
||||
recipe = {
|
||||
{'default:diamond', 'doors:door_wood', 'default:diamond'},
|
||||
{'default:obsidian','default:obsidian','default:obsidian'}
|
||||
}
|
||||
})
|
||||
|
||||
minetest.register_craft({
|
||||
output = 'telemosaic:beacon_off_protected',
|
||||
type = 'shapeless',
|
||||
recipe = {"telemosaic:beacon_off", "default:steel_ingot"}
|
||||
})
|
||||
|
||||
minetest.register_craft({
|
||||
output = 'telemosaic:extender_one',
|
||||
recipe = {
|
||||
{'default:obsidian','doors:door_wood','default:obsidian'}
|
||||
}
|
||||
})
|
||||
minetest.register_craft({
|
||||
output = 'telemosaic:extender_two',
|
||||
recipe = {
|
||||
{'', 'group:telemosaic_extender_one',''},
|
||||
{'group:telemosaic_extender_one','default:obsidian','group:telemosaic_extender_one'},
|
||||
{'', 'group:telemosaic_extender_one',''}
|
||||
}
|
||||
})
|
||||
minetest.register_craft({
|
||||
output = 'telemosaic:extender_three',
|
||||
recipe = {
|
||||
{'', 'group:telemosaic_extender_two',''},
|
||||
{'group:telemosaic_extender_two','default:obsidian','group:telemosaic_extender_two'},
|
||||
{'', 'group:telemosaic_extender_two',''}
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
-- how to recycle a key
|
||||
minetest.register_craft({
|
||||
type = 'shapeless',
|
||||
recipe = {'telemosaic:key'},
|
||||
output = 'default:mese_crystal_fragment'
|
||||
})
|
524
init.lua
524
init.lua
@ -57,526 +57,8 @@ telemosaic = {
|
||||
|
||||
}
|
||||
|
||||
local M = telemosaic
|
||||
local C = M.config
|
||||
local modpath = minetest.get_modpath(minetest.get_current_modname())
|
||||
|
||||
local function hash_pos(pos)
|
||||
return math.floor(pos.x + 0.5) .. ':' ..
|
||||
math.floor(pos.y + 0.5) .. ':' ..
|
||||
math.floor(pos.z + 0.5)
|
||||
end
|
||||
local function unhash_pos(hash)
|
||||
local pos = {}
|
||||
local list = string.split(hash, ':')
|
||||
pos.x = tonumber(list[1])
|
||||
pos.y = tonumber(list[2])
|
||||
pos.z = tonumber(list[3])
|
||||
return pos
|
||||
end
|
||||
|
||||
local function count_extenders(pos)
|
||||
local extended = 0.0
|
||||
for z=-3,3 do
|
||||
for x=-3,3 do
|
||||
local node = minetest.get_node({ x=pos.x+x, y=pos.y, z=pos.z+z})
|
||||
local name = node.name
|
||||
-- trim color off the back
|
||||
name = string.gsub(name, '^(telemosaic:extender_%a+)_%a+', '%1')
|
||||
extended = extended + ( C.extender_ranges[name] or 0.0 )
|
||||
end
|
||||
end
|
||||
--print("Total extended: " .. extended)
|
||||
return extended
|
||||
end
|
||||
|
||||
-- returns true if the beacon is in an error state (protected or not)
|
||||
local function is_err_beacon(pos)
|
||||
local node = minetest.get_node(pos)
|
||||
if not node then
|
||||
-- no node or name
|
||||
return false
|
||||
end
|
||||
return node.name == "telemosaic:beacon_err" or node.name == "telemosaic:beacon_err_protected"
|
||||
end
|
||||
|
||||
-- swaps out the beacon with the new state suffix
|
||||
local function swap_beacon(pos, new_state_suffix)
|
||||
local node = minetest.get_node(pos)
|
||||
if not node then
|
||||
-- no node at pos
|
||||
return
|
||||
end
|
||||
|
||||
local name = node.name
|
||||
local new_node_name = "telemosaic:beacon" .. new_state_suffix
|
||||
|
||||
if string.match(name, "_protected") then
|
||||
-- protected beacon
|
||||
new_node_name = new_node_name .. "_protected"
|
||||
end
|
||||
|
||||
minetest.swap_node(pos, { name = new_node_name })
|
||||
end
|
||||
|
||||
local function beacon_rightclick(pos, node, player, itemstack, pointed_thing)
|
||||
local name = itemstack:get_name()
|
||||
--print("Clicked by a " ..name)
|
||||
if name == 'default:mese_crystal_fragment' and itemstack:get_count() == 1 then
|
||||
--print("Clicked by a single key")
|
||||
itemstack = ItemStack({
|
||||
name = "telemosaic:key",
|
||||
count = 1,
|
||||
wear = 0,
|
||||
metadata = hash_pos(pointed_thing.under),
|
||||
})
|
||||
elseif name == 'telemosaic:key' then
|
||||
local posstring = itemstack:get_metadata()
|
||||
local thispos = hash_pos(pointed_thing.under)
|
||||
--print("Key with metadata " .. posstring)
|
||||
if posstring ~= thispos and not minetest.is_protected(pointed_thing.under, player:get_player_name()) then
|
||||
local dest_pos = unhash_pos(posstring)
|
||||
local extended = count_extenders(pointed_thing.under)
|
||||
if vector.distance(dest_pos, pointed_thing.under) <= C.beacon_range + extended then
|
||||
swap_beacon(pointed_thing.under, "")
|
||||
else
|
||||
swap_beacon(pointed_thing.under, "_err")
|
||||
end
|
||||
|
||||
-- set the destination anyway, it just won't work as
|
||||
-- long as the beacon is in err state
|
||||
local meta = minetest.get_meta(pointed_thing.under)
|
||||
meta:set_string('telemosaic:dest', posstring)
|
||||
--print ("set to " .. meta:get_string('telemosaic:dest'))
|
||||
itemstack = ItemStack({
|
||||
name = "default:mese_crystal_fragment",
|
||||
count = 1, wear = 0,
|
||||
})
|
||||
end
|
||||
else
|
||||
-- teleport when right-clicked
|
||||
if C.right_click_teleport then
|
||||
local pl = M.players[player:get_player_name()]
|
||||
pl.right_clicked = true
|
||||
pl.clicked_pos = pointed_thing.under
|
||||
pl.allow_teleport = true
|
||||
|
||||
-- normal place-item thing
|
||||
elseif itemstack:get_definition().type == "node" then
|
||||
return core.item_place_node(itemstack, player, pointed_thing)
|
||||
end
|
||||
end
|
||||
return itemstack
|
||||
end
|
||||
|
||||
local function extender_place(placepos, placer, itemstack, pointed_thing)
|
||||
-- go over all possible *err* beacons, and update them
|
||||
for z=-3,3 do
|
||||
for x=-3,3 do
|
||||
local pos = { x=placepos.x+x, y=placepos.y, z=placepos.z+z }
|
||||
if is_err_beacon(pos) then
|
||||
-- candidate!
|
||||
local dest_hash = minetest.get_meta(pos):get_string('telemosaic:dest')
|
||||
|
||||
if dest_hash ~= nil and dest_hash ~= '' then
|
||||
local dest = unhash_pos(dest_hash)
|
||||
local extended = count_extenders(pos)
|
||||
local dist = vector.distance(pos, dest)
|
||||
|
||||
if dist <= C.beacon_range + extended then
|
||||
-- upgrade :-)
|
||||
swap_beacon(pos, "")
|
||||
|
||||
else
|
||||
local count = math.ceil(dist - (C.beacon_range + extended))
|
||||
minetest.chat_send_player(placer:get_player_name(), "You still need to add extensions for "..count.." nodes" )
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function extender_dig(digpos, oldnode, oldmetadata, digger)
|
||||
-- go over all possible *actual* beacons, and update them
|
||||
for z=-3,3 do
|
||||
for x=-3,3 do
|
||||
local pos = { x=digpos.x+x, y=digpos.y, z=digpos.z+z }
|
||||
local node = minetest.get_node(pos)
|
||||
if node ~= nil and node.name == 'telemosaic:beacon' then
|
||||
-- candidate!
|
||||
local dest_hash = minetest.get_meta(pos):get_string('telemosaic:dest')
|
||||
if dest_hash ~= nil and dest_hash ~= '' then
|
||||
local dest = unhash_pos(dest_hash)
|
||||
local extended = count_extenders(pos)
|
||||
local dist = vector.distance(pos, dest)
|
||||
|
||||
if dist > C.beacon_range + extended then
|
||||
-- downgrade :-(
|
||||
swap_beacon(pos, "_err")
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function check_teleport_dest(dest)
|
||||
-- check the destination node for beacons, and the two nodes
|
||||
-- above for "walkthrough"
|
||||
-- "ignore" is ok, we could not emerge in time then.
|
||||
local dest_bot = minetest.get_node({ x = dest.x, y = dest.y , z = dest.z })
|
||||
local dest_mid = minetest.get_node({ x = dest.x, y = dest.y+1, z = dest.z })
|
||||
local dest_top = minetest.get_node({ x = dest.x, y = dest.y+2, z = dest.z })
|
||||
--print ("Looking at " .. dest_bot.name .. ", " .. dest_mid.name .. ", " .. dest_top.name)
|
||||
local dest_ok = true
|
||||
if dest_bot.name ~= 'ignore' and not string.match(dest_bot.name, '^telemosaic:beacon') then
|
||||
dest_ok = false
|
||||
--print("Bottom is not beacon")
|
||||
end
|
||||
if dest_mid.name ~= 'ignore' and dest_mid.name ~= 'air' then
|
||||
local def = minetest.registered_nodes[dest_mid.name]
|
||||
if def and def.walkable then
|
||||
dest_ok = false
|
||||
--print("Mid is walkable")
|
||||
end
|
||||
end
|
||||
if dest_top.name ~= 'ignore' and dest_top.name ~= 'air' then
|
||||
local def = minetest.registered_nodes[dest_top.name]
|
||||
if def and def.walkable then
|
||||
dest_ok = false
|
||||
--print("Top is walkable")
|
||||
end
|
||||
end
|
||||
return dest_ok
|
||||
end
|
||||
|
||||
-- register protected and plain beacons with different suffixes, names and textures
|
||||
for _,is_protected in pairs({ true, false }) do
|
||||
|
||||
local node_name_suffix = ""
|
||||
local texture_overlay = ""
|
||||
local description_prefix = ""
|
||||
|
||||
if is_protected then
|
||||
node_name_suffix = "_protected"
|
||||
texture_overlay = "^telemosaic_beacon_protected_overlay.png"
|
||||
description_prefix = "Protected "
|
||||
end
|
||||
|
||||
minetest.register_node('telemosaic:beacon' .. node_name_suffix, {
|
||||
description = description_prefix .. 'Telemosaic beacon (on)',
|
||||
tiles = {
|
||||
'telemosaic_beacon_top.png' .. texture_overlay,
|
||||
'telemosaic_beacon_side.png',
|
||||
'telemosaic_beacon_side.png',
|
||||
'telemosaic_beacon_side.png',
|
||||
'telemosaic_beacon_side.png',
|
||||
'telemosaic_beacon_side.png',
|
||||
},
|
||||
paramtype = 'light',
|
||||
groups = { cracky = 2, not_in_creative_inventory = 1 },
|
||||
drop = 'telemosaic:beacon_off',
|
||||
on_rightclick = beacon_rightclick,
|
||||
})
|
||||
|
||||
minetest.register_node('telemosaic:beacon_err' .. node_name_suffix, {
|
||||
description = description_prefix .. 'Telemosaic beacon (err)',
|
||||
tiles = {
|
||||
'telemosaic_beacon_err.png' .. texture_overlay,
|
||||
'telemosaic_beacon_side.png',
|
||||
'telemosaic_beacon_side.png',
|
||||
'telemosaic_beacon_side.png',
|
||||
'telemosaic_beacon_side.png',
|
||||
'telemosaic_beacon_side.png',
|
||||
},
|
||||
paramtype = 'light',
|
||||
groups = { cracky = 2, not_in_creative_inventory = 1 },
|
||||
drop = 'telemosaic:beacon_off',
|
||||
on_rightclick = beacon_rightclick,
|
||||
})
|
||||
|
||||
minetest.register_node('telemosaic:beacon_off' .. node_name_suffix, {
|
||||
description = description_prefix .. 'Telemosaic beacon',
|
||||
tiles = {
|
||||
'telemosaic_beacon_off.png' .. texture_overlay,
|
||||
'telemosaic_beacon_side.png',
|
||||
'telemosaic_beacon_side.png',
|
||||
'telemosaic_beacon_side.png',
|
||||
'telemosaic_beacon_side.png',
|
||||
'telemosaic_beacon_side.png',
|
||||
},
|
||||
paramtype = 'light',
|
||||
groups = { cracky = 2 },
|
||||
on_rightclick = beacon_rightclick,
|
||||
})
|
||||
|
||||
end
|
||||
|
||||
|
||||
minetest.register_tool('telemosaic:key', {
|
||||
description = 'Telemosaic key',
|
||||
inventory_image = 'telemosaic_key.png',
|
||||
stack_max = 1,
|
||||
groups = { not_in_creative_inventory = 1 },
|
||||
})
|
||||
|
||||
-- extenders come in three strengths, and many colors
|
||||
|
||||
local strengths = {
|
||||
-- index starts at 1
|
||||
'one',
|
||||
'two',
|
||||
'three',
|
||||
}
|
||||
local colors = {
|
||||
-- TODO: localisation
|
||||
-- default: { name= 'grey', value= '#ffffff00'},
|
||||
{ name= 'white', value= '#ffffff80'},
|
||||
{ name= 'dark_grey', value= '#000000c0'},
|
||||
{ name= 'black', value= '#00000080'},
|
||||
{ name= 'violet', value= '#40008080'},
|
||||
{ name= 'blue', value= '#0000ff80'},
|
||||
{ name= 'cyan', value= '#00ffff80'},
|
||||
{ name= 'dark_green', value= '#00800080'},
|
||||
{ name= 'green', value= '#00ff0080'},
|
||||
{ name= 'yellow', value= '#ffff0080'},
|
||||
{ name= 'brown', value= '#80400080'},
|
||||
{ name= 'orange', value= '#ff800080'},
|
||||
{ name= 'red', value= '#ff000080'},
|
||||
{ name= 'magenta', value= '#ff00ff80'},
|
||||
{ name= 'pink', value= '#ff808080'},
|
||||
}
|
||||
|
||||
for num, strength in ipairs(strengths) do
|
||||
minetest.register_node(string.format('telemosaic:extender_%s', strength), {
|
||||
description = string.format('Telemosaic extender, tier %d', num),
|
||||
tiles = {
|
||||
string.format('telemosaic_extender_%s.png', strength)
|
||||
},
|
||||
paramtype = 'light',
|
||||
groups = { cracky = 2, [string.format('telemosaic_extender_%s', strength)] = 1 },
|
||||
after_place_node = extender_place,
|
||||
after_dig_node = extender_dig,
|
||||
})
|
||||
-- colored versions, not in creative inventory, if dyes available
|
||||
if minetest.get_modpath('dye') then
|
||||
for _,c in ipairs(colors) do
|
||||
minetest.register_node(string.format('telemosaic:extender_%s_%s', strength, c.name), {
|
||||
description = string.format('Telemosaic extender, tier %d (%s)', num, c.name),
|
||||
tiles = {
|
||||
string.format('telemosaic_extender_%s.png^[colorize:%s', strength, c.value),
|
||||
},
|
||||
paramtype = 'light',
|
||||
groups = { cracky = 2, [string.format('telemosaic_extender_%s', strength)] = 1, not_in_creative_inventory = 1 },
|
||||
after_place_node = extender_place,
|
||||
after_dig_node = extender_dig,
|
||||
})
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
minetest.register_craft({
|
||||
output = 'telemosaic:beacon_off',
|
||||
recipe = {
|
||||
{'default:diamond', 'doors:door_wood', 'default:diamond'},
|
||||
{'default:obsidian','default:obsidian','default:obsidian'}
|
||||
}
|
||||
})
|
||||
|
||||
minetest.register_craft({
|
||||
output = 'telemosaic:beacon_off_protected',
|
||||
type = 'shapeless',
|
||||
recipe = {"telemosaic:beacon_off", "default:steel_ingot"}
|
||||
})
|
||||
|
||||
minetest.register_craft({
|
||||
output = 'telemosaic:extender_one',
|
||||
recipe = {
|
||||
{'default:obsidian','doors:door_wood','default:obsidian'}
|
||||
}
|
||||
})
|
||||
minetest.register_craft({
|
||||
output = 'telemosaic:extender_two',
|
||||
recipe = {
|
||||
{'', 'group:telemosaic_extender_one',''},
|
||||
{'group:telemosaic_extender_one','default:obsidian','group:telemosaic_extender_one'},
|
||||
{'', 'group:telemosaic_extender_one',''}
|
||||
}
|
||||
})
|
||||
minetest.register_craft({
|
||||
output = 'telemosaic:extender_three',
|
||||
recipe = {
|
||||
{'', 'group:telemosaic_extender_two',''},
|
||||
{'group:telemosaic_extender_two','default:obsidian','group:telemosaic_extender_two'},
|
||||
{'', 'group:telemosaic_extender_two',''}
|
||||
}
|
||||
})
|
||||
|
||||
-- coloring recipes
|
||||
if minetest.get_modpath('dye') then
|
||||
for num, strength in ipairs(strengths) do
|
||||
-- uncolor
|
||||
minetest.register_craft({
|
||||
type = "shapeless",
|
||||
output = string.format('telemosaic:extender_%s', strength),
|
||||
recipe = { string.format('group:telemosaic_extender_%s', strength), 'dye:grey' },
|
||||
})
|
||||
-- color with dye
|
||||
for _,c in ipairs(colors) do
|
||||
minetest.register_craft({
|
||||
type = "shapeless",
|
||||
output = string.format('telemosaic:extender_%s_%s', strength, c.name),
|
||||
recipe = { string.format('group:telemosaic_extender_%s', strength), string.format('dye:%s', c.name) },
|
||||
})
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- how to recycle a key
|
||||
minetest.register_craft({
|
||||
type = 'shapeless',
|
||||
recipe = {'telemosaic:key'},
|
||||
output = 'default:mese_crystal_fragment'
|
||||
})
|
||||
|
||||
telemosaic.travel_allowed = function(player, src, dest)
|
||||
return true
|
||||
end
|
||||
|
||||
minetest.register_on_joinplayer(function(player)
|
||||
local name = player:get_player_name()
|
||||
if not M.players[name] then
|
||||
local pos = player:getpos()
|
||||
local pos_hash = hash_pos(pos)
|
||||
M.players[name] = {
|
||||
last_pos = pos_hash,
|
||||
time_in_pos = 0.0,
|
||||
allow_teleport = false, -- no teleport after join
|
||||
started_emerge = false, -- had not emerged destination yet
|
||||
}
|
||||
end
|
||||
end)
|
||||
|
||||
minetest.register_globalstep(function(dtime)
|
||||
for _,player in ipairs(minetest.get_connected_players()) do
|
||||
local name = player:get_player_name()
|
||||
local pl = M.players[name]
|
||||
local do_right_click_teleport = pl.right_clicked
|
||||
local pos = player:getpos()
|
||||
local pos_hash = hash_pos(pos)
|
||||
-- from now on, pos is slightly *under* the player
|
||||
pos.y = pos.y - 0.01
|
||||
local node = minetest.get_node(pos)
|
||||
--print ("At position " .. pos_hash .. " standing on a " .. node.name)
|
||||
if C.right_click_teleport and pl.clicked_pos ~= nil then
|
||||
pos = pl.clicked_pos
|
||||
node = minetest.get_node(pos)
|
||||
end
|
||||
if pos_hash ~= pl.last_pos then
|
||||
--print("Moved to " .. pos_hash)
|
||||
pl.last_pos = pos_hash
|
||||
pl.time_in_pos = 0.0
|
||||
pl.allow_teleport = true
|
||||
pl.started_emerge = false
|
||||
pl.right_clicked = false
|
||||
|
||||
elseif pl.allow_teleport and (node.name == 'telemosaic:beacon' or node.name == 'telemosaic:beacon_protected') then
|
||||
if node.name == 'telemosaic:beacon_protected' then
|
||||
-- check protection on protected telemosaic
|
||||
if minetest.is_protected(pos, name) then
|
||||
-- protected telemosaic, reset moved-flag and abort
|
||||
pl.allow_teleport = false
|
||||
pl.last_pos = pos_hash
|
||||
pl.right_clicked = false
|
||||
return
|
||||
end
|
||||
end
|
||||
pl.time_in_pos = pl.time_in_pos + dtime
|
||||
|
||||
if pl.time_in_pos > C.emerge_delay and not pl.started_emerge then
|
||||
pl.started_emerge = true
|
||||
if minetest.emerge_area then
|
||||
local dest_hash = minetest.get_meta(pos):get_string('telemosaic:dest')
|
||||
if dest_hash ~= nil and dest_hash ~= '' then
|
||||
local dest = unhash_pos(dest_hash)
|
||||
local pos_top = { x = dest.x, y = dest.y - 2, z = dest.z }
|
||||
-- try to emerge the area
|
||||
--print("Emerging " .. hash_pos(dest) .. " to " .. hash_pos(pos_top))
|
||||
minetest.emerge_area(dest, pos_top)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if (pl.time_in_pos > C.teleport_delay) and (do_right_click_teleport or not C.right_click_teleport) then
|
||||
|
||||
-- reset values now to prevent spamming
|
||||
pl.right_clicked = false
|
||||
pl.time_in_pos = 0.0
|
||||
|
||||
local dest_hash = minetest.get_meta(pos):get_string('telemosaic:dest')
|
||||
if dest_hash ~= nil and dest_hash ~= '' then
|
||||
local dest = unhash_pos(dest_hash)
|
||||
|
||||
-- test destination nodes
|
||||
local dest_ok = check_teleport_dest(dest)
|
||||
|
||||
--print("Ping to " .. dest_hash)
|
||||
local extended = count_extenders(pos)
|
||||
-- check for range before teleport (with leeway)
|
||||
local dist = vector.distance(pos, dest)
|
||||
--print("Dist :" .. (dist-0.5) .. " to " .. (C.beacon_range + extended))
|
||||
|
||||
if dest_ok and dist - 0.5 <= C.beacon_range + extended and telemosaic.travel_allowed(player, pos, dest) then
|
||||
dest.y = dest.y + 0.5
|
||||
minetest.sound_play( {name="telemosaic_set", gain=1}, {pos=pos, max_hear_distance=30})
|
||||
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",
|
||||
glow = 15,
|
||||
})
|
||||
player:setpos(dest)
|
||||
minetest.sound_play( {name="telemosaic_teleport", gain=1}, {pos=dest, max_hear_distance=30})
|
||||
minetest.add_particlespawner({
|
||||
amount = 100,
|
||||
time = 0.25,
|
||||
minpos = {x=dest.x, y=dest.y+0.3, z=dest.z},
|
||||
maxpos = {x=dest.x, y=dest.y+2, z=dest.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",
|
||||
glow = 15,
|
||||
})
|
||||
pl.last_pos = hash_pos(dest)
|
||||
else
|
||||
-- beacon is in error, one way or another.
|
||||
-- but don't swap it out - we won't get it back otherwise!
|
||||
end
|
||||
|
||||
if not C.right_click_teleport then -- right-click allows teleporting again without moving
|
||||
pl.allow_teleport = false -- need to move first, regardless
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end)
|
||||
dofile(modpath.."/teleport.lua")
|
||||
dofile(modpath.."/crafts.lua")
|
||||
|
||||
|
487
teleport.lua
Normal file
487
teleport.lua
Normal file
@ -0,0 +1,487 @@
|
||||
|
||||
|
||||
local M = telemosaic
|
||||
local C = M.config
|
||||
|
||||
local function hash_pos(pos)
|
||||
return math.floor(pos.x + 0.5) .. ':' ..
|
||||
math.floor(pos.y + 0.5) .. ':' ..
|
||||
math.floor(pos.z + 0.5)
|
||||
end
|
||||
local function unhash_pos(hash)
|
||||
local pos = {}
|
||||
local list = string.split(hash, ':')
|
||||
pos.x = tonumber(list[1])
|
||||
pos.y = tonumber(list[2])
|
||||
pos.z = tonumber(list[3])
|
||||
return pos
|
||||
end
|
||||
|
||||
local function count_extenders(pos)
|
||||
local extended = 0.0
|
||||
for z=-3,3 do
|
||||
for x=-3,3 do
|
||||
local node = minetest.get_node({ x=pos.x+x, y=pos.y, z=pos.z+z})
|
||||
local name = node.name
|
||||
-- trim color off the back
|
||||
name = string.gsub(name, '^(telemosaic:extender_%a+)_%a+', '%1')
|
||||
extended = extended + ( C.extender_ranges[name] or 0.0 )
|
||||
end
|
||||
end
|
||||
--print("Total extended: " .. extended)
|
||||
return extended
|
||||
end
|
||||
|
||||
-- returns true if the beacon is in an error state (protected or not)
|
||||
local function is_err_beacon(pos)
|
||||
local node = minetest.get_node(pos)
|
||||
if not node then
|
||||
-- no node or name
|
||||
return false
|
||||
end
|
||||
return node.name == "telemosaic:beacon_err" or node.name == "telemosaic:beacon_err_protected"
|
||||
end
|
||||
|
||||
-- swaps out the beacon with the new state suffix
|
||||
local function swap_beacon(pos, new_state_suffix)
|
||||
local node = minetest.get_node(pos)
|
||||
if not node then
|
||||
-- no node at pos
|
||||
return
|
||||
end
|
||||
|
||||
local name = node.name
|
||||
local new_node_name = "telemosaic:beacon" .. new_state_suffix
|
||||
|
||||
if string.match(name, "_protected") then
|
||||
-- protected beacon
|
||||
new_node_name = new_node_name .. "_protected"
|
||||
end
|
||||
|
||||
minetest.swap_node(pos, { name = new_node_name })
|
||||
end
|
||||
|
||||
|
||||
local function extender_place(placepos, placer, itemstack, pointed_thing)
|
||||
-- go over all possible *err* beacons, and update them
|
||||
for z=-3,3 do
|
||||
for x=-3,3 do
|
||||
local pos = { x=placepos.x+x, y=placepos.y, z=placepos.z+z }
|
||||
if is_err_beacon(pos) then
|
||||
-- candidate!
|
||||
local dest_hash = minetest.get_meta(pos):get_string('telemosaic:dest')
|
||||
|
||||
if dest_hash ~= nil and dest_hash ~= '' then
|
||||
local dest = unhash_pos(dest_hash)
|
||||
local extended = count_extenders(pos)
|
||||
local dist = vector.distance(pos, dest)
|
||||
|
||||
if dist <= C.beacon_range + extended then
|
||||
-- upgrade :-)
|
||||
swap_beacon(pos, "")
|
||||
|
||||
else
|
||||
local count = math.ceil(dist - (C.beacon_range + extended))
|
||||
minetest.chat_send_player(placer:get_player_name(), "You still need to add extensions for "..count.." nodes" )
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function extender_dig(digpos, oldnode, oldmetadata, digger)
|
||||
-- go over all possible *actual* beacons, and update them
|
||||
for z=-3,3 do
|
||||
for x=-3,3 do
|
||||
local pos = { x=digpos.x+x, y=digpos.y, z=digpos.z+z }
|
||||
local node = minetest.get_node(pos)
|
||||
if node ~= nil and node.name == 'telemosaic:beacon' then
|
||||
-- candidate!
|
||||
local dest_hash = minetest.get_meta(pos):get_string('telemosaic:dest')
|
||||
if dest_hash ~= nil and dest_hash ~= '' then
|
||||
local dest = unhash_pos(dest_hash)
|
||||
local extended = count_extenders(pos)
|
||||
local dist = vector.distance(pos, dest)
|
||||
|
||||
if dist > C.beacon_range + extended then
|
||||
-- downgrade :-(
|
||||
swap_beacon(pos, "_err")
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function check_teleport_dest(dest)
|
||||
-- check the destination node for beacons, and the two nodes
|
||||
-- above for "walkthrough"
|
||||
-- "ignore" is ok, we could not emerge in time then.
|
||||
local dest_bot = minetest.get_node({ x = dest.x, y = dest.y , z = dest.z })
|
||||
local dest_mid = minetest.get_node({ x = dest.x, y = dest.y+1, z = dest.z })
|
||||
local dest_top = minetest.get_node({ x = dest.x, y = dest.y+2, z = dest.z })
|
||||
--print ("Looking at " .. dest_bot.name .. ", " .. dest_mid.name .. ", " .. dest_top.name)
|
||||
local dest_ok = true
|
||||
if dest_bot.name ~= 'ignore' and not string.match(dest_bot.name, '^telemosaic:beacon') then
|
||||
dest_ok = false
|
||||
--print("Bottom is not beacon")
|
||||
end
|
||||
if dest_mid.name ~= 'ignore' and dest_mid.name ~= 'air' then
|
||||
local def = minetest.registered_nodes[dest_mid.name]
|
||||
if def and def.walkable then
|
||||
dest_ok = false
|
||||
--print("Mid is walkable")
|
||||
end
|
||||
end
|
||||
if dest_top.name ~= 'ignore' and dest_top.name ~= 'air' then
|
||||
local def = minetest.registered_nodes[dest_top.name]
|
||||
if def and def.walkable then
|
||||
dest_ok = false
|
||||
--print("Top is walkable")
|
||||
end
|
||||
end
|
||||
return dest_ok
|
||||
end
|
||||
|
||||
|
||||
-- teleports the player with given telemosaic pos
|
||||
function do_teleport(pos, player, pl)
|
||||
|
||||
if is_err_beacon(pos) then
|
||||
return
|
||||
end
|
||||
|
||||
local dest_hash = minetest.get_meta(pos):get_string('telemosaic:dest')
|
||||
if dest_hash ~= nil and dest_hash ~= '' then
|
||||
local dest = unhash_pos(dest_hash)
|
||||
|
||||
-- test destination nodes
|
||||
local dest_ok = check_teleport_dest(dest)
|
||||
|
||||
--print("Ping to " .. dest_hash)
|
||||
local extended = count_extenders(pos)
|
||||
-- check for range before teleport (with leeway)
|
||||
local dist = vector.distance(pos, dest)
|
||||
--print("Dist :" .. (dist-0.5) .. " to " .. (C.beacon_range + extended))
|
||||
|
||||
if dest_ok and dist - 0.5 <= C.beacon_range + extended and telemosaic.travel_allowed(player, pos, dest) then
|
||||
dest.y = dest.y + 0.5
|
||||
|
||||
minetest.sound_play( {name="telemosaic_set", gain=1}, {pos=pos, max_hear_distance=30})
|
||||
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",
|
||||
glow = 15,
|
||||
})
|
||||
player:setpos(dest)
|
||||
|
||||
minetest.sound_play( {name="telemosaic_teleport", gain=1}, {pos=dest, max_hear_distance=30})
|
||||
minetest.add_particlespawner({
|
||||
amount = 100,
|
||||
time = 0.25,
|
||||
minpos = {x=dest.x, y=dest.y+0.3, z=dest.z},
|
||||
maxpos = {x=dest.x, y=dest.y+2, z=dest.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",
|
||||
glow = 15,
|
||||
})
|
||||
pl.last_pos = hash_pos(dest)
|
||||
else
|
||||
-- beacon is in error, one way or another.
|
||||
-- but don't swap it out - we won't get it back otherwise!
|
||||
end
|
||||
pl.allow_teleport = false -- need to move first, regardless
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
local function beacon_rightclick(pos, node, player, itemstack, pointed_thing)
|
||||
local name = itemstack:get_name()
|
||||
--print("Clicked by a " ..name)
|
||||
if name == 'default:mese_crystal_fragment' and itemstack:get_count() == 1 then
|
||||
--print("Clicked by a single key")
|
||||
itemstack = ItemStack({
|
||||
name = "telemosaic:key",
|
||||
count = 1,
|
||||
wear = 0,
|
||||
metadata = hash_pos(pointed_thing.under),
|
||||
})
|
||||
elseif name == 'telemosaic:key' then
|
||||
local posstring = itemstack:get_metadata()
|
||||
local thispos = hash_pos(pointed_thing.under)
|
||||
--print("Key with metadata " .. posstring)
|
||||
if posstring ~= thispos and not minetest.is_protected(pointed_thing.under, player:get_player_name()) then
|
||||
local dest_pos = unhash_pos(posstring)
|
||||
local extended = count_extenders(pointed_thing.under)
|
||||
if vector.distance(dest_pos, pointed_thing.under) <= C.beacon_range + extended then
|
||||
swap_beacon(pointed_thing.under, "")
|
||||
else
|
||||
swap_beacon(pointed_thing.under, "_err")
|
||||
end
|
||||
|
||||
-- set the destination anyway, it just won't work as
|
||||
-- long as the beacon is in err state
|
||||
local meta = minetest.get_meta(pointed_thing.under)
|
||||
meta:set_string('telemosaic:dest', posstring)
|
||||
--print ("set to " .. meta:get_string('telemosaic:dest'))
|
||||
itemstack = ItemStack({
|
||||
name = "default:mese_crystal_fragment",
|
||||
count = 1, wear = 0,
|
||||
})
|
||||
end
|
||||
else
|
||||
-- teleport when right-clicked
|
||||
if C.right_click_teleport then
|
||||
local pl = M.players[player:get_player_name()]
|
||||
do_teleport(pos, player, pl)
|
||||
|
||||
-- normal place-item thing
|
||||
elseif itemstack:get_definition().type == "node" then
|
||||
return core.item_place_node(itemstack, player, pointed_thing)
|
||||
|
||||
end
|
||||
end
|
||||
return itemstack
|
||||
end
|
||||
|
||||
|
||||
-- register protected and plain beacons with different suffixes, names and textures
|
||||
for _,is_protected in pairs({ true, false }) do
|
||||
|
||||
local node_name_suffix = ""
|
||||
local texture_overlay = ""
|
||||
local description_prefix = ""
|
||||
|
||||
if is_protected then
|
||||
node_name_suffix = "_protected"
|
||||
texture_overlay = "^telemosaic_beacon_protected_overlay.png"
|
||||
description_prefix = "Protected "
|
||||
end
|
||||
|
||||
minetest.register_node('telemosaic:beacon' .. node_name_suffix, {
|
||||
description = description_prefix .. 'Telemosaic beacon (on)',
|
||||
tiles = {
|
||||
'telemosaic_beacon_top.png' .. texture_overlay,
|
||||
'telemosaic_beacon_side.png',
|
||||
'telemosaic_beacon_side.png',
|
||||
'telemosaic_beacon_side.png',
|
||||
'telemosaic_beacon_side.png',
|
||||
'telemosaic_beacon_side.png',
|
||||
},
|
||||
paramtype = 'light',
|
||||
groups = { cracky = 2, not_in_creative_inventory = 1 },
|
||||
drop = 'telemosaic:beacon_off',
|
||||
on_rightclick = beacon_rightclick,
|
||||
})
|
||||
|
||||
minetest.register_node('telemosaic:beacon_err' .. node_name_suffix, {
|
||||
description = description_prefix .. 'Telemosaic beacon (err)',
|
||||
tiles = {
|
||||
'telemosaic_beacon_err.png' .. texture_overlay,
|
||||
'telemosaic_beacon_side.png',
|
||||
'telemosaic_beacon_side.png',
|
||||
'telemosaic_beacon_side.png',
|
||||
'telemosaic_beacon_side.png',
|
||||
'telemosaic_beacon_side.png',
|
||||
},
|
||||
paramtype = 'light',
|
||||
groups = { cracky = 2, not_in_creative_inventory = 1 },
|
||||
drop = 'telemosaic:beacon_off',
|
||||
on_rightclick = beacon_rightclick,
|
||||
})
|
||||
|
||||
minetest.register_node('telemosaic:beacon_off' .. node_name_suffix, {
|
||||
description = description_prefix .. 'Telemosaic beacon',
|
||||
tiles = {
|
||||
'telemosaic_beacon_off.png' .. texture_overlay,
|
||||
'telemosaic_beacon_side.png',
|
||||
'telemosaic_beacon_side.png',
|
||||
'telemosaic_beacon_side.png',
|
||||
'telemosaic_beacon_side.png',
|
||||
'telemosaic_beacon_side.png',
|
||||
},
|
||||
paramtype = 'light',
|
||||
groups = { cracky = 2 },
|
||||
on_rightclick = beacon_rightclick,
|
||||
})
|
||||
|
||||
end
|
||||
|
||||
|
||||
minetest.register_tool('telemosaic:key', {
|
||||
description = 'Telemosaic key',
|
||||
inventory_image = 'telemosaic_key.png',
|
||||
stack_max = 1,
|
||||
groups = { not_in_creative_inventory = 1 },
|
||||
})
|
||||
|
||||
-- extenders come in three strengths, and many colors
|
||||
|
||||
local strengths = {
|
||||
-- index starts at 1
|
||||
'one',
|
||||
'two',
|
||||
'three',
|
||||
}
|
||||
local colors = {
|
||||
-- TODO: localisation
|
||||
-- default: { name= 'grey', value= '#ffffff00'},
|
||||
{ name= 'white', value= '#ffffff80'},
|
||||
{ name= 'dark_grey', value= '#000000c0'},
|
||||
{ name= 'black', value= '#00000080'},
|
||||
{ name= 'violet', value= '#40008080'},
|
||||
{ name= 'blue', value= '#0000ff80'},
|
||||
{ name= 'cyan', value= '#00ffff80'},
|
||||
{ name= 'dark_green', value= '#00800080'},
|
||||
{ name= 'green', value= '#00ff0080'},
|
||||
{ name= 'yellow', value= '#ffff0080'},
|
||||
{ name= 'brown', value= '#80400080'},
|
||||
{ name= 'orange', value= '#ff800080'},
|
||||
{ name= 'red', value= '#ff000080'},
|
||||
{ name= 'magenta', value= '#ff00ff80'},
|
||||
{ name= 'pink', value= '#ff808080'},
|
||||
}
|
||||
|
||||
for num, strength in ipairs(strengths) do
|
||||
minetest.register_node(string.format('telemosaic:extender_%s', strength), {
|
||||
description = string.format('Telemosaic extender, tier %d', num),
|
||||
tiles = {
|
||||
string.format('telemosaic_extender_%s.png', strength)
|
||||
},
|
||||
paramtype = 'light',
|
||||
groups = { cracky = 2, [string.format('telemosaic_extender_%s', strength)] = 1 },
|
||||
after_place_node = extender_place,
|
||||
after_dig_node = extender_dig,
|
||||
})
|
||||
-- colored versions, not in creative inventory, if dyes available
|
||||
if minetest.get_modpath('dye') then
|
||||
for _,c in ipairs(colors) do
|
||||
minetest.register_node(string.format('telemosaic:extender_%s_%s', strength, c.name), {
|
||||
description = string.format('Telemosaic extender, tier %d (%s)', num, c.name),
|
||||
tiles = {
|
||||
string.format('telemosaic_extender_%s.png^[colorize:%s', strength, c.value),
|
||||
},
|
||||
paramtype = 'light',
|
||||
groups = { cracky = 2, [string.format('telemosaic_extender_%s', strength)] = 1, not_in_creative_inventory = 1 },
|
||||
after_place_node = extender_place,
|
||||
after_dig_node = extender_dig,
|
||||
})
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
-- coloring recipes
|
||||
if minetest.get_modpath('dye') then
|
||||
for num, strength in ipairs(strengths) do
|
||||
-- uncolor
|
||||
minetest.register_craft({
|
||||
type = "shapeless",
|
||||
output = string.format('telemosaic:extender_%s', strength),
|
||||
recipe = { string.format('group:telemosaic_extender_%s', strength), 'dye:grey' },
|
||||
})
|
||||
-- color with dye
|
||||
for _,c in ipairs(colors) do
|
||||
minetest.register_craft({
|
||||
type = "shapeless",
|
||||
output = string.format('telemosaic:extender_%s_%s', strength, c.name),
|
||||
recipe = { string.format('group:telemosaic_extender_%s', strength), string.format('dye:%s', c.name) },
|
||||
})
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
telemosaic.travel_allowed = function(player, src, dest)
|
||||
return true
|
||||
end
|
||||
|
||||
minetest.register_on_joinplayer(function(player)
|
||||
local name = player:get_player_name()
|
||||
if not M.players[name] then
|
||||
local pos = player:getpos()
|
||||
local pos_hash = hash_pos(pos)
|
||||
M.players[name] = {
|
||||
last_pos = pos_hash,
|
||||
time_in_pos = 0.0,
|
||||
allow_teleport = false, -- no teleport after join
|
||||
started_emerge = false, -- had not emerged destination yet
|
||||
}
|
||||
end
|
||||
end)
|
||||
|
||||
|
||||
minetest.register_globalstep(function(dtime)
|
||||
for _,player in ipairs(minetest.get_connected_players()) do
|
||||
local name = player:get_player_name()
|
||||
local pl = M.players[name]
|
||||
|
||||
local pos = player:getpos()
|
||||
local pos_hash = hash_pos(pos)
|
||||
-- from now on, pos is slightly *under* the player
|
||||
pos.y = pos.y - 0.01
|
||||
local node = minetest.get_node(pos)
|
||||
|
||||
if pos_hash ~= pl.last_pos then
|
||||
--print("Moved to " .. pos_hash)
|
||||
pl.last_pos = pos_hash
|
||||
pl.time_in_pos = 0.0
|
||||
pl.allow_teleport = true
|
||||
pl.started_emerge = false
|
||||
|
||||
elseif pl.allow_teleport and (node.name == 'telemosaic:beacon' or node.name == 'telemosaic:beacon_protected') then
|
||||
if node.name == 'telemosaic:beacon_protected' then
|
||||
-- check protection on protected telemosaic
|
||||
if minetest.is_protected(pos, name) then
|
||||
-- protected telemosaic, reset moved-flag and abort
|
||||
pl.allow_teleport = false
|
||||
pl.last_pos = pos_hash
|
||||
return
|
||||
end
|
||||
end
|
||||
pl.time_in_pos = pl.time_in_pos + dtime
|
||||
|
||||
if pl.time_in_pos > C.emerge_delay and not pl.started_emerge then
|
||||
pl.started_emerge = true
|
||||
if minetest.emerge_area then
|
||||
local dest_hash = minetest.get_meta(pos):get_string('telemosaic:dest')
|
||||
if dest_hash ~= nil and dest_hash ~= '' then
|
||||
local dest = unhash_pos(dest_hash)
|
||||
local pos_top = { x = dest.x, y = dest.y - 2, z = dest.z }
|
||||
-- try to emerge the area
|
||||
--print("Emerging " .. hash_pos(dest) .. " to " .. hash_pos(pos_top))
|
||||
minetest.emerge_area(dest, pos_top)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if pl.time_in_pos > C.teleport_delay then
|
||||
-- reset values now to prevent spamming
|
||||
pl.time_in_pos = 0.0
|
||||
do_teleport(pos, player, pl)
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
Loading…
x
Reference in New Issue
Block a user