1.13.2 (404) multiprotocol support (#67)
Adds support for 1.13.2 protocol (404) Expands https://github.com/iceiix/steven/issues/18 Enhance protocol support Metadata: * Support 1.13.2 slot data format, bool and varint item id, optional damage (moved to NBT) https://wiki.vg/index.php?title=Slot_Data&type=revision&diff=14363&oldid=7835 Packets: * Add 1.13.2 packets, and implement all the command data parsers https://wiki.vg/Command_Data#Parsers * Send new plugin channel minecraft:brand https://wiki.vg/Plugin_channels#minecraft:brand * Add 1.13.2 metadata format, with shifted IDs https://wiki.vg/Entity_metadata#Entity_Metadata_Format * Implement particle entity metadata * Add structures for 16 new packets Blocks: The Flattening: * Assign flattened IDs in correct order using new 'offset' macro token * Assign hierarchical (pre-flattening) block IDs sequentially by counting Some data * Split VANILLA_ID_MAP into flat/hier struct, to support before and after the flattening * Extend travis build time to 20 minutes because the blocks macro takes a long time * Support both flat/hier blocks by passing protocol_version to by_vanilla_id Add block states and offsets for all blocks, replacing metadata for 1.13+: * Add stripped logs and what was Log2 to Log * Add the Wood blocks, should be called bark, previously Axis::None Log * Add leaves distance and offset * Add jungle/acacia to Leaves moved from Leaves2 * Add dispenser offsets, direction * Add note block states * Add offset None to Missing253 and Missing254, no holes in block states of 1.13.2 * Add bed colors * Add seagrass, tall seagrass, remove redundant deadgrass, and piston offset * Add torch, TNT, fire offsets, remove slabs * Add furnance offset, merges lit into a property * Add pressure plate offsets, new pressure plates, redstone ore/lit merged * Add lever offsets, new directions from ceiling/floor, rename LeverDirections * Add redstone torch offsets, new blocks since lit/unlit is now merged, and standing/wall is split * Change lever to split face/facing, rm LeverDirection, add AttachedFace * Add stone button offsets, face/facing similar to lever * Move face/facing data and variant to AttachedFace, reuse for lever/stonebutton * Add data_with_facing_and_powered() to AttachedFace, for lever/stonebutton * Add wooden button offsets each wood * Add pumpkin without a face * Add carved pumpkin, portal offsets * Add lit pumpkin (as jack-o-lantern) offsets after carved pumpkin * Add repeater offsets, merged into Repeater * Change brown mushroom block to booleans instead of MushroomVariant * Add mushroom block offsets, red/brown mushroom blocks, and a new mushroom stem block * Add command block, cobblestone walls, and flower pot offsets Empty flower pot, and potted plants including saplings. Rename variant DarkOak to DarkOakSaplings because it is a sapling, and remove the duplicate Dandelion variant which causes duplicate blocks. * Increase recursion limit in steven_blocks * Add colored banner offsets * Add wooden slab including double slab, in a different position for pre-1.13 and 1.13 * StoneSlabVariant::Wood -> StoneSlabVariant::PetrifiedWood * Add fence_gate_offset() for wooden fence gates * Add frosted ice age, offset * Add new blocks: kelp, turtle egg, coral, coral fans, sea pickle, blue ice, smooth stone * Add new blocks: conduit, void air, cave aid, bubble column, last of the 1.13 blocks
This commit is contained in:
parent
37e6d962ec
commit
68441320e8
|
@ -21,7 +21,7 @@ use byteorder::{BigEndian, WriteBytesExt, ReadBytesExt};
|
|||
pub struct Stack {
|
||||
id: isize,
|
||||
count: isize,
|
||||
damage: isize,
|
||||
damage: Option<isize>,
|
||||
tag: Option<nbt::NamedTag>,
|
||||
}
|
||||
|
||||
|
@ -31,7 +31,7 @@ impl Default for Stack {
|
|||
Stack {
|
||||
id: -1,
|
||||
count: 0,
|
||||
damage: 0,
|
||||
damage: None,
|
||||
tag: None,
|
||||
}
|
||||
}
|
||||
|
@ -39,14 +39,31 @@ impl Default for Stack {
|
|||
|
||||
impl Serializable for Option<Stack> {
|
||||
fn read_from<R: io::Read>(buf: &mut R) -> Result<Option<Stack>, protocol::Error> {
|
||||
let id = buf.read_i16::<BigEndian>()?;
|
||||
let protocol_version = unsafe { protocol::CURRENT_PROTOCOL_VERSION };
|
||||
|
||||
if protocol_version >= 404 {
|
||||
let present = buf.read_u8()? != 0;
|
||||
if !present {
|
||||
return Ok(None)
|
||||
}
|
||||
}
|
||||
|
||||
let id = if protocol_version >= 404 {
|
||||
protocol::VarInt::read_from(buf)?.0 as isize
|
||||
} else {
|
||||
buf.read_i16::<BigEndian>()? as isize
|
||||
};
|
||||
|
||||
if id == -1 {
|
||||
return Ok(None);
|
||||
}
|
||||
let count = buf.read_u8()? as isize;
|
||||
let damage = buf.read_i16::<BigEndian>()? as isize;
|
||||
|
||||
let protocol_version = unsafe { protocol::CURRENT_PROTOCOL_VERSION };
|
||||
let damage = if protocol_version >= 404 {
|
||||
// 1.13.2+ stores damage in the NBT
|
||||
None
|
||||
} else {
|
||||
Some(buf.read_i16::<BigEndian>()? as isize)
|
||||
};
|
||||
|
||||
let tag: Option<nbt::NamedTag> = if protocol_version >= 47 {
|
||||
Serializable::read_from(buf)?
|
||||
|
@ -74,9 +91,10 @@ impl Serializable for Option<Stack> {
|
|||
fn write_to<W: io::Write>(&self, buf: &mut W) -> Result<(), protocol::Error> {
|
||||
match *self {
|
||||
Some(ref val) => {
|
||||
// TODO: if protocol_version >= 404, send present and id varint, no damage, for 1.13.2
|
||||
buf.write_i16::<BigEndian>(val.id as i16)?;
|
||||
buf.write_u8(val.count as u8)?;
|
||||
buf.write_i16::<BigEndian>(val.damage as i16)?;
|
||||
buf.write_i16::<BigEndian>(val.damage.unwrap_or(0) as i16)?;
|
||||
// TODO: compress zlib NBT if 1.7
|
||||
val.tag.write_to(buf)?;
|
||||
}
|
||||
|
|
|
@ -18,6 +18,7 @@ use std::io;
|
|||
use std::fmt;
|
||||
use crate::protocol;
|
||||
use crate::protocol::Serializable;
|
||||
use crate::protocol::LenPrefixed;
|
||||
use crate::format;
|
||||
use crate::item;
|
||||
use crate::shared::Position;
|
||||
|
@ -271,13 +272,151 @@ impl Metadata {
|
|||
u8::write_to(&0xFF, buf)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn read_from113<R: io::Read>(buf: &mut R) -> Result<Self, protocol::Error> {
|
||||
let mut m = Self::new();
|
||||
loop {
|
||||
let index = u8::read_from(buf)? as i32;
|
||||
if index == 0xFF {
|
||||
break;
|
||||
}
|
||||
let ty = protocol::VarInt::read_from(buf)?.0;
|
||||
match ty {
|
||||
0 => m.put_raw(index, i8::read_from(buf)?),
|
||||
1 => m.put_raw(index, protocol::VarInt::read_from(buf)?.0),
|
||||
2 => m.put_raw(index, f32::read_from(buf)?),
|
||||
3 => m.put_raw(index, String::read_from(buf)?),
|
||||
4 => m.put_raw(index, format::Component::read_from(buf)?),
|
||||
5 => m.put_raw(index, LenPrefixed::<bool, format::Component>::read_from(buf)?),
|
||||
6 => m.put_raw(index, Option::<item::Stack>::read_from(buf)?),
|
||||
7 => m.put_raw(index, bool::read_from(buf)?),
|
||||
8 => m.put_raw(index,
|
||||
[f32::read_from(buf)?,
|
||||
f32::read_from(buf)?,
|
||||
f32::read_from(buf)?]),
|
||||
9 => m.put_raw(index, Position::read_from(buf)?),
|
||||
10 => {
|
||||
if bool::read_from(buf)? {
|
||||
m.put_raw(index, Option::<Position>::read_from(buf)?);
|
||||
} else {
|
||||
m.put_raw::<Option<Position>>(index, None);
|
||||
}
|
||||
}
|
||||
11 => m.put_raw(index, protocol::VarInt::read_from(buf)?),
|
||||
12 => {
|
||||
if bool::read_from(buf)? {
|
||||
m.put_raw(index, Option::<protocol::UUID>::read_from(buf)?);
|
||||
} else {
|
||||
m.put_raw::<Option<protocol::UUID>>(index, None);
|
||||
}
|
||||
}
|
||||
13 => m.put_raw(index, protocol::VarInt::read_from(buf)?.0 as u16),
|
||||
14 => {
|
||||
let ty = u8::read_from(buf)?;
|
||||
if ty != 0 {
|
||||
let name = nbt::read_string(buf)?;
|
||||
let tag = nbt::Tag::read_from(buf)?;
|
||||
|
||||
m.put_raw(index, nbt::NamedTag(name, tag));
|
||||
}
|
||||
}
|
||||
15 => panic!("TODO: particle"),
|
||||
_ => return Err(protocol::Error::Err("unknown metadata type".to_owned())),
|
||||
}
|
||||
}
|
||||
Ok(m)
|
||||
}
|
||||
|
||||
fn write_to113<W: io::Write>(&self, buf: &mut W) -> Result<(), protocol::Error> {
|
||||
for (k, v) in &self.map {
|
||||
(*k as u8).write_to(buf)?;
|
||||
match *v {
|
||||
Value::Byte(ref val) => {
|
||||
u8::write_to(&0, buf)?;
|
||||
val.write_to(buf)?;
|
||||
}
|
||||
Value::Int(ref val) => {
|
||||
u8::write_to(&1, buf)?;
|
||||
protocol::VarInt(*val).write_to(buf)?;
|
||||
}
|
||||
Value::Float(ref val) => {
|
||||
u8::write_to(&2, buf)?;
|
||||
val.write_to(buf)?;
|
||||
}
|
||||
Value::String(ref val) => {
|
||||
u8::write_to(&3, buf)?;
|
||||
val.write_to(buf)?;
|
||||
}
|
||||
Value::FormatComponent(ref val) => {
|
||||
u8::write_to(&4, buf)?;
|
||||
val.write_to(buf)?;
|
||||
}
|
||||
Value::OptionalFormatComponent(ref val) => {
|
||||
u8::write_to(&5, buf)?;
|
||||
val.write_to(buf)?;
|
||||
}
|
||||
Value::OptionalItemStack(ref val) => {
|
||||
u8::write_to(&6, buf)?;
|
||||
val.write_to(buf)?;
|
||||
}
|
||||
Value::Bool(ref val) => {
|
||||
u8::write_to(&7, buf)?;
|
||||
val.write_to(buf)?;
|
||||
}
|
||||
Value::Vector(ref val) => {
|
||||
u8::write_to(&8, buf)?;
|
||||
val[0].write_to(buf)?;
|
||||
val[1].write_to(buf)?;
|
||||
val[2].write_to(buf)?;
|
||||
}
|
||||
Value::Position(ref val) => {
|
||||
u8::write_to(&9, buf)?;
|
||||
val.write_to(buf)?;
|
||||
}
|
||||
Value::OptionalPosition(ref val) => {
|
||||
u8::write_to(&10, buf)?;
|
||||
val.is_some().write_to(buf)?;
|
||||
val.write_to(buf)?;
|
||||
}
|
||||
Value::Direction(ref val) => {
|
||||
u8::write_to(&11, buf)?;
|
||||
val.write_to(buf)?;
|
||||
}
|
||||
Value::OptionalUUID(ref val) => {
|
||||
u8::write_to(&12, buf)?;
|
||||
val.is_some().write_to(buf)?;
|
||||
val.write_to(buf)?;
|
||||
}
|
||||
Value::Block(ref val) => {
|
||||
u8::write_to(&13, buf)?;
|
||||
protocol::VarInt(*val as i32).write_to(buf)?;
|
||||
}
|
||||
Value::NBTTag(ref _val) => {
|
||||
u8::write_to(&14, buf)?;
|
||||
// TODO: write NBT tags metadata
|
||||
//nbt::Tag(*val).write_to(buf)?;
|
||||
}
|
||||
Value::Particle(ref val) => {
|
||||
u8::write_to(&15, buf)?;
|
||||
val.write_to(buf)?;
|
||||
}
|
||||
_ => panic!("unexpected metadata"),
|
||||
}
|
||||
}
|
||||
u8::write_to(&0xFF, buf)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
impl Serializable for Metadata {
|
||||
fn read_from<R: io::Read>(buf: &mut R) -> Result<Self, protocol::Error> {
|
||||
let protocol_version = unsafe { protocol::CURRENT_PROTOCOL_VERSION };
|
||||
|
||||
if protocol_version >= 74 {
|
||||
if protocol_version >= 404 {
|
||||
Metadata::read_from113(buf)
|
||||
} else if protocol_version >= 74 {
|
||||
Metadata::read_from19(buf)
|
||||
} else {
|
||||
Metadata::read_from18(buf)
|
||||
|
@ -287,7 +426,9 @@ impl Serializable for Metadata {
|
|||
fn write_to<W: io::Write>(&self, buf: &mut W) -> Result<(), protocol::Error> {
|
||||
let protocol_version = unsafe { protocol::CURRENT_PROTOCOL_VERSION };
|
||||
|
||||
if protocol_version >= 74 {
|
||||
if protocol_version >= 404 {
|
||||
self.write_to113(buf)
|
||||
} else if protocol_version >= 74 {
|
||||
self.write_to19(buf)
|
||||
} else {
|
||||
self.write_to18(buf)
|
||||
|
@ -319,6 +460,7 @@ pub enum Value {
|
|||
Float(f32),
|
||||
String(String),
|
||||
FormatComponent(format::Component),
|
||||
OptionalFormatComponent(LenPrefixed<bool, format::Component>),
|
||||
OptionalItemStack(Option<item::Stack>),
|
||||
Bool(bool),
|
||||
Vector([f32; 3]),
|
||||
|
@ -329,6 +471,146 @@ pub enum Value {
|
|||
OptionalUUID(Option<protocol::UUID>),
|
||||
Block(u16), // TODO: Proper type
|
||||
NBTTag(nbt::NamedTag),
|
||||
Particle(ParticleData),
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum ParticleData {
|
||||
AmbientEntityEffect,
|
||||
AngryVillager,
|
||||
Barrier,
|
||||
Block {
|
||||
block_state: protocol::VarInt,
|
||||
},
|
||||
Bubble,
|
||||
Cloud,
|
||||
Crit,
|
||||
DamageIndicator,
|
||||
DragonBreath,
|
||||
DrippingLava,
|
||||
DrippingWater,
|
||||
Dust {
|
||||
red: f32,
|
||||
green: f32,
|
||||
blue: f32,
|
||||
scale: f32,
|
||||
},
|
||||
Effect,
|
||||
ElderGuardian,
|
||||
EnchantedHit,
|
||||
Enchant,
|
||||
EndRod,
|
||||
EntityEffect,
|
||||
ExplosionEmitter,
|
||||
Explosion,
|
||||
FallingDust {
|
||||
block_state: protocol::VarInt,
|
||||
},
|
||||
Firework,
|
||||
Fishing,
|
||||
Flame,
|
||||
HappyVillager,
|
||||
Heart,
|
||||
InstantEffect,
|
||||
Item {
|
||||
item: Option<item::Stack>,
|
||||
},
|
||||
ItemSlime,
|
||||
ItemSnowball,
|
||||
LargeSmoke,
|
||||
Lava,
|
||||
Mycelium,
|
||||
Note,
|
||||
Poof,
|
||||
Portal,
|
||||
Rain,
|
||||
Smoke,
|
||||
Spit,
|
||||
SquidInk,
|
||||
SweepAttack,
|
||||
TotemOfUndying,
|
||||
Underwater,
|
||||
Splash,
|
||||
Witch,
|
||||
BubblePop,
|
||||
CurrentDown,
|
||||
BubbleColumnUp,
|
||||
Nautilus,
|
||||
Dolphin,
|
||||
}
|
||||
|
||||
impl Serializable for ParticleData {
|
||||
fn read_from<R: io::Read>(buf: &mut R) -> Result<Self, protocol::Error> {
|
||||
let id = protocol::VarInt::read_from(buf)?.0;
|
||||
Ok(match id {
|
||||
0 => ParticleData::AmbientEntityEffect,
|
||||
1 => ParticleData::AngryVillager,
|
||||
2 => ParticleData::Barrier,
|
||||
3 => ParticleData::Block {
|
||||
block_state: Serializable::read_from(buf)?
|
||||
},
|
||||
4 => ParticleData::Bubble,
|
||||
5 => ParticleData::Cloud,
|
||||
6 => ParticleData::Crit,
|
||||
7 => ParticleData::DamageIndicator,
|
||||
8 => ParticleData::DragonBreath,
|
||||
9 => ParticleData::DrippingLava,
|
||||
10 => ParticleData::DrippingWater,
|
||||
11 => ParticleData::Dust {
|
||||
red: Serializable::read_from(buf)?,
|
||||
green: Serializable::read_from(buf)?,
|
||||
blue: Serializable::read_from(buf)?,
|
||||
scale: Serializable::read_from(buf)?,
|
||||
},
|
||||
12 => ParticleData::Effect,
|
||||
13 => ParticleData::ElderGuardian,
|
||||
14 => ParticleData::EnchantedHit,
|
||||
15 => ParticleData::Enchant,
|
||||
16 => ParticleData::EndRod,
|
||||
17 => ParticleData::EntityEffect,
|
||||
18 => ParticleData::ExplosionEmitter,
|
||||
19 => ParticleData::Explosion,
|
||||
20 => ParticleData::FallingDust {
|
||||
block_state: Serializable::read_from(buf)?,
|
||||
},
|
||||
21 => ParticleData::Firework,
|
||||
22 => ParticleData::Fishing,
|
||||
23 => ParticleData::Flame,
|
||||
24 => ParticleData::HappyVillager,
|
||||
25 => ParticleData::Heart,
|
||||
26 => ParticleData::InstantEffect,
|
||||
27 => ParticleData::Item {
|
||||
item: Serializable::read_from(buf)?,
|
||||
},
|
||||
28 => ParticleData::ItemSlime,
|
||||
29 => ParticleData::ItemSnowball,
|
||||
30 => ParticleData::LargeSmoke,
|
||||
31 => ParticleData::Lava,
|
||||
32 => ParticleData::Mycelium,
|
||||
33 => ParticleData::Note,
|
||||
34 => ParticleData::Poof,
|
||||
35 => ParticleData::Portal,
|
||||
36 => ParticleData::Rain,
|
||||
37 => ParticleData::Smoke,
|
||||
38 => ParticleData::Spit,
|
||||
39 => ParticleData::SquidInk,
|
||||
40 => ParticleData::SweepAttack,
|
||||
41 => ParticleData::TotemOfUndying,
|
||||
42 => ParticleData::Underwater,
|
||||
43 => ParticleData::Splash,
|
||||
44 => ParticleData::Witch,
|
||||
45 => ParticleData::BubblePop,
|
||||
46 => ParticleData::CurrentDown,
|
||||
47 => ParticleData::BubbleColumnUp,
|
||||
48 => ParticleData::Nautilus,
|
||||
49 => ParticleData::Dolphin,
|
||||
_ => panic!("unrecognized particle data id {}", id),
|
||||
})
|
||||
}
|
||||
|
||||
fn write_to<W: io::Write>(&self, _buf: &mut W) -> Result<(), protocol::Error> {
|
||||
unimplemented!()
|
||||
}
|
||||
}
|
||||
|
||||
pub trait MetaValue {
|
||||
|
@ -408,6 +690,19 @@ impl MetaValue for format::Component {
|
|||
}
|
||||
}
|
||||
|
||||
impl MetaValue for LenPrefixed<bool, format::Component> {
|
||||
fn unwrap(value: &Value) -> &Self {
|
||||
match *value {
|
||||
Value::OptionalFormatComponent(ref val) => val,
|
||||
_ => panic!("incorrect key"),
|
||||
}
|
||||
}
|
||||
fn wrap(self) -> Value {
|
||||
Value::OptionalFormatComponent(self)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
impl MetaValue for Option<item::Stack> {
|
||||
fn unwrap(value: &Value) -> &Self {
|
||||
match *value {
|
||||
|
|
Loading…
Reference in New Issue