Skip to main content

warcraft3_stats_observer/
player.rs

1use std::fmt::Debug;
2
3use crate::build_queue::BuildQueueInfo;
4use crate::hero::HeroInfo;
5use crate::player_item::PlayerItemInfo;
6use crate::string_utils::PaddedString;
7use crate::structure::StructureInfo;
8use crate::unit::UnitInfo;
9use crate::upgrade::UpgradeInfo;
10
11const MAX_NAME_LENGTH: usize = 36;
12
13/// Maximum number of heroes per player tracked by the observer API.
14pub const MAX_HEROES: usize = 999;
15/// Maximum number of structures per player tracked by the observer API.
16pub const MAX_STRUCTURES: usize = 999;
17/// Maximum number of upgrades per player tracked by the observer API.
18pub const MAX_UPGRADES: usize = 999;
19/// Maximum number of unit kinds per player tracked by the observer API.
20pub const MAX_UNITS: usize = 999;
21/// Maximum number of in-progress build queue entries per player.
22pub const MAX_UNITS_IN_QUEUE: usize = 999;
23/// Maximum number of distinct items collected per player.
24pub const MAX_ITEMS: usize = 999;
25/// Number of upkeep levels reported by the observer API.
26pub const MAX_UPKEEP_LEVELS: usize = 10;
27
28/// Race chosen by the player in the lobby. Bit-flag encoded.
29#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
30#[repr(u8)]
31pub enum RacePreference {
32    Human = 0x01,
33    Orc = 0x02,
34    Nightelf = 0x04,
35    Undead = 0x08,
36    Demon = 0x10,
37    Random = 0x20,
38    UserSelectable = 0x40,
39}
40
41/// Race a player is actually playing.
42#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
43#[repr(u8)]
44pub enum PlayerRace {
45    Unknown = 0,
46    Human = 1,
47    Orc = 2,
48    Undead = 3,
49    NightElf = 4,
50    Demon = 5,
51    Last = 6,
52    Other = 7,
53    Creep = 8,
54    Commoner = 9,
55    Critter = 10,
56    Naga = 11,
57}
58
59/// What occupies a player slot.
60#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
61#[repr(u8)]
62pub enum PlayerType {
63    Empty = 0,
64    Player = 1,
65    Computer = 2,
66    Neutral = 3,
67    Observer = 4,
68    None = 5,
69    Other = 6,
70}
71
72/// End-of-game result for a player.
73#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
74#[repr(u8)]
75pub enum PlayerGameResult {
76    Victory = 0,
77    Defeat = 1,
78    Tie = 2,
79    Neutral = 3,
80}
81
82/// Live state of a player slot.
83#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
84#[repr(u8)]
85pub enum PlayerSlotState {
86    Empty = 0,
87    Playing = 1,
88    Left = 2,
89}
90
91/// Difficulty preference selected for a computer player.
92#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
93#[repr(u8)]
94pub enum AiDifficultyPreference {
95    Newbie = 0,
96    Normal = 1,
97    Insane = 2,
98}
99
100/// Per-player state — name, race, resources, and arrays of heroes,
101/// structures, units, upgrades, items, and build queue entries.
102#[repr(C, packed)]
103pub struct PlayerInfo {
104    /// Display name of the player.
105    pub name: PaddedString<MAX_NAME_LENGTH>,
106    /// Race the player chose in the lobby (may be `Random` or
107    /// `UserSelectable`).
108    pub race_preference: RacePreference,
109    /// Race the player is actually playing this game.
110    pub player_race: PlayerRace,
111    /// Game-internal player ID (slot number).
112    pub id: u8,
113    /// Index of the team the player belongs to.
114    pub team_index: u8,
115    /// Team color index assigned to the player.
116    pub team_color: u8,
117    /// What kind of participant occupies this slot (human, computer, observer, …).
118    pub player_type: PlayerType,
119    /// Handicap percentage (e.g. `100` = no handicap, `50` = 50% max HP).
120    pub handicap: u32,
121    /// End-of-game result, once the game has ended.
122    pub game_result: PlayerGameResult,
123    /// Live state of the player's slot (empty / playing / left).
124    pub slot_state: PlayerSlotState,
125    /// Difficulty selected for this player when [`Self::player_type`]
126    /// is `Computer`.
127    pub ai_difficulty: AiDifficultyPreference,
128    /// Some sort of APM measurement, now sure how it differs from
129    /// [`Self::real_time_actions_per_minute`].
130    pub actions_per_minute: u32,
131    /// Some sort of APM measurement, now sure how it differs from
132    /// [`Self::actions_per_minute`].
133    pub real_time_actions_per_minute: u32,
134    /// Current gold on hand.
135    pub gold: u32,
136    /// Total gold mined this game.
137    pub gold_mined: u32,
138    /// Gold lost to upkeep over the course of the game.
139    pub gold_upkeep_lost: u32,
140    /// Not sure what this is
141    pub gold_diversion_tax: u32,
142    /// Current lumber on hand.
143    pub lumber: u32,
144    /// Total lumber harvested this game.
145    pub lumber_mined: u32,
146    /// Lumber lost to upkeep over the course of the game.
147    pub lumber_upkeep_lost: u32,
148    /// Not sure what this is.
149    pub lumber_diversion_tax: u32,
150    /// Current food cap (maximum population).
151    pub food_cap: u32,
152    /// Current food used (current population).
153    pub food_used: u32,
154    /// Number of valid entries in [`Self::heroes`].
155    pub hero_count: u32,
156    /// Heroes owned by the player.
157    pub heroes: [HeroInfo; MAX_HEROES],
158    /// Number of valid entries in [`Self::structures`].
159    pub structure_count: u32,
160    /// Structures owned by the player.
161    pub structures: [StructureInfo; MAX_STRUCTURES],
162    /// Number of valid entries in [`Self::upgrades`].
163    pub upgrade_count: u32,
164    /// Upgrades available to (researched or in progress by) the player.
165    pub upgrades: [UpgradeInfo; MAX_UPGRADES],
166    /// Number of valid entries in [`Self::units`].
167    pub unit_count: u32,
168    /// Aggregate stats per unit kind owned by the player.
169    pub units: [UnitInfo; MAX_UNITS],
170    /// Number of valid entries in [`Self::units_in_queue`].
171    pub units_in_queue_count: u32,
172    /// In-progress training, research, and revival entries.
173    pub units_in_queue: [BuildQueueInfo; MAX_UNITS_IN_QUEUE],
174    /// Number of valid entries in [`Self::items`].
175    pub item_count: u32,
176    /// Aggregate stats per item type the player has interacted with.
177    pub items: [PlayerItemInfo; MAX_ITEMS],
178    /// Time spent in each upkeep level, indexed by level (in milliseconds).
179    /// Not reliable for replays because it looks at wall time rather than in-game time
180    /// i.e. replays can be paused, slow-down, or sped up, but it doesn't account for that.
181    /// Unknown if it keeps ticking while the "waiting for players" screen is counting down.
182    pub time_in_upkeep: [u32; MAX_UPKEEP_LEVELS],
183}
184// Number generated from SIZE fields of https://github.com/TinkerWorX/Blizzard.Net.Warcraft3
185// noinspection RsAssertEqual
186const _: () = assert!(size_of::<PlayerInfo>() == 6416738);