ItemStackComponentizationFix.java
net.minecraft.util.datafix.fixes.ItemStackComponentizationFix
信息
- 全限定名:net.minecraft.util.datafix.fixes.ItemStackComponentizationFix
- 类型:public class
- 包:net.minecraft.util.datafix.fixes
- 源码路径:src/main/java/net/minecraft/util/datafix/fixes/ItemStackComponentizationFix.java
- 起始行号:L28
- 继承:DataFix
- 职责:
TODO
字段/常量
-
HIDE_ENCHANTMENTS- 类型:
int - 修饰符:
private static final - 源码定位:
L29 - 说明:
TODO
- 类型:
-
HIDE_MODIFIERS- 类型:
int - 修饰符:
private static final - 源码定位:
L30 - 说明:
TODO
- 类型:
-
HIDE_UNBREAKABLE- 类型:
int - 修饰符:
private static final - 源码定位:
L31 - 说明:
TODO
- 类型:
-
HIDE_CAN_DESTROY- 类型:
int - 修饰符:
private static final - 源码定位:
L32 - 说明:
TODO
- 类型:
-
HIDE_CAN_PLACE- 类型:
int - 修饰符:
private static final - 源码定位:
L33 - 说明:
TODO
- 类型:
-
HIDE_ADDITIONAL- 类型:
int - 修饰符:
private static final - 源码定位:
L34 - 说明:
TODO
- 类型:
-
HIDE_DYE- 类型:
int - 修饰符:
private static final - 源码定位:
L35 - 说明:
TODO
- 类型:
-
HIDE_UPGRADES- 类型:
int - 修饰符:
private static final - 源码定位:
L36 - 说明:
TODO
- 类型:
-
POTION_HOLDER_IDS- 类型:
Set<String> - 修饰符:
private static final - 源码定位:
L37 - 说明:
TODO
- 类型:
-
BUCKETED_MOB_IDS- 类型:
Set<String> - 修饰符:
private static final - 源码定位:
L40 - 说明:
TODO
- 类型:
-
BUCKETED_MOB_TAGS- 类型:
List<String> - 修饰符:
private static final - 源码定位:
L48 - 说明:
TODO
- 类型:
-
BOOLEAN_BLOCK_STATE_PROPERTIES- 类型:
Set<String> - 修饰符:
private static final - 源码定位:
L51 - 说明:
TODO
- 类型:
-
PROPERTY_SPLITTER- 类型:
Splitter - 修饰符:
private static final - 源码定位:
L100 - 说明:
TODO
- 类型:
内部类/嵌套类型
net.minecraft.util.datafix.fixes.ItemStackComponentizationFix.ItemStackData- 类型:
class - 修饰符:
private static - 源码定位:
L709 - 说明:
TODO
- 类型:
构造器
public ItemStackComponentizationFix(Schema outputSchema) @ L102
- 构造器名:ItemStackComponentizationFix
- 源码定位:L102
- 修饰符:public
参数:
- outputSchema: Schema
说明:
TODO
方法
下面的方法块按源码顺序生成。
private static void fixItemStack(ItemStackComponentizationFix.ItemStackData itemStack, Dynamic<?> dynamic) @ L106
- 方法名:fixItemStack
- 源码定位:L106
- 返回类型:void
- 修饰符:private static
参数:
- itemStack: ItemStackComponentizationFix.ItemStackData
- dynamic: Dynamic<?>
说明:
TODO
private static Dynamic<?> fixBlockStateTag(Dynamic<?> blockStateTag) @ L222
- 方法名:fixBlockStateTag
- 源码定位:L222
- 返回类型:Dynamic<?>
- 修饰符:private static
参数:
- blockStateTag: Dynamic<?>
说明:
TODO
private static Dynamic<?> fixDisplay(ItemStackComponentizationFix.ItemStackData itemStack, Dynamic<?> display, int hideFlags) @ L238
- 方法名:fixDisplay
- 源码定位:L238
- 返回类型:Dynamic<?>
- 修饰符:private static
参数:
- itemStack: ItemStackComponentizationFix.ItemStackData
- display: Dynamic<?>
- hideFlags: int
说明:
TODO
private static <T> Dynamic<T> fixBlockEntityTag(ItemStackComponentizationFix.ItemStackData itemStack, Dynamic<T> blockEntity, String id) @ L274
- 方法名:fixBlockEntityTag
- 源码定位:L274
- 返回类型:
Dynamic - 修饰符:private static
参数:
- itemStack: ItemStackComponentizationFix.ItemStackData
- blockEntity: Dynamic
- id: String
说明:
TODO
private static void fixEnchantments(ItemStackComponentizationFix.ItemStackData itemStack, Dynamic<?> dynamic, String key, String componentType, boolean hideInTooltip) @ L335
- 方法名:fixEnchantments
- 源码定位:L335
- 返回类型:void
- 修饰符:private static
参数:
- itemStack: ItemStackComponentizationFix.ItemStackData
- dynamic: Dynamic<?>
- key: String
- componentType: String
- hideInTooltip: boolean
说明:
TODO
private static Optional<Pair<String,Integer>> parseEnchantment(Dynamic<?> entry) @ L365
- 方法名:parseEnchantment
- 源码定位:L365
- 返回类型:Optional<Pair<String,Integer>>
- 修饰符:private static
参数:
- entry: Dynamic<?>
说明:
TODO
private static void fixAdventureModeChecks(ItemStackComponentizationFix.ItemStackData itemStack, Dynamic<?> dynamic, int hideFlags) @ L369
- 方法名:fixAdventureModeChecks
- 源码定位:L369
- 返回类型:void
- 修饰符:private static
参数:
- itemStack: ItemStackComponentizationFix.ItemStackData
- dynamic: Dynamic<?>
- hideFlags: int
说明:
TODO
private static void fixBlockStatePredicates(ItemStackComponentizationFix.ItemStackData itemStack, Dynamic<?> dynamic, String tag, String componentId, boolean hideInTooltip) @ L374
- 方法名:fixBlockStatePredicates
- 源码定位:L374
- 返回类型:void
- 修饰符:private static
参数:
- itemStack: ItemStackComponentizationFix.ItemStackData
- dynamic: Dynamic<?>
- tag: String
- componentId: String
- hideInTooltip: boolean
说明:
TODO
private static Dynamic<?> fixBlockStatePredicate(Dynamic<?> dynamic, String string) @ L398
- 方法名:fixBlockStatePredicate
- 源码定位:L398
- 返回类型:Dynamic<?>
- 修饰符:private static
参数:
- dynamic: Dynamic<?>
- string: String
说明:
TODO
private static void fixAttributeModifiers(ItemStackComponentizationFix.ItemStackData itemStack, Dynamic<?> dynamic, int hideFlags) @ L436
- 方法名:fixAttributeModifiers
- 源码定位:L436
- 返回类型:void
- 修饰符:private static
参数:
- itemStack: ItemStackComponentizationFix.ItemStackData
- dynamic: Dynamic<?>
- hideFlags: int
说明:
TODO
private static Dynamic<?> fixAttributeModifier(Dynamic<?> input) @ L450
- 方法名:fixAttributeModifier
- 源码定位:L450
- 返回类型:Dynamic<?>
- 修饰符:private static
参数:
- input: Dynamic<?>
说明:
TODO
private static Pair<Dynamic<?>,Dynamic<?>> fixMapDecoration(Dynamic<?> decoration) @ L469
- 方法名:fixMapDecoration
- 源码定位:L469
- 返回类型:Pair<Dynamic,Dynamic>
- 修饰符:private static
参数:
- decoration: Dynamic<?>
说明:
TODO
private static String fixMapDecorationType(int id) @ L479
- 方法名:fixMapDecorationType
- 源码定位:L479
- 返回类型:String
- 修饰符:private static
参数:
- id: int
说明:
TODO
private static void fixPotionContents(ItemStackComponentizationFix.ItemStackData itemStack, Dynamic<?> dynamic) @ L518
- 方法名:fixPotionContents
- 源码定位:L518
- 返回类型:void
- 修饰符:private static
参数:
- itemStack: ItemStackComponentizationFix.ItemStackData
- dynamic: Dynamic<?>
说明:
TODO
private static void fixWritableBook(ItemStackComponentizationFix.ItemStackData itemStack, Dynamic<?> dynamic) @ L532
- 方法名:fixWritableBook
- 源码定位:L532
- 返回类型:void
- 修饰符:private static
参数:
- itemStack: ItemStackComponentizationFix.ItemStackData
- dynamic: Dynamic<?>
说明:
TODO
private static void fixWrittenBook(ItemStackComponentizationFix.ItemStackData itemStack, Dynamic<?> dynamic) @ L539
- 方法名:fixWrittenBook
- 源码定位:L539
- 返回类型:void
- 修饰符:private static
参数:
- itemStack: ItemStackComponentizationFix.ItemStackData
- dynamic: Dynamic<?>
说明:
TODO
private static Dynamic<?> fixBookPages(ItemStackComponentizationFix.ItemStackData itemStack, Dynamic<?> dynamic) @ L555
- 方法名:fixBookPages
- 源码定位:L555
- 返回类型:Dynamic<?>
- 修饰符:private static
参数:
- itemStack: ItemStackComponentizationFix.ItemStackData
- dynamic: Dynamic<?>
说明:
TODO
private static Dynamic<?> createFilteredText(Dynamic<?> dynamic, String text, Optional<String> filtered) @ L573
- 方法名:createFilteredText
- 源码定位:L573
- 返回类型:Dynamic<?>
- 修饰符:private static
参数:
- dynamic: Dynamic<?>
- text: String
- filtered: Optional
说明:
TODO
private static void fixBucketedMobData(ItemStackComponentizationFix.ItemStackData itemStack, Dynamic<?> dynamic) @ L582
- 方法名:fixBucketedMobData
- 源码定位:L582
- 返回类型:void
- 修饰符:private static
参数:
- itemStack: ItemStackComponentizationFix.ItemStackData
- dynamic: Dynamic<?>
说明:
TODO
private static void fixLodestoneTracker(ItemStackComponentizationFix.ItemStackData itemStack, Dynamic<?> dynamic) @ L594
- 方法名:fixLodestoneTracker
- 源码定位:L594
- 返回类型:void
- 修饰符:private static
参数:
- itemStack: ItemStackComponentizationFix.ItemStackData
- dynamic: Dynamic<?>
说明:
TODO
private static void fixFireworkStar(ItemStackComponentizationFix.ItemStackData itemStack) @ L614
- 方法名:fixFireworkStar
- 源码定位:L614
- 返回类型:void
- 修饰符:private static
参数:
- itemStack: ItemStackComponentizationFix.ItemStackData
说明:
TODO
private static void fixFireworkRocket(ItemStackComponentizationFix.ItemStackData itemStack) @ L621
- 方法名:fixFireworkRocket
- 源码定位:L621
- 返回类型:void
- 修饰符:private static
参数:
- itemStack: ItemStackComponentizationFix.ItemStackData
说明:
TODO
private static Dynamic<?> fixFireworkExplosion(Dynamic<?> explosion) @ L637
- 方法名:fixFireworkExplosion
- 源码定位:L637
- 返回类型:Dynamic<?>
- 修饰符:private static
参数:
- explosion: Dynamic<?>
说明:
TODO
public static Dynamic<?> fixProfile(Dynamic<?> dynamic) @ L651
- 方法名:fixProfile
- 源码定位:L651
- 返回类型:Dynamic<?>
- 修饰符:public static
参数:
- dynamic: Dynamic<?>
说明:
TODO
private static boolean isValidPlayerName(String name) @ L676
- 方法名:isValidPlayerName
- 源码定位:L676
- 返回类型:boolean
- 修饰符:private static
参数:
- name: String
说明:
TODO
private static Dynamic<?> fixProfileProperties(OptionalDynamic<?> dynamic) @ L680
- 方法名:fixProfileProperties
- 源码定位:L680
- 返回类型:Dynamic<?>
- 修饰符:private static
参数:
- dynamic: OptionalDynamic<?>
说明:
TODO
protected TypeRewriteRule makeRule() @ L693
- 方法名:makeRule
- 源码定位:L693
- 返回类型:TypeRewriteRule
- 修饰符:protected
参数:
- 无
说明:
TODO
代码
public class ItemStackComponentizationFix extends DataFix {
private static final int HIDE_ENCHANTMENTS = 1;
private static final int HIDE_MODIFIERS = 2;
private static final int HIDE_UNBREAKABLE = 4;
private static final int HIDE_CAN_DESTROY = 8;
private static final int HIDE_CAN_PLACE = 16;
private static final int HIDE_ADDITIONAL = 32;
private static final int HIDE_DYE = 64;
private static final int HIDE_UPGRADES = 128;
private static final Set<String> POTION_HOLDER_IDS = Set.of(
"minecraft:potion", "minecraft:splash_potion", "minecraft:lingering_potion", "minecraft:tipped_arrow"
);
private static final Set<String> BUCKETED_MOB_IDS = Set.of(
"minecraft:pufferfish_bucket",
"minecraft:salmon_bucket",
"minecraft:cod_bucket",
"minecraft:tropical_fish_bucket",
"minecraft:axolotl_bucket",
"minecraft:tadpole_bucket"
);
private static final List<String> BUCKETED_MOB_TAGS = List.of(
"NoAI", "Silent", "NoGravity", "Glowing", "Invulnerable", "Health", "Age", "Variant", "HuntingCooldown", "BucketVariantTag"
);
private static final Set<String> BOOLEAN_BLOCK_STATE_PROPERTIES = Set.of(
"attached",
"bottom",
"conditional",
"disarmed",
"drag",
"enabled",
"extended",
"eye",
"falling",
"hanging",
"has_bottle_0",
"has_bottle_1",
"has_bottle_2",
"has_record",
"has_book",
"inverted",
"in_wall",
"lit",
"locked",
"occupied",
"open",
"persistent",
"powered",
"short",
"signal_fire",
"snowy",
"triggered",
"unstable",
"waterlogged",
"berries",
"bloom",
"shrieking",
"can_summon",
"up",
"down",
"north",
"east",
"south",
"west",
"slot_0_occupied",
"slot_1_occupied",
"slot_2_occupied",
"slot_3_occupied",
"slot_4_occupied",
"slot_5_occupied",
"cracked",
"crafting"
);
private static final Splitter PROPERTY_SPLITTER = Splitter.on(',');
public ItemStackComponentizationFix(Schema outputSchema) {
super(outputSchema, true);
}
private static void fixItemStack(ItemStackComponentizationFix.ItemStackData itemStack, Dynamic<?> dynamic) {
int hideFlags = itemStack.removeTag("HideFlags").asInt(0);
itemStack.moveTagToComponent("Damage", "minecraft:damage", dynamic.createInt(0));
itemStack.moveTagToComponent("RepairCost", "minecraft:repair_cost", dynamic.createInt(0));
itemStack.moveTagToComponent("CustomModelData", "minecraft:custom_model_data");
itemStack.removeTag("BlockStateTag")
.result()
.ifPresent(blockStateTag -> itemStack.setComponent("minecraft:block_state", fixBlockStateTag((Dynamic<?>)blockStateTag)));
itemStack.moveTagToComponent("EntityTag", "minecraft:entity_data");
itemStack.fixSubTag("BlockEntityTag", false, blockEntityTag -> {
String id = NamespacedSchema.ensureNamespaced(blockEntityTag.get("id").asString(""));
blockEntityTag = fixBlockEntityTag(itemStack, blockEntityTag, id);
Dynamic<?> withoutId = blockEntityTag.remove("id");
return withoutId.equals(blockEntityTag.emptyMap()) ? withoutId : blockEntityTag;
});
itemStack.moveTagToComponent("BlockEntityTag", "minecraft:block_entity_data");
if (itemStack.removeTag("Unbreakable").asBoolean(false)) {
Dynamic<?> component = dynamic.emptyMap();
if ((hideFlags & 4) != 0) {
component = component.set("show_in_tooltip", dynamic.createBoolean(false));
}
itemStack.setComponent("minecraft:unbreakable", component);
}
fixEnchantments(itemStack, dynamic, "Enchantments", "minecraft:enchantments", (hideFlags & 1) != 0);
if (itemStack.is("minecraft:enchanted_book")) {
fixEnchantments(itemStack, dynamic, "StoredEnchantments", "minecraft:stored_enchantments", (hideFlags & 32) != 0);
}
itemStack.fixSubTag("display", false, display -> fixDisplay(itemStack, display, hideFlags));
fixAdventureModeChecks(itemStack, dynamic, hideFlags);
fixAttributeModifiers(itemStack, dynamic, hideFlags);
Optional<? extends Dynamic<?>> trim = itemStack.removeTag("Trim").result();
if (trim.isPresent()) {
Dynamic<?> fixedTrim = (Dynamic<?>)trim.get();
if ((hideFlags & 128) != 0) {
fixedTrim = fixedTrim.set("show_in_tooltip", fixedTrim.createBoolean(false));
}
itemStack.setComponent("minecraft:trim", fixedTrim);
}
if ((hideFlags & 32) != 0) {
itemStack.setComponent("minecraft:hide_additional_tooltip", dynamic.emptyMap());
}
if (itemStack.is("minecraft:crossbow")) {
itemStack.removeTag("Charged");
itemStack.moveTagToComponent("ChargedProjectiles", "minecraft:charged_projectiles", dynamic.createList(Stream.empty()));
}
if (itemStack.is("minecraft:bundle")) {
itemStack.moveTagToComponent("Items", "minecraft:bundle_contents", dynamic.createList(Stream.empty()));
}
if (itemStack.is("minecraft:filled_map")) {
itemStack.moveTagToComponent("map", "minecraft:map_id");
Map<? extends Dynamic<?>, ? extends Dynamic<?>> decorations = itemStack.removeTag("Decorations")
.asStream()
.map(ItemStackComponentizationFix::fixMapDecoration)
.collect(Collectors.toMap(Pair::getFirst, Pair::getSecond, (first, second) -> first));
if (!decorations.isEmpty()) {
itemStack.setComponent("minecraft:map_decorations", dynamic.createMap(decorations));
}
}
if (itemStack.is(POTION_HOLDER_IDS)) {
fixPotionContents(itemStack, dynamic);
}
if (itemStack.is("minecraft:writable_book")) {
fixWritableBook(itemStack, dynamic);
}
if (itemStack.is("minecraft:written_book")) {
fixWrittenBook(itemStack, dynamic);
}
if (itemStack.is("minecraft:suspicious_stew")) {
itemStack.moveTagToComponent("effects", "minecraft:suspicious_stew_effects");
}
if (itemStack.is("minecraft:debug_stick")) {
itemStack.moveTagToComponent("DebugProperty", "minecraft:debug_stick_state");
}
if (itemStack.is(BUCKETED_MOB_IDS)) {
fixBucketedMobData(itemStack, dynamic);
}
if (itemStack.is("minecraft:goat_horn")) {
itemStack.moveTagToComponent("instrument", "minecraft:instrument");
}
if (itemStack.is("minecraft:knowledge_book")) {
itemStack.moveTagToComponent("Recipes", "minecraft:recipes");
}
if (itemStack.is("minecraft:compass")) {
fixLodestoneTracker(itemStack, dynamic);
}
if (itemStack.is("minecraft:firework_rocket")) {
fixFireworkRocket(itemStack);
}
if (itemStack.is("minecraft:firework_star")) {
fixFireworkStar(itemStack);
}
if (itemStack.is("minecraft:player_head")) {
itemStack.removeTag("SkullOwner").result().ifPresent(skullOwner -> itemStack.setComponent("minecraft:profile", fixProfile((Dynamic<?>)skullOwner)));
}
}
private static Dynamic<?> fixBlockStateTag(Dynamic<?> blockStateTag) {
return DataFixUtils.orElse(blockStateTag.asMapOpt().result().map(entries -> entries.collect(Collectors.toMap(Pair::getFirst, entry -> {
String key = ((Dynamic)entry.getFirst()).asString("");
Dynamic<?> value = (Dynamic<?>)entry.getSecond();
if (BOOLEAN_BLOCK_STATE_PROPERTIES.contains(key)) {
Optional<Boolean> bool = value.asBoolean().result();
if (bool.isPresent()) {
return value.createString(String.valueOf(bool.get()));
}
}
Optional<Number> number = value.asNumber().result();
return number.isPresent() ? value.createString(number.get().toString()) : value;
}))).map(blockStateTag::createMap), blockStateTag);
}
private static Dynamic<?> fixDisplay(ItemStackComponentizationFix.ItemStackData itemStack, Dynamic<?> display, int hideFlags) {
display.get("Name")
.result()
.filter(LegacyComponentDataFixUtils::isStrictlyValidJson)
.ifPresent(name -> itemStack.setComponent("minecraft:custom_name", (Dynamic<?>)name));
OptionalDynamic<?> lore = display.get("Lore");
if (lore.result().isPresent()) {
itemStack.setComponent(
"minecraft:lore", display.createList(display.get("Lore").asStream().filter(LegacyComponentDataFixUtils::isStrictlyValidJson))
);
}
Optional<Integer> color = display.get("color").asNumber().result().map(Number::intValue);
boolean hideDye = (hideFlags & 64) != 0;
if (color.isPresent() || hideDye) {
Dynamic<?> dyedColor = display.emptyMap().set("rgb", display.createInt(color.orElse(10511680)));
if (hideDye) {
dyedColor = dyedColor.set("show_in_tooltip", display.createBoolean(false));
}
itemStack.setComponent("minecraft:dyed_color", dyedColor);
}
Optional<String> locName = display.get("LocName").asString().result();
if (locName.isPresent()) {
itemStack.setComponent("minecraft:item_name", LegacyComponentDataFixUtils.createTranslatableComponent(display.getOps(), locName.get()));
}
if (itemStack.is("minecraft:filled_map")) {
itemStack.setComponent("minecraft:map_color", display.get("MapColor"));
display = display.remove("MapColor");
}
return display.remove("Name").remove("Lore").remove("color").remove("LocName");
}
private static <T> Dynamic<T> fixBlockEntityTag(ItemStackComponentizationFix.ItemStackData itemStack, Dynamic<T> blockEntity, String id) {
itemStack.setComponent("minecraft:lock", blockEntity.get("Lock"));
blockEntity = blockEntity.remove("Lock");
Optional<Dynamic<T>> lootTable = blockEntity.get("LootTable").result();
if (lootTable.isPresent()) {
Dynamic<T> containerLoot = blockEntity.emptyMap().set("loot_table", lootTable.get());
long seed = blockEntity.get("LootTableSeed").asLong(0L);
if (seed != 0L) {
containerLoot = containerLoot.set("seed", blockEntity.createLong(seed));
}
itemStack.setComponent("minecraft:container_loot", containerLoot);
blockEntity = blockEntity.remove("LootTable").remove("LootTableSeed");
}
return switch (id) {
case "minecraft:skull" -> {
itemStack.setComponent("minecraft:note_block_sound", blockEntity.get("note_block_sound"));
yield blockEntity.remove("note_block_sound");
}
case "minecraft:decorated_pot" -> {
itemStack.setComponent("minecraft:pot_decorations", blockEntity.get("sherds"));
Optional<Dynamic<T>> item = blockEntity.get("item").result();
if (item.isPresent()) {
itemStack.setComponent(
"minecraft:container",
blockEntity.createList(Stream.of(blockEntity.emptyMap().set("slot", blockEntity.createInt(0)).set("item", item.get())))
);
}
yield blockEntity.remove("sherds").remove("item");
}
case "minecraft:banner" -> {
itemStack.setComponent("minecraft:banner_patterns", blockEntity.get("patterns"));
Optional<Number> base = blockEntity.get("Base").asNumber().result();
if (base.isPresent()) {
itemStack.setComponent("minecraft:base_color", blockEntity.createString(ExtraDataFixUtils.dyeColorIdToName(base.get().intValue())));
}
yield blockEntity.remove("patterns").remove("Base");
}
case "minecraft:shulker_box", "minecraft:chest", "minecraft:trapped_chest", "minecraft:furnace", "minecraft:ender_chest", "minecraft:dispenser", "minecraft:dropper", "minecraft:brewing_stand", "minecraft:hopper", "minecraft:barrel", "minecraft:smoker", "minecraft:blast_furnace", "minecraft:campfire", "minecraft:chiseled_bookshelf", "minecraft:crafter" -> {
List<Dynamic<T>> items = blockEntity.get("Items")
.asList(
dynamic -> dynamic.emptyMap()
.set("slot", dynamic.createInt(dynamic.get("Slot").asByte((byte)0) & 255))
.set("item", dynamic.remove("Slot"))
);
if (!items.isEmpty()) {
itemStack.setComponent("minecraft:container", blockEntity.createList(items.stream()));
}
yield blockEntity.remove("Items");
}
case "minecraft:beehive" -> {
itemStack.setComponent("minecraft:bees", blockEntity.get("bees"));
yield blockEntity.remove("bees");
}
default -> blockEntity;
};
}
private static void fixEnchantments(
ItemStackComponentizationFix.ItemStackData itemStack, Dynamic<?> dynamic, String key, String componentType, boolean hideInTooltip
) {
OptionalDynamic<?> rawEnchantments = itemStack.removeTag(key);
List<Pair<String, Integer>> enchantments = rawEnchantments.asList(Function.identity())
.stream()
.flatMap(enchantmentx -> parseEnchantment(enchantmentx).stream())
.filter(enchantmentx -> (Integer)enchantmentx.getSecond() > 0)
.toList();
if (!enchantments.isEmpty() || hideInTooltip) {
Dynamic<?> component = dynamic.emptyMap();
Dynamic<?> levels = dynamic.emptyMap();
for (Pair<String, Integer> enchantment : enchantments) {
levels = levels.set(enchantment.getFirst(), dynamic.createInt(enchantment.getSecond()));
}
component = component.set("levels", levels);
if (hideInTooltip) {
component = component.set("show_in_tooltip", dynamic.createBoolean(false));
}
itemStack.setComponent(componentType, component);
}
if (rawEnchantments.result().isPresent() && enchantments.isEmpty()) {
itemStack.setComponent("minecraft:enchantment_glint_override", dynamic.createBoolean(true));
}
}
private static Optional<Pair<String, Integer>> parseEnchantment(Dynamic<?> entry) {
return entry.get("id").asString().apply2stable((id, level) -> Pair.of(id, Mth.clamp(level.intValue(), 0, 255)), entry.get("lvl").asNumber()).result();
}
private static void fixAdventureModeChecks(ItemStackComponentizationFix.ItemStackData itemStack, Dynamic<?> dynamic, int hideFlags) {
fixBlockStatePredicates(itemStack, dynamic, "CanDestroy", "minecraft:can_break", (hideFlags & 8) != 0);
fixBlockStatePredicates(itemStack, dynamic, "CanPlaceOn", "minecraft:can_place_on", (hideFlags & 16) != 0);
}
private static void fixBlockStatePredicates(
ItemStackComponentizationFix.ItemStackData itemStack, Dynamic<?> dynamic, String tag, String componentId, boolean hideInTooltip
) {
Optional<? extends Dynamic<?>> oldPredicate = itemStack.removeTag(tag).result();
if (!oldPredicate.isEmpty()) {
Dynamic<?> component = dynamic.emptyMap()
.set(
"predicates",
dynamic.createList(
oldPredicate.get()
.asStream()
.map(
value -> DataFixUtils.orElse(value.asString().map(string -> fixBlockStatePredicate((Dynamic<?>)value, string)).result(), value)
)
)
);
if (hideInTooltip) {
component = component.set("show_in_tooltip", dynamic.createBoolean(false));
}
itemStack.setComponent(componentId, component);
}
}
private static Dynamic<?> fixBlockStatePredicate(Dynamic<?> dynamic, String string) {
int startProperties = string.indexOf(91);
int startNbt = string.indexOf(123);
int blockNameEnd = string.length();
if (startProperties != -1) {
blockNameEnd = startProperties;
}
if (startNbt != -1) {
blockNameEnd = Math.min(blockNameEnd, startNbt);
}
String blockOrTagName = string.substring(0, blockNameEnd);
Dynamic<?> predicate = dynamic.emptyMap().set("blocks", dynamic.createString(blockOrTagName.trim()));
int endProperties = string.indexOf(93);
if (startProperties != -1 && endProperties != -1) {
Dynamic<?> properties = dynamic.emptyMap();
for (String property : PROPERTY_SPLITTER.split(string.substring(startProperties + 1, endProperties))) {
int assignment = property.indexOf(61);
if (assignment != -1) {
String key = property.substring(0, assignment).trim();
String value = property.substring(assignment + 1).trim();
properties = properties.set(key, dynamic.createString(value));
}
}
predicate = predicate.set("state", properties);
}
int endNbt = string.indexOf(125);
if (startNbt != -1 && endNbt != -1) {
predicate = predicate.set("nbt", dynamic.createString(string.substring(startNbt, endNbt + 1)));
}
return predicate;
}
private static void fixAttributeModifiers(ItemStackComponentizationFix.ItemStackData itemStack, Dynamic<?> dynamic, int hideFlags) {
OptionalDynamic<?> attributeModifiersField = itemStack.removeTag("AttributeModifiers");
if (!attributeModifiersField.result().isEmpty()) {
boolean hideInTooltip = (hideFlags & 2) != 0;
List<? extends Dynamic<?>> attributeModifiers = attributeModifiersField.asList(ItemStackComponentizationFix::fixAttributeModifier);
Dynamic<?> component = dynamic.emptyMap().set("modifiers", dynamic.createList(attributeModifiers.stream()));
if (hideInTooltip) {
component = component.set("show_in_tooltip", dynamic.createBoolean(false));
}
itemStack.setComponent("minecraft:attribute_modifiers", component);
}
}
private static Dynamic<?> fixAttributeModifier(Dynamic<?> input) {
Dynamic<?> result = input.emptyMap()
.set("name", input.createString(""))
.set("amount", input.createDouble(0.0))
.set("operation", input.createString("add_value"));
result = Dynamic.copyField(input, "AttributeName", result, "type");
result = Dynamic.copyField(input, "Slot", result, "slot");
result = Dynamic.copyField(input, "UUID", result, "uuid");
result = Dynamic.copyField(input, "Name", result, "name");
result = Dynamic.copyField(input, "Amount", result, "amount");
return Dynamic.copyAndFixField(input, "Operation", result, "operation", operation -> {
return operation.createString(switch (operation.asInt(0)) {
case 1 -> "add_multiplied_base";
case 2 -> "add_multiplied_total";
default -> "add_value";
});
});
}
private static Pair<Dynamic<?>, Dynamic<?>> fixMapDecoration(Dynamic<?> decoration) {
Dynamic<?> id = DataFixUtils.orElseGet(decoration.get("id").result(), () -> decoration.createString(""));
Dynamic<?> value = decoration.emptyMap()
.set("type", decoration.createString(fixMapDecorationType(decoration.get("type").asInt(0))))
.set("x", decoration.createDouble(decoration.get("x").asDouble(0.0)))
.set("z", decoration.createDouble(decoration.get("z").asDouble(0.0)))
.set("rotation", decoration.createFloat((float)decoration.get("rot").asDouble(0.0)));
return Pair.of(id, value);
}
private static String fixMapDecorationType(int id) {
return switch (id) {
case 1 -> "frame";
case 2 -> "red_marker";
case 3 -> "blue_marker";
case 4 -> "target_x";
case 5 -> "target_point";
case 6 -> "player_off_map";
case 7 -> "player_off_limits";
case 8 -> "mansion";
case 9 -> "monument";
case 10 -> "banner_white";
case 11 -> "banner_orange";
case 12 -> "banner_magenta";
case 13 -> "banner_light_blue";
case 14 -> "banner_yellow";
case 15 -> "banner_lime";
case 16 -> "banner_pink";
case 17 -> "banner_gray";
case 18 -> "banner_light_gray";
case 19 -> "banner_cyan";
case 20 -> "banner_purple";
case 21 -> "banner_blue";
case 22 -> "banner_brown";
case 23 -> "banner_green";
case 24 -> "banner_red";
case 25 -> "banner_black";
case 26 -> "red_x";
case 27 -> "village_desert";
case 28 -> "village_plains";
case 29 -> "village_savanna";
case 30 -> "village_snowy";
case 31 -> "village_taiga";
case 32 -> "jungle_temple";
case 33 -> "swamp_hut";
default -> "player";
};
}
private static void fixPotionContents(ItemStackComponentizationFix.ItemStackData itemStack, Dynamic<?> dynamic) {
Dynamic<?> component = dynamic.emptyMap();
Optional<String> potion = itemStack.removeTag("Potion").asString().result().filter(id -> !id.equals("minecraft:empty"));
if (potion.isPresent()) {
component = component.set("potion", dynamic.createString(potion.get()));
}
component = itemStack.moveTagInto("CustomPotionColor", component, "custom_color");
component = itemStack.moveTagInto("custom_potion_effects", component, "custom_effects");
if (!component.equals(dynamic.emptyMap())) {
itemStack.setComponent("minecraft:potion_contents", component);
}
}
private static void fixWritableBook(ItemStackComponentizationFix.ItemStackData itemStack, Dynamic<?> dynamic) {
Dynamic<?> pages = fixBookPages(itemStack, dynamic);
if (pages != null) {
itemStack.setComponent("minecraft:writable_book_content", dynamic.emptyMap().set("pages", pages));
}
}
private static void fixWrittenBook(ItemStackComponentizationFix.ItemStackData itemStack, Dynamic<?> dynamic) {
Dynamic<?> pages = fixBookPages(itemStack, dynamic);
String title = itemStack.removeTag("title").asString("");
Optional<String> filteredTitle = itemStack.removeTag("filtered_title").asString().result();
Dynamic<?> component = dynamic.emptyMap();
component = component.set("title", createFilteredText(dynamic, title, filteredTitle));
component = itemStack.moveTagInto("author", component, "author");
component = itemStack.moveTagInto("resolved", component, "resolved");
component = itemStack.moveTagInto("generation", component, "generation");
if (pages != null) {
component = component.set("pages", pages);
}
itemStack.setComponent("minecraft:written_book_content", component);
}
private static @Nullable Dynamic<?> fixBookPages(ItemStackComponentizationFix.ItemStackData itemStack, Dynamic<?> dynamic) {
List<String> pages = itemStack.removeTag("pages").asList(pagex -> pagex.asString(""));
Map<String, String> filteredPages = itemStack.removeTag("filtered_pages").asMap(key -> key.asString("0"), pagex -> pagex.asString(""));
if (pages.isEmpty()) {
return null;
} else {
List<Dynamic<?>> fixedPages = new ArrayList<>(pages.size());
for (int i = 0; i < pages.size(); i++) {
String page = pages.get(i);
String filteredPage = filteredPages.get(String.valueOf(i));
fixedPages.add(createFilteredText(dynamic, page, Optional.ofNullable(filteredPage)));
}
return dynamic.createList(fixedPages.stream());
}
}
private static Dynamic<?> createFilteredText(Dynamic<?> dynamic, String text, Optional<String> filtered) {
Dynamic<?> fixedPage = dynamic.emptyMap().set("raw", dynamic.createString(text));
if (filtered.isPresent()) {
fixedPage = fixedPage.set("filtered", dynamic.createString(filtered.get()));
}
return fixedPage;
}
private static void fixBucketedMobData(ItemStackComponentizationFix.ItemStackData itemStack, Dynamic<?> dynamic) {
Dynamic<?> data = dynamic.emptyMap();
for (String key : BUCKETED_MOB_TAGS) {
data = itemStack.moveTagInto(key, data, key);
}
if (!data.equals(dynamic.emptyMap())) {
itemStack.setComponent("minecraft:bucket_entity_data", data);
}
}
private static void fixLodestoneTracker(ItemStackComponentizationFix.ItemStackData itemStack, Dynamic<?> dynamic) {
Optional<? extends Dynamic<?>> lodestonePos = itemStack.removeTag("LodestonePos").result();
Optional<? extends Dynamic<?>> lodestoneDimension = itemStack.removeTag("LodestoneDimension").result();
if (!lodestonePos.isEmpty() || !lodestoneDimension.isEmpty()) {
boolean lodestoneTracked = itemStack.removeTag("LodestoneTracked").asBoolean(true);
Dynamic<?> component = dynamic.emptyMap();
if (lodestonePos.isPresent() && lodestoneDimension.isPresent()) {
component = component.set(
"target", dynamic.emptyMap().set("pos", (Dynamic<?>)lodestonePos.get()).set("dimension", (Dynamic<?>)lodestoneDimension.get())
);
}
if (!lodestoneTracked) {
component = component.set("tracked", dynamic.createBoolean(false));
}
itemStack.setComponent("minecraft:lodestone_tracker", component);
}
}
private static void fixFireworkStar(ItemStackComponentizationFix.ItemStackData itemStack) {
itemStack.fixSubTag("Explosion", true, explosion -> {
itemStack.setComponent("minecraft:firework_explosion", fixFireworkExplosion(explosion));
return explosion.remove("Type").remove("Colors").remove("FadeColors").remove("Trail").remove("Flicker");
});
}
private static void fixFireworkRocket(ItemStackComponentizationFix.ItemStackData itemStack) {
itemStack.fixSubTag(
"Fireworks",
true,
fireworks -> {
Stream<? extends Dynamic<?>> explosions = fireworks.get("Explosions").asStream().map(ItemStackComponentizationFix::fixFireworkExplosion);
int flight = fireworks.get("Flight").asInt(0);
itemStack.setComponent(
"minecraft:fireworks",
fireworks.emptyMap().set("explosions", fireworks.createList(explosions)).set("flight_duration", fireworks.createByte((byte)flight))
);
return fireworks.remove("Explosions").remove("Flight");
}
);
}
private static Dynamic<?> fixFireworkExplosion(Dynamic<?> explosion) {
explosion = explosion.set("shape", explosion.createString(switch (explosion.get("Type").asInt(0)) {
case 1 -> "large_ball";
case 2 -> "star";
case 3 -> "creeper";
case 4 -> "burst";
default -> "small_ball";
})).remove("Type");
explosion = explosion.renameField("Colors", "colors");
explosion = explosion.renameField("FadeColors", "fade_colors");
explosion = explosion.renameField("Trail", "has_trail");
return explosion.renameField("Flicker", "has_twinkle");
}
public static Dynamic<?> fixProfile(Dynamic<?> dynamic) {
Optional<String> simpleName = dynamic.asString().result();
if (simpleName.isPresent()) {
return isValidPlayerName(simpleName.get()) ? dynamic.emptyMap().set("name", dynamic.createString(simpleName.get())) : dynamic.emptyMap();
} else {
String name = dynamic.get("Name").asString("");
Optional<? extends Dynamic<?>> id = dynamic.get("Id").result();
Dynamic<?> properties = fixProfileProperties(dynamic.get("Properties"));
Dynamic<?> profile = dynamic.emptyMap();
if (isValidPlayerName(name)) {
profile = profile.set("name", dynamic.createString(name));
}
if (id.isPresent()) {
profile = profile.set("id", (Dynamic<?>)id.get());
}
if (properties != null) {
profile = profile.set("properties", properties);
}
return profile;
}
}
private static boolean isValidPlayerName(String name) {
return name.length() > 16 ? false : name.chars().filter(c -> c <= 32 || c >= 127).findAny().isEmpty();
}
private static @Nullable Dynamic<?> fixProfileProperties(OptionalDynamic<?> dynamic) {
Map<String, List<Pair<String, Optional<String>>>> properties = dynamic.asMap(key -> key.asString(""), list -> list.asList(property -> {
String value = property.get("Value").asString("");
Optional<String> signature = property.get("Signature").asString().result();
return Pair.of(value, signature);
}));
return properties.isEmpty() ? null : dynamic.createList(properties.entrySet().stream().flatMap(entry -> entry.getValue().stream().map(pair -> {
Dynamic<?> property = dynamic.emptyMap().set("name", dynamic.createString(entry.getKey())).set("value", dynamic.createString(pair.getFirst()));
Optional<String> signature = pair.getSecond();
return signature.isPresent() ? property.set("signature", dynamic.createString(signature.get())) : property;
})));
}
@Override
protected TypeRewriteRule makeRule() {
return this.writeFixAndRead(
"ItemStack componentization",
this.getInputSchema().getType(References.ITEM_STACK),
this.getOutputSchema().getType(References.ITEM_STACK),
dynamic -> {
Optional<? extends Dynamic<?>> fixedItemStack = ItemStackComponentizationFix.ItemStackData.read(dynamic).map(itemStack -> {
fixItemStack(itemStack, itemStack.tag);
return itemStack.write();
});
return DataFixUtils.orElse(fixedItemStack, dynamic);
}
);
}
private static class ItemStackData {
private final String item;
private final int count;
private Dynamic<?> components;
private final Dynamic<?> remainder;
private Dynamic<?> tag;
private ItemStackData(String item, int count, Dynamic<?> remainder) {
this.item = NamespacedSchema.ensureNamespaced(item);
this.count = count;
this.components = remainder.emptyMap();
this.tag = remainder.get("tag").orElseEmptyMap();
this.remainder = remainder.remove("tag");
}
public static Optional<ItemStackComponentizationFix.ItemStackData> read(Dynamic<?> dynamic) {
return dynamic.get("id")
.asString()
.apply2stable(
(item, count) -> new ItemStackComponentizationFix.ItemStackData(item, count.intValue(), dynamic.remove("id").remove("Count")),
dynamic.get("Count").asNumber()
)
.result();
}
public OptionalDynamic<?> removeTag(String key) {
OptionalDynamic<?> value = this.tag.get(key);
this.tag = this.tag.remove(key);
return value;
}
public void setComponent(String type, Dynamic<?> value) {
this.components = this.components.set(type, value);
}
public void setComponent(String type, OptionalDynamic<?> optionalValue) {
optionalValue.result().ifPresent(value -> this.components = this.components.set(type, (Dynamic<?>)value));
}
public Dynamic<?> moveTagInto(String fromKey, Dynamic<?> target, String toKey) {
Optional<? extends Dynamic<?>> value = this.removeTag(fromKey).result();
return value.isPresent() ? target.set(toKey, (Dynamic<?>)value.get()) : target;
}
public void moveTagToComponent(String key, String type, Dynamic<?> defaultValue) {
Optional<? extends Dynamic<?>> value = this.removeTag(key).result();
if (value.isPresent() && !value.get().equals(defaultValue)) {
this.setComponent(type, (Dynamic<?>)value.get());
}
}
public void moveTagToComponent(String key, String type) {
this.removeTag(key).result().ifPresent(value -> this.setComponent(type, (Dynamic<?>)value));
}
public void fixSubTag(String key, boolean dontFixWhenFieldIsMissing, UnaryOperator<Dynamic<?>> function) {
OptionalDynamic<?> value = this.tag.get(key);
if (!dontFixWhenFieldIsMissing || !value.result().isEmpty()) {
Dynamic<?> map = value.orElseEmptyMap();
map = function.apply(map);
if (map.equals(map.emptyMap())) {
this.tag = this.tag.remove(key);
} else {
this.tag = this.tag.set(key, map);
}
}
}
public Dynamic<?> write() {
Dynamic<?> result = this.tag.emptyMap().set("id", this.tag.createString(this.item)).set("count", this.tag.createInt(this.count));
if (!this.tag.equals(this.tag.emptyMap())) {
this.components = this.components.set("minecraft:custom_data", this.tag);
}
if (!this.components.equals(this.tag.emptyMap())) {
result = result.set("components", this.components);
}
return mergeRemainder(result, this.remainder);
}
private static <T> Dynamic<T> mergeRemainder(Dynamic<T> itemStack, Dynamic<?> remainder) {
DynamicOps<T> ops = itemStack.getOps();
return ops.getMap(itemStack.getValue())
.flatMap(itemStackMap -> ops.mergeToMap(remainder.convert(ops).getValue(), (MapLike<T>)itemStackMap))
.map(merged -> new Dynamic<>(ops, (T)merged))
.result()
.orElse(itemStack);
}
public boolean is(String id) {
return this.item.equals(id);
}
public boolean is(Set<String> ids) {
return ids.contains(this.item);
}
public boolean hasComponent(String id) {
return this.components.get(id).result().isPresent();
}
}
}引用的其他类
-
- 引用位置:
参数
- 引用位置:
-
- 引用位置:
方法调用 - 关联成员:
Mth.clamp()
- 引用位置:
-
- 引用位置:
方法调用 - 关联成员:
ExtraDataFixUtils.dyeColorIdToName()
- 引用位置:
-
- 引用位置:
方法调用 - 关联成员:
LegacyComponentDataFixUtils.createTranslatableComponent()
- 引用位置:
-
- 引用位置:
方法调用 - 关联成员:
NamespacedSchema.ensureNamespaced()
- 引用位置:
-
- 引用位置:
参数/方法调用/返回值 - 关联成员:
Dynamic.copyAndFixField(), Dynamic.copyField()
- 引用位置: