Skip to content

Commit ca42e5e

Browse files
committed
feat(world): border
1 parent ed4f119 commit ca42e5e

File tree

5 files changed

+121
-48
lines changed

5 files changed

+121
-48
lines changed

src/args.rs

Lines changed: 22 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -23,22 +23,27 @@ use clap::Parser;
2323
pub struct Args {
2424
/// The directory to load the map from. Should be DIM1, or the equivalent renamed folder.
2525
pub map_dir: String,
26-
/// The address to serve crawlspace on. Defaults to [::] (all interfaces) if not set.
27-
#[arg(short, long)]
28-
addr: Option<String>,
26+
/// The address to serve crawlspace on.
27+
#[arg(short, long, default_value = "[::]")]
28+
pub addr: String,
2929
/// The port to serve crawlspace on. Defaults to 25565 if not set.
30-
#[arg(short, long)]
31-
port: Option<u16>,
32-
}
33-
34-
impl Args {
35-
#[inline(always)]
36-
pub fn addr(&self) -> String {
37-
self.addr.clone().unwrap_or("[::]".into())
38-
}
39-
40-
#[inline(always)]
41-
pub fn port(&self) -> u16 {
42-
self.port.unwrap_or(25565)
43-
}
30+
#[arg(short, long, default_value = "25565")]
31+
pub port: u16,
32+
/// The x coordinate of the spawnpoint.
33+
#[arg(short = 'x', long, default_value = "0")]
34+
pub spawn_x: f64,
35+
/// The y coordinate of the spawnpoint.
36+
#[arg(short = 'y', long, default_value = "100")]
37+
pub spawn_y: f64,
38+
/// The z coordinate of the spawnpoint.
39+
#[arg(short = 'z', long, default_value = "0")]
40+
pub spawn_z: f64,
41+
/// The border radius, centered around the spawnpoint. Defaults to 10 chunks. One
42+
/// chunk past the border will be loaded.
43+
#[arg(short = 'b', long, default_value = "160")]
44+
pub border_radius: i32,
45+
#[arg(short, long, default_value = "Limbo")]
46+
pub motd: String,
47+
#[arg(long, default_value = "500")]
48+
pub max_players: usize,
4449
}

src/main.rs

Lines changed: 1 addition & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,6 @@ mod world;
3939

4040
const VERSION: &str = "1.21.1";
4141
const VERSION_NUM: i32 = 767;
42-
const DESCRIPTION: &str = "sheldon cooper residence";
43-
const MAX_PLAYERS: usize = 906;
4442
const TICK_RATE: u8 = 20;
4543

4644
type CrawlState = Arc<state::State>;
@@ -80,14 +78,7 @@ async fn main() -> Result<()> {
8078
let world_cache = WorldCache::from(world);
8179
info!("Done.");
8280

83-
let state = Arc::new(state::State::new(
84-
VERSION,
85-
VERSION_NUM,
86-
DESCRIPTION,
87-
MAX_PLAYERS,
88-
args.addr(),
89-
args.port(),
90-
));
81+
let state = Arc::new(state::State::new(VERSION, VERSION_NUM, args));
9182

9283
#[cfg(feature = "lan")]
9384
net::spawn_lan_broadcast(state.clone()).await?;

src/net/player.rs

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,8 @@ use crate::{
3737
login::*,
3838
play::{
3939
ConfirmTeleportS, GameEvent, GameEventC, Gamemode, KeepAliveC, LoginPlayC,
40-
PlayerInfoUpdateC, PlayerStatus, SetCenterChunkC, SynchronisePositionC,
40+
PlayerInfoUpdateC, PlayerStatus, SetBorderCenterC, SetBorderSizeC, SetCenterChunkC,
41+
SynchronisePositionC,
4142
},
4243
},
4344
PacketState,
@@ -289,21 +290,33 @@ impl SharedPlayer {
289290

290291
drop(io);
291292

292-
self.teleport_awaiting(0.0, 100.0, 0.0, 0.0, 0.0).await?;
293+
let spawnpoint = state.spawnpoint;
294+
self.teleport_awaiting(spawnpoint.0, spawnpoint.1, spawnpoint.2, 0.0, 0.0)
295+
.await?;
296+
297+
let mut io = self.0.io.lock().await;
298+
299+
io.tx(&SetBorderCenterC {
300+
x: spawnpoint.0,
301+
z: spawnpoint.2,
302+
})
303+
.await?;
304+
305+
io.tx(&SetBorderSizeC(state.border_radius as f64 * 2.0))
306+
.await?;
293307

294308
let player_add = PlayerInfoUpdateC {
295309
players: &[PlayerStatus::for_player(self.uuid().await).add_player("AFK", &[])],
296310
};
297311

298-
let mut io = self.0.io.lock().await;
299312
io.tx(&player_add).await?;
300313

301314
let await_chunks = GameEventC::from(GameEvent::StartWaitingForLevelChunks);
302315
io.tx(&await_chunks).await?;
303316

304317
let set_center = SetCenterChunkC {
305-
x: VarInt(0),
306-
y: VarInt(0),
318+
x: VarInt(spawnpoint.0.floor() as i32 / 16),
319+
y: VarInt(spawnpoint.2.floor() as i32 / 16),
307320
};
308321
io.tx(&set_center).await?;
309322
drop(io);

src/protocol/packets/play/world.rs

Lines changed: 65 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,10 @@ use bytes::BufMut;
2424
use fastnbt::SerOpts;
2525

2626
use crate::{
27-
protocol::{datatypes::VarInt, Encode, Packet},
27+
protocol::{
28+
datatypes::{VarInt, VarLong},
29+
Encode, Packet,
30+
},
2831
world::{
2932
self,
3033
blocks::{BlockState, Blocks},
@@ -320,3 +323,64 @@ impl ChunkDataUpdateLightC<'_> {
320323
}
321324
}
322325
}
326+
327+
#[derive(Debug)]
328+
pub struct InitializeWorldBorderC {
329+
pub x: f64,
330+
pub z: f64,
331+
pub old_diameter: f64,
332+
pub new_diameter: f64,
333+
pub speed: i64,
334+
pub teleport_boundary: i32,
335+
pub warning_blocks: i32,
336+
pub warning_time_sec: i32,
337+
}
338+
339+
impl Packet for InitializeWorldBorderC {
340+
const ID: i32 = 0x25;
341+
}
342+
343+
impl Encode for InitializeWorldBorderC {
344+
fn encode(&self, mut w: impl std::io::Write) -> color_eyre::eyre::Result<()> {
345+
self.x.encode(&mut w)?;
346+
self.z.encode(&mut w)?;
347+
self.old_diameter.encode(&mut w)?;
348+
self.new_diameter.encode(&mut w)?;
349+
VarLong(self.speed).encode(&mut w)?;
350+
VarInt(self.teleport_boundary).encode(&mut w)?;
351+
VarInt(self.warning_blocks).encode(&mut w)?;
352+
VarInt(self.warning_time_sec).encode(&mut w)?;
353+
Ok(())
354+
}
355+
}
356+
357+
#[derive(Debug)]
358+
pub struct SetBorderCenterC {
359+
pub x: f64,
360+
pub z: f64,
361+
}
362+
363+
impl Packet for SetBorderCenterC {
364+
const ID: i32 = 0x4D;
365+
}
366+
367+
impl Encode for SetBorderCenterC {
368+
fn encode(&self, mut w: impl std::io::Write) -> color_eyre::eyre::Result<()> {
369+
self.x.encode(&mut w)?;
370+
self.z.encode(&mut w)?;
371+
Ok(())
372+
}
373+
}
374+
375+
#[derive(Debug)]
376+
pub struct SetBorderSizeC(pub f64);
377+
378+
impl Packet for SetBorderSizeC {
379+
const ID: i32 = 0x4F;
380+
}
381+
382+
impl Encode for SetBorderSizeC {
383+
fn encode(&self, w: impl std::io::Write) -> color_eyre::eyre::Result<()> {
384+
self.0.encode(w)
385+
}
386+
}

src/state.rs

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ use tokio::sync::{mpsc, Mutex, Semaphore};
2323
use tokio_util::sync::CancellationToken;
2424

2525
use crate::{
26+
args::Args,
2627
net::{cache::RegistryCache, player::SharedPlayer},
2728
protocol::packets::login::registry::ALL_REGISTRIES,
2829
};
@@ -45,22 +46,18 @@ pub struct State {
4546
pub shutdown_token: CancellationToken,
4647

4748
pub net_sema: Arc<Semaphore>,
49+
50+
pub spawnpoint: (f64, f64, f64),
51+
pub border_radius: i32,
4852
}
4953

5054
impl State {
5155
#[must_use]
52-
pub fn new(
53-
version_name: &str,
54-
version_number: i32,
55-
description: &str,
56-
max_players: usize,
57-
addr: String,
58-
port: u16,
59-
) -> Self {
60-
let max = max_players.min(Semaphore::MAX_PERMITS);
61-
62-
if max < max_players {
63-
warn!("Requested max player count {max_players} is less than max semaphore permits {max} - limited to {max}.");
56+
pub fn new(version_name: &str, version_number: i32, args: Args) -> Self {
57+
let max = args.max_players.min(Semaphore::MAX_PERMITS);
58+
59+
if max < args.max_players {
60+
warn!("Requested max player count {} is less than max semaphore permits {max} - limited to {max}.", args.max_players);
6461
}
6562

6663
let (player_send, player_recv) = mpsc::channel(16);
@@ -69,11 +66,11 @@ impl State {
6966
Self {
7067
max_players: max,
7168
current_players: AtomicUsize::new(0),
72-
description: description.to_owned(),
69+
description: args.motd,
7370
version_name: version_name.to_owned(),
7471
version_number: version_number.to_owned(),
75-
addr,
76-
port,
72+
addr: args.addr,
73+
port: args.port,
7774

7875
registry_cache: RegistryCache::from(&*ALL_REGISTRIES),
7976

@@ -83,6 +80,9 @@ impl State {
8380
shutdown_token,
8481

8582
net_sema: Arc::new(Semaphore::new(max)),
83+
84+
spawnpoint: (args.spawn_x, args.spawn_y, args.spawn_z),
85+
border_radius: args.border_radius,
8686
}
8787
}
8888
}

0 commit comments

Comments
 (0)