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:
parent
2e224a77f9
commit
1f183ed76e
|
@ -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 | ✓ |
|
||||
|
|
|
@ -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]);
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
||||
);
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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,
|
||||
|
|
103
src/world/mod.rs
103
src/world/mod.rs
|
@ -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)?;
|
||||
|
|
Loading…
Reference in New Issue