Skip to content

Alliance

Alliance info, members, chat and help behind client.alliance.

alliance.service

Your alliance and others: members, chat, help, diplomacy and the treasury.

It covers:

  • Alliance members (get members, online status, last seen)
  • Member management (kick, rank, invite, applications, leave)
  • Diplomacy, auto war, the newsletter and treasury donations
  • Alliance chat (send messages, get history)
  • Alliance help (the help list and its pushes, helping, asking for help)
  • Your alliance's chronicle and subscriber count
  • Map bookmarks, your own and your alliance's (list, add, change, delete)

Classes:

Name Description
AllianceService

Alliance chat, help, members, applications, diplomacy and the treasury.

Attributes:

Name Type Description
AllianceHelpUpdate

logger module-attribute

logger = logging.getLogger(__name__)

AllianceHelpUpdate module-attribute

AllianceService

AllianceService(client: EmpireClient)

Bases: BaseService

Alliance chat, help, members, applications, diplomacy and the treasury.

Reached as client.alliance.

Usage
client = EmpireClient(...)
client.login()

# Send chat message
client.alliance.send_chat("Hello alliance!")

# Help every request on the alliance help list
client.alliance.help_all()

# Subscribe to incoming messages
def on_message(response: AllianceChatMessageResponse):
    print(f"{response.player_name}: {response.decoded_text}")

client.alliance.on_chat_message(on_message)

Methods:

Name Description
get_alliance_info

Get info about an alliance.

get_members

Get the list of alliance members from the server.

get_online_members

Get alliance members who are currently online.

get_member

Get a specific member by player ID.

kick_member

Remove a member from your alliance.

set_rank

Give a member another rank; AllianceRank.LEADER hands over the leadership.

invite

Invite a player to your alliance.

get_applications

Get your alliance's applications, nearest first, with the applicants' owner records.

answer_application

Accept or refuse an application.

leave

Leave your alliance. Once the server accepts, help_requests is emptied.

change_diplomacy

Change or propose your alliance's relation with another alliance.

refuse_diplomacy

Refuse another alliance's diplomacy request or peace offer.

set_auto_war

Turn auto war on or off.

send_newsletter

Send the alliance newsletter to every member.

donate

Donate resources from one of your castles to the alliance treasury.

search_alliances

Search for alliances by name.

get_local_members

Get members of the local player's alliance.

get_local_online_members

Get online members of the local player's alliance.

get_chronicle

Get your alliance's chronicle, newest first.

get_subscriber_count

Get how many of your alliance's members have a subscription.

send_chat

Send a message to alliance chat.

get_chat_log

Get alliance chat history.

on_chat_message

Register a callback for incoming alliance chat messages.

on_help_update

Call callback with the login data's ahl section and each ahl, ahh, ahd and ahf push,

help_member

Help one request on the help list.

help_all

Help every request on the help list.

request_build_help

Ask the alliance to help build a building.

request_repair_help

Ask the alliance to help repair a building.

request_recruit_help

Ask the alliance to help with a recruitment.

request_heal_help

Ask the alliance to help heal wounded units.

get_bookmarks

Get your own and your alliance's map bookmarks.

add_bookmark

Bookmark a map position: for yourself as a friend or an enemy, or for your alliance.

change_bookmark

Rename one of your own bookmarks, or switch it between friend and enemy.

delete_bookmark

Delete a bookmark: one of your own by its position, an alliance one by its id.

Attributes:

Name Type Description
cached_members dict[int, AllianceMember]

Get the cached member dictionary.

local_alliance_id int | None

Get the local player's alliance ID.

help_requests list[AllianceHelpRequest]

The alliance help list as the login data and the pushes since left it.

cached_members property

cached_members: dict[int, AllianceMember]

Get the cached member dictionary.

Returns members from the last get_members() call, keyed by player_id. Call get_members() to refresh.

Returns:

Type Description
dict[int, AllianceMember]

Dict mapping player_id to AllianceMember

local_alliance_id property

local_alliance_id: int | None

Get the local player's alliance ID.

Returns:

Type Description
int | None

Alliance ID if in an alliance, None otherwise: the player data sends

int | None

a negative AID outside one

Client: CastleUserData.isInAlliance (bundle line 9986) is allianceID >= 0

help_requests property

help_requests: list[AllianceHelpRequest]

The alliance help list as the login data and the pushes since left it.

The login data's ahl section fills it, and so does an ahl push; ahh replaces or adds a request by LID, ahd removes one. The client never asks the server for the list, and neither does this library. The list is not emptied when the session drops, as the client keeps it; the next login's ahl section replaces it.

Client: AllianceHelpRequestData (bundle line 133359) keeps the list the same way, from GBDCommand.exec (bundle line 129381) and the AHL/AHH/AHD commands; it has no reset of its own (CastleBasicData.reset, bundle line 2109, is empty)

get_alliance_info

get_alliance_info(alliance_id: int, timeout: float = 5.0) -> GetAllianceInfoResponse

Get info about an alliance.

Parameters:

Name Type Description Default
alliance_id int

Your own is client.alliance.local_alliance_id; another is an AllianceSearchResult.alliance_id from client.alliance.search_alliances()

required
timeout float

Timeout in seconds

5.0

Raises:

Type Description
CommandError / EmpireTimeoutError / ConnectionClosedError

see EmpireClient.send

get_members

get_members(alliance_id: int, timeout: float = 5.0) -> list[AllianceMember]

Get the list of alliance members from the server.

This fetches alliance info and returns all members with their online status (via AMI array), level, rank, etc.

Parameters:

Name Type Description Default
alliance_id int

Your own is client.alliance.local_alliance_id; another alliance's is AllianceSearchResult.alliance_id from search_alliances or a player's client.player.get_player_info(player_id).alliance_id

required
timeout float

Timeout in seconds to wait for response

5.0

Returns:

Type Description
list[AllianceMember]

List of AllianceMember objects

Example
members = client.alliance.get_members(301)
for member in members:
    print(f"{member.name}: online={member.is_online}")

get_online_members

get_online_members(alliance_id: int, timeout: float = 5.0) -> list[AllianceMember]

Get alliance members who are currently online.

Fetches the member list and filters to only online members (members with online status from AMI array).

Parameters:

Name Type Description Default
alliance_id int

Your own is client.alliance.local_alliance_id; another alliance's is AllianceSearchResult.alliance_id from search_alliances or a player's client.player.get_player_info(player_id).alliance_id

required
timeout float

Timeout in seconds to wait for response

5.0

Returns:

Type Description
list[AllianceMember]

List of online AllianceMember objects

Example
online = client.alliance.get_online_members(301)
print(f"{len(online)} members online")

get_member

get_member(player_id: int, no_cache: bool = False) -> AllianceMember | None

Get a specific member by player ID.

Parameters:

Name Type Description Default
player_id int

The member's AllianceMember.player_id, as get_members lists it

required
no_cache bool

If True, refresh alliance data from server first

False

Returns:

Type Description
AllianceMember | None

AllianceMember if found, None otherwise

Raises:

Type Description
NotInAllianceError

no_cache with no alliance cached, and you are in none; nothing is sent

Example
member = client.alliance.get_member(12345)  # From cache
member = client.alliance.get_member(12345, no_cache=True)  # Fresh data

kick_member

kick_member(player_id: int, timeout: float = 5.0) -> AllianceInfo

Remove a member from your alliance.

Parameters:

Name Type Description Default
player_id int

The member's AllianceMember.player_id

required

Returns:

Type Description
AllianceInfo

The alliance after the kick

Raises:

Type Description
NotInAllianceError

You are in no alliance (nothing is sent), or the server answered ALLI_NOT_FOUND

PacketError

The reply carries no alliance

CommandError / EmpireTimeoutError / ConnectionClosedError

see EmpireClient.send

Client: AKMCommand.executeCommand (bundle line 121513) reads the reply's ain

set_rank

set_rank(player_id: int, rank: AllianceRank, timeout: float = 5.0) -> AllianceInfo | None

Give a member another rank; AllianceRank.LEADER hands over the leadership.

Parameters:

Name Type Description Default
player_id int

The member's AllianceMember.player_id

required
rank AllianceRank

The new rank

required

Returns:

Type Description
AllianceInfo | None

The alliance after the change, or None when the server answers NO_CHANGE,

AllianceInfo | None

which the client takes as nothing to do

Raises:

Type Description
NotInAllianceError

You are in no alliance (nothing is sent), or the server answered ALLI_NOT_FOUND

PacketError

The reply carries no alliance

CommandError / EmpireTimeoutError / ConnectionClosedError

see EmpireClient.send

Client: ARMCommand.executeCommand (bundle line 121589) reads the reply's ain and passes over NO_CHANGE

invite

invite(player_id: int, timeout: float = 5.0) -> bool

Invite a player to your alliance.

Parameters:

Name Type Description Default
player_id int

The player's id, e.g. PlayerOwnerInfo.player_id from client.player.get_player_info()

required

Returns:

Type Description
bool

Whether the server accepted the invitation; it refuses an id that names

bool

no player with INVALID_PLAYER_ID

Raises:

Type Description
NotInAllianceError

You are in no alliance (nothing is sent), or the server answered ALLI_NOT_FOUND

Client: CastlePlayerInfoDialog shows its invite button for CastleUserData.canInviteToAlliance (bundle line 9994), which needs isInAlliance

get_applications

get_applications(timeout: float = 5.0) -> AllianceApplicationListResponse

Get your alliance's applications, nearest first, with the applicants' owner records.

Raises:

Type Description
NotInAllianceError

You are in no alliance (nothing is sent), or the server answered ALLI_NOT_FOUND

CommandError / EmpireTimeoutError / ConnectionClosedError

see EmpireClient.send

answer_application

answer_application(player_id: int, accept: bool, timeout: float = 5.0) -> bool

Accept or refuse an application.

Parameters:

Name Type Description Default
player_id int

The applicant's AllianceApplication.player_id

required
accept bool

True to accept, False to refuse

required

Returns:

Type Description
bool

Whether the server accepted the answer

Raises:

Type Description
NotInAllianceError

You are in no alliance (nothing is sent), or the server answered ALLI_NOT_FOUND

leave

leave(timeout: float = 5.0) -> bool

Leave your alliance. Once the server accepts, help_requests is emptied.

Client: AQICommand.executeCommand (bundle line 121556) calls CastleAllianceData.resetMyAlliance (bundle line 11620), which cleans the help list

Returns:

Type Description
bool

Whether the server accepted it

Raises:

Type Description
NotInAllianceError

You are in no alliance (nothing is sent), or the server answered ALLI_NOT_FOUND

change_diplomacy

change_diplomacy(alliance_id: int, new_status: DiplomacyStatus, tribute: int = 0, timeout: float = 5.0) -> ChangeDiplomacyResponse

Change or propose your alliance's relation with another alliance.

Parameters:

Name Type Description Default
alliance_id int

The other alliance, e.g. AllianceDiplomacyStatus.alliance_id

required
new_status DiplomacyStatus

The relation to change to

required
tribute int

Only to accept a peace offer: PeaceOffer.tribute as the offer states it

0

Raises:

Type Description
NotInAllianceError

You are in no alliance (nothing is sent), or the server answered ALLI_NOT_FOUND

CommandError / EmpireTimeoutError / ConnectionClosedError

see EmpireClient.send

Client: CastleAllianceInfoDialogDiplomacy.updateButtons (bundle line 72349) offers each change from the other alliance's status to your own

refuse_diplomacy

refuse_diplomacy(alliance_id: int, timeout: float = 5.0) -> AllianceInfo | None

Refuse another alliance's diplomacy request or peace offer.

Returns:

Type Description
AllianceInfo | None

The other alliance after the refusal

Raises:

Type Description
NotInAllianceError

You are in no alliance (nothing is sent), or the server answered ALLI_NOT_FOUND

PacketError

The reply carries no alliance

CommandError / EmpireTimeoutError / ConnectionClosedError

see EmpireClient.send

Client: ARDCommand.executeCommand (bundle line 121574) reads the reply's A; CastleAllianceDialogDiplomacy opens the dialogs that refuse (bundle lines 69323, 69352)

set_auto_war

set_auto_war(enabled: bool, timeout: float = 5.0) -> bool

Turn auto war on or off.

Returns:

Type Description
bool

Whether auto war is on afterwards

Raises:

Type Description
NotInAllianceError

You are in no alliance (nothing is sent), or the server answered ALLI_NOT_FOUND

CommandError / EmpireTimeoutError / ConnectionClosedError

see EmpireClient.send

send_newsletter

send_newsletter(subject: str, text: str, timeout: float = 5.0) -> bool

Send the alliance newsletter to every member.

Parameters:

Name Type Description Default
subject str

The subject (the client's field takes 20 characters)

required
text str

The text; the client does not send an empty one

required

Returns:

Type Description
bool

Whether the server accepted it

Raises:

Type Description
ValueError

text is empty

NotInAllianceError

You are in no alliance (nothing is sent), or the server answered ALLI_NOT_FOUND

donate

donate(castle_id: int, donation: AllianceDonation, *, spend_rubies: bool = False, timeout: float = 5.0) -> DonateResponse

Donate resources from one of your castles to the alliance treasury.

Donating AllianceDonation.rubies spends them; see "Spending rubies" in the guides.

Parameters:

Name Type Description Default
castle_id int

The donating castle, a Castle.id from client.state.get_castles()

required
donation AllianceDonation

The amounts; the client sends nothing when every amount is 0

required
spend_rubies bool

Allow a donation of rubies

False
timeout float

Timeout in seconds

5.0

Raises:

Type Description
UnknownCastleError

castle_id is not in your castle list

AmbiguousCastleError

castle_id repeats across your kingdoms

ValueError

every amount is 0, or rubies are donated and spend_rubies is False

NotInAllianceError

You are in no alliance (nothing is sent), or the server answered ALLI_NOT_FOUND

CommandError / EmpireTimeoutError / ConnectionClosedError

see EmpireClient.send

Client: CastleAllianceDonateDialog.onDonateForAlliance (bundle line 45576) sends the picked castle's objectId and kingdomID

search_alliances

search_alliances(search_term: str, timeout: float = 5.0) -> list[AllianceSearchResult]

Search for alliances by name.

Parameters:

Name Type Description Default
search_term str

The alliance name to search for (partial match)

required
timeout float

Timeout in seconds to wait for response

5.0

Returns:

Type Description
list[AllianceSearchResult]

List of AllianceSearchResult objects matching the search; empty when

list[AllianceSearchResult]

the server finds none (ALLI_NOT_FOUND), which the client

list[AllianceSearchResult]

shows as "alliance not found" (HGHCommand.executeCommand, bundle line 124377)

Raises:

Type Description
CommandError

The server refused for another reason

PacketError

The reply's payload is not an object

Example
results = client.alliance.search_alliances("PACT")
for alliance in results:
    print(f"{alliance.name} (ID: {alliance.alliance_id}, {alliance.member_count} members)")

Note: 'hgh' is shared with the highscore command. Requests for it run one at a time, but after one times out its late reply can be taken by the next, a get_highscore() call included. Replies carry LT and LID, but the client takes the list and league a reply names rather than the ones it asked for, so no reply is refused on them (see GetHighscoreRequest).

get_local_members

get_local_members(timeout: float = 5.0) -> list[AllianceMember]

Get members of the local player's alliance.

Convenience method that automatically uses the logged-in player's alliance ID.

Parameters:

Name Type Description Default
timeout float

Timeout in seconds to wait for response

5.0

Returns:

Type Description
list[AllianceMember]

List of AllianceMember objects

Raises:

Type Description
NotInAllianceError

You are in no alliance; nothing is sent

Example
members = client.alliance.get_local_members()
for member in members:
    print(f"{member.name}: {'online' if member.is_online else 'offline'}")

get_local_online_members

get_local_online_members(timeout: float = 5.0) -> list[AllianceMember]

Get online members of the local player's alliance.

Convenience method that automatically uses the logged-in player's alliance ID and filters to online members only.

Parameters:

Name Type Description Default
timeout float

Timeout in seconds to wait for response

5.0

Returns:

Type Description
list[AllianceMember]

List of online AllianceMember objects

Raises:

Type Description
NotInAllianceError

You are in no alliance; nothing is sent

Example
online = client.alliance.get_local_online_members()
print(f"{len(online)} alliance members online")

get_chronicle

get_chronicle(timeout: float = 5.0) -> list[AllianceChronicleEntry]

Get your alliance's chronicle, newest first.

Raises:

Type Description
NotInAllianceError

You are in no alliance (nothing is sent), or the server answered ALLI_NOT_FOUND

CommandError / EmpireTimeoutError / ConnectionClosedError

see EmpireClient.send

Client: CastleAllianceDialogOverview (bundle line 70407) asks for it

get_subscriber_count

get_subscriber_count(timeout: float = 5.0) -> int

Get how many of your alliance's members have a subscription.

Sent outside an alliance too, as the client sends it at login and right after leaving one.

Raises:

Type Description
NotInAllianceError

The server answered ALLI_NOT_FOUND

CommandError / EmpireTimeoutError / ConnectionClosedError

see EmpireClient.send

Client: SubscriptionData.onGbdArrived (bundle line 120092) and AQICommand.executeCommand (bundle line 121557) call requestASC

send_chat

send_chat(message: str) -> None

Send a message to alliance chat.

Parameters:

Name Type Description Default
message str

The message text to send (will be auto-encoded)

required
Example
client.alliance.send_chat("Hello alliance!")
client.alliance.send_chat("Special chars work: 100% safe!")

get_chat_log

get_chat_log(timeout: float = 5.0) -> list[ChatMessageData]

Get alliance chat history.

The game client never asks for acl; it only reads the acl the server sends, which a live server pushes once at login. A live server also answers this request, with the same CM list.

Parameters:

Name Type Description Default
timeout float

Timeout in seconds to wait for response

5.0

Returns:

Type Description
list[ChatMessageData]

The messages of the acl reply's CM list

Example
history = client.alliance.get_chat_log()
for entry in history:
    print(f"{entry.player_name}: {entry.decoded_text}")

on_chat_message

on_chat_message(callback: Callable[[AllianceChatMessageResponse], object]) -> None

Register a callback for incoming alliance chat messages.

The callback will be called whenever a chat message is received, including messages from other players and confirmations of your own.

Callbacks run on the receive thread: they must not block, and a call that waits for a reply raises ReceiveThreadError.

Args: callback: Function that receives AllianceChatMessageResponse

Example:

def on_message(msg: AllianceChatMessageResponse):
    print(f"[{msg.player_name}] {msg.decoded_text}")

client.alliance.on_chat_message(on_message)

on_chat_message.remove(callback) detaches it, a no-op if it is not registered, so reconnect re-wiring can detach unconditionally.

Unregister a callback with on_chat_message.remove(callback).

on_help_update

on_help_update(callback: Callable[[AllianceHelpUpdate], object]) -> None

Call callback with the login data's ahl section and each ahl, ahh, ahd and ahf push, after help_requests is updated.

Detach it again with on_help_update.remove(callback), a no-op if it is not registered.

Unregister a callback with on_help_update.remove(callback).

help_member

help_member(request: AllianceHelpRequest | int) -> None

Help one request on the help list.

The client has no handler for an ahc answer, so none is waited for.

Parameters:

Name Type Description Default
request AllianceHelpRequest | int

An AllianceHelpRequest from help_requests, or its list_id

required

help_all

help_all() -> None

Help every request on the help list.

The client has no handler for an aha answer, so none is waited for.

request_build_help

request_build_help(building_id: int, timeout: float = 5.0) -> bool

Ask the alliance to help build a building.

Parameters:

Name Type Description Default
building_id int

The building's object id, e.g. BuildResponse.building_id

required

Returns:

Type Description
bool

Whether the server accepted the request

request_repair_help

request_repair_help(building_id: int, timeout: float = 5.0) -> bool

Ask the alliance to help repair a building.

Parameters:

Name Type Description Default
building_id int

The damaged building's object id

required

Returns:

Type Description
bool

Whether the server accepted the request

request_recruit_help

request_recruit_help(recruit_id: int, help_type: HelpType, timeout: float = 5.0) -> bool

Ask the alliance to help with a recruitment.

Parameters:

Name Type Description Default
recruit_id int

The recruitment's id; the library does not read recruitment ids yet

required
help_type HelpType

HelpType.RECRUITMENT, LOOP_RECRUIT or RECRUITMENT_LIST

required

Returns:

Type Description
bool

Whether the server accepted the request

request_heal_help

request_heal_help(hospital_entry_id: int, hospital_list_id: int, timeout: float = 5.0) -> bool

Ask the alliance to help heal wounded units.

Parameters:

Name Type Description Default
hospital_entry_id int

The hospital entry; the library does not read hospital entry ids yet

required
hospital_list_id int

The hospital list the entry is on

required

Returns:

Type Description
bool

Whether the server accepted the request

get_bookmarks

get_bookmarks(timeout: float = 5.0) -> GetBookmarksResponse

Get your own and your alliance's map bookmarks.

Returns:

Type Description
GetBookmarksResponse

The gbl reply: own_bookmarks and alliance_bookmarks

Raises:

Type Description
CommandError / EmpireTimeoutError / ConnectionClosedError

see EmpireClient.send

add_bookmark

add_bookmark(x: int, y: int, name: str, bookmark_type: BookmarkType = PLAYER_FRIEND, kingdom: Kingdom = GREEN, *, attack_in_seconds: int | None = None, attacker_ids: list[int] | None = None, message_attackers: bool = True, timeout: float = 5.0) -> Bookmark

Bookmark a map position: for yourself as a friend or an enemy, or for your alliance.

An own list holds MAX_PLAYER_BOOKMARKS, an alliance's MAX_ALLIANCE_BOOKMARKS; the server refuses a bookmark past them.

Parameters:

Name Type Description Default
x int

Map x

required
y int

Map y

required
name str

1 to BOOKMARK_NAME_MAX_LENGTH characters, sent as typed

required
bookmark_type BookmarkType

What it marks; the alliance types need the right to manage bookmarks

PLAYER_FRIEND
kingdom Kingdom

The kingdom

GREEN
attack_in_seconds int | None

An alliance attack order's attack, ATTACK_ORDER_MIN_SECONDS to ATTACK_ORDER_MAX_SECONDS from now; only for ALLIANCE_ATTACK_ORDER

None
attacker_ids list[int] | None

The members an attack order sends, at least one; only for ALLIANCE_ATTACK_ORDER

None
message_attackers bool

Whether an attack order's attackers get a message (the client's default)

True
timeout float

Timeout in seconds

5.0

Returns:

Type Description
Bookmark

The bookmark added, with its bookmark_id

Raises:

Type Description
ValueError

The client's bookmark dialog would not send it

NotInAllianceError

An alliance type while you are in no alliance; nothing is sent

CommandError

The server refused it: BOOKMARK_ALREADY_ADDED, BOOKMARK_MAX_ENTRYS, NO_SELF_TARGET (your own castle) and the others BADCommand shows

EmpireTimeoutError / ConnectionClosedError

see EmpireClient.send

Client: C2SAddBookmark (bundle line 68517), sent by CastleWorldmapBookmarkSetDialog.onSubmitButtonClicked (bundle line 19584) once isNameValid holds and, for an attack order, checkButtonSubmitState (bundle line 19547) sees an attacker; the time range is TeamAttackConfiguration's (bundle line 68564); the alliance tab is enabled only by playerCanCreateAllianceBookmark (bundle line 19563), which needs isInAlliance; BADCommand (bundle line 131653)

change_bookmark

change_bookmark(x: int, y: int, name: str, bookmark_type: BookmarkType = PLAYER_FRIEND, kingdom: Kingdom = GREEN, timeout: float = 5.0) -> Bookmark

Rename one of your own bookmarks, or switch it between friend and enemy.

Parameters:

Name Type Description Default
x int

The bookmark's map x

required
y int

The bookmark's map y

required
name str

The new name, 1 to BOOKMARK_NAME_MAX_LENGTH characters, sent as typed

required
bookmark_type BookmarkType

PLAYER_FRIEND or PLAYER_ENEMY

PLAYER_FRIEND
kingdom Kingdom

The bookmark's kingdom

GREEN
timeout float

Timeout in seconds

5.0

Returns:

Type Description
Bookmark

The bookmark changed

Raises:

Type Description
ValueError

An alliance type, or a name the dialog would refuse; the client changes only own bookmarks

CommandError

The server refused it

EmpireTimeoutError / ConnectionClosedError

see EmpireClient.send

Client: C2SChangeBookmark (bundle line 68532), sent by CastleWorldmapBookmarkSetDialog.onSubmitButtonClicked (bundle line 19584) for an own bookmark it edits; BCHCommand (bundle line 131672)

delete_bookmark

delete_bookmark(bookmark: Bookmark, *, notify_attackers: bool = False, timeout: float = 5.0) -> bool

Delete a bookmark: one of your own by its position, an alliance one by its id.

Parameters:

Name Type Description Default
bookmark Bookmark

A Bookmark from get_bookmarks or add_bookmark

required
notify_attackers bool

For an alliance bookmark, tell an attack order's attackers, as the delete dialog's notify button does

False
timeout float

Timeout in seconds

5.0

Returns:

Type Description
bool

True when the server accepted it, False when it refused it

Raises:

Type Description
ValueError

The bookmark has no type the client knows, so it sends nothing

NotInAllianceError

An alliance bookmark while you are in no alliance; nothing is sent

Client: CastleBookmarkData.deleteBookmark (bundle line 33474) sends C2SDeleteBookmark (bundle line 68457) for an own bookmark and C2SDeleteAllianceBookmark (bundle line 68446) for an alliance one. deleteBookmark checks no alliance itself; nothing is sent outside one, as the client creates alliance bookmarks only with isInAlliance (playerCanCreateAllianceBookmark, bundle line 19563)

alliance.models.chronicle

Alliance chronicle and subscriber count.

Commands:

  • all: Your alliance's chronicle, the log on the alliance overview
  • asc: How many of your alliance's members have a subscription

Classes:

Name Description
ChronicleDiplomacy

A diplomacy entry: CHANGE_DIPLOMACY, GET_REQUEST_DIPLOMACY, SEND_REQUEST_DIPLOMACY or

ChronicleBuff

An alliance upgrade (UPGRADE), or a boost bought or extended (ACTIVATE_TEMP_BUFF, EXTEND_TEMP_BUFF).

ChronicleAmount

An amount, AV[0]: coins, rubies, resources or glory donated, paid, won or received.

ChronicleLevel

The alliance's level after LEVEL_UP or LEVEL_DOWN, AV[0]: their text's {0}.

ChroniclePlace

The place the alliance came in, AV[0], of TOURNAMENT_RANK and ALLIANCE_RANK_OF_LAST_ROUND:

ChronicleTournamentPrize

The alliance tournament's prize, TOURNAMENT_REWARD: its text's {0} coins and {1} rubies.

ChronicleText

AV[0], which the client puts in the text as it is: the new name of CHANGE_NAME, and on an

ChronicleMember

The member thrown out, demoted or promoted (MEMBER_KICKED, MEMBER_DEMOTE, MEMBER_PROMOTE):

ChronicleDaimyoContract

A daimyo alliance contract completed: DAIMYO_ALLIANCE_CASTLE_CONTRACT_COMPLETED or

AllianceChronicleRequest

Ask for your alliance's chronicle.

AllianceChronicleEntry

One entry of your alliance's chronicle.

AllianceChronicleResponse

Your alliance's chronicle.

AllianceSubscriberCountRequest

Ask how many of your alliance's members have a subscription.

AllianceSubscriberCountResponse

How many of your alliance's members have a subscription.

Attributes:

Name Type Description
ChronicleDetails

What a chronicle entry's AV holds, by action: AllianceChronicleEntry.details.

logger module-attribute

logger = logging.getLogger(__name__)

Action module-attribute

ChronicleDetails module-attribute

What a chronicle entry's AV holds, by action: AllianceChronicleEntry.details.

ChronicleDiplomacy dataclass

ChronicleDiplomacy(alliance_name: str | None, status: DiplomacyStatus | int | None)

A diplomacy entry: CHANGE_DIPLOMACY, GET_REQUEST_DIPLOMACY, SEND_REQUEST_DIPLOMACY or REFUSE_DIPLOMACY.

Client: AllianceActionListItemVO.getActionText (bundle line 66342) reads AV[1] and AV[2]

Methods:

Name Description
from_values

Attributes:

Name Type Description
ACTIONS tuple[AllianceChronicleAction, ...]
alliance_name str | None

The other alliance's name, AV[1].

status DiplomacyStatus | int | None

The status changed to or asked for, AV[2].

ACTIONS class-attribute

ACTIONS: tuple[AllianceChronicleAction, ...] = (Action.CHANGE_DIPLOMACY, Action.GET_REQUEST_DIPLOMACY, Action.SEND_REQUEST_DIPLOMACY, Action.REFUSE_DIPLOMACY)

alliance_name instance-attribute

alliance_name: str | None

The other alliance's name, AV[1].

status instance-attribute

status: DiplomacyStatus | int | None

The status changed to or asked for, AV[2].

from_values classmethod

from_values(values: list[Any]) -> ChronicleDiplomacy

ChronicleBuff dataclass

ChronicleBuff(buff: AllianceBuffType | int | None, level: int | float | None = None)

An alliance upgrade (UPGRADE), or a boost bought or extended (ACTIVATE_TEMP_BUFF, EXTEND_TEMP_BUFF).

Client: AllianceActionListItemVO.getActionText (bundle lines 66344-66348) reads the buff from AV[0], and for an UPGRADE of MEMBERS or FORGE_UPGRADE fills the text with the rest

Methods:

Name Description
from_values

Attributes:

Name Type Description
ACTIONS tuple[AllianceChronicleAction, ...]
buff AllianceBuffType | int | None

What was upgraded or boosted, AV[0].

level int | float | None

The smithy's new level, AV[1] of a FORGE_UPGRADE; None for any other buff.

ACTIONS class-attribute

ACTIONS: tuple[AllianceChronicleAction, ...] = (Action.UPGRADE, Action.ACTIVATE_TEMP_BUFF, Action.EXTEND_TEMP_BUFF)

buff instance-attribute

buff: AllianceBuffType | int | None

What was upgraded or boosted, AV[0].

level class-attribute instance-attribute

level: int | float | None = None

The smithy's new level, AV[1] of a FORGE_UPGRADE; None for any other buff.

from_values classmethod

from_values(values: list[Any]) -> ChronicleBuff

ChronicleAmount dataclass

ChronicleAmount(amount: int | float | None)

An amount, AV[0]: coins, rubies, resources or glory donated, paid, won or received.

For the donations and MEMBER_EARN_FAME the client reads AV[0] as the amount, taking the singular text for 1 (AllianceActionListItemVO.getActionText, bundle line 66350); for the others only their text's {0} (dialog_alliance_chronic<action>) says so.

Methods:

Name Description
from_values

Attributes:

Name Type Description
ACTIONS tuple[AllianceChronicleAction, ...]
amount int | float | None

The amount, AV[0].

ACTIONS class-attribute

ACTIONS: tuple[AllianceChronicleAction, ...] = (Action.MEMBER_DONATE_COINS, Action.MEMBER_DONATE_RUBIES, Action.MEMBER_DONATE_RESOURCES, Action.MEMBER_EARN_FAME, Action.DONATE_COINS_BY_LEVEL_UP, Action.DONATE_RUBIES_BY_LEVEL_UP, Action.DONATE_RESOURCES_BY_LEVEL_UP, Action.PRIZE_COINS_OF_LAST_ROUND, Action.PRIZE_RUBIES_OF_LAST_ROUND, Action.TRIBUTE_PAY_COINS, Action.TRIBUTE_PAY_RUBIES, Action.TRIBUTE_PAY_RESOURCES, Action.TRIBUTE_GET_COINS, Action.TRIBUTE_GET_RUBIES, Action.TRIBUTE_GET_RESOURCES, Action.REWARD_COINS, Action.REWARD_RUBIES)

amount instance-attribute

amount: int | float | None

The amount, AV[0].

from_values classmethod

from_values(values: list[Any]) -> ChronicleAmount

ChronicleLevel dataclass

ChronicleLevel(level: int | float | None)

The alliance's level after LEVEL_UP or LEVEL_DOWN, AV[0]: their text's {0}.

Methods:

Name Description
from_values

Attributes:

Name Type Description
ACTIONS tuple[AllianceChronicleAction, ...]
level int | float | None

The level reached, AV[0].

ACTIONS class-attribute

ACTIONS: tuple[AllianceChronicleAction, ...] = (Action.LEVEL_UP, Action.LEVEL_DOWN)

level instance-attribute

level: int | float | None

The level reached, AV[0].

from_values classmethod

from_values(values: list[Any]) -> ChronicleLevel

ChroniclePlace dataclass

ChroniclePlace(place: int | float | None)

The place the alliance came in, AV[0], of TOURNAMENT_RANK and ALLIANCE_RANK_OF_LAST_ROUND: their text's {0}.

Methods:

Name Description
from_values

Attributes:

Name Type Description
ACTIONS tuple[AllianceChronicleAction, ...]
place int | float | None

The place, AV[0].

ACTIONS class-attribute

ACTIONS: tuple[AllianceChronicleAction, ...] = (Action.TOURNAMENT_RANK, Action.ALLIANCE_RANK_OF_LAST_ROUND)

place instance-attribute

place: int | float | None

The place, AV[0].

from_values classmethod

from_values(values: list[Any]) -> ChroniclePlace

ChronicleTournamentPrize dataclass

ChronicleTournamentPrize(coins: int | float | None, rubies: int | float | None)

The alliance tournament's prize, TOURNAMENT_REWARD: its text's {0} coins and {1} rubies.

AV[2] is the name the overview shows, AllianceChronicleEntry.named_alliance_name.

Methods:

Name Description
from_values

Attributes:

Name Type Description
ACTIONS tuple[AllianceChronicleAction, ...]
coins int | float | None

Coins won, AV[0].

rubies int | float | None

Rubies won, AV[1].

ACTIONS class-attribute

ACTIONS: tuple[AllianceChronicleAction, ...] = (Action.TOURNAMENT_REWARD,)

coins instance-attribute

coins: int | float | None

Coins won, AV[0].

rubies instance-attribute

rubies: int | float | None

Rubies won, AV[1].

from_values classmethod

from_values(values: list[Any]) -> ChronicleTournamentPrize

ChronicleText dataclass

ChronicleText(text: str | None)

AV[0], which the client puts in the text as it is: the new name of CHANGE_NAME, and on an alliance battle ground the tower defeated, the penalty increase in percent or the statuettes gained.

Client: AllianceActionListItemVO.getActionText (bundle line 66352)

Methods:

Name Description
from_values

Attributes:

Name Type Description
ACTIONS tuple[AllianceChronicleAction, ...]
text str | None

AV[0] as text.

ACTIONS class-attribute

ACTIONS: tuple[AllianceChronicleAction, ...] = (Action.CHANGE_NAME, Action.ALLIANCE_BATTLE_GROUND_OWNED_TOWER_DEFEATED, Action.ALLIANCE_BATTLE_GROUND_MALUS_INCREASED, Action.ALLIANCE_BATTLE_GROUND_POINTS_GAINED)

text instance-attribute

text: str | None

AV[0] as text.

from_values classmethod

from_values(values: list[Any]) -> ChronicleText

ChronicleMember dataclass

ChronicleMember(member_name: str | None)

The member thrown out, demoted or promoted (MEMBER_KICKED, MEMBER_DEMOTE, MEMBER_PROMOTE): their text's {1}. Nothing in the client reads AV[0] of these entries.

Methods:

Name Description
from_values

Attributes:

Name Type Description
ACTIONS tuple[AllianceChronicleAction, ...]
member_name str | None

The member's name, AV[1].

ACTIONS class-attribute

ACTIONS: tuple[AllianceChronicleAction, ...] = (Action.MEMBER_KICKED, Action.MEMBER_DEMOTE, Action.MEMBER_PROMOTE)

member_name instance-attribute

member_name: str | None

The member's name, AV[1].

from_values classmethod

from_values(values: list[Any]) -> ChronicleMember

ChronicleDaimyoContract dataclass

ChronicleDaimyoContract(contract_id: int | None)

A daimyo alliance contract completed: DAIMYO_ALLIANCE_CASTLE_CONTRACT_COMPLETED or DAIMYO_ALLIANCE_TOWNSHIP_CONTRACT_COMPLETED.

Client: AllianceActionListItemVO.getActionText (bundle lines 66354-66357) reads the contract from AV[0]

Methods:

Name Description
from_values
series_position

The contract, its level within its rank (from 1) and how many levels the rank has.

Attributes:

Name Type Description
ACTIONS tuple[AllianceChronicleAction, ...]
contract_id int | None

The contract, AV[0].

ACTIONS class-attribute

ACTIONS: tuple[AllianceChronicleAction, ...] = (Action.DAIMYO_ALLIANCE_CASTLE_CONTRACT_COMPLETED, Action.DAIMYO_ALLIANCE_TOWNSHIP_CONTRACT_COMPLETED)

contract_id instance-attribute

contract_id: int | None

The contract, AV[0].

from_values classmethod

from_values(values: list[Any]) -> ChronicleDaimyoContract

series_position

series_position(game_data: GameData) -> tuple[DaimyoContractDef, int, int]

The contract, its level within its rank (from 1) and how many levels the rank has.

Both actions look the contract up among the daimyo castle contracts, a township's too, as the client does.

Raises:

Type Description
KeyError

The castle contracts have no such contract

Client: SamuraiDaimyoDataXml.getContractSeriesIndex and getNumberOfContractsForSeries (bundle lines 13915-13925), with CONTRACT_TYPE_CASTLE (bundle lines 66354-66357)

AllianceChronicleRequest pydantic-model

Bases: BaseRequest

Ask for your alliance's chronicle.

Command: all Payload: {}

Client: C2SAllianceActionListVO (bundle line 70469)

AllianceChronicleEntry pydantic-model

Bases: BasePayload

One entry of your alliance's chronicle.

details types what action_values holds for the action; describe() writes the entry's line as the overview shows it.

Client: AllianceActionListItemVO.parseActionListItem (bundle line 66338)

Fields:

Validators:

player_id pydantic-field

player_id: ClientInt = 0

Wire key PID

The player the entry is about

player_name pydantic-field

player_name: str | None = None

Wire key PN

The player's name

seconds_ago pydantic-field

seconds_ago: ClientInt = 0

Wire key MA

Seconds since the action

action pydantic-field

Wire key A

What happened

action_values pydantic-field

action_values: list[Any]

Wire key AV

The action's text arguments as sent; typed by details

action_type property

action_type: AllianceChronicleAction | None

action as an AllianceChronicleAction, None for an action the client does not define.

details property

details: ChronicleDetails | None

What action_values holds for this action, typed; None for an action whose values nothing reads.

An entry about a player (a capital or metropolis taken or lost, a member removed for inactivity, a new Storm Lord, an owner who joined) names them in player_name instead.

is_deleted_player property

is_deleted_player: bool

The entry's player has deleted their account since; the overview shows "Deleted player".

Client: CastleAllianceDialogOverview.fillActionList (bundle line 70410), PN starting !!!_

named_alliance_id property

named_alliance_id: int | None

The alliance the overview links for an entry no player made (player_id -1), AV[0].

None for an entry a player made, and for TOURNAMENT_REWARD and TOURNAMENT_RANK, which link none.

Client: CastleAllianceDialogOverview.fillActionList (bundle lines 70410-70420)

named_alliance_name property

named_alliance_name: str | None

The name the overview shows for an entry no player made (player_id -1): AV[1], or AV[2] for TOURNAMENT_REWARD; None for TOURNAMENT_RANK and an entry a player made.

Client: CastleAllianceDialogOverview.fillActionList (bundle lines 70410-70420)

describe

describe(game_data: GameData | None = None, *, lang: str = 'en', skin: str = '') -> str

The entry's line in the chronicle, as the alliance overview writes it.

Fetches the language file on first use, as empire_core.texts.text does, and a daimyo contract entry loads the game data on first use.

Parameters:

Name Type Description Default
game_data GameData | None

The game data a daimyo contract entry reads; GameData.require when not given

None
lang str

Language code (default: "en")

'en'
skin str

The skin of the special server played on, such as "Maya", whose own texts the client prefers there (in the Great Empire only); empty elsewhere

''

Raises:

Type Description
GameDataNotLoadedError

A daimyo contract entry without game_data, and the game data cannot be loaded

KeyError

A daimyo contract the game data lacks, where the client fails too

Client: AllianceActionListItemVO.getActionText (bundle lines 66341-66358), its text id through SpecialServerHelper.checkTextIDForSkinText (bundle line 1679)

AllianceChronicleResponse pydantic-model

Bases: BaseResponse

Your alliance's chronicle.

Command: all

Client: ALLCommand.executeCommand (bundle line 121528) into CastleAllianceData.parse_ALL (bundle line 11565), which reads AL with AllianceInfoVO.parseActionList (bundle line 25962) and reverses it

Fields:

Validators:

alliance_id pydantic-field

alliance_id: ClientInt = 0

Wire key AID

Your alliance's id

entries pydantic-field

Wire key AL

The entries, newest first

AllianceSubscriberCountRequest pydantic-model

Bases: BaseRequest

Ask how many of your alliance's members have a subscription.

Command: asc Payload: {}

Client: C2SGetAllianceSubscriberCountEventVO (bundle line 120106)

AllianceSubscriberCountResponse pydantic-model

Bases: BaseResponse

How many of your alliance's members have a subscription.

Command: asc

Client: ASCCommand.executeCommand (bundle line 128655) into SubscriptionData.parseASC (bundle line 120005); the treasury's subscriptions tab shows it against the member limit (CastleAllianceDialogTreasurySubscriptions.updateSubscriberCount, bundle line 70697)

Fields:

subscriber_count pydantic-field

subscriber_count: ClientInt = 0

Wire key ASC

Members of your alliance with a subscription

alliance.models.chat

Alliance chat protocol models.

Commands:

  • acm: Send/receive alliance chat messages
  • acl: Get alliance chat log/history

Classes:

Name Description
AllianceChatMessageRequest

Request to send an alliance chat message.

ChatMessageData

One alliance chat message: an acm push's CM block, or one entry of an acl reply's CM list.

AllianceChatMessageResponse

Response containing an alliance chat message.

AllianceChatLogRequest

Request to get alliance chat history.

AllianceChatLogResponse

Response containing alliance chat history.

logger module-attribute

logger = logging.getLogger(__name__)

AllianceChatMessageRequest pydantic-model

Bases: BaseRequest

Request to send an alliance chat message.

Command: acm Payload: {"M": "encoded_message_text"}

The message text must be encoded; create does it.

Client: C2SAllianceChatVO (bundle line 66771)

Fields:

message pydantic-field

message: str

Wire key M

create classmethod

create(text: str) -> 'AllianceChatMessageRequest'

A chat message request, the text encoded as C2SAllianceChatVO does after dropping carriage returns.

ChatMessageData pydantic-model

Bases: BasePayload

One alliance chat message: an acm push's CM block, or one entry of an acl reply's CM list.

sent_at is taken when the message is read, as the client dates it. Read-only.

Client: ChatMessageVO.parseObj (bundle line 111316), reached through CastleChatData.getParsedMessage (bundle line 111301).

Fields:

Validators:

model_config class-attribute

model_config: ConfigDict = ConfigDict(frozen=True)

player_id pydantic-field

player_id: ClientInt = 0

Wire key PID

The sender's player id

player_name pydantic-field

player_name: str = ''

Wire key PN

The sender's name

message_text pydantic-field

message_text: str = ''

Wire key MT

The message text as sent, still encoded

age_seconds pydantic-field

age_seconds: int | float | None = None

Wire key MA

Seconds since the message was sent; None when the reply has no number for it

sent_at pydantic-field

sent_at: float | None = None

When the message was sent, wall-clock time.time() seconds; None when age_seconds is None

decoded_text property

decoded_text: str

The message text decoded as ChatMessageVO.parseObj (bundle line 111316) decodes it.

AllianceChatMessageResponse pydantic-model

Bases: BaseResponse

Response containing an alliance chat message.

Command: acm Payload: {"CM": {"PID": player_id, "PN": "player_name", "MT": "message_text", "MA": age_seconds}}

This is received when:

  1. Another player sends a message to alliance chat
  2. Confirmation of our own sent message

Client: ACMCommand.executeCommand (bundle line 121316) passes CM to CastleChatData.parseSingleMessage (bundle line 111288).

Fields:

chat_message pydantic-field

chat_message: ChatMessageData | None = None

Wire key CM

player_name property

player_name: str

Get the sender's player name.

message_text property

message_text: str

Get the raw message text (may contain encoded characters).

decoded_text property

decoded_text: str

Get the message text with special characters decoded.

player_id property

player_id: int

Get the sender's player ID.

AllianceChatLogRequest pydantic-model

Bases: BaseRequest

Request to get alliance chat history.

Command: acl Payload: {} (empty)

The client never sends acl: it has no C2S VO for it, and the only C2S_ALLIANCE_CHAT_LOG is an unused constant in ggs.dll (line 18958). It only reads the acl the server sends, so this payload is not taken from the client. A live server answers it with the CM list, and also pushes one acl at login.

AllianceChatLogResponse pydantic-model

Bases: BaseResponse

Response containing alliance chat history.

Command: acl Payload: {"CM": [{"PID": player_id, "PN": "player_name", "MT": "message_text", "MA": age_seconds}, ...]}

Client: ACLCommand.executeCommand (bundle line 121301) passes the reply to CastleChatData.parseHistory (bundle line 111294), which reads each entry of CM as a ChatMessageVO.

Fields:

Validators:

chat_log pydantic-field

chat_log: list[ChatMessageData]

Wire key CM

The messages, in the order the reply lists them

alliance.models.diplomacy

Alliance diplomacy, auto war, the newsletter and treasury donations.

Commands:

  • adp: Change or propose a relation with another alliance
  • ard: Refuse another alliance's request
  • saw: Turn auto war on or off
  • anl: Send the alliance newsletter
  • ado: Donate to the alliance treasury

Classes:

Name Description
ChangeDiplomacyRequest

Change or propose your alliance's relation with another alliance.

ChangeDiplomacyResponse

The relation after a change, with both alliances.

RefuseDiplomacyRequest

Refuse another alliance's diplomacy request or peace offer.

RefuseDiplomacyResponse

The other alliance after a refusal.

SetAutoWarRequest

Turn auto war on or off.

SetAutoWarResponse

Auto war after the change.

SendNewsletterRequest

Send the alliance newsletter to every member.

SendNewsletterResponse

The answer to a newsletter; the client reads nothing from it.

AllianceDonation

What to donate to the alliance treasury.

DonateRequest

Donate resources from one of your castles to the alliance treasury.

DonateResponse

Your currencies and the alliance after a donation; the castle's grc stays in the extra fields.

ChangeDiplomacyRequest pydantic-model

Bases: BaseRequest

Change or propose your alliance's relation with another alliance.

Command: adp Payload: {"AID": alliance_id, "NDR": new_status, "T": tribute}

T is always sent; the client sets it only when accepting a peace offer, to the offer's percentage, negative when it was demanded.

Client: C2SAllianceChangeDiplomacyVO (bundle line 22149), sent by CastleAllianceRequestDiplomacyDialog.onAccept (bundle line 44785), CastleReceivedPeaceOfferDialog.onAcceptConfirmed (bundle line 44856) and CastleAllianceInfoDialogDiplomacy.sendNewRank (bundle line 72379)

Fields:

alliance_id pydantic-field

alliance_id: int

Wire key AID

The other alliance

new_status pydantic-field

new_status: DiplomacyStatus

Wire key NDR

The relation to change to

tribute pydantic-field

tribute: int = 0

Wire key T

The peace offer's tribute; 0 otherwise

ChangeDiplomacyResponse pydantic-model

Bases: BaseResponse

The relation after a change, with both alliances.

Command: adp

Client: ADPCommand.executeCommand (bundle line 121361)

Fields:

Validators:

old_status pydantic-field

old_status: ClientInt = 0

Wire key ODR

The relation before, a DiplomacyStatus value

new_status pydantic-field

new_status: ClientInt = 0

Wire key NDR

The relation now, a DiplomacyStatus value

request_status pydantic-field

request_status: ClientInt = 0

Wire key S

How the request stands

own_alliance pydantic-field

own_alliance: AllianceInfo | None = None

Wire key AS

Your alliance

other_alliance pydantic-field

other_alliance: AllianceInfo | None = None

Wire key AO

The other alliance

RefuseDiplomacyRequest pydantic-model

Bases: BaseRequest

Refuse another alliance's diplomacy request or peace offer.

Command: ard Payload: {"AID": alliance_id}

Client: C2SAllianceRefuseDiplomacyVO (bundle line 44795), sent by CastleAllianceRequestDiplomacyDialog.onRefuse (bundle line 44784) and CastleReceivedPeaceOfferDialog (bundle line 44851)

Fields:

alliance_id pydantic-field

alliance_id: int

Wire key AID

The other alliance

RefuseDiplomacyResponse pydantic-model

Bases: BaseResponse

The other alliance after a refusal.

Command: ard

Client: ARDCommand.executeCommand (bundle line 121574)

Fields:

Validators:

alliance pydantic-field

alliance: AllianceInfo | None = None

Wire key A

The other alliance

SetAutoWarRequest pydantic-model

Bases: BaseRequest

Turn auto war on or off.

Command: saw Payload: {"AW": 1 or 0}

Client: C2SSetAutoWar (bundle line 69369), sent by CastleAllianceDialogDiplomacy.sendAutoWarUpdate (bundle line 69284)

Fields:

auto_war pydantic-field

auto_war: int

Wire key AW

1 for on, 0 for off

SetAutoWarResponse pydantic-model

Bases: BaseResponse

Auto war after the change.

Command: saw

Client: SAWCommand.executeCommand (bundle line 122010)

Fields:

Validators:

auto_war pydantic-field

auto_war: bool = False

Wire key AW

Auto war is on

SendNewsletterRequest pydantic-model

Bases: BaseRequest

Send the alliance newsletter to every member.

Command: anl Payload: {"SJ": subject, "TXT": text}, both encoded as chat text

Client: C2SAllianceNewsletterVO (bundle line 69739), sent by CastleAllianceMessageToAllDialog.onClick (bundle line 69715)

Fields:

subject pydantic-field

subject: str

Wire key SJ

The subject, encoded

text pydantic-field

text: str

Wire key TXT

The text, encoded

create classmethod

create(subject: str, text: str) -> SendNewsletterRequest

A newsletter, both parts encoded as C2SAllianceNewsletterVO encodes them.

SendNewsletterResponse pydantic-model

Bases: BaseResponse

The answer to a newsletter; the client reads nothing from it.

Command: anl

Client: ANLCommand.executeCommand (bundle line 121543)

Fields:

AllianceDonation pydantic-model

Bases: EmpireModel

What to donate to the alliance treasury.

These are the donatables the client offers a player: the allianceFundsDonatables rows of items v786.03 with directlyByPlayer, each sent under its CollectableHelper.getServerKeyByCollectable key, the keys AllianceStorage reads.

Client: CastleAllianceDonateDialog.showLoaded (bundle line 45511)

Fields:

wood pydantic-field

wood: int = 0

Wood

stone pydantic-field

stone: int = 0

Stone

coins pydantic-field

coins: int = 0

Coins

rubies pydantic-field

rubies: int = 0

Rubies

iron pydantic-field

iron: int = 0

Iron

oil pydantic-field

oil: int = 0

Olive oil

glass pydantic-field

glass: int = 0

Glass

coal pydantic-field

coal: int = 0

Charcoal

alliance_coins pydantic-field

alliance_coins: int = 0

Alliance coins

rift_coins pydantic-field

rift_coins: int = 0

Rift coins

legendary_rift_coins pydantic-field

legendary_rift_coins: int = 0

Legendary rift coins

resource_values

resource_values() -> dict[str, int]

The RV block: each amount above 0 under its key.

Client: CastleAllianceDonateDialog.onDonateForAlliance (bundle line 45571)

DonateRequest pydantic-model

Bases: BaseRequest

Donate resources from one of your castles to the alliance treasury.

Command: ado Payload: {"AID": castle_id, "KID": kingdom, "RV": {key: amount, ...}}

AID is the donating castle, not the alliance.

Client: C2SAllianceDonateVO (bundle line 70645), sent by CastleAllianceDonateDialog.onDonateForAlliance (bundle line 45571)

Fields:

castle_id pydantic-field

castle_id: int

Wire key AID

The donating castle, e.g. CastleInfo.castle_id

kingdom pydantic-field

kingdom: Kingdom

Wire key KID

The donating castle's kingdom

resources pydantic-field

resources: dict[str, int]

Wire key RV

The amounts, keyed as AllianceDonation keys them

create classmethod

create(castle_id: int, kingdom: Kingdom, donation: AllianceDonation) -> DonateRequest

A donation of donation from castle_id.

DonateResponse pydantic-model

Bases: BaseResponse

Your currencies and the alliance after a donation; the castle's grc stays in the extra fields.

Command: ado

Client: ADOCommand.executeCommand (bundle line 121346)

Fields:

Validators:

currency pydantic-field

currency: CurrencyBlock = None

Wire key gcu

Coins and rubies after the donation

alliance pydantic-field

alliance: AllianceInfo | None = None

Wire key ain

The alliance after the donation

alliance.models.help

Alliance help: the help list, its pushes, and helping or asking for help.

Commands:

  • ahl: The alliance help list
  • ahh: One help request added or changed (push)
  • ahd: One help request removed (push)
  • ahf: Someone helped one of your requests (push)
  • ahc: Help one request
  • aha: Help every request
  • ahr: Ask the alliance for help

Classes:

Name Description
RecruitHelpParams

The recruitment a recruit help request is for: its OP.

HealHelpParams

The wounded units a heal help request is for: its OP.

BuildingHelpParams

The building a repair or build help request is for: its OP.

AllianceHelpRequest

One request on the alliance help list.

AllianceHelpListResponse

The alliance help list.

AllianceHelpRequestChanged

One help request added to the list or changed on it, pushed by the server.

AllianceHelpRequestRemoved

One help request taken off the list, pushed by the server.

AllianceHelpReceived

Someone helped one of your requests, pushed by the server.

HelpMemberRequest

Help one request on the alliance help list.

HelpAllRequest

Help every request on the alliance help list.

AskHelpRequest

Ask the alliance for help.

AskHelpResponse

The answer to asking for help; it carries nothing the client reads.

Attributes:

Name Type Description
REPAIR_HELP_COOLDOWN_SECONDS

Seconds between two repair help requests. Client: AllianceConst.ALLIANCE_HELP_REPAIR_COOLDOWN (dll line 18772)

HelpParams

logger module-attribute

logger = logging.getLogger(__name__)

REPAIR_HELP_COOLDOWN_SECONDS module-attribute

REPAIR_HELP_COOLDOWN_SECONDS = 10800

Seconds between two repair help requests. Client: AllianceConst.ALLIANCE_HELP_REPAIR_COOLDOWN (dll line 18772)

HelpParams module-attribute

RecruitHelpParams pydantic-model

Bases: BasePayload

The recruitment a recruit help request is for: its OP.

Client: AllianceHelpRequestRecruitParamsVO.parseParams (bundle line 51138)

Fields:

recruit_id pydantic-field

recruit_id: ClientInt = 0

Wire key RID

The recruitment's id

area_id pydantic-field

area_id: ClientInt = 0

Wire key AID

The castle recruiting

space_id pydantic-field

space_id: ClientInt = 0

Wire key SID

The recruiting building's space

recruitment_list_id pydantic-field

recruitment_list_id: ClientInt = 0

Wire key RLID

The recruitment list

HealHelpParams pydantic-model

Bases: BasePayload

The wounded units a heal help request is for: its OP.

Client: AllianceHelpRequestHealParamsVO.parseParams (bundle line 50800)

Fields:

hospital_entry_id pydantic-field

hospital_entry_id: ClientInt = 0

Wire key RID

The hospital entry

hospital_list_id pydantic-field

hospital_list_id: ClientInt = 0

Wire key T

The hospital list the entry is on

area_id pydantic-field

area_id: ClientInt = 0

Wire key AID

The castle with the hospital

space_id pydantic-field

space_id: ClientInt = 0

Wire key SID

The hospital's space

BuildingHelpParams pydantic-model

Bases: BasePayload

The building a repair or build help request is for: its OP.

Client: AllianceHelpRequestRepairParamsVO.parseParams (bundle line 50054), AllianceHelpRequestConstructionParamsVO.parseParams (bundle line 31702)

Fields:

kingdom_id pydantic-field

kingdom_id: ClientInt = 0

Wire key KID

The castle's kingdom

area_id pydantic-field

area_id: ClientInt = 0

Wire key AID

The castle

object_id pydantic-field

object_id: ClientInt = 0

Wire key OID

The building's object id

AllianceHelpRequest pydantic-model

Bases: BasePayload

One request on the alliance help list.

Deliberately more lenient than the client: AllianceHelpRequestParamsFactory.parseParams (bundle line 133451) switches on the raw TID and throws for any other type or a missing OP, losing the whole list; here such an entry is skipped alone, and TID is read with int(), so "3" counts as 3.

Client: AllianceHelpRequestData.parseHelpRequestEntry (bundle line 133416)

Fields:

Validators:

already_confirmed pydantic-field

already_confirmed: bool = False

Wire key AC

You already helped this request

list_id pydantic-field

list_id: ClientInt = 0

Wire key LID

The request's id on the help list

player_name pydantic-field

player_name: str | None = None

Wire key PN

The asking player's name

progress pydantic-field

progress: ClientInt = 0

Wire key P

Helps received so far

player_id pydantic-field

player_id: ClientInt = 0

Wire key PID

The asking player's id

help_type pydantic-field

help_type: ClientInt = 0

Wire key TID

What help is asked for, a HelpType value

params pydantic-field

params: HelpParams

Wire key OP

What the request is for; its shape follows help_type

remaining_seconds pydantic-field

remaining_seconds: int | float = -1

Wire key RT

Seconds until the request expires; -1 when it does not

help_type_enum property

help_type_enum: HelpType | None

help_type as a HelpType.

AllianceHelpListResponse pydantic-model

Bases: BaseResponse

The alliance help list.

Command: ahl, as a login section of gbd and as a push. The client never asks for it: C2S_ALLIANCE_HELP_LIST (bundle line 71) has no VO and no call site.

Client: AHLCommand.executeCommand (bundle line 121904), AllianceHelpRequestData.parse_AHL (bundle line 133386), read from gbd (bundle line 129381)

Fields:

Validators:

requests pydantic-field

Wire key AHL

The help requests

seconds_since_repair_help pydantic-field

seconds_since_repair_help: ClientInt = -1

Wire key TSL

Seconds since you last asked for repair help; -1 when never

repair_help_cooldown_seconds property

repair_help_cooldown_seconds: int

Seconds until you may ask for repair help again, 0 when you may now.

AllianceHelpRequestChanged pydantic-model

Bases: BaseResponse

One help request added to the list or changed on it, pushed by the server.

Command: ahh Payload: the request's own keys, plus TSL

Client: AHHCommand.executeCommand (bundle line 121889), AllianceHelpRequestData.parse_AHH (bundle line 133394) replaces the entry with the same LID or adds it

Fields:

Validators:

  • _request_is_the_payload

request pydantic-field

request: AllianceHelpRequest | None = None

The request; None when unreadable

seconds_since_repair_help pydantic-field

seconds_since_repair_help: ClientInt | None = None

Wire key TSL

Seconds since you last asked for repair help; -1 when never

AllianceHelpRequestRemoved pydantic-model

Bases: BaseResponse

One help request taken off the list, pushed by the server.

Command: ahd

Client: AHDCommand.executeCommand (bundle line 121859), AllianceHelpRequestData.parse_AHD (bundle line 133396)

Fields:

list_id pydantic-field

list_id: ClientInt = 0

Wire key LID

The removed request's id

AllianceHelpReceived pydantic-model

Bases: BaseResponse

Someone helped one of your requests, pushed by the server.

Command: ahf

Client: AHFCommand.executeCommand (bundle line 121874), AllianceHelpRequestData.parse_AHF (bundle line 133384); the feedback component reads WID as a building's wod id (bundle line 133498)

Fields:

helper_name pydantic-field

helper_name: str | None = None

Wire key PN

The helping player's name

list_id pydantic-field

list_id: ClientInt = 0

Wire key LID

Your request's id

building_wod_id pydantic-field

building_wod_id: ClientInt = 0

Wire key WID

The helped building's wod id; 0 for none

HelpMemberRequest pydantic-model

Bases: BaseRequest

Help one request on the alliance help list.

Command: ahc Payload: {"LID": list_id, "KID": 1}

The client always sends KID 1, WorldDessert.KINGDOM_ID (dll line 20019).

Client: C2SAllianceHelpConfirmedVO (bundle line 105302), sent by AllianceHelpRequestScrollItem.onMouseClick (bundle line 105288)

Fields:

list_id pydantic-field

list_id: int

Wire key LID

The request's AllianceHelpRequest.list_id

kingdom_id pydantic-field

kingdom_id: int = 1

Wire key KID

Always 1, as the client sends it

for_request classmethod

for_request(request: AllianceHelpRequest) -> HelpMemberRequest

Help request.

HelpAllRequest pydantic-model

Bases: BaseRequest

Help every request on the alliance help list.

Command: aha Payload: {"KID": 15}

Client: C2SAllianceHelpAllRequestVO (bundle line 105268) defaults KID to 15 and CastleAllianceActionOverviewDialogHelpRequest.onClick (bundle line 105247) sends it with that default

Fields:

kingdom_id pydantic-field

kingdom_id: int = 15

Wire key KID

Always 15, as the client sends it

AskHelpRequest pydantic-model

Bases: BaseRequest

Ask the alliance for help.

Command: ahr Payload: {"ID": target_id, "T": type}

For heal help the client puts the hospital list id in T, not a help type.

Client: C2SAllianceHelpRequestVO (bundle line 36196), sent by RingMenuButtonConstructionHelpRequest.onClick (bundle line 49994), RingMenuButtonRepairHelpRequest.onClick (bundle line 81402) and CastleAllianceHelpRequestButtonComponent.onClick (bundle line 50836)

Fields:

target_id pydantic-field

target_id: int

Wire key ID

The building, recruitment or hospital entry to help

type_id pydantic-field

type_id: int

Wire key T

The HelpType, or for heal help the hospital list id

build classmethod

build(building_id: int) -> AskHelpRequest

Ask for help building building_id, the building's object id.

repair classmethod

repair(building_id: int) -> AskHelpRequest

Ask for help repairing building_id, the building's object id.

recruit classmethod

recruit(recruit_id: int, help_type: HelpType) -> AskHelpRequest

Ask for help with the recruitment recruit_id; help_type is one of the three recruit types.

heal classmethod

heal(hospital_entry_id: int, hospital_list_id: int) -> AskHelpRequest

Ask for help healing the hospital entry hospital_entry_id on list hospital_list_id.

AskHelpResponse pydantic-model

Bases: BaseResponse

The answer to asking for help; it carries nothing the client reads.

Command: ahr

Client: AHRCommand.executeCommand (bundle line 121919)

Fields:

alliance.models.info

Alliance info models.

Commands:

  • ain: Get alliance info (includes member list)

Classes:

Name Description
AllianceMember

One member of an ain reply's M list: an owner record.

AllianceBuilding

Alliance building info from ABL array.

AllianceStorage

The alliance treasury, the STO block.

AllianceMemberInfo

A member's extra alliance info: one AMI row.

AllianceDiplomacyStatus

The alliance's standing with one other alliance: an ADL entry.

PeaceOffer

An open peace offer between this alliance and yours: the ain block's PO.

CrestLayout

One crest layout the alliance holds: an entry of the ain block's ACLS.

AllianceCrests

The alliance's crest and its fallback: the ain block's aee.

AllianceInfo

Full alliance information from ain response.

GetAllianceInfoRequest

Request alliance information including member list.

GetAllianceInfoResponse

Response containing alliance information.

logger module-attribute

logger = logging.getLogger(__name__)

StorageAmount module-attribute

AllianceMember pydantic-model

Bases: PlayerProfileBase

One member of an ain reply's M list: an owner record.

The member's login activity comes from the alliance's AMI row for it (AllianceMemberInfo.login_activity), an OnlineState value.

Client: AllianceInfoVO.parseMemberList (bundle line 25968) reads each entry with CastleOtherPlayerData.parseOwnerInfo (bundle line 138996)

Fields:

member_info property

member_info: AllianceMemberInfo | None

The member's AMI row: donations, login activity and landmark counts; None when the reply has none.

Client: AllianceInfoVO.getAdditionalMemberInfos (bundle line 25979)

activity_tier property

activity_tier: int | None

The member's login activity, an OnlineState value; None when the reply has no AMI row.

is_online property

is_online: bool

Whether the member is online now.

Client: AllianceInfoVO.getOnlineUserList (bundle line 25980)

AllianceBuilding pydantic-model

Bases: BasePayload

Alliance building info from ABL array.

Fields:

building_type pydantic-field

building_type: int = 0

Wire key BT

level pydantic-field

level: int = 0

Wire key L

cooldown pydantic-field

cooldown: int = -1

Wire key CD

AllianceStorage pydantic-model

Bases: BasePayload

The alliance treasury, the STO block.

The client reads one key per allianceFundsDonatables row of the item data, so a later items version can add keys; these are the rows of v786.03. On an alliance battle ground server it reads the event's alliance currency instead of AIN; that key stays in the model's extra fields.

Client: AllianceInfoVO.parseStorageFromServer (bundle line 25940), each key from CollectableHelper.getServerKeyByCollectable (bundle line 1646) over AllianceFundsDonatableVO (bundle line 66532); amounts floored by ACollectableItemVO.amount (bundle line 3575)

Fields:

wood pydantic-field

wood: StorageAmount = 0

Wire key W

Wood

stone pydantic-field

stone: StorageAmount = 0

Wire key S

Stone

coins pydantic-field

coins: StorageAmount = 0

Wire key C1

Coins

rubies pydantic-field

rubies: StorageAmount = 0

Wire key C2

Rubies

iron pydantic-field

iron: StorageAmount = 0

Wire key I

Iron

oil pydantic-field

oil: StorageAmount = 0

Wire key O

Olive oil

glass pydantic-field

glass: StorageAmount = 0

Wire key G

Glass

coal pydantic-field

coal: StorageAmount = 0

Wire key C

Charcoal

fury_doubloons pydantic-field

fury_doubloons: StorageAmount = 0

Wire key FD

Fury doubloons

time_doubloons pydantic-field

time_doubloons: StorageAmount = 0

Wire key TD

Time doubloons

spirit_doubloons pydantic-field

spirit_doubloons: StorageAmount = 0

Wire key SD

Spirit doubloons

vigor_doubloons pydantic-field

vigor_doubloons: StorageAmount = 0

Wire key VD

Vigor doubloons

bastion_doubloons pydantic-field

bastion_doubloons: StorageAmount = 0

Wire key BD

Bastion doubloons

rampart_doubloons pydantic-field

rampart_doubloons: StorageAmount = 0

Wire key RD

Rampart doubloons

alliance_coins pydantic-field

alliance_coins: StorageAmount = 0

Wire key AC

Alliance coins

rift_coins pydantic-field

rift_coins: StorageAmount = 0

Wire key RC

Rift coins

legendary_rift_coins pydantic-field

legendary_rift_coins: StorageAmount = 0

Wire key LRC

Legendary rift coins

alliance_influence pydantic-field

alliance_influence: StorageAmount = 0

Wire key AIN

Alliance influence; only on alliance battle ground servers

AllianceMemberInfo pydantic-model

Bases: BasePayload

A member's extra alliance info: one AMI row.

Client: AdditionalMemberInfoVO.parseAMI (bundle line 66296) shifts the fields off in this order and reads each with int, so a missing field is 0.

Fields:

Validators:

  • _from_row

player_id pydantic-field

player_id: ClientInt = 0

The member's player id

given_coins pydantic-field

given_coins: ClientInt = 0

Coins the member donated to the alliance

given_rubies pydantic-field

given_rubies: ClientInt = 0

Rubies the member donated to the alliance

given_resources pydantic-field

given_resources: ClientInt = 0

Resources the member donated

login_activity pydantic-field

login_activity: ClientInt = 0

0 online, 1 last 12 hours, 2 last 48 hours, 3 last week, 4 longer ago

capital_count pydantic-field

capital_count: ClientInt = 0

Capitals the member holds

metropolis_count pydantic-field

metropolis_count: ClientInt = 0

Metropolises the member holds

kings_tower_count pydantic-field

kings_tower_count: ClientInt = 0

Kings towers the member holds

monument_count pydantic-field

monument_count: ClientInt = 0

Monuments the member holds

laboratory_count pydantic-field

laboratory_count: ClientInt = 0

Laboratories the member holds

daily_fame pydantic-field

daily_fame: ClientInt = 0

Fame gained today

login_activity_enum property

login_activity_enum: OnlineState | None

login_activity as an OnlineState, None for a value the client does not define.

AllianceDiplomacyStatus pydantic-model

Bases: BasePayload

The alliance's standing with one other alliance: an ADL entry.

Client: AllianceInfoVO.parseStatusList (bundle line 25973) into an OtherAllianceStatusListItemVO (bundle line 66330).

Fields:

alliance_id pydantic-field

alliance_id: ClientInt = 0

Wire key AID

The other alliance

alliance_name pydantic-field

alliance_name: str | None = None

Wire key AN

The other alliance's name

status pydantic-field

status: ClientInt = 0

Wire key AS

0 at war, 1 neutral, 2 soft allied, 3 real allied

status_confirmed pydantic-field

status_confirmed: ClientInt = 0

Wire key AC

1 once agreed, 0 while only requested

status_enum property

status_enum: DiplomacyStatus | None

status as a DiplomacyStatus, None for a value the client does not define.

PeaceOffer pydantic-model

Bases: BasePayload

An open peace offer between this alliance and yours: the ain block's PO.

Client: AllianceInfoVO.fillFromParamObject (bundle line 25928) reads T and TS into a PeaceOfferVO (bundle line 42688)

Fields:

Validators:

tribute pydantic-field

tribute: ClientInt = 0

Wire key T

The tribute percentage, negative when demanded

remaining_seconds pydantic-field

remaining_seconds: int | float = 0

Wire key TS

Seconds until the offer ends

is_demanded property

is_demanded: bool

Whether the tribute is demanded rather than offered: a negative T.

tribute_percentage property

tribute_percentage: int

The tribute offered or demanded, as a positive percentage.

CrestLayout pydantic-model

Bases: BasePayload

One crest layout the alliance holds: an entry of the ain block's ACLS.

The client stores the colours from ACLCS and never reads them; live replies have been seen carrying ACCS there instead, which stays in the extra fields.

Client: AllianceInfoVO.fillFromParamObject (bundle line 25932)

Fields:

Validators:

layout_id pydantic-field

layout_id: EnumOrInt['AllianceCrestLayout'] | None = None

Wire key ACLI

The crest layout; None when the entry names none

seconds_left pydantic-field

seconds_left: int | float = 0

Wire key ACLET

Seconds until the layout ends

is_active pydantic-field

is_active: bool = False

Wire key ACIA

The layout is the one in use

color_ids pydantic-field

color_ids: tuple[Annotated[EnumOrInt['AllianceCrestColor'], BeforeValidator(js_int)], ...] | None = None

Wire key ACLCS

The layout's colours, as ACCS names them; None when unsent

AllianceCrests pydantic-model

Bases: BasePayload

The alliance's crest and its fallback: the ain block's aee.

Client: CastleAllianceData.parseAllianceCrestForAlliance (bundle line 11589); AllianceInfoVO.parseFallbackCrest (bundle line 26146) keeps ACFB only when it has both ACLI and ACCS

Fields:

Validators:

crest pydantic-field

crest: AllianceCrest | None = None

Wire key ACCA

The current crest; None when unsent, where the client draws a random one

fallback_crest pydantic-field

fallback_crest: AllianceCrest | None = None

Wire key ACFB

The fallback crest

AllianceInfo pydantic-model

Bases: BasePayload

Full alliance information from ain response.

Contains alliance details, member list, buildings, storage, etc.

Client: AllianceInfoVO.fillFromParamObject (bundle line 25928), parseMemberList (bundle line 25968), parseStorageFromServer (bundle line 25940), parseBuffList (bundle line 25955); CastleAllianceData.parseAllianceInfo (bundle line 11609) for RT

Fields:

Validators:

alliance_id pydantic-field

alliance_id: ParseInt = 0

Wire key AID

Alliance id

name pydantic-field

name: str = ''

Wire key N

Alliance name

members pydantic-field

members: list[AllianceMember]

Wire key M

Members, highest rank first

fame_points pydantic-field

fame_points: ClientInt = 0

Wire key CF

Alliance fame points

highest_fame_points pydantic-field

highest_fame_points: ParseInt = 0

Wire key HF

Highest fame points reached

might pydantic-field

might: ParseInt = 0

Wire key MP

Alliance might points

highest_alliance_might pydantic-field

highest_alliance_might: ParseInt = 0

Wire key HAMP

Highest might points reached

description pydantic-field

description: str = ''

Wire key D

The alliance's description, decoded as chat text

announcement pydantic-field

announcement: str = ' '

Wire key A

The alliance's announcement; " " when it has none

language pydantic-field

language: str = 'en'

Wire key ALL

The alliance's language code

external_member_level pydantic-field

external_member_level: ParseInt = 0

Wire key ML

External member level

status_to_own_alliance pydantic-field

status_to_own_alliance: ParseInt = 0

Wire key DOA

Diplomacy status towards the player's own alliance, a DiplomacyStatus value

is_searching_members pydantic-field

is_searching_members: bool = False

Wire key IS

The alliance is looking for players

is_accepting_members pydantic-field

is_accepting_members: bool = False

Wire key IA

Players may apply to join

application_count pydantic-field

application_count: ParseInt = 12

Wire key AA

Pending applications

auto_war pydantic-field

auto_war: bool = False

Wire key AW

Auto war is on

aqua_points pydantic-field

aqua_points: int | float = 0

Wire key AP

Aqua points

free_renames pydantic-field

free_renames: ClientInt = 0

Wire key FR

Free alliance renames left

can_be_invited_to_hard_pact pydantic-field

can_be_invited_to_hard_pact: bool = False

Wire key HP

Open to hard pact invitations

can_be_invited_to_soft_pact pydantic-field

can_be_invited_to_soft_pact: bool = False

Wire key SP

Open to soft pact invitations

is_able_to_forge pydantic-field

is_able_to_forge: bool = False

Wire key MF

The alliance forge can be used

is_forge_inventory_full pydantic-field

is_forge_inventory_full: bool = False

Wire key IF

The alliance forge inventory is full

soft_relic_forge_uses pydantic-field

soft_relic_forge_uses: ClientInt = 0

Wire key SRFU

Soft relic forge uses

hard_relic_forge_uses pydantic-field

hard_relic_forge_uses: ClientInt = 0

Wire key HRFU

Hard relic forge uses

is_king_alliance pydantic-field

is_king_alliance: bool = False

Wire key KA

The alliance holds the king title

refresh_seconds pydantic-field

refresh_seconds: ClientInt = 0

Wire key RT

Seconds until the alliance should be requested again; 0 when none is set

peace_offer pydantic-field

peace_offer: PeaceOffer | None = None

Wire key PO

The open peace offer with your alliance; None when there is none

crest_layouts pydantic-field

crest_layouts: list[CrestLayout]

Wire key ACLS

The crest layouts the alliance holds

crests pydantic-field

crests: AllianceCrests | None = None

Wire key aee

The alliance's crest

storage pydantic-field

storage: AllianceStorage | None = None

Wire key STO

Alliance storage

buildings pydantic-field

buildings: list[AllianceBuilding]

Wire key ABL

Alliance buffs

member_info pydantic-field

member_info: list[AllianceMemberInfo]

Wire key AMI

Donations, activity and landmark counts per member

alliance_diplomacy pydantic-field

alliance_diplomacy: list[AllianceDiplomacyStatus]

Wire key ADL

The alliance's standing with other alliances

capitals pydantic-field

capitals: list[MapAreaItem]

Wire key ACA

Map rows of the alliance's capitals

metropolises pydantic-field

metropolises: list[MapAreaItem]

Wire key ATC

Map rows of the alliance's metropolises

kings_towers pydantic-field

kings_towers: list[MapAreaItem]

Wire key AKT

Map rows of the alliance's kings towers

monuments pydantic-field

monuments: list[MapAreaItem]

Wire key AMO

Map rows of the alliance's monuments

laboratories pydantic-field

laboratories: list[MapAreaItem]

Wire key ALA

Map rows of the alliance's laboratories

status_to_own_alliance_enum property

status_to_own_alliance_enum: DiplomacyStatus | None

status_to_own_alliance as a DiplomacyStatus, None for a value the client does not define.

member_count property

member_count: int

Get the number of members.

online_members property

online_members: list[AllianceMember]

Get list of currently online members.

online_count property

online_count: int

Get count of online members.

leader property

leader: AllianceMember | None

The member with rank 0, None when there is none.

Client: AllianceInfoVO.allianceLeader (bundle line 25986)

model_post_init

model_post_init(__context: Any) -> None

Give each member its AMI row.

Client: AllianceInfoVO.parseAMI (bundle line 25947) keys the rows by player id; a later row wins.

GetAllianceInfoRequest pydantic-model

Bases: BaseRequest

Request alliance information including member list.

Command: ain Payload: {"AID": alliance_id}

Returns full alliance info with all members, their online status (via AMI array), level, rank, castle count, and might.

Client: C2SGetAllianceInfoVO (bundle line 9760)

Fields:

alliance_id pydantic-field

alliance_id: int

Wire key AID

Your own is client.alliance.local_alliance_id; another is an AllianceSearchResult.alliance_id from client.alliance.search_alliances()

accepts_reply

accepts_reply(payload: Any) -> bool

Whether an ain reply is about this alliance: its A.AID, when sent, is AID.

Client: AINCommand (bundle line 121461) hands A to CastleAllianceData.parseAllianceInfo (bundle line 11605), which keys it by int(A.AID) and reads nothing without one.

GetAllianceInfoResponse pydantic-model

Bases: BaseResponse

Response containing alliance information.

Command: ain Payload: {"A": {"AID": ..., "N": ..., "M": [...], ...}}

Client: AINCommand.executeCommand (bundle line 121461)

Fields:

Validators:

alliance pydantic-field

alliance: AllianceInfo | None = None

Wire key A

The alliance; None without an AID

members property

members: list[AllianceMember]

Convenience accessor for alliance members.

online_members property

online_members: list[AllianceMember]

Get list of currently online members.

alliance_block

alliance_block(value: Any) -> Any

An alliance block to read, or None: one without an AID is not read.

Client: CastleAllianceData.parseAllianceInfo (bundle line 11605)

alliance_of_ain

alliance_of_ain(value: Any) -> Any

The alliance block of an ain reply nested in another reply, or None.

Client: CastleAllianceData.parse_AIN (bundle line 11560)

alliance.models.members

Alliance member management.

Commands:

  • akm: Kick a member
  • arm: Change a member's rank
  • aip: Invite a player
  • aal: The alliance's applications
  • aaa: Answer an application
  • aqi: Leave the alliance

Classes:

Name Description
KickMemberRequest

Remove a member from your alliance.

KickMemberResponse

The alliance after a kick.

RerankMemberRequest

Give a member another rank; rank 0 hands over the leadership.

RerankMemberResponse

The alliance after a rank change.

InvitePlayerRequest

Invite a player to your alliance.

InvitePlayerResponse

The answer to an invitation; INVALID_PLAYER_ID when there is no such player.

AllianceApplicationListRequest

Ask for your alliance's applications.

AllianceApplication

One application to join your alliance.

AllianceApplicationListResponse

Your alliance's applications, with the applicants' owner records.

AnswerApplicationRequest

Accept or refuse an application.

AnswerApplicationResponse

The answer to answering an application; the client reads nothing from it.

QuitAllianceRequest

Leave your alliance.

QuitAllianceResponse

The answer to leaving; its gal block stays in the extra fields.

logger module-attribute

logger = logging.getLogger(__name__)

KickMemberRequest pydantic-model

Bases: BaseRequest

Remove a member from your alliance.

Command: akm Payload: {"PID": player_id}

Client: C2SAllianceKickMemberVO (bundle line 70354), sent by CastleAllianceMemberSettingsDialog.onKickMember (bundle line 70332)

Fields:

player_id pydantic-field

player_id: int

Wire key PID

The member's AllianceMember.player_id

KickMemberResponse pydantic-model

Bases: _AllianceEcho

The alliance after a kick.

Command: akm

Client: AKMCommand.executeCommand (bundle line 121513)

Fields:

Validators:

  • _alliance → alliance

RerankMemberRequest pydantic-model

Bases: BaseRequest

Give a member another rank; rank 0 hands over the leadership.

Command: arm Payload: {"PID": player_id, "R": rank}

Client: C2SAllianceRerankMemberVO (bundle line 70363), sent by CastleAllianceMemberSettingsDialog.changeMemberRank (bundle line 70333) and sendNewLeader (bundle line 70320)

Fields:

player_id pydantic-field

player_id: int

Wire key PID

The member's AllianceMember.player_id

rank pydantic-field

Wire key R

The new rank

RerankMemberResponse pydantic-model

Bases: _AllianceEcho

The alliance after a rank change.

Command: arm

Client: ARMCommand.executeCommand (bundle line 121589); it takes NO_CHANGE as nothing to do

Fields:

Validators:

  • _alliance → alliance

InvitePlayerRequest pydantic-model

Bases: BaseRequest

Invite a player to your alliance.

Command: aip Payload: {"SV": "player_id"}

Both call sites send the player's id as a string, not a name.

Client: C2SAllianceInvitePlayerVO (bundle line 42819), sent by CastlePlayerInfoDialog.onInvitePlayerToAlliance (bundle line 3928) and CastleMapobjectInfoComponent.onInvitePlayerToAlliance (bundle line 66485)

Fields:

search_value pydantic-field

search_value: str

Wire key SV

The player's id, as a string

for_player classmethod

for_player(player_id: int) -> InvitePlayerRequest

Invite the player player_id.

InvitePlayerResponse pydantic-model

Bases: BaseResponse

The answer to an invitation; INVALID_PLAYER_ID when there is no such player.

Command: aip

Client: AIPCommand.executeCommand (bundle line 121476)

Fields:

AllianceApplicationListRequest pydantic-model

Bases: BaseRequest

Ask for your alliance's applications.

Command: aal Payload: {}

Client: C2SAllianceApplicationListVO (bundle line 70138)

AllianceApplication pydantic-model

Bases: BasePayload

One application to join your alliance.

Client: AllianceApplicationListItemVO.parseItem (bundle line 66522)

Fields:

Validators:

player_id pydantic-field

player_id: ClientInt = 0

Wire key PID

The applying player's id

distance pydantic-field

distance: ClientInt = 0

Wire key D

Distance to the applicant

text pydantic-field

text: str = ''

Wire key AT

The application's text, decoded

seconds_since_applied pydantic-field

seconds_since_applied: int | float = 0

Wire key AA

Seconds since the application

AllianceApplicationListResponse pydantic-model

Bases: BaseResponse

Your alliance's applications, with the applicants' owner records.

Command: aal

Client: AALCommand.executeCommand (bundle line 121217) reads OI with parseOwnerInfoArray and AL with CastleAllianceData.parse_AAL (bundle line 11590), which sorts the applications by distance

Fields:

Validators:

applications pydantic-field

applications: list[AllianceApplication]

Wire key AL

The applications, nearest first

owners pydantic-field

Wire key OI

The applicants

owner_of

owner_of(application: AllianceApplication) -> PlayerProfileBase | None

The applicant's owner record, None when the reply has none.

AnswerApplicationRequest pydantic-model

Bases: BaseRequest

Accept or refuse an application.

Command: aaa Payload: {"PID": player_id, "A": 1 or 0}

Client: C2SAllianceAnswerApplicationVO (bundle line 70244), sent by CastleAllianceReadApplicationDialog.onAcceptApplication and onDenyApplication (bundle line 70231)

Fields:

player_id pydantic-field

player_id: int

Wire key PID

The applicant's AllianceApplication.player_id

accept pydantic-field

accept: int

Wire key A

1 to accept, 0 to refuse

create classmethod

create(player_id: int, accept: bool) -> AnswerApplicationRequest

AnswerApplicationResponse pydantic-model

Bases: BaseResponse

The answer to answering an application; the client reads nothing from it.

Command: aaa

Client: AAACommand.executeCommand (bundle line 121191)

Fields:

QuitAllianceRequest pydantic-model

Bases: BaseRequest

Leave your alliance.

Command: aqi Payload: {}

Client: C2SAllianceQuitVO (bundle line 69639), sent by CastleAllianceDialogManagement.quitAlliance (bundle line 69616)

QuitAllianceResponse pydantic-model

Bases: BaseResponse

The answer to leaving; its gal block stays in the extra fields.

Command: aqi

Client: AQICommand.executeCommand (bundle line 121556)

Fields:

alliance.models.bookmarks

Map bookmarks, your own and your alliance's.

Commands:

  • gbl: Your own and your alliance's bookmarks
  • bad / bch / bde / abd: Add, change and delete a bookmark; abd deletes an alliance bookmark

Classes:

Name Description
GetBookmarksRequest

Ask for your own and your alliance's map bookmarks.

BookmarkAttackOrder

The attack order an alliance attack order bookmark carries.

Bookmark

One map bookmark: an entry of a gbl reply's BL or ABL.

GetBookmarksResponse

Your own and your alliance's map bookmarks.

AddBookmarkRequest

Bookmark a map position, for yourself or for your alliance.

AddBookmarkResponse

The bookmark added, read as a gbl entry.

ChangeBookmarkRequest

Rename one of your own bookmarks, or switch it between friend and enemy.

ChangeBookmarkResponse

The bookmark changed, read as a gbl entry.

DeleteBookmarkRequest

Delete own bookmarks by their positions.

BookmarkPosition

Where a deleted bookmark was.

DeleteBookmarkResponse

The own bookmarks deleted.

DeleteAllianceBookmarkRequest

Delete alliance bookmarks by their ids.

DeleteAllianceBookmarkResponse

Acknowledgement of a deleted alliance bookmark; the client reads nothing from it.

Attributes:

Name Type Description
BOOKMARK_NAME_MAX_LENGTH

The longest bookmark name the client's bookmark dialog takes: twice the castle name's limit.

MAX_PLAYER_BOOKMARKS

How many own bookmarks a player keeps.

MAX_ALLIANCE_BOOKMARKS

How many bookmarks an alliance keeps.

ATTACK_ORDER_MIN_SECONDS

The soonest an alliance attack order may be set, in seconds from now.

ATTACK_ORDER_MAX_SECONDS

The latest an alliance attack order may be set, in seconds from now.

logger module-attribute

logger = logging.getLogger(__name__)

BOOKMARK_NAME_MAX_LENGTH module-attribute

BOOKMARK_NAME_MAX_LENGTH = 30

The longest bookmark name the client's bookmark dialog takes: twice the castle name's limit.

Client: CastleWorldmapBookmarkSetDialog.initLoaded (bundle line 19546) sets maxChars to 2 * PlayerConst.CASTLE_NAME_MAX_LENGTH (dll line 19599)

MAX_PLAYER_BOOKMARKS module-attribute

MAX_PLAYER_BOOKMARKS = 50

How many own bookmarks a player keeps.

Client: PlayerConst.BOOKMARKS_MAX_ENTRYS (dll line 19599), read by CastleBookmarkData.isPlayerListFull

MAX_ALLIANCE_BOOKMARKS module-attribute

MAX_ALLIANCE_BOOKMARKS = 20

How many bookmarks an alliance keeps.

Client: AllianceConst.ALLIANCE_BOOKMARK_MAX_ENTRIES (dll line 18805), read by CastleBookmarkData.isAllianceListFull

ATTACK_ORDER_MIN_SECONDS module-attribute

ATTACK_ORDER_MIN_SECONDS = 3600

The soonest an alliance attack order may be set, in seconds from now.

Client: AllianceConst.ALLIANCE_BOOKMARK_MIN_TIME_OFFSET (dll line 18782), checked by TeamAttackConfiguration (bundle line 68564)

ATTACK_ORDER_MAX_SECONDS module-attribute

ATTACK_ORDER_MAX_SECONDS = 86340

The latest an alliance attack order may be set, in seconds from now.

Client: AllianceConst.ALLIANCE_BOOKMARK_MAX_TIME_OFFSET (dll line 18783), checked by TeamAttackConfiguration (bundle line 68564)

GetBookmarksRequest pydantic-model

Bases: BaseRequest

Ask for your own and your alliance's map bookmarks.

Command: gbl Payload: {}

Client: C2SGetBookmarkList (bundle line 25872)

BookmarkAttackOrder pydantic-model

Bases: BasePayload

The attack order an alliance attack order bookmark carries.

Client: CastleBookmarkAttackOrderDetailsVO.parseParamObject (bundle line 68503)

Fields:

Validators:

assigned_attacker_ids pydantic-field

assigned_attacker_ids: list[int]

Wire key M

The players sent to attack

attack_in_seconds pydantic-field

attack_in_seconds: int | float | None = None

Wire key TI

Seconds until the attack; None when the reply has no number for it

Bookmark pydantic-model

Bases: BasePayload

One map bookmark: an entry of a gbl reply's BL or ABL.

Client: CastleBookmarkData.parseBookmarkObject (bundle line 33427) reads OI as an owner record, then CastleWorldmapBookmarkVO.parseParamObject (bundle line 68469) reads the rest.

Fields:

Validators:

kingdom pydantic-field

kingdom: ClientInt = 0

Wire key KID

The bookmarked area's kingdom

x pydantic-field

x: ClientInt = 0

Wire key X

Map x

y pydantic-field

y: ClientInt = 0

Wire key Y

Map y

area pydantic-field

area: MapAreaItem | None = None

Wire key AI

The bookmarked map row

owner pydantic-field

owner: PlayerProfileBase | None = None

Wire key OI

The owner record of the bookmarked area

name pydantic-field

name: str | None = None

Wire key N

The bookmark's name

bookmark_type pydantic-field

bookmark_type: int | None = None

Wire key TY

What the bookmark marks, a BookmarkType value

bookmark_id pydantic-field

bookmark_id: ClientInt = 0

Wire key BID

The bookmark's id

creator_id pydantic-field

creator_id: ClientInt = 0

Wire key C

The player who made it; 0 when unsent

attack_order pydantic-field

attack_order: BookmarkAttackOrder | None = None

The attack order; only on alliance attack order bookmarks

bookmark_type_enum property

bookmark_type_enum: BookmarkType | None

bookmark_type as a BookmarkType, None for a type the client does not define.

GetBookmarksResponse pydantic-model

Bases: BaseResponse

Your own and your alliance's map bookmarks.

Command: gbl

Client: GBLCommand.executeCommand (bundle line 131706), CastleBookmarkData.parse_GBL (bundle line 33453)

Fields:

Validators:

own_bookmarks pydantic-field

own_bookmarks: list[Bookmark]

Wire key BL

Your own bookmarks

alliance_bookmarks pydantic-field

alliance_bookmarks: list[Bookmark]

Wire key ABL

Your alliance's bookmarks

AddBookmarkRequest pydantic-model

Bases: BaseRequest

Bookmark a map position, for yourself or for your alliance.

Command: bad Payload: {"K", "X", "Y", "TY", "TI", "IM", "N", "M"}, in the client's key order

Only an alliance attack order carries its time (TI, seconds from now), its attackers (M) and whether they get a message (IM); every other bookmark sends -1, [] and 0. The name goes out as typed.

Client: C2SAddBookmark (bundle line 68517), sent by CastleWorldmapBookmarkSetDialog.onSubmitButtonClicked (bundle line 19584); the attack order's seconds from TeamAttackConfiguration.updateDateAndTimeDisplay (bundle line 68566)

Fields:

kingdom pydantic-field

kingdom: int

Wire key K

The kingdom

x pydantic-field

x: int

Wire key X

Map x

y pydantic-field

y: int

Wire key Y

Map y

bookmark_type pydantic-field

bookmark_type: int

Wire key TY

What it marks, a BookmarkType value

attack_in_seconds pydantic-field

attack_in_seconds: int = -1

Wire key TI

Seconds until the attack order's attack; -1 for any other bookmark

message_attackers pydantic-field

message_attackers: int = 0

Wire key IM

1 to send the attack order's attackers a message, else 0

name pydantic-field

name: str

Wire key N

The bookmark's name

attacker_ids pydantic-field

attacker_ids: list[int]

Wire key M

The players the attack order sends; empty for any other

AddBookmarkResponse pydantic-model

Bases: BaseResponse, Bookmark

The bookmark added, read as a gbl entry.

Command: bad

Client: BADCommand.executeCommand (bundle line 131653) passes the reply to CastleBookmarkData.parse_BAD (bundle line 33442), which reads it with parseBookmarkObject (bundle line 33427)

Fields:

Validators:

ChangeBookmarkRequest pydantic-model

Bases: BaseRequest

Rename one of your own bookmarks, or switch it between friend and enemy.

Command: bch Payload: {"KID", "X", "Y", "IF", "DN"}, in the client's key order

Client: C2SChangeBookmark (bundle line 68532), sent by CastleWorldmapBookmarkSetDialog.onSubmitButtonClicked (bundle line 19584) only for an own bookmark the dialog edits; IF is !!typeIndex

Fields:

kingdom pydantic-field

kingdom: int

Wire key KID

The bookmark's kingdom

x pydantic-field

x: int

Wire key X

Map x

y pydantic-field

y: int

Wire key Y

Map y

friend pydantic-field

friend: bool

Wire key IF

True for a friend bookmark, False for an enemy one

name pydantic-field

name: str

Wire key DN

The new name

ChangeBookmarkResponse pydantic-model

Bases: BaseResponse, Bookmark

The bookmark changed, read as a gbl entry.

Command: bch

Client: BCHCommand.executeCommand (bundle line 131672), CastleBookmarkData.parse_BCH (bundle line 33443)

Fields:

Validators:

DeleteBookmarkRequest pydantic-model

Bases: BaseRequest

Delete own bookmarks by their positions.

Command: bde Payload: {"BM": [[kingdom, x, y], ...]}

Client: C2SDeleteBookmark (bundle line 68457), sent by CastleBookmarkData.deleteBookmark and deleteBookmarks (bundle lines 33474-33475) for an own bookmark

Fields:

positions pydantic-field

positions: list[list[int]]

Wire key BM

Each bookmark's [kingdom, x, y]

BookmarkPosition pydantic-model

Bases: BasePayload

Where a deleted bookmark was.

Client: CastleBookmarkData.parse_BDE (bundle line 33445) reads K, X and Y

Fields:

kingdom pydantic-field

kingdom: ClientInt = 0

Wire key K

The kingdom

x pydantic-field

x: ClientInt = 0

Wire key X

Map x

y pydantic-field

y: ClientInt = 0

Wire key Y

Map y

DeleteBookmarkResponse pydantic-model

Bases: BaseResponse

The own bookmarks deleted.

Command: bde

Client: BDECommand.executeCommand (bundle line 131687), CastleBookmarkData.parse_BDE (bundle line 33445): the BM list, else the reply itself as one position

Fields:

Validators:

  • _one_or_many
  • _positions → deleted

deleted pydantic-field

Wire key BM

The positions deleted

DeleteAllianceBookmarkRequest pydantic-model

Bases: BaseRequest

Delete alliance bookmarks by their ids.

Command: abd Payload: {"BM": [[bookmark_id, notify], ...]}

notify is 1 to tell an attack order's attackers, as the delete dialog's notify button does.

Client: C2SDeleteAllianceBookmark (bundle line 68446), sent by CastleBookmarkData.deleteBookmark (bundle line 33474) from CastleDeleteAllianceBookmarkDialog.deleteBookmark (bundle line 69192)

Fields:

entries pydantic-field

entries: list[list[int]]

Wire key BM

Each bookmark's [bookmark_id, notify]

DeleteAllianceBookmarkResponse pydantic-model

Bases: BaseResponse

Acknowledgement of a deleted alliance bookmark; the client reads nothing from it.

Command: abd Client: ABDCommand.executeCommand (bundle line 131636)

Fields:

alliance.models.search

Alliance search.

Commands:

  • hgh: Search alliances

Classes:

Name Description
AllianceSearchResult

One row of an alliance highscore list: [rank, score, [alliance_id, name, member_count, fame_points]].

SearchAllianceRequest

Search for an alliance.

SearchAllianceResponse

Response to alliance search.

logger module-attribute

logger = logging.getLogger(__name__)

AllianceSearchResult pydantic-model

Bases: BasePayload

One row of an alliance highscore list: [rank, score, [alliance_id, name, member_count, fame_points]].

Client: CastleHighscoreDialog.onGetHighscoreData (bundle line 27538) shifts rank and score off an alliance list's row and fills an AllianceHighscoreInfoVO (bundle line 27680) from the third field, which it ignores unless that is an array. Every number is read with int.

Fields:

Validators:

  • _from_row

rank pydantic-field

rank: ClientInt = 0

Rank on the list

score pydantic-field

score: ClientInt = 0

The listed value, the alliance's might on list type 11

alliance_id pydantic-field

alliance_id: ClientInt = 0

Alliance id

name pydantic-field

name: str = ''

Alliance name

member_count pydantic-field

member_count: ClientInt = 0

Number of members

fame_points pydantic-field

fame_points: ClientInt = 0

The alliance's current fame

SearchAllianceRequest pydantic-model

Bases: BaseRequest

Search for an alliance.

Command: hgh Payload: {"LT": 11, "LID": 6, "SV": name_query}

Client: CastleHighscoreDialog.requestHighscoreData (bundle line 27636); 6 is ClientConstHighscore.getLeagueIdByLevel of the level cap (bundle line 45331)

Fields:

list_type pydantic-field

list_type: RankingType = RankingType.ALLIANCE_MIGHT_POINTS

Wire key LT

The highscore list searched

league_type_id pydantic-field

league_type_id: int = 6

Wire key LID

The league to search in; 6 is the level 70 league

search_value pydantic-field

search_value: str

Wire key SV

The alliance name to search for

create classmethod

create(query: str) -> 'SearchAllianceRequest'

SearchAllianceResponse pydantic-model

Bases: BaseResponse

Response to alliance search.

Command: hgh — shared with GetHighscoreResponse, which owns the registry entry; this model is instantiated manually by AllianceService.

Not registered: see class docstring.

Client: HGHCommand.executeCommand (bundle line 124377)

Fields:

Validators:

results pydantic-field

Wire key L

The matching rows