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.
=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~=~
All source code (lua):
(C) Auke Kok <sofar@foo-projects.org>
LGPL-2.1+
LGPL-2.0+
All textures, models:
(C) Auke Kok <sofar@foo-projects.org>
CC-BY-3.0
CC-BY-SA-3.0
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_user - list, and use warps
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.
warps are stored in the world folder file "warps.txt".
A warpstone can be given or found in the creative inventory (item
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
that duration, otherwise the warp will be cancelled. This may avoid
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.
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.
========

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 = {}
local warps_queue = {}
local queue_state = 0
local warps_freeze = 5
warps = {}
warps_queue = {}
queue_state = 0
local warps_freeze = 1
-- t = time in usec
-- p = player obj
-- w = warp name
local S = minetest.get_mod_storage()
assert(S, "mod_storage is required")
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},
})
return
end
end
minetest.chat_send_player(player:get_player_name(), "Unknown warp \"" .. dest .. "\"")
end
-- import warps or load
local function firstload()
local store = S:get("warps")
local worldpath = minetest.get_worldpath()
if store then
warps = minetest.deserialize(store)
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() 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")
if err then
-- 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
minetest.log("action", "[warps] loaded ")
return
end
while true do
@ -54,99 +119,7 @@ local function firstload()
table.insert(warps, w)
end
fh:close()
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
minetest.log("action", "[warps] loaded " .. table.getn(warps) .. " warp location(s)")
end
minetest.register_privilege("warp_admin", {
@ -166,34 +139,22 @@ minetest.register_chatcommand("setwarp", {
description = "Set a warp location to the players location",
privs = { warp_admin = true },
func = function(name, param)
param = param:gsub("%W", "")
if param == "" then
return false, "Cannot set warp: Name missing."
end
local h = "Created"
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 = 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)
local pos = player:getpos()
if not pos then
return false, "Internal error while getting your position. Please try again later"
end
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)
return true, h .. " warp \"" .. param .. "\""
end,
})
@ -233,40 +194,10 @@ 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
warp_queue_add(player, param)
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",
@ -278,14 +209,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", prepare_formspec(""))
meta:set_string("formspec",
"field[destination;Warp Destination;]")
meta:set_string("infotext", "Uninitialized Warp Stone")
end,
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")
return false
end
if not (fields.destination and fields.quit) then
if not fields.destination 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", 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 .. "\"")
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 .. "\"")
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 == "" or lookup_warp(destination) == nil then
minetest.chat_send_player(puncher:get_player_name(),
"Unknown warp location for this warp stone, cannot warp!")
if destination == "" 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,
})
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