diff options
Diffstat (limited to 'server/src')
| -rw-r--r-- | server/src/game.rs | 127 | ||||
| -rw-r--r-- | server/src/interaction.rs | 227 | ||||
| -rw-r--r-- | server/src/main.rs | 2 | 
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?; | 
