-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathstate.lua
145 lines (130 loc) · 4.11 KB
/
state.lua
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
local m = tigris.mobs
-- Registrations.
m.actions = {}
m.states = {}
m.interactions = {}
function m.register_action(n, d)
m.actions[n] = d
end
function m.register_state(n, d)
m.states[n] = d
end
function m.register_interaction(n, d)
m.interactions[n] = d
end
-- Reset state for self to new state <s> with data.
function m.reset_state(self, s, data)
self._data.state_data = data or {}
self.sdata = self._data.state_data
self._data.state = s
end
-- Apply global events and interactions from def to the current context.
local function apply_global(def, context)
-- When global exists in the script, add events and interactions to the current script as long as they're not already specified.
if def.script.global and context.script then
if def.script.global.events then
for k,v in pairs(def.script.global.events) do
context.script.events[k] = context.script.events[k] or v
end
end
if def.script.global.interactions then
for k,v in pairs(def.script.global.interactions) do
local o = context.script.interactions[k]
context.script.interactions[k] = (o == nil) and v or o
end
end
end
end
-- Build a context from self with globals applied.
local function get_context(self)
if not self._data.state then
return
end
local context = {
def = self.def,
-- The current state's script.
script = self.def.script[self._data.state] and table.copy(self.def.script[self._data.state]) or nil,
}
if not context.script then
return
end
apply_global(self.def, context)
return context
end
-- Fire an event to self.
function m.fire_event(self, event)
local context = get_context(self)
if not context then
return
end
local sname = context.script.events[event.name]
if sname == "ignore" then
return
end
assert(sname, "Invalid event: " .. tostring(event.name))
-- Reset to the new state.
m.reset_state(self, sname, event.data)
end
-- Apply an interaction to self by other.
function m.interaction(self, other)
local context = get_context(self)
if not context then
return
end
context.other = other
for k,v in pairs(context.script.interactions) do
if v then
assert(m.interactions[k], "Invalid interaction: " .. tostring(k))
m.interactions[k].func(self, context)
end
end
end
-- Run the current state.
function m.state(self, dtime, def)
self._data.state_data = self._data.state_data or {}
self.sdata = self._data.state_data
local state = self._data.state
local context = {
dtime = dtime,
def = def,
script = def.script[state] and table.copy(def.script[state]) or nil,
data = self.sdata,
}
apply_global(def, context)
if m.states[state] and context.script then
-- Run the base state function.
local event = m.states[state].func(self, context)
-- If no event came up, run through actions.
if not event then
for _,v in ipairs(context.script.actions or {}) do
if m.actions[v] then
event = m.actions[v].func(self, context)
if event then
break
end
else
minetest.log("warning", def.name .. " with invalid action: " .. tostring(v))
end
end
end
-- If the base function or an action returned an event, then fire it.
if event then
if context.script.events[event.name] then
m.fire_event(self, event)
else
minetest.log("warning", def.name .. " with invalid event: " .. tostring(state) .. ":" .. tostring(event.name))
end
end
else
minetest.log("warning", def.name .. " with invalid state: " .. tostring(state))
end
end
-- The nil action.
m.register_action("", {
func = function()
return
end,
})
tigris.include("states.lua")
tigris.include("actions.lua")
tigris.include("interactions.lua")