1 import math
2 import utils
3 import cocos
4
5 from cocos.actions.instant_actions import CallFuncS
6 from cocos.actions.interval_actions import MoveTo, Delay
7 from cocos.director import director
8 from twisted.internet.endpoints import TCP4ClientEndpoint, TCP4ServerEndpoint
9 from twisted.python.log import err
10
11 from clientController import ClientController, EndMenu
12 from commands import *
13 import constants
14 from constants import UNIT_STARTING_OPACITY, TIMER_Z
15 from maps import Vertex
16 from game_layers import InfoLayer, ActionButton,TransTimer, MenuButton
17 from models import *
18 from utils import get_action_button_clicked
19 from research import RESEARCH
20 from client import ServerNoteFactory
21 import music
22 from twisted.internet import reactor
23
24
25
26
27
29
31 super(ServerController, self).__init__(mapName)
32
33 self.pid = self.map.players.pop(0)
34
35 self.connectedClients = {}
36
37 self.connectedClientsIP = {}
38
39 self.gameStarted = False
40
41
42 self.curLevel = 1
43
44
45 '''
46 Local methods
47 '''
48
54
55
56
57
66
68 if actionName[0] == "B":
69 if actionName[1:] == "CPU":
70 for a in self.visibleASes:
71 if self.map.AS[a].cores:
72 k, core = self.map.AS[a].cores.popitem()
73 self.map.AS[a].usedCores[k] = core
74 self.build_unit(actionName[1:],self.player,core.vid, unit)
75 break
76 else:
77 self.build_unit(actionName[1:], self.player, unit.curVertex.vid, unit)
78 elif actionName[0] == "T":
79 self.build_unit(actionName[1:], self.player, unit.curVertex.vid)
80 elif actionName == "DEL":
81 self.remove_unit(unit)
82 elif actionName[0] == "R":
83 self.perform_research(actionName,self.player,unit)
84 elif actionName == "Ping":
85 unit.ping(self.remove_unit)
86 elif actionName == "UPingOfDeath":
87 self.upgrade_unit(unit,actionName[1:])
88 elif actionName == "UNMap":
89 self.upgrade_unit(unit,actionName[1:])
90 elif actionName == "USinkhole":
91 self.upgrade_unit(unit,actionName[1:])
92 elif actionName == "Shake":
93 self.curAction = "Shake"
94 self.selectedUnits = [unit]
95 elif actionName == "Attack":
96 self.curAction = "Attack"
97 self.selectedUnits = [unit]
98 elif actionName == "Decrypt":
99 self.upgrade_unit(unit,unit.originalType)
100 self.dispatch_event("click_on_action", actionName)
101
102 '''
103 Local/Network triggered methods
104 '''
105
108
110 if attacker == None:
111 if self.selectedUnits:
112 attacker = self.selectedUnits.pop()
113 if type(attacker) == BufferOverflow:
114
115 if type(target) == Vertex:
116 targetVertex = target
117 else:
118 targetVertex = target.curVertex
119
120 attacker.should_attack = 0
121
122 for troopSlot in targetVertex.troopSlots.values():
123 troop = troopSlot.troop
124 if troop.pid != attacker.pid:
125 attacker.should_attack += 1
126 attacker.attack(troop,self.map)
127 if targetVertex.building != None and targetVertex.building.pid != attacker.pid:
128 attacker.should_attack += 1
129 attacker.attack(targetVertex.building,self.map)
130
131 if attacker.should_attack == 0:
132 attacker.should_attack = 1
133
134 else:
135
136 attacker.attack(target,self.map)
137
138
139 - def build_unit(self, tid, owner, vid, builder=None,onInit=False):
140 curVertex = self.map.get_vertex(vid)
141 newUnit = self.build_unit_common(tid, owner, curVertex, builder=builder,onInit=onInit)
142
143 if newUnit and not onInit:
144
145 for pid in self.connectedClients.keys():
146 d = self.connect_end_point(self.connectedClients[pid])
147 def c(ampProto):
148 return ampProto.callRemote(BuildUnit, pid=owner.pid, tid=tid, vid=vid, uid=newUnit.uid,buid=-1)
149 d.addCallback(c)
150 d.addErrback(err)
151
152 if newUnit.buildTime != 0:
153 owner.underConstruction[newUnit.uid] = newUnit
154 newUnit.update_opacity(math.floor(curVertex.visibilityState) * UNIT_STARTING_OPACITY)
155
156 return newUnit
157
159
160 curVertex = oldUnit.curVertex
161 owner = self.players[oldUnit.pid]
162 self.remove_unit(oldUnit)
163 newUnit = self.build_unit(newType,owner,curVertex.vid)
164 if newType == "EncryptedTroop":
165 newUnit.originalType = oldUnit.__class__.__name__
166 return newUnit
167
168
170 if unit.isRemoved:
171
172
173 return
174 unit.do(CallFuncS(self.remove_unit_common))
175
176 for p in self.connectedClients.keys():
177 d = self.connect_end_point(self.connectedClients[p])
178
179 def c(ampProto):
180 return ampProto.callRemote(RemoveUnit, pid=unit.pid, uid=unit.uid)
181 d.addCallback(c)
182 d.addErrback(err)
183 reactor.callLater(10, d.cancel)
184
185
186
187 - def start_cpu(self,newUnit,owner,builder=None,researchF=None,upgradeFrom=None):
188
189 cpu = owner.idleCPUs.pop()
190
191 timer = TransTimer(newUnit.buildTime, pos=cpu.position)
192
193 if owner.pid == self.pid:
194 action = timer.get_move_action()
195 self.map.add(timer, z=TIMER_Z)
196 else:
197 action = Delay(newUnit.buildTime)
198 cpu.action = action
199 action += CallFunc(self.stop_cpu, cpu,owner)
200 if builder:
201 action += CallFunc(self.remove_unit,builder)
202 elif researchF:
203 action += CallFunc(self.finish_research, newUnit,owner,researchF)
204 if owner.pid == self.pid:
205 timer.do(action)
206 else:
207 self.do(action)
208
210 if owner.pid == self.pid:
211 utils.play_sound("Clock_end.wav")
212 owner.idleCPUs.append(cpu)
213
215 if issubclass(type(unit), Troop) and dest != unit.curVertex and dest.emptyTroopSlots and unit.isSelectable:
216
217 path = self.map.get_path(unit.curVertex, dest, pid, unit)
218
219
220 if not path:
221 utils.play_sound("firewall.wav")
222 return
223
224
225 sinkHoleIndex = -1
226 for i in range(1,len(path)):
227 vertID = path[i]
228 vert = self.map.vertices[vertID]
229 if vert.building != None and type(vert.building) == Sinkhole and type(unit) != EncryptedTroop and vert.building.pid != pid:
230 sinkHoleIndex = i
231 if sinkHoleIndex != -1:
232 dest = unit.curVertex
233 t = path[:sinkHoleIndex]
234 t.reverse()
235 path = path[:sinkHoleIndex + 1] + t
236
237
238 unit.isSelectable = False
239 unit.curVertex.remove_troop(unit)
240 slot = dest.add_trans_troop(unit)
241 unit.destVertex = dest
242 if unit.pid == self.pid:
243 self.dispatch_event("click_on_move", unit.__class__.__name__, dest.vid)
244
245
246 for p in self.connectedClients.keys():
247 d = self.connect_end_point(self.connectedClients[p])
248
249 def c(ampProto):
250 return ampProto.callRemote(MoveTroop, pid=pid, uid=unit.uid, vid=-1, path=path)
251 d.addCallback(c)
252 d.addErrback(err)
253 reactor.callLater(10, d.cancel)
254
255
256 if pid == self.pid:
257 utils.play_sound("Move.wav")
258 action = CallFuncS(self.cm.remove_tricky)
259 action += MoveTo(unit.curVertex.position, 0.2)
260 else:
261 action = MoveTo(unit.curVertex.position, 0.2)
262
263
264 for i in range(1, len(path)):
265 vertex = self.map.vertices[path[i]]
266 action += MoveTo(vertex.position, 1 / unit.speed)
267 action += CallFuncS(self.update_location, vertex.position, pid, vertex)
268 if i == sinkHoleIndex:
269 action += CallFunc(utils.play_sound, "Sinkhole.wav")
270 action += CallFunc(unit.on_attack,math.ceil(unit.health/3.0),vertex.building)
271 action += Delay(1)
272
273
274 if type(dest.building) != RSA or type(unit) == EncryptedTroop or dest.building.pid != unit.pid:
275 action += MoveTo(slot.position, 0.2)
276 action += CallFuncS(self.update_location, slot.position, pid)
277 else:
278 action += CallFuncS(self.upgrade_unit,"EncryptedTroop")
279 action += CallFuncS(self.cm.add)
280 unit.do(action)
281 return path
282 return []
283
285 if vertex:
286 unit.curVertex = vertex
287 if vertex.vid == unit.destVertex.vid:
288 vertex.set_trans_troop(unit)
289 self.client_update_location(unit.uid, vertex.vid, pid)
290 else:
291 unit.position = position
292 unit.cshape.center = position
293 unit.isSelectable = True
294
304
305
306
307 '''
308 Twisted client methods
309 '''
310
311
313 from twisted.internet import reactor
314 endpoint = TCP4ClientEndpoint(reactor, ip, 8750)
315 factory = ServerNoteFactory()
316 return endpoint.connect(factory)
317
319 for client_pid in self.connectedClients.keys():
320 d = self.connect_end_point(self.connectedClients[client_pid])
321
322 def c(ampProto):
323 return ampProto.callRemote(Attack, tpid=tpid, tuid=tuid, val=val)
324 d.addCallback(c)
325 d.addErrback(err)
326 reactor.callLater(10, d.cancel)
327
329 for client_pid in self.connectedClients.keys():
330 d = self.connect_end_point(self.connectedClients[client_pid])
331
332 def c(ampProto):
333 return ampProto.callRemote(AttackAnimation, pid=pid, uid=uid, tpid=tpid,tuid=tuid,path=path)
334 d.addCallback(c)
335 d.addErrback(err)
336 reactor.callLater(10, d.cancel)
337
339 for client_pid in self.connectedClients.keys():
340 d = self.connect_end_point(self.connectedClients[client_pid])
341
342 def c(ampProto):
343 if uid in self.players[pid].underConstruction.keys():
344 u = self.players[pid].underConstruction[uid]
345 else:
346 u = self.players[pid].units[uid]
347 return ampProto.callRemote(UpdateHealth, pid=pid, uid=uid, h=health,tid=u.tid,vid=u.curVertex.vid)
348 d.addCallback(c)
349 d.addErrback(err)
350 reactor.callLater(10, d.cancel)
351
353 for p in self.connectedClients.keys():
354 d = self.connect_end_point(self.connectedClients[p])
355
356 def c(ampProto):
357 return ampProto.callRemote(UpdateLocation, pid=pid, uid=uid, vid=vid)
358 d.addCallback(c)
359 d.addErrback(err)
360 reactor.callLater(10, d.cancel)
361
363 for pid in self.connectedClients.keys():
364 d = self.connect_end_point(self.connectedClients[pid])
365
366 def c(ampProto):
367 return ampProto.callRemote(AddPlayer, pid=newpid)
368 d.addCallback(c)
369 d.addErrback(err)
370 reactor.callLater(10, d.cancel)
371
373 for pid in self.connectedClients.keys():
374 d = self.connect_end_point(self.connectedClients[pid])
375 def c(ampProto):
376 return ampProto.callRemote(StartGame)
377 d.addCallback(c)
378 d.addErrback(err)
379 reactor.callLater(10, d.cancel)
380
381 '''
382 helper methods
383 '''
384
389