1 package cz.cuni.amis.pogamut.udk.server.impl;
2
3 import java.util.Collection;
4 import java.util.List;
5 import java.util.logging.Level;
6 import java.util.logging.Logger;
7
8 import com.google.inject.Inject;
9
10 import cz.cuni.amis.pogamut.base.agent.IAgentId;
11 import cz.cuni.amis.pogamut.base.agent.state.impl.AgentStateStarting;
12 import cz.cuni.amis.pogamut.base.communication.command.IAct;
13 import cz.cuni.amis.pogamut.base.communication.connection.impl.socket.SocketConnection;
14 import cz.cuni.amis.pogamut.base.communication.connection.impl.socket.SocketConnectionAddress;
15 import cz.cuni.amis.pogamut.base.communication.worldview.IWorldView;
16 import cz.cuni.amis.pogamut.base.communication.worldview.event.IWorldEventListener;
17 import cz.cuni.amis.pogamut.base.component.bus.IComponentBus;
18 import cz.cuni.amis.pogamut.base.server.AbstractWorldServer;
19 import cz.cuni.amis.pogamut.base.utils.collections.adapters.WVVisibleObjectsSetAdapter;
20 import cz.cuni.amis.pogamut.base.utils.guice.AgentScoped;
21 import cz.cuni.amis.pogamut.base.utils.logging.IAgentLogger;
22 import cz.cuni.amis.pogamut.udk.bot.IUDKBot;
23 import cz.cuni.amis.pogamut.udk.bot.impl.NativeUDKBotAdapter;
24 import cz.cuni.amis.pogamut.udk.bot.jmx.BotJMXProxy;
25 import cz.cuni.amis.pogamut.udk.communication.messages.gbcommands.AddBot;
26 import cz.cuni.amis.pogamut.udk.communication.messages.gbcommands.GetMaps;
27 import cz.cuni.amis.pogamut.udk.communication.messages.gbcommands.PasswordReply;
28 import cz.cuni.amis.pogamut.udk.communication.messages.gbcommands.Ready;
29 import cz.cuni.amis.pogamut.udk.communication.messages.gbinfomessages.GameInfo;
30 import cz.cuni.amis.pogamut.udk.communication.messages.gbinfomessages.MapList;
31 import cz.cuni.amis.pogamut.udk.communication.messages.gbinfomessages.Mutator;
32 import cz.cuni.amis.pogamut.udk.communication.messages.gbinfomessages.Password;
33 import cz.cuni.amis.pogamut.udk.communication.messages.gbinfomessages.Player;
34 import cz.cuni.amis.pogamut.udk.communication.translator.shared.events.MapPointListObtained;
35 import cz.cuni.amis.pogamut.udk.communication.translator.shared.events.PlayerListObtained;
36 import cz.cuni.amis.pogamut.udk.communication.translator.shared.events.ReadyCommandRequest;
37 import cz.cuni.amis.pogamut.udk.communication.worldview.map.UDKMap;
38 import cz.cuni.amis.pogamut.udk.server.IUDKServer;
39 import cz.cuni.amis.utils.collections.ObservableCollection;
40 import cz.cuni.amis.utils.collections.TranslatedObservableCollection;
41 import cz.cuni.amis.utils.flag.Flag;
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65 @AgentScoped
66 public abstract class AbstractUDKServer<WORLD_VIEW extends IWorldView, ACT extends IAct> extends AbstractWorldServer<WORLD_VIEW, ACT, IUDKBot> implements IUDKServer {
67
68 ObservableCollection<Player> players = null;
69
70 List<Mutator> mutators = null;
71
72 Flag<Double> gameSpeed = new Flag<Double>();
73
74 List<MapList> maps = null;
75
76 Flag<String> mapName = new Flag<String>();
77
78 private UDKMap map;
79
80 ObservableCollection<? extends NativeUDKBotAdapter> nativeAgents = null;
81
82
83
84
85 ObservableCollection<IUDKBot> agents = null;
86
87
88
89
90
91 private String desiredPassword = null;
92
93 private IWorldEventListener<PlayerListObtained> playerListObtainedListener = new IWorldEventListener<PlayerListObtained>() {
94
95 @Override
96 public void notify(PlayerListObtained event) {
97 players.addAll(event.getPlayers());
98
99 }
100 };
101
102 private IWorldEventListener<MapPointListObtained> mapPointListObtainedListener = new IWorldEventListener<MapPointListObtained>() {
103
104 @Override
105 public void notify(MapPointListObtained event) {
106
107
108 getAct().act(new GetMaps());
109 }
110 };
111 private SocketConnection connection;
112
113 @Inject
114 public AbstractUDKServer(IAgentId agentId, IAgentLogger agentLogger,
115 IComponentBus bus, SocketConnection connection,
116 WORLD_VIEW worldView, ACT act) {
117 super(agentId, agentLogger, bus, worldView, act);
118
119 this.connection = connection;
120
121 getWorldView().addEventListener(ReadyCommandRequest.class, readyCommandRequestListener);
122 getWorldView().addEventListener(Password.class, passwordRequestedListener);
123
124
125 getWorldView().addEventListener(PlayerListObtained.class, playerListObtainedListener);
126
127 getWorldView().addEventListener(MapPointListObtained.class, mapPointListObtainedListener);
128
129 players = new WVVisibleObjectsSetAdapter<Player>(Player.class, getWorldView());
130 }
131
132 public void setAddress(String host, int port) {
133 if (log.isLoggable(Level.WARNING)) log.warning("Setting address to: " + host + ":" + port);
134 this.connection.setAddress(new SocketConnectionAddress(host, port));
135 }
136
137
138
139
140
141
142 public void setPassword(String password) {
143 this.desiredPassword = password;
144 }
145
146
147
148
149
150
151
152
153
154
155
156 protected void readyCommandRequested() {
157 getAct().act(new Ready());
158 }
159
160
161
162
163
164
165 private IWorldEventListener<ReadyCommandRequest> readyCommandRequestListener = new IWorldEventListener<ReadyCommandRequest>() {
166
167 @Override
168 public void notify(ReadyCommandRequest event) {
169 setState(new AgentStateStarting("GameBots2004 greeted us, sending READY."));
170 readyCommandRequested();
171 setState(new AgentStateStarting("READY sent."));
172 }
173 };
174
175
176
177
178
179
180
181
182
183
184
185
186
187 private PasswordReply passwordReply = null;
188
189
190
191
192
193
194
195
196
197
198
199 public PasswordReply getPasswordReply() {
200 return passwordReply;
201 }
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221 protected PasswordReply createPasswordReply() {
222 return desiredPassword != null ? new PasswordReply(desiredPassword)
223 : null;
224 }
225
226
227
228
229
230 private IWorldEventListener<Password> passwordRequestedListener = new IWorldEventListener<Password>() {
231
232 @Override
233 public void notify(Password event) {
234 setState(new AgentStateStarting("Password requested by the world."));
235 passwordReply = createPasswordReply();
236 if (passwordReply == null) {
237 passwordReply = new PasswordReply("");
238 }
239 if (log.isLoggable(Level.INFO)) log.info("Password required for the world, replying with '"
240 + passwordReply.getPassword() + "'.");
241 getAct().act(passwordReply);
242 }
243 };
244
245
246
247
248
249
250
251
252 private GameInfo gameInfo = null;
253
254 public GameInfo getGameInfo() {
255 if (gameInfo == null) {
256 gameInfo = getWorldView().getSingle(GameInfo.class);
257 }
258 return gameInfo;
259 }
260
261 @Override
262 public WORLD_VIEW getWorldView() {
263 return super.getWorldView();
264 }
265
266 @Override
267 public Collection<MapList> getAvailableMaps() {
268 return maps;
269 }
270
271 @Override
272 public Flag<Double> getGameSpeedFlag() {
273 return gameSpeed;
274 }
275
276 @Override
277 public String getMapName() {
278 if (getGameInfo() == null) return null;
279 return getGameInfo().getLevel();
280 }
281
282 @Override
283 public ObservableCollection<Player> getPlayers() {
284 return players;
285 }
286
287 @Override
288 public List<Mutator> getMutators() {
289 return mutators;
290 }
291
292 @Override
293 public ObservableCollection<IUDKBot> getAgents() {
294 if (agents != null) {
295 return agents;
296 }
297
298 if (getPlayers() == null) {
299
300 return null;
301 } else {
302 agents = new TranslatedObservableCollection<IUDKBot, Player>(
303 getPlayers()) {
304
305 @Override
306 protected IUDKBot translate(Player obj) {
307 if (obj.getJmx() != null) {
308 try {
309
310 return new BotJMXProxy(obj.getJmx());
311 } catch (Exception ex) {
312
313 Logger.getLogger(
314 AbstractUDKServer.class.getName()).log(
315 Level.SEVERE, "JMX error", ex);
316 throw new RuntimeException(ex);
317 }
318 } else {
319 return null;
320 }
321 }
322
323 @Override
324 protected Object getKeyForObj(Player elem) {
325 return elem.getId();
326 }
327 };
328 }
329 return agents;
330 }
331
332 @Override
333 public ObservableCollection<? extends NativeUDKBotAdapter> getNativeAgents() {
334 if (nativeAgents != null) {
335 return nativeAgents;
336 }
337
338 if (getPlayers() == null) {
339
340 return null;
341 } else {
342
343 nativeAgents = new TranslatedObservableCollection<NativeUDKBotAdapter, Player>(
344 getPlayers()) {
345
346 @Override
347 protected NativeUDKBotAdapter translate(Player obj) {
348 if (obj.getJmx() == null) {
349 try {
350
351 return new NativeUDKBotAdapter(obj,
352 AbstractUDKServer.this, getAct(),
353 getWorldView());
354 } catch (Exception ex) {
355
356 Logger.getLogger(
357 AbstractUDKServer.class.getName()).log(
358 Level.SEVERE, "JMX error", ex);
359 throw new RuntimeException(ex);
360 }
361 } else {
362 return null;
363 }
364 }
365
366 @Override
367 protected Object getKeyForObj(Player elem) {
368 return elem.getId();
369 }
370 };
371 }
372 return nativeAgents;
373
374 }
375
376 @Override
377 public void connectNativeBot(String botName, String botType) {
378 getAct().act(new AddBot(botName, null, null, 3, botType));
379 }
380
381 @Override
382 public UDKMap getMap() {
383 if (map == null) {
384 map = new UDKMap(getWorldView());
385 }
386 return map;
387 }
388
389
390
391
392
393
394
395
396
397
398 protected void reset() {
399 map = null;
400 gameInfo = null;
401 if (players != null) players.clear();
402 if (mutators != null) mutators.clear();
403 if (maps != null) maps.clear();
404 if (nativeAgents != null) nativeAgents.clear();
405 if (agents != null) agents.clear();
406 }
407
408 @Override
409 protected void resetAgent() {
410 super.resetAgent();
411 reset();
412 }
413
414 @Override
415 protected void stopAgent() {
416 super.stopAgent();
417 reset();
418 }
419
420 @Override
421 protected void killAgent() {
422 super.killAgent();
423 reset();
424 }
425
426 @Override
427 protected void startAgent() {
428 super.startAgent();
429 }
430
431 }