Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Command Handling Refactor #25

Merged
merged 3 commits into from
May 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions .github/workflows/checks.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ jobs:
matrix:
rust:
- stable
- 1.65.0
- 1.66.0
steps:
- name: Checkout sources
uses: actions/checkout@v2
Expand All @@ -38,7 +38,7 @@ jobs:
matrix:
rust:
- stable
- 1.65.0
- 1.66.0
steps:
- name: Checkout sources
uses: actions/checkout@v2
Expand All @@ -62,7 +62,7 @@ jobs:
matrix:
rust:
- stable
- 1.65.0
- 1.66.0
steps:
- name: Checkout sources
uses: actions/checkout@v2
Expand All @@ -89,7 +89,7 @@ jobs:
matrix:
rust:
- stable
- 1.65.0
- 1.66.0
steps:
- name: Checkout sources
uses: actions/checkout@v2
Expand Down
55 changes: 55 additions & 0 deletions src/command.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
//! Wrapper for Company of Heroes 3 player commands.

use crate::{
command_data::{Pgbid, Unknown},
command_type::CommandType,
data::ticks,
};

#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};

/// Wrapper for one of many Company of Heroes 3 player commands parsed from a replay file. For
/// details on the specifics of a given command, see the specific enum variants.
///
/// Commands are collected during tick parsing and then associated with the `Player` instance that
/// sent them. To access, see `Player::commands`.

#[derive(Clone, Debug)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "magnus", magnus::wrap(class = "VaultCoh::Command"))]
pub enum Command {
BuildGlobalUpgrade(Pgbid),
BuildSquad(Pgbid),
SelectBattlegroup(Pgbid),
SelectBattlegroupAbility(Pgbid),
UseBattlegroupAbility(Pgbid),
Unknown(Unknown),
}

impl Command {
pub(crate) fn from_data_command_at_tick(command: ticks::Command, tick: u32) -> Self {
match command.data {
ticks::CommandData::Pgbid(pgbid) => match command.action_type {
CommandType::CMD_BuildSquad => Self::BuildSquad(Pgbid::new(tick, pgbid)),
CommandType::CMD_Upgrade => Self::BuildGlobalUpgrade(Pgbid::new(tick, pgbid)),
CommandType::PCMD_Ability => Self::UseBattlegroupAbility(Pgbid::new(tick, pgbid)),
CommandType::PCMD_InstantUpgrade => {
Self::SelectBattlegroup(Pgbid::new(tick, pgbid))
}
CommandType::PCMD_TentativeUpgrade => {
Self::SelectBattlegroupAbility(Pgbid::new(tick, pgbid))
}
_ => panic!(
"a pgbid command isn't being handled here! command type {:?}",
command.action_type
),
},
ticks::CommandData::Unknown => Self::Unknown(Unknown::new(tick, command.action_type)),
}
}
}

// this is safe as Command does not contain any Ruby types
#[cfg(feature = "magnus")]
unsafe impl magnus::IntoValueFromNative for Command {}
5 changes: 5 additions & 0 deletions src/command_data/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
mod pgbid;
mod unknown;

pub use crate::command_data::pgbid::Pgbid;
pub use crate::command_data::unknown::Unknown;
29 changes: 29 additions & 0 deletions src/command_data/pgbid.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};

#[derive(Debug, Copy, Clone)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct Pgbid {
tick: u32,
pgbid: u32,
}

impl Pgbid {
pub(crate) fn new(tick: u32, pgbid: u32) -> Self {
Self { tick, pgbid }
}

/// This value is the tick at which the command was found while parsing the replay, which
/// represents the time in the replay at which it was executed. Because CoH3's engine runs at 8
/// ticks per second, you can divide this value by 8 to get the number of seconds since the
/// replay began, which will tell you when this command was executed.
pub fn tick(&self) -> u32 {
self.tick
}
/// Internal ID that uniquely identifies entity associated with the command. This value can be
/// matched to CoH3 attribute files in order to determine the entity in question. Note that,
/// while rare, it is possible that this value may change between patches for the same entity.
pub fn pgbid(&self) -> u32 {
self.pgbid
}
}
30 changes: 30 additions & 0 deletions src/command_data/unknown.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
use crate::command_type::CommandType;

#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};

#[derive(Debug, Copy, Clone)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct Unknown {
tick: u32,
action_type: CommandType,
}

impl Unknown {
pub(crate) fn new(tick: u32, action_type: CommandType) -> Self {
Self { tick, action_type }
}

/// This value is the tick at which the command was found while parsing the replay, which
/// represents the time in the replay at which it was executed. Because CoH3's engine runs at 8
/// ticks per second, you can divide this value by 8 to get the number of seconds since the
/// replay began, which will tell you when this command was executed.
pub fn tick(&self) -> u32 {
self.tick
}
/// This value identifies the type of the command (build, move, stop, etc.). Commands with
/// similar functionality can be grouped by this value.
pub fn action_type(&self) -> CommandType {
self.action_type
}
}
Loading
Loading