empire-core 0.7.3__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- empire_core/__init__.py +36 -0
- empire_core/_archive/actions.py +511 -0
- empire_core/_archive/automation/__init__.py +24 -0
- empire_core/_archive/automation/alliance_tools.py +266 -0
- empire_core/_archive/automation/battle_reports.py +196 -0
- empire_core/_archive/automation/building_queue.py +242 -0
- empire_core/_archive/automation/defense_manager.py +124 -0
- empire_core/_archive/automation/map_scanner.py +370 -0
- empire_core/_archive/automation/multi_account.py +296 -0
- empire_core/_archive/automation/quest_automation.py +94 -0
- empire_core/_archive/automation/resource_manager.py +380 -0
- empire_core/_archive/automation/target_finder.py +153 -0
- empire_core/_archive/automation/tasks.py +224 -0
- empire_core/_archive/automation/unit_production.py +719 -0
- empire_core/_archive/cli.py +68 -0
- empire_core/_archive/client_async.py +469 -0
- empire_core/_archive/commands.py +201 -0
- empire_core/_archive/connection_async.py +228 -0
- empire_core/_archive/defense.py +156 -0
- empire_core/_archive/events/__init__.py +35 -0
- empire_core/_archive/events/base.py +153 -0
- empire_core/_archive/events/manager.py +85 -0
- empire_core/accounts.py +190 -0
- empire_core/client/__init__.py +0 -0
- empire_core/client/client.py +459 -0
- empire_core/config.py +87 -0
- empire_core/exceptions.py +42 -0
- empire_core/network/__init__.py +0 -0
- empire_core/network/connection.py +378 -0
- empire_core/protocol/__init__.py +0 -0
- empire_core/protocol/models/__init__.py +339 -0
- empire_core/protocol/models/alliance.py +186 -0
- empire_core/protocol/models/army.py +444 -0
- empire_core/protocol/models/attack.py +229 -0
- empire_core/protocol/models/auth.py +216 -0
- empire_core/protocol/models/base.py +403 -0
- empire_core/protocol/models/building.py +455 -0
- empire_core/protocol/models/castle.py +317 -0
- empire_core/protocol/models/chat.py +150 -0
- empire_core/protocol/models/defense.py +300 -0
- empire_core/protocol/models/map.py +269 -0
- empire_core/protocol/packet.py +104 -0
- empire_core/services/__init__.py +31 -0
- empire_core/services/alliance.py +222 -0
- empire_core/services/base.py +107 -0
- empire_core/services/castle.py +221 -0
- empire_core/state/__init__.py +0 -0
- empire_core/state/manager.py +398 -0
- empire_core/state/models.py +215 -0
- empire_core/state/quest_models.py +60 -0
- empire_core/state/report_models.py +115 -0
- empire_core/state/unit_models.py +75 -0
- empire_core/state/world_models.py +269 -0
- empire_core/storage/__init__.py +1 -0
- empire_core/storage/database.py +237 -0
- empire_core/utils/__init__.py +0 -0
- empire_core/utils/battle_sim.py +172 -0
- empire_core/utils/calculations.py +170 -0
- empire_core/utils/crypto.py +8 -0
- empire_core/utils/decorators.py +69 -0
- empire_core/utils/enums.py +111 -0
- empire_core/utils/helpers.py +252 -0
- empire_core/utils/response_awaiter.py +153 -0
- empire_core/utils/troops.py +93 -0
- empire_core-0.7.3.dist-info/METADATA +197 -0
- empire_core-0.7.3.dist-info/RECORD +67 -0
- empire_core-0.7.3.dist-info/WHEEL +4 -0
|
@@ -0,0 +1,378 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Synchronous WebSocket connection for EmpireCore.
|
|
3
|
+
|
|
4
|
+
Uses websocket-client library with a dedicated receive thread.
|
|
5
|
+
Designed to work well with Discord.py by not competing for the event loop.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
import logging
|
|
9
|
+
import threading
|
|
10
|
+
import time
|
|
11
|
+
from dataclasses import dataclass, field
|
|
12
|
+
from typing import Callable, Dict, List, Optional
|
|
13
|
+
|
|
14
|
+
import websocket
|
|
15
|
+
|
|
16
|
+
from empire_core.protocol.packet import Packet
|
|
17
|
+
|
|
18
|
+
logger = logging.getLogger(__name__)
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
@dataclass
|
|
22
|
+
class ResponseWaiter:
|
|
23
|
+
"""A waiter for a specific command response."""
|
|
24
|
+
|
|
25
|
+
event: threading.Event = field(default_factory=threading.Event)
|
|
26
|
+
result: Optional[Packet] = None
|
|
27
|
+
error: Optional[Exception] = None
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
class Connection:
|
|
31
|
+
"""
|
|
32
|
+
Synchronous WebSocket connection with threaded message routing.
|
|
33
|
+
|
|
34
|
+
Features:
|
|
35
|
+
- Request/response pattern via waiters (consumed on match)
|
|
36
|
+
- Pub/sub pattern via subscribers (broadcast to all)
|
|
37
|
+
- Automatic keepalive thread
|
|
38
|
+
- Thread-safe operations
|
|
39
|
+
"""
|
|
40
|
+
|
|
41
|
+
def __init__(self, url: str):
|
|
42
|
+
self.url = url
|
|
43
|
+
self.ws: Optional[websocket.WebSocket] = None
|
|
44
|
+
|
|
45
|
+
self._running = False
|
|
46
|
+
self._recv_thread: Optional[threading.Thread] = None
|
|
47
|
+
self._keepalive_thread: Optional[threading.Thread] = None
|
|
48
|
+
|
|
49
|
+
# Request/response waiters: cmd_id -> ResponseWaiter
|
|
50
|
+
# These are consumed when matched (one response per waiter)
|
|
51
|
+
self._waiters: Dict[str, List[ResponseWaiter]] = {}
|
|
52
|
+
self._waiters_lock = threading.Lock()
|
|
53
|
+
|
|
54
|
+
# Pub/sub subscribers: cmd_id -> list of callbacks
|
|
55
|
+
# These receive copies of all matching packets
|
|
56
|
+
self._subscribers: Dict[str, List[Callable[[Packet], None]]] = {}
|
|
57
|
+
self._subscribers_lock = threading.Lock()
|
|
58
|
+
|
|
59
|
+
# Global packet handler (for state updates, etc.)
|
|
60
|
+
self.on_packet: Optional[Callable[[Packet], None]] = None
|
|
61
|
+
|
|
62
|
+
# Disconnect callback
|
|
63
|
+
self.on_disconnect: Optional[Callable[[], None]] = None
|
|
64
|
+
|
|
65
|
+
@property
|
|
66
|
+
def connected(self) -> bool:
|
|
67
|
+
"""Check if connection is active."""
|
|
68
|
+
return self.ws is not None and self.ws.connected and self._running
|
|
69
|
+
|
|
70
|
+
def connect(self, timeout: float = 10.0) -> None:
|
|
71
|
+
"""
|
|
72
|
+
Connect to the WebSocket server.
|
|
73
|
+
|
|
74
|
+
Args:
|
|
75
|
+
timeout: Connection timeout in seconds
|
|
76
|
+
"""
|
|
77
|
+
if self.connected:
|
|
78
|
+
logger.warning("Already connected")
|
|
79
|
+
return
|
|
80
|
+
|
|
81
|
+
logger.info(f"Connecting to {self.url}...")
|
|
82
|
+
|
|
83
|
+
self.ws = websocket.WebSocket()
|
|
84
|
+
self.ws.settimeout(timeout)
|
|
85
|
+
|
|
86
|
+
try:
|
|
87
|
+
self.ws.connect(self.url)
|
|
88
|
+
self._running = True
|
|
89
|
+
|
|
90
|
+
# Start receive thread
|
|
91
|
+
self._recv_thread = threading.Thread(
|
|
92
|
+
target=self._recv_loop,
|
|
93
|
+
name="EmpireCore-Recv",
|
|
94
|
+
daemon=True,
|
|
95
|
+
)
|
|
96
|
+
self._recv_thread.start()
|
|
97
|
+
|
|
98
|
+
# Start keepalive thread
|
|
99
|
+
self._keepalive_thread = threading.Thread(
|
|
100
|
+
target=self._keepalive_loop,
|
|
101
|
+
name="EmpireCore-Keepalive",
|
|
102
|
+
daemon=True,
|
|
103
|
+
)
|
|
104
|
+
self._keepalive_thread.start()
|
|
105
|
+
|
|
106
|
+
logger.info("Connected successfully")
|
|
107
|
+
|
|
108
|
+
except Exception as e:
|
|
109
|
+
logger.error(f"Connection failed: {e}")
|
|
110
|
+
self._cleanup()
|
|
111
|
+
raise
|
|
112
|
+
|
|
113
|
+
def disconnect(self) -> None:
|
|
114
|
+
"""Disconnect from the server and cleanup resources."""
|
|
115
|
+
if not self._running:
|
|
116
|
+
return
|
|
117
|
+
|
|
118
|
+
logger.info("Disconnecting...")
|
|
119
|
+
self._running = False
|
|
120
|
+
|
|
121
|
+
# Cancel all waiters
|
|
122
|
+
self._cancel_all_waiters()
|
|
123
|
+
|
|
124
|
+
# Close websocket
|
|
125
|
+
self._cleanup()
|
|
126
|
+
|
|
127
|
+
# Wait for threads to finish
|
|
128
|
+
if self._recv_thread and self._recv_thread.is_alive():
|
|
129
|
+
self._recv_thread.join(timeout=2.0)
|
|
130
|
+
if self._keepalive_thread and self._keepalive_thread.is_alive():
|
|
131
|
+
self._keepalive_thread.join(timeout=2.0)
|
|
132
|
+
|
|
133
|
+
logger.info("Disconnected")
|
|
134
|
+
|
|
135
|
+
def _cleanup(self) -> None:
|
|
136
|
+
"""Close websocket connection."""
|
|
137
|
+
if self.ws:
|
|
138
|
+
try:
|
|
139
|
+
self.ws.close()
|
|
140
|
+
except Exception:
|
|
141
|
+
pass
|
|
142
|
+
self.ws = None
|
|
143
|
+
|
|
144
|
+
def send(self, data: str) -> None:
|
|
145
|
+
"""
|
|
146
|
+
Send data to the server.
|
|
147
|
+
|
|
148
|
+
Args:
|
|
149
|
+
data: String data to send
|
|
150
|
+
|
|
151
|
+
Raises:
|
|
152
|
+
RuntimeError: If not connected
|
|
153
|
+
"""
|
|
154
|
+
if not self.connected:
|
|
155
|
+
raise RuntimeError("Not connected")
|
|
156
|
+
|
|
157
|
+
# Remove null terminator if present (we'll add it)
|
|
158
|
+
if data.endswith("\x00"):
|
|
159
|
+
data = data[:-1]
|
|
160
|
+
|
|
161
|
+
try:
|
|
162
|
+
if self.ws is None:
|
|
163
|
+
raise RuntimeError("Not connected")
|
|
164
|
+
self.ws.send(data)
|
|
165
|
+
logger.debug(f"Sent: {data[:100]}...")
|
|
166
|
+
except Exception as e:
|
|
167
|
+
logger.error(f"Send failed: {e}")
|
|
168
|
+
raise
|
|
169
|
+
|
|
170
|
+
def send_bytes(self, data: bytes) -> None:
|
|
171
|
+
"""Send raw bytes to the server."""
|
|
172
|
+
self.send(data.decode("utf-8"))
|
|
173
|
+
|
|
174
|
+
def wait_for(
|
|
175
|
+
self,
|
|
176
|
+
cmd_id: str,
|
|
177
|
+
timeout: float = 5.0,
|
|
178
|
+
) -> Packet:
|
|
179
|
+
"""
|
|
180
|
+
Wait for a response with the given command ID.
|
|
181
|
+
|
|
182
|
+
This is a blocking call that waits for a matching packet.
|
|
183
|
+
The waiter is consumed when a match is found.
|
|
184
|
+
|
|
185
|
+
Args:
|
|
186
|
+
cmd_id: Command ID to wait for
|
|
187
|
+
timeout: Timeout in seconds
|
|
188
|
+
|
|
189
|
+
Returns:
|
|
190
|
+
The matching Packet
|
|
191
|
+
|
|
192
|
+
Raises:
|
|
193
|
+
TimeoutError: If no response within timeout
|
|
194
|
+
RuntimeError: If connection closed while waiting
|
|
195
|
+
"""
|
|
196
|
+
waiter = ResponseWaiter()
|
|
197
|
+
|
|
198
|
+
with self._waiters_lock:
|
|
199
|
+
if cmd_id not in self._waiters:
|
|
200
|
+
self._waiters[cmd_id] = []
|
|
201
|
+
self._waiters[cmd_id].append(waiter)
|
|
202
|
+
|
|
203
|
+
try:
|
|
204
|
+
if waiter.event.wait(timeout=timeout):
|
|
205
|
+
if waiter.error:
|
|
206
|
+
raise waiter.error
|
|
207
|
+
if waiter.result:
|
|
208
|
+
return waiter.result
|
|
209
|
+
raise RuntimeError("Waiter completed without result")
|
|
210
|
+
else:
|
|
211
|
+
raise TimeoutError(f"Timeout waiting for '{cmd_id}'")
|
|
212
|
+
finally:
|
|
213
|
+
# Clean up waiter
|
|
214
|
+
with self._waiters_lock:
|
|
215
|
+
if cmd_id in self._waiters:
|
|
216
|
+
try:
|
|
217
|
+
self._waiters[cmd_id].remove(waiter)
|
|
218
|
+
if not self._waiters[cmd_id]:
|
|
219
|
+
del self._waiters[cmd_id]
|
|
220
|
+
except ValueError:
|
|
221
|
+
pass
|
|
222
|
+
|
|
223
|
+
def subscribe(self, cmd_id: str, callback: Callable[[Packet], None]) -> None:
|
|
224
|
+
"""
|
|
225
|
+
Subscribe to packets with the given command ID.
|
|
226
|
+
|
|
227
|
+
Unlike waiters, subscribers receive ALL matching packets
|
|
228
|
+
and are not consumed.
|
|
229
|
+
|
|
230
|
+
Args:
|
|
231
|
+
cmd_id: Command ID to subscribe to
|
|
232
|
+
callback: Function to call with matching packets
|
|
233
|
+
"""
|
|
234
|
+
with self._subscribers_lock:
|
|
235
|
+
if cmd_id not in self._subscribers:
|
|
236
|
+
self._subscribers[cmd_id] = []
|
|
237
|
+
self._subscribers[cmd_id].append(callback)
|
|
238
|
+
|
|
239
|
+
def unsubscribe(self, cmd_id: str, callback: Callable[[Packet], None]) -> None:
|
|
240
|
+
"""Remove a subscriber."""
|
|
241
|
+
with self._subscribers_lock:
|
|
242
|
+
if cmd_id in self._subscribers:
|
|
243
|
+
try:
|
|
244
|
+
self._subscribers[cmd_id].remove(callback)
|
|
245
|
+
if not self._subscribers[cmd_id]:
|
|
246
|
+
del self._subscribers[cmd_id]
|
|
247
|
+
except ValueError:
|
|
248
|
+
pass
|
|
249
|
+
|
|
250
|
+
def _recv_loop(self) -> None:
|
|
251
|
+
"""Background thread that receives and routes messages."""
|
|
252
|
+
logger.debug("Receive loop started")
|
|
253
|
+
|
|
254
|
+
while self._running:
|
|
255
|
+
try:
|
|
256
|
+
if not self.ws:
|
|
257
|
+
break
|
|
258
|
+
|
|
259
|
+
# Set a timeout so we can check _running periodically
|
|
260
|
+
self.ws.settimeout(1.0)
|
|
261
|
+
|
|
262
|
+
try:
|
|
263
|
+
data = self.ws.recv()
|
|
264
|
+
except websocket.WebSocketTimeoutException:
|
|
265
|
+
continue # Check _running and try again
|
|
266
|
+
|
|
267
|
+
if not data:
|
|
268
|
+
continue
|
|
269
|
+
|
|
270
|
+
# Parse packet
|
|
271
|
+
if isinstance(data, bytes):
|
|
272
|
+
packet = Packet.from_bytes(data)
|
|
273
|
+
else:
|
|
274
|
+
packet = Packet.from_bytes(data.encode("utf-8"))
|
|
275
|
+
|
|
276
|
+
# Route the packet
|
|
277
|
+
self._route_packet(packet)
|
|
278
|
+
|
|
279
|
+
except websocket.WebSocketConnectionClosedException:
|
|
280
|
+
logger.warning("Connection closed by server")
|
|
281
|
+
break
|
|
282
|
+
except Exception as e:
|
|
283
|
+
if self._running:
|
|
284
|
+
logger.error(f"Error in receive loop: {e}")
|
|
285
|
+
break
|
|
286
|
+
|
|
287
|
+
# Connection lost
|
|
288
|
+
self._running = False
|
|
289
|
+
self._cancel_all_waiters()
|
|
290
|
+
|
|
291
|
+
if self.on_disconnect:
|
|
292
|
+
try:
|
|
293
|
+
self.on_disconnect()
|
|
294
|
+
except Exception as e:
|
|
295
|
+
logger.error(f"Error in disconnect callback: {e}")
|
|
296
|
+
|
|
297
|
+
logger.debug("Receive loop ended")
|
|
298
|
+
|
|
299
|
+
def _route_packet(self, packet: Packet) -> None:
|
|
300
|
+
"""
|
|
301
|
+
Route a packet to waiters and subscribers.
|
|
302
|
+
|
|
303
|
+
Order:
|
|
304
|
+
1. Check waiters (consumed on match)
|
|
305
|
+
2. Notify subscribers (broadcast)
|
|
306
|
+
3. Call global handler
|
|
307
|
+
|
|
308
|
+
Uses copy-on-read pattern to minimize lock hold time.
|
|
309
|
+
"""
|
|
310
|
+
cmd_id = packet.command_id
|
|
311
|
+
|
|
312
|
+
waiter = None
|
|
313
|
+
callbacks = None
|
|
314
|
+
|
|
315
|
+
# Acquire locks briefly just to extract what we need
|
|
316
|
+
if cmd_id:
|
|
317
|
+
# Check waiters (request/response pattern)
|
|
318
|
+
with self._waiters_lock:
|
|
319
|
+
waiters_list = self._waiters.get(cmd_id)
|
|
320
|
+
if waiters_list:
|
|
321
|
+
waiter = waiters_list.pop(0)
|
|
322
|
+
if not waiters_list:
|
|
323
|
+
del self._waiters[cmd_id]
|
|
324
|
+
|
|
325
|
+
# Get subscriber callbacks (copy the list)
|
|
326
|
+
with self._subscribers_lock:
|
|
327
|
+
subs = self._subscribers.get(cmd_id)
|
|
328
|
+
if subs:
|
|
329
|
+
callbacks = list(subs)
|
|
330
|
+
|
|
331
|
+
# Now dispatch outside of locks
|
|
332
|
+
if waiter:
|
|
333
|
+
waiter.result = packet
|
|
334
|
+
waiter.event.set()
|
|
335
|
+
|
|
336
|
+
if callbacks:
|
|
337
|
+
for callback in callbacks:
|
|
338
|
+
try:
|
|
339
|
+
callback(packet)
|
|
340
|
+
except Exception as e:
|
|
341
|
+
logger.error(f"Subscriber error: {e}")
|
|
342
|
+
|
|
343
|
+
# Global handler
|
|
344
|
+
if self.on_packet:
|
|
345
|
+
try:
|
|
346
|
+
self.on_packet(packet)
|
|
347
|
+
except Exception as e:
|
|
348
|
+
logger.error(f"Packet handler error: {e}")
|
|
349
|
+
|
|
350
|
+
def _keepalive_loop(self) -> None:
|
|
351
|
+
"""Background thread that sends keepalive pings."""
|
|
352
|
+
logger.debug("Keepalive loop started")
|
|
353
|
+
|
|
354
|
+
while self._running:
|
|
355
|
+
time.sleep(30)
|
|
356
|
+
|
|
357
|
+
if not self._running:
|
|
358
|
+
break
|
|
359
|
+
|
|
360
|
+
try:
|
|
361
|
+
# Send GGE-specific keepalive
|
|
362
|
+
self.send("%xt%EmpireEx_21%pin%1%<RoundHouseKick>%")
|
|
363
|
+
logger.debug("Sent keepalive ping")
|
|
364
|
+
except Exception as e:
|
|
365
|
+
if self._running:
|
|
366
|
+
logger.error(f"Keepalive failed: {e}")
|
|
367
|
+
break
|
|
368
|
+
|
|
369
|
+
logger.debug("Keepalive loop ended")
|
|
370
|
+
|
|
371
|
+
def _cancel_all_waiters(self) -> None:
|
|
372
|
+
"""Cancel all pending waiters."""
|
|
373
|
+
with self._waiters_lock:
|
|
374
|
+
for waiters in self._waiters.values():
|
|
375
|
+
for waiter in waiters:
|
|
376
|
+
waiter.error = RuntimeError("Connection closed")
|
|
377
|
+
waiter.event.set()
|
|
378
|
+
self._waiters.clear()
|
|
File without changes
|
|
@@ -0,0 +1,339 @@
|
|
|
1
|
+
"""
|
|
2
|
+
GGE Protocol Models - Pydantic models for Goodgame Empire protocol commands.
|
|
3
|
+
|
|
4
|
+
This package contains type-safe models for all GGE protocol commands extracted
|
|
5
|
+
from pygge and GGE-BOT implementations.
|
|
6
|
+
|
|
7
|
+
Structure:
|
|
8
|
+
- base.py: Base classes and common types
|
|
9
|
+
- auth.py: Authentication commands (lli, lre, vpn, vln, etc.)
|
|
10
|
+
- chat.py: Alliance chat commands (acm, acl)
|
|
11
|
+
- alliance.py: Alliance commands (ahc, aha, ahr)
|
|
12
|
+
- castle.py: Castle commands (gcl, dcl, jca, arc, etc.)
|
|
13
|
+
- map.py: Map commands (gaa, gam, fnm, adi, etc.)
|
|
14
|
+
- attack.py: Attack/spy commands (cra, csm, gas, etc.)
|
|
15
|
+
- building.py: Building commands (ebu, eup, emo, sbd, etc.)
|
|
16
|
+
- army.py: Army/soldier/hospital commands (bup, spl, gui, hru, etc.)
|
|
17
|
+
- defense.py: Defense commands (dfc, dfk, dfw, dfm)
|
|
18
|
+
|
|
19
|
+
TODO (lower priority):
|
|
20
|
+
- shop.py: Shop/purchase commands (sbp, gbc)
|
|
21
|
+
- events.py: Event commands (sei, pep, hgh, sede)
|
|
22
|
+
- gifts.py: Gift commands (clb, gpg)
|
|
23
|
+
- quests.py: Quest commands (qsc, qdr, fcq)
|
|
24
|
+
- account.py: Account commands (gpi, scp, vpm, cpne, etc.)
|
|
25
|
+
- settings.py: Settings commands (ani, mvf, opt, hfl)
|
|
26
|
+
- misc.py: Miscellaneous commands (txi, txs, txc, gbl, etc.)
|
|
27
|
+
"""
|
|
28
|
+
|
|
29
|
+
from .alliance import (
|
|
30
|
+
AskHelpRequest,
|
|
31
|
+
AskHelpResponse,
|
|
32
|
+
HelpAllRequest,
|
|
33
|
+
HelpAllResponse,
|
|
34
|
+
HelpMemberRequest,
|
|
35
|
+
HelpMemberResponse,
|
|
36
|
+
HelpRequestNotification,
|
|
37
|
+
)
|
|
38
|
+
from .army import (
|
|
39
|
+
CancelHealRequest,
|
|
40
|
+
CancelHealResponse,
|
|
41
|
+
CancelProductionRequest,
|
|
42
|
+
CancelProductionResponse,
|
|
43
|
+
DeleteUnitsRequest,
|
|
44
|
+
DeleteUnitsResponse,
|
|
45
|
+
DeleteWoundedRequest,
|
|
46
|
+
DeleteWoundedResponse,
|
|
47
|
+
DoubleProductionRequest,
|
|
48
|
+
DoubleProductionResponse,
|
|
49
|
+
GetProductionQueueRequest,
|
|
50
|
+
GetProductionQueueResponse,
|
|
51
|
+
GetUnitsRequest,
|
|
52
|
+
GetUnitsResponse,
|
|
53
|
+
HealAllRequest,
|
|
54
|
+
HealAllResponse,
|
|
55
|
+
HealUnitsRequest,
|
|
56
|
+
HealUnitsResponse,
|
|
57
|
+
ProduceUnitsRequest,
|
|
58
|
+
ProduceUnitsResponse,
|
|
59
|
+
ProductionQueueItem,
|
|
60
|
+
SkipHealRequest,
|
|
61
|
+
SkipHealResponse,
|
|
62
|
+
)
|
|
63
|
+
from .attack import (
|
|
64
|
+
AttackPreset,
|
|
65
|
+
CreateAttackRequest,
|
|
66
|
+
CreateAttackResponse,
|
|
67
|
+
GetPresetsRequest,
|
|
68
|
+
GetPresetsResponse,
|
|
69
|
+
SendSpyRequest,
|
|
70
|
+
SendSpyResponse,
|
|
71
|
+
SkipAttackCooldownRequest,
|
|
72
|
+
SkipAttackCooldownResponse,
|
|
73
|
+
SkipDefenseCooldownRequest,
|
|
74
|
+
SkipDefenseCooldownResponse,
|
|
75
|
+
)
|
|
76
|
+
from .auth import (
|
|
77
|
+
CheckUsernameAvailableRequest,
|
|
78
|
+
CheckUsernameAvailableResponse,
|
|
79
|
+
CheckUsernameExistsRequest,
|
|
80
|
+
CheckUsernameExistsResponse,
|
|
81
|
+
LoginRequest,
|
|
82
|
+
LoginResponse,
|
|
83
|
+
PasswordRecoveryRequest,
|
|
84
|
+
PasswordRecoveryResponse,
|
|
85
|
+
PlayerData,
|
|
86
|
+
RegisterRequest,
|
|
87
|
+
RegisterResponse,
|
|
88
|
+
)
|
|
89
|
+
from .base import (
|
|
90
|
+
DEFAULT_ZONE,
|
|
91
|
+
BasePayload,
|
|
92
|
+
BaseRequest,
|
|
93
|
+
BaseResponse,
|
|
94
|
+
ErrorResponse,
|
|
95
|
+
GGECommand,
|
|
96
|
+
HelpType,
|
|
97
|
+
PlayerInfo,
|
|
98
|
+
Position,
|
|
99
|
+
ProductionListType,
|
|
100
|
+
ResourceAmount,
|
|
101
|
+
UnitCount,
|
|
102
|
+
decode_chat_text,
|
|
103
|
+
encode_chat_text,
|
|
104
|
+
get_response_model,
|
|
105
|
+
parse_response,
|
|
106
|
+
)
|
|
107
|
+
from .building import (
|
|
108
|
+
BuildRequest,
|
|
109
|
+
BuildResponse,
|
|
110
|
+
BuyExtensionRequest,
|
|
111
|
+
BuyExtensionResponse,
|
|
112
|
+
CollectExtensionGiftRequest,
|
|
113
|
+
CollectExtensionGiftResponse,
|
|
114
|
+
DestroyBuildingRequest,
|
|
115
|
+
DestroyBuildingResponse,
|
|
116
|
+
FastCompleteRequest,
|
|
117
|
+
FastCompleteResponse,
|
|
118
|
+
MoveBuildingRequest,
|
|
119
|
+
MoveBuildingResponse,
|
|
120
|
+
RepairAllRequest,
|
|
121
|
+
RepairAllResponse,
|
|
122
|
+
RepairBuildingRequest,
|
|
123
|
+
RepairBuildingResponse,
|
|
124
|
+
SellBuildingRequest,
|
|
125
|
+
SellBuildingResponse,
|
|
126
|
+
TimeSkipBuildingRequest,
|
|
127
|
+
TimeSkipBuildingResponse,
|
|
128
|
+
UpgradeBuildingRequest,
|
|
129
|
+
UpgradeBuildingResponse,
|
|
130
|
+
UpgradeWallRequest,
|
|
131
|
+
UpgradeWallResponse,
|
|
132
|
+
)
|
|
133
|
+
from .castle import (
|
|
134
|
+
BuildingInfo,
|
|
135
|
+
CastleInfo,
|
|
136
|
+
DetailedCastleInfo,
|
|
137
|
+
GetCastlesRequest,
|
|
138
|
+
GetCastlesResponse,
|
|
139
|
+
GetDetailedCastleRequest,
|
|
140
|
+
GetDetailedCastleResponse,
|
|
141
|
+
GetProductionRequest,
|
|
142
|
+
GetProductionResponse,
|
|
143
|
+
GetResourcesRequest,
|
|
144
|
+
GetResourcesResponse,
|
|
145
|
+
ProductionRates,
|
|
146
|
+
RelocateCastleRequest,
|
|
147
|
+
RelocateCastleResponse,
|
|
148
|
+
RenameCastleRequest,
|
|
149
|
+
RenameCastleResponse,
|
|
150
|
+
SelectCastleRequest,
|
|
151
|
+
SelectCastleResponse,
|
|
152
|
+
)
|
|
153
|
+
from .chat import (
|
|
154
|
+
AllianceChatLogRequest,
|
|
155
|
+
AllianceChatLogResponse,
|
|
156
|
+
AllianceChatMessageRequest,
|
|
157
|
+
AllianceChatMessageResponse,
|
|
158
|
+
ChatLogEntry,
|
|
159
|
+
ChatMessageData,
|
|
160
|
+
)
|
|
161
|
+
from .defense import (
|
|
162
|
+
ChangeKeepDefenseRequest,
|
|
163
|
+
ChangeKeepDefenseResponse,
|
|
164
|
+
ChangeMoatDefenseRequest,
|
|
165
|
+
ChangeMoatDefenseResponse,
|
|
166
|
+
ChangeWallDefenseRequest,
|
|
167
|
+
ChangeWallDefenseResponse,
|
|
168
|
+
DefenseConfiguration,
|
|
169
|
+
GetDefenseRequest,
|
|
170
|
+
GetDefenseResponse,
|
|
171
|
+
GetSupportDefenseRequest,
|
|
172
|
+
GetSupportDefenseResponse,
|
|
173
|
+
)
|
|
174
|
+
from .map import (
|
|
175
|
+
FindNPCRequest,
|
|
176
|
+
FindNPCResponse,
|
|
177
|
+
GetMapAreaRequest,
|
|
178
|
+
GetMapAreaResponse,
|
|
179
|
+
GetMovementsRequest,
|
|
180
|
+
GetMovementsResponse,
|
|
181
|
+
GetTargetInfoRequest,
|
|
182
|
+
GetTargetInfoResponse,
|
|
183
|
+
MapObject,
|
|
184
|
+
Movement,
|
|
185
|
+
NPCLocation,
|
|
186
|
+
TargetInfo,
|
|
187
|
+
)
|
|
188
|
+
|
|
189
|
+
__all__ = [
|
|
190
|
+
# Base
|
|
191
|
+
"GGECommand",
|
|
192
|
+
"DEFAULT_ZONE",
|
|
193
|
+
"HelpType",
|
|
194
|
+
"ProductionListType",
|
|
195
|
+
"BasePayload",
|
|
196
|
+
"BaseRequest",
|
|
197
|
+
"BaseResponse",
|
|
198
|
+
"ErrorResponse",
|
|
199
|
+
"Position",
|
|
200
|
+
"ResourceAmount",
|
|
201
|
+
"UnitCount",
|
|
202
|
+
"PlayerInfo",
|
|
203
|
+
"encode_chat_text",
|
|
204
|
+
"decode_chat_text",
|
|
205
|
+
"get_response_model",
|
|
206
|
+
"parse_response",
|
|
207
|
+
# Auth
|
|
208
|
+
"LoginRequest",
|
|
209
|
+
"LoginResponse",
|
|
210
|
+
"PlayerData",
|
|
211
|
+
"RegisterRequest",
|
|
212
|
+
"RegisterResponse",
|
|
213
|
+
"CheckUsernameAvailableRequest",
|
|
214
|
+
"CheckUsernameAvailableResponse",
|
|
215
|
+
"CheckUsernameExistsRequest",
|
|
216
|
+
"CheckUsernameExistsResponse",
|
|
217
|
+
"PasswordRecoveryRequest",
|
|
218
|
+
"PasswordRecoveryResponse",
|
|
219
|
+
# Chat
|
|
220
|
+
"AllianceChatMessageRequest",
|
|
221
|
+
"AllianceChatMessageResponse",
|
|
222
|
+
"ChatMessageData",
|
|
223
|
+
"AllianceChatLogRequest",
|
|
224
|
+
"AllianceChatLogResponse",
|
|
225
|
+
"ChatLogEntry",
|
|
226
|
+
# Alliance
|
|
227
|
+
"HelpMemberRequest",
|
|
228
|
+
"HelpMemberResponse",
|
|
229
|
+
"HelpAllRequest",
|
|
230
|
+
"HelpAllResponse",
|
|
231
|
+
"AskHelpRequest",
|
|
232
|
+
"AskHelpResponse",
|
|
233
|
+
"HelpRequestNotification",
|
|
234
|
+
# Castle
|
|
235
|
+
"GetCastlesRequest",
|
|
236
|
+
"GetCastlesResponse",
|
|
237
|
+
"CastleInfo",
|
|
238
|
+
"GetDetailedCastleRequest",
|
|
239
|
+
"GetDetailedCastleResponse",
|
|
240
|
+
"DetailedCastleInfo",
|
|
241
|
+
"BuildingInfo",
|
|
242
|
+
"SelectCastleRequest",
|
|
243
|
+
"SelectCastleResponse",
|
|
244
|
+
"RenameCastleRequest",
|
|
245
|
+
"RenameCastleResponse",
|
|
246
|
+
"RelocateCastleRequest",
|
|
247
|
+
"RelocateCastleResponse",
|
|
248
|
+
"GetResourcesRequest",
|
|
249
|
+
"GetResourcesResponse",
|
|
250
|
+
"GetProductionRequest",
|
|
251
|
+
"GetProductionResponse",
|
|
252
|
+
"ProductionRates",
|
|
253
|
+
# Map
|
|
254
|
+
"GetMapAreaRequest",
|
|
255
|
+
"GetMapAreaResponse",
|
|
256
|
+
"MapObject",
|
|
257
|
+
"GetMovementsRequest",
|
|
258
|
+
"GetMovementsResponse",
|
|
259
|
+
"Movement",
|
|
260
|
+
"FindNPCRequest",
|
|
261
|
+
"FindNPCResponse",
|
|
262
|
+
"NPCLocation",
|
|
263
|
+
"GetTargetInfoRequest",
|
|
264
|
+
"GetTargetInfoResponse",
|
|
265
|
+
"TargetInfo",
|
|
266
|
+
# Attack
|
|
267
|
+
"CreateAttackRequest",
|
|
268
|
+
"CreateAttackResponse",
|
|
269
|
+
"SendSpyRequest",
|
|
270
|
+
"SendSpyResponse",
|
|
271
|
+
"GetPresetsRequest",
|
|
272
|
+
"GetPresetsResponse",
|
|
273
|
+
"AttackPreset",
|
|
274
|
+
"SkipAttackCooldownRequest",
|
|
275
|
+
"SkipAttackCooldownResponse",
|
|
276
|
+
"SkipDefenseCooldownRequest",
|
|
277
|
+
"SkipDefenseCooldownResponse",
|
|
278
|
+
# Building
|
|
279
|
+
"BuildRequest",
|
|
280
|
+
"BuildResponse",
|
|
281
|
+
"UpgradeBuildingRequest",
|
|
282
|
+
"UpgradeBuildingResponse",
|
|
283
|
+
"MoveBuildingRequest",
|
|
284
|
+
"MoveBuildingResponse",
|
|
285
|
+
"SellBuildingRequest",
|
|
286
|
+
"SellBuildingResponse",
|
|
287
|
+
"DestroyBuildingRequest",
|
|
288
|
+
"DestroyBuildingResponse",
|
|
289
|
+
"FastCompleteRequest",
|
|
290
|
+
"FastCompleteResponse",
|
|
291
|
+
"TimeSkipBuildingRequest",
|
|
292
|
+
"TimeSkipBuildingResponse",
|
|
293
|
+
"UpgradeWallRequest",
|
|
294
|
+
"UpgradeWallResponse",
|
|
295
|
+
"RepairBuildingRequest",
|
|
296
|
+
"RepairBuildingResponse",
|
|
297
|
+
"RepairAllRequest",
|
|
298
|
+
"RepairAllResponse",
|
|
299
|
+
"BuyExtensionRequest",
|
|
300
|
+
"BuyExtensionResponse",
|
|
301
|
+
"CollectExtensionGiftRequest",
|
|
302
|
+
"CollectExtensionGiftResponse",
|
|
303
|
+
# Army
|
|
304
|
+
"ProduceUnitsRequest",
|
|
305
|
+
"ProduceUnitsResponse",
|
|
306
|
+
"GetProductionQueueRequest",
|
|
307
|
+
"GetProductionQueueResponse",
|
|
308
|
+
"ProductionQueueItem",
|
|
309
|
+
"DoubleProductionRequest",
|
|
310
|
+
"DoubleProductionResponse",
|
|
311
|
+
"CancelProductionRequest",
|
|
312
|
+
"CancelProductionResponse",
|
|
313
|
+
"GetUnitsRequest",
|
|
314
|
+
"GetUnitsResponse",
|
|
315
|
+
"DeleteUnitsRequest",
|
|
316
|
+
"DeleteUnitsResponse",
|
|
317
|
+
"HealUnitsRequest",
|
|
318
|
+
"HealUnitsResponse",
|
|
319
|
+
"CancelHealRequest",
|
|
320
|
+
"CancelHealResponse",
|
|
321
|
+
"SkipHealRequest",
|
|
322
|
+
"SkipHealResponse",
|
|
323
|
+
"DeleteWoundedRequest",
|
|
324
|
+
"DeleteWoundedResponse",
|
|
325
|
+
"HealAllRequest",
|
|
326
|
+
"HealAllResponse",
|
|
327
|
+
# Defense
|
|
328
|
+
"GetDefenseRequest",
|
|
329
|
+
"GetDefenseResponse",
|
|
330
|
+
"DefenseConfiguration",
|
|
331
|
+
"ChangeKeepDefenseRequest",
|
|
332
|
+
"ChangeKeepDefenseResponse",
|
|
333
|
+
"ChangeWallDefenseRequest",
|
|
334
|
+
"ChangeWallDefenseResponse",
|
|
335
|
+
"ChangeMoatDefenseRequest",
|
|
336
|
+
"ChangeMoatDefenseResponse",
|
|
337
|
+
"GetSupportDefenseRequest",
|
|
338
|
+
"GetSupportDefenseResponse",
|
|
339
|
+
]
|