Skip to content

Commit

Permalink
Split .rs files
Browse files Browse the repository at this point in the history
  • Loading branch information
hsnks100 committed Nov 18, 2024
1 parent 4431144 commit 2109165
Show file tree
Hide file tree
Showing 20 changed files with 1,489 additions and 1,393 deletions.
75 changes: 24 additions & 51 deletions src/game_cache.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,22 +4,22 @@ const CACHE_SIZE: usize = 256;

/// Represents a cache for storing game data packets.
#[derive(Debug)]
struct GameCache {
pub struct GameCache {
/// A deque to hold cached game data.
cache: VecDeque<Vec<u8>>,
}

impl GameCache {
/// Creates a new GameCache with a fixed size.
fn new() -> Self {
pub fn new() -> Self {
Self {
cache: VecDeque::with_capacity(CACHE_SIZE),
}
}

/// Searches for the game data in the cache.
/// Returns `Some(position)` if found, otherwise `None`.
fn find(&self, data: &Vec<u8>) -> Option<u8> {
pub fn find(&self, data: &Vec<u8>) -> Option<u8> {
self.cache
.iter()
.position(|cached_data| cached_data == data)
Expand All @@ -29,7 +29,7 @@ impl GameCache {
/// Adds new game data to the cache.
/// If the cache is full, it removes the oldest entry.
/// Returns the position where the data was added.
fn add(&mut self, data: Vec<u8>) -> u8 {
pub fn add(&mut self, data: Vec<u8>) -> u8 {
if self.cache.len() == CACHE_SIZE {
self.cache.pop_front();
}
Expand All @@ -38,15 +38,15 @@ impl GameCache {
}

/// Retrieves game data from the cache by position.
fn get(&self, position: u8) -> Option<&Vec<u8>> {
pub fn get(&self, position: u8) -> Option<&Vec<u8>> {
self.cache.get(position as usize)
}
}

/// Represents a connected client.
#[derive(Debug)]
struct Client {
id: u32,
pub struct Client {
pub id: u32,
/// Cache for received data (client's send cache).
receive_cache: GameCache,
/// Queue of pending inputs.
Expand All @@ -55,7 +55,7 @@ struct Client {

impl Client {
/// Creates a new client with empty caches.
fn new(id: u32) -> Self {
pub fn new(id: u32) -> Self {
Self {
id,
receive_cache: GameCache::new(),
Expand All @@ -64,29 +64,29 @@ impl Client {
}

/// Adds an input to the pending inputs queue.
fn add_input(&mut self, data: Vec<u8>) {
pub fn add_input(&mut self, data: Vec<u8>) {
self.pending_inputs.push_back(data);
}

/// Retrieves and removes the next input from the pending queue.
fn get_next_input(&mut self) -> Option<Vec<u8>> {
pub fn get_next_input(&mut self) -> Option<Vec<u8>> {
self.pending_inputs.pop_front()
}
}

/// Represents the result of processing a frame.
#[derive(Debug)]
struct FrameResult {
frame_index: usize,
use_cache: bool,
cache_pos: u8,
data_to_send: Vec<u8>,
aggregated_data: Vec<u8>,
pub struct FrameResult {
pub frame_index: usize,
pub use_cache: bool,
pub cache_pos: u8,
pub data_to_send: Vec<u8>,
pub aggregated_data: Vec<u8>,
}

/// Represents the game data processor for handling inputs and outputs.
#[derive(Debug)]
struct GameDataProcessor {
pub struct GameDataProcessor {
/// Map of connected clients.
clients: HashMap<u32, Client>,
/// Global cache for aggregated game data.
Expand All @@ -99,7 +99,7 @@ struct GameDataProcessor {

impl GameDataProcessor {
/// Creates a new GameDataProcessor with no clients.
fn new() -> Self {
pub fn new() -> Self {
Self {
clients: HashMap::new(),
aggregated_cache: GameCache::new(),
Expand All @@ -109,78 +109,58 @@ impl GameDataProcessor {
}

/// Adds a new client to the processor.
fn add_client(&mut self, client_id: u32) {
pub fn add_client(&mut self, client_id: u32) {
self.clients.insert(client_id, Client::new(client_id));
}

/// Processes incoming game data from a client.
/// Stores the data in the client's pending inputs.
fn process_incoming(&mut self, client_id: u32, data: Vec<u8>) {
pub fn process_incoming(&mut self, client_id: u32, data: Vec<u8>) {
let client = self.clients.get_mut(&client_id).expect("Client not found");

// Check if data is a cache position (1 byte).
let actual_data = if data.len() == 1 {
let position = data[0];
if let Some(cached_data) = client.receive_cache.get(position) {
// Data found in client's cache.
cached_data.clone()
} else {
// Invalid cache position; handle as needed.
panic!(
"Invalid cache position {} received from client {}",
position, client_id
);
}
} else {
// Add data to client's receive cache.
client.receive_cache.add(data.clone());
data
};

// Add the actual data to the client's pending inputs.
client.add_input(actual_data);
}

/// Processes a frame if inputs from all clients are available.
/// Returns Some(FrameResult) if the frame was processed.
fn process_frame(&mut self) -> Option<FrameResult> {
pub fn process_frame(&mut self) -> Option<FrameResult> {
let mut frame_data = Vec::new();

// First, check if all clients have inputs available without popping them
let all_clients_have_input = self
.clients
.values()
.all(|client| !client.pending_inputs.is_empty());

if !all_clients_have_input {
// Cannot process frame yet
return None;
}

// All clients have provided input; now proceed to pop inputs and process the frame.
for (&client_id, client) in &mut self.clients {
// Now safe to pop inputs
let input = client.get_next_input().expect("Input should be available");
frame_data.extend(input.clone());
// Store the input per frame.
self.frame_inputs
.entry(self.frame_index)
.or_default()
.insert(client_id, input);
}

// Proceed with frame processing
println!("\n--- Processing Frame {} ---", self.frame_index + 1);

// Prepare outgoing data for clients.
let (use_cache, cache_pos, data_to_send) = self.prepare_outgoing(frame_data.clone());
println!(
"server->clients: use_cache_pos={}, cache_pos={}, data_to_send={:?}",
use_cache, cache_pos, data_to_send
);
println!("Aggregated data: {:?}", frame_data);

// Create a FrameResult to return.
let frame_result = FrameResult {
frame_index: self.frame_index,
use_cache,
Expand All @@ -189,20 +169,15 @@ impl GameDataProcessor {
aggregated_data: frame_data,
};

// Increment frame index.
self.frame_index += 1;
Some(frame_result)
}

/// Prepares outgoing game data to send to clients.
/// Returns a tuple indicating whether to use cache, cache position, and data to send.
fn prepare_outgoing(&mut self, data: Vec<u8>) -> (bool, u8, Vec<u8>) {
// Check if the aggregated data is already in the global cache.
pub fn prepare_outgoing(&mut self, data: Vec<u8>) -> (bool, u8, Vec<u8>) {
if let Some(pos) = self.aggregated_cache.find(&data) {
// Data found in cache; send cache position.
(true, pos, Vec::new())
} else {
// Data not found; add to cache and send data.
let pos = self.aggregated_cache.add(data.clone());
(false, pos, data)
}
Expand All @@ -222,13 +197,11 @@ mod tests {
processor.add_client(2); // Client ID 2

// Expected cache usage and positions per frame.
let expected_results = vec![
(false, 0), // Frame 1: New data, cache position 0
let expected_results = [(false, 0), // Frame 1: New data, cache position 0
(true, 0), // Frame 2: Using cache position 0
(false, 1), // Frame 3: New data, cache position 1
(false, 2), // Frame 4: New data, cache position 2
(true, 1), // Frame 5: Using cache position 1
];
(true, 1)];

// Test inputs from clients at different times.
let inputs = vec![
Expand Down
Loading

0 comments on commit 2109165

Please sign in to comment.