Compare commits

1 Commits

Author SHA1 Message Date
be1f8d5dad Version MFF. 2018-09-08 23:19:56 +02:00
14 changed files with 116 additions and 215 deletions

View File

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

6
LICENSE Normal file → Executable file
View File

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

11
README Normal file → Executable file
View File

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

1
depends.txt Executable file
View File

@ -0,0 +1 @@
default

1
description.txt Executable file
View File

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

294
init.lua Normal file → Executable file
View File

@ -10,31 +10,96 @@ of the license, or (at your option) any later version.
--]] --]]
local warps = {} warps = {}
local warps_queue = {} warps_queue = {}
local queue_state = 0 queue_state = 0
local warps_freeze = 5 local warps_freeze = 1
-- t = time in usec -- t = time in usec
-- p = player obj -- p = player obj
-- w = warp name -- w = warp name
local S = minetest.get_mod_storage() local warp = function(player, dest)
assert(S, "mod_storage is required") 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},
})
return
end
end
minetest.chat_send_player(player:get_player_name(), "Unknown warp \"" .. dest .. "\"")
end
-- import warps or load do_warp_queue = function()
local function firstload() if table.getn(warps_queue) == 0 then
local store = S:get("warps") queue_state = 0
local worldpath = minetest.get_worldpath()
if store then
warps = minetest.deserialize(store)
return return
end 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() then
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
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") local fh,err = io.open(worldpath .. "/warps.txt", "r")
if err then if err then
-- If it doesn't exist, we've never used this mod before. minetest.log("action", "[warps] loaded ")
if not err:find("No such file or directory") then
minetest.log("error", "[warps] Error trying to load warps.txt: " .. err)
end
return return
end end
while true do while true do
@ -54,99 +119,7 @@ local function firstload()
table.insert(warps, w) table.insert(warps, w)
end end
fh:close() fh:close()
minetest.log("action", "[warps] converted warps to mod_storage. Please delete 'warps.txt'.") minetest.log("action", "[warps] loaded " .. table.getn(warps) .. " warp location(s)")
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 end
minetest.register_privilege("warp_admin", { minetest.register_privilege("warp_admin", {
@ -166,34 +139,22 @@ minetest.register_chatcommand("setwarp", {
description = "Set a warp location to the players location", description = "Set a warp location to the players location",
privs = { warp_admin = true }, privs = { warp_admin = true },
func = function(name, param) func = function(name, param)
param = param:gsub("%W", "") local h = "created"
if param == "" then
return false, "Cannot set warp: Name missing."
end
local h = "Created"
for i = 1,table.getn(warps) do for i = 1,table.getn(warps) do
if warps[i].name == param then if warps[i].name == param then
table.remove(warps, i) table.remove(warps, i)
h = "Changed" h = "changed"
break break
end end
end end
local player = minetest.get_player_by_name(name) local player = minetest.get_player_by_name(name)
local pos = vector.round(player:get_pos()) local pos = player:getpos()
table.insert(warps, { if not pos then
name = param, return false, "Internal error while getting your position. Please try again later"
x = pos.x, end
y = pos.y, table.insert(warps, { name = param, x = pos.x, y = pos.y, z = pos.z, yaw = player:get_look_yaw(), pitch = player:get_look_pitch() })
z = pos.z, save()
yaw = round_digits(player:get_look_horizontal(), 3), minetest.log("action", name .. " " .. h .. " warp \"" .. param .. "\": " .. pos.x .. ", " .. pos.y .. ", " .. pos.z)
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 .. "\"" return true, h .. " warp \"" .. param .. "\""
end, end,
}) })
@ -233,40 +194,10 @@ minetest.register_chatcommand("warp", {
privs = { warp_user = true }, privs = { warp_user = true },
func = function(name, param) func = function(name, param)
local player = minetest.get_player_by_name(name) local player = minetest.get_player_by_name(name)
if not minetest.check_player_privs(player, {warp_admin = true}) then warp_queue_add(player, param)
warp_queue_add(player, param)
else
warp(player, param)
end
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", { minetest.register_node("warps:warpstone", {
visual = "mesh", visual = "mesh",
mesh = "warps_warpstone.obj", mesh = "warps_warpstone.obj",
@ -278,14 +209,14 @@ minetest.register_node("warps:warpstone", {
paramtype = "light", paramtype = "light",
groups = { choppy=3 }, groups = { choppy=3 },
light_source = 8, light_source = 8,
diggable = false,
selection_box = { selection_box = {
type = "fixed", type = "fixed",
fixed = {-0.25, -0.5, -0.25, 0.25, 0.5, 0.25} fixed = {-0.25, -0.5, -0.25, 0.25, 0.5, 0.25}
}, },
on_construct = function(pos) on_construct = function(pos)
local meta = minetest.get_meta(pos) local meta = minetest.get_meta(pos)
meta:set_string("formspec", prepare_formspec("")) meta:set_string("formspec",
"field[destination;Warp Destination;]")
meta:set_string("infotext", "Uninitialized Warp Stone") meta:set_string("infotext", "Uninitialized Warp Stone")
end, end,
on_receive_fields = function(pos, formname, fields, sender) on_receive_fields = function(pos, formname, fields, sender)
@ -293,45 +224,32 @@ minetest.register_node("warps:warpstone", {
minetest.chat_send_player(sender:get_player_name(), "You do not have permission to modify warp stones") minetest.chat_send_player(sender:get_player_name(), "You do not have permission to modify warp stones")
return false return false
end end
if not (fields.destination and fields.quit) then if not fields.destination then
return return
end end
local dest
if fields.destination == "" and fields.ddwarp then
dest = fields.ddwarp
else
dest = fields.destination
end
local meta = minetest.get_meta(pos) local meta = minetest.get_meta(pos)
meta:set_string("formspec",
meta:set_string("formspec", prepare_formspec(dest)) "field[destination;Warp Destination;" .. fields.destination .. "]")
meta:set_string("infotext", "Warp stone to " .. dest) meta:set_string("infotext", "Warp stone to " .. fields.destination)
meta:set_string("warps_destination", dest) meta:set_string("warps_destination", fields.destination)
minetest.log("action", sender:get_player_name() .. " changed warp stone at " minetest.log("action", sender:get_player_name() .. " changed warp stone to \"" .. fields.destination .. "\"")
.. minetest.pos_to_string(pos) .. " to \"" .. dest .. "\"")
end, end,
on_punch = function(pos, node, puncher, pointed_thingo) on_punch = function(pos, node, puncher, pointed_thingo)
if puncher:get_player_control().sneak and if puncher:get_player_control().sneak and minetest.check_player_privs(puncher:get_player_name(), {warp_admin = true}) then
minetest.check_player_privs(puncher:get_player_name(), {warp_admin = true}) then
minetest.remove_node(pos) minetest.remove_node(pos)
minetest.chat_send_player(puncher:get_player_name(), "Warp stone removed!") minetest.chat_send_player(puncher:get_player_name(), "Warp stone removed!")
return return
end end
local meta = minetest.get_meta(pos) local meta = minetest.get_meta(pos)
local destination = meta:get_string("warps_destination") local destination = meta:get_string("warps_destination")
if destination == "" or lookup_warp(destination) == nil then if destination == "" then
minetest.chat_send_player(puncher:get_player_name(), minetest.chat_send_player(puncher:get_player_name(), "Unknown warp location for this warp stone, cannot warp!")
"Unknown warp location for this warp stone, cannot warp!")
return false return false
end end
minetest.log("action", string.format("Going to warp player %s to waypoint %s",
puncher:get_player_name(), destination
))
warp_queue_add(puncher, destination) warp_queue_add(puncher, destination)
end, end,
}) })
firstload() -- load existing warps
load()

View File

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

0
models/warps_warpstone.obj Normal file → Executable file
View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 206 KiB

0
sounds/LICENSE Normal file → Executable file
View File

Binary file not shown.

Binary file not shown.

BIN
textures/warps_warpstone.png Normal file → Executable file

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.8 KiB

After

Width:  |  Height:  |  Size: 1.7 KiB

BIN
textures/warps_warpstone_guide.png Normal file → Executable file

Binary file not shown.

Before

Width:  |  Height:  |  Size: 348 B

After

Width:  |  Height:  |  Size: 199 B