airshuttle/route.lua

275 lines
7.4 KiB
Lua

--[[
Airshuttle
==========
Copyright (C) 2018 Joachim Stolberg
See LICENSE.txt for more information
]]--
local P = minetest.pos_to_string
local MAX_NUM_WAYPOINTS = 50
local MAX_NUM_ROUTES = 50
-------------------------------------------------------------------
-- Data base storage
-------------------------------------------------------------------
local storage = minetest.get_mod_storage()
local AirRoutes = minetest.deserialize(storage:get_string("AirRoutes")) or {}
local function update_mod_storage()
storage:set_string("AirRoutes", minetest.serialize(AirRoutes))
end
local function array(size, val)
local tbl = {}
for i = 1,size do
if type(val) == "table" then
tbl[i] = table.copy(val)
else
tbl[i] = val
end
end
return tbl
end
local function range(val, min, max)
val = math.floor(math.abs(tonumber(val) or min))
if val > max then return max end
if val < min then return min end
return val
end
local function replace_node(pos, player_name, old_name, new_node)
local node = minetest.get_node(pos)
local player = minetest.get_player_by_name(player_name)
if player and node.name == old_name then
minetest.remove_node(pos)
minetest.set_node(pos, new_node)
local after_place_node = minetest.registered_nodes[new_node.name].after_place_node
if after_place_node then
after_place_node(pos, player)
end
end
end
local function add_waypoint(name, id, number, pos, height)
if not AirRoutes[name] then
AirRoutes[name] = {}
end
if not AirRoutes[name][id] then
AirRoutes[name][id] = array(MAX_NUM_WAYPOINTS, false)
end
local speed = range(height, 2, 8)
pos.y = pos.y + height
AirRoutes[name][id][number] = {waypoint = table.copy(pos), speed = speed}
update_mod_storage()
return pos
end
local function get_waypoint(name, id, number)
if AirRoutes[name]
and AirRoutes[name][id]
and AirRoutes[name][id][number] then
return AirRoutes[name][id][number].waypoint
end
return nil
end
local function del_waypoint(name, id, number)
if get_waypoint(name, id, number) then
AirRoutes[name][id][number] = false
end
update_mod_storage()
end
local function del_route(name, id)
if AirRoutes[name] and AirRoutes[name][id] then
AirRoutes[name][id] = array(MAX_NUM_WAYPOINTS, false)
end
update_mod_storage()
end
local function show_route(name, id)
if AirRoutes[name] and AirRoutes[name][id] then
local tbl = {}
for num = 1,MAX_NUM_WAYPOINTS do
if AirRoutes[name][id][num] then
local item = AirRoutes[name][id][num]
tbl[#tbl+1] = num.." : "..P(item.waypoint)..", "..item.speed.." m/s\n"
replace_node(item.waypoint, name, "air", {name="airshuttle:routemarker", param2 = num})
end
end
local text = "AirShuttle route "..id..":\n"..table.concat(tbl)
minetest.chat_send_player(name, text)
end
update_mod_storage()
end
function airshuttle.get_next_waypoint(name, id, number)
if not number then number = 0 end
if AirRoutes[name] and AirRoutes[name][id] then
for num = number+1,MAX_NUM_WAYPOINTS do
if AirRoutes[name][id][num] then
return num,
AirRoutes[name][id][num].waypoint,
AirRoutes[name][id][num].speed
end
end
end
end
function airshuttle.get_next_id(name)
if not AirRoutes[name] then
AirRoutes[name] = {}
end
for id = 1, MAX_NUM_ROUTES do
if not AirRoutes[name][id] then
AirRoutes[name][id] = array(MAX_NUM_WAYPOINTS, false)
update_mod_storage()
return id
end
end
end
function airshuttle.delete_id(name, id)
if AirRoutes[name] and AirRoutes[name][id] then
AirRoutes[name][id] = false
end
update_mod_storage()
end
minetest.register_node("airshuttle:routemarker", {
description = "AirShuttle Route Marker",
drawtype = "node",
tiles = {
"airshuttle_marker_top.png",
"airshuttle_marker_top.png",
"airshuttle_marker.png",
"airshuttle_marker.png",
"airshuttle_marker.png",
"airshuttle_marker.png",
},
after_place_node = function(pos, placer)
local meta = minetest.get_meta(pos)
local node = minetest.get_node(pos)
local spos = minetest.pos_to_string(pos)
meta:set_string("infotext", "Waypoint "..node.param2.." "..spos)
minetest.get_node_timer(pos):start(60*5)
end,
on_timer = function(pos, elapsed)
minetest.remove_node(pos)
end,
paramtype = "light",
light_source = 8,
use_texture_alpha = true,
sunlight_propagates = true,
is_ground_content = false,
drop = "",
walkable = false,
groups = {cracky = 3, oddly_breakable_by_hand = 3, not_in_creative_inventory = 1},
sounds = default.node_sound_glass_defaults(),
})
minetest.register_privilege("airshuttle",
{description = "rights to buy and operate an AirShuttle",
give_to_singleplayer = false})
minetest.register_chatcommand("add_waypoint", {
params = "<id> <number> <extra-height>" ,
description = "Set AirShuttle fly waypoint",
func = function(name, param)
if minetest.check_player_privs(name, "airshuttle") then
local id, number, height = param:match('^(%d+)%s(%d+)%s(%d+)$')
if not id or not number or not height then
return false, "Incorrect usage, /add_waypoint <id> <number> <extra-height>"
end
id = range(id, 1, MAX_NUM_ROUTES)
number = range(number, 1, MAX_NUM_WAYPOINTS)
height = range(height, 1, 50) + 1
local pos = get_waypoint(name, id, number)
if pos then
replace_node(pos, name, "airshuttle:routemarker", {name = "air"})
end
local player = minetest.get_player_by_name(name)
pos = player and player:get_pos() or nil
if pos then
pos = vector.round(pos)
pos = add_waypoint(name, id, number, pos, height)
replace_node(pos, name, "air", {name="airshuttle:routemarker", param2 = number})
local spos = minetest.pos_to_string(pos)
return true, "Waypoint "..number.." at "..spos.." added."
end
else
return false, "You do not have the necessary privs"
end
end,
})
minetest.register_chatcommand("del_waypoint", {
params = "<id> <number>" ,
description = "Delete AirShuttle fly waypoint",
func = function(name, param)
if minetest.check_player_privs(name, "airshuttle") then
local id, number = param:match('^(%d+)%s(%d+)$')
if not id or not number then
return false, "Incorrect usage, /del_waypoint <id> <number>"
end
id = range(id, 1, MAX_NUM_ROUTES)
number = range(number, 1, MAX_NUM_WAYPOINTS)
local player = minetest.get_player_by_name(name)
local pos = get_waypoint(name, id, number)
if pos then
del_waypoint(name, id, number)
replace_node(pos, name, "airshuttle:routemarker", {name = "air"})
local spos = minetest.pos_to_string(pos)
return true, "Waypoint "..id.." at "..spos.." removed."
end
else
return false, "You do not have the necessary privs"
end
end,
})
minetest.register_chatcommand("del_route", {
params = "<id>" ,
description = "Delete AirShuttle fly route",
func = function(name, param)
if minetest.check_player_privs(name, "airshuttle") then
local id = param:match('^(%d+)$')
if not id then
return false, "Incorrect usage, /del_route <id>"
end
id = range(id, 1, MAX_NUM_ROUTES)
del_route(name, id)
return true, "Route "..id.." removed."
else
return false, "You do not have the necessary privs"
end
end,
})
minetest.register_chatcommand("show_route", {
params = "<id>" ,
description = "Show AirShuttle fly route",
func = function(name, param)
if minetest.check_player_privs(name, "airshuttle") then
local id = param:match('^(%d+)$')
if not id then
return false, "Incorrect usage, /show_route <id>"
end
id = range(id, 1, MAX_NUM_ROUTES)
show_route(name, id)
return true
else
return false, "You do not have the necessary privs"
end
end,
})