1.16.4 (754) / 1.16.3 (753) / 1.16.2 (751) protocol (#390)
Adds support for 1.16.4 (754) / 1.16.3 (753) / 1.16.2 (751) protocols * Update packet IDs and readme * Add and handle ChunkData_Biomes3D_VarInt variant * Support world chunk data padded bit map array * Add and handle JoinGame_WorldNames_IsHard variant * Add and handle MultiBlockChange_Packed variant * Add UnlockRecipes_WithBlastSmoker variant * Add SetDisplayedRecipe and SetRecipeBookState packets
This commit is contained in:
parent
f4414e7814
commit
4a757656ab
|
@ -23,6 +23,9 @@ Join with your favorite IRC client.
|
||||||
|
|
||||||
| Game version | Protocol version | Supported? |
|
| Game version | Protocol version | Supported? |
|
||||||
| ------ | --- | --- |
|
| ------ | --- | --- |
|
||||||
|
| 1.16.4 | 754 | ✓ |
|
||||||
|
| 1.16.3 | 753 | ✓ |
|
||||||
|
| 1.16.2 | 751 | ✓ |
|
||||||
| 1.16.1 | 736 | ✓ |
|
| 1.16.1 | 736 | ✓ |
|
||||||
| 1.16 | 735 | ✓ |
|
| 1.16 | 735 | ✓ |
|
||||||
| 1.15.2 | 578 | ✓ |
|
| 1.15.2 | 578 | ✓ |
|
||||||
|
|
|
@ -40,9 +40,9 @@ use std::net::TcpStream;
|
||||||
use std::sync::atomic::{AtomicBool, AtomicI32, Ordering};
|
use std::sync::atomic::{AtomicBool, AtomicI32, Ordering};
|
||||||
use std::time::{Duration, Instant};
|
use std::time::{Duration, Instant};
|
||||||
|
|
||||||
pub const SUPPORTED_PROTOCOLS: [i32; 21] = [
|
pub const SUPPORTED_PROTOCOLS: [i32; 24] = [
|
||||||
736, 735, 578, 575, 498, 490, 485, 480, 477, 452, 451, 404, 340, 316, 315, 210, 109, 107, 74,
|
754, 753, 751, 736, 735, 578, 575, 498, 490, 485, 480, 477, 452, 451, 404, 340, 316, 315, 210,
|
||||||
47, 5,
|
109, 107, 74, 47, 5,
|
||||||
];
|
];
|
||||||
|
|
||||||
static CURRENT_PROTOCOL_VERSION: AtomicI32 = AtomicI32::new(SUPPORTED_PROTOCOLS[0]);
|
static CURRENT_PROTOCOL_VERSION: AtomicI32 = AtomicI32::new(SUPPORTED_PROTOCOLS[0]);
|
||||||
|
@ -1156,6 +1156,8 @@ impl Conn {
|
||||||
let pos = buf.position() as usize;
|
let pos = buf.position() as usize;
|
||||||
let ibuf = buf.into_inner();
|
let ibuf = buf.into_inner();
|
||||||
if ibuf.len() != pos {
|
if ibuf.len() != pos {
|
||||||
|
debug!("pos = {:?}", pos);
|
||||||
|
debug!("ibuf = {:?}", ibuf);
|
||||||
return Result::Err(Error::Err(format!(
|
return Result::Err(Error::Err(format!(
|
||||||
"Failed to read all of packet 0x{:X}, \
|
"Failed to read all of packet 0x{:X}, \
|
||||||
had {} bytes left",
|
had {} bytes left",
|
||||||
|
|
|
@ -353,6 +353,16 @@ state_packets!(
|
||||||
field crafting_book_open: bool = when(|p: &CraftingBookData| p.action.0 == 1),
|
field crafting_book_open: bool = when(|p: &CraftingBookData| p.action.0 == 1),
|
||||||
field crafting_filter: bool = when(|p: &CraftingBookData| p.action.0 == 1),
|
field crafting_filter: bool = when(|p: &CraftingBookData| p.action.0 == 1),
|
||||||
}
|
}
|
||||||
|
/// SetDisplayedRecipe replaces CraftingBookData, type 0.
|
||||||
|
packet SetDisplayedRecipe {
|
||||||
|
field recipe_id: String =,
|
||||||
|
}
|
||||||
|
/// SetRecipeBookState replaces CraftingBookData, type 1.
|
||||||
|
packet SetRecipeBookState {
|
||||||
|
field book_id: VarInt =, // TODO: enum, 0: crafting, 1: furnace, 2: blast furnace, 3: smoker
|
||||||
|
field book_open: bool =,
|
||||||
|
field filter_active: bool =,
|
||||||
|
}
|
||||||
packet NameItem {
|
packet NameItem {
|
||||||
field item_name: String =,
|
field item_name: String =,
|
||||||
}
|
}
|
||||||
|
@ -881,6 +891,11 @@ state_packets!(
|
||||||
field message: format::Component =,
|
field message: format::Component =,
|
||||||
}
|
}
|
||||||
/// MultiBlockChange is used to update a batch of blocks in a single packet.
|
/// MultiBlockChange is used to update a batch of blocks in a single packet.
|
||||||
|
packet MultiBlockChange_Packed {
|
||||||
|
field chunk_section_pos: u64 =,
|
||||||
|
field no_trust_edges: bool =,
|
||||||
|
field records: LenPrefixed<VarInt, VarLong> =,
|
||||||
|
}
|
||||||
packet MultiBlockChange_VarInt {
|
packet MultiBlockChange_VarInt {
|
||||||
field chunk_x: i32 =,
|
field chunk_x: i32 =,
|
||||||
field chunk_z: i32 =,
|
field chunk_z: i32 =,
|
||||||
|
@ -1047,6 +1062,16 @@ state_packets!(
|
||||||
}
|
}
|
||||||
/// ChunkData sends or updates a single chunk on the client. If New is set
|
/// ChunkData sends or updates a single chunk on the client. If New is set
|
||||||
/// then biome data should be sent too.
|
/// then biome data should be sent too.
|
||||||
|
packet ChunkData_Biomes3D_VarInt {
|
||||||
|
field chunk_x: i32 =,
|
||||||
|
field chunk_z: i32 =,
|
||||||
|
field new: bool =,
|
||||||
|
field bitmask: VarInt =,
|
||||||
|
field heightmaps: Option<nbt::NamedTag> =,
|
||||||
|
field biomes: LenPrefixed<VarInt, VarInt> = when(|p: &ChunkData_Biomes3D_VarInt| p.new),
|
||||||
|
field data: LenPrefixedBytes<VarInt> =,
|
||||||
|
field block_entities: LenPrefixed<VarInt, Option<nbt::NamedTag>> =,
|
||||||
|
}
|
||||||
packet ChunkData_Biomes3D_bool {
|
packet ChunkData_Biomes3D_bool {
|
||||||
field chunk_x: i32 =,
|
field chunk_x: i32 =,
|
||||||
field chunk_z: i32 =,
|
field chunk_z: i32 =,
|
||||||
|
@ -1200,6 +1225,39 @@ state_packets!(
|
||||||
}
|
}
|
||||||
/// JoinGame is sent after completing the login process. This
|
/// JoinGame is sent after completing the login process. This
|
||||||
/// sets the initial state for the client.
|
/// sets the initial state for the client.
|
||||||
|
packet JoinGame_WorldNames_IsHard {
|
||||||
|
/// 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 =,
|
||||||
|
/// 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 {
|
packet JoinGame_WorldNames {
|
||||||
/// The entity id the client will be referenced by
|
/// The entity id the client will be referenced by
|
||||||
field entity_id: i32 =,
|
field entity_id: i32 =,
|
||||||
|
@ -1231,7 +1289,6 @@ state_packets!(
|
||||||
/// Whether the world is a superflat world
|
/// Whether the world is a superflat world
|
||||||
field is_flat: bool =,
|
field is_flat: bool =,
|
||||||
}
|
}
|
||||||
|
|
||||||
packet JoinGame_HashedSeed_Respawn {
|
packet JoinGame_HashedSeed_Respawn {
|
||||||
/// The entity id the client will be referenced by
|
/// The entity id the client will be referenced by
|
||||||
field entity_id: i32 =,
|
field entity_id: i32 =,
|
||||||
|
@ -1527,6 +1584,19 @@ state_packets!(
|
||||||
field recipe_ids: LenPrefixed<VarInt, String> =,
|
field recipe_ids: LenPrefixed<VarInt, String> =,
|
||||||
field recipe_ids2: LenPrefixed<VarInt, String> = when(|p: &UnlockRecipes_WithSmelting| p.action.0 == 0),
|
field recipe_ids2: LenPrefixed<VarInt, String> = when(|p: &UnlockRecipes_WithSmelting| p.action.0 == 0),
|
||||||
}
|
}
|
||||||
|
packet UnlockRecipes_WithBlastSmoker {
|
||||||
|
field action: VarInt =,
|
||||||
|
field crafting_book_open: bool =,
|
||||||
|
field filtering_craftable: bool =,
|
||||||
|
field smelting_book_open: bool =,
|
||||||
|
field filtering_smeltable: bool =,
|
||||||
|
field blast_furnace_open: bool =,
|
||||||
|
field filtering_blast_furnace: bool =,
|
||||||
|
field smoker_open: bool =,
|
||||||
|
field filtering_smoker: bool =,
|
||||||
|
field recipe_ids: LenPrefixed<VarInt, String> =,
|
||||||
|
field recipe_ids2: LenPrefixed<VarInt, String> = when(|p: &UnlockRecipes_WithBlastSmoker| p.action.0 == 0),
|
||||||
|
}
|
||||||
/// EntityDestroy destroys the entities with the ids in the provided slice.
|
/// EntityDestroy destroys the entities with the ids in the provided slice.
|
||||||
packet EntityDestroy {
|
packet EntityDestroy {
|
||||||
field entity_ids: LenPrefixed<VarInt, VarInt> =,
|
field entity_ids: LenPrefixed<VarInt, VarInt> =,
|
||||||
|
|
|
@ -14,6 +14,7 @@ mod v1_14_3;
|
||||||
mod v1_14_4;
|
mod v1_14_4;
|
||||||
mod v1_15;
|
mod v1_15;
|
||||||
mod v1_16_1;
|
mod v1_16_1;
|
||||||
|
mod v1_16_4;
|
||||||
mod v1_7_10;
|
mod v1_7_10;
|
||||||
mod v1_8_9;
|
mod v1_8_9;
|
||||||
mod v1_9;
|
mod v1_9;
|
||||||
|
@ -25,6 +26,9 @@ mod v1_9_2;
|
||||||
pub fn protocol_name_to_protocol_version(s: String) -> i32 {
|
pub fn protocol_name_to_protocol_version(s: String) -> i32 {
|
||||||
match s.as_ref() {
|
match s.as_ref() {
|
||||||
"" => SUPPORTED_PROTOCOLS[0],
|
"" => SUPPORTED_PROTOCOLS[0],
|
||||||
|
"1.16.4" => 754,
|
||||||
|
"1.16.3" => 753,
|
||||||
|
"1.16.2" => 751,
|
||||||
"1.16.1" => 736,
|
"1.16.1" => 736,
|
||||||
"1.16" => 735,
|
"1.16" => 735,
|
||||||
"1.15.2" => 578,
|
"1.15.2" => 578,
|
||||||
|
@ -64,6 +68,7 @@ pub fn translate_internal_packet_id_for_version(
|
||||||
to_internal: bool,
|
to_internal: bool,
|
||||||
) -> i32 {
|
) -> i32 {
|
||||||
match version {
|
match version {
|
||||||
|
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),
|
736 => v1_16_1::translate_internal_packet_id(state, dir, id, to_internal),
|
||||||
735 => v1_16_1::translate_internal_packet_id(state, dir, id, to_internal),
|
735 => v1_16_1::translate_internal_packet_id(state, dir, id, to_internal),
|
||||||
578 => v1_15::translate_internal_packet_id(state, dir, id, to_internal),
|
578 => v1_15::translate_internal_packet_id(state, dir, id, to_internal),
|
||||||
|
|
|
@ -0,0 +1,179 @@
|
||||||
|
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
|
||||||
|
0x06 => TabComplete
|
||||||
|
0x07 => ConfirmTransactionServerbound
|
||||||
|
0x08 => ClickWindowButton
|
||||||
|
0x09 => ClickWindow
|
||||||
|
0x0a => CloseWindow
|
||||||
|
0x0b => PluginMessageServerbound
|
||||||
|
0x0c => EditBook
|
||||||
|
0x0d => QueryEntityNBT
|
||||||
|
0x0e => UseEntity_Sneakflag
|
||||||
|
0x0f => GenerateStructure
|
||||||
|
0x10 => KeepAliveServerbound_i64
|
||||||
|
0x11 => LockDifficulty
|
||||||
|
0x12 => PlayerPosition
|
||||||
|
0x13 => PlayerPositionLook
|
||||||
|
0x14 => PlayerLook
|
||||||
|
0x15 => Player
|
||||||
|
0x16 => VehicleMove
|
||||||
|
0x17 => SteerBoat
|
||||||
|
0x18 => PickItem
|
||||||
|
0x19 => CraftRecipeRequest
|
||||||
|
0x1a => ClientAbilities_u8
|
||||||
|
0x1b => PlayerDigging
|
||||||
|
0x1c => PlayerAction
|
||||||
|
0x1d => SteerVehicle
|
||||||
|
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 => Animation
|
||||||
|
0x06 => Statistics
|
||||||
|
0x07 => AcknowledgePlayerDigging
|
||||||
|
0x08 => BlockBreakAnimation
|
||||||
|
0x09 => UpdateBlockEntity
|
||||||
|
0x0a => BlockAction
|
||||||
|
0x0b => BlockChange_VarInt
|
||||||
|
0x0c => BossBar
|
||||||
|
0x0d => ServerDifficulty_Locked
|
||||||
|
0x0e => ServerMessage_Sender
|
||||||
|
0x0f => TabCompleteReply
|
||||||
|
0x10 => DeclareCommands
|
||||||
|
0x11 => ConfirmTransaction
|
||||||
|
0x12 => WindowClose
|
||||||
|
0x13 => WindowItems
|
||||||
|
0x14 => WindowProperty
|
||||||
|
0x15 => WindowSetSlot
|
||||||
|
0x16 => SetCooldown
|
||||||
|
0x17 => PluginMessageClientbound
|
||||||
|
0x18 => NamedSoundEffect
|
||||||
|
0x19 => Disconnect
|
||||||
|
0x1a => EntityAction
|
||||||
|
0x1b => Explosion
|
||||||
|
0x1c => ChunkUnload
|
||||||
|
0x1d => ChangeGameState
|
||||||
|
0x1e => WindowOpenHorse
|
||||||
|
0x1f => KeepAliveClientbound_i64
|
||||||
|
0x20 => ChunkData_Biomes3D_VarInt
|
||||||
|
0x21 => Effect
|
||||||
|
0x22 => Particle_f64
|
||||||
|
0x23 => UpdateLight_WithTrust
|
||||||
|
0x24 => JoinGame_WorldNames_IsHard
|
||||||
|
0x25 => Maps
|
||||||
|
0x26 => TradeList_WithRestock
|
||||||
|
0x27 => EntityMove_i16
|
||||||
|
0x28 => EntityLookAndMove_i16
|
||||||
|
0x29 => EntityLook_VarInt
|
||||||
|
0x2a => Entity
|
||||||
|
0x2b => VehicleTeleport
|
||||||
|
0x2c => OpenBook
|
||||||
|
0x2d => WindowOpen_VarInt
|
||||||
|
0x2e => SignEditorOpen
|
||||||
|
0x2f => CraftRecipeResponse
|
||||||
|
0x30 => PlayerAbilities
|
||||||
|
0x31 => CombatEvent
|
||||||
|
0x32 => PlayerInfo
|
||||||
|
0x33 => FacePlayer
|
||||||
|
0x34 => TeleportPlayer_WithConfirm
|
||||||
|
0x35 => UnlockRecipes_WithBlastSmoker
|
||||||
|
0x36 => EntityDestroy
|
||||||
|
0x37 => EntityRemoveEffect
|
||||||
|
0x38 => ResourcePackSend
|
||||||
|
0x39 => Respawn_WorldName
|
||||||
|
0x3a => EntityHeadLook
|
||||||
|
0x3b => MultiBlockChange_Packed
|
||||||
|
0x3c => SelectAdvancementTab
|
||||||
|
0x3d => WorldBorder
|
||||||
|
0x3e => Camera
|
||||||
|
0x3f => SetCurrentHotbarSlot
|
||||||
|
0x40 => UpdateViewPosition
|
||||||
|
0x41 => UpdateViewDistance
|
||||||
|
0x42 => SpawnPosition
|
||||||
|
0x43 => ScoreboardDisplay
|
||||||
|
0x44 => EntityMetadata
|
||||||
|
0x45 => EntityAttach
|
||||||
|
0x46 => EntityVelocity
|
||||||
|
0x47 => EntityEquipment_VarInt // TODO: changed to an array, but earlier than 1.16.1
|
||||||
|
0x48 => SetExperience
|
||||||
|
0x49 => UpdateHealth
|
||||||
|
0x4a => ScoreboardObjective
|
||||||
|
0x4b => SetPassengers
|
||||||
|
0x4c => Teams_VarInt
|
||||||
|
0x4d => UpdateScore
|
||||||
|
0x4e => TimeUpdate
|
||||||
|
0x4f => Title
|
||||||
|
0x50 => EntitySoundEffect
|
||||||
|
0x51 => SoundEffect
|
||||||
|
0x52 => StopSound
|
||||||
|
0x53 => PlayerListHeaderFooter
|
||||||
|
0x54 => NBTQueryResponse
|
||||||
|
0x55 => CollectItem
|
||||||
|
0x56 => EntityTeleport_f64
|
||||||
|
0x57 => Advancements
|
||||||
|
0x58 => EntityProperties
|
||||||
|
0x59 => EntityEffect
|
||||||
|
0x5a => DeclareRecipes
|
||||||
|
0x5b => TagsWithEntities
|
||||||
|
}
|
||||||
|
}
|
||||||
|
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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
|
@ -16,6 +16,7 @@ pub struct Map {
|
||||||
bits: Vec<u64>,
|
bits: Vec<u64>,
|
||||||
pub bit_size: usize,
|
pub bit_size: usize,
|
||||||
length: usize,
|
length: usize,
|
||||||
|
padded: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -53,17 +54,20 @@ impl Map {
|
||||||
bit_size: size,
|
bit_size: size,
|
||||||
length: len,
|
length: len,
|
||||||
bits: Vec::with_capacity((len * size) / 64),
|
bits: Vec::with_capacity((len * size) / 64),
|
||||||
|
padded: false,
|
||||||
};
|
};
|
||||||
for _ in 0..len {
|
for _ in 0..len {
|
||||||
map.bits.push(0)
|
map.bits.push(0)
|
||||||
}
|
}
|
||||||
map
|
map
|
||||||
}
|
}
|
||||||
pub fn from_raw(bits: Vec<u64>, size: usize) -> Map {
|
|
||||||
|
pub fn from_raw(bits: Vec<u64>, size: usize, padded: bool) -> Map {
|
||||||
Map {
|
Map {
|
||||||
length: (bits.len() * 64 + (size - 1)) / size,
|
length: (bits.len() * 64 + (size - 1)) / size,
|
||||||
bit_size: size,
|
bit_size: size,
|
||||||
bits,
|
bits,
|
||||||
|
padded,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -75,8 +79,17 @@ impl Map {
|
||||||
n
|
n
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn get_bit_offset(&self, i: usize) -> usize {
|
||||||
|
let padding = if self.padded {
|
||||||
|
i / (64 / self.bit_size) * (64 % self.bit_size)
|
||||||
|
} else {
|
||||||
|
0
|
||||||
|
};
|
||||||
|
i * self.bit_size + padding
|
||||||
|
}
|
||||||
|
|
||||||
pub fn set(&mut self, i: usize, val: usize) {
|
pub fn set(&mut self, i: usize, val: usize) {
|
||||||
let i = i * self.bit_size;
|
let i = self.get_bit_offset(i);
|
||||||
let pos = i / 64;
|
let pos = i / 64;
|
||||||
let mask = (1u64 << self.bit_size) - 1;
|
let mask = (1u64 << self.bit_size) - 1;
|
||||||
let ii = i % 64;
|
let ii = i % 64;
|
||||||
|
@ -90,7 +103,7 @@ impl Map {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get(&self, i: usize) -> usize {
|
pub fn get(&self, i: usize) -> usize {
|
||||||
let i = i * self.bit_size;
|
let i = self.get_bit_offset(i);
|
||||||
let pos = i / 64;
|
let pos = i / 64;
|
||||||
let mask = (1 << self.bit_size) - 1;
|
let mask = (1 << self.bit_size) - 1;
|
||||||
let ii = i % 64;
|
let ii = i % 64;
|
||||||
|
|
|
@ -509,6 +509,7 @@ impl Server {
|
||||||
self pck {
|
self pck {
|
||||||
PluginMessageClientbound_i16 => on_plugin_message_clientbound_i16,
|
PluginMessageClientbound_i16 => on_plugin_message_clientbound_i16,
|
||||||
PluginMessageClientbound => on_plugin_message_clientbound_1,
|
PluginMessageClientbound => on_plugin_message_clientbound_1,
|
||||||
|
JoinGame_WorldNames_IsHard => on_game_join_worldnames_ishard,
|
||||||
JoinGame_WorldNames => on_game_join_worldnames,
|
JoinGame_WorldNames => on_game_join_worldnames,
|
||||||
JoinGame_HashedSeed_Respawn => on_game_join_hashedseed_respawn,
|
JoinGame_HashedSeed_Respawn => on_game_join_hashedseed_respawn,
|
||||||
JoinGame_i32_ViewDistance => on_game_join_i32_viewdistance,
|
JoinGame_i32_ViewDistance => on_game_join_i32_viewdistance,
|
||||||
|
@ -521,6 +522,7 @@ impl Server {
|
||||||
KeepAliveClientbound_i64 => on_keep_alive_i64,
|
KeepAliveClientbound_i64 => on_keep_alive_i64,
|
||||||
KeepAliveClientbound_VarInt => on_keep_alive_varint,
|
KeepAliveClientbound_VarInt => on_keep_alive_varint,
|
||||||
KeepAliveClientbound_i32 => on_keep_alive_i32,
|
KeepAliveClientbound_i32 => on_keep_alive_i32,
|
||||||
|
ChunkData_Biomes3D_VarInt => on_chunk_data_biomes3d_varint,
|
||||||
ChunkData_Biomes3D_bool => on_chunk_data_biomes3d_bool,
|
ChunkData_Biomes3D_bool => on_chunk_data_biomes3d_bool,
|
||||||
ChunkData => on_chunk_data,
|
ChunkData => on_chunk_data,
|
||||||
ChunkData_Biomes3D => on_chunk_data_biomes3d,
|
ChunkData_Biomes3D => on_chunk_data_biomes3d,
|
||||||
|
@ -533,6 +535,7 @@ impl Server {
|
||||||
ChunkUnload => on_chunk_unload,
|
ChunkUnload => on_chunk_unload,
|
||||||
BlockChange_VarInt => on_block_change_varint,
|
BlockChange_VarInt => on_block_change_varint,
|
||||||
BlockChange_u8 => on_block_change_u8,
|
BlockChange_u8 => on_block_change_u8,
|
||||||
|
MultiBlockChange_Packed => on_multi_block_change_packed,
|
||||||
MultiBlockChange_VarInt => on_multi_block_change_varint,
|
MultiBlockChange_VarInt => on_multi_block_change_varint,
|
||||||
MultiBlockChange_u16 => on_multi_block_change_u16,
|
MultiBlockChange_u16 => on_multi_block_change_u16,
|
||||||
TeleportPlayer_WithConfirm => on_teleport_player_withconfirm,
|
TeleportPlayer_WithConfirm => on_teleport_player_withconfirm,
|
||||||
|
@ -970,6 +973,13 @@ impl Server {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn on_game_join_worldnames_ishard(
|
||||||
|
&mut self,
|
||||||
|
join: packet::play::clientbound::JoinGame_WorldNames_IsHard,
|
||||||
|
) {
|
||||||
|
self.on_game_join(join.gamemode, join.entity_id)
|
||||||
|
}
|
||||||
|
|
||||||
fn on_game_join_worldnames(&mut self, join: packet::play::clientbound::JoinGame_WorldNames) {
|
fn on_game_join_worldnames(&mut self, join: packet::play::clientbound::JoinGame_WorldNames) {
|
||||||
self.on_game_join(join.gamemode, join.entity_id)
|
self.on_game_join(join.gamemode, join.entity_id)
|
||||||
}
|
}
|
||||||
|
@ -1777,6 +1787,22 @@ impl Server {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn on_chunk_data_biomes3d_varint(
|
||||||
|
&mut self,
|
||||||
|
chunk_data: packet::play::clientbound::ChunkData_Biomes3D_VarInt,
|
||||||
|
) {
|
||||||
|
self.world
|
||||||
|
.load_chunk115(
|
||||||
|
chunk_data.chunk_x,
|
||||||
|
chunk_data.chunk_z,
|
||||||
|
chunk_data.new,
|
||||||
|
chunk_data.bitmask.0 as u16,
|
||||||
|
chunk_data.data.data,
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
self.load_block_entities(chunk_data.block_entities.data);
|
||||||
|
}
|
||||||
|
|
||||||
fn on_chunk_data_biomes3d_bool(
|
fn on_chunk_data_biomes3d_bool(
|
||||||
&mut self,
|
&mut self,
|
||||||
chunk_data: packet::play::clientbound::ChunkData_Biomes3D_bool,
|
chunk_data: packet::play::clientbound::ChunkData_Biomes3D_bool,
|
||||||
|
@ -1934,6 +1960,31 @@ impl Server {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn on_multi_block_change_packed(
|
||||||
|
&mut self,
|
||||||
|
block_change: packet::play::clientbound::MultiBlockChange_Packed,
|
||||||
|
) {
|
||||||
|
let sx = (block_change.chunk_section_pos >> 42) as i32;
|
||||||
|
let sy = ((block_change.chunk_section_pos << 44) >> 44) as i32;
|
||||||
|
let sz = ((block_change.chunk_section_pos << 22) >> 42) as i32;
|
||||||
|
|
||||||
|
for record in block_change.records.data {
|
||||||
|
let block_raw_id = record.0 >> 12;
|
||||||
|
let lz = (record.0 & 0xf) as i32;
|
||||||
|
let ly = ((record.0 >> 4) & 0xf) as i32;
|
||||||
|
let lx = ((record.0 >> 8) & 0xf) as i32;
|
||||||
|
|
||||||
|
self.world.set_block(
|
||||||
|
Position::new(sx + lx as i32, sy + ly as i32, sz + lz as i32),
|
||||||
|
block::Block::by_vanilla_id(
|
||||||
|
block_raw_id as usize,
|
||||||
|
self.protocol_version,
|
||||||
|
&self.world.modded_block_ids,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn on_multi_block_change_varint(
|
fn on_multi_block_change_varint(
|
||||||
&mut self,
|
&mut self,
|
||||||
block_change: packet::play::clientbound::MultiBlockChange_VarInt,
|
block_change: packet::play::clientbound::MultiBlockChange_VarInt,
|
||||||
|
|
|
@ -1066,7 +1066,8 @@ impl World {
|
||||||
}
|
}
|
||||||
|
|
||||||
let bits = LenPrefixed::<VarInt, u64>::read_from(&mut data)?.data;
|
let bits = LenPrefixed::<VarInt, u64>::read_from(&mut data)?.data;
|
||||||
let m = bit::Map::from_raw(bits, bit_size as usize);
|
let padded = self.protocol_version >= 736;
|
||||||
|
let m = bit::Map::from_raw(bits, bit_size as usize, padded);
|
||||||
|
|
||||||
for bi in 0..4096 {
|
for bi in 0..4096 {
|
||||||
let id = m.get(bi);
|
let id = m.get(bi);
|
||||||
|
|
Loading…
Reference in New Issue