aboutsummaryrefslogtreecommitdiff
path: root/server/src
diff options
context:
space:
mode:
Diffstat (limited to 'server/src')
-rw-r--r--server/src/game.rs127
-rw-r--r--server/src/interaction.rs227
-rw-r--r--server/src/main.rs2
3 files changed, 168 insertions, 188 deletions
diff --git a/server/src/game.rs b/server/src/game.rs
index d481dc4f..46bc0569 100644
--- a/server/src/game.rs
+++ b/server/src/game.rs
@@ -1,6 +1,6 @@
use crate::{
data::Gamedata,
- interaction::interact,
+ interaction::{interact, tick_tile, InteractEffect, TickEffect},
protocol::{ItemIndex, PacketC, PacketS, PlayerID, RecipeIndex, TileIndex},
};
use anyhow::{anyhow, bail, Result};
@@ -12,12 +12,14 @@ use std::{
sync::Arc,
};
+#[derive(Debug, PartialEq)]
pub struct Involvement {
pub recipe: RecipeIndex,
pub progress: f32,
pub working: usize,
}
+#[derive(Debug, PartialEq)]
pub struct Item {
pub kind: ItemIndex,
pub active: Option<Involvement>,
@@ -80,8 +82,8 @@ impl Game {
});
if let Some(item) = &tdata.item {
out.push(PacketC::ProduceItem {
- item: item.kind,
tile,
+ item: item.kind,
})
}
}
@@ -111,7 +113,7 @@ impl Game {
.players
.remove(&player)
.ok_or(anyhow!("player does not exist"))?;
- if let Some(id) = p.item {
+ if let Some(_id) = p.item {
// TODO place on ground
}
self.packet_out
@@ -121,6 +123,10 @@ impl Game {
self.packet_out
.push_back(PacketC::Position { player, pos, rot });
}
+ PacketS::Collide { player, force } => {
+ self.packet_out
+ .push_back(PacketC::Collide { player, force });
+ }
PacketS::Interact { pos, edge } => {
info!("interact {pos:?} edge={edge}");
@@ -139,64 +145,83 @@ impl Game {
}
let tile_had_item = tile.item.is_some();
+ let player_had_item = tile.item.is_some();
- interact(&self.data, edge, tile, player);
-
- // interact(
- // &self.data,
- // edge,
- // tilekind,
- // &mut tile.active,
- // item,
- // hand,
- // |out| match out {
- // Out::Take(index) => {
- // info!("take");
- // let item = tile.items.remove(index);
- // player.hand = Some(item);
- // self.packet_out
- // .push_back(PacketC::TakeItem { item, player: pid })
- // }
- // Out::Put => {
- // info!("put");
- // let hand = player.hand.take().unwrap();
- // tile.items.push(hand);
- // self.packet_out
- // .push_back(PacketC::PutItem { item: hand, pos })
- // }
- // Out::Produce(kind) => {
- // info!("produce");
- // let id = self.item_id_counter;
- // self.item_id_counter += 1;
- // self.items.insert(id, kind);
- // tile.items.push(id);
- // self.packet_out
- // .push_back(PacketC::ProduceItem { id, pos, kind });
- // }
- // Out::Consume(index) => {
- // info!("consume");
- // let id = tile.items.remove(index);
- // info!("left {:?}", tile.items);
- // self.packet_out.push_back(PacketC::ConsumeItem { id, pos });
- // }
- // Out::SetActive(progress) => {
- // self.packet_out.push_back(PacketC::SetActive {
- // tile: pos,
- // progress,
- // });
- // }
- // },
- // );
+ if let Some(effect) = interact(&self.data, edge, tile, player) {
+ match effect {
+ InteractEffect::Put => self.packet_out.push_back(PacketC::PutItem {
+ player: pid,
+ tile: pos,
+ }),
+ InteractEffect::Take => self.packet_out.push_back(PacketC::TakeItem {
+ player: pid,
+ tile: pos,
+ }),
+ InteractEffect::Produce => {
+ if tile_had_item {
+ self.packet_out
+ .push_back(PacketC::ConsumeItem { tile: pos });
+ }
+ if player_had_item {
+ self.packet_out.push_back(PacketC::PutItem {
+ player: pid,
+ tile: pos,
+ });
+ self.packet_out
+ .push_back(PacketC::ConsumeItem { tile: pos });
+ }
+ if let Some(i) = &player.item {
+ self.packet_out.push_back(PacketC::ProduceItem {
+ tile: pos,
+ item: i.kind,
+ });
+ self.packet_out.push_back(PacketC::TakeItem {
+ player: pid,
+ tile: pos,
+ })
+ }
+ if let Some(i) = &tile.item {
+ self.packet_out.push_back(PacketC::ProduceItem {
+ tile: pos,
+ item: i.kind,
+ });
+ }
+ }
+ }
+ }
player.interacting = edge;
}
- PacketS::Collide { player, force } => {}
}
Ok(())
}
pub fn tick(&mut self, dt: f32) {
for (&pos, tile) in &mut self.tiles {
+ if let Some(effect) = tick_tile(dt, &self.data, tile) {
+ match effect {
+ TickEffect::Progress => self.packet_out.push_back(PacketC::SetActive {
+ tile: pos,
+ progress: tile
+ .item
+ .as_ref()
+ .unwrap()
+ .active
+ .as_ref()
+ .map(|i| i.progress),
+ }),
+ TickEffect::Produce => {
+ self.packet_out
+ .push_back(PacketC::ConsumeItem { tile: pos });
+ if let Some(item) = &tile.item {
+ self.packet_out.push_back(PacketC::ProduceItem {
+ tile: pos,
+ item: item.kind,
+ });
+ }
+ }
+ }
+ }
// let items = tile.items.iter().map(|e| self.items[e]).collect::<Vec<_>>();
// tick_tile(
// dt,
diff --git a/server/src/interaction.rs b/server/src/interaction.rs
index aa216410..75cd0c84 100644
--- a/server/src/interaction.rs
+++ b/server/src/interaction.rs
@@ -1,11 +1,9 @@
use crate::{
- data::{Action, Gamedata},
+ data::Gamedata,
game::{Involvement, Item, Player, Tile},
protocol::{ItemIndex, TileIndex},
};
-use log::{debug, info};
use serde::{Deserialize, Serialize};
-use std::collections::BTreeSet;
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum Recipe {
@@ -36,32 +34,47 @@ impl Recipe {
Recipe::Instant { tile, .. } => *tile,
}
}
+ pub fn duration(&self) -> Option<f32> {
+ match self {
+ Recipe::Passive { duration, .. } => Some(*duration),
+ Recipe::Active { duration, .. } => Some(*duration),
+ _ => None,
+ }
+ }
+ pub fn supports_tile(&self, tile: TileIndex) -> bool {
+ if let Some(tile_constraint) = self.tile() {
+ if tile != tile_constraint {
+ false
+ } else {
+ true
+ }
+ } else {
+ true
+ }
+ }
+}
+
+pub enum InteractEffect {
+ Put,
+ Take,
+ Produce,
}
-pub fn interact(data: &Gamedata, edge: bool, tile: &mut Tile, player: &mut Player) {
+pub fn interact(
+ data: &Gamedata,
+ edge: bool,
+ tile: &mut Tile,
+ player: &mut Player,
+) -> Option<InteractEffect> {
if !edge {
- return;
+ return None;
}
for recipe in &data.recipes {
- if let Some(tile_constraint) = recipe.tile() {
- if tile.kind != tile_constraint {
- continue;
- }
+ if !recipe.supports_tile(tile.kind) {
+ continue;
}
match recipe {
- Recipe::Passive {
- duration,
- input,
- output,
- ..
- } => todo!(),
- Recipe::Active {
- duration,
- input: inputs,
- outputs,
- ..
- } => todo!(),
Recipe::Instant {
inputs, outputs, ..
} => {
@@ -72,125 +85,67 @@ pub fn interact(data: &Gamedata, edge: bool, tile: &mut Tile, player: &mut Playe
if ok {
player.item = outputs[0].map(|kind| Item { kind, active: None });
tile.item = outputs[1].map(|kind| Item { kind, active: None });
+ return Some(InteractEffect::Produce);
}
}
+ _ => (),
}
}
-}
-// if !edge {
-// debug!("falling edge");
-// if let Some(ac) = active {
-// if matches!(data.recipes[ac.recipe].action, Action::Active(_)) {
-// debug!("workers--");
-// ac.working -= 1;
-// }
-// }
-// return;
-// }
-
-// if hand.is_none() {
-// debug!("rising edge");
-// if let Some(active) = active {
-// if matches!(data.recipes[active.recipe].action, Action::Active(_)) {
-// debug!("workers++");
-// active.working += 1;
-// }
-// }
-// }
-// if active.is_none() && !items.is_empty() && hand.is_none() {
-// out(Take(items.len() - 1));
-// return;
-// }
-
-// if active.is_none() {
-// if let Some(hi) = hand {
-// if allowed.contains(&hi) {
-// out(Put);
-// items.push(hi);
-// hand = None;
-// }
-// }
-// }
-
-// if hand.is_none() && active.is_none() {
-// 'rloop: for (ri, r) in data.recipes.iter().enumerate() {
-// if tile != r.tile {
-// continue;
-// }
-// let mut inputs = r.inputs.clone();
-// for i in &items {
-// debug!("take {i:?} {inputs:?}");
-// let Some(pos) = inputs.iter().position(|e| e == i) else {
-// continue 'rloop;
-// };
-// inputs.remove(pos);
-// }
-// debug!("end {inputs:?}");
-// if !inputs.is_empty() {
-// continue;
-// }
+ if tile.item.is_none() {
+ if let Some(item) = player.item.take() {
+ tile.item = Some(item);
+ return Some(InteractEffect::Put);
+ }
+ }
+ if player.item.is_none() {
+ if let Some(item) = tile.item.take() {
+ player.item = Some(item);
+ return Some(InteractEffect::Take);
+ }
+ }
-// match r.action {
-// Action::Passive(_) => {
-// info!("use passive recipe {ri}");
-// *active = Some(Involvement {
-// recipe: ri,
-// progress: 0.,
-// working: 1,
-// });
-// break 'rloop;
-// }
-// Action::Active(_) => {
-// info!("use active recipe {ri}");
-// *active = Some(Involvement {
-// recipe: ri,
-// progress: 0.,
-// working: 1,
-// });
-// break 'rloop;
-// }
-// Action::Instant => {
-// info!("use instant recipe {ri}");
-// for _ in 0..items.len() {
-// out(Consume(0))
-// }
-// for i in &r.outputs {
-// out(Produce(*i));
-// }
-// if !r.outputs.is_empty() {
-// out(Take(r.outputs.len() - 1));
-// }
-// items.clear();
-// break 'rloop;
-// }
-// Action::Never => (),
-// }
-// }
-// }
+ None
+}
-// pub fn tick_tile(
-// dt: f32,
-// data: &Gamedata,
-// _tile: TileIndex,
-// active: &mut Option<Involvement>,
-// items: Vec<ItemIndex>,
-// mut out: impl FnMut(Out),
-// ) {
-// if let Some(a) = active {
-// let r = &data.recipes[a.recipe];
-// a.progress += a.working as f32 * dt / r.action.duration();
-// if a.progress >= 1. {
-// for _ in 0..items.len() {
-// out(Consume(0))
-// }
-// for i in &r.outputs {
-// out(Produce(*i));
-// }
-// out(SetActive(None));
-// active.take();
-// } else {
-// out(SetActive(Some(a.progress)));
-// }
-// }
-// }
+pub enum TickEffect {
+ Progress,
+ Produce,
+}
+pub fn tick_tile(dt: f32, data: &Gamedata, tile: &mut Tile) -> Option<TickEffect> {
+ if let Some(item) = &mut tile.item {
+ if let Some(a) = &mut item.active {
+ let r = &data.recipes[a.recipe];
+ if r.supports_tile(tile.kind) {
+ a.progress += a.working as f32 * dt / r.duration().unwrap();
+ if a.progress >= 1. {
+ let Recipe::Passive { output, .. } = &data.recipes[a.recipe] else {
+ unreachable!()
+ };
+ tile.item = output.map(|kind| Item { kind, active: None });
+ return Some(TickEffect::Produce);
+ }
+ return Some(TickEffect::Progress);
+ }
+ } else {
+ for (ri, recipe) in data.recipes.iter().enumerate() {
+ if let Some(tile_constraint) = recipe.tile() {
+ if tile.kind != tile_constraint {
+ continue;
+ }
+ }
+ if let Recipe::Passive { input, .. } = recipe {
+ if *input == item.kind {
+ item.active = Some(Involvement {
+ recipe: ri,
+ progress: 0.,
+ working: 1,
+ })
+ }
+ }
+ }
+ return Some(TickEffect::Progress);
+ }
+ }
+ None
+}
diff --git a/server/src/main.rs b/server/src/main.rs
index 6cb65141..c4df346e 100644
--- a/server/src/main.rs
+++ b/server/src/main.rs
@@ -53,7 +53,7 @@ async fn main() -> Result<()> {
});
}
- for id in 0.. {
+ for id in 1.. {
tokio::select! {
r = raw_listener.accept() => {
let (sock, addr) = r?;