You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

147 lines
3.5 KiB

use rhai::{
serde::{from_dynamic, to_dynamic},
Dynamic, Func, AST,
};
use uuid::Uuid;
use std::collections::HashMap;
use super::config::{Config, Pile};
mod engine;
use engine::setup_engine;
mod functions;
use functions::Functions;
mod types;
pub use types::{CardId, CardIdx, PileKind};
use types::{Data, Player, RhaiResult};
pub struct RunningGame {
#[allow(unused)] // TODO Remove
name: String,
pub piles: HashMap<String, Pile>,
pub player_piles: Vec<HashMap<String, Pile>>,
functions: Functions,
current_player: Player,
data: HashMap<String, serde_json::Value>,
pub players: HashMap<Uuid, u32>,
}
// TODO add errors
impl RunningGame {
fn get_fns(ast: &AST) -> Vec<String> {
ast.iter_functions()
.map(|(_, _, name, _, _)| name.to_string())
.collect()
}
pub fn compile(path: std::path::PathBuf) -> RhaiResult<(AST, Vec<String>)> {
let e = setup_engine();
let ast = e.compile_file(path)?;
let fns = Self::get_fns(&ast);
Ok((ast, fns))
}
pub fn new(
name: String,
ast: AST,
fns: &[String],
conf: &Config,
current_players: &[Uuid],
) -> Self {
// log::info!("Fns: {:?}", fns);
let functions = Functions::new(fns, ast.clone(), &name);
let engine = setup_engine();
let setup = Func::<(Dynamic,), Dynamic>::create_from_ast(engine, ast, "setup");
let piles = conf.piles.clone();
let player_piles = vec![conf.player_piles.clone(); current_players.len()];
let Data {
piles,
player_piles,
players: _,
other,
} = from_dynamic(
&setup(
to_dynamic(Data::new(piles, player_piles, current_players.len() as u32)).unwrap(),
)
.unwrap(),
)
.unwrap();
let mut players = HashMap::new();
for (i, player) in current_players.iter().enumerate() {
players.insert(player.clone(), i as u32);
}
log::info!("Players in game {}: {:?}", name, players);
Self {
name,
piles,
player_piles,
functions,
current_player: Player::new(0, current_players.len() as u32),
data: other,
players,
}
// Self {setup: Box::new(Func::<(Vec<Pile>, Vec<Vec<Pile>>), ()>::create_from_ast(engine, ast, "setup"))}
}
pub fn get_player_for_uuid(&self, user: &Uuid) -> Option<u32> {
self.players.get(user).copied()
}
pub fn get_current_player(&self) -> u32 {
self.current_player.num
}
fn data_as_dynamic(&self) -> RhaiResult<Dynamic> {
to_dynamic(Data {
piles: self.piles.clone(),
player_piles: self.player_piles.clone(),
players: self.current_player.max,
other: self.data.clone(),
})
}
fn save_data(&mut self, d: &Dynamic) -> RhaiResult<()> {
let d: Data = from_dynamic(d)?;
self.data = d.other;
self.piles = d.piles;
self.player_piles = d.player_piles;
Ok(())
}
pub fn on_click(&mut self, card: CardId, player: u32) {
let action_author = Player::new(player, self.current_player.max);
let data = self.data_as_dynamic().unwrap();
let arr = self
.functions
.on_click(data, card, action_author, self.current_player)
.unwrap();
self.save_data(&arr[0]).unwrap();
let turn_end: bool = arr[1].clone().cast();
if turn_end {
self.turn_end()
}
}
fn turn_end(&mut self) {
let data = self.data_as_dynamic().unwrap();
let mut arr = self.functions.turn_end(data, self.current_player).unwrap();
self.save_data(&arr[0]).unwrap();
self.current_player = arr.remove(1).cast();
self.turn_start();
}
fn turn_start(&mut self) {
let data = self.data_as_dynamic().unwrap();
let data = self
.functions
.turn_start(data, self.current_player)
.transpose()
.unwrap();
if let Some(data) = data {
self.save_data(&data).unwrap();
}
}
}