Compare commits

22 Commits

Author SHA1 Message Date
01ad0c80b3 Delete depends.txt and description.txt and update mod.conf (#7)
Co-authored-by: sys4 <bricassa@sys4.fr>
2022-03-06 19:40:17 +01:00
0a8f1683bc Replace deprecated methods (#6)
Co-authored-by: sys4 <bricassa@sys4.fr>
2021-04-09 20:24:03 +02:00
b2d71bf105 Fix errors under 5.x and allow selecting warps from a dropdown (#5)
- Loading would previously fail if there was both no data in mod_storage "warps" and no warps.txt
- A wrong variable used while adding the warp queue was causing crashes when attempting to warp
- Don't even attempt to teleport to a warp spot that doesn't exit
- Allow selecting warps from a dropdown for ease of use, but still allow text input as warps might be created later than the warp crystals are created (negotiable, invalid input could be dropped and only the combobox allowed if others object).
2021-02-16 22:07:09 +01:00
81c3bd5bd9 Remove debug info. 2019-02-02 22:15:26 -08:00
70fedaa536 Update docs. 2019-02-02 21:19:08 -08:00
0a6451608d Set the node to non-diggable, to prevent accidental digging by admin. 2019-02-02 21:13:19 -08:00
c8e4942e41 Convert warps to mod_storage. 2019-02-02 21:11:53 -08:00
b7fd67c431 Support send_mapblock when we can. 2019-02-02 20:47:23 -08:00
37315e72c9 Remove hard dependency on default. 2019-02-02 20:44:37 -08:00
5c24fff8b5 Modified whoosh sound. (#2) 2017-10-16 16:09:01 -07:00
493e23d3a8 Use fixed horizontal/vertical functions. (#3)
Replaces deprecates yaw/pitch functions.
2017-10-03 09:05:12 -07:00
6125489914 Fix license copypasta. 2017-09-01 18:45:55 -07:00
928c997e0b Tidy up code (#1)
- Break too long lines
- Use vector helper functions
- Round warp positions (less data to save)
- Disallow from setting warp ""
2016-06-27 13:09:27 -07:00
74e68db79c Attempt to emerge/mapgen areas before teleporting to them.
The client will still have to actually load the mapblocks, but the
server should safely teleport a player to the location, even if
it wasn't even generated.
2016-04-06 11:43:27 -07:00
979ba1c934 Change licenses slightly, more permissive. 2016-04-06 11:42:46 -07:00
e83b17a0de Adding screenshot.png for the in-game mod manager. 2016-01-30 15:56:45 -08:00
32c4680329 Add mod.conf 2016-01-04 14:59:04 -08:00
ded6fd1195 Allow admins to travel without waiting when using the /warp cmd. 2016-01-03 23:18:23 -08:00
1053e592df Fix sound level for woosh/plop.
positional sounds need to be mono, otherwise they're
player loud at all distances, which is not what is
intended.
2015-12-26 22:53:44 -08:00
5da8914073 Merge pull request #2 from everamzah/master 2015-09-14 14:31:59 -07:00
7d36e4b3c0 Remove odd chars from warp name 2015-09-09 11:04:03 -04:00
aa772124b3 Update init.lua
Check if the player exists before doing warp queue.
2015-09-09 07:41:11 -04:00
10 changed files with 214 additions and 110 deletions

16
.luacheckrc Normal file
View File

@ -0,0 +1,16 @@
read_globals = {
"DIR_DELIM",
"core",
"dump",
"vector", "nodeupdate",
"VoxelManip", "VoxelArea",
"PseudoRandom", "ItemStack",
"AreaStore",
"default",
table = { fields = { "copy", "getn" } }
}
globals = {
"minetest"
}

View File

@ -1,17 +1,15 @@
warps- a minetest mod that adds more farming crops
See spdx.org/licenses to see what the License Identifiers used below mean.
=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~
All source code (lua):
(C) Auke Kok <sofar@foo-projects.org>
LGPL-2.0+
LGPL-2.1+
All textures, models:
(C) Auke Kok <sofar@foo-projects.org>
CC-BY-SA-3.0
CC-BY-3.0
All sounds: read sounds/LICENSE

11
README
View File

@ -11,7 +11,9 @@
priv: warp_admin - set/change/delete warps
priv: warp_user - list, and use warps
warps are stored in the world folder file "warps.txt".
warps are stored in mod_storage. If you had an older version that
uses the `warps.txt` file, it will be converted on load, after
which the file can be removed.
A warpstone can be given or found in the creative inventory (item
id: warps:warpstone). This warpstone can be placed on the ground
@ -22,9 +24,10 @@ warpstone can be removed by shift-punching the warp stone.
All warps are delayed by ~5 seconds. You have to stand still for
that duration, otherwise the warp will be cancelled. This may avoid
warp spamming and warping out of combat a bit. There's a bit
of variation in time due to the timer resolution in minetest
being rather large.
warp spamming and warping out of combat a bit. The mod tries
really hard to make sure that the player finds themselves in a
loaded area.
========

View File

@ -1 +0,0 @@
default

View File

@ -1 +0,0 @@
Warp locations and warp stones (portal stones)

287
init.lua
View File

@ -10,94 +10,31 @@ of the license, or (at your option) any later version.
--]]
warps = {}
warps_queue = {}
queue_state = 0
local warps = {}
local warps_queue = {}
local queue_state = 0
local warps_freeze = 5
-- t = time in usec
-- p = player obj
-- w = warp name
local warp = function(player, dest)
for i = 1,table.getn(warps) do
if warps[i].name == dest then
player:setpos({x = warps[i].x, y = warps[i].y, z = warps[i].z})
-- MT Core FIXME
-- get functions don't output proper values for set!
-- https://github.com/minetest/minetest/issues/2658
player:set_look_yaw(warps[i].yaw - (math.pi/2))
player:set_look_pitch(0 - warps[i].pitch)
minetest.chat_send_player(player:get_player_name(), "Warped to \"" .. dest .. "\"")
minetest.log("action", player:get_player_name() .. " warped to \"" .. dest .. "\"")
minetest.sound_play("warps_plop", {
pos = {x = warps[i].x, y = warps[i].y, z = warps[i].z},
})
local S = minetest.get_mod_storage()
assert(S, "mod_storage is required")
-- import warps or load
local function firstload()
local store = S:get("warps")
local worldpath = minetest.get_worldpath()
if store then
warps = minetest.deserialize(store)
return
end
end
minetest.chat_send_player(player:get_player_name(), "Unknown warp \"" .. dest .. "\"")
end
do_warp_queue = function()
if table.getn(warps_queue) == 0 then
queue_state = 0
return
end
local t = minetest.get_us_time()
for i = table.getn(warps_queue),1,-1 do
local e = warps_queue[i]
if e.p:getpos().x == e.pos.x and e.p:getpos().y == e.pos.y and e.p:getpos().z == e.pos.z then
if t > e.t then
warp(e.p, e.w)
table.remove(warps_queue, i)
end
else
minetest.sound_stop(e.sh)
minetest.chat_send_player(e.p:get_player_name(), "You have to stand still for " .. warps_freeze .. " seconds!")
table.remove(warps_queue, i)
end
end
if table.getn(warps_queue) == 0 then
queue_state = 0
return
end
minetest.after(1, do_warp_queue)
end
local warp_queue_add = function(player, dest)
table.insert(warps_queue, {
t = minetest.get_us_time() + ( warps_freeze * 1000000 ),
pos = player:getpos(),
p = player,
w = dest,
sh = minetest.sound_play("warps_woosh", { pos = player:getpos() })
})
minetest.chat_send_player(player:get_player_name(), "Don't move for " .. warps_freeze .. " seconds!")
if queue_state == 0 then
queue_state = 1
minetest.after(1, do_warp_queue)
end
end
local worldpath = minetest.get_worldpath()
local save = function ()
local fh,err = io.open(worldpath .. "/warps.txt", "w")
if err then
print("No existing warps to read.")
return
end
for i = 1,table.getn(warps) do
local s = warps[i].name .. " " .. warps[i].x .. " " .. warps[i].y .. " " .. warps[i].z .. " " .. warps[i].yaw .. " " .. warps[i].pitch .. "\n"
fh:write(s)
end
fh:close()
end
local load = function ()
local fh,err = io.open(worldpath .. "/warps.txt", "r")
if err then
minetest.log("action", "[warps] loaded ")
-- If it doesn't exist, we've never used this mod before.
if not err:find("No such file or directory") then
minetest.log("error", "[warps] Error trying to load warps.txt: " .. err)
end
return
end
while true do
@ -117,7 +54,99 @@ local load = function ()
table.insert(warps, w)
end
fh:close()
minetest.log("action", "[warps] loaded " .. table.getn(warps) .. " warp location(s)")
minetest.log("action", "[warps] converted warps to mod_storage. Please delete 'warps.txt'.")
S:set_string("warps", minetest.serialize(warps))
end
local function lookup_warp(name)
for i = 1,table.getn(warps) do
if warps[i].name == name then
return warps[i]
end
end
end
local function round_digits(n, digits)
digits = digits or 0
local multi = math.pow(10, digits)
n = n * multi
if n > 0 then
return math.floor(n + 0.5) / multi
else
return math.ceil(n - 0.5) / multi
end
end
local warp = function(player, dest)
local warp = lookup_warp(dest)
if not warp then
minetest.chat_send_player(player:get_player_name(), "Unknown warp \"" .. dest .. "\"")
return
end
local pos = vector.new(warp)
pos.y = pos.y + 0.5
player:set_pos(pos)
player:set_look_horizontal(warp.yaw)
player:set_look_vertical(warp.pitch)
minetest.chat_send_player(player:get_player_name(), "Warped to \"" .. dest .. "\"")
minetest.log("action", player:get_player_name() .. " warped to \"" .. dest .. "\"")
minetest.sound_play("warps_plop", {pos = pos})
end
local function do_warp_queue()
if table.getn(warps_queue) == 0 then
queue_state = 0
return
end
local t = minetest.get_us_time()
for i = table.getn(warps_queue),1,-1 do
local e = warps_queue[i]
if e.p:get_pos() then
if vector.equals(e.p:get_pos(), e.pos) then
if t > e.t then
warp(e.p, e.w)
table.remove(warps_queue, i)
end
else
minetest.sound_stop(e.sh)
minetest.chat_send_player(e.p:get_player_name(),
"You have to stand still for " .. warps_freeze .. " seconds!")
table.remove(warps_queue, i)
end
end
end
if table.getn(warps_queue) == 0 then
queue_state = 0
return
end
minetest.after(1, do_warp_queue)
end
local warp_queue_add = function(player, dest)
table.insert(warps_queue, {
t = minetest.get_us_time() + (warps_freeze * 1000000),
pos = player:get_pos(),
p = player,
w = dest,
sh = minetest.sound_play("warps_woosh", { pos = player:get_pos() })
})
minetest.chat_send_player(player:get_player_name(), "Don't move for " .. warps_freeze .. " seconds!")
if queue_state == 0 then
queue_state = 1
minetest.after(1, do_warp_queue)
end
-- attempt to emerge the target area before the player gets there
local pos = vector.new(lookup_warp(dest))
minetest.get_voxel_manip():read_from_map(pos, pos)
if not minetest.get_node_or_nil(pos) then
minetest.emerge_area(vector.subtract(pos, 80), vector.add(pos, 80))
end
-- force mapblock send to player, if supported
if player.send_mapblock then
player:send_mapblock(vector.divide(pos, 16))
end
end
minetest.register_privilege("warp_admin", {
@ -137,19 +166,34 @@ minetest.register_chatcommand("setwarp", {
description = "Set a warp location to the players location",
privs = { warp_admin = true },
func = function(name, param)
local h = "created"
param = param:gsub("%W", "")
if param == "" then
return false, "Cannot set warp: Name missing."
end
local h = "Created"
for i = 1,table.getn(warps) do
if warps[i].name == param then
table.remove(warps, i)
h = "changed"
h = "Changed"
break
end
end
local player = minetest.get_player_by_name(name)
local pos = player:getpos()
table.insert(warps, { name = param, x = pos.x, y = pos.y, z = pos.z, yaw = player:get_look_yaw(), pitch = player:get_look_pitch() })
save()
minetest.log("action", name .. " " .. h .. " warp \"" .. param .. "\": " .. pos.x .. ", " .. pos.y .. ", " .. pos.z)
local pos = vector.round(player:get_pos())
table.insert(warps, {
name = param,
x = pos.x,
y = pos.y,
z = pos.z,
yaw = round_digits(player:get_look_horizontal(), 3),
pitch = round_digits(player:get_look_vertical(), 3)
})
S:set_string("warps", minetest.serialize(warps))
minetest.log("action", name .. " " .. h .. " warp \"" .. param .. "\": " ..
pos.x .. ", " .. pos.y .. ", " .. pos.z)
return true, h .. " warp \"" .. param .. "\""
end,
})
@ -189,10 +233,40 @@ minetest.register_chatcommand("warp", {
privs = { warp_user = true },
func = function(name, param)
local player = minetest.get_player_by_name(name)
if not minetest.check_player_privs(player, {warp_admin = true}) then
warp_queue_add(player, param)
else
warp(player, param)
end
end
})
local function prepare_dropdown(x,y,w,h,curr_dest)
local dd = string.format("dropdown[%f,%f;%f,%f;ddwarp;", x, y, w, h)
local sel = 0
for idx, warp in ipairs(warps) do
local warpname = warp.name
dd = dd .. minetest.formspec_escape(warpname) .. ","
if curr_dest == warpname then
sel = idx
end
end
dd = dd .. ";"..tostring(sel).."]"
return dd
end
local function prepare_formspec(dest)
local custdest = ""
if not lookup_warp(dest) then
custdest = dest
end
return "size[4.5,3]label[0.7,0;Warp destination]"
.."field[1,2.2;3,0.2;destination;Future destination;"
..minetest.formspec_escape(custdest).."]"
.."button_exit[0.7,2.7;3,0.5;proceed;Proceed]"
..prepare_dropdown(0.7,0.4,3,1, dest)
end
minetest.register_node("warps:warpstone", {
visual = "mesh",
mesh = "warps_warpstone.obj",
@ -204,14 +278,14 @@ minetest.register_node("warps:warpstone", {
paramtype = "light",
groups = { choppy=3 },
light_source = 8,
diggable = false,
selection_box = {
type = "fixed",
fixed = {-0.25, -0.5, -0.25, 0.25, 0.5, 0.25}
},
on_construct = function(pos)
local meta = minetest.get_meta(pos)
meta:set_string("formspec",
"field[destination;Warp Destination;]")
meta:set_string("formspec", prepare_formspec(""))
meta:set_string("infotext", "Uninitialized Warp Stone")
end,
on_receive_fields = function(pos, formname, fields, sender)
@ -219,32 +293,45 @@ minetest.register_node("warps:warpstone", {
minetest.chat_send_player(sender:get_player_name(), "You do not have permission to modify warp stones")
return false
end
if not fields.destination then
if not (fields.destination and fields.quit) then
return
end
local dest
if fields.destination == "" and fields.ddwarp then
dest = fields.ddwarp
else
dest = fields.destination
end
local meta = minetest.get_meta(pos)
meta:set_string("formspec",
"field[destination;Warp Destination;" .. fields.destination .. "]")
meta:set_string("infotext", "Warp stone to " .. fields.destination)
meta:set_string("warps_destination", fields.destination)
minetest.log("action", sender:get_player_name() .. " changed warp stone to \"" .. fields.destination .. "\"")
meta:set_string("formspec", prepare_formspec(dest))
meta:set_string("infotext", "Warp stone to " .. dest)
meta:set_string("warps_destination", dest)
minetest.log("action", sender:get_player_name() .. " changed warp stone at "
.. minetest.pos_to_string(pos) .. " to \"" .. dest .. "\"")
end,
on_punch = function(pos, node, puncher, pointed_thingo)
if puncher:get_player_control().sneak and minetest.check_player_privs(puncher:get_player_name(), {warp_admin = true}) then
if puncher:get_player_control().sneak and
minetest.check_player_privs(puncher:get_player_name(), {warp_admin = true}) then
minetest.remove_node(pos)
minetest.chat_send_player(puncher:get_player_name(), "Warp stone removed!")
return
end
local meta = minetest.get_meta(pos)
local destination = meta:get_string("warps_destination")
if destination == "" then
minetest.chat_send_player(puncher:get_player_name(), "Unknown warp location for this warp stone, cannot warp!")
if destination == "" or lookup_warp(destination) == nil then
minetest.chat_send_player(puncher:get_player_name(),
"Unknown warp location for this warp stone, cannot warp!")
return false
end
minetest.log("action", string.format("Going to warp player %s to waypoint %s",
puncher:get_player_name(), destination
))
warp_queue_add(puncher, destination)
end,
})
-- load existing warps
load()
firstload()

2
mod.conf Normal file
View File

@ -0,0 +1,2 @@
name = warps
description = Warp locations and warp stones (portal stones)

BIN
screenshot.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 206 KiB

Binary file not shown.

Binary file not shown.