Skip to content

Commit 2b9d106

Browse files
authored
Merge pull request feather-rs#269 from Schuwi/fix-world-loading
Fix various world loading problems (Issue feather-rs#265)
2 parents 2a83e56 + 3a903bd commit 2b9d106

15 files changed

Lines changed: 567 additions & 141 deletions

File tree

Cargo.lock

Lines changed: 14 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

core/anvil/Cargo.toml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,13 @@ feather-util = { path = "../util" }
1414

1515
thiserror = "1.0"
1616
tokio = { version = "0.2", features = ["full"] }
17-
serde = "1.0"
17+
serde = "1.0.112" # >= 1.0.112 needed for a fix in #[serde(flatten)]
1818
uuid = "0.8"
1919
hematite-nbt = "0.4"
2020
byteorder = "1.3"
2121
bitvec = "0.17"
2222
anyhow = "1.0"
2323
arrayvec = { version = "0.5", features = ["serde"] }
24+
25+
[dev-dependencies]
26+
"serde_test" = "1.0.112"

core/anvil/src/block_entity.rs

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -58,39 +58,45 @@ pub struct BlockEntityBase {
5858
/// Kind of a block entity.
5959
#[derive(Debug, Clone, Serialize, Deserialize)]
6060
#[serde(tag = "id")]
61-
#[serde(rename_all = "PascalCase")]
6261
pub enum BlockEntityKind {
6362
#[serde(rename = "minecraft:beacon")]
63+
#[serde(rename_all = "PascalCase")]
6464
Beacon {
6565
levels: i32,
6666
primary: i32,
6767
secondary: i32,
6868
},
6969
#[serde(rename = "minecraft:bed")]
70+
#[serde(rename_all = "PascalCase")]
7071
Bed, // empty in JE
7172
#[serde(rename = "minecraft:brewing_stand")]
73+
#[serde(rename_all = "PascalCase")]
7274
BrewingStand {
7375
items: Vec<InventorySlot>,
7476
brew_time: i16,
7577
fuel: i8,
7678
},
7779
#[serde(rename = "minecraft:cauldron")]
80+
#[serde(rename_all = "PascalCase")]
7881
Cauldron {
7982
items: Vec<InventorySlot>,
8083
potion_id: i16,
8184
splash_potion: bool,
8285
is_movable: bool,
8386
},
8487
#[serde(rename = "minecraft:chest")]
88+
#[serde(rename_all = "PascalCase")]
8589
Chest {
86-
#[serde(rename = "Items")]
90+
#[serde(default)]
8791
items: Vec<InventorySlot>,
8892
loot_table: Option<String>,
8993
loot_table_seed: Option<i64>,
9094
},
9195
#[serde(rename = "minecraft:comparator")]
96+
#[serde(rename_all = "PascalCase")]
9297
Comparator { output_signal: i32 },
9398
#[serde(rename = "minecraft:command_block")]
99+
#[serde(rename_all = "PascalCase")]
94100
CommandBlock {
95101
custom_name: Option<String>,
96102
command: String,
@@ -104,32 +110,42 @@ pub enum BlockEntityKind {
104110
last_execution: i64,
105111
},
106112
#[serde(rename = "minecraft:daylight_detector")]
113+
#[serde(rename_all = "PascalCase")]
107114
DaylightDetector, // empty
108115
#[serde(rename = "minecraft:dispenser")]
116+
#[serde(rename_all = "PascalCase")]
109117
Dispenser { items: Vec<InventorySlot> },
110118
#[serde(rename = "minecraft:dropper")]
119+
#[serde(rename_all = "PascalCase")]
111120
Dropper { items: Vec<InventorySlot> },
112121
#[serde(rename = "minecraft:enchanting_table")]
122+
#[serde(rename_all = "PascalCase")]
113123
EnchantingTable,
114124
#[serde(rename = "minecraft:ender_chest")]
125+
#[serde(rename_all = "PascalCase")]
115126
EnderChest,
116127
#[serde(rename = "minecraft:end_gateway")]
128+
#[serde(rename_all = "PascalCase")]
117129
EndGateway { age: i64, exact_teleport: bool },
118130
#[serde(rename = "minecraft:end_portal")]
131+
#[serde(rename_all = "PascalCase")]
119132
EndPortal,
120133
#[serde(rename = "minecraft:furnace")]
134+
#[serde(rename_all = "PascalCase")]
121135
Furnace {
122136
items: Vec<InventorySlot>,
123137
burn_time: i16,
124138
cook_time: i16,
125139
cook_time_total: i16,
126140
},
127141
#[serde(rename = "minecraft:hopper")]
142+
#[serde(rename_all = "PascalCase")]
128143
Hopper {
129144
items: Vec<InventorySlot>,
130145
transfer_cooldown: i32,
131146
},
132147
#[serde(rename = "minecraft:jigsaw")]
148+
#[serde(rename_all = "PascalCase")]
133149
Jigsaw {
134150
target_pool: String,
135151
final_state: String,
@@ -138,8 +154,12 @@ pub enum BlockEntityKind {
138154
attachment_type: String,
139155
},
140156
#[serde(rename = "minecraft:jukebox")]
157+
#[serde(rename_all = "PascalCase")]
141158
Jukebox { record_item: InventorySlot },
142159
// TODO: a few more
160+
/// Fallback type for unknown block entities
161+
#[serde(other)]
162+
Unknown,
143163
}
144164

145165
impl BlockEntityKind {
@@ -163,6 +183,7 @@ impl BlockEntityKind {
163183
BlockEntityKind::Hopper { .. } => BlockEntityVariant::Hopper,
164184
BlockEntityKind::Jigsaw { .. } => BlockEntityVariant::Jigsaw,
165185
BlockEntityKind::Jukebox { .. } => BlockEntityVariant::Jukebox,
186+
BlockEntityKind::Unknown { .. } => BlockEntityVariant::Unknown,
166187
}
167188
}
168189
}
@@ -188,4 +209,5 @@ pub enum BlockEntityVariant {
188209
Hopper,
189210
Jigsaw,
190211
Jukebox,
212+
Unknown,
191213
}

core/anvil/src/entity.rs

Lines changed: 30 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -131,8 +131,6 @@ pub struct BaseEntityData {
131131
pub rotation: ArrayVec<[f32; 2]>,
132132
#[serde(rename = "Motion")]
133133
pub velocity: ArrayVec<[f64; 3]>,
134-
#[serde(rename = "Health")]
135-
pub health: f32,
136134
}
137135

138136
impl BaseEntityData {
@@ -149,7 +147,6 @@ impl BaseEntityData {
149147
String::from("Motion"),
150148
Value::List(self.velocity.iter().copied().map(Value::Double).collect()),
151149
);
152-
map.insert(String::from("Health"), Value::Float(self.health));
153150
}
154151
}
155152

@@ -161,12 +158,11 @@ pub enum EntityLoadError {
161158

162159
impl BaseEntityData {
163160
/// Creates a `BaseEntityData` from its parameters.
164-
pub fn new(pos: Position, velocity: Vec3d, health: f32) -> Self {
161+
pub fn new(pos: Position, velocity: Vec3d) -> Self {
165162
Self {
166163
position: [pos.x, pos.y, pos.z].into(),
167164
rotation: [pos.yaw, pos.pitch].into(),
168165
velocity: [velocity.x, velocity.y, velocity.z].into(),
169-
health,
170166
}
171167
}
172168

@@ -202,7 +198,6 @@ impl Default for BaseEntityData {
202198
position: [0.0, 0.0, 0.0].into(),
203199
rotation: [0.0, 0.0].into(),
204200
velocity: [0.0, 0.0, 0.0].into(),
205-
health: 20.0,
206201
}
207202
}
208203
}
@@ -211,26 +206,45 @@ impl Default for BaseEntityData {
211206
pub struct AnimalData {
212207
#[serde(flatten)]
213208
pub base: BaseEntityData,
209+
#[serde(rename = "Health")]
210+
pub health: f32,
214211
}
215212

216213
impl AnimalData {
217214
fn write_to_map(self, map: &mut HashMap<String, Value>) {
218215
self.base.write_to_map(map);
216+
map.insert(String::from("Health"), Value::Float(self.health));
217+
}
218+
}
219+
220+
impl AnimalData {
221+
/// Creates an `AnimalData` from its parameters.
222+
pub fn new(base: BaseEntityData, health: f32) -> Self {
223+
Self { base, health }
224+
}
225+
}
226+
227+
impl Default for AnimalData {
228+
fn default() -> Self {
229+
AnimalData {
230+
base: Default::default(),
231+
health: 20.0,
232+
}
219233
}
220234
}
221235

222236
/// Represents a single item, without slot information.
223237
#[derive(Debug, Clone, Serialize, Deserialize)]
224238
pub struct ItemData {
225239
#[serde(rename = "Count")]
226-
pub count: u8,
240+
pub count: i8,
227241
#[serde(rename = "id")]
228242
pub item: String,
229243
}
230244

231245
impl ItemData {
232246
fn write_to_map(self, map: &mut HashMap<String, Value>) {
233-
map.insert(String::from("Count"), Value::Byte(self.count as i8));
247+
map.insert(String::from("Count"), Value::Byte(self.count));
234248
map.insert(String::from("id"), Value::String(self.item));
235249
}
236250
}
@@ -255,9 +269,11 @@ pub struct ItemEntityData {
255269
#[serde(rename = "Age")]
256270
pub age: i16,
257271
#[serde(rename = "PickupDelay")]
258-
pub pickup_delay: u8,
272+
pub pickup_delay: i16,
259273
#[serde(rename = "Item")]
260274
pub item: ItemData,
275+
#[serde(rename = "Health")]
276+
pub health: i16,
261277
}
262278

263279
impl ItemEntityData {
@@ -269,10 +285,8 @@ impl ItemEntityData {
269285
map.insert(String::from("Item"), Value::Compound(item));
270286

271287
map.insert(String::from("Age"), Value::Short(self.age));
272-
map.insert(
273-
String::from("PickupDelay"),
274-
Value::Byte(self.pickup_delay as i8),
275-
);
288+
map.insert(String::from("PickupDelay"), Value::Short(self.pickup_delay));
289+
map.insert(String::from("Health"), Value::Short(self.health));
276290
}
277291
}
278292

@@ -288,14 +302,14 @@ pub struct ArrowEntityData {
288302
// TODO: Change this field to `bool` when issue with hematite_nbt is resolved.
289303
// See: https://github.com/PistonDevelopers/hematite_nbt/issues/43
290304
#[serde(rename = "crit")]
291-
pub critical: u8,
305+
pub critical: i8,
292306
}
293307

294308
impl ArrowEntityData {
295309
fn write_to_map(self, map: &mut HashMap<String, Value>) {
296310
self.entity.write_to_map(map);
297311

298-
map.insert(String::from("crit"), Value::Byte(self.critical as i8));
312+
map.insert(String::from("crit"), Value::Byte(self.critical));
299313
}
300314
}
301315

@@ -310,7 +324,6 @@ mod tests {
310324
position: [1.0, 2.0, 3.0].into(),
311325
rotation: [4.0, 5.0].into(),
312326
velocity: [6.0, 7.0, 8.0].into(),
313-
health: 20.0,
314327
};
315328
let pos = data.read_position().unwrap();
316329

@@ -328,7 +341,6 @@ mod tests {
328341
position: [1.0, 2.0, 3.0].into(),
329342
rotation: [4.0, 5.0].into(),
330343
velocity: [6.0, 7.0, 8.0].into(),
331-
health: 20.0,
332344
};
333345
let vel = data.read_velocity().unwrap();
334346

@@ -342,7 +354,7 @@ mod tests {
342354
let pos = position!(1.0, 10.0, 3.0, 115.0, -3.0);
343355
let vel = vec3(0.0, 1.0, 2.0);
344356

345-
let data = BaseEntityData::new(pos, vel, 20.0);
357+
let data = BaseEntityData::new(pos, vel);
346358
assert_eq!(data.read_position(), Ok(pos));
347359
assert_eq!(data.read_velocity(), Ok(vel));
348360
}

core/anvil/src/player.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use crate::entity::BaseEntityData;
1+
use crate::entity::AnimalData;
22
use feather_inventory::player_constants::{
33
HOTBAR_SIZE, INVENTORY_SIZE, SLOT_ARMOR_MAX, SLOT_ARMOR_MIN, SLOT_HOTBAR_OFFSET,
44
SLOT_INVENTORY_OFFSET, SLOT_OFFHAND,
@@ -19,7 +19,7 @@ use uuid::Uuid;
1919
pub struct PlayerData {
2020
// Inherit base entity data
2121
#[serde(flatten)]
22-
pub entity: BaseEntityData,
22+
pub animal: AnimalData,
2323

2424
#[serde(rename = "playerGameType")]
2525
pub gamemode: i32,

0 commit comments

Comments
 (0)