-
Notifications
You must be signed in to change notification settings - Fork 1
/
eventlog.lua
executable file
·122 lines (105 loc) · 2.99 KB
/
eventlog.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
local class = require 'middleclass.middleclass'
require 'colliderwrapper'
require 'utils'
require 'events.tickevent'
require 'statecache'
EventLog = class('EventLog')
EventLog.events = {}
EventLog.cache = nil
function EventLog:initialize(startState)
self.collider = ColliderWrapper:new(self)
self.events = {}
self.startState = startState
self.cache = StateCache:new()
end
function EventLog:append(event)
table.insert(self.events, event)
end
function EventLog:insert(event, t)
local seenTicks = 0
local newEvents = {}
-- if the event happens at 0, insert the event
table.insert(newEvents, e)
-- wind time forwards, inserting the event when get to the right point
for _, e in ipairs(self.events) do
table.insert(newEvents, e)
if e:isInstanceOf(TickEvent) then
seenTicks = seenTicks + 1
if seenTicks == t then
table.insert(newEvents, event)
end
end
end
-- if we didn't get to insert the event, push out the log to contain enough TickEvents
-- and insert
if seenTicks < t then
for i = seenTicks, t-1, 1 do
table.insert(newEvents, TickEvent:new())
end
table.insert(newEvents, event)
end
self.cache:invalidateAfter(t)
self.events = newEvents
end
function EventLog:eventsInRange(first, last)
local events = {}
local time = 0
for _, e in ipairs(self.events) do
if e:isInstanceOf(TickEvent) then
time = time + 1
end
if time > last then
break
end
if time >= first and time < last then
table.insert(events, e)
end
end
if time < last then
for i = time, last-1, 1 do
table.insert(events, TickEvent:new())
end
end
return events
end
function EventLog:play(t)
local cacheTime, cached = self.cache:before(t)
local state
if not cacheTime then
self.collider:clear()
local events = self:eventsInRange(0, t)
state = self:applyEvents(self.startState, events, 0)
else
local events = self:eventsInRange(cacheTime, t)
state = self:applyEvents(cached, events, cacheTime)
end
self.cache:insert(state, t)
self:sanitizeCollider(state)
return state
end
function EventLog:applyEvents(state, events, startTime)
local newState = copystate(state)
local time = startTime
for _, e in ipairs(events) do
e:apply(newState, self.collider)
if e:isInstanceOf(TickEvent) then
time = time + 1
self.collider:tick(time, newState)
end
end
return newState
end
function EventLog:reset()
self.cache:invalidateAfter(0)
end
function EventLog:sanitizeCollider(entities)
for k, e in pairs(entities) do
if type(k) == "number" then
if e.ghosted then
self.collider:setGhost(e.hitbox)
else
self.collider:setSolid(e.hitbox)
end
end
end
end