added file-watcher for memory dumps
parent
2b0ba06bf1
commit
0395cbc942
|
|
@ -2557,6 +2557,16 @@ dependencies = [
|
|||
"windows-sys 0.42.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "notify-debouncer-mini"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e23e9fa24f094b143c1eb61f90ac6457de87be6987bc70746e0179f7dbc9007b"
|
||||
dependencies = [
|
||||
"crossbeam-channel",
|
||||
"notify",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ntapi"
|
||||
version = "0.4.0"
|
||||
|
|
@ -3293,6 +3303,8 @@ dependencies = [
|
|||
"bevy_egui",
|
||||
"json",
|
||||
"lazy_static",
|
||||
"notify",
|
||||
"notify-debouncer-mini",
|
||||
"reqwest",
|
||||
]
|
||||
|
||||
|
|
|
|||
|
|
@ -10,6 +10,8 @@ bevy = "0.10.0"
|
|||
bevy_egui = "0.20.1"
|
||||
json = "0.12.4"
|
||||
lazy_static = "1.4.0"
|
||||
notify = "5.1.0"
|
||||
notify-debouncer-mini = "0.2.1"
|
||||
reqwest = { version = "0.11.14", features = ["blocking", "json"] }
|
||||
|
||||
# Enable a small amount of optimization in debug mode
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
use bevy::{prelude::*, window::WindowResolution};
|
||||
|
||||
mod battle;
|
||||
mod inspector;
|
||||
mod memory_reader;
|
||||
mod ui;
|
||||
|
||||
pub fn run() {
|
||||
|
|
@ -21,5 +23,6 @@ pub fn run() {
|
|||
.add_plugin(crate::database::DatabasePlugin)
|
||||
.add_plugin(inspector::InspectorPlugin)
|
||||
.add_plugin(ui::UiPlugin)
|
||||
.add_plugin(memory_reader::MemoryReaderPlugin)
|
||||
.run()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,6 @@
|
|||
use super::inspector::Battle;
|
||||
|
||||
pub fn parse_battle_party(data: &Vec<u8>) -> Result<Battle, String> {
|
||||
let mut result = Battle::default();
|
||||
Ok(result)
|
||||
}
|
||||
|
|
@ -3,10 +3,7 @@ use std::collections::HashMap;
|
|||
use bevy::prelude::*;
|
||||
use bevy_egui::EguiContexts;
|
||||
|
||||
use crate::{
|
||||
database::{load_url_asset, Database},
|
||||
pokemon::*,
|
||||
};
|
||||
use crate::{database::load_url_asset, pokemon::*};
|
||||
|
||||
use super::ui::{EguiAsset, UiAssets};
|
||||
|
||||
|
|
@ -15,25 +12,22 @@ pub struct InspectorPlugin;
|
|||
impl Plugin for InspectorPlugin {
|
||||
fn build(&self, app: &mut App) {
|
||||
app.insert_resource(Inspector::default())
|
||||
.add_system(state_changed)
|
||||
.add_startup_system(test_init);
|
||||
.add_system(state_changed);
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Resource, Default)]
|
||||
pub struct Inspector {
|
||||
pub allies: Vec<PokemonInstance>,
|
||||
pub enemies: Vec<PokemonInstance>,
|
||||
pub battle: Battle,
|
||||
}
|
||||
|
||||
impl Inspector {
|
||||
pub fn clear(&mut self) {
|
||||
self.allies.clear();
|
||||
self.enemies.clear();
|
||||
}
|
||||
#[derive(Default, Clone)]
|
||||
pub struct Battle {
|
||||
pub player_party: Vec<PokemonInstance>,
|
||||
pub enemy_party: Vec<PokemonInstance>,
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
#[derive(Default, Clone)]
|
||||
pub struct PokemonInstance {
|
||||
pub pokemon: Pokemon,
|
||||
pub nature: Option<Nature>,
|
||||
|
|
@ -41,55 +35,6 @@ pub struct PokemonInstance {
|
|||
pub evs: HashMap<BaseStat, u8>,
|
||||
}
|
||||
|
||||
fn test_init(mut inspector: ResMut<Inspector>, pokemon_database: Res<Database<Pokemon>>) {
|
||||
for name in vec!["baltoy"].iter() {
|
||||
inspector.enemies.push(PokemonInstance {
|
||||
pokemon: pokemon_database.map.get(*name).unwrap().clone(),
|
||||
ivs: {
|
||||
let mut result = HashMap::new();
|
||||
for stat in BaseStat::all().iter() {
|
||||
result.insert(
|
||||
*stat,
|
||||
match stat {
|
||||
BaseStat::Hp => 31,
|
||||
BaseStat::Attack => 27,
|
||||
BaseStat::Defense => 26,
|
||||
BaseStat::SpecialAttack => 0,
|
||||
BaseStat::SpecialDefense => 21,
|
||||
BaseStat::Speed => 15,
|
||||
},
|
||||
);
|
||||
}
|
||||
result
|
||||
},
|
||||
..default()
|
||||
});
|
||||
}
|
||||
for name in vec!["seadra", "sceptile", "ampharos", "shedinja"].iter() {
|
||||
inspector.allies.push(PokemonInstance {
|
||||
pokemon: pokemon_database.map.get(*name).unwrap().clone(),
|
||||
ivs: {
|
||||
let mut result = HashMap::new();
|
||||
for stat in BaseStat::all().iter() {
|
||||
result.insert(
|
||||
*stat,
|
||||
match stat {
|
||||
BaseStat::Hp => 31,
|
||||
BaseStat::Attack => 27,
|
||||
BaseStat::Defense => 26,
|
||||
BaseStat::SpecialAttack => 0,
|
||||
BaseStat::SpecialDefense => 21,
|
||||
BaseStat::Speed => 15,
|
||||
},
|
||||
);
|
||||
}
|
||||
result
|
||||
},
|
||||
..default()
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
fn state_changed(
|
||||
inspector: Res<Inspector>,
|
||||
assets: Res<AssetServer>,
|
||||
|
|
@ -97,7 +42,12 @@ fn state_changed(
|
|||
mut contexts: EguiContexts,
|
||||
) {
|
||||
if inspector.is_changed() {
|
||||
for instance in inspector.enemies.iter().chain(inspector.allies.iter()) {
|
||||
for instance in inspector
|
||||
.battle
|
||||
.enemy_party
|
||||
.iter()
|
||||
.chain(inspector.battle.player_party.iter())
|
||||
{
|
||||
let pokemon = instance.pokemon.clone();
|
||||
|
||||
if !ui_assets.sprite_map.contains_key(&pokemon.key()) {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,91 @@
|
|||
use bevy::prelude::*;
|
||||
use notify_debouncer_mini::new_debouncer;
|
||||
use std::{
|
||||
fs,
|
||||
sync::{Arc, Mutex},
|
||||
thread,
|
||||
time::Duration,
|
||||
};
|
||||
|
||||
use super::{
|
||||
battle::parse_battle_party,
|
||||
inspector::{Battle, Inspector},
|
||||
};
|
||||
|
||||
pub struct MemoryReaderPlugin;
|
||||
|
||||
impl Plugin for MemoryReaderPlugin {
|
||||
fn build(&self, app: &mut App) {
|
||||
app.add_event::<ParsedBattleEvent>()
|
||||
.insert_resource(EventQueue::default())
|
||||
.add_startup_system(init_memory_reader)
|
||||
.add_system(flush_updates)
|
||||
.add_system(update_inspector);
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct ParsedBattleEvent(Battle);
|
||||
|
||||
#[derive(Resource, Default)]
|
||||
struct EventQueue {
|
||||
updates: Arc<Mutex<Vec<ParsedBattleEvent>>>,
|
||||
}
|
||||
|
||||
fn flush_updates(queue: Res<EventQueue>, mut events: EventWriter<ParsedBattleEvent>) {
|
||||
match queue.updates.lock() {
|
||||
Ok(mut updates) => {
|
||||
for update in updates.drain(..) {
|
||||
events.send(update)
|
||||
}
|
||||
}
|
||||
Err(err) => {
|
||||
error!("{err}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn update_inspector(mut inspector: ResMut<Inspector>, mut events: EventReader<ParsedBattleEvent>) {
|
||||
for event in events.iter() {
|
||||
inspector.battle = event.0.clone();
|
||||
}
|
||||
}
|
||||
|
||||
fn init_memory_reader(queue: Res<EventQueue>) {
|
||||
let updates = queue.updates.clone();
|
||||
|
||||
thread::spawn(move || {
|
||||
let watch_path = std::path::Path::new("/tmp/ivpeek/");
|
||||
fs::create_dir_all(watch_path).expect("Failed to create path for {watch_path:?}");
|
||||
|
||||
let (tx, rx) = std::sync::mpsc::channel();
|
||||
|
||||
let mut debouncer = new_debouncer(Duration::from_millis(1_000), None, tx)
|
||||
.expect("Could not create notify debouncer");
|
||||
|
||||
debouncer
|
||||
.watcher()
|
||||
.watch(watch_path, notify::RecursiveMode::NonRecursive)
|
||||
.expect("Could not watch for {watch_path:?}");
|
||||
|
||||
for result in rx {
|
||||
match result {
|
||||
Ok(events) => {
|
||||
for event in events.iter() {
|
||||
match fs::read(&event.path) {
|
||||
Ok(data) => match parse_battle_party(&data) {
|
||||
Ok(battle) => match updates.lock() {
|
||||
Ok(mut updates) => updates.push(ParsedBattleEvent(battle)),
|
||||
Err(err) => error!("{err}"),
|
||||
},
|
||||
Err(err) => error!("Failed to parse party data: ${err}"),
|
||||
},
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
}
|
||||
Err(err) => error!("Watcher error: {err:?}"),
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
@ -74,7 +74,7 @@ fn ui_system(mut contexts: EguiContexts, inspector: Res<Inspector>, ui_assets: R
|
|||
egui::CentralPanel::default().show(contexts.ctx_mut(), |ui| {
|
||||
egui::ScrollArea::vertical().show(ui, |ui| {
|
||||
ui.heading("Enemy team");
|
||||
for instance in inspector.enemies.iter() {
|
||||
for instance in inspector.battle.enemy_party.iter() {
|
||||
ui.add_space(8.);
|
||||
render_pokemon_instance(ui, &ui_assets, instance);
|
||||
ui.add_space(8.);
|
||||
|
|
@ -83,7 +83,7 @@ fn ui_system(mut contexts: EguiContexts, inspector: Res<Inspector>, ui_assets: R
|
|||
ui.separator();
|
||||
|
||||
ui.heading("Player team");
|
||||
for instance in inspector.allies.iter() {
|
||||
for instance in inspector.battle.player_party.iter() {
|
||||
ui.add_space(8.);
|
||||
render_pokemon_instance(ui, &ui_assets, instance);
|
||||
ui.add_space(8.);
|
||||
|
|
|
|||
Loading…
Reference in New Issue