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.
Files changed (67) hide show
  1. empire_core/__init__.py +36 -0
  2. empire_core/_archive/actions.py +511 -0
  3. empire_core/_archive/automation/__init__.py +24 -0
  4. empire_core/_archive/automation/alliance_tools.py +266 -0
  5. empire_core/_archive/automation/battle_reports.py +196 -0
  6. empire_core/_archive/automation/building_queue.py +242 -0
  7. empire_core/_archive/automation/defense_manager.py +124 -0
  8. empire_core/_archive/automation/map_scanner.py +370 -0
  9. empire_core/_archive/automation/multi_account.py +296 -0
  10. empire_core/_archive/automation/quest_automation.py +94 -0
  11. empire_core/_archive/automation/resource_manager.py +380 -0
  12. empire_core/_archive/automation/target_finder.py +153 -0
  13. empire_core/_archive/automation/tasks.py +224 -0
  14. empire_core/_archive/automation/unit_production.py +719 -0
  15. empire_core/_archive/cli.py +68 -0
  16. empire_core/_archive/client_async.py +469 -0
  17. empire_core/_archive/commands.py +201 -0
  18. empire_core/_archive/connection_async.py +228 -0
  19. empire_core/_archive/defense.py +156 -0
  20. empire_core/_archive/events/__init__.py +35 -0
  21. empire_core/_archive/events/base.py +153 -0
  22. empire_core/_archive/events/manager.py +85 -0
  23. empire_core/accounts.py +190 -0
  24. empire_core/client/__init__.py +0 -0
  25. empire_core/client/client.py +459 -0
  26. empire_core/config.py +87 -0
  27. empire_core/exceptions.py +42 -0
  28. empire_core/network/__init__.py +0 -0
  29. empire_core/network/connection.py +378 -0
  30. empire_core/protocol/__init__.py +0 -0
  31. empire_core/protocol/models/__init__.py +339 -0
  32. empire_core/protocol/models/alliance.py +186 -0
  33. empire_core/protocol/models/army.py +444 -0
  34. empire_core/protocol/models/attack.py +229 -0
  35. empire_core/protocol/models/auth.py +216 -0
  36. empire_core/protocol/models/base.py +403 -0
  37. empire_core/protocol/models/building.py +455 -0
  38. empire_core/protocol/models/castle.py +317 -0
  39. empire_core/protocol/models/chat.py +150 -0
  40. empire_core/protocol/models/defense.py +300 -0
  41. empire_core/protocol/models/map.py +269 -0
  42. empire_core/protocol/packet.py +104 -0
  43. empire_core/services/__init__.py +31 -0
  44. empire_core/services/alliance.py +222 -0
  45. empire_core/services/base.py +107 -0
  46. empire_core/services/castle.py +221 -0
  47. empire_core/state/__init__.py +0 -0
  48. empire_core/state/manager.py +398 -0
  49. empire_core/state/models.py +215 -0
  50. empire_core/state/quest_models.py +60 -0
  51. empire_core/state/report_models.py +115 -0
  52. empire_core/state/unit_models.py +75 -0
  53. empire_core/state/world_models.py +269 -0
  54. empire_core/storage/__init__.py +1 -0
  55. empire_core/storage/database.py +237 -0
  56. empire_core/utils/__init__.py +0 -0
  57. empire_core/utils/battle_sim.py +172 -0
  58. empire_core/utils/calculations.py +170 -0
  59. empire_core/utils/crypto.py +8 -0
  60. empire_core/utils/decorators.py +69 -0
  61. empire_core/utils/enums.py +111 -0
  62. empire_core/utils/helpers.py +252 -0
  63. empire_core/utils/response_awaiter.py +153 -0
  64. empire_core/utils/troops.py +93 -0
  65. empire_core-0.7.3.dist-info/METADATA +197 -0
  66. empire_core-0.7.3.dist-info/RECORD +67 -0
  67. 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
+ ]