134 lines
4.5 KiB
Lua
134 lines
4.5 KiB
Lua
|
|
local dbg
|
|
if moddebug then dbg=moddebug.dbg("people") else dbg={v1=function() end,v2=function() end,v3=function() end} end
|
|
|
|
-- This table tracks all the people in the world. It's keyed on the person
|
|
-- name, and each entry is a table keyed as follows:
|
|
-- entity - the active luaentity reference, or nil if not active
|
|
-- pos - when inactive, the entity's position
|
|
-- waketime - time in seconds until this entity should be re-awoken,
|
|
-- or nil (only ever set when inactive)
|
|
-- waking - used internally to track wakeup status
|
|
-- dead - used internally to track when dead
|
|
-- wakecmds - list of commands to run on activation, each being
|
|
-- at table of {name, args}
|
|
-- Changes to this should be via the functions below.
|
|
people.people = {}
|
|
local file = io.open(minetest.get_worldpath().."/people_people", "r")
|
|
if file then
|
|
people.people = minetest.deserialize(file:read("*all"))
|
|
file:close()
|
|
end
|
|
|
|
local people_save = function()
|
|
-- We save without the entity field, because all will be inactive
|
|
-- when reloaded
|
|
local speople = {}
|
|
for k, v in pairs(people.people) do
|
|
speople[k] = {
|
|
pos = v.pos,
|
|
waketime = v.waketime,
|
|
}
|
|
end
|
|
local file = io.open(minetest.get_worldpath().."/people_people", "w")
|
|
if file then
|
|
file:write(minetest.serialize(speople))
|
|
file:close()
|
|
end
|
|
end
|
|
|
|
|
|
people.people_add = function(entity)
|
|
people.people[entity.name] = {entity=entity}
|
|
dbg.v2(entity.name.." added")
|
|
end
|
|
|
|
people.people_set_active = function(entity)
|
|
local pr = people.people[entity.name]
|
|
if not pr then
|
|
-- Should never happen
|
|
dbg.v1(entity.name.." reactivated without existing record")
|
|
pr = {}
|
|
people.people[entity.name] = pr
|
|
end
|
|
pr.entity = entity
|
|
if pr.waketime then
|
|
local loadpos = pr.pos
|
|
if not loadpos then
|
|
dbg.v1("Activated entity has waketime but no pos")
|
|
else
|
|
dbg.v2("Free forceload for "..minetest.pos_to_string(loadpos))
|
|
minetest.forceload_free_block(loadpos)
|
|
end
|
|
pr.pos = nil
|
|
pr.waketime = nil
|
|
pr.waking = nil
|
|
end
|
|
dbg.v2(entity.name.." activated")
|
|
if pr.wakecmds then
|
|
-- We can't do these right now, because we're already within the
|
|
-- on_activate handler for this entity.
|
|
minetest.after(0, function()
|
|
for _, wc in pairs(pr.wakecmds) do
|
|
local name = wc[1]
|
|
local param = wc[2]
|
|
dbg.v1("Re-running chat command after wake-up: "..name.." : "..param or "nil")
|
|
local success, reply = people.do_command(name, param)
|
|
if reply then
|
|
minetest.chat_send_player(name, reply)
|
|
end
|
|
end
|
|
pr.wakecmds = {}
|
|
end)
|
|
end
|
|
end
|
|
|
|
people.people_set_inactive = function(entity)
|
|
if not people.people[entity.name] then
|
|
dbg.v1("people_set_inactive for "..entity.name or nil.." with no people record")
|
|
return
|
|
end
|
|
if people.people[entity.name].dead then
|
|
people.people[entity.name] = nil
|
|
dbg.v2(entity.name.." deactivated forever")
|
|
else
|
|
people.people[entity.name].entity = nil
|
|
people.people[entity.name].pos = entity.object:getpos()
|
|
if entity.wait == 0 then
|
|
people.people[entity.name].waketime = minetest.get_gametime() + 1
|
|
else
|
|
people.people[entity.name].waketime = entity.wait
|
|
end
|
|
dbg.v2(entity.name.." deactivated")
|
|
end
|
|
people_save()
|
|
end
|
|
|
|
|
|
--- Called at regular intervals
|
|
-- Handles waking entities that are unloaded and shouldn't be any more.
|
|
-- Once a second is probably about right, although more frequently wouldn't
|
|
-- hurt.
|
|
people.people_wake = function()
|
|
|
|
for k, v in pairs(people.people) do
|
|
if v.waketime and v.waketime <= minetest.get_gametime() and not v.waking then
|
|
|
|
-- Need to flag that we're doing it, because there will be a
|
|
-- delay before the block is actually loaded.
|
|
v.waking = true
|
|
|
|
-- Wake the entity by (yuk) setting a forceload. The activation
|
|
-- of the entity will cause the forceload to be freed.
|
|
dbg.v2("Set forceload for "..minetest.pos_to_string(v.pos).." to activate "..k)
|
|
minetest.forceload_block(v.pos)
|
|
|
|
-- Only one at a time, even though this will introduce some
|
|
-- inaccuracy as to when they actually wake
|
|
break
|
|
end
|
|
end
|
|
|
|
end
|
|
|