253 lines
11 KiB
Lua

-- API FILE
-- Does not include:
-- Sonic screwdriver (sonic.lua)
-- Exterior registering (tardis/exterior_api.lua)
-- Does include:
-- Get exterior position
-- Place Tardis interior
-- Rebuild Tardis interior
-- Locate Tardis
-- Is this node a Time Rotor?
-- Switch a Time Rotor on/off
-- Lock/Unlock Tardis exit door
-- Toggle antigrav system
--Planned:
-- Summon Tardis API
-- Waypoints
-- Power
-- and more
local data = minetest.get_mod_storage()
local S = minetest.get_translator("drwho_tardis")
drwho_tardis.get = {}
-- Returns the default depth Tardis interiors are placed at
function drwho_tardis.get:interior_depth()
return _drwho_tardis.interiorDepth
end
-- Returns the interior type of a player's Tardis
function drwho_tardis.get:interior_type(id)
local user = _drwho_tardis.get_user(id)
local type = user.console_room.type or "old"
return type
end
-- Returns the exterior position of a player's Tardis (locate_tardis)
function drwho_tardis.get:tardis_ext_position(id)
local user = _drwho_tardis.get_user(id)
if user.out_pos == nil or user.out_pos == "" then
return false, "They don't have a Tardis!", nil -- sucess, errmsg, value
end
return true, "", user.out_pos
end
-- Returns the Tardis exterior list, or an empty table if for some reason "exterior_list" doesn't exist
function drwho_tardis.get:exterior_list()
local ext_list = minetest.deserialize(data:get_string("exterior_list")) or {}
return ext_list
end
-- Returns exterior information based on it's index in the exterior_list
function drwho_tardis.get:exterior_info(index)
local ext_list = drwho_tardis.get:exterior_list()
return ext_list[index] -- if it's nil that's sad
end
-- Returns the current power levels of a player's Tardis
function drwho_tardis.get:power(id)
local user = _drwho_tardis.get_user(id)
return true, user.power, nil
end
-------------------------------------------------------------------------------------------------------
---------------------- PRIVATE API FUNCTIONS -----------------------------------------------
-------------------------------------------------------------------------------------------------------
-- [PRIVATE] Places a Tardis interior for a player (console room)
function _drwho_tardis:place_tardis_interior(id, type, pos)
if pos == nil then
return false, "Position not provided!", nil
else
local user = _drwho_tardis.get_user(id) -- get user data
if type == "custom" then
-- Assume that the given pos is where the door is going to be
user.console_room.type = type -- Save the fact their interior is custom
user.console_room.door_pos_table = {door_0 = pos} -- Remember the door position
user.console_room.door_offset_table = {door_0={x=0,y=0,z=0}} -- door offset is 0
user.in_pos = pos -- save new interior position
_drwho_tardis.save_user(id, user) -- save user data
return true, "", {door_0 = pos} -- success, message, door_pos_table
end
pos.y = _drwho_tardis.interiorDepth -- set the y pos of the interior
local exit_door_offset = {x=0,y=0,z=0}
if _drwho_tardis.rooms[type] then
minetest.place_schematic(pos, _drwho_tardis.rooms[type].path) --minetest.get_modpath("drwho_tardis") .. "/schems/console_room.mts"
exit_door_offset = _drwho_tardis.rooms[type].exit_door_offset -- = {x=7,y=2,z=16}
local exit_door_pos = vector.add(pos, exit_door_offset) -- Schematic adjustments so that the player gets teleported right in front of the door
user.console_room.type = type -- Save what type of interior they have
user.console_room.exit_door_pos = exit_door_pos -- Remember the door position
user.console_room.exit_door_offset = exit_door_offset -- Remember the door offset
user.console_room.anchor_pos = pos -- Remember the schematic place anchor pos
user.in_pos = exit_door_pos -- save new interior position
_drwho_tardis.save_user(id, user) -- save user data
return true, "", exit_door_pos -- success, message, door position
else
return false, "Invalid interior room type! Use /tardis_int to change it.", type -- success, errmsg, int_type
end
end
end
-- id is the username of the player who owns the Tardis
function _drwho_tardis:init_interior_door(id, exit_door_pos)
local d_meta = minetest.get_meta(exit_door_pos)
local d_timer = minetest.get_node_timer(exit_door_pos)
d_timer:start(0.2) --start door timer (in case it doesn't start on construct)
d_meta:set_string("id", id) --set door id
d_meta:set_string("type", "exit") -- set door type
return true, exit_door_pos
end
-- [PRIVATE] Rebuilds a player's Tardis (rebuild_tardis)
-- Can fix old interiors being too high up in the world, and fix caves running through them
function _drwho_tardis:rebuild_tardis_interior(id)
local user = _drwho_tardis.get_user(id, user) -- get user data
local in_pos = table.copy(user.in_pos)
if in_pos == "" or in_pos == nil then
return false, "You don't have a Tardis!" -- success, errmsg
end
local type = user.console_room.type
if type=="" or type==nil then type = "default" end -- defaults
local exit_door_offset = table.copy(user.console_room.exit_door_offset)
if exit_door_offset == nil or exit_door_offset == "" or exit_door_offset == {} then
exit_door_offset = _drwho_tardis.rooms[type].exit_door_offset
user.console_room.exit_door_offset = exit_door_offset
end
local exit_door_offset = user.console_room.exit_door_offset
if exit_door_offset=="" or exit_door_offset==nil then exit_door_offset = {x=7,y=2,z=16} end -- defaults
-- This ensures that the old and new line up properly
local anchor_pos = vector.subtract(in_pos, exit_door_offset)
local success, msg, exit_door_pos = _drwho_tardis:place_tardis_interior(id, type, anchor_pos)
if success == false then
_drwho_tardis.save_user(id, user) -- save user data
return false, msg, exit_door_pos -- exit_door_pos is actually the type in this situation after returned by the place API function
end
-- Interior door stuff
_drwho_tardis:init_interior_door(id, exit_door_pos)
-- Clear Time Rotor pos because that doesn't exist anymore
_drwho_tardis.update_one_value(id, "r_pos", "")
return true, "", exit_door_pos -- success!
end
-- Check if the Time Rotor is there or not
-- name is required, pos is not
function _drwho_tardis.is_time_rotor(id, pos)
local user = _drwho_tardis.get_user(id) -- get user data
local r_pos = pos or table.copy(user.r_pos)
if not r_pos or r_pos == "" or r_pos == {} then return false, "r_pos doesn't exist", r_pos end
local rmeta = minetest.get_meta(r_pos)
local rotor_node = minetest.get_node(r_pos)
if minetest.get_item_group(rotor_node.name, 'tardis_time_rotor') == 1 or
minetest.get_item_group(rotor_node.name, 'tardis_time_rotor_active') == 1 then
return true, "rotor is there", r_pos
else
return false, "rotor is not there", r_pos
end
end
-- Starts/stops time rotor animation
function _drwho_tardis.switch_time_rotor(id, on_off)
local user = _drwho_tardis.get_user(id) -- get user data
-- 'r' is the Rotor
local r_pos = table.copy(user.r_pos)
local is_it_there, msg = _drwho_tardis.is_time_rotor(id)
if is_it_there then
local rmeta = minetest.get_meta(r_pos)
local style = rmeta:get_string("style")
local rotor_node = minetest.get_node(r_pos)
if on_off == "on" then
minetest.swap_node(r_pos, {name = "drwho_tardis:rotor_active"..style })
return true, r_pos
elseif on_off == "off" then
minetest.swap_node(r_pos, {name = "drwho_tardis:rotor"..style })
return true, r_pos
end
else
minetest.chat_send_player(id, S("You need to have a Time Rotor!"))
return false, r_pos
end
end
-- locks or unlocks the interior door. if on_off is not given, it will toggle.
function _drwho_tardis.toggle_int_door(id, on_off)
local user = _drwho_tardis.get_user(id) -- get user data
local in_pos = table.copy(user.in_pos)
if on_off == "lock" then
minetest.set_node(in_pos, { name = "drwho_tardis:in_door_locked" })
local dmeta = minetest.get_meta(in_pos)
dmeta:set_string("id", id) -- set door id
dmeta:set_string("type", "exit") -- set door type
return true, "Interior door locked"
elseif on_off == "unlock" then
minetest.set_node(in_pos, { name = "drwho_tardis:in_door" })
-- Start door timer
local dtimer = minetest.get_node_timer(in_pos)
local dmeta = minetest.get_meta(in_pos)
dmeta:set_string("id", id) -- set door id
dmeta:set_string("type", "exit") -- set door type
dtimer:start(0.2) -- start door timer (in case it doesn't start on construct)
return true, "Interior door unlocked"
else -- on_off is not given, toggle door
if minetest.get_node(in_pos).name == "drwho_tardis:in_door" then
minetest.set_node(in_pos, { name = "drwho_tardis:in_door_locked" })
local dmeta = minetest.get_meta(in_pos)
dmeta:set_string("id", id) -- set door id
dmeta:set_string("type", "exit") -- set door type
return true, "Interior door locked"
else
minetest.set_node(in_pos, { name = "drwho_tardis:in_door" })
-- Start door timer
local dtimer = minetest.get_node_timer(in_pos)
local dmeta = minetest.get_meta(in_pos)
dmeta:set_string("id", id) -- set door id
dmeta:set_string("type", "exit") -- set door type
dtimer:start(0.2) -- start door timer (in case it doesn't start on construct)
return true, "Interior door unlocked"
end
end
end
-- Toggle the antigrav system
-- returns success, status
function _drwho_tardis.toggle_mavity(id)
local user = _drwho_tardis.get_user(id) -- get user data
local msg
if user.respect_mavity == "yes" then -- It's on, turn it off
user.respect_mavity = "no"
msg = "Antigrav system disabled"
elseif user.respect_mavity == "no" then -- It's off, set to sink
user.respect_mavity = "sink" -- sink in liquids mode
msg = "Antigrav system enabled and set to sink in liquids"
else -- it's "sink" or nil; turn it on
user.respect_mavity = "yes"
msg = "Antigrav system enabled but won't sink in water"
end
_drwho_tardis.save_user(id, user) -- save user data
return true, msg
end