master
Wuzzy 2020-09-08 19:07:57 +02:00
parent 7c1202ba48
commit 9d9a85e0b3
1 changed files with 174 additions and 174 deletions

348
init.lua
View File

@ -4,158 +4,158 @@ teleports.lastplayername =""
teleports.filename = minetest.get_worldpath() .. "/teleports.txt" teleports.filename = minetest.get_worldpath() .. "/teleports.txt"
function teleports:save() function teleports:save()
local datastring = minetest.serialize(self.teleports) local datastring = minetest.serialize(self.teleports)
if not datastring then if not datastring then
return return
end end
local file, err = io.open(self.filename, "w") local file, err = io.open(self.filename, "w")
if err then if err then
return return
end end
file:write(datastring) file:write(datastring)
file:close() file:close()
end end
function teleports:load() function teleports:load()
local file, err = io.open(self.filename, "r") local file, err = io.open(self.filename, "r")
if err then if err then
self.teleports = {} self.teleports = {}
return return
end end
self.teleports = minetest.deserialize(file:read("*all")) self.teleports = minetest.deserialize(file:read("*all"))
if type(self.teleports) ~= "table" then if type(self.teleports) ~= "table" then
self.teleports = {} self.teleports = {}
end end
file:close() file:close()
end end
function teleports:find_nearby(pos, count) function teleports:find_nearby(pos, count)
local nearby = {} local nearby = {}
for i = #teleports.teleports, 1, -1 do for i = #teleports.teleports, 1, -1 do
local EachTeleport = teleports.teleports[i] local EachTeleport = teleports.teleports[i]
if not vector.equals(EachTeleport.pos, pos) and vector.distance(EachTeleport.pos, pos) < 260 then if not vector.equals(EachTeleport.pos, pos) and vector.distance(EachTeleport.pos, pos) < 260 then
table.insert(nearby, EachTeleport) table.insert(nearby, EachTeleport)
if #nearby>count then if #nearby>count then
break break
end end
end end
end end
return nearby return nearby
end end
function teleports.animate(pos, playername) function teleports.animate(pos, playername)
minetest.add_particlespawner({ minetest.add_particlespawner({
amount = 80, amount = 80,
time = 5, time = 5,
minpos = {x=pos.x-1, y=pos.y, z=pos.z-1}, 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}, maxpos = {x=pos.x+1, y=pos.y+3, z=pos.z+1},
minvel = {x=0, y=-1, z=0}, minvel = {x=0, y=-1, z=0},
maxvel = {x=0, y=1, z=0}, maxvel = {x=0, y=1, z=0},
minacc = {x=0, y=-1, z=0}, minacc = {x=0, y=-1, z=0},
maxacc = {x=0, y=1, z=0}, maxacc = {x=0, y=1, z=0},
minexptime = 1, minexptime = 1,
maxexptime = 1, maxexptime = 1,
minsize = 0.5, minsize = 0.5,
maxsize = 2, maxsize = 2,
collisiondetection = false, collisiondetection = false,
vertical = true, vertical = true,
texture = "default_diamond.png", texture = "default_diamond.png",
playername = playername, playername = playername,
}) })
minetest.add_particlespawner({ minetest.add_particlespawner({
amount = 20, amount = 20,
time = 5, time = 5,
minpos = {x=pos.x-1, y=pos.y, z=pos.z-1}, 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}, maxpos = {x=pos.x+1, y=pos.y+3, z=pos.z+1},
minvel = {x=0, y=-1, z=0}, minvel = {x=0, y=-1, z=0},
maxvel = {x=0, y=1, z=0}, maxvel = {x=0, y=1, z=0},
minacc = {x=0, y=-1, z=0}, minacc = {x=0, y=-1, z=0},
maxacc = {x=0, y=1, z=0}, maxacc = {x=0, y=1, z=0},
minexptime = 1, minexptime = 1,
maxexptime = 1, maxexptime = 1,
minsize = 0.5, minsize = 0.5,
maxsize = 2, maxsize = 2,
collisiondetection = false, collisiondetection = false,
vertical = true, vertical = true,
texture = "default_diamond.png", texture = "default_diamond.png",
}) })
end end
function teleports.teleportate(parameters) function teleports.teleportate(parameters)
local pos1,pos2,playername = parameters[1],parameters[2],parameters[3] local pos1,pos2,playername = parameters[1],parameters[2],parameters[3]
local player = minetest.get_player_by_name(playername) local player = minetest.get_player_by_name(playername)
if player and player:is_player() and playername~=teleports.lastplayername then if player and player:is_player() and playername~=teleports.lastplayername then
local pos = player:getpos() local pos = player:getpos()
if vector.distance(pos, {x=pos1.x,y=pos1.y+0.5,z=pos1.z}) < 0.52 then 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 if math.random(1, 100) > 5 then
teleports.lastplayername = playername teleports.lastplayername = playername
player:setpos({x=pos2.x,y=pos2.y+0.5,z=pos2.z}) player:setpos({x=pos2.x,y=pos2.y+0.5,z=pos2.z})
else else
player:setpos({x=pos2.x-5+math.random(1, 10),y=pos2.y+3,z=pos2.z-5+math.random(1, 10)}) 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 end
end end
end end
function teleports.do_teleporting(pos1, pos2, playername) function teleports.do_teleporting(pos1, pos2, playername)
teleports.animate(pos1, playername) teleports.animate(pos1, playername)
minetest.after(3.0, teleports.teleportate, {pos1, pos2, playername}) minetest.after(3.0, teleports.teleportate, {pos1, pos2, playername})
end end
teleports.set_formspec = function(pos) teleports.set_formspec = function(pos)
local meta = minetest.get_meta(pos) local meta = minetest.get_meta(pos)
local node = minetest.get_node(pos) local node = minetest.get_node(pos)
local buttons = ""; local buttons = "";
for i, EachTeleport in ipairs( teleports:find_nearby(pos, 5) ) do for i, EachTeleport in ipairs( teleports:find_nearby(pos, 5) ) do
if EachTeleport["name"] then if EachTeleport["name"] then
buttons = buttons.."button_exit[3,"..(i)..";4,0.5;tp"..i..";GO>"..minetest.formspec_escape(EachTeleport.name).."]"; buttons = buttons.."button_exit[3,"..(i)..";4,0.5;tp"..i..";GO>"..minetest.formspec_escape(EachTeleport.name).."]";
else else
buttons = buttons.."button_exit[3,"..(i)..";4,0.5;tp"..i..";GO>"..EachTeleport.pos.x..","..EachTeleport.pos.y..","..EachTeleport.pos.z.."]"; buttons = buttons.."button_exit[3,"..(i)..";4,0.5;tp"..i..";GO>"..EachTeleport.pos.x..","..EachTeleport.pos.y..","..EachTeleport.pos.z.."]";
end end
end end
meta:set_string("formspec", "size[8,10;]" meta:set_string("formspec", "size[8,10;]"
.."label[0,0;" .. 'Go to available teleports! Use mossy cobble as fuel!' .. "]" .."label[0,0;" .. 'Go to available teleports! Use mossy cobble as fuel!' .. "]"
.."list[current_name;price;0,1;1,1;]" .."list[current_name;price;0,1;1,1;]"
..buttons ..buttons
.."button_exit[1,5;2,0.5;cancel;Cancel]" .."button_exit[1,5;2,0.5;cancel;Cancel]"
.."list[current_player;main;0,6;8,4;]") .."list[current_player;main;0,6;8,4;]")
end end
teleports.on_receive_fields = function(pos, formname, fields, player) teleports.on_receive_fields = function(pos, formname, fields, player)
local meta = minetest.env:get_meta(pos); local meta = minetest.env:get_meta(pos);
local inv = meta:get_inventory(); local inv = meta:get_inventory();
local price = {name="default:mossycobble", count=1, wear=0, metadata=""} 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 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 if inv:contains_item("price", price) then
inv:remove_item("price", price); inv:remove_item("price", price);
teleports.lastplayername = "" teleports.lastplayername = ""
local available = teleports:find_nearby(pos, 5) local available = teleports:find_nearby(pos, 5)
if player ~= nil and player:is_player() then if player ~= nil and player:is_player() then
local playerpos = player:getpos() local playerpos = player:getpos()
if fields.tp1 and #available>0 then if fields.tp1 and #available>0 then
teleports.do_teleporting(playerpos, available[1].pos, player:get_player_name()) teleports.do_teleporting(playerpos, available[1].pos, player:get_player_name())
elseif fields.tp2 and #available>1 then elseif fields.tp2 and #available>1 then
teleports.do_teleporting(playerpos, available[2].pos, player:get_player_name()) teleports.do_teleporting(playerpos, available[2].pos, player:get_player_name())
elseif fields.tp3 and #available>2 then elseif fields.tp3 and #available>2 then
teleports.do_teleporting(playerpos, available[3].pos, player:get_player_name()) teleports.do_teleporting(playerpos, available[3].pos, player:get_player_name())
elseif fields.tp4 and #available>3 then elseif fields.tp4 and #available>3 then
teleports.do_teleporting(playerpos, available[4].pos, player:get_player_name()) teleports.do_teleporting(playerpos, available[4].pos, player:get_player_name())
elseif fields.tp5 and #available>4 then elseif fields.tp5 and #available>4 then
teleports.do_teleporting(playerpos, available[5].pos, player:get_player_name()) teleports.do_teleporting(playerpos, available[5].pos, player:get_player_name())
elseif fields.tp6 and #available>5 then elseif fields.tp6 and #available>5 then
teleports.do_teleporting(playerpos, available[6].pos, player:get_player_name()) teleports.do_teleporting(playerpos, available[6].pos, player:get_player_name())
end end
end end
teleports.set_formspec(pos) teleports.set_formspec(pos)
end end
end end
end end
teleports.allow_metadata_inventory_put = function(pos, listname, index, stack, player) teleports.allow_metadata_inventory_put = function(pos, listname, index, stack, player)
if listname=="price" and stack:get_name()=="default:mossycobble" then if listname=="price" and stack:get_name()=="default:mossycobble" then
return 99 return 99
else else
return 0 return 0
end end
end end
teleports.allow_metadata_inventory_take = function(pos, listname, index, stack, player) teleports.allow_metadata_inventory_take = function(pos, listname, index, stack, player)
return 0 return 0
@ -173,37 +173,37 @@ minetest.register_node("teleports:teleport", {
groups = {cracky=1, level=3}, groups = {cracky=1, level=3},
drop = 'default:diamond', drop = 'default:diamond',
sounds = default.node_sound_stone_defaults(), sounds = default.node_sound_stone_defaults(),
after_place_node = function(pos, placer) after_place_node = function(pos, placer)
if placer and placer:is_player() then if placer and placer:is_player() then
local meta = minetest.env:get_meta(pos) local meta = minetest.env:get_meta(pos)
local inv = meta:get_inventory() local inv = meta:get_inventory()
inv:set_size("price", 1) inv:set_size("price", 1)
local initialcharge = {name="default:mossycobble", count=30, wear=0, metadata=""} local initialcharge = {name="default:mossycobble", count=30, wear=0, metadata=""}
inv:add_item("price", initialcharge) inv:add_item("price", initialcharge)
teleports.set_formspec(pos) teleports.set_formspec(pos)
local sign_pos = minetest.find_node_near(pos, 1, "default:sign_wall_wood") local sign_pos = minetest.find_node_near(pos, 1, "default:sign_wall_wood")
if sign_pos then if sign_pos then
local sign_meta = minetest.env:get_meta(sign_pos) local sign_meta = minetest.env:get_meta(sign_pos)
local sign_text = sign_meta:get_string("text") local sign_text = sign_meta:get_string("text")
local secret_name = sign_text:sub(0, 16) local secret_name = sign_text:sub(0, 16)
table.insert(teleports.teleports, {pos=vector.round(pos), name=secret_name}) table.insert(teleports.teleports, {pos=vector.round(pos), name=secret_name})
else else
table.insert(teleports.teleports, {pos=vector.round(pos)}) table.insert(teleports.teleports, {pos=vector.round(pos)})
end end
teleports:save() teleports:save()
end end
end, end,
on_destruct = function(pos) on_destruct = function(pos)
for i, EachTeleport in ipairs(teleports.teleports) do for i, EachTeleport in ipairs(teleports.teleports) do
if vector.equals(EachTeleport.pos, pos) then if vector.equals(EachTeleport.pos, pos) then
table.remove(teleports.teleports, i) table.remove(teleports.teleports, i)
teleports:save() teleports:save()
end end
end end
end, end,
on_receive_fields = teleports.on_receive_fields, on_receive_fields = teleports.on_receive_fields,
allow_metadata_inventory_put = teleports.allow_metadata_inventory_put, allow_metadata_inventory_put = teleports.allow_metadata_inventory_put,
allow_metadata_inventory_take = teleports.allow_metadata_inventory_take, allow_metadata_inventory_take = teleports.allow_metadata_inventory_take,
}) })
@ -240,31 +240,31 @@ minetest.register_abm({
local objectsnear=minetest.get_objects_inside_radius({x=pos.x,y=pos.y+0.5,z=pos.z}, 0.52); local objectsnear=minetest.get_objects_inside_radius({x=pos.x,y=pos.y+0.5,z=pos.z}, 0.52);
if #objectsnear>0 then if #objectsnear>0 then
local player = objectsnear[1]; local player = objectsnear[1];
-- check only first two objekts then give up -- check only first two objekts then give up
if #objectsnear>1 and not player:is_player() then if #objectsnear>1 and not player:is_player() then
player = objectsnear[2]; player = objectsnear[2];
end end
if player:is_player() and player:get_player_name()~=teleports.lastplayername then if player:is_player() and player:get_player_name()~=teleports.lastplayername then
local positions = teleports:find_nearby(pos, 10) local positions = teleports:find_nearby(pos, 10)
if #positions>0 then if #positions>0 then
local key = math.random(1, #positions) local key = math.random(1, #positions)
local dir, dirmag; local dir, dirmag;
local view = player:get_look_dir(); local view = player:get_look_dir();
local dist, distmin; distmin = 99; local dist, distmin; distmin = 99;
for i=1,#positions do -- find teleport closest to where player is looking 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}; 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 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=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; 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); dist = math.sqrt(dir.x*dir.x+dir.y*dir.y+dir.z*dir.z);
if dist<distmin then distmin = dist; key = i end if dist<distmin then distmin = dist; key = i end
end end
local pos2 = positions[key].pos local pos2 = positions[key].pos
teleports.do_teleporting(pos, pos2, player:get_player_name()) teleports.do_teleporting(pos, pos2, player:get_player_name())
end end
else else
teleports.lastplayername = "" teleports.lastplayername = ""
end end
end end
end, end,