1.18.1 protocol (757) (#640)

https://wiki.vg/index.php?title=Protocol&oldid=17203 1.18.1
https://wiki.vg/index.php?title=Protocol&type=revision&diff=17203&oldid=16918 1.18.1 vs 1.17.1

* protocol: add UpdateSimulationDistance packet and update IDs
* protocol: add JoinGame_WorldNames_IsHard_SimDist packet variant
* protocol: add UpdateBlockEntity_VarInt packet variant
* protocol: start adding ChunkData_AndLight, combining ChunkData + UpdateLight
* protocol: ChunkData_AndLight: add struct BlockEntityAtPackedLocation

* server: handle JoinGame_WorldNames_IsHard_SimDist packet variant
* server: handle combined chunk data and light packet
* server: on_chunk_data_and_light: set all bits in now-removed bitmask

* bit map: add derived std::fmt::Debug implementation
* bit map: allow creating, but not accessing, zero-length bit maps

* world: sanity check chunk bit_size, failing earlier
* world: read biome data bits after palette
* world: support single-valued palettes
* world: handle single-valued biomes
* world: add checks for direct palettes; update comments
* world: parse dimension tags
* world: load dimension type tags: min_y
* world: skip chunk sections underneath y<0
* world: force filling sky on 1.18+ for now, workaround until mask/fill_sky can be calculated correctly wrt min_y

* readme: add 1.18.1 (757)
This commit is contained in:
iceiix 2022-08-06 16:32:40 -07:00 committed by GitHub
parent 2e224a77f9
commit 1f183ed76e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
27 changed files with 471 additions and 44 deletions

View File

@ -24,6 +24,7 @@ Discussion forum: [https://github.com/iceiix/stevenarella/discussions](https://g
| Game version | Protocol version | Supported? |
| ------ | --- | --- |
| 1.18.1 | 757 | ✓ |
| 1.17.1 | 756 | ✓ |
| 1.16.5 | 754 | ✓ |
| 1.16.4 | 754 | ✓ |

View File

@ -39,9 +39,9 @@ use std::io::{Read, Write};
use std::net::TcpStream;
use std::sync::atomic::{AtomicBool, AtomicI32, Ordering};
pub const SUPPORTED_PROTOCOLS: [i32; 25] = [
756, 754, 753, 751, 736, 735, 578, 575, 498, 490, 485, 480, 477, 452, 451, 404, 340, 316, 315,
210, 109, 107, 74, 47, 5,
pub const SUPPORTED_PROTOCOLS: [i32; 26] = [
757, 756, 754, 753, 751, 736, 735, 578, 575, 498, 490, 485, 480, 477, 452, 451, 404, 340, 316,
315, 210, 109, 107, 74, 47, 5,
];
static CURRENT_PROTOCOL_VERSION: AtomicI32 = AtomicI32::new(SUPPORTED_PROTOCOLS[0]);

View File

@ -835,7 +835,12 @@ state_packets!(
}
/// UpdateBlockEntity updates the nbt tag of a block entity in the
/// world.
packet UpdateBlockEntity {
packet UpdateBlockEntity_VarInt {
field location: Position =,
field action: VarInt =,
field nbt: Option<nbt::NamedTag> =,
}
packet UpdateBlockEntity_u8 {
field location: Position =,
field action: u8 =,
field nbt: Option<nbt::NamedTag> =,
@ -1132,6 +1137,21 @@ state_packets!(
}
/// ChunkData sends or updates a single chunk on the client. If New is set
/// then biome data should be sent too.
packet ChunkData_AndLight {
field chunk_x: i32 =,
field chunk_z: i32 =,
field heightmaps: Option<nbt::NamedTag> =,
field data: LenPrefixedBytes<VarInt> =,
field block_entities: LenPrefixed<VarInt, packet::BlockEntityAtPackedLocation> =,
field trust_edges: bool =,
field sky_light_mask: LenPrefixed<VarInt, i64> =,
field block_light_mask: LenPrefixed<VarInt, i64> =,
field empty_sky_light_mask: LenPrefixed<VarInt, i64> =,
field empty_block_light_mask: LenPrefixed<VarInt, i64> =,
field sky_light_arrays: LenPrefixed<VarInt, LenPrefixed<VarInt, u8>> =,
field block_light_arrays: LenPrefixed<VarInt, LenPrefixed<VarInt, u8>> =,
}
packet ChunkData_Biomes3D_Bitmasks {
field chunk_x: i32 =,
field chunk_z: i32 =,
@ -1324,6 +1344,41 @@ state_packets!(
}
/// JoinGame is sent after completing the login process. This
/// sets the initial state for the client.
packet JoinGame_WorldNames_IsHard_SimDist {
/// The entity id the client will be referenced by
field entity_id: i32 =,
/// Whether hardcore mode is enabled
field is_hardcore: bool =,
/// The starting gamemode of the client
field gamemode: u8 =,
/// The previous gamemode of the client
field previous_gamemode: u8 =,
/// Identifiers for all worlds on the server
field world_names: LenPrefixed<VarInt, String> =,
/// Represents a dimension registry
field dimension_codec: Option<nbt::NamedTag> =,
/// The dimension the client is starting in
field dimension: Option<nbt::NamedTag> =,
/// The world being spawned into
field world_name: String =,
/// Truncated SHA-256 hash of world's seed
field hashed_seed: i64 =,
/// The max number of players on the server
field max_players: VarInt =,
/// The render distance (2-32)
field view_distance: VarInt =,
/// The distance the client will process entities
field simulation_distance: VarInt =,
/// Whether the client should reduce the amount of debug
/// information it displays in F3 mode
field reduced_debug_info: bool =,
/// Whether to prompt or immediately respawn
field enable_respawn_screen: bool =,
/// Whether the world is in debug mode
field is_debug: bool =,
/// Whether the world is a superflat world
field is_flat: bool =,
}
packet JoinGame_WorldNames_IsHard {
/// The entity id the client will be referenced by
field entity_id: i32 =,
@ -2019,6 +2074,10 @@ state_packets!(
field object_name: String =,
field value: Option<i32 > = when(|p: &UpdateScore_i32| p.action != 1),
}
/// UpdateSimulationDistance is used to set how far the client will process entities.
packet UpdateSimulationDistance {
field simulation_distance: VarInt =,
}
/// SpawnPosition is sent to change the player's current spawn point. Currently
/// only used by the client for the compass.
packet SpawnPosition_Angle {
@ -2714,6 +2773,34 @@ impl Serializable for CriterionProgress {
}
}
#[derive(Debug, Default, Clone, PartialEq)]
pub struct BlockEntityAtPackedLocation {
/// The packed section coordinates, calculated from ((blockX & 15) << 4) | (blockZ & 15)
pub packed_xz: u8,
/// The height relative to the world
pub y: i16,
pub ty: VarInt,
pub data: Option<nbt::NamedTag>,
}
impl Serializable for BlockEntityAtPackedLocation {
fn read_from<R: io::Read>(buf: &mut R) -> Result<Self, Error> {
Ok(BlockEntityAtPackedLocation {
packed_xz: Serializable::read_from(buf)?,
y: Serializable::read_from(buf)?,
ty: Serializable::read_from(buf)?,
data: Serializable::read_from(buf)?,
})
}
fn write_to<W: io::Write>(&self, buf: &mut W) -> Result<(), Error> {
self.packed_xz.write_to(buf)?;
self.y.write_to(buf)?;
self.ty.write_to(buf)?;
self.data.write_to(buf)
}
}
#[derive(Debug, Default, Clone, PartialEq)]
pub struct EntityEquipment {
pub slot: u8,

View File

@ -16,6 +16,7 @@ mod v1_15;
mod v1_16_1;
mod v1_16_4;
mod v1_17_1;
mod v1_18_1;
mod v1_7_10;
mod v1_8_9;
mod v1_9;
@ -27,6 +28,7 @@ mod v1_9_2;
pub fn protocol_name_to_protocol_version(s: String) -> i32 {
match s.as_ref() {
"" => SUPPORTED_PROTOCOLS[0],
"1.18.1" => 757,
"1.17.1" => 756,
"1.16.5" => 754,
"1.16.4" => 754,
@ -71,6 +73,7 @@ pub fn translate_internal_packet_id_for_version(
to_internal: bool,
) -> i32 {
match version {
757 => v1_18_1::translate_internal_packet_id(state, dir, id, to_internal),
756 => v1_17_1::translate_internal_packet_id(state, dir, id, to_internal),
754 | 753 | 751 => v1_16_4::translate_internal_packet_id(state, dir, id, to_internal),
736 => v1_16_1::translate_internal_packet_id(state, dir, id, to_internal),

View File

@ -46,7 +46,7 @@ protocol_packet_ids!(
0x06 => Animation
0x07 => Statistics
0x08 => BlockBreakAnimation
0x09 => UpdateBlockEntity
0x09 => UpdateBlockEntity_u8
0x0a => BlockAction
0x0b => BlockChange_VarInt
0x0c => BossBar

View File

@ -62,7 +62,7 @@ protocol_packet_ids!(
0x06 => Animation
0x07 => Statistics
0x08 => BlockBreakAnimation
0x09 => UpdateBlockEntity
0x09 => UpdateBlockEntity_u8
0x0a => BlockAction
0x0b => BlockChange_VarInt
0x0c => BossBar

View File

@ -62,7 +62,7 @@ protocol_packet_ids!(
0x06 => Animation
0x07 => Statistics
0x08 => BlockBreakAnimation
0x09 => UpdateBlockEntity
0x09 => UpdateBlockEntity_u8
0x0a => BlockAction
0x0b => BlockChange_VarInt
0x0c => BossBar

View File

@ -49,7 +49,7 @@ protocol_packet_ids!(
0x06 => Animation
0x07 => Statistics
0x08 => BlockBreakAnimation
0x09 => UpdateBlockEntity
0x09 => UpdateBlockEntity_u8
0x0a => BlockAction
0x0b => BlockChange_VarInt
0x0c => BossBar

View File

@ -49,7 +49,7 @@ protocol_packet_ids!(
0x06 => Animation
0x07 => Statistics
0x08 => BlockBreakAnimation
0x09 => UpdateBlockEntity
0x09 => UpdateBlockEntity_u8
0x0a => BlockAction
0x0b => BlockChange_VarInt
0x0c => BossBar

View File

@ -52,7 +52,7 @@ protocol_packet_ids!(
0x06 => Animation
0x07 => Statistics
0x08 => BlockBreakAnimation
0x09 => UpdateBlockEntity
0x09 => UpdateBlockEntity_u8
0x0a => BlockAction
0x0b => BlockChange_VarInt
0x0c => BossBar

View File

@ -62,7 +62,7 @@ protocol_packet_ids!(
0x06 => Animation
0x07 => Statistics
0x08 => BlockBreakAnimation
0x09 => UpdateBlockEntity
0x09 => UpdateBlockEntity_u8
0x0a => BlockAction
0x0b => BlockChange_VarInt
0x0c => BossBar

View File

@ -65,7 +65,7 @@ protocol_packet_ids!(
0x06 => Animation
0x07 => Statistics
0x08 => BlockBreakAnimation
0x09 => UpdateBlockEntity
0x09 => UpdateBlockEntity_u8
0x0a => BlockAction
0x0b => BlockChange_VarInt
0x0c => BossBar

View File

@ -65,7 +65,7 @@ protocol_packet_ids!(
0x06 => Animation
0x07 => Statistics
0x08 => BlockBreakAnimation
0x09 => UpdateBlockEntity
0x09 => UpdateBlockEntity_u8
0x0a => BlockAction
0x0b => BlockChange_VarInt
0x0c => BossBar

View File

@ -65,7 +65,7 @@ protocol_packet_ids!(
0x06 => Animation
0x07 => Statistics
0x08 => BlockBreakAnimation
0x09 => UpdateBlockEntity
0x09 => UpdateBlockEntity_u8
0x0a => BlockAction
0x0b => BlockChange_VarInt
0x0c => BossBar

View File

@ -65,7 +65,7 @@ protocol_packet_ids!(
0x06 => Animation
0x07 => Statistics
0x08 => BlockBreakAnimation
0x09 => UpdateBlockEntity
0x09 => UpdateBlockEntity_u8
0x0a => BlockAction
0x0b => BlockChange_VarInt
0x0c => BossBar

View File

@ -65,7 +65,7 @@ protocol_packet_ids!(
0x06 => Animation
0x07 => Statistics
0x08 => BlockBreakAnimation
0x09 => UpdateBlockEntity
0x09 => UpdateBlockEntity_u8
0x0a => BlockAction
0x0b => BlockChange_VarInt
0x0c => BossBar

View File

@ -66,7 +66,7 @@ protocol_packet_ids!(
0x07 => Statistics
0x08 => AcknowledgePlayerDigging
0x09 => BlockBreakAnimation
0x0a => UpdateBlockEntity
0x0a => UpdateBlockEntity_u8
0x0b => BlockAction
0x0c => BlockChange_VarInt
0x0d => BossBar

View File

@ -66,7 +66,7 @@ protocol_packet_ids!(
0x06 => Statistics
0x07 => AcknowledgePlayerDigging
0x08 => BlockBreakAnimation
0x09 => UpdateBlockEntity
0x09 => UpdateBlockEntity_u8
0x0a => BlockAction
0x0b => BlockChange_VarInt
0x0c => BossBar

View File

@ -67,7 +67,7 @@ protocol_packet_ids!(
0x06 => Statistics
0x07 => AcknowledgePlayerDigging
0x08 => BlockBreakAnimation
0x09 => UpdateBlockEntity
0x09 => UpdateBlockEntity_u8
0x0a => BlockAction
0x0b => BlockChange_VarInt
0x0c => BossBar

View File

@ -68,7 +68,7 @@ protocol_packet_ids!(
0x07 => Statistics
0x08 => AcknowledgePlayerDigging
0x09 => BlockBreakAnimation
0x0a => UpdateBlockEntity
0x0a => UpdateBlockEntity_u8
0x0b => BlockAction
0x0c => BlockChange_VarInt
0x0d => BossBar

View File

@ -0,0 +1,191 @@
protocol_packet_ids!(
handshake Handshaking {
serverbound Serverbound {
0x00 => Handshake
}
clientbound Clientbound {
}
}
play Play {
serverbound Serverbound {
0x00 => TeleportConfirm
0x01 => QueryBlockNBT
0x02 => SetDifficulty
0x03 => ChatMessage
0x04 => ClientStatus
0x05 => ClientSettings_Filtering
0x06 => TabComplete
0x07 => ClickWindowButton
0x08 => ClickWindow_State
0x09 => CloseWindow
0x0a => PluginMessageServerbound
0x0b => EditBook_Pages
0x0c => QueryEntityNBT
0x0d => UseEntity_Sneakflag
0x0e => GenerateStructure
0x0f => KeepAliveServerbound_i64
0x10 => LockDifficulty
0x11 => PlayerPosition
0x12 => PlayerPositionLook
0x13 => PlayerLook
0x14 => Player
0x15 => VehicleMove
0x16 => SteerBoat
0x17 => PickItem
0x18 => CraftRecipeRequest
0x19 => ClientAbilities_u8
0x1a => PlayerDigging
0x1b => PlayerAction
0x1c => SteerVehicle
0x1d => WindowPong
0x1e => SetDisplayedRecipe
0x1f => SetRecipeBookState
0x20 => NameItem
0x21 => ResourcePackStatus
0x22 => AdvancementTab
0x23 => SelectTrade
0x24 => SetBeaconEffect
0x25 => HeldItemChange
0x26 => UpdateCommandBlock
0x27 => UpdateCommandBlockMinecart
0x28 => CreativeInventoryAction
0x29 => UpdateJigsawBlock_Joint
0x2a => UpdateStructureBlock
0x2b => SetSign
0x2c => ArmSwing
0x2d => SpectateTeleport
0x2e => PlayerBlockPlacement_insideblock
0x2f => UseItem
}
clientbound Clientbound {
0x00 => SpawnObject_VarInt
0x01 => SpawnExperienceOrb
0x02 => SpawnMob_NoMeta
0x03 => SpawnPainting_VarInt
0x04 => SpawnPlayer_f64_NoMeta
0x05 => SculkVibrationSignal
0x06 => Animation
0x07 => Statistics
0x08 => AcknowledgePlayerDigging
0x09 => BlockBreakAnimation
0x0a => UpdateBlockEntity_VarInt
0x0b => BlockAction
0x0c => BlockChange_VarInt
0x0d => BossBar
0x0e => ServerDifficulty_Locked
0x0f => ServerMessage_Sender
0x10 => ClearTitles
0x11 => TabCompleteReply
0x12 => DeclareCommands
0x13 => WindowClose
0x14 => WindowItems_StateCarry
0x15 => WindowProperty
0x16 => WindowSetSlot_State
0x17 => SetCooldown
0x18 => PluginMessageClientbound
0x19 => NamedSoundEffect
0x1a => Disconnect
0x1b => EntityAction
0x1c => Explosion_VarInt
0x1d => ChunkUnload
0x1e => ChangeGameState
0x1f => WindowOpenHorse
0x20 => WorldBorderInit
0x21 => KeepAliveClientbound_i64
0x22 => ChunkData_AndLight
0x23 => Effect
0x24 => Particle_f64
0x25 => UpdateLight_Arrays
0x26 => JoinGame_WorldNames_IsHard_SimDist
0x27 => Maps
0x28 => TradeList_WithRestock
0x29 => EntityMove_i16
0x2a => EntityLookAndMove_i16
0x2b => EntityLook_VarInt
0x2c => VehicleTeleport
0x2d => OpenBook
0x2e => WindowOpen_VarInt
0x2f => SignEditorOpen
0x30 => WindowPing
0x31 => CraftRecipeResponse
0x32 => PlayerAbilities
0x33 => CombatEventEnd
0x34 => CombatEventEnter
0x35 => CombatEventDeath
0x36 => PlayerInfo
0x37 => FacePlayer
0x38 => TeleportPlayer_WithDismount
0x39 => UnlockRecipes_WithBlastSmoker
0x3a => EntityDestroy
0x3b => EntityRemoveEffect
0x3c => ResourcePackSend_Prompt
0x3d => Respawn_NBT
0x3e => EntityHeadLook
0x3f => MultiBlockChange_Packed
0x40 => SelectAdvancementTab
0x41 => ActionBar
0x42 => WorldBorderCenter
0x43 => WorldBorderLerpSize
0x44 => WorldBorderSize
0x45 => WorldBorderWarningDelay
0x46 => WorldBorderWarningReach
0x47 => Camera
0x48 => SetCurrentHotbarSlot
0x49 => UpdateViewPosition
0x4a => UpdateViewDistance
0x4b => SpawnPosition_Angle
0x4c => ScoreboardDisplay
0x4d => EntityMetadata
0x4e => EntityAttach
0x4f => EntityVelocity
0x50 => EntityEquipment_Array
0x51 => SetExperience
0x52 => UpdateHealth
0x53 => ScoreboardObjective
0x54 => SetPassengers
0x55 => Teams_VarInt
0x56 => UpdateScore
0x57 => UpdateSimulationDistance
0x58 => TitleSubtitle
0x59 => TimeUpdate
0x5a => Title
0x5b => TitleTimes
0x5c => EntitySoundEffect
0x5d => SoundEffect
0x5e => StopSound
0x5f => PlayerListHeaderFooter
0x60 => NBTQueryResponse
0x61 => CollectItem
0x62 => EntityTeleport_f64
0x63 => Advancements
0x64 => EntityProperties_VarIntVarInt
0x65 => EntityEffect
0x66 => DeclareRecipes
0x67 => Tags_Nested
}
}
login Login {
serverbound Serverbound {
0x00 => LoginStart
0x01 => EncryptionResponse
0x02 => LoginPluginResponse
}
clientbound Clientbound {
0x00 => LoginDisconnect
0x01 => EncryptionRequest
0x02 => LoginSuccess_UUID
0x03 => SetInitialCompression
0x04 => LoginPluginRequest
}
}
status Status {
serverbound Serverbound {
0x00 => StatusRequest
0x01 => StatusPing
}
clientbound Clientbound {
0x00 => StatusResponse
0x01 => StatusPong
}
}
);

View File

@ -89,7 +89,7 @@ protocol_packet_ids!(
0x32 => ConfirmTransaction
0x33 => UpdateSign
0x34 => Maps_NoTracking
0x35 => UpdateBlockEntity
0x35 => UpdateBlockEntity_u8
0x36 => SignEditorOpen
0x37 => Statistics
0x38 => PlayerInfo

View File

@ -49,7 +49,7 @@ protocol_packet_ids!(
0x06 => Animation
0x07 => Statistics
0x08 => BlockBreakAnimation
0x09 => UpdateBlockEntity
0x09 => UpdateBlockEntity_u8
0x0a => BlockAction
0x0b => BlockChange_VarInt
0x0c => BossBar

View File

@ -49,7 +49,7 @@ protocol_packet_ids!(
0x06 => Animation
0x07 => Statistics
0x08 => BlockBreakAnimation
0x09 => UpdateBlockEntity
0x09 => UpdateBlockEntity_u8
0x0a => BlockAction
0x0b => BlockChange_VarInt
0x0c => BossBar

View File

@ -12,6 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
#[derive(Debug)]
pub struct Map {
bits: Vec<u64>,
pub bit_size: usize,
@ -63,11 +64,20 @@ impl Map {
}
pub fn from_raw(bits: Vec<u64>, size: usize, padded: bool) -> Map {
Map {
length: (bits.len() * 64 + (size - 1)) / size,
bit_size: size,
bits,
padded,
if size == 0 {
Map {
length: 0,
bit_size: size,
bits,
padded,
}
} else {
Map {
length: (bits.len() * 64 + (size - 1)) / size,
bit_size: size,
bits,
padded,
}
}
}
@ -80,6 +90,7 @@ impl Map {
}
fn get_bit_offset(&self, i: usize) -> usize {
assert!(self.length != 0);
let padding = if self.padded {
i / (64 / self.bit_size) * (64 % self.bit_size)
} else {

View File

@ -581,6 +581,7 @@ impl Server {
self pck {
PluginMessageClientbound_i16 => on_plugin_message_clientbound_i16,
PluginMessageClientbound => on_plugin_message_clientbound_1,
JoinGame_WorldNames_IsHard_SimDist => on_game_join_worldnames_ishard_simdist,
JoinGame_WorldNames_IsHard => on_game_join_worldnames_ishard,
JoinGame_WorldNames => on_game_join_worldnames,
JoinGame_HashedSeed_Respawn => on_game_join_hashedseed_respawn,
@ -595,6 +596,7 @@ impl Server {
KeepAliveClientbound_i64 => on_keep_alive_i64,
KeepAliveClientbound_VarInt => on_keep_alive_varint,
KeepAliveClientbound_i32 => on_keep_alive_i32,
ChunkData_AndLight => on_chunk_data_and_light,
ChunkData_Biomes3D_Bitmasks => on_chunk_data_biomes3d_bitmasks,
ChunkData_Biomes3D_VarInt => on_chunk_data_biomes3d_varint,
ChunkData_Biomes3D_bool => on_chunk_data_biomes3d_bool,
@ -618,7 +620,8 @@ impl Server {
TeleportPlayer_OnGround => on_teleport_player_onground,
TimeUpdate => on_time_update,
ChangeGameState => on_game_state_change,
UpdateBlockEntity => on_block_entity_update,
UpdateBlockEntity_VarInt => on_block_entity_update_varint,
UpdateBlockEntity_u8 => on_block_entity_update_u8,
UpdateBlockEntity_Data => on_block_entity_update_data,
UpdateSign => on_sign_update,
UpdateSign_u16 => on_sign_update_u16,
@ -1055,10 +1058,19 @@ impl Server {
.write_plugin_message(channel, data); // TODO handle errors
}
fn on_game_join_worldnames_ishard_simdist(
&mut self,
join: packet::play::clientbound::JoinGame_WorldNames_IsHard_SimDist,
) {
self.world.load_dimension_type(join.dimension);
self.on_game_join(join.gamemode, join.entity_id)
}
fn on_game_join_worldnames_ishard(
&mut self,
join: packet::play::clientbound::JoinGame_WorldNames_IsHard,
) {
self.world.load_dimension_type(join.dimension);
self.on_game_join(join.gamemode, join.entity_id)
}
@ -1677,9 +1689,27 @@ impl Server {
}
}
fn on_block_entity_update(
fn on_block_entity_update_varint(
&mut self,
block_update: packet::play::clientbound::UpdateBlockEntity,
block_update: packet::play::clientbound::UpdateBlockEntity_VarInt,
) {
self.on_block_entity_update_u8(packet::play::clientbound::UpdateBlockEntity_u8 {
location: block_update.location,
action: block_update.action.0 as u8,
nbt: block_update.nbt,
});
}
fn on_block_entity_update_data(
&mut self,
_block_update: packet::play::clientbound::UpdateBlockEntity_Data,
) {
// TODO: handle UpdateBlockEntity_Data for 1.7, decompress gzipped_nbt
}
fn on_block_entity_update_u8(
&mut self,
block_update: packet::play::clientbound::UpdateBlockEntity_u8,
) {
match block_update.nbt {
None => {
@ -1736,13 +1766,6 @@ impl Server {
}
}
fn on_block_entity_update_data(
&mut self,
_block_update: packet::play::clientbound::UpdateBlockEntity_Data,
) {
// TODO: handle UpdateBlockEntity_Data for 1.7, decompress gzipped_nbt
}
fn on_sign_update(&mut self, mut update_sign: packet::play::clientbound::UpdateSign) {
format::convert_legacy(&mut update_sign.line1);
format::convert_legacy(&mut update_sign.line2);
@ -1931,7 +1954,7 @@ impl Server {
// Not something we care about, so break the loop
_ => continue,
}
self.on_block_entity_update(packet::play::clientbound::UpdateBlockEntity {
self.on_block_entity_update_u8(packet::play::clientbound::UpdateBlockEntity_u8 {
location: Position::new(x, y, z),
action,
nbt: Some(block_entity.clone()),
@ -1945,6 +1968,24 @@ impl Server {
}
}
fn on_chunk_data_and_light(
&mut self,
chunk_data: packet::play::clientbound::ChunkData_AndLight,
) {
self.world
.load_chunk117(
chunk_data.chunk_x,
chunk_data.chunk_z,
true,
0xffff, // world height/16 (256/16 = 16) bits
16, // TODO: get all bitmasks
chunk_data.data.data,
)
.unwrap();
//self.load_block_entities(chunk_data.block_entities.data); // TODO: load entities
// TODO: update light
}
fn on_chunk_data_biomes3d_bitmasks(
&mut self,
chunk_data: packet::play::clientbound::ChunkData_Biomes3D_Bitmasks,

View File

@ -25,6 +25,7 @@ use crate::types::hash::FNVHash;
use crate::types::{bit, nibble};
use cgmath::prelude::*;
use flate2::read::ZlibDecoder;
use log::info;
use std::cmp::Ordering;
use std::collections::HashMap;
use std::collections::VecDeque;
@ -38,6 +39,7 @@ mod storage;
#[derive(Default)]
pub struct World {
chunks: HashMap<CPos, Chunk, BuildHasherDefault<FNVHash>>,
min_y: i32,
render_list: Vec<(i32, i32, i32)>,
@ -1005,6 +1007,17 @@ impl World {
self.load_chunk19_to_117(false, x, z, new, mask, num_sections, data)
}
pub fn load_dimension_type(&mut self, dimension_tags: Option<crate::nbt::NamedTag>) {
if let Some(crate::nbt::NamedTag(_, crate::nbt::Tag::Compound(tags))) = dimension_tags {
info!("Dimension type: {:?}", tags);
if let Some(crate::nbt::Tag::Int(min_y)) = tags.get("min_y") {
self.min_y = *min_y;
}
// TODO: More tags https://wiki.vg/Protocol#Login_.28play.29
}
}
#[allow(clippy::or_fun_call)]
fn load_chunk19_to_117(
&mut self,
@ -1031,10 +1044,48 @@ impl World {
}
let chunk = self.chunks.get_mut(&cpos).unwrap();
for i in 0..num_sections {
for i1 in 0..num_sections {
let i: i32 = (i1 as i32) + (self.min_y >> 4);
if i < 0 {
// TODO: support y<0 in the world (needs shifting in all section access)
let block_count = data.read_u16::<byteorder::LittleEndian>()?;
let bit_size = data.read_u8()?;
let single_value = Some(VarInt::read_from(&mut data)?.0);
if bit_size != 0 || single_value != Some(0) || block_count != 0 {
panic!("TODO: support chunk data y<0 non-air (bit_size {}, single_value {:?}, block_count {})", bit_size, single_value, block_count);
}
let _bits = LenPrefixed::<VarInt, u64>::read_from(&mut data)?.data;
// biome
let _bit_size = data.read_u8()?;
if _bit_size == 0 {
let _single_value = VarInt::read_from(&mut data)?.0;
} else {
if bit_size >= 4 {
panic!(
"TODO: handle direct palettes, bit_size {} >= 4 for biomes",
bit_size
);
}
let count = VarInt::read_from(&mut data)?.0;
for _i in 0..count {
let _id = VarInt::read_from(&mut data)?.0;
}
}
let _bits = LenPrefixed::<VarInt, u64>::read_from(&mut data)?.data;
continue;
}
let i = i as usize;
if chunk.sections[i].is_none() {
let mut fill_sky = chunk.sections.iter().skip(i).all(|v| v.is_none());
fill_sky &= (mask & !((1 << i) | ((1 << i) - 1))) == 0;
if self.protocol_version >= 757 {
// TODO: fix conditionalizing fill sky on 1.18+
fill_sky = true;
}
if !fill_sky || mask & (1 << i) != 0 {
chunk.sections[i] = Some(Section::new(i as u8, fill_sky));
}
@ -1047,16 +1098,30 @@ impl World {
if self.protocol_version >= 451 {
let _block_count = data.read_u16::<byteorder::LittleEndian>()?;
// TODO: use block_count
// TODO: use block_count, "The client will keep count of the blocks as they are
// broken and placed, and, if the block count reaches 0, the whole chunk
// section is not rendered, even if it still has blocks." per https://wiki.vg/Chunk_Format#Data_structure
}
let mut bit_size = data.read_u8()?;
let mut mappings: HashMap<usize, block::Block, BuildHasherDefault<FNVHash>> =
HashMap::with_hasher(BuildHasherDefault::default());
let mut single_value: Option<usize> = None;
if bit_size == 0 {
bit_size = 13;
if self.protocol_version >= 757 {
// Single-valued palette
single_value = Some(VarInt::read_from(&mut data)?.0.try_into().unwrap());
} else {
bit_size = 13;
}
} else {
let count = VarInt::read_from(&mut data)?.0;
if bit_size >= 9 {
panic!(
"TODO: handle direct palettes, bit_size {} >= 9 for block states",
bit_size
);
}
for i in 0..count {
let id = VarInt::read_from(&mut data)?.0;
let bl = self
@ -1065,13 +1130,17 @@ impl World {
mappings.insert(i as usize, bl);
}
}
if bit_size > 16 {
// https://wiki.vg/Chunk_Format#Data_structure "This increase can go up to 16 bits per block"...
panic!("load_chunk19_to_117: bit_size={:?} > 16", bit_size);
}
let bits = LenPrefixed::<VarInt, u64>::read_from(&mut data)?.data;
let padded = self.protocol_version >= 736;
let m = bit::Map::from_raw(bits, bit_size as usize, padded);
for bi in 0..4096 {
let id = m.get(bi);
let id = single_value.unwrap_or_else(|| m.get(bi));
section.blocks.set(
bi,
mappings
@ -1101,7 +1170,31 @@ impl World {
}
}
if self.protocol_version >= 451 {
if self.protocol_version >= 757 {
// Biomes palette TODO: refactor with block states, "palette container"
let _bit_size = data.read_u8()?;
if _bit_size == 0 {
// Single-valued palette
let _single_value = VarInt::read_from(&mut data)?.0;
} else {
if bit_size >= 4 {
panic!(
"TODO: handle direct palettes, bit_size {} >= 4 for biomes",
bit_size
);
}
let count = VarInt::read_from(&mut data)?.0;
for _i in 0..count {
let _id = VarInt::read_from(&mut data)?.0;
//let bl = self
// .id_map
// .by_vanilla_id(id as usize, &self.modded_block_ids);
//mappings.insert(i as usize, bl);
}
}
let _bits = LenPrefixed::<VarInt, u64>::read_from(&mut data)?.data;
} else if self.protocol_version >= 451 {
// Skylight in update skylight packet for 1.14+
} else {
data.read_exact(&mut section.block_light.data)?;