Compare commits
1
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
371c3e6a84 |
+2
-2
@@ -1,7 +1,7 @@
|
|||||||
# for Linux
|
# for Linux
|
||||||
[target.x86_64-unknown-linux-gnu]
|
[target.x86_64-unknown-linux-gnu]
|
||||||
linker = "clang"
|
linker = "clang"
|
||||||
rustflags = ["-C", "link-arg=-fuse-ld=/usr/bin/mold", "-Zshare-generics=y", "-D", "warnings", ]
|
rustflags = ["-C", "link-arg=-fuse-ld=/usr/bin/mold", "-Zshare-generics=y", ]
|
||||||
|
|
||||||
[unstable]
|
[unstable]
|
||||||
codegen-backend = true
|
codegen-backend = true
|
||||||
@@ -10,4 +10,4 @@ codegen-backend = true
|
|||||||
codegen-backend = "llvm"
|
codegen-backend = "llvm"
|
||||||
|
|
||||||
[profile.dev.package."*"]
|
[profile.dev.package."*"]
|
||||||
codegen-backend = "llvm"
|
codegen-backend = "llvm"
|
||||||
@@ -25,7 +25,6 @@ jobs:
|
|||||||
- name: Cache Rust dependencies and build artifacts
|
- name: Cache Rust dependencies and build artifacts
|
||||||
uses: Swatinem/rust-cache@779680da715d629ac1d338a641029a2f4372abb5 # v2.8.2
|
uses: Swatinem/rust-cache@779680da715d629ac1d338a641029a2f4372abb5 # v2.8.2
|
||||||
with:
|
with:
|
||||||
prefix-key: v1-rust
|
|
||||||
shared-key: linux-nightly
|
shared-key: linux-nightly
|
||||||
cache-bin: false
|
cache-bin: false
|
||||||
|
|
||||||
@@ -46,7 +45,7 @@ jobs:
|
|||||||
pkg-config
|
pkg-config
|
||||||
|
|
||||||
- name: Build
|
- name: Build
|
||||||
run: cargo build --locked -j 4
|
run: RUSTFLAGS="-D warnings" cargo build --locked -j 4
|
||||||
|
|
||||||
- name: Run unit tests
|
- name: Run unit tests
|
||||||
run: cargo test --locked --lib -j 4
|
run: cargo test --locked --lib -j 4
|
||||||
|
|||||||
@@ -14,8 +14,6 @@ use enum_cycling_derive::EnumCycle;
|
|||||||
|
|
||||||
use crate::{AppState, player::Player, replay::StopReplayRecording};
|
use crate::{AppState, player::Player, replay::StopReplayRecording};
|
||||||
|
|
||||||
mod save_state;
|
|
||||||
|
|
||||||
pub const PLAYER_DEBUG_ROW_COUNT: usize = 6;
|
pub const PLAYER_DEBUG_ROW_COUNT: usize = 6;
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, Reflect)]
|
#[derive(Clone, Copy, Debug, PartialEq, Eq, Reflect)]
|
||||||
@@ -380,9 +378,6 @@ impl Plugin for DebugToolsPlugin {
|
|||||||
fn build(&self, app: &mut App) {
|
fn build(&self, app: &mut App) {
|
||||||
app.init_resource::<DebugSettings>()
|
app.init_resource::<DebugSettings>()
|
||||||
.init_resource::<FrameStepState>()
|
.init_resource::<FrameStepState>()
|
||||||
.init_resource::<save_state::DebugSaveState>()
|
|
||||||
.add_systems(OnEnter(AppState::InMatch), save_state::clear)
|
|
||||||
.add_systems(OnExit(AppState::InMatch), save_state::clear)
|
|
||||||
.add_systems(
|
.add_systems(
|
||||||
PreUpdate,
|
PreUpdate,
|
||||||
prepare_frame_step
|
prepare_frame_step
|
||||||
@@ -390,13 +385,6 @@ impl Plugin for DebugToolsPlugin {
|
|||||||
.before(RunGgrsSystems)
|
.before(RunGgrsSystems)
|
||||||
.run_if(in_state(AppState::InMatch)),
|
.run_if(in_state(AppState::InMatch)),
|
||||||
)
|
)
|
||||||
.add_systems(
|
|
||||||
PreUpdate,
|
|
||||||
save_state::save_or_restore
|
|
||||||
.after(InputSystems)
|
|
||||||
.before(RunGgrsSystems)
|
|
||||||
.run_if(in_state(AppState::InMatch)),
|
|
||||||
)
|
|
||||||
.add_systems(PreUpdate, restore_frame_step_time.after(RunGgrsSystems))
|
.add_systems(PreUpdate, restore_frame_step_time.after(RunGgrsSystems))
|
||||||
.add_systems(
|
.add_systems(
|
||||||
Update,
|
Update,
|
||||||
|
|||||||
@@ -1,196 +0,0 @@
|
|||||||
use bevy::prelude::*;
|
|
||||||
|
|
||||||
use crate::{
|
|
||||||
camera::MatchCamera,
|
|
||||||
fighter::{
|
|
||||||
FighterECB, FighterFacingDirection, FighterHitboxes, FighterHitstop,
|
|
||||||
FighterPreviousFacingDirection, FighterPreviousTranslation, FighterTranslation,
|
|
||||||
FighterVelocity, Grounded,
|
|
||||||
animation::FighterAnimationFrame,
|
|
||||||
attack::{
|
|
||||||
FighterDamage, FighterKnockbackVelocity, FighterPendingHitReaction,
|
|
||||||
FighterReceivedAttacks, FighterSolvedHurtboxes, FighterStaleMoveQueue,
|
|
||||||
},
|
|
||||||
baked_animation::FighterBoneMatrices,
|
|
||||||
state::FighterState,
|
|
||||||
},
|
|
||||||
input::FighterInput,
|
|
||||||
player::Player,
|
|
||||||
stage::line::StageCollision,
|
|
||||||
};
|
|
||||||
|
|
||||||
#[derive(Resource, Default)]
|
|
||||||
pub(super) struct DebugSaveState {
|
|
||||||
checkpoint: Option<Checkpoint>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone)]
|
|
||||||
struct Checkpoint {
|
|
||||||
fighters: Vec<FighterCheckpoint>,
|
|
||||||
stage_collision: StageCollision,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone)]
|
|
||||||
struct FighterCheckpoint {
|
|
||||||
entity: Entity,
|
|
||||||
handle: usize,
|
|
||||||
ecb: FighterECB,
|
|
||||||
previous_ecb: crate::fighter::ecb::FighterPreviousECB,
|
|
||||||
velocity: FighterVelocity,
|
|
||||||
translation: FighterTranslation,
|
|
||||||
previous_translation: FighterPreviousTranslation,
|
|
||||||
facing: FighterFacingDirection,
|
|
||||||
previous_facing: FighterPreviousFacingDirection,
|
|
||||||
animation: FighterAnimationFrame,
|
|
||||||
state: FighterState,
|
|
||||||
input: FighterInput,
|
|
||||||
damage: FighterDamage,
|
|
||||||
pending_hit_reaction: FighterPendingHitReaction,
|
|
||||||
hitstop: FighterHitstop,
|
|
||||||
knockback_velocity: FighterKnockbackVelocity,
|
|
||||||
stale_moves: FighterStaleMoveQueue,
|
|
||||||
hitboxes: FighterHitboxes,
|
|
||||||
received_attacks: FighterReceivedAttacks,
|
|
||||||
solved_hurtboxes: FighterSolvedHurtboxes,
|
|
||||||
bone_matrices: FighterBoneMatrices,
|
|
||||||
grounded: bool,
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(super) fn save_or_restore(world: &mut World) {
|
|
||||||
if world.resource::<super::DebugSettings>().menu_open {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
let left = world
|
|
||||||
.query::<&Gamepad>()
|
|
||||||
.iter(world)
|
|
||||||
.any(|gamepad| gamepad.just_pressed(GamepadButton::DPadLeft));
|
|
||||||
let right = world
|
|
||||||
.query::<&Gamepad>()
|
|
||||||
.iter(world)
|
|
||||||
.any(|gamepad| gamepad.just_pressed(GamepadButton::DPadRight));
|
|
||||||
|
|
||||||
if left == right {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
let Some(roster) = world
|
|
||||||
.get_resource::<crate::fighter::FighterRoster>()
|
|
||||||
.map(|roster| roster.0.clone())
|
|
||||||
else {
|
|
||||||
return;
|
|
||||||
};
|
|
||||||
if roster.len() != 1 {
|
|
||||||
warn!("Save states are only available in single-player matches");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if left {
|
|
||||||
let Some(stage_collision) = world.get_resource::<StageCollision>().cloned() else {
|
|
||||||
return;
|
|
||||||
};
|
|
||||||
let mut checkpoint_fighters = Vec::with_capacity(roster.len());
|
|
||||||
for entity in roster.iter().copied() {
|
|
||||||
let Some(checkpoint) = capture_fighter(world, entity) else {
|
|
||||||
warn!("Could not save the current fighter state");
|
|
||||||
return;
|
|
||||||
};
|
|
||||||
checkpoint_fighters.push(checkpoint);
|
|
||||||
}
|
|
||||||
world.resource_mut::<DebugSaveState>().checkpoint = Some(Checkpoint {
|
|
||||||
fighters: checkpoint_fighters,
|
|
||||||
stage_collision,
|
|
||||||
});
|
|
||||||
info!("Saved debug game state");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
let Some(checkpoint) = world.resource::<DebugSaveState>().checkpoint.clone() else {
|
|
||||||
warn!("No debug game state has been saved");
|
|
||||||
return;
|
|
||||||
};
|
|
||||||
if checkpoint.fighters.len() != roster.len()
|
|
||||||
|| checkpoint
|
|
||||||
.fighters
|
|
||||||
.iter()
|
|
||||||
.zip(roster.iter())
|
|
||||||
.any(|(saved, current)| saved.entity != *current)
|
|
||||||
{
|
|
||||||
warn!("Saved debug game state belongs to another match");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
for saved in &checkpoint.fighters {
|
|
||||||
let Some(player) = world.entity(saved.entity).get::<Player>() else {
|
|
||||||
warn!("Could not restore the saved fighter state");
|
|
||||||
return;
|
|
||||||
};
|
|
||||||
if player.handle != saved.handle {
|
|
||||||
warn!("Saved debug game state belongs to another match");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut entity = world.entity_mut(saved.entity);
|
|
||||||
entity.insert(saved.ecb);
|
|
||||||
entity.insert(saved.previous_ecb);
|
|
||||||
entity.insert(saved.velocity);
|
|
||||||
entity.insert(saved.translation);
|
|
||||||
entity.insert(saved.previous_translation);
|
|
||||||
entity.insert(saved.facing);
|
|
||||||
entity.insert(saved.previous_facing);
|
|
||||||
entity.insert(saved.animation);
|
|
||||||
entity.insert(saved.state.clone());
|
|
||||||
entity.insert(saved.input);
|
|
||||||
entity.insert(saved.damage);
|
|
||||||
entity.insert(saved.pending_hit_reaction.clone());
|
|
||||||
entity.insert(saved.hitstop);
|
|
||||||
entity.insert(saved.knockback_velocity);
|
|
||||||
entity.insert(saved.stale_moves.clone());
|
|
||||||
entity.insert(saved.hitboxes.clone());
|
|
||||||
entity.insert(saved.received_attacks.clone());
|
|
||||||
entity.insert(saved.solved_hurtboxes.clone());
|
|
||||||
entity.insert(saved.bone_matrices.clone());
|
|
||||||
if saved.grounded {
|
|
||||||
entity.insert(Grounded);
|
|
||||||
} else {
|
|
||||||
entity.remove::<Grounded>();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
world.insert_resource(checkpoint.stage_collision);
|
|
||||||
for mut match_camera in world.query::<&mut MatchCamera>().iter_mut(world) {
|
|
||||||
match_camera.needs_snap = true;
|
|
||||||
}
|
|
||||||
info!("Restored debug game state");
|
|
||||||
}
|
|
||||||
|
|
||||||
fn capture_fighter(world: &World, entity: Entity) -> Option<FighterCheckpoint> {
|
|
||||||
let fighter = world.entity(entity);
|
|
||||||
Some(FighterCheckpoint {
|
|
||||||
entity,
|
|
||||||
handle: fighter.get::<Player>()?.handle,
|
|
||||||
ecb: *fighter.get::<FighterECB>()?,
|
|
||||||
previous_ecb: *fighter.get::<crate::fighter::ecb::FighterPreviousECB>()?,
|
|
||||||
velocity: *fighter.get::<FighterVelocity>()?,
|
|
||||||
translation: *fighter.get::<FighterTranslation>()?,
|
|
||||||
previous_translation: *fighter.get::<FighterPreviousTranslation>()?,
|
|
||||||
facing: *fighter.get::<FighterFacingDirection>()?,
|
|
||||||
previous_facing: *fighter.get::<FighterPreviousFacingDirection>()?,
|
|
||||||
animation: *fighter.get::<FighterAnimationFrame>()?,
|
|
||||||
state: fighter.get::<FighterState>()?.clone(),
|
|
||||||
input: *fighter.get::<FighterInput>()?,
|
|
||||||
damage: *fighter.get::<FighterDamage>()?,
|
|
||||||
pending_hit_reaction: fighter.get::<FighterPendingHitReaction>()?.clone(),
|
|
||||||
hitstop: *fighter.get::<FighterHitstop>()?,
|
|
||||||
knockback_velocity: *fighter.get::<FighterKnockbackVelocity>()?,
|
|
||||||
stale_moves: fighter.get::<FighterStaleMoveQueue>()?.clone(),
|
|
||||||
hitboxes: fighter.get::<FighterHitboxes>()?.clone(),
|
|
||||||
received_attacks: fighter.get::<FighterReceivedAttacks>()?.clone(),
|
|
||||||
solved_hurtboxes: fighter.get::<FighterSolvedHurtboxes>()?.clone(),
|
|
||||||
bone_matrices: fighter.get::<FighterBoneMatrices>()?.clone(),
|
|
||||||
grounded: fighter.contains::<Grounded>(),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(super) fn clear(mut save_state: ResMut<DebugSaveState>) {
|
|
||||||
save_state.checkpoint = None;
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user