2018-07-23 15:14:54 +02:00
|
|
|
|
|
|
|
local MISSION_ATTRIBUTE_NAME = "currentmission"
|
2018-07-24 15:46:58 +02:00
|
|
|
local CURRENT_MISSION_SPEC_VERSION = 1
|
2018-07-23 15:14:54 +02:00
|
|
|
|
|
|
|
local playermissions = {}
|
|
|
|
|
2018-07-24 15:46:58 +02:00
|
|
|
--persistence stuff
|
|
|
|
|
|
|
|
minetest.register_on_joinplayer(function(player)
|
|
|
|
local missionStr = player:get_attribute(MISSION_ATTRIBUTE_NAME)
|
|
|
|
|
|
|
|
local mission = nil
|
|
|
|
if missionStr then
|
|
|
|
mission = minetest.deserialize(missionStr)
|
|
|
|
end
|
|
|
|
|
|
|
|
if mission and mission.version == CURRENT_MISSION_SPEC_VERSION then
|
|
|
|
-- only load if compatible with current spec
|
|
|
|
local step = mission.steps[mission.currentstep]
|
|
|
|
|
|
|
|
-- reset init flag
|
|
|
|
step.initialized = false
|
|
|
|
|
|
|
|
-- store in variable
|
|
|
|
playermissions[player:get_player_name()] = mission
|
|
|
|
end
|
|
|
|
end)
|
|
|
|
|
|
|
|
minetest.register_on_leaveplayer(function(player)
|
|
|
|
playermissions[player:get_player_name()] = nil
|
|
|
|
end)
|
2018-07-23 15:14:54 +02:00
|
|
|
|
|
|
|
local get_current_mission = function(player)
|
|
|
|
return playermissions[player:get_player_name()]
|
|
|
|
end
|
|
|
|
|
2018-07-24 15:46:58 +02:00
|
|
|
local persist_mission = function(player, mission)
|
|
|
|
player:set_attribute(MISSION_ATTRIBUTE_NAME, minetest.serialize(mission))
|
|
|
|
end
|
|
|
|
|
|
|
|
|
2018-07-23 15:14:54 +02:00
|
|
|
local set_current_mission = function(player, mission)
|
|
|
|
playermissions[player:get_player_name()] = mission
|
|
|
|
end
|
|
|
|
|
2018-07-24 15:46:58 +02:00
|
|
|
-- start a mission
|
2018-07-23 15:14:54 +02:00
|
|
|
missions.start = function(pos, player)
|
|
|
|
local mission = get_current_mission(player)
|
|
|
|
local playername = player:get_player_name()
|
|
|
|
|
|
|
|
if mission then
|
|
|
|
minetest.chat_send_player(playername, "A Mission is already running: '" .. mission.name .. "'")
|
|
|
|
return
|
|
|
|
end
|
|
|
|
|
2018-07-23 16:09:01 +02:00
|
|
|
local steps = missions.get_steps(pos)
|
|
|
|
if #steps == 0 then
|
|
|
|
minetest.chat_send_player(playername, "Mission has no steps!")
|
|
|
|
return
|
|
|
|
end
|
|
|
|
|
2018-07-23 15:14:54 +02:00
|
|
|
local meta = minetest.get_meta(pos)
|
|
|
|
|
|
|
|
mission = {
|
2018-07-24 15:46:58 +02:00
|
|
|
version = CURRENT_MISSION_SPEC_VERSION,
|
2018-07-23 16:09:01 +02:00
|
|
|
steps = steps,
|
|
|
|
currentstep = 1,
|
2018-07-23 15:14:54 +02:00
|
|
|
start = os.time(os.date("!*t")),
|
|
|
|
time = meta:get_int("time") or 300,
|
|
|
|
name = meta:get_string("name") or "<no name>",
|
|
|
|
description = meta:get_string("description") or ""
|
|
|
|
}
|
|
|
|
|
|
|
|
set_current_mission(player, mission)
|
|
|
|
end
|
|
|
|
|
2018-07-24 15:46:58 +02:00
|
|
|
-- update the mission
|
2018-07-23 16:09:01 +02:00
|
|
|
local update_mission = function(mission, player)
|
|
|
|
|
|
|
|
local now = os.time(os.date("!*t"))
|
|
|
|
local remainingTime = mission.time - (now - mission.start)
|
|
|
|
local playername = player:get_player_name()
|
|
|
|
local step = mission.steps[mission.currentstep]
|
|
|
|
|
|
|
|
if not step then
|
|
|
|
-- no more steps
|
|
|
|
minetest.chat_send_player(playername, "Mission completed: '" .. mission.name .. "'")
|
|
|
|
set_current_mission(player, nil)
|
|
|
|
return
|
|
|
|
end
|
|
|
|
|
|
|
|
local spec = missions.get_step_spec_by_type(step.type)
|
|
|
|
|
2018-07-23 16:32:18 +02:00
|
|
|
missions.hud_update(player, mission)
|
|
|
|
|
2018-07-23 16:09:01 +02:00
|
|
|
local success = false
|
|
|
|
local failed = false
|
|
|
|
|
|
|
|
local on_success = function()
|
|
|
|
success = true
|
|
|
|
end
|
|
|
|
|
|
|
|
local on_failed = function(msg)
|
|
|
|
failed = true
|
|
|
|
minetest.chat_send_player(playername, "Mission failed: " .. msg)
|
|
|
|
set_current_mission(player, nil)
|
2018-07-23 16:32:18 +02:00
|
|
|
missions.hud_update_status(player, "")
|
2018-07-23 16:09:01 +02:00
|
|
|
if spec.on_step_exit then
|
|
|
|
spec.on_step_exit(step, step.data, player)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
if remainingTime <= 0 then
|
|
|
|
on_failed("timed out")
|
|
|
|
return
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
if not step.initialized then
|
|
|
|
if spec.on_step_enter then
|
|
|
|
spec.on_step_enter(step, step.data, player, on_success, on_failed)
|
|
|
|
end
|
|
|
|
step.initialized = true
|
|
|
|
end
|
|
|
|
|
|
|
|
if failed then
|
|
|
|
return
|
|
|
|
end
|
|
|
|
|
|
|
|
if not success then
|
|
|
|
if spec.on_step_interval then
|
|
|
|
spec.on_step_interval(step, step.data, player, on_success, on_failed)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
if failed then
|
|
|
|
return
|
|
|
|
end
|
|
|
|
|
2018-07-23 16:32:18 +02:00
|
|
|
|
|
|
|
if spec.get_status then
|
|
|
|
local status = spec.get_status(step, step.data, player)
|
|
|
|
missions.hud_update_status(player, status)
|
|
|
|
else
|
|
|
|
missions.hud_update_status(player, "")
|
|
|
|
end
|
|
|
|
|
|
|
|
|
2018-07-23 16:09:01 +02:00
|
|
|
if success then
|
|
|
|
mission.currentstep = mission.currentstep + 1
|
|
|
|
if spec.on_step_exit then
|
|
|
|
spec.on_step_exit(step, step.data, player)
|
|
|
|
end
|
|
|
|
return
|
|
|
|
end
|
|
|
|
end
|
2018-07-23 15:14:54 +02:00
|
|
|
|
2018-07-24 15:46:58 +02:00
|
|
|
-- mission persist job
|
|
|
|
local persistTimer = 0
|
|
|
|
minetest.register_globalstep(function(dtime)
|
|
|
|
persistTimer = persistTimer + dtime;
|
|
|
|
if persistTimer >= 5 then
|
|
|
|
local players = minetest.get_connected_players()
|
|
|
|
for i,player in ipairs(players) do
|
|
|
|
local mission = get_current_mission(player)
|
|
|
|
persist_mission(player, mission)
|
|
|
|
end
|
|
|
|
|
|
|
|
persistTimer = 0
|
|
|
|
end
|
|
|
|
end)
|
2018-07-23 15:14:54 +02:00
|
|
|
|
2018-07-24 15:46:58 +02:00
|
|
|
-- mission update step
|
2018-07-23 15:14:54 +02:00
|
|
|
local timer = 0
|
|
|
|
minetest.register_globalstep(function(dtime)
|
|
|
|
timer = timer + dtime;
|
2018-07-23 16:09:01 +02:00
|
|
|
if timer >= 0.5 then
|
2018-07-23 15:14:54 +02:00
|
|
|
local players = minetest.get_connected_players()
|
2018-07-24 15:46:58 +02:00
|
|
|
for i,player in ipairs(players) do
|
2018-07-23 15:14:54 +02:00
|
|
|
local playername = player:get_player_name()
|
|
|
|
local mission = get_current_mission(player)
|
|
|
|
|
|
|
|
if mission then
|
2018-07-23 16:09:01 +02:00
|
|
|
update_mission(mission, player)
|
|
|
|
else
|
|
|
|
missions.hud_update(player, nil)
|
2018-07-23 15:14:54 +02:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
timer = 0
|
|
|
|
end
|
|
|
|
end)
|