1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
//! V2702 (21w10a + 3) — schematic-relevant subset of `V2702.java`.
//!
//! Arrow-family `player` flag -> `pickup` byte (V2702.java:13-31). When an arrow,
//! spectral_arrow, or trident has no `pickup` key, the legacy boolean `player`
//! (default `true`) is removed and rewritten as a `pickup` byte (1 if player,
//! else 0). Registered per-id on ENTITY. Nothing non-schematic is present.
//!
//! VERSION = MCVersions.V21W10A (2699) + 3 = 2702.
use crate::nbt::NbtMap;
use super::super::loss::{report_loss, LossKind, Severity};
use super::super::registry::RegistryBuilder;
use super::super::types::MapExt;
const VERSION: i32 = 2702;
fn convert_arrow(
data: &mut NbtMap,
_from: super::super::version::EncodedVersion,
_to: super::super::version::EncodedVersion,
) {
if data.has_key("pickup") {
return;
}
// getBoolean("player", true): default true when absent.
let player = data.get_bool("player").unwrap_or(true);
data.take("player");
data.set_byte("pickup", if player { 1 } else { 0 });
}
/// Inverse of `convert_arrow` (V2702.java:13-31): restore the legacy boolean
/// `player` from the `pickup` byte and drop `pickup`.
///
/// The forward only ever produced `pickup` 0 (player=false) or 1 (player=true),
/// so those map back exactly. `pickup == 2` (creative-only pickup) has no
/// representation in the pre-2702 boolean `player`; we best-effort it as
/// `player = (pickup != 0)` -> `true` and report the dropped distinction
/// (rule 11: the modern value genuinely can't be encoded in the old boolean).
fn revert_arrow(
data: &mut NbtMap,
_from: super::super::version::EncodedVersion,
_to: super::super::version::EncodedVersion,
) {
// Forward removed `player` and always wrote `pickup`; if `pickup` is somehow
// absent, mirror the forward default (player=true).
let pickup = data.get_i32("pickup").unwrap_or(1);
if pickup == 2 {
report_loss(
VERSION,
LossKind::UnsupportedInTarget,
Severity::Loss,
"arrow pickup=2 (creative pickup) collapses to player=true; the creative-only distinction is lost",
);
}
data.take("pickup");
// vanilla treats `player` as a boolean -> non-zero pickup means player pickup.
data.set_bool("player", pickup != 0);
}
pub fn register(reg: &mut RegistryBuilder) {
reg.entity
.add_converter_for_id("minecraft:arrow", VERSION, 0, Box::new(convert_arrow));
reg.entity
.add_reverse_converter_for_id("minecraft:arrow", VERSION, 0, Box::new(revert_arrow));
reg.entity.add_converter_for_id(
"minecraft:spectral_arrow",
VERSION,
0,
Box::new(convert_arrow),
);
reg.entity.add_reverse_converter_for_id(
"minecraft:spectral_arrow",
VERSION,
0,
Box::new(revert_arrow),
);
reg.entity
.add_converter_for_id("minecraft:trident", VERSION, 0, Box::new(convert_arrow));
reg.entity.add_reverse_converter_for_id(
"minecraft:trident",
VERSION,
0,
Box::new(revert_arrow),
);
}