use crate::{ protocol::{ItemID, ItemIndex, PacketC, PacketS, PlayerID, TileIndex}, recipes::Gamedata, }; use anyhow::{anyhow, Result}; use glam::IVec2; use std::{ collections::{HashMap, VecDeque}, ops::Deref, sync::Arc, }; pub struct Tile { kind: TileIndex, items: Vec, active: bool, progress: f32, } struct Player { name: String, hand: Option, } pub struct Game { data: Arc, item_id_counter: ItemID, tiles: HashMap, items: HashMap, players: HashMap, packet_out: VecDeque, } impl Game { pub fn new(gamedata: Arc) -> Self { let mut g = Self { data: gamedata.clone(), item_id_counter: 0, items: Default::default(), packet_out: Default::default(), players: Default::default(), tiles: Default::default(), }; for x in -5..5 { for y in -5..5 { g.tiles .insert(IVec2 { x, y }, gamedata.get_tile("floor").unwrap().into()); } } for x in -5..5 { g.tiles.insert( IVec2 { x, y: -5 }, gamedata.get_tile("table").unwrap().into(), ); g.tiles.insert( IVec2 { x, y: 4 }, gamedata.get_tile("table").unwrap().into(), ); } for y in -5..5 { g.tiles.insert( IVec2 { x: -5, y }, gamedata.get_tile("table").unwrap().into(), ); g.tiles.insert( IVec2 { x: 4, y }, gamedata.get_tile("table").unwrap().into(), ); } g.tiles.extend( [([-5, 1], "pan"), ([-5, 2], "pan"), ([4, 3], "meat-spawn")].map(|(k, v)| { ( IVec2::from_array(k), Tile { active: false, items: vec![], kind: gamedata.get_tile(v).unwrap().into(), progress: 0., }, ) }), ); g } pub fn packet_out(&mut self) -> Option { self.packet_out.pop_front() } pub fn prime_client(&self, id: PlayerID) -> Vec { let mut out = Vec::new(); for (&id, player) in &self.players { out.push(PacketC::AddPlayer { id, name: player.name.clone(), hand: player.hand.map(|i| (i, self.items[&i].clone())), }) } for (&pos, tdata) in &self.tiles { out.push(PacketC::UpdateMap { pos, tile: tdata.kind.clone(), }); for &id in &tdata.items { out.push(PacketC::ProduceItem { id, pos, kind: self.items[&id].clone(), }) } } out.push(PacketC::Joined { id, data: self.data.deref().to_owned(), }); out } pub fn packet_in(&mut self, player: PlayerID, packet: PacketS) -> Result<()> { match packet { PacketS::Join { name } => { self.players.insert( player, Player { hand: None, name: name.clone(), }, ); self.packet_out.push_back(PacketC::AddPlayer { id: player, name, hand: None, }); } PacketS::Leave => { let p = self .players .remove(&player) .ok_or(anyhow!("player does not exist"))?; if let Some(id) = p.hand { self.items.remove(&id).expect("hand item lost"); } self.packet_out .push_back(PacketC::RemovePlayer { id: player }) } PacketS::Position { pos, rot } => { self.packet_out .push_back(PacketC::Position { player, pos, rot }); } PacketS::Interact { pos, edge } => { // if let Some(item) = player_data.hand.take() { // info!("put {item}"); // tile.items.push(item); // self.packet_out.push_back(PacketC::PutItem { item, pos }) // } else { // if let Some(item) = tile.items.pop() { // info!("take {item}"); // player_data.hand = Some(item); // self.packet_out // .push_back(PacketC::TakeItem { item, player }) // } // } } } Ok(()) } } impl From for Tile { fn from(kind: TileIndex) -> Self { Self { kind, progress: 0., active: false, items: vec![], } } }