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,317 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Castle protocol models.
|
|
3
|
+
|
|
4
|
+
Commands:
|
|
5
|
+
- gcl: Get castles list
|
|
6
|
+
- dcl: Get detailed castle info
|
|
7
|
+
- jca: Jump to / select castle
|
|
8
|
+
- arc: Rename castle
|
|
9
|
+
- rst: Relocate castle
|
|
10
|
+
- grc: Get resources
|
|
11
|
+
- gpa: Get production rates
|
|
12
|
+
"""
|
|
13
|
+
|
|
14
|
+
from __future__ import annotations
|
|
15
|
+
|
|
16
|
+
from pydantic import ConfigDict, Field
|
|
17
|
+
|
|
18
|
+
from .base import BaseRequest, BaseResponse, Position, ResourceAmount
|
|
19
|
+
|
|
20
|
+
# =============================================================================
|
|
21
|
+
# GCL - Get Castles List
|
|
22
|
+
# =============================================================================
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
class GetCastlesRequest(BaseRequest):
|
|
26
|
+
"""
|
|
27
|
+
Get list of player's castles.
|
|
28
|
+
|
|
29
|
+
Command: gcl
|
|
30
|
+
Payload: {} (empty)
|
|
31
|
+
"""
|
|
32
|
+
|
|
33
|
+
command = "gcl"
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
class CastleInfo(BaseResponse):
|
|
37
|
+
"""Basic castle information."""
|
|
38
|
+
|
|
39
|
+
model_config = ConfigDict(populate_by_name=True, extra="allow")
|
|
40
|
+
|
|
41
|
+
castle_id: int = Field(alias="CID")
|
|
42
|
+
castle_name: str = Field(alias="CN")
|
|
43
|
+
x: int = Field(alias="X")
|
|
44
|
+
y: int = Field(alias="Y")
|
|
45
|
+
kingdom_id: int = Field(alias="KID", default=0)
|
|
46
|
+
castle_type: int = Field(alias="CT", default=0) # 0=main, 1=outpost, etc.
|
|
47
|
+
level: int = Field(alias="L", default=1)
|
|
48
|
+
|
|
49
|
+
@property
|
|
50
|
+
def position(self) -> Position:
|
|
51
|
+
"""Get castle position as Position object."""
|
|
52
|
+
return Position(X=self.x, Y=self.y, KID=self.kingdom_id)
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
class GetCastlesResponse(BaseResponse):
|
|
56
|
+
"""
|
|
57
|
+
Response containing list of player's castles.
|
|
58
|
+
|
|
59
|
+
Command: gcl
|
|
60
|
+
Payload: {"C": [castle_info, ...]}
|
|
61
|
+
"""
|
|
62
|
+
|
|
63
|
+
command = "gcl"
|
|
64
|
+
|
|
65
|
+
castles: list[CastleInfo] = Field(alias="C", default_factory=list)
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
# =============================================================================
|
|
69
|
+
# DCL - Get Detailed Castle Info
|
|
70
|
+
# =============================================================================
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
class GetDetailedCastleRequest(BaseRequest):
|
|
74
|
+
"""
|
|
75
|
+
Get detailed information about a specific castle.
|
|
76
|
+
|
|
77
|
+
Command: dcl
|
|
78
|
+
Payload: {"CID": castle_id}
|
|
79
|
+
"""
|
|
80
|
+
|
|
81
|
+
command = "dcl"
|
|
82
|
+
|
|
83
|
+
castle_id: int = Field(alias="CID")
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
class BuildingInfo(BaseResponse):
|
|
87
|
+
"""Building information within a castle."""
|
|
88
|
+
|
|
89
|
+
model_config = ConfigDict(populate_by_name=True, extra="allow")
|
|
90
|
+
|
|
91
|
+
building_id: int = Field(alias="BID")
|
|
92
|
+
building_type: int = Field(alias="BT")
|
|
93
|
+
level: int = Field(alias="L")
|
|
94
|
+
x: int = Field(alias="X")
|
|
95
|
+
y: int = Field(alias="Y")
|
|
96
|
+
status: int = Field(alias="S", default=0) # 0=normal, 1=upgrading, 2=damaged
|
|
97
|
+
health: int = Field(alias="H", default=100)
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
class DetailedCastleInfo(CastleInfo):
|
|
101
|
+
"""Detailed castle information including buildings and resources."""
|
|
102
|
+
|
|
103
|
+
buildings: list[BuildingInfo] = Field(alias="B", default_factory=list)
|
|
104
|
+
resources: ResourceAmount | None = Field(alias="R", default=None)
|
|
105
|
+
population: int = Field(alias="P", default=0)
|
|
106
|
+
max_population: int = Field(alias="MP", default=0)
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
class GetDetailedCastleResponse(BaseResponse):
|
|
110
|
+
"""
|
|
111
|
+
Response containing detailed castle information.
|
|
112
|
+
|
|
113
|
+
Command: dcl
|
|
114
|
+
"""
|
|
115
|
+
|
|
116
|
+
command = "dcl"
|
|
117
|
+
|
|
118
|
+
castle: DetailedCastleInfo | None = Field(alias="C", default=None)
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
# =============================================================================
|
|
122
|
+
# JCA - Jump to Castle / Select Castle
|
|
123
|
+
# =============================================================================
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
class SelectCastleRequest(BaseRequest):
|
|
127
|
+
"""
|
|
128
|
+
Select/jump to a castle (makes it the active castle).
|
|
129
|
+
|
|
130
|
+
Command: jca
|
|
131
|
+
Payload: {"CID": castle_id}
|
|
132
|
+
"""
|
|
133
|
+
|
|
134
|
+
command = "jca"
|
|
135
|
+
|
|
136
|
+
castle_id: int = Field(alias="CID")
|
|
137
|
+
|
|
138
|
+
|
|
139
|
+
class SelectCastleResponse(BaseResponse):
|
|
140
|
+
"""
|
|
141
|
+
Response to castle selection.
|
|
142
|
+
|
|
143
|
+
Command: jca
|
|
144
|
+
"""
|
|
145
|
+
|
|
146
|
+
command = "jca"
|
|
147
|
+
|
|
148
|
+
success: bool = Field(default=True)
|
|
149
|
+
error_code: int = Field(alias="E", default=0)
|
|
150
|
+
|
|
151
|
+
|
|
152
|
+
# =============================================================================
|
|
153
|
+
# ARC - Rename Castle
|
|
154
|
+
# =============================================================================
|
|
155
|
+
|
|
156
|
+
|
|
157
|
+
class RenameCastleRequest(BaseRequest):
|
|
158
|
+
"""
|
|
159
|
+
Rename a castle.
|
|
160
|
+
|
|
161
|
+
Command: arc
|
|
162
|
+
Payload: {"CID": castle_id, "CN": "new_name"}
|
|
163
|
+
"""
|
|
164
|
+
|
|
165
|
+
command = "arc"
|
|
166
|
+
|
|
167
|
+
castle_id: int = Field(alias="CID")
|
|
168
|
+
castle_name: str = Field(alias="CN")
|
|
169
|
+
|
|
170
|
+
|
|
171
|
+
class RenameCastleResponse(BaseResponse):
|
|
172
|
+
"""
|
|
173
|
+
Response to castle rename.
|
|
174
|
+
|
|
175
|
+
Command: arc
|
|
176
|
+
"""
|
|
177
|
+
|
|
178
|
+
command = "arc"
|
|
179
|
+
|
|
180
|
+
success: bool = Field(default=True)
|
|
181
|
+
error_code: int = Field(alias="E", default=0)
|
|
182
|
+
|
|
183
|
+
|
|
184
|
+
# =============================================================================
|
|
185
|
+
# RST - Relocate Castle
|
|
186
|
+
# =============================================================================
|
|
187
|
+
|
|
188
|
+
|
|
189
|
+
class RelocateCastleRequest(BaseRequest):
|
|
190
|
+
"""
|
|
191
|
+
Relocate a castle to new coordinates.
|
|
192
|
+
|
|
193
|
+
Command: rst
|
|
194
|
+
Payload: {"CID": castle_id, "X": x, "Y": y, "KID": kingdom_id}
|
|
195
|
+
"""
|
|
196
|
+
|
|
197
|
+
command = "rst"
|
|
198
|
+
|
|
199
|
+
castle_id: int = Field(alias="CID")
|
|
200
|
+
x: int = Field(alias="X")
|
|
201
|
+
y: int = Field(alias="Y")
|
|
202
|
+
kingdom_id: int = Field(alias="KID", default=0)
|
|
203
|
+
|
|
204
|
+
|
|
205
|
+
class RelocateCastleResponse(BaseResponse):
|
|
206
|
+
"""
|
|
207
|
+
Response to castle relocation.
|
|
208
|
+
|
|
209
|
+
Command: rst
|
|
210
|
+
"""
|
|
211
|
+
|
|
212
|
+
command = "rst"
|
|
213
|
+
|
|
214
|
+
success: bool = Field(default=True)
|
|
215
|
+
error_code: int = Field(alias="E", default=0)
|
|
216
|
+
|
|
217
|
+
|
|
218
|
+
# =============================================================================
|
|
219
|
+
# GRC - Get Resources
|
|
220
|
+
# =============================================================================
|
|
221
|
+
|
|
222
|
+
|
|
223
|
+
class GetResourcesRequest(BaseRequest):
|
|
224
|
+
"""
|
|
225
|
+
Get current resources for a castle.
|
|
226
|
+
|
|
227
|
+
Command: grc
|
|
228
|
+
Payload: {"CID": castle_id}
|
|
229
|
+
"""
|
|
230
|
+
|
|
231
|
+
command = "grc"
|
|
232
|
+
|
|
233
|
+
castle_id: int = Field(alias="CID")
|
|
234
|
+
|
|
235
|
+
|
|
236
|
+
class GetResourcesResponse(BaseResponse):
|
|
237
|
+
"""
|
|
238
|
+
Response containing castle resources.
|
|
239
|
+
|
|
240
|
+
Command: grc
|
|
241
|
+
"""
|
|
242
|
+
|
|
243
|
+
command = "grc"
|
|
244
|
+
|
|
245
|
+
resources: ResourceAmount | None = Field(alias="R", default=None)
|
|
246
|
+
storage_capacity: ResourceAmount | None = Field(alias="SC", default=None)
|
|
247
|
+
|
|
248
|
+
|
|
249
|
+
# =============================================================================
|
|
250
|
+
# GPA - Get Production
|
|
251
|
+
# =============================================================================
|
|
252
|
+
|
|
253
|
+
|
|
254
|
+
class GetProductionRequest(BaseRequest):
|
|
255
|
+
"""
|
|
256
|
+
Get production rates for a castle.
|
|
257
|
+
|
|
258
|
+
Command: gpa
|
|
259
|
+
Payload: {"CID": castle_id}
|
|
260
|
+
"""
|
|
261
|
+
|
|
262
|
+
command = "gpa"
|
|
263
|
+
|
|
264
|
+
castle_id: int = Field(alias="CID")
|
|
265
|
+
|
|
266
|
+
|
|
267
|
+
class ProductionRates(BaseResponse):
|
|
268
|
+
"""Production rates per hour."""
|
|
269
|
+
|
|
270
|
+
model_config = ConfigDict(populate_by_name=True, extra="allow")
|
|
271
|
+
|
|
272
|
+
wood: float = Field(alias="W", default=0.0)
|
|
273
|
+
stone: float = Field(alias="S", default=0.0)
|
|
274
|
+
food: float = Field(alias="F", default=0.0)
|
|
275
|
+
coins: float = Field(alias="C", default=0.0)
|
|
276
|
+
|
|
277
|
+
|
|
278
|
+
class GetProductionResponse(BaseResponse):
|
|
279
|
+
"""
|
|
280
|
+
Response containing production rates.
|
|
281
|
+
|
|
282
|
+
Command: gpa
|
|
283
|
+
"""
|
|
284
|
+
|
|
285
|
+
command = "gpa"
|
|
286
|
+
|
|
287
|
+
production: ProductionRates | None = Field(alias="P", default=None)
|
|
288
|
+
consumption: ProductionRates | None = Field(alias="CO", default=None)
|
|
289
|
+
|
|
290
|
+
|
|
291
|
+
__all__ = [
|
|
292
|
+
# GCL - Get Castles
|
|
293
|
+
"GetCastlesRequest",
|
|
294
|
+
"GetCastlesResponse",
|
|
295
|
+
"CastleInfo",
|
|
296
|
+
# DCL - Detailed Castle
|
|
297
|
+
"GetDetailedCastleRequest",
|
|
298
|
+
"GetDetailedCastleResponse",
|
|
299
|
+
"DetailedCastleInfo",
|
|
300
|
+
"BuildingInfo",
|
|
301
|
+
# JCA - Select Castle
|
|
302
|
+
"SelectCastleRequest",
|
|
303
|
+
"SelectCastleResponse",
|
|
304
|
+
# ARC - Rename Castle
|
|
305
|
+
"RenameCastleRequest",
|
|
306
|
+
"RenameCastleResponse",
|
|
307
|
+
# RST - Relocate Castle
|
|
308
|
+
"RelocateCastleRequest",
|
|
309
|
+
"RelocateCastleResponse",
|
|
310
|
+
# GRC - Get Resources
|
|
311
|
+
"GetResourcesRequest",
|
|
312
|
+
"GetResourcesResponse",
|
|
313
|
+
# GPA - Get Production
|
|
314
|
+
"GetProductionRequest",
|
|
315
|
+
"GetProductionResponse",
|
|
316
|
+
"ProductionRates",
|
|
317
|
+
]
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Alliance chat protocol models.
|
|
3
|
+
|
|
4
|
+
Commands:
|
|
5
|
+
- acm: Send/receive alliance chat messages
|
|
6
|
+
- acl: Get alliance chat log/history
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from __future__ import annotations
|
|
10
|
+
|
|
11
|
+
from pydantic import BaseModel, ConfigDict, Field
|
|
12
|
+
|
|
13
|
+
from .base import BaseRequest, BaseResponse, decode_chat_text, encode_chat_text
|
|
14
|
+
|
|
15
|
+
# =============================================================================
|
|
16
|
+
# ACM - Alliance Chat Message
|
|
17
|
+
# =============================================================================
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class AllianceChatMessageRequest(BaseRequest):
|
|
21
|
+
"""
|
|
22
|
+
Request to send an alliance chat message.
|
|
23
|
+
|
|
24
|
+
Command: acm
|
|
25
|
+
Payload: {"M": "encoded_message_text"}
|
|
26
|
+
|
|
27
|
+
The message text must be encoded using encode_chat_text() before sending.
|
|
28
|
+
"""
|
|
29
|
+
|
|
30
|
+
command = "acm"
|
|
31
|
+
|
|
32
|
+
message: str = Field(alias="M")
|
|
33
|
+
|
|
34
|
+
@classmethod
|
|
35
|
+
def create(cls, text: str) -> "AllianceChatMessageRequest":
|
|
36
|
+
"""Create a chat message request with properly encoded text."""
|
|
37
|
+
return cls(M=encode_chat_text(text))
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
class ChatMessageData(BaseModel):
|
|
41
|
+
"""
|
|
42
|
+
The CM (Chat Message) data within an alliance chat response.
|
|
43
|
+
|
|
44
|
+
Contains the actual message content and sender info.
|
|
45
|
+
"""
|
|
46
|
+
|
|
47
|
+
model_config = ConfigDict(populate_by_name=True, extra="allow")
|
|
48
|
+
|
|
49
|
+
player_name: str = Field(alias="PN")
|
|
50
|
+
message_text: str = Field(alias="MT")
|
|
51
|
+
player_id: int = Field(alias="PID")
|
|
52
|
+
|
|
53
|
+
@property
|
|
54
|
+
def decoded_text(self) -> str:
|
|
55
|
+
"""Get the message text with special characters decoded."""
|
|
56
|
+
return decode_chat_text(self.message_text)
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
class AllianceChatMessageResponse(BaseResponse):
|
|
60
|
+
"""
|
|
61
|
+
Response containing an alliance chat message.
|
|
62
|
+
|
|
63
|
+
Command: acm
|
|
64
|
+
Payload: {"CM": {"PN": "player_name", "MT": "message_text", "PID": player_id}}
|
|
65
|
+
|
|
66
|
+
This is received when:
|
|
67
|
+
1. Another player sends a message to alliance chat
|
|
68
|
+
2. Confirmation of our own sent message
|
|
69
|
+
"""
|
|
70
|
+
|
|
71
|
+
command = "acm"
|
|
72
|
+
|
|
73
|
+
chat_message: ChatMessageData = Field(alias="CM")
|
|
74
|
+
|
|
75
|
+
@property
|
|
76
|
+
def player_name(self) -> str:
|
|
77
|
+
"""Get the sender's player name."""
|
|
78
|
+
return self.chat_message.player_name
|
|
79
|
+
|
|
80
|
+
@property
|
|
81
|
+
def message_text(self) -> str:
|
|
82
|
+
"""Get the raw message text (may contain encoded characters)."""
|
|
83
|
+
return self.chat_message.message_text
|
|
84
|
+
|
|
85
|
+
@property
|
|
86
|
+
def decoded_text(self) -> str:
|
|
87
|
+
"""Get the message text with special characters decoded."""
|
|
88
|
+
return self.chat_message.decoded_text
|
|
89
|
+
|
|
90
|
+
@property
|
|
91
|
+
def player_id(self) -> int:
|
|
92
|
+
"""Get the sender's player ID."""
|
|
93
|
+
return self.chat_message.player_id
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
# =============================================================================
|
|
97
|
+
# ACL - Alliance Chat Log
|
|
98
|
+
# =============================================================================
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
class AllianceChatLogRequest(BaseRequest):
|
|
102
|
+
"""
|
|
103
|
+
Request to get alliance chat history.
|
|
104
|
+
|
|
105
|
+
Command: acl
|
|
106
|
+
Payload: {} (empty)
|
|
107
|
+
"""
|
|
108
|
+
|
|
109
|
+
command = "acl"
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
class ChatLogEntry(BaseModel):
|
|
113
|
+
"""A single entry in the chat log history."""
|
|
114
|
+
|
|
115
|
+
model_config = ConfigDict(populate_by_name=True, extra="allow")
|
|
116
|
+
|
|
117
|
+
player_name: str = Field(alias="PN")
|
|
118
|
+
message_text: str = Field(alias="MT")
|
|
119
|
+
player_id: int = Field(alias="PID")
|
|
120
|
+
timestamp: int | None = Field(alias="T", default=None)
|
|
121
|
+
|
|
122
|
+
@property
|
|
123
|
+
def decoded_text(self) -> str:
|
|
124
|
+
"""Get the message text with special characters decoded."""
|
|
125
|
+
return decode_chat_text(self.message_text)
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
class AllianceChatLogResponse(BaseResponse):
|
|
129
|
+
"""
|
|
130
|
+
Response containing alliance chat history.
|
|
131
|
+
|
|
132
|
+
Command: acl
|
|
133
|
+
Payload: {"CL": [{"PN": "name", "MT": "text", "PID": id, "T": timestamp}, ...]}
|
|
134
|
+
"""
|
|
135
|
+
|
|
136
|
+
command = "acl"
|
|
137
|
+
|
|
138
|
+
chat_log: list[ChatLogEntry] = Field(alias="CL", default_factory=list)
|
|
139
|
+
|
|
140
|
+
|
|
141
|
+
__all__ = [
|
|
142
|
+
# ACM - Chat Message
|
|
143
|
+
"AllianceChatMessageRequest",
|
|
144
|
+
"AllianceChatMessageResponse",
|
|
145
|
+
"ChatMessageData",
|
|
146
|
+
# ACL - Chat Log
|
|
147
|
+
"AllianceChatLogRequest",
|
|
148
|
+
"AllianceChatLogResponse",
|
|
149
|
+
"ChatLogEntry",
|
|
150
|
+
]
|