-
Notifications
You must be signed in to change notification settings - Fork 1
/
GameObject.lua
209 lines (167 loc) · 5.11 KB
/
GameObject.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
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
-- GameObject
-- mixin
GameObject = {
-- x,y,oid,class,owner
-- props
-- sync_high, sync_low
-- zones, zone
-- changeMonitorHigh
-- changeMonitorLow
-- counts object destructions to be able to kill running tickers (eg. after)
die_counter = 0,
onMixin = function (self)
--~ print("GO MIXIN")
object_manager.create(self)
if not self.created_via_network then
-- print("CREATE FOR NETWORK", self.oid, self.class)
self:netCreate()
end
if self.sync_high then
self.changeMonitorHigh = MonitorChanges:new{ timeout = config.sync_high, obj = self, keys = self.sync_high }
end
if self.sync_low then
self.changeMonitorLow = MonitorChanges:new{ timeout = config.sync_low, obj = self, keys = self.sync_low }
end
self.zones = {}
self.zone = 0
-- TODO sync -> prop
--~ for _,v in pairs(self.sync_low) do
--~
--~ end
end,
calculateOwnZone = function (self)
local w = config.map_width
local h = config.map_height
local x = utils.clamp(self.x, 0, w)
local y = utils.clamp(self.y, 0, h)
local c = config.zones
local g = w / c
self.zone = math.floor(x / g) + math.floor(y / g) * c
end,
-- you need to manually call this
calculateZones = function (self, overlap)
overlap = overlap or 400
-- clear zones
for k,v in pairs(self.zones) do self.zones[k] = nil end
self.zone = 0
local w = config.map_width
local h = config.map_height
local x = utils.clamp(self.x, 0, w)
local y = utils.clamp(self.y, 0, h)
local c = config.zones
local g = w / c
for cx = 0,c-1 do
for cy = 0,c-1 do
local gx = cx * g
local gy = cy * g
if collision.minDistPointToAABB(x,y, gx,gy, gx+g,gy+g) < overlap then
local z = cx + c * cy
table.insert(self.zones, z)
end
end
end
--~ print(x,y, self.zone)
--~ utils.vardump(self.zones)
end,
onUpdate = function (self, ...)
profile.start("onupdate.gameobject." .. self.class)
--~ print("GO UPDATE")
profile.start("onupdatelocal.gameobject." .. self.class)
if self:isLocal() then
if self.onUpdateLocal then self:onUpdateLocal(...) end
if self.changeMonitorHigh then self.changeMonitorHigh:checkAndSend() end
if self.changeMonitorLow then self.changeMonitorLow:checkAndSend() end
else
if self.onUpdateRemote then self:onUpdateRemote(...) end
end
profile.stop()
profile.start("onupdateboth.gameobject." .. self.class)
if self.onUpdateBoth then self:onUpdateBoth(...) end
profile.stop()
profile.start("onupdate.zone")
self:calculateOwnZone()
profile.stop()
profile.stop()
end,
after = function (self, duration, fun)
local starting_die_counter = self.die_counter
the.app.view.timer:after(duration, function()
if self.die_counter == starting_die_counter then fun() end
end)
end,
every = function (self, duration, fun)
local starting_die_counter = self.die_counter
the.app.view.timer:every(duration, function()
if self.die_counter == starting_die_counter then fun() end
end)
end,
onDie = function (self, ...)
self.die_counter = self.die_counter + 1
if self:isLocal() then
if self.onDieLocal then self:onDieLocal(...) end
network.send({channel = "game", cmd = "delete", oid = self.oid, })
else
if self.onDieRemote then self:onDieRemote(...) end
end
if self.onDieBoth then self:onDieBoth(...) end
object_manager.delete(self)
end,
receive = function (self, message_name, ...)
end,
receiveWithoutResendingToNet = function (self, message_name, ...)
--~ print("GO RECEIVE", message_name, ...)
if self:isLocal() then
if self.receiveLocal then self:receiveLocal(message_name, ...) end
else
if self.receiveRemote then self:receiveRemote(message_name, ...) end
end
if self.receiveBoth then self:receiveBoth(message_name, ...) end
self:sendResync()
end,
receive = function (self, message_name, ...)
self:receiveWithoutResendingToNet(message_name, ...)
-- deliver message to network
local params = {...}
network.send({channel = "game", cmd = "msg", oid = self.oid,
name = message_name, params = params, time = network.time})
end,
netCreate = function (self)
local m = {
channel = "game", cmd = "create", class = self.class, oid = self.oid, owner = self.owner,
x = self.x, y = self.y, width = self.width, height = self.height,
}
if self.props then
for _,prop in pairs(self.props) do
m[prop] = self[prop]
end
end
network.send(m)
end,
isLocal = function (self)
if self.owner and self.owner > 0 then
return self.owner == network.client_id
else
return network.client_id == network.lowest_client_id
end
end,
sendResync = function (self)
if not self:isLocal() then return end
local nils = {}
local msg = { channel = "game", cmd = "sync", oid = self.oid, owner = self.owner, time = network.time, }
for _,prop in pairs(self.props) do
if self[prop] == nil then table.insert(nils, prop) end
msg[prop] = self[prop]
end
msg.nils = nils
network.send(msg, false)
end,
propsToString = function (self)
local r = ""
if self.props then
for k,v in pairs(self.props) do
r = r .. v .. "=" .. tostring(self[v]) .. " "
end
end
return r
end,
}