129 lines
3.5 kB
1
use rand::Rng;
2
use std::{
3
io::{self, Read, Write},
4
sync::mpsc,
5
thread,
6
time::Duration,
7
};
8
9
// This is a practice program to test if the main programs behaviour works fine
10
// This program has been validated and confirmed to work as expected with scanmem
11
12
// Structure to hold the "real" game state
13
struct GameState {
14
// Internal values that control the actual game state
15
values: Vec<i32>,
16
}
17
18
// Structure to manage what's displayed on screen
19
struct GameDisplay {
20
// Pointers to copies of values shown to the player
21
display_values: Vec<Box<i32>>,
22
}
23
24
impl GameState {
25
fn new(count: usize, rng: &mut impl Rng) -> Self {
26
let mut values = Vec::with_capacity(count);
27
for _ in 0..count {
28
values.push(rng.gen_range(1..10));
29
}
30
Self { values }
31
}
32
33
fn get_value(&self, index: usize) -> i32 {
34
self.values[index]
35
}
36
37
fn set_value(&mut self, index: usize, value: i32) {
38
self.values[index] = value;
39
}
40
}
41
42
impl GameDisplay {
43
fn new(count: usize) -> Self {
44
let mut display_values = Vec::with_capacity(count);
45
for _ in 0..count {
46
display_values.push(Box::new(0));
47
}
48
Self { display_values }
49
}
50
51
fn update_from_state(&mut self, state: &GameState) {
52
for (i, val) in state.values.iter().enumerate() {
53
*self.display_values[i] = *val;
54
}
55
}
56
57
fn get_display_ptr(&self, index: usize) -> *const i32 {
58
&*self.display_values[index] as *const i32
59
}
60
61
fn get_displayed_value(&self, index: usize) -> i32 {
62
*self.display_values[index]
63
}
64
}
65
66
fn main() {
67
let mut rng = rand::thread_rng();
68
69
const LEN: usize = 10;
70
71
let mut game_state = GameState::new(LEN, &mut rng);
72
let mut game_display = GameDisplay::new(LEN);
73
74
game_display.update_from_state(&game_state);
75
76
let (tx, rx) = mpsc::channel();
77
78
thread::spawn(move || {
79
let mut buffer = [0; 1];
80
loop {
81
if let Ok(_) = io::stdin().read_exact(&mut buffer) {
82
let _ = tx.send(());
83
}
84
}
85
});
86
87
let mut refresh_counter = 0;
88
89
loop {
90
print!("\x1B[2J\x1B[1;1H");
91
92
refresh_counter += 1;
93
if refresh_counter >= 3 {
94
refresh_counter = 0;
95
game_display.update_from_state(&game_state);
96
println!("(Display refreshed from game state)");
97
}
98
99
println!(
100
"Memory Scanner Target (Realistic Game Structure) - Press ENTER for new values, Ctrl+C to quit"
101
);
102
println!("Displayed values (what you see on screen):");
103
104
for i in 0..LEN {
105
let display_value = game_display.get_displayed_value(i);
106
let display_ptr = game_display.get_display_ptr(i);
107
println!(
108
"Value {}: {} (displayed at {:p})",
109
i, display_value, display_ptr
110
);
111
}
112
113
println!("\nInternal game state (would be hidden in a real game):");
114
for i in 0..LEN {
115
println!("Value {}: {}", i, game_state.get_value(i));
116
}
117
118
println!("\nPress ENTER to change all values...");
119
io::stdout().flush().unwrap();
120
121
if rx.recv_timeout(Duration::from_secs(1)).is_ok() {
122
for i in 0..LEN {
123
game_state.set_value(i, rng.gen_range(1..10));
124
}
125
game_display.update_from_state(&game_state);
126
refresh_counter = 0;
127
}
128
}
129
}
130