mirror of
https://github.com/timvisee/lazymc.git
synced 2025-05-19 04:40:22 -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::config::*;
|
||||||
use crate::forge;
|
use crate::forge;
|
||||||
use crate::mc::{self, uuid};
|
use crate::mc::{self, dimension, uuid};
|
||||||
use crate::net;
|
use crate::net;
|
||||||
use crate::proto;
|
use crate::proto;
|
||||||
use crate::proto::client::{Client, ClientInfo, ClientState};
|
use crate::proto::client::{Client, ClientInfo, ClientState};
|
||||||
@ -273,13 +273,14 @@ async fn send_lobby_join_game(
|
|||||||
writer: &mut WriteHalf<'_>,
|
writer: &mut WriteHalf<'_>,
|
||||||
server: &Server,
|
server: &Server,
|
||||||
) -> Result<(), ()> {
|
) -> Result<(), ()> {
|
||||||
// Grab probed dimension codec
|
// Get dimension codec and build lobby dimension
|
||||||
let dimension_codec: CompoundTag =
|
let dimension_codec: CompoundTag =
|
||||||
if let Some(ref join_game) = server.probed_join_game.lock().await.as_ref() {
|
if let Some(ref join_game) = server.probed_join_game.lock().await.as_ref() {
|
||||||
join_game.dimension_codec.clone()
|
join_game.dimension_codec.clone()
|
||||||
} else {
|
} 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
|
// Send Minecrafts default states, slightly customised for lobby world
|
||||||
packet::write_packet(
|
packet::write_packet(
|
||||||
@ -299,7 +300,7 @@ async fn send_lobby_join_game(
|
|||||||
"minecraft:the_end".into(),
|
"minecraft:the_end".into(),
|
||||||
],
|
],
|
||||||
dimension_codec,
|
dimension_codec,
|
||||||
dimension: snbt_to_compound_tag(include_str!("../res/dimension.snbt")),
|
dimension,
|
||||||
world_name: "lazymc:lobby".into(),
|
world_name: "lazymc:lobby".into(),
|
||||||
hashed_seed: 0,
|
hashed_seed: 0,
|
||||||
max_players: status.as_ref().map(|s| s.players.max as i32).unwrap_or(20),
|
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;
|
pub mod ban;
|
||||||
|
#[cfg(feature = "lobby")]
|
||||||
|
pub mod dimension;
|
||||||
pub mod favicon;
|
pub mod favicon;
|
||||||
#[cfg(feature = "rcon")]
|
#[cfg(feature = "rcon")]
|
||||||
pub mod rcon;
|
pub mod rcon;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user