mirror of
https://github.com/timvisee/lazymc.git
synced 2025-05-19 12:50:23 -07:00
Dynamically build lobby dimension from probed server dimension codec
This commit is contained in:
parent
f513957bff
commit
cf6bd526d9
32
src/lobby.rs
32
src/lobby.rs
@ -30,7 +30,7 @@ use tokio::time;
|
||||
|
||||
use crate::config::*;
|
||||
use crate::forge;
|
||||
use crate::mc::{self, uuid};
|
||||
use crate::mc::{self, dimension, uuid};
|
||||
use crate::net;
|
||||
use crate::proto;
|
||||
use crate::proto::client::{Client, ClientInfo, ClientState};
|
||||
@ -273,13 +273,14 @@ async fn send_lobby_join_game(
|
||||
writer: &mut WriteHalf<'_>,
|
||||
server: &Server,
|
||||
) -> Result<(), ()> {
|
||||
// Grab probed dimension codec
|
||||
// Get dimension codec and build lobby dimension
|
||||
let dimension_codec: CompoundTag =
|
||||
if let Some(ref join_game) = server.probed_join_game.lock().await.as_ref() {
|
||||
join_game.dimension_codec.clone()
|
||||
} else {
|
||||
snbt_to_compound_tag(include_str!("../res/dimension_codec.snbt"))
|
||||
dimension::lobby_default_dimension_codec()
|
||||
};
|
||||
let dimension: CompoundTag = dimension::lobby_dimension(&dimension_codec);
|
||||
|
||||
// Send Minecrafts default states, slightly customised for lobby world
|
||||
packet::write_packet(
|
||||
@ -299,7 +300,7 @@ async fn send_lobby_join_game(
|
||||
"minecraft:the_end".into(),
|
||||
],
|
||||
dimension_codec,
|
||||
dimension: snbt_to_compound_tag(include_str!("../res/dimension.snbt")),
|
||||
dimension,
|
||||
world_name: "lazymc:lobby".into(),
|
||||
hashed_seed: 0,
|
||||
max_players: status.as_ref().map(|s| s.players.max as i32).unwrap_or(20),
|
||||
@ -858,26 +859,3 @@ async fn drain_stream(reader: &mut ReadHalf<'_>) -> Result<(), ()> {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Read NBT CompoundTag from SNBT.
|
||||
fn snbt_to_compound_tag(data: &str) -> CompoundTag {
|
||||
use quartz_nbt::io::{write_nbt, Flavor};
|
||||
use quartz_nbt::snbt;
|
||||
|
||||
// Parse SNBT data
|
||||
let compound = snbt::parse(data).expect("failed to parse SNBT");
|
||||
|
||||
// Encode to binary
|
||||
let mut binary = Vec::new();
|
||||
write_nbt(&mut binary, None, &compound, Flavor::Uncompressed)
|
||||
.expect("failed to encode NBT CompoundTag as binary");
|
||||
|
||||
// Parse binary with usable NBT create
|
||||
bin_to_compound_tag(&mut &*binary)
|
||||
}
|
||||
|
||||
/// Read NBT CompoundTag from SNBT.
|
||||
fn bin_to_compound_tag(data: &[u8]) -> CompoundTag {
|
||||
use nbt::decode::read_compound_tag;
|
||||
read_compound_tag(&mut &*data).unwrap()
|
||||
}
|
||||
|
112
src/mc/dimension.rs
Normal file
112
src/mc/dimension.rs
Normal file
@ -0,0 +1,112 @@
|
||||
use nbt::CompoundTag;
|
||||
|
||||
/// Create lobby dimension from the given codec.
|
||||
///
|
||||
/// This creates a dimension suitable for the lobby that should be suitable for the current server
|
||||
/// version.
|
||||
pub fn lobby_dimension(codec: &CompoundTag) -> CompoundTag {
|
||||
// Retrieve dimension types from codec
|
||||
let dimension_types = match codec.get_compound_tag("minecraft:dimension_type") {
|
||||
Ok(types) => types,
|
||||
Err(_) => return lobby_default_dimension(),
|
||||
};
|
||||
|
||||
// Get base dimension
|
||||
let mut base = lobby_base_dimension(dimension_types);
|
||||
|
||||
// Change known properties on base to get more desirable dimension
|
||||
base.insert_i8("piglin_safe", 1);
|
||||
base.insert_f32("ambient_light", 0.0);
|
||||
// base.insert_str("infiniburn", "minecraft:infiniburn_end");
|
||||
base.insert_i8("respawn_anchor_works", 0);
|
||||
base.insert_i8("has_skylight", 0);
|
||||
base.insert_i8("bed_works", 0);
|
||||
base.insert_str("effects", "minecraft:the_end");
|
||||
base.insert_i64("fixed_time", 0);
|
||||
base.insert_i8("has_raids", 0);
|
||||
base.insert_i32("min_y", 0);
|
||||
base.insert_i32("height", 1);
|
||||
base.insert_i32("logical_height", 1);
|
||||
base.insert_f64("coordinate_scale", 1.0);
|
||||
base.insert_i8("ultrawarm", 0);
|
||||
base.insert_i8("has_ceiling", 0);
|
||||
|
||||
base
|
||||
}
|
||||
|
||||
/// Get lobby base dimension.
|
||||
///
|
||||
/// This retrieves the most desirable dimension to use as base for the lobby from the given list of
|
||||
/// `dimension_types`.
|
||||
///
|
||||
/// If no dimension is found in the given tag, a default one will be returned.
|
||||
fn lobby_base_dimension(dimension_types: &CompoundTag) -> CompoundTag {
|
||||
// The dimension types we prefer the most, in order
|
||||
let preferred = vec![
|
||||
"minecraft:the_end",
|
||||
"minecraft:the_nether",
|
||||
"minecraft:the_overworld",
|
||||
];
|
||||
|
||||
let dimensions = dimension_types.get_compound_tag_vec("value").unwrap();
|
||||
|
||||
for name in preferred {
|
||||
if let Some(dimension) = dimensions
|
||||
.iter()
|
||||
.find(|d| d.get_str("name").map(|n| n == name).unwrap_or(false))
|
||||
{
|
||||
if let Ok(dimension) = dimension.get_compound_tag("element") {
|
||||
return dimension.clone();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Return first dimension
|
||||
if let Some(dimension) = dimensions.first() {
|
||||
if let Ok(dimension) = dimension.get_compound_tag("element") {
|
||||
return dimension.clone();
|
||||
}
|
||||
}
|
||||
|
||||
// Fall back to default dimension
|
||||
lobby_default_dimension()
|
||||
}
|
||||
|
||||
/// Default lobby dimension codec from resource file.
|
||||
///
|
||||
/// This likely breaks if the Minecraft version doesn't match exactly.
|
||||
/// Please use an up-to-date coded from the server instead.
|
||||
pub fn lobby_default_dimension_codec() -> CompoundTag {
|
||||
snbt_to_compound_tag(include_str!("../../res/dimension_codec.snbt"))
|
||||
}
|
||||
|
||||
/// Default lobby dimension from resource file.
|
||||
///
|
||||
/// This likely breaks if the Minecraft version doesn't match exactly.
|
||||
/// Please use `lobby_dimension` with an up-to-date coded from the server instead.
|
||||
fn lobby_default_dimension() -> CompoundTag {
|
||||
snbt_to_compound_tag(include_str!("../../res/dimension.snbt"))
|
||||
}
|
||||
|
||||
/// Read NBT CompoundTag from SNBT.
|
||||
fn snbt_to_compound_tag(data: &str) -> CompoundTag {
|
||||
use quartz_nbt::io::{write_nbt, Flavor};
|
||||
use quartz_nbt::snbt;
|
||||
|
||||
// Parse SNBT data
|
||||
let compound = snbt::parse(data).expect("failed to parse SNBT");
|
||||
|
||||
// Encode to binary
|
||||
let mut binary = Vec::new();
|
||||
write_nbt(&mut binary, None, &compound, Flavor::Uncompressed)
|
||||
.expect("failed to encode NBT CompoundTag as binary");
|
||||
|
||||
// Parse binary with usable NBT create
|
||||
bin_to_compound_tag(&mut &*binary)
|
||||
}
|
||||
|
||||
/// Read NBT CompoundTag from SNBT.
|
||||
fn bin_to_compound_tag(data: &[u8]) -> CompoundTag {
|
||||
use nbt::decode::read_compound_tag;
|
||||
read_compound_tag(&mut &*data).unwrap()
|
||||
}
|
@ -1,4 +1,6 @@
|
||||
pub mod ban;
|
||||
#[cfg(feature = "lobby")]
|
||||
pub mod dimension;
|
||||
pub mod favicon;
|
||||
#[cfg(feature = "rcon")]
|
||||
pub mod rcon;
|
||||
|
Loading…
x
Reference in New Issue
Block a user