epic/common.lua

231 lines
5.0 KiB
Lua

function epic.create_texture(type, overlay)
local texture = "epic_node_bg.png"
if type == "action" then
texture = "epic_node_action.png"
elseif type == "condition" then
texture = "epic_node_condition.png"
end
return {
texture,
texture,
texture .. "^epic_next_marker.png",
texture,
texture,
texture .. "^" .. overlay,
}
end
local has_screwdriver = minetest.get_modpath("screwdriver")
-- local on_rotate function
function epic.on_rotate(...)
if has_screwdriver then
-- call rotation function on screwdriver mod if available
screwdriver.rotate_simple(...)
end
end
-- creates an empty state, ready for execution
function epic.new_state()
return {
stack = {},
data = {},
step_data = {},
initialized = false
}
end
-- starts the configured epic node at position
function epic.start(playername, pos)
local player = minetest.get_player_by_name(playername)
if not player then
-- player not online
return false
end
local meta = minetest.get_meta(pos)
local main_pos = epic.to_absolute_pos(pos, minetest.string_to_pos(meta:get_string("main_pos")))
local epic_name = meta:get_string("name")
if not main_pos then
-- no main position
return false
end
-- start epic
epic.execute_epic(player, main_pos, epic_name)
return true
end
-- abort epic if running
function epic.abort(playername)
local state = epic.state[playername]
if state then
if epic.log_executor then
minetest.log("action", "[epic] player aborted manually: " .. playername)
end
state.abort = "manual"
end
end
-- debug log
function epic.debug(msg)
if epic.log_executor then
minetest.log("action", "[epic] " .. msg)
end
end
-- converts a pos to a relative one in respect to the node_pos
function epic.to_relative_pos(node_pos, remote_abs_pos)
if not node_pos or not remote_abs_pos then
return
end
return vector.subtract(remote_abs_pos, node_pos)
end
-- converts the relative pos to an absolute one
function epic.to_absolute_pos(node_pos, remote_rel_pos)
if not node_pos or not remote_rel_pos then
return
end
return vector.add(node_pos, remote_rel_pos)
end
-- shows a waypoint for given seconds
function epic.show_waypoint(playername, pos, name, seconds)
local player = minetest.get_player_by_name(playername)
if not player then
return
end
local id = player:hud_add({
hud_elem_type = "waypoint",
name = name,
text = "m",
number = 0xFF0000,
world_pos = pos
})
minetest.after(seconds, function()
player = minetest.get_player_by_name(playername)
if not player then
return
end
player:hud_remove(id)
end)
end
local SECONDS_IN_DAY = 3600*24
local SECONDS_IN_HOUR = 3600
local SECONDS_IN_MINUTE = 60
function epic.format_time(seconds)
local str = ""
if seconds >= SECONDS_IN_DAY then
local days = math.floor(seconds / SECONDS_IN_DAY)
str = str .. days .. " d "
seconds = seconds - (days * SECONDS_IN_DAY)
end
if seconds >= SECONDS_IN_HOUR then
local hours = math.floor(seconds / SECONDS_IN_HOUR)
str = str .. hours .. " h "
seconds = seconds - (hours * SECONDS_IN_HOUR)
end
if seconds >= SECONDS_IN_MINUTE then
local minutes = math.floor(seconds / SECONDS_IN_MINUTE)
str = str .. minutes .. " min "
seconds = seconds - (minutes * SECONDS_IN_MINUTE)
end
str = str .. math.floor(seconds) .. " s"
return str
end
-- converts the direction from a param2
function epic.get_direction(param2)
local direction = minetest.facedir_to_dir(param2)
if direction.x == -1 and direction.z == 0 then
return { x=0, y=0, z=1 }
elseif direction.x == 0 and direction.z == 1 then
return { x=1, y=0, z=0 }
elseif direction.x == 1 and direction.z == 0 then
return { x=0, y=0, z=-1 }
elseif direction.x == 0 and direction.z == -1 then
return { x=-1, y=0, z=0 }
else
return nil
end
end
-- returns the position of the next epic block
function epic.get_next_pos(pos)
local node = minetest.get_node(pos)
local direction = epic.get_direction(node.param2)
if direction == nil then
return
end
local next_pos = vector.add(pos, direction)
return next_pos
end
-- returns a node and loads the area if needed
function epic.get_node(pos)
local node = minetest.get_node_or_nil(pos)
if node == nil then
minetest.get_voxel_manip(pos, pos)
node = minetest.get_node_or_nil(pos)
end
return node
end
-- returns true if the node has an "epic" definition
function epic.is_epic(node)
local nodedef = minetest.registered_nodes[node.name]
return nodedef and nodedef.epic
end
-- executes an epic function
function epic.execute_epic(player, main_pos, name)
if epic.state[player:get_player_name()] then
-- already running a function
return
end
minetest.log("action", "[epic] player " .. player:get_player_name() ..
" executes function at " .. minetest.pos_to_string(main_pos))
local state = epic.new_state()
state.ip = main_pos
state.name = name
epic.state[player:get_player_name()] = state
epic.run_hook("on_execute_epic", { player, main_pos, state })
end
function epic.get_mapblock_pos(pos)
return {
x = math.floor(pos.x / 16),
y = math.floor(pos.y / 16),
z = math.floor(pos.z / 16)
}
end