/*
Hurry Curry! - a game about cooking
Copyright 2024 metamuffin
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, version 3 of the License only.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see .
*/
pub mod bot;
pub mod conveyor;
pub mod customers;
pub mod environment_effect;
pub mod item_portal;
pub mod player_portal;
use crate::data::ItemTileRegistry;
use anyhow::{anyhow, Result};
use conveyor::Conveyor;
use customers::Customers;
use environment_effect::{EnvironmentController, EnvironmentEffect, EnvironmentEffectController};
use hurrycurry_client_lib::Game;
use hurrycurry_protocol::{
glam::{IVec2, Vec2},
PacketC, PacketS,
};
use item_portal::ItemPortal;
use player_portal::PlayerPortal;
use serde::{Deserialize, Serialize};
use std::collections::VecDeque;
pub type DynEntity = Box;
pub type Entities = Vec;
pub struct EntityContext<'a> {
pub game: &'a mut Game,
pub packet_out: &'a mut VecDeque,
pub packet_in: &'a mut VecDeque,
pub score_changed: &'a mut bool,
pub dt: f32,
}
pub trait Entity {
fn tick(&mut self, c: EntityContext<'_>) -> Result<()>;
fn destructor(&mut self, _c: EntityContext<'_>) {}
}
// macro_rules! entities {
// ($($e:ident),*) => {
// #[derive(Debug)]
// pub enum Entity { $($e($e)),* }
// impl EntityT for Entity {
// fn tick(&mut self, c: EntityContext<'_>) -> Result<()> {
// match self { $(Entity::$e(x) => x.tick(c)),*, }
// }
// fn destructor(&mut self, c: EntityContext<'_>) {
// match self { $(Entity::$e(x) => x.destructor(c)),*, }
// }
// }
// };
// }
// entities!(
// Conveyor,
// ItemPortal,
// PlayerPortal,
// Customers,
// EnvironmentEffectController,
// EnvironmentController
// );
#[derive(Debug, Clone, Deserialize, Serialize)]
#[serde(rename_all = "snake_case")]
pub enum EntityDecl {
Conveyor {
from: Option,
to: Option,
filter_dir: Option,
filter: Option,
dir: Option,
speed: Option,
},
ItemPortal {
from: Option,
to: IVec2,
},
PlayerPortal {
from: Option,
to: Vec2,
},
Customers {},
EnvironmentEffect(EnvironmentEffect),
Environment(Vec),
}
pub fn construct_entity(
pos: Option,
decl: &EntityDecl,
reg: &ItemTileRegistry,
) -> Result {
Ok(match decl.to_owned() {
EntityDecl::ItemPortal { from, to } => Box::new(ItemPortal {
from: from.or(pos).ok_or(anyhow!("no item portal start"))?,
to,
}),
EntityDecl::PlayerPortal { from, to } => Box::new(PlayerPortal {
from: from
.or(pos.map(|v| v.as_vec2()))
.ok_or(anyhow!("no player portal start"))?,
to,
}),
EntityDecl::Conveyor {
from,
to,
speed,
dir,
filter,
filter_dir,
} => {
let from = from.or(pos).ok_or(anyhow!("conveyor has no start"))?;
let to = to
.or(dir.map(|s| s + from))
.ok_or(anyhow!("conveyor has no destination"))?;
Box::new(Conveyor {
from,
to,
max_cooldown: 1. / speed.unwrap_or(2.),
filter_tile: filter_dir.map(|o| to + o),
filter_item: filter.map(|name| reg.register_item(name)),
cooldown: 0.,
})
}
EntityDecl::Customers {} => Box::new(Customers::new()?),
EntityDecl::EnvironmentEffect(config) => Box::new(EnvironmentEffectController::new(config)),
EntityDecl::Environment(names) => Box::new(EnvironmentController(names)),
})
}