Army¶
Units, production and the hospital behind client.army.
army.service¶
Units, recruitment and the hospital of your castles.
Every command here acts on the castle the session has joined, so each method
joins the castle first (jca), as the client is inside a castle before it
shows the recruit or hospital dialog.
Action methods return True when the server accepted the action and False when it rejected it with an error code; transport failures (timeout, disconnect) raise. Query methods raise on any failure. A refused join raises before anything is sent.
Classes:
| Name | Description |
|---|---|
ArmyService |
Units, recruitment and the hospital of one of your castles. |
ArmyService
¶
Bases: BaseService
Units, recruitment and the hospital of one of your castles.
Reached as client.army.
Each method joins the castle it is given first (jca), as the client acts
on the castle it is in. It joins in that castle's Castle.kingdom_id from
client.state.get_castles(), and raises UnknownCastleError for a castle not listed there.
A castle id listed in several of your kingdoms raises AmbiguousCastleError.
Usage
Methods:
| Name | Description |
|---|---|
get_units |
Get the available unit inventory for a castle. |
get_units_response |
Get every unit inventory a castle reports. |
dismiss_units |
Dismiss units of the castle, or of its stronghold. |
produce_units |
Produce units or tools. |
get_production_list |
Get one production list of a castle: the slot producing now and the queue, |
cancel_production |
Cancel a production slot. |
double_production_slot |
Double the units of a production slot, for rubies; see "Spending rubies" in the guides. |
heal_units |
Queue wounded units for healing. |
heal_all |
Heal every wounded unit at once, for rubies; see "Spending rubies" in the guides. |
cancel_heal |
Cancel a hospital slot, by its |
skip_heal |
Finish a hospital slot now, by its |
dismiss_wounded |
Dismiss wounded units of one type instead of healing them. |
dismiss_wounded_units |
Dismiss wounded units of several types at once, as |
get_units
¶
Get the available unit inventory for a castle.
Covers soldiers and tools. Units in production, in the stronghold or in the hospital are reported separately - use get_units_response() for those.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
castle_id
|
int
|
One of your castles, a |
required |
timeout
|
float
|
Timeout in seconds |
5.0
|
Returns:
| Type | Description |
|---|---|
dict[UnitOrTool, int]
|
The castle's units and tools, |
get_units_response
¶
get_units_response(castle_id: int, timeout: float = 5.0) -> GetUnitsResponse
Get every unit inventory a castle reports.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
castle_id
|
int
|
One of your castles, a |
required |
timeout
|
float
|
Timeout in seconds |
5.0
|
Returns:
| Type | Description |
|---|---|
GetUnitsResponse
|
The full gui response: available, in production, stronghold, hospital |
Raises:
| Type | Description |
|---|---|
CommandError
|
The server refused to join the castle, so |
dismiss_units
¶
dismiss_units(castle_id: int, wod_id: int, amount: int, from_stronghold: bool = False, timeout: float = 5.0) -> bool
Dismiss units of the castle, or of its stronghold.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
castle_id
|
int
|
One of your castles, a |
required |
Client: CastleRecruitDismissUnitsDialog.dismissUnits (bundle line 84330)
produce_units
¶
produce_units(castle_id: int, list_id: ProductionListId, wod_id: int, amount: int, *, spend_rubies: bool = False, private_offer_id: int = -1, timeout: float = 5.0) -> bool
Produce units or tools.
Spends rubies when the unit or tool has a ruby price (cost_rubies or, on a temporary
server, temp_server_cost_rubies in the game data, refused on either kind of server), and
with spend_rubies on missing resources; see "Spending rubies" in the guides.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
castle_id
|
int
|
One of your castles, a |
required |
list_id
|
ProductionListId
|
SOLDIERS, TOOLS or AUXILIARIES |
required |
wod_id
|
int
|
Unit or tool wod id |
required |
amount
|
int
|
How many to produce |
required |
spend_rubies
|
bool
|
Allow a ruby price, and pay rubies for missing resources as the client's resource wait dialog does |
False
|
private_offer_id
|
int
|
With |
-1
|
timeout
|
float
|
Timeout in seconds |
5.0
|
Raises:
| Type | Description |
|---|---|
ValueError
|
The list is the hospital, or the unit has a ruby price or is not in the
game data, and |
GameDataNotLoadedError
|
|
Client: C2SBuyUnitPackageVO (bundle line 35277); BasicUnitVO.basicCostC2 (bundle line
19248); the ruby path is CastleResourceWaitDialogProperties.getResourceSkipCommand (bundle line 35218)
get_production_list
¶
get_production_list(castle_id: int, list_id: ProductionListId, timeout: float = 5.0) -> ProductionList
Get one production list of a castle: the slot producing now and the queue,
or the hospital slots for ProductionListId.HOSPITAL.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
castle_id
|
int
|
One of your castles, a |
required |
Client: C2SShowPackageListVO (bundle line 22860)
cancel_production
¶
cancel_production(castle_id: int, list_id: ProductionListId, slot_type: SlotType, position: int, timeout: float = 5.0) -> bool
Cancel a production slot.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
castle_id
|
int
|
One of your castles, a |
required |
slot_type
|
SlotType
|
PRODUCTION for the slot producing now, QUEUE for a queued one |
required |
position
|
int
|
0 for the slot producing now, else the slot's
|
required |
Client: CastleRecruitDialogUnits.onCancelCurrentSlotConfirmed (bundle line 23655)
double_production_slot
¶
double_production_slot(castle_id: int, list_id: ProductionListId, slot_type: SlotType, position: int, *, spend_rubies: bool = False, timeout: float = 5.0) -> bool
Double the units of a production slot, for rubies; see "Spending rubies" in the guides.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
castle_id
|
int
|
One of your castles, a |
required |
slot_type
|
SlotType
|
PRODUCTION for the slot producing now, QUEUE for a queued one |
required |
position
|
int
|
0 for the slot producing now, else the slot's
|
required |
spend_rubies
|
bool
|
Allow the rubies it costs; without it nothing is sent |
False
|
timeout
|
float
|
Timeout in seconds |
5.0
|
Raises:
| Type | Description |
|---|---|
ValueError
|
|
Client: RecruitmentHelper.boostCurrentSlot (bundle line 23165), after
CastleRecruitDialogUnits.handleBoostSlot (bundle line 23692) prices it with
getUnitDoublingCosts (bundle line 23546), always in rubies
heal_units
¶
heal_units(castle_id: int, wod_id: int, amount: int, *, spend_rubies: bool = False, timeout: float = 5.0) -> bool
Queue wounded units for healing.
A unit whose UnitStats.healing_cost_rubies is above 0 heals for rubies; see "Spending
rubies" in the guides. A subscription that waives it is not checked.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
castle_id
|
int
|
One of your castles, a |
required |
wod_id
|
int
|
The wounded unit's wod id |
required |
amount
|
int
|
How many to heal |
required |
spend_rubies
|
bool
|
Allow healing a unit that costs rubies |
False
|
timeout
|
float
|
Timeout in seconds |
5.0
|
Raises:
| Type | Description |
|---|---|
ValueError
|
The unit heals for rubies, or is not in the game data, and |
GameDataNotLoadedError
|
|
Client: CastleRecruitSelectedUnitComponent.onReviveClick (bundle line 51105), priced at
healingCostC2 per unit (bundle line 51110)
heal_all
¶
heal_all(castle_id: int, ruby_cost: int, *, spend_rubies: bool = False, timeout: float = 5.0) -> bool
Heal every wounded unit at once, for rubies; see "Spending rubies" in the guides.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
castle_id
|
int
|
One of your castles, a |
required |
ruby_cost
|
int
|
The price the client would show (see |
required |
spend_rubies
|
bool
|
Allow a |
False
|
timeout
|
float
|
Timeout in seconds |
5.0
|
Raises:
| Type | Description |
|---|---|
ValueError
|
|
Client: CastleHospitalReviveAllDialog.reviveAll (bundle line 83667), with the price from
CastleRecruitDialogHospital.openReviveAllDialog (bundle lines 83509-83513)
cancel_heal
¶
Cancel a hospital slot, by its HospitalSlot.position.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
castle_id
|
int
|
One of your castles, a |
required |
Client: CastleRecruitDialogHospital.onCurrentSlotCancelled (bundle line 83508)
skip_heal
¶
skip_heal(castle_id: int, position: int, *, spend_rubies: bool = False, timeout: float = 5.0) -> bool
Finish a hospital slot now, by its HospitalSlot.position, for rubies; see "Spending
rubies" in the guides.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
castle_id
|
int
|
One of your castles, a |
required |
position
|
int
|
The slot's |
required |
spend_rubies
|
bool
|
Allow the rubies it costs; without it nothing is sent |
False
|
timeout
|
float
|
Timeout in seconds |
5.0
|
Raises:
| Type | Description |
|---|---|
ValueError
|
|
Client: CastleRecruitDialogHospital.skipCurrentSlot (bundle line 83504), priced in rubies
by updateSkipTooltip (bundle line 83582)
dismiss_wounded
¶
Dismiss wounded units of one type instead of healing them.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
castle_id
|
int
|
One of your castles, a |
required |
Client: CastleHospitalDismissUnitsDialog.dismissUnits (bundle line 83737)
army.spy_army¶
Positional army data from a spy report.
The report's S block is consumed positionally by the game client
(CastleSpyArmyInfoVO.parseArmyInfo), which shifts one entry per position in
this order:
left, middle, right, keep, stronghold, support, reserve (optional)
Each entry is a list of [wod_id, amount] pairs. Summing the whole block
flattens the three wall flanks together with keep, stronghold, support and
reserve troops — a number the game never shows and which says nothing about
where a castle is actually strong.
Classes:
| Name | Description |
|---|---|
SpyArmy |
A spied castle's defenders, by the position they hold. |
Attributes:
| Name | Type | Description |
|---|---|---|
SpyStacks |
One position of a spied army: its stacks in the order sent, an id sent twice kept twice. |
|
SpyArmyBlock |
A reply's |
SpyStacks
module-attribute
¶
SpyStacks = Annotated[tuple[WodAmount, ...], BeforeValidator(_stacks)]
One position of a spied army: its stacks in the order sent, an id sent twice kept twice.
SpyArmyBlock
module-attribute
¶
SpyArmyBlock = Annotated[SpyArmy | None, BeforeValidator(_spied)]
A reply's S block as a SpyArmy, None when it is missing or empty (no spy report).
SpyArmy
pydantic-model
¶
Bases: EmpireModel
A spied castle's defenders, by the position they hold.
Reads a report's S block: SpyArmy.model_validate(report_s). A block shorter
than the full seven positions is normal (the server omits trailing ones), so a
missing position is empty.
Client: CastleSpyArmyInfoVO.parseArmyInfo (bundle line 30699)
Fields:
-
left(SpyStacks) -
middle(SpyStacks) -
right(SpyStacks) -
keep(SpyStacks) -
stronghold(SpyStacks) -
support(SpyStacks) -
reserve(SpyStacks)
Validators:
-
_by_position
sections
¶
sections() -> list[tuple[SpyArmySection, tuple[WodAmount, ...]]]
Every position in wire order, for display.
army.models.hospital¶
Hospital protocol models.
Commands:
- hru: Heal wounded units
- hcs: Cancel a hospital slot
- hss: Skip a hospital slot (rubies)
- hdu: Dismiss wounded units
- hra: Heal all wounded units (rubies)
These act on the castle the session has joined (jca).
Classes:
| Name | Description |
|---|---|
HealUnitsRequest |
Queue wounded units of the joined castle for healing. |
HealUnitsResponse |
The joined castle after an |
CancelHealRequest |
Cancel a hospital slot of the joined castle. |
CancelHealResponse |
The joined castle after an |
SkipHealRequest |
Finish a hospital slot of the joined castle now, for rubies. |
SkipHealResponse |
Currencies after an |
DismissWoundedRequest |
Dismiss wounded units of one type in the joined castle. |
WoundedUnits |
One |
DismissManyWoundedRequest |
Dismiss wounded units of several types in the joined castle. |
DismissWoundedResponse |
The joined castle after an |
HealAllRequest |
Heal every wounded unit of the joined castle at once, for rubies. |
HealAllResponse |
The joined castle after an |
HealUnitsRequest
pydantic-model
¶
Bases: BaseRequest
Queue wounded units of the joined castle for healing.
Command: hru Payload: {"U": wod_id, "A": amount}
Client: C2SReviveUnitPackageVO (bundle line 84175), built by
CastleRecruitSelectedUnitComponent.onReviveClick (bundle line 51105)
Fields:
HealUnitsResponse
pydantic-model
¶
Bases: BaseResponse
The joined castle after an hru.
Command: hru
Client: HRUCommand.executeCommand (bundle line 124532)
Fields:
-
error_code(int) -
production_list(ProductionListBlock) -
currencies(CurrencyBlock) -
unit_inventory(UnitInventoryBlock)
currencies
pydantic-field
¶
currencies: CurrencyBlock = None
Wire key gcu
Coins and rubies after the change
CancelHealRequest
pydantic-model
¶
Bases: BaseRequest
Cancel a hospital slot of the joined castle.
Command: hcs Payload: {"S": position}
Client: C2SCancelHospitalSlot (bundle line 83616), built by
CastleRecruitDialogHospital.onCurrentSlotCancelled (bundle line 83508)
Fields:
CancelHealResponse
pydantic-model
¶
Bases: BaseResponse
The joined castle after an hcs.
Command: hcs
Client: HCSCommand.executeCommand (bundle line 124454)
Fields:
SkipHealRequest
pydantic-model
¶
Bases: BaseRequest
Finish a hospital slot of the joined castle now, for rubies.
Command: hss Payload: {"S": position}
Client: C2SSkipHospitalSlot (bundle line 83625), built by
CastleRecruitDialogHospital (bundle line 83504)
Fields:
SkipHealResponse
pydantic-model
¶
Bases: BaseResponse
Currencies after an hss.
Command: hss
Client: HSSCommand.executeCommand (bundle line 50856)
Fields:
currencies
pydantic-field
¶
currencies: CurrencyBlock = None
Wire key gcu
Coins and rubies after the change
DismissWoundedRequest
pydantic-model
¶
Bases: BaseRequest
Dismiss wounded units of one type in the joined castle.
Command: hdu Payload: {"U": wod_id, "A": amount}
Client: C2SDismissHospitalUnits (bundle line 83748), built by
CastleHospitalDismissUnitsDialog.dismissUnits (bundle line 83737)
Fields:
WoundedUnits
pydantic-model
¶
DismissManyWoundedRequest
pydantic-model
¶
Bases: BaseRequest
Dismiss wounded units of several types in the joined castle.
Command: hdu Payload: {"UT": [{"U": wod_id, "A": amount}, ...]}
Client: C2SDismissManyHospitalUnits (bundle line 83834), built by
CastleRecruitDialogHospital.onConfirmDeleteAll (bundle line 83498)
Fields:
DismissWoundedResponse
pydantic-model
¶
Bases: BaseResponse
The joined castle after an hdu.
Command: hdu
Client: HDUCommand.executeCommand (bundle line 124470)
Fields:
HealAllRequest
pydantic-model
¶
Bases: BaseRequest
Heal every wounded unit of the joined castle at once, for rubies.
Command: hra Payload: {"C2": ruby_cost}
C2 is the price the client shows: the sum over the hospital of
int(amount * reviveAllCostC2), less the active prime-sales revive-all
discount percent, rounded up. The server answers INVALID_AMOUNT when
the hospital changed ("alert_hospital_amountOutdated").
Client: C2SReviveAllHospitalUnits (bundle line 83677), sent by
CastleHospitalReviveAllDialog.reviveAll (bundle line 83667) with the
price from CastleRecruitDialogHospital.openReviveAllDialog (bundle line 83509)
Fields:
HealAllResponse
pydantic-model
¶
Bases: BaseResponse
The joined castle after an hra.
Command: hra
Client: HRACommand.executeCommand (bundle line 124513)
Fields:
-
error_code(int) -
currencies(CurrencyBlock) -
unit_inventory(UnitInventoryBlock) -
production_area(RawBlock)
currencies
pydantic-field
¶
currencies: CurrencyBlock = None
Wire key gcu
Coins and rubies after the change
army.models.production¶
Unit and tool production models.
Commands:
- bup: Produce units or tools
- spl: Get a production list
- bou: Double the units of a production slot
- mcu: Cancel a production slot
These act on the castle the session has joined (jca);
bup and bou also name that castle and its kingdom.
Classes:
| Name | Description |
|---|---|
ProductionSlot |
One slot of a soldier, tool or auxiliary list: a |
CurrentProductionSlot |
The slot producing now, the |
HospitalSlot |
One slot of the hospital list, a positional |
ProductionList |
One production list, the |
ProduceUnitsRequest |
Produce units or tools in the joined castle. |
AddedUnit |
Units |
ProduceUnitsResponse |
The joined castle after a |
GetProductionListRequest |
Get one production list of the joined castle. |
GetProductionListResponse |
One production list of the joined castle. |
DoubleProductionSlotRequest |
Double the units of a production slot, for rubies. |
DoubleProductionSlotResponse |
The production list after a |
CancelProductionRequest |
Cancel a production slot of the joined castle. |
CancelProductionResponse |
The production list after an |
ProductionListBlock
module-attribute
¶
ProductionListBlock = Annotated[ProductionList | None, BeforeValidator(object_or_none)]
ProductionSlot
pydantic-model
¶
Bases: BasePayload
One slot of a soldier, tool or auxiliary list: a QS entry or the PS block.
The client reads three optional parts of the same object: the top-level
keys only when ICT is set, then P (which overrides the unit, amount,
boosts, alliance help and recruitment id), then SI (the lock state).
Numbers go through int(), RAH and VIP through !!, and
RUT is kept as sent. An entry that is not an object reads as an empty slot.
Client: UnitPackageSlotVO.fillFromParamObject (bundle line 61416);
PS first goes through initProductionSlot (bundle line 61417)
Fields:
-
position(int) -
wod_id(int) -
amount(int) -
boost_count(int) -
received_alliance_help(bool) -
recruitment_id(int) -
remaining_seconds(int) -
production_seconds(int) -
source_recruitment_id(int) -
seconds_till_locked(int | float | str | None) -
is_vip(bool) -
is_locked(bool) -
is_free(bool)
Validators:
-
_fill_as_the_client_does
position
pydantic-field
¶
position: int = 0
Index in the queue, the position boost and cancel requests take; 0 for the slot producing now
boost_count
pydantic-field
¶
boost_count: int = 0
Wire key CBS
How often the slot's units were doubled
production_seconds
pydantic-field
¶
production_seconds: int = 0
Wire key ICT
Total production time, in seconds
source_recruitment_id
pydantic-field
¶
source_recruitment_id: int = 0
Wire key SPID
Source recruitment id
seconds_till_locked
pydantic-field
¶
Seconds until the slot locks while it is empty, else -1; 0 means locked
CurrentProductionSlot
pydantic-model
¶
Bases: ProductionSlot
The slot producing now, the PS block: free until the block says otherwise.
Client: UnitPackageList.parseCurrentProductionSlot (bundle line 138906)
Fields:
-
position(int) -
wod_id(int) -
amount(int) -
boost_count(int) -
received_alliance_help(bool) -
recruitment_id(int) -
remaining_seconds(int) -
production_seconds(int) -
source_recruitment_id(int) -
seconds_till_locked(int | float | str | None) -
is_vip(bool) -
is_locked(bool) -
is_free(bool)
Validators:
-
_fill_as_the_client_does
HospitalSlot
pydantic-model
¶
Bases: BasePayload
One slot of the hospital list, a positional PIDL entry.
[wod_id, amount, remaining_seconds, speed * 100, heal_time_reduction,
recruitment_id, seconds_till_locked], which the client reads in that order
with no int(); here each goes through js_int so the fields are
ints, and a missing value reads as 0. An entry that is not an array reads as
an empty slot here, where the client would stop reading the list.
Client: UnitHealPackageSlotVO.fillFromParamArray (bundle line 138964)
Fields:
ProductionList
pydantic-model
¶
Bases: BasePayload
One production list, the spl block.
The client ignores a block without LID. The hospital list
(ProductionListId.HOSPITAL) sends PIDL and ASI; every other list
sends QS, PS, RM and TCT.
Client: CastleMilitaryData.parse_SPL (bundle line 138830),
UnitPackageList.parseList / parseMilitaryList (bundle lines 138899, 138907);
RecruitmentConst (dll line 19660) for the RM modes
Fields:
-
list_id(int | None) -
queue(list[ProductionSlot]) -
current(CurrentProductionSlot) -
recruitment_mode(int) -
remaining_seconds(int) -
hospital_slots(list[HospitalSlot]) -
active_slot_index(ParseInt)
Validators:
-
_client_ints
list_id
pydantic-field
¶
list_id: int | None = None
Wire key LID
A ProductionListId; None when missing
recruitment_mode
pydantic-field
¶
recruitment_mode: int = 0
Wire key RM
0 finishes the first stack first, 1 finishes the stacks equally
remaining_seconds
pydantic-field
¶
remaining_seconds: int = 0
Wire key TCT
Seconds until the list's production is done
hospital_slots
pydantic-field
¶
hospital_slots: list[HospitalSlot]
Wire key PIDL
Hospital list only: slots by position
ProduceUnitsRequest
pydantic-model
¶
Bases: BaseRequest
Produce units or tools in the joined castle.
Command: bup Payload: {"LID": list_id, "WID": wod_id, "AMT": amount, "PO": -1, "PWR": 0, "SK": 73, "SID": kingdom_id, "AID": castle_id}
PWR 1 pays rubies for missing resources: the client sends it from the
resource wait dialog's skip (CastleResourceWaitDialog.skipForRubies,
bundle line 32069), with PO set to the resource merchant's private offer
id (CastlePrivateOfferData.getPrivateOfferMerchantID, bundle line 131979,
-1 when there is none). SK is always 73 (BUY_UNIT_PACKAGE_SK).
Client: C2SBuyUnitPackageVO (bundle line 35277), built by
CastleRecruitSelectedUnitComponent (bundle line 51107) and
CastleResourceWaitDialogProperties.getResourceSkipCommand (bundle line 35218)
Fields:
-
list_id(ProductionListId) -
wod_id(int) -
amount(int) -
private_offer_id(int) -
pay_with_rubies(int) -
sk(int) -
kingdom_id(Kingdom) -
castle_id(int)
AddedUnit
pydantic-model
¶
Bases: BasePayload
Units bup put straight into the inventory, the O block.
Client: BUPCommand.executeCommand (bundle line 125531) calls
unitInventory.addUnit(O.W, O.AMT) when O is set and not 0
Fields:
Validators:
-
_client_ints
ProduceUnitsResponse
pydantic-model
¶
Bases: BaseResponse
The joined castle after a bup.
Command: bup Payload: {"spl": {...}, "grc": {...}, "gcu": {...}, "gui": {...}, "O": {"W": wod_id, "AMT": amount}}
Client: BUPCommand.executeCommand (bundle line 125531): spl to
parse_SPL, grc to AreaDataUpdater.parseGRC, gcu to
CurrencyData.parseGCU, gui to parse_GUI
Fields:
-
error_code(int) -
production_list(ProductionListBlock) -
resources(RawBlock) -
currencies(CurrencyBlock) -
unit_inventory(UnitInventoryBlock) -
added_unit(AddedUnit | None)
resources
pydantic-field
¶
resources: RawBlock = None
Wire key grc
The castle's resources, as a raw block
currencies
pydantic-field
¶
currencies: CurrencyBlock = None
Wire key gcu
Coins and rubies after the change
GetProductionListRequest
pydantic-model
¶
Bases: BaseRequest
Get one production list of the joined castle.
Command: spl Payload: {"LID": list_id}
Client: C2SShowPackageListVO (bundle line 22860)
Fields:
accepts_reply
¶
Whether an spl reply is about this list: its LID is the one asked for, or it is empty.
Client: CastleMilitaryData.parse_SPL (bundle line 138830) updates the
list named by the reply's LID and ignores a reply without one. The
server answers {} for a list the castle cannot produce (seen live for
the auxiliaries list on a castle without that building), which the client
never asks for; an empty reply names no list, so it cannot be another
request's.
GetProductionListResponse
pydantic-model
¶
Bases: BaseResponse, ProductionList
One production list of the joined castle.
Command: spl
Client: SPLCommand.executeCommand (bundle line 125676) hands the reply to
CastleMilitaryData.parse_SPL
Fields:
-
list_id(int | None) -
queue(list[ProductionSlot]) -
current(CurrentProductionSlot) -
recruitment_mode(int) -
remaining_seconds(int) -
hospital_slots(list[HospitalSlot]) -
active_slot_index(ParseInt) -
error_code(int)
Validators:
-
_client_ints
DoubleProductionSlotRequest
pydantic-model
¶
Bases: BaseRequest
Double the units of a production slot, for rubies.
Command: bou Payload: {"LID": list_id, "S": position, "AID": castle_id, "SID": kingdom_id, "ST": slot_type}
S is the slot's position: 0 for the slot producing now, its index in
QS for a queued one.
Client: C2SBoostUnitPackageVO (bundle line 79040), built by
RecruitmentHelper.boostCurrentSlot (bundle line 23165) from the recruit
dialog's boost button (onDoubleUnitsConfirmation, bundle line 23694)
Fields:
DoubleProductionSlotResponse
pydantic-model
¶
Bases: BaseResponse
The production list after a bou.
Command: bou
Client: BOUCommand.executeCommand (bundle line 125515)
Fields:
currencies
pydantic-field
¶
currencies: CurrencyBlock = None
Wire key gcu
Coins and rubies after the change
CancelProductionRequest
pydantic-model
¶
Bases: BaseRequest
Cancel a production slot of the joined castle.
Command: mcu Payload: {"LID": list_id, "S": position, "ST": slot_type}
Client: C2SCancelUnitPackageVO (bundle line 83843), built by
CastleRecruitDialogUnits.onCancelCurrentSlotConfirmed (bundle line 23655)
Fields:
CancelProductionResponse
pydantic-model
¶
Bases: BaseResponse
The production list after an mcu.
Command: mcu
Client: MCUCommand.executeCommand (bundle line 125616)
Fields:
army.models.units¶
Unit inventory, dismissing units, and attack waves.
Commands:
- gui: Get units inventory
- dup: Dismiss units
AttackWave and WaveFlank are the waves a cra attack sends.
Classes:
| Name | Description |
|---|---|
GetUnitsRequest |
Get the unit inventories of the castle the session is in. |
UnitInventory |
A castle's unit inventories, the |
GetUnitsResponse |
The unit inventories of the castle the session is in. |
DismissUnitsRequest |
Dismiss units of the joined castle. |
DismissUnitsResponse |
The joined castle after a |
WaveFlank |
One flank of an attack wave. |
AttackWave |
A single attack wave: left, right and middle flank. |
Attributes:
| Name | Type | Description |
|---|---|---|
BUY_UNIT_PACKAGE_SK |
|
BUY_UNIT_PACKAGE_SK
module-attribute
¶
SK of every bup: each client caller leaves C2SBuyUnitPackageVO's
default; nothing in the client reads it or says what it means.
RawBlock
module-attribute
¶
RawBlock = Annotated[dict[str, Any] | None, BeforeValidator(object_or_none)]
A reply block this module keeps as sent; the docstring names the client parser.
UnitInventoryBlock
module-attribute
¶
UnitInventoryBlock = Annotated[UnitInventory | None, BeforeValidator(object_or_none)]
GetUnitsRequest
pydantic-model
¶
Bases: BaseRequest
Get the unit inventories of the castle the session is in.
Command: gui Payload: {}
The request names no castle: the server answers for the joined castle, and
with NOT_IN_OWNED_CASTLE once a map scan has moved the session away.
Client: C2SGetUnitInventoryVO (no fields)
UnitInventory
pydantic-model
¶
Bases: BasePayload
A castle's unit inventories, the gui block.
Client: CastleMilitaryData.parse_GUI, which fills each inventory with
AUnitInventory.fillFromWodAmountArray (bundle line 42572)
Fields:
-
units(WodAmounts) -
in_production(WodAmounts) -
stronghold(WodAmounts) -
hospital(WodAmounts)
GetUnitsResponse
pydantic-model
¶
Bases: BaseResponse, UnitInventory
The unit inventories of the castle the session is in.
Command: gui Payload: {"I": [[wod_id, amount], ...], "TU": [...], "SHI": [...], "HI": [...]}
Client: GUICommand.exec (bundle line 125600) hands the reply to
CastleMilitaryData.parse_GUI, which reads I, TU, SHI and HI and nothing else.
Fields:
-
units(WodAmounts) -
in_production(WodAmounts) -
stronghold(WodAmounts) -
hospital(WodAmounts) -
error_code(int)
DismissUnitsRequest
pydantic-model
¶
Bases: BaseRequest
Dismiss units of the joined castle.
Command: dup Payload: {"WID": wod_id, "A": amount, "S": 0 or 1}
Client: C2SDismissUnitPackageVO (bundle line 84341), built by
CastleRecruitDismissUnitsDialog.dismissUnits (bundle line 84330)
Fields:
DismissUnitsResponse
pydantic-model
¶
Bases: BaseResponse
The joined castle after a dup.
Command: dup
Client: DUPCommand.executeCommand (bundle line 125585)
Fields:
WaveFlank
pydantic-model
¶
Bases: BasePayload
One flank of an attack wave.
Payload: {"T": [[tool_id, count], ...], "U": [[unit_id, count], ...]}, one pair per slot
Client: CastleAttackWaveVO.getWaveInfoObject (bundle line 99930) sends each
container's getSlotList() (bundle line 20573)
Fields:
AttackWave
pydantic-model
¶
Bases: BasePayload
A single attack wave: left, right and middle flank.
Payload: {"L": flank, "R": flank, "M": flank}, in the client's key order.
Client: CastleAttackWaveVO.getWaveInfoObject (bundle line 99930)
Fields: