123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224 |
- if not minetest.global_exists("jaunt") then jaunt = {} end
- jaunt.modpath = minetest.get_modpath("jaunt")
- -- Localize for performance.
- local vector_distance = vector.distance
- local vector_round = vector.round
- -- private: assemble a formspec string
- function jaunt.get_formspec(player)
- local formspec = "size[4.5,5.5]" ..
- default.gui_bg ..
- default.gui_bg_img ..
- default.gui_slots
- formspec = formspec ..
- "item_image[0,0;1,1;passport:passport_adv]" ..
- "label[1,0;Key: Teleport to player beacon.]" ..
- "label[1,0.4;Requires teleport for anchor.]" ..
- "field[0.3,1.3;2.9,1;player;;]" ..
- "button[3.0,1.0;1.5,1;go;Jaunt]" ..
- "field_close_on_enter[player;true]" ..
- "button[1.25,2.0;2.25,1;cancel;Abort]" ..
- "label[0,3;Jaunt range is influenced by the status\nof the target's beacon. Marked players can\nbe found from farther.]" ..
- "item_image[1.25,4.5;1,1;command_tokens:mark_player]" ..
- "item_image[2.25,4.5;1,1;player_labels:show]"
- return formspec
- end
- -- api: show formspec to player
- function jaunt.show_formspec(player)
- local formspec = jaunt.get_formspec(player)
- minetest.show_formspec(player, "jaunt:fs", formspec)
- end
- -- Find nearby teleport, and return its range.
- function jaunt.valid_teleport(pos)
- local tar = minetest.find_node_near(pos, 2, "teleports:teleport", true)
- if tar then
- -- Range is halved because when we're jaunting, there is no teleport at the
- -- other end to receive us! Also, this means that when using a nyan TP, the
- -- range is more-or-less the same as the original, hard-coded jaunt range.
- local range = teleports.calculate_range(tar)
- return true, (range * 0.5)
- end
- end
- jaunt.on_receive_fields = function(player, formname, fields)
- if formname ~= "jaunt:fs" then return end
- local pname = player:get_player_name()
- -- security check to make sure player can use this feature
- if not passport.player_has_key(pname) then
- return true
- end
- if not survivalist.player_beat_cave_challenge(pname) then
- return true
- end
- -- Jaunt ability is revoked for cheaters.
- if sheriff.is_cheater(pname) then
- return true
- end
- if fields.cancel then
- passport.show_formspec(pname)
- return true
- end
- if fields.quit then
- return true
- end
- local uspos = vector_round(player:get_pos())
- if fields.key_enter_field == "player" or fields.go then
- local success, tp_range = jaunt.valid_teleport(uspos)
- if success then -- Teleport was found.
- local target = rename.grn((fields.player or ""):trim())
- if target ~= pname then
- local other = minetest.get_player_by_name(target)
- if other and other:is_player() and not cloaking.is_cloaked(target) then
- local marked = command_tokens.mark.player_marked(target)
- local beacon = player_labels.query_nametag_onoff(target)
- -- a player can be located if either they're marked or their beacon (nametag) is activated
- if marked or beacon then
- if passport.player_has_key(target) then
- -- if a player is marked, but their beacon is off, then the range at which
- -- they can be detected is halved
- local range = tp_range
- if not marked and not beacon then
- -- Not marked, nametag off.
- range = range * 0.25
- elseif marked and not beacon then
- -- Nametag off, but marked.
- range = range * 0.5
- elseif marked and beacon then
- -- Nametag on and marked.
- range = range * 1.5
- end
- local tarpos = other:get_pos()
- tarpos.y = tarpos.y + 1
- tarpos = vector_round(tarpos)
- local total_dist = vector_distance(tarpos, uspos)
- -- Take 1 second per 100 meters traveled.
- local spinup_time = math.floor(total_dist / 100)
- -- Randomize target position a bit.
- tarpos.x = tarpos.x + math.random(-1, 1)
- tarpos.z = tarpos.z + math.random(-1, 1)
- -- Make sure it's air.
- local finpos = minetest.find_node_near(tarpos, 2, "air", true)
- -- Make sure target isn't standing in/on something that disallows teleport.
- if true then
- local nodename = sky.get_last_walked_node(target)
- local ndef = minetest.registered_nodes[nodename]
- if ndef and ndef.disallow_teleport then
- finpos = nil
- end
- nodename = sky.get_last_walked_nodeabove(target)
- ndef = minetest.registered_nodes[nodename]
- if ndef and ndef.disallow_teleport then
- finpos = nil
- end
- end
- if finpos and rc.current_realm_at_pos(finpos) == rc.current_realm_at_pos(uspos) then
- if total_dist < range then
- -- Alert player that someone's coming to them.
- local RED = core.get_color_escape_sequence("#ff0000")
- minetest.chat_send_player(target,
- RED .. "# Server: Alert! Incoming jaunt from <" ..
- rename.gpn(pname) .. ">.")
- chat_core.alert_player_sound(target)
- -- Teleport player to chosen location.
- preload_tp.execute({
- player_name = pname,
- target_position = finpos,
- send_blocks = true,
- particle_effects = true,
- spinup_time = spinup_time,
- -- Pre-teleport callback.
- pre_teleport_callback = function()
- -- Abort teleport if player logged off.
- if not minetest.get_player_by_name(target) then
- minetest.chat_send_player(pname, "# Server: Lost link to target beacon.")
- return true -- Abort transport.
- end
- -- Abort teleport if target player cloaked themselves.
- if cloaking.is_cloaked(target) then
- minetest.chat_send_player(pname, "# Server: Lost link to target beacon.")
- return true -- Abort transport.
- end
- end,
- -- Post-teleport callback.
- post_teleport_callback = function()
- portal_sickness.on_use_portal(pname)
- end,
- })
- -- don't reshow the formspec
- minetest.close_formspec(pname, "jaunt:fs")
- return true
- else
- minetest.chat_send_player(pname, "# Server: Target Key's signal origin is too weak to accurately triangulate!")
- end
- else
- minetest.chat_send_player(pname, "# Server: Could not detect evidence of a Key's beacon signal.")
- end
- else
- minetest.chat_send_player(pname, "# Server: Could not detect evidence of a Key's beacon signal.")
- end
- else
- minetest.chat_send_player(pname, "# Server: Could not detect evidence of a Key's beacon signal.")
- end
- else
- minetest.chat_send_player(pname, "# Server: Could not detect evidence of a Key's beacon signal.")
- end
- else
- minetest.chat_send_player(pname, "# Server: Cleverly refusing to scan for your own Key's beacon signal.")
- end
- else
- minetest.chat_send_player(pname, "# Server: Key requires access to proximate teleport to deploy this function.")
- end
- end
- jaunt.show_formspec(pname)
- return true
- end
- if not jaunt.registered then
- minetest.register_on_player_receive_fields(function(...)
- return jaunt.on_receive_fields(...)
- end)
- local c = "jaunt:core"
- local f = jaunt.modpath .. "/init.lua"
- reload.register_file(c, f, false)
- jaunt.registered = true
- end
|