Skip to content

Commit

Permalink
fix(player): only open window on interaction with container
Browse files Browse the repository at this point in the history
  • Loading branch information
bigspeedfpv committed Nov 28, 2024
1 parent d056ebe commit 163ae45
Show file tree
Hide file tree
Showing 11 changed files with 164 additions and 42 deletions.
4 changes: 2 additions & 2 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ use std::{fs::OpenOptions, sync::Arc};
use args::Args;
use clap::Parser;
use color_eyre::eyre::Result;
use net::cache::WorldCache;
use net::cache::{RegistryCache, WorldCache};
use server::Server;
use tracing_subscriber::{layer::SubscriberExt, prelude::*, EnvFilter};
use world::read_world;
Expand Down Expand Up @@ -77,7 +77,7 @@ async fn main() -> Result<()> {
let state = Arc::new(state::State::new(VERSION, VERSION_NUM, args));

info!("Generating world chunk packets");
let world_cache = WorldCache::from_anvil(state.clone(), world);
let world_cache = WorldCache::from_anvil(state.clone(), &world);
info!("Done.");

#[cfg(feature = "lan")]
Expand Down
70 changes: 60 additions & 10 deletions src/net/cache.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
* <https://www.gnu.org/licenses/>.
*/

use std::cmp::Ordering;
use std::{cmp::Ordering, collections::HashMap};

use rayon::prelude::*;

Expand All @@ -30,17 +30,18 @@ use crate::{
},
Encoder,
},
world::{blocks::Blocks, World},
world::{blocks::Blocks, BlockEntity, Container, World},
CrawlState,
};

#[derive(Debug)]
pub struct WorldCache {
pub encoded: Vec<Vec<u8>>,
pub containers: HashMap<(i32, i32, i32), Container>,
}

impl WorldCache {
pub fn from_anvil(crawlstate: CrawlState, world: World) -> Self {
pub fn from_anvil(crawlstate: CrawlState, world: &World) -> Self {
let mut chunks = world.0.iter().collect::<Vec<_>>();

chunks.sort_by(|((ax, az), _), ((bx, bz), _)| {
Expand All @@ -53,23 +54,72 @@ impl WorldCache {

let block_states = Blocks::new();

let chunks = chunks
.par_iter()
.map(|(_, c)| ChunkDataUpdateLightC::new(crawlstate.clone(), c, &block_states))
.collect::<Vec<ChunkDataUpdateLightC<'_>>>();
let containers = chunks
.iter()
.map(|(_, c)| {
c.block_entities
.iter()
.filter_map(|block_entity| {
// TODO: cache this somewhere so block entities aren't parsed twice on startup
let block_entity = BlockEntity::try_parse((*block_entity).clone())
.map_or_else(
|why| {
warn!(
"Failed to parse block entity: {why}, ignoring in container cache for ({}, {})",
c.x_pos,
c.z_pos,
);
None
},
|e| match e.keep_packed {
true => None,
false => Some(e),
},
);

let Some(block_entity) = block_entity else {
return None;
};

match block_entity.id.as_str() {
"minecraft:chest" | "minecraft:trapped_chest" | "minecraft:barrel" => {
Some(block_entity)
}
_ => None,
}
})
.map(|container| {
(
(container.x, container.y, container.z),
Container(Vec::new()),
)
})
.collect::<Vec<((i32, i32, i32), Container)>>()
})
.flatten()
.collect();

info!("Containers: {:?}", containers);

let encoded = chunks
.par_iter()
.map(|chunk| {
.map(|(_, chunk)| {
let mut encoder = Encoder::new();
encoder
.append_packet(chunk)
.append_packet(&ChunkDataUpdateLightC::new(
crawlstate.clone(),
chunk,
&block_states,
))
.expect("Failed to append packet to encoder");
encoder.take().to_vec()
})
.collect();

Self { encoded }
Self {
encoded,
containers,
}
}
}

Expand Down
7 changes: 2 additions & 5 deletions src/net/io.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,6 @@ pub struct NetIo {
pub connected: RwLock<bool>,
read_half: Mutex<OwnedReadHalf>,
write_half: Mutex<OwnedWriteHalf>,
frame: Mutex<Frame>,
decoder: Mutex<protocol::Decoder>,
encoder: Mutex<protocol::Encoder>,
}
Expand Down Expand Up @@ -67,10 +66,6 @@ impl NetIo {
connected: RwLock::new(true),
read_half: Mutex::new(read_half),
write_half: Mutex::new(write_half),
frame: Mutex::new(Frame {
id: -1,
body: BytesMut::new(),
}),
decoder: Mutex::new(protocol::Decoder::new()),
encoder: Mutex::new(protocol::Encoder::new()),
}
Expand Down Expand Up @@ -100,6 +95,8 @@ impl NetIo {
continue;
}

// TODO: decode here, rather than forcing the consumer to do it.
// probably need to box frame data? idk enough rust for this
return Ok(frame);
};

Expand Down
34 changes: 24 additions & 10 deletions src/net/player.rs
Original file line number Diff line number Diff line change
Expand Up @@ -558,19 +558,33 @@ impl SharedPlayer {
}

async fn handle_use_item(&self, packet: UseItemOnS) -> Result<()> {
let id = self.0.next_window_id.fetch_add(1, Ordering::Relaxed);
let crawlstate = self.0.crawlstate.clone();
let server = crawlstate.get_server().await;

let window = Window {
id,
kind: WindowType::Generic9x3,
title: "Hi".into(),
};
let x = packet.location.x as i32;
let y = packet.location.y as i32;
let z = packet.location.z as i32;

self.0.io.tx(&OpenScreenC::from(&window)).await?;
debug!("Player {} clicked at {}, {}, {}", self.id(), x, y, z);

{
let mut sw = self.0.window.write().await;
*sw = Some(window);
match server.get_container(x, y, z) {
None => (),
Some(container) => {
let id = self.0.next_window_id.fetch_add(1, Ordering::Relaxed);

let window = Window {
id,
kind: WindowType::Generic9x3,
title: "Hi".into(),
};

self.0.io.tx(&OpenScreenC::from(&window)).await?;

{
let mut sw = self.0.window.write().await;
*sw = Some(window);
}
}
}

Ok(())
Expand Down
3 changes: 3 additions & 0 deletions src/protocol/datatypes/slot.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,6 @@
* License along with Crawlspace. If not, see
* <https://www.gnu.org/licenses/>.
*/

#[derive(Debug, Clone)]
pub struct Slot;
2 changes: 1 addition & 1 deletion src/protocol/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ pub mod datatypes {

pub use impls::*;
pub use position::*;

pub use slot::*;
pub use string::*;
pub use text_component::*;
pub use variable::*;
Expand Down
38 changes: 27 additions & 11 deletions src/server/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,13 @@ pub mod window;
use std::{
collections::{HashMap, HashSet},
sync::Arc,
time::Duration,
};

use color_eyre::eyre::Result;

use tokio::sync::Mutex;

#[cfg(feature = "timings")]
use tokio::time::Instant;

Expand All @@ -34,6 +38,7 @@ use crate::{
cache::WorldCache,
player::{SharedPlayer, TeleportError},
},
world::{Container, World},
CrawlState,
};

Expand All @@ -44,37 +49,45 @@ pub struct Server {
pub ticker: Ticker,

world_cache: Arc<WorldCache>,
players: HashMap<u16, SharedPlayer>,
players: Mutex<HashMap<u16, SharedPlayer>>,

crawlstate: CrawlState,
}

impl Server {
#[must_use]
pub fn new(state: CrawlState, world_cache: WorldCache, tick_rate: u8) -> Self {
Server {
pub fn new(state: CrawlState, world_cache: WorldCache, tick_rate: u8) -> Arc<Self> {
let server = Arc::new(Server {
ticker: Ticker::new(tick_rate),
world_cache: Arc::new(world_cache),
players: HashMap::new(),
crawlstate: state,
}
players: Mutex::new(HashMap::new()),
crawlstate: state.clone(),
});

let state_server = server.clone();
tokio::spawn(async move {
state.set_server(state_server).await;
});

server
}

async fn tick(&mut self) {
async fn tick(&self) {
#[cfg(feature = "timings")]
let run_start = Instant::now();

let state = self.crawlstate.clone();
let mut player_recv = state.player_recv.lock().await;

let mut players = self.players.lock().await;
while let Ok(p) = player_recv.try_recv() {
self.players.insert(p.0.id, p.clone());
players.insert(p.0.id, p.clone());
tokio::spawn(Self::send_world_to(p.clone(), self.world_cache.clone()));
}

let mut invalid_players: HashSet<u16> = HashSet::new();

for (id, player) in &self.players {
for (id, player) in &*players {
let _ = player.keepalive().await;

match player.handle_all_packets().await {
Expand Down Expand Up @@ -103,13 +116,12 @@ impl Server {

for id in invalid_players {
// TODO: kick player properly
self.players.remove(&id);
players.remove(&id);
}

#[cfg(feature = "timings")]
{
let run_end = Instant::now();
debug!("Tick took {}ms", (run_start - run_end).as_millis());
debug!("Tick took {}ms", (run_end - run_start).as_millis());
}
}
Expand All @@ -121,4 +133,8 @@ impl Server {

Ok(())
}

pub fn get_container(&self, x: i32, y: i32, z: i32) -> Option<Container> {
self.world_cache.containers.get(&(x, y, z)).cloned()
}
}
4 changes: 2 additions & 2 deletions src/server/ticker.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
* <https://www.gnu.org/licenses/>.
*/

use std::time::Duration;
use std::{sync::Arc, time::Duration};

use tokio::time::{sleep, Instant};

Expand All @@ -36,7 +36,7 @@ impl Ticker {
}
}

pub async fn run(&mut self, mut server: super::Server) {
pub async fn run(&mut self, server: Arc<super::Server>) {
loop {
let now = Instant::now();
let elapsed = now - self.last_tick;
Expand Down
19 changes: 18 additions & 1 deletion src/state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,14 @@

use std::sync::{atomic::AtomicUsize, Arc};

use tokio::sync::{mpsc, Mutex, Semaphore};
use tokio::sync::{mpsc, Mutex, RwLock, Semaphore};
use tokio_util::sync::CancellationToken;

use crate::{
args::Args,
net::{cache::RegistryCache, player::SharedPlayer},
protocol::packets::login::registry::ALL_REGISTRIES,
server::Server,
};

#[derive(Debug)]
Expand All @@ -49,6 +50,8 @@ pub struct State {

pub spawnpoint: (f64, f64, f64),
pub border_radius: i32,

server: RwLock<Option<Arc<Server>>>,
}

impl State {
Expand Down Expand Up @@ -83,6 +86,20 @@ impl State {

spawnpoint: (args.spawn_x, args.spawn_y, args.spawn_z),
border_radius: args.border_radius,

server: RwLock::new(None),
}
}

pub async fn set_server(&self, server: Arc<Server>) {
let mut write = self.server.write().await;
*write = Some(server);
}

pub async fn get_server(&self) -> Arc<Server> {
let server = self.server.read().await;
server
.clone()
.expect("state.get_server called before server initialized")
}
}
Loading

0 comments on commit 163ae45

Please sign in to comment.