Skip to content

Commit 163ae45

Browse files
committed
fix(player): only open window on interaction with container
1 parent d056ebe commit 163ae45

File tree

11 files changed

+164
-42
lines changed

11 files changed

+164
-42
lines changed

src/main.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ use std::{fs::OpenOptions, sync::Arc};
2222
use args::Args;
2323
use clap::Parser;
2424
use color_eyre::eyre::Result;
25-
use net::cache::WorldCache;
25+
use net::cache::{RegistryCache, WorldCache};
2626
use server::Server;
2727
use tracing_subscriber::{layer::SubscriberExt, prelude::*, EnvFilter};
2828
use world::read_world;
@@ -77,7 +77,7 @@ async fn main() -> Result<()> {
7777
let state = Arc::new(state::State::new(VERSION, VERSION_NUM, args));
7878

7979
info!("Generating world chunk packets");
80-
let world_cache = WorldCache::from_anvil(state.clone(), world);
80+
let world_cache = WorldCache::from_anvil(state.clone(), &world);
8181
info!("Done.");
8282

8383
#[cfg(feature = "lan")]

src/net/cache.rs

Lines changed: 60 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
* <https://www.gnu.org/licenses/>.
1818
*/
1919

20-
use std::cmp::Ordering;
20+
use std::{cmp::Ordering, collections::HashMap};
2121

2222
use rayon::prelude::*;
2323

@@ -30,17 +30,18 @@ use crate::{
3030
},
3131
Encoder,
3232
},
33-
world::{blocks::Blocks, World},
33+
world::{blocks::Blocks, BlockEntity, Container, World},
3434
CrawlState,
3535
};
3636

3737
#[derive(Debug)]
3838
pub struct WorldCache {
3939
pub encoded: Vec<Vec<u8>>,
40+
pub containers: HashMap<(i32, i32, i32), Container>,
4041
}
4142

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

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

5455
let block_states = Blocks::new();
5556

56-
let chunks = chunks
57-
.par_iter()
58-
.map(|(_, c)| ChunkDataUpdateLightC::new(crawlstate.clone(), c, &block_states))
59-
.collect::<Vec<ChunkDataUpdateLightC<'_>>>();
57+
let containers = chunks
58+
.iter()
59+
.map(|(_, c)| {
60+
c.block_entities
61+
.iter()
62+
.filter_map(|block_entity| {
63+
// TODO: cache this somewhere so block entities aren't parsed twice on startup
64+
let block_entity = BlockEntity::try_parse((*block_entity).clone())
65+
.map_or_else(
66+
|why| {
67+
warn!(
68+
"Failed to parse block entity: {why}, ignoring in container cache for ({}, {})",
69+
c.x_pos,
70+
c.z_pos,
71+
);
72+
None
73+
},
74+
|e| match e.keep_packed {
75+
true => None,
76+
false => Some(e),
77+
},
78+
);
79+
80+
let Some(block_entity) = block_entity else {
81+
return None;
82+
};
83+
84+
match block_entity.id.as_str() {
85+
"minecraft:chest" | "minecraft:trapped_chest" | "minecraft:barrel" => {
86+
Some(block_entity)
87+
}
88+
_ => None,
89+
}
90+
})
91+
.map(|container| {
92+
(
93+
(container.x, container.y, container.z),
94+
Container(Vec::new()),
95+
)
96+
})
97+
.collect::<Vec<((i32, i32, i32), Container)>>()
98+
})
99+
.flatten()
100+
.collect();
101+
102+
info!("Containers: {:?}", containers);
60103

61104
let encoded = chunks
62105
.par_iter()
63-
.map(|chunk| {
106+
.map(|(_, chunk)| {
64107
let mut encoder = Encoder::new();
65108
encoder
66-
.append_packet(chunk)
109+
.append_packet(&ChunkDataUpdateLightC::new(
110+
crawlstate.clone(),
111+
chunk,
112+
&block_states,
113+
))
67114
.expect("Failed to append packet to encoder");
68115
encoder.take().to_vec()
69116
})
70117
.collect();
71118

72-
Self { encoded }
119+
Self {
120+
encoded,
121+
containers,
122+
}
73123
}
74124
}
75125

src/net/io.rs

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,6 @@ pub struct NetIo {
3838
pub connected: RwLock<bool>,
3939
read_half: Mutex<OwnedReadHalf>,
4040
write_half: Mutex<OwnedWriteHalf>,
41-
frame: Mutex<Frame>,
4241
decoder: Mutex<protocol::Decoder>,
4342
encoder: Mutex<protocol::Encoder>,
4443
}
@@ -67,10 +66,6 @@ impl NetIo {
6766
connected: RwLock::new(true),
6867
read_half: Mutex::new(read_half),
6968
write_half: Mutex::new(write_half),
70-
frame: Mutex::new(Frame {
71-
id: -1,
72-
body: BytesMut::new(),
73-
}),
7469
decoder: Mutex::new(protocol::Decoder::new()),
7570
encoder: Mutex::new(protocol::Encoder::new()),
7671
}
@@ -100,6 +95,8 @@ impl NetIo {
10095
continue;
10196
}
10297

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

src/net/player.rs

Lines changed: 24 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -558,19 +558,33 @@ impl SharedPlayer {
558558
}
559559

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

563-
let window = Window {
564-
id,
565-
kind: WindowType::Generic9x3,
566-
title: "Hi".into(),
567-
};
564+
let x = packet.location.x as i32;
565+
let y = packet.location.y as i32;
566+
let z = packet.location.z as i32;
568567

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

571-
{
572-
let mut sw = self.0.window.write().await;
573-
*sw = Some(window);
570+
match server.get_container(x, y, z) {
571+
None => (),
572+
Some(container) => {
573+
let id = self.0.next_window_id.fetch_add(1, Ordering::Relaxed);
574+
575+
let window = Window {
576+
id,
577+
kind: WindowType::Generic9x3,
578+
title: "Hi".into(),
579+
};
580+
581+
self.0.io.tx(&OpenScreenC::from(&window)).await?;
582+
583+
{
584+
let mut sw = self.0.window.write().await;
585+
*sw = Some(window);
586+
}
587+
}
574588
}
575589

576590
Ok(())

src/protocol/datatypes/slot.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,3 +16,6 @@
1616
* License along with Crawlspace. If not, see
1717
* <https://www.gnu.org/licenses/>.
1818
*/
19+
20+
#[derive(Debug, Clone)]
21+
pub struct Slot;

src/protocol/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ pub mod datatypes {
2727

2828
pub use impls::*;
2929
pub use position::*;
30-
30+
pub use slot::*;
3131
pub use string::*;
3232
pub use text_component::*;
3333
pub use variable::*;

src/server/mod.rs

Lines changed: 27 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,13 @@ pub mod window;
2323
use std::{
2424
collections::{HashMap, HashSet},
2525
sync::Arc,
26+
time::Duration,
2627
};
2728

2829
use color_eyre::eyre::Result;
30+
31+
use tokio::sync::Mutex;
32+
2933
#[cfg(feature = "timings")]
3034
use tokio::time::Instant;
3135

@@ -34,6 +38,7 @@ use crate::{
3438
cache::WorldCache,
3539
player::{SharedPlayer, TeleportError},
3640
},
41+
world::{Container, World},
3742
CrawlState,
3843
};
3944

@@ -44,37 +49,45 @@ pub struct Server {
4449
pub ticker: Ticker,
4550

4651
world_cache: Arc<WorldCache>,
47-
players: HashMap<u16, SharedPlayer>,
52+
players: Mutex<HashMap<u16, SharedPlayer>>,
4853

4954
crawlstate: CrawlState,
5055
}
5156

5257
impl Server {
5358
#[must_use]
54-
pub fn new(state: CrawlState, world_cache: WorldCache, tick_rate: u8) -> Self {
55-
Server {
59+
pub fn new(state: CrawlState, world_cache: WorldCache, tick_rate: u8) -> Arc<Self> {
60+
let server = Arc::new(Server {
5661
ticker: Ticker::new(tick_rate),
5762
world_cache: Arc::new(world_cache),
58-
players: HashMap::new(),
59-
crawlstate: state,
60-
}
63+
players: Mutex::new(HashMap::new()),
64+
crawlstate: state.clone(),
65+
});
66+
67+
let state_server = server.clone();
68+
tokio::spawn(async move {
69+
state.set_server(state_server).await;
70+
});
71+
72+
server
6173
}
6274

63-
async fn tick(&mut self) {
75+
async fn tick(&self) {
6476
#[cfg(feature = "timings")]
6577
let run_start = Instant::now();
6678

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

82+
let mut players = self.players.lock().await;
7083
while let Ok(p) = player_recv.try_recv() {
71-
self.players.insert(p.0.id, p.clone());
84+
players.insert(p.0.id, p.clone());
7285
tokio::spawn(Self::send_world_to(p.clone(), self.world_cache.clone()));
7386
}
7487

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

77-
for (id, player) in &self.players {
90+
for (id, player) in &*players {
7891
let _ = player.keepalive().await;
7992

8093
match player.handle_all_packets().await {
@@ -103,13 +116,12 @@ impl Server {
103116

104117
for id in invalid_players {
105118
// TODO: kick player properly
106-
self.players.remove(&id);
119+
players.remove(&id);
107120
}
108121

109122
#[cfg(feature = "timings")]
110123
{
111124
let run_end = Instant::now();
112-
debug!("Tick took {}ms", (run_start - run_end).as_millis());
113125
debug!("Tick took {}ms", (run_end - run_start).as_millis());
114126
}
115127
}
@@ -121,4 +133,8 @@ impl Server {
121133

122134
Ok(())
123135
}
136+
137+
pub fn get_container(&self, x: i32, y: i32, z: i32) -> Option<Container> {
138+
self.world_cache.containers.get(&(x, y, z)).cloned()
139+
}
124140
}

src/server/ticker.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
* <https://www.gnu.org/licenses/>.
1818
*/
1919

20-
use std::time::Duration;
20+
use std::{sync::Arc, time::Duration};
2121

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

@@ -36,7 +36,7 @@ impl Ticker {
3636
}
3737
}
3838

39-
pub async fn run(&mut self, mut server: super::Server) {
39+
pub async fn run(&mut self, server: Arc<super::Server>) {
4040
loop {
4141
let now = Instant::now();
4242
let elapsed = now - self.last_tick;

src/state.rs

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,14 @@
1919

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

22-
use tokio::sync::{mpsc, Mutex, Semaphore};
22+
use tokio::sync::{mpsc, Mutex, RwLock, Semaphore};
2323
use tokio_util::sync::CancellationToken;
2424

2525
use crate::{
2626
args::Args,
2727
net::{cache::RegistryCache, player::SharedPlayer},
2828
protocol::packets::login::registry::ALL_REGISTRIES,
29+
server::Server,
2930
};
3031

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

5051
pub spawnpoint: (f64, f64, f64),
5152
pub border_radius: i32,
53+
54+
server: RwLock<Option<Arc<Server>>>,
5255
}
5356

5457
impl State {
@@ -83,6 +86,20 @@ impl State {
8386

8487
spawnpoint: (args.spawn_x, args.spawn_y, args.spawn_z),
8588
border_radius: args.border_radius,
89+
90+
server: RwLock::new(None),
8691
}
8792
}
93+
94+
pub async fn set_server(&self, server: Arc<Server>) {
95+
let mut write = self.server.write().await;
96+
*write = Some(server);
97+
}
98+
99+
pub async fn get_server(&self) -> Arc<Server> {
100+
let server = self.server.read().await;
101+
server
102+
.clone()
103+
.expect("state.get_server called before server initialized")
104+
}
88105
}

0 commit comments

Comments
 (0)