2020-09-08 10:11:47 -07:00
|
|
|
local S = minetest.get_translator("teleports")
|
|
|
|
local F = minetest.formspec_escape
|
|
|
|
|
2014-08-01 09:35:01 -07:00
|
|
|
teleports = {}
|
2014-10-19 08:03:02 -07:00
|
|
|
teleports.teleports = {}
|
|
|
|
teleports.lastplayername =""
|
|
|
|
teleports.filename = minetest.get_worldpath() .. "/teleports.txt"
|
|
|
|
|
2020-09-08 10:08:37 -07:00
|
|
|
local TELEPORT_MAX_DIST = 260
|
|
|
|
|
2014-10-19 08:03:02 -07:00
|
|
|
function teleports:save()
|
2020-09-08 10:07:57 -07:00
|
|
|
local datastring = minetest.serialize(self.teleports)
|
|
|
|
if not datastring then
|
|
|
|
return
|
|
|
|
end
|
|
|
|
local file, err = io.open(self.filename, "w")
|
|
|
|
if err then
|
|
|
|
return
|
|
|
|
end
|
|
|
|
file:write(datastring)
|
|
|
|
file:close()
|
2014-10-19 08:03:02 -07:00
|
|
|
end
|
|
|
|
function teleports:load()
|
2020-09-08 10:07:57 -07:00
|
|
|
local file, err = io.open(self.filename, "r")
|
|
|
|
if err then
|
|
|
|
self.teleports = {}
|
|
|
|
return
|
|
|
|
end
|
|
|
|
self.teleports = minetest.deserialize(file:read("*all"))
|
|
|
|
if type(self.teleports) ~= "table" then
|
|
|
|
self.teleports = {}
|
|
|
|
end
|
|
|
|
file:close()
|
2014-10-19 08:03:02 -07:00
|
|
|
end
|
|
|
|
function teleports:find_nearby(pos, count)
|
2020-09-08 10:07:57 -07:00
|
|
|
local nearby = {}
|
|
|
|
for i = #teleports.teleports, 1, -1 do
|
|
|
|
local EachTeleport = teleports.teleports[i]
|
2020-09-08 10:08:37 -07:00
|
|
|
if not vector.equals(EachTeleport.pos, pos) and vector.distance(EachTeleport.pos, pos) < TELEPORT_MAX_DIST then
|
2020-09-08 10:07:57 -07:00
|
|
|
table.insert(nearby, EachTeleport)
|
2020-09-08 10:21:16 -07:00
|
|
|
if #nearby>=count then
|
2020-09-08 10:07:57 -07:00
|
|
|
break
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
return nearby
|
2014-10-19 08:03:02 -07:00
|
|
|
end
|
2016-10-02 06:44:33 -07:00
|
|
|
function teleports.animate(pos, playername)
|
2020-09-08 10:07:57 -07:00
|
|
|
minetest.add_particlespawner({
|
|
|
|
amount = 80,
|
|
|
|
time = 5,
|
|
|
|
minpos = {x=pos.x-1, y=pos.y, z=pos.z-1},
|
|
|
|
maxpos = {x=pos.x+1, y=pos.y+3, z=pos.z+1},
|
|
|
|
minvel = {x=0, y=-1, z=0},
|
|
|
|
maxvel = {x=0, y=1, z=0},
|
|
|
|
minacc = {x=0, y=-1, z=0},
|
|
|
|
maxacc = {x=0, y=1, z=0},
|
|
|
|
minexptime = 1,
|
|
|
|
maxexptime = 1,
|
|
|
|
minsize = 0.5,
|
|
|
|
maxsize = 2,
|
|
|
|
collisiondetection = false,
|
|
|
|
vertical = true,
|
|
|
|
texture = "default_diamond.png",
|
|
|
|
playername = playername,
|
|
|
|
})
|
|
|
|
minetest.add_particlespawner({
|
|
|
|
amount = 20,
|
|
|
|
time = 5,
|
|
|
|
minpos = {x=pos.x-1, y=pos.y, z=pos.z-1},
|
|
|
|
maxpos = {x=pos.x+1, y=pos.y+3, z=pos.z+1},
|
|
|
|
minvel = {x=0, y=-1, z=0},
|
|
|
|
maxvel = {x=0, y=1, z=0},
|
|
|
|
minacc = {x=0, y=-1, z=0},
|
|
|
|
maxacc = {x=0, y=1, z=0},
|
|
|
|
minexptime = 1,
|
|
|
|
maxexptime = 1,
|
|
|
|
minsize = 0.5,
|
|
|
|
maxsize = 2,
|
|
|
|
collisiondetection = false,
|
|
|
|
vertical = true,
|
|
|
|
texture = "default_diamond.png",
|
|
|
|
})
|
2016-10-02 06:44:33 -07:00
|
|
|
end
|
|
|
|
function teleports.teleportate(parameters)
|
2020-09-08 10:07:57 -07:00
|
|
|
local pos1,pos2,playername = parameters[1],parameters[2],parameters[3]
|
2016-10-02 06:44:33 -07:00
|
|
|
|
2020-09-08 10:07:57 -07:00
|
|
|
local player = minetest.get_player_by_name(playername)
|
|
|
|
if player and player:is_player() and playername~=teleports.lastplayername then
|
|
|
|
local pos = player:getpos()
|
|
|
|
if vector.distance(pos, {x=pos1.x,y=pos1.y+0.5,z=pos1.z}) < 0.52 then
|
|
|
|
if math.random(1, 100) > 5 then
|
|
|
|
teleports.lastplayername = playername
|
|
|
|
player:setpos({x=pos2.x,y=pos2.y+0.5,z=pos2.z})
|
|
|
|
else
|
|
|
|
player:setpos({x=pos2.x-5+math.random(1, 10),y=pos2.y+3,z=pos2.z-5+math.random(1, 10)})
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
2016-10-02 06:44:33 -07:00
|
|
|
end
|
|
|
|
function teleports.do_teleporting(pos1, pos2, playername)
|
2020-09-08 10:07:57 -07:00
|
|
|
teleports.animate(pos1, playername)
|
|
|
|
minetest.after(3.0, teleports.teleportate, {pos1, pos2, playername})
|
2016-10-02 06:44:33 -07:00
|
|
|
end
|
2014-10-19 08:03:02 -07:00
|
|
|
teleports.set_formspec = function(pos)
|
|
|
|
local meta = minetest.get_meta(pos)
|
|
|
|
local node = minetest.get_node(pos)
|
2016-10-02 00:36:45 -07:00
|
|
|
|
2020-09-08 10:07:57 -07:00
|
|
|
local buttons = "";
|
2020-09-08 10:38:04 -07:00
|
|
|
local x = 1
|
|
|
|
local y = 1
|
|
|
|
for i, EachTeleport in ipairs( teleports:find_nearby(pos, 6) ) do
|
|
|
|
if i == 4 then
|
|
|
|
x = x + 3.5
|
|
|
|
y = 1
|
|
|
|
end
|
2020-09-08 10:07:57 -07:00
|
|
|
if EachTeleport["name"] then
|
2020-09-08 10:38:04 -07:00
|
|
|
buttons = buttons.."button_exit["..x..","..y..";3.5,0.5;tp"..i..";"..F(S("GO>@1",EachTeleport.name)).."]";
|
2020-09-08 10:07:57 -07:00
|
|
|
else
|
2020-09-08 10:38:04 -07:00
|
|
|
buttons = buttons.."button_exit["..x..","..y..";3.5,0.5;tp"..i..";"..F(S("GO>@1,@2,@3",EachTeleport.pos.x,EachTeleport.pos.y,EachTeleport.pos.z)).."]";
|
2020-09-08 10:07:57 -07:00
|
|
|
end
|
2020-09-08 10:38:04 -07:00
|
|
|
y = y + 1
|
2020-09-08 10:07:57 -07:00
|
|
|
end
|
2016-10-02 00:36:45 -07:00
|
|
|
|
2020-09-08 10:38:04 -07:00
|
|
|
meta:set_string("formspec", "size[8,9;]"
|
2020-09-08 10:11:47 -07:00
|
|
|
.."label[0,0;" .. F(S("Go to available teleports! Use mossy cobblestone as fuel!")) .. "]"
|
2020-09-08 10:07:57 -07:00
|
|
|
.."list[current_name;price;0,1;1,1;]"
|
|
|
|
..buttons
|
2020-09-08 10:38:04 -07:00
|
|
|
.."button_exit[1,4;2,0.5;cancel;"..F(S("Cancel")).."]"
|
|
|
|
.."list[current_player;main;0,5;8,4;]")
|
2014-10-19 08:03:02 -07:00
|
|
|
end
|
|
|
|
teleports.on_receive_fields = function(pos, formname, fields, player)
|
2020-09-08 10:07:57 -07:00
|
|
|
local meta = minetest.env:get_meta(pos);
|
2014-10-19 08:03:02 -07:00
|
|
|
local inv = meta:get_inventory();
|
2020-09-08 10:07:57 -07:00
|
|
|
local price = {name="default:mossycobble", count=1, wear=0, metadata=""}
|
|
|
|
if fields.tp1 or fields.tp2 or fields.tp3 or fields.tp4 or fields.tp5 or fields.tp6 then
|
|
|
|
if inv:contains_item("price", price) then
|
|
|
|
inv:remove_item("price", price);
|
|
|
|
teleports.lastplayername = ""
|
2020-09-08 10:38:04 -07:00
|
|
|
local available = teleports:find_nearby(pos, 6)
|
2020-09-08 10:07:57 -07:00
|
|
|
if player ~= nil and player:is_player() then
|
|
|
|
local playerpos = player:getpos()
|
|
|
|
if fields.tp1 and #available>0 then
|
|
|
|
teleports.do_teleporting(playerpos, available[1].pos, player:get_player_name())
|
|
|
|
elseif fields.tp2 and #available>1 then
|
|
|
|
teleports.do_teleporting(playerpos, available[2].pos, player:get_player_name())
|
|
|
|
elseif fields.tp3 and #available>2 then
|
|
|
|
teleports.do_teleporting(playerpos, available[3].pos, player:get_player_name())
|
|
|
|
elseif fields.tp4 and #available>3 then
|
|
|
|
teleports.do_teleporting(playerpos, available[4].pos, player:get_player_name())
|
|
|
|
elseif fields.tp5 and #available>4 then
|
|
|
|
teleports.do_teleporting(playerpos, available[5].pos, player:get_player_name())
|
|
|
|
elseif fields.tp6 and #available>5 then
|
|
|
|
teleports.do_teleporting(playerpos, available[6].pos, player:get_player_name())
|
|
|
|
end
|
|
|
|
end
|
2016-10-02 00:36:45 -07:00
|
|
|
|
2020-09-08 10:07:57 -07:00
|
|
|
teleports.set_formspec(pos)
|
|
|
|
end
|
|
|
|
end
|
2014-10-19 08:03:02 -07:00
|
|
|
end
|
|
|
|
teleports.allow_metadata_inventory_put = function(pos, listname, index, stack, player)
|
2020-09-08 10:07:57 -07:00
|
|
|
if listname=="price" and stack:get_name()=="default:mossycobble" then
|
|
|
|
return 99
|
|
|
|
else
|
|
|
|
return 0
|
|
|
|
end
|
2014-10-19 08:03:02 -07:00
|
|
|
end
|
|
|
|
teleports.allow_metadata_inventory_take = function(pos, listname, index, stack, player)
|
|
|
|
return 0
|
|
|
|
end
|
|
|
|
|
|
|
|
teleports:load()
|
|
|
|
|
2014-08-01 09:35:01 -07:00
|
|
|
|
|
|
|
minetest.register_node("teleports:teleport", {
|
2020-09-08 10:11:47 -07:00
|
|
|
description = S("Teleport"),
|
2014-08-01 09:35:01 -07:00
|
|
|
drawtype = "glasslike",
|
|
|
|
tiles = {"teleports_teleport_top.png"},
|
|
|
|
is_ground_content = false,
|
2020-09-08 10:31:46 -07:00
|
|
|
light_source = minetest.LIGHT_MAX,
|
2014-08-01 09:35:01 -07:00
|
|
|
groups = {cracky=1, level=3},
|
|
|
|
drop = 'default:diamond',
|
|
|
|
sounds = default.node_sound_stone_defaults(),
|
2020-09-08 10:07:57 -07:00
|
|
|
after_place_node = function(pos, placer)
|
|
|
|
if placer and placer:is_player() then
|
|
|
|
local meta = minetest.env:get_meta(pos)
|
|
|
|
local inv = meta:get_inventory()
|
|
|
|
inv:set_size("price", 1)
|
|
|
|
local initialcharge = {name="default:mossycobble", count=30, wear=0, metadata=""}
|
|
|
|
inv:add_item("price", initialcharge)
|
|
|
|
teleports.set_formspec(pos)
|
2020-09-08 10:30:50 -07:00
|
|
|
local sign_pos = minetest.find_node_near(pos, 1, {"default:sign_wall_wood", "default:sign_wall_steel"})
|
2020-09-08 10:07:57 -07:00
|
|
|
if sign_pos then
|
|
|
|
local sign_meta = minetest.env:get_meta(sign_pos)
|
|
|
|
local sign_text = sign_meta:get_string("text")
|
|
|
|
local secret_name = sign_text:sub(0, 16)
|
|
|
|
table.insert(teleports.teleports, {pos=vector.round(pos), name=secret_name})
|
|
|
|
else
|
|
|
|
table.insert(teleports.teleports, {pos=vector.round(pos)})
|
|
|
|
end
|
|
|
|
teleports:save()
|
|
|
|
end
|
|
|
|
end,
|
|
|
|
on_destruct = function(pos)
|
|
|
|
for i, EachTeleport in ipairs(teleports.teleports) do
|
|
|
|
if vector.equals(EachTeleport.pos, pos) then
|
|
|
|
table.remove(teleports.teleports, i)
|
|
|
|
teleports:save()
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end,
|
|
|
|
on_receive_fields = teleports.on_receive_fields,
|
|
|
|
allow_metadata_inventory_put = teleports.allow_metadata_inventory_put,
|
|
|
|
allow_metadata_inventory_take = teleports.allow_metadata_inventory_take,
|
2014-08-01 09:35:01 -07:00
|
|
|
})
|
2014-10-19 08:03:02 -07:00
|
|
|
|
|
|
|
|
2020-09-08 10:07:02 -07:00
|
|
|
minetest.override_item("default:diamondblock", {
|
2014-08-01 09:35:01 -07:00
|
|
|
on_place = function(itemstack, placer, pointed_thing)
|
|
|
|
local stack = ItemStack("default:diamondblock")
|
|
|
|
local pos = pointed_thing.above
|
|
|
|
if
|
|
|
|
minetest.get_node({x=pos.x+1,y=pos.y,z=pos.z}).name=="default:diamondblock" and
|
|
|
|
minetest.get_node({x=pos.x+1,y=pos.y,z=pos.z+1}).name=="default:diamondblock" and
|
|
|
|
minetest.get_node({x=pos.x+1,y=pos.y,z=pos.z-1}).name=="default:diamondblock" and
|
|
|
|
minetest.get_node({x=pos.x-1,y=pos.y,z=pos.z}).name=="default:diamondblock" and
|
|
|
|
minetest.get_node({x=pos.x-1,y=pos.y,z=pos.z+1}).name=="default:diamondblock" and
|
|
|
|
minetest.get_node({x=pos.x-1,y=pos.y,z=pos.z-1}).name=="default:diamondblock" and
|
|
|
|
minetest.get_node({x=pos.x,y=pos.y,z=pos.z+1}).name=="default:diamondblock" and
|
|
|
|
minetest.get_node({x=pos.x,y=pos.y,z=pos.z-1}).name=="default:diamondblock"
|
|
|
|
then
|
|
|
|
stack = ItemStack("teleports:teleport")
|
|
|
|
end
|
|
|
|
local ret = minetest.item_place(stack, placer, pointed_thing)
|
|
|
|
if ret==nil then
|
|
|
|
return itemstack
|
|
|
|
else
|
|
|
|
return ItemStack("default:diamondblock "..itemstack:get_count()-(1-ret:get_count()))
|
|
|
|
end
|
|
|
|
end,
|
|
|
|
})
|
|
|
|
|
|
|
|
minetest.register_abm({
|
|
|
|
nodenames = {"teleports:teleport"},
|
2018-10-28 12:09:52 -07:00
|
|
|
interval = 3,
|
2014-08-01 09:35:01 -07:00
|
|
|
chance = 1,
|
|
|
|
action = function(pos)
|
2014-10-19 08:03:02 -07:00
|
|
|
local objectsnear=minetest.get_objects_inside_radius({x=pos.x,y=pos.y+0.5,z=pos.z}, 0.52);
|
2014-08-01 09:35:01 -07:00
|
|
|
if #objectsnear>0 then
|
2014-10-19 08:03:02 -07:00
|
|
|
local player = objectsnear[1];
|
2020-09-08 10:07:57 -07:00
|
|
|
-- check only first two objekts then give up
|
|
|
|
if #objectsnear>1 and not player:is_player() then
|
|
|
|
player = objectsnear[2];
|
|
|
|
end
|
2014-10-19 08:03:02 -07:00
|
|
|
if player:is_player() and player:get_player_name()~=teleports.lastplayername then
|
2020-09-08 10:38:04 -07:00
|
|
|
local positions = teleports:find_nearby(pos, 11)
|
2014-10-19 08:03:02 -07:00
|
|
|
if #positions>0 then
|
2014-08-01 09:35:01 -07:00
|
|
|
local key = math.random(1, #positions)
|
2020-09-08 10:07:57 -07:00
|
|
|
local dir, dirmag;
|
|
|
|
local view = player:get_look_dir();
|
|
|
|
local dist, distmin; distmin = 99;
|
|
|
|
for i=1,#positions do -- find teleport closest to where player is looking
|
|
|
|
dir = {x=positions[i].pos.x-pos.x,y=positions[i].pos.y-pos.y,z=positions[i].pos.z-pos.z};
|
|
|
|
dirmag = math.sqrt(dir.x*dir.x+dir.y*dir.y+dir.z*dir.z); if dirmag == 0 then dirmag = 1 end
|
|
|
|
dir.x=dir.x/dirmag;dir.y=dir.y/dirmag;dir.z=dir.z/dirmag;
|
|
|
|
dir.x = view.x-dir.x;dir.y = view.y-dir.y;dir.z = view.z-dir.z;
|
|
|
|
dist = math.sqrt(dir.x*dir.x+dir.y*dir.y+dir.z*dir.z);
|
|
|
|
if dist<distmin then distmin = dist; key = i end
|
|
|
|
end
|
2016-10-02 06:44:33 -07:00
|
|
|
|
2020-09-08 10:07:57 -07:00
|
|
|
local pos2 = positions[key].pos
|
|
|
|
teleports.do_teleporting(pos, pos2, player:get_player_name())
|
|
|
|
end
|
|
|
|
else
|
|
|
|
teleports.lastplayername = ""
|
2014-08-01 09:35:01 -07:00
|
|
|
end
|
|
|
|
end
|
|
|
|
end,
|
|
|
|
})
|