Code/net/minecraft/util/datafix/fixes/ItemStackComponentizationFi...

824 lines
36 KiB
Java
Raw Normal View History

2025-07-01 06:20:03 +00:00
package net.minecraft.util.datafix.fixes;
import com.google.common.base.Splitter;
import com.mojang.datafixers.DataFix;
import com.mojang.datafixers.DataFixUtils;
import com.mojang.datafixers.TypeRewriteRule;
import com.mojang.datafixers.schemas.Schema;
import com.mojang.datafixers.util.Pair;
import com.mojang.serialization.Dynamic;
import com.mojang.serialization.DynamicOps;
import com.mojang.serialization.MapLike;
import com.mojang.serialization.OptionalDynamic;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.Map.Entry;
import java.util.function.Function;
import java.util.function.UnaryOperator;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import javax.annotation.Nullable;
import net.minecraft.util.Mth;
import net.minecraft.util.datafix.ExtraDataFixUtils;
import net.minecraft.util.datafix.LegacyComponentDataFixUtils;
import net.minecraft.util.datafix.schemas.NamespacedSchema;
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 p_331666_) {
super(p_331666_, true);
}
private static void fixItemStack(ItemStackComponentizationFix.ItemStackData p_335726_, Dynamic<?> p_329007_) {
int i = p_335726_.removeTag("HideFlags").asInt(0);
p_335726_.moveTagToComponent("Damage", "minecraft:damage", p_329007_.createInt(0));
p_335726_.moveTagToComponent("RepairCost", "minecraft:repair_cost", p_329007_.createInt(0));
p_335726_.moveTagToComponent("CustomModelData", "minecraft:custom_model_data");
p_335726_.removeTag("BlockStateTag").result().ifPresent(p_333568_ -> p_335726_.setComponent("minecraft:block_state", fixBlockStateTag((Dynamic<?>)p_333568_)));
p_335726_.moveTagToComponent("EntityTag", "minecraft:entity_data");
p_335726_.fixSubTag("BlockEntityTag", false, p_330163_ -> {
String s = NamespacedSchema.ensureNamespaced(p_330163_.get("id").asString(""));
p_330163_ = fixBlockEntityTag(p_335726_, p_330163_, s);
Dynamic<?> dynamic2 = p_330163_.remove("id");
return dynamic2.equals(p_330163_.emptyMap()) ? dynamic2 : p_330163_;
});
p_335726_.moveTagToComponent("BlockEntityTag", "minecraft:block_entity_data");
if (p_335726_.removeTag("Unbreakable").asBoolean(false)) {
Dynamic<?> dynamic = p_329007_.emptyMap();
if ((i & 4) != 0) {
dynamic = dynamic.set("show_in_tooltip", p_329007_.createBoolean(false));
}
p_335726_.setComponent("minecraft:unbreakable", dynamic);
}
fixEnchantments(p_335726_, p_329007_, "Enchantments", "minecraft:enchantments", (i & 1) != 0);
if (p_335726_.is("minecraft:enchanted_book")) {
fixEnchantments(p_335726_, p_329007_, "StoredEnchantments", "minecraft:stored_enchantments", (i & 32) != 0);
}
p_335726_.fixSubTag("display", false, p_332023_ -> fixDisplay(p_335726_, p_332023_, i));
fixAdventureModeChecks(p_335726_, p_329007_, i);
fixAttributeModifiers(p_335726_, p_329007_, i);
Optional<? extends Dynamic<?>> optional = p_335726_.removeTag("Trim").result();
if (optional.isPresent()) {
Dynamic<?> dynamic1 = (Dynamic<?>)optional.get();
if ((i & 128) != 0) {
dynamic1 = dynamic1.set("show_in_tooltip", dynamic1.createBoolean(false));
}
p_335726_.setComponent("minecraft:trim", dynamic1);
}
if ((i & 32) != 0) {
p_335726_.setComponent("minecraft:hide_additional_tooltip", p_329007_.emptyMap());
}
if (p_335726_.is("minecraft:crossbow")) {
p_335726_.removeTag("Charged");
p_335726_.moveTagToComponent("ChargedProjectiles", "minecraft:charged_projectiles", p_329007_.createList(Stream.empty()));
}
if (p_335726_.is("minecraft:bundle")) {
p_335726_.moveTagToComponent("Items", "minecraft:bundle_contents", p_329007_.createList(Stream.empty()));
}
if (p_335726_.is("minecraft:filled_map")) {
p_335726_.moveTagToComponent("map", "minecraft:map_id");
Map<? extends Dynamic<?>, ? extends Dynamic<?>> map = p_335726_.removeTag("Decorations")
.asStream()
.map(ItemStackComponentizationFix::fixMapDecoration)
.collect(Collectors.toMap(Pair::getFirst, Pair::getSecond, (p_328286_, p_333385_) -> p_328286_));
if (!map.isEmpty()) {
p_335726_.setComponent("minecraft:map_decorations", p_329007_.createMap(map));
}
}
if (p_335726_.is(POTION_HOLDER_IDS)) {
fixPotionContents(p_335726_, p_329007_);
}
if (p_335726_.is("minecraft:writable_book")) {
fixWritableBook(p_335726_, p_329007_);
}
if (p_335726_.is("minecraft:written_book")) {
fixWrittenBook(p_335726_, p_329007_);
}
if (p_335726_.is("minecraft:suspicious_stew")) {
p_335726_.moveTagToComponent("effects", "minecraft:suspicious_stew_effects");
}
if (p_335726_.is("minecraft:debug_stick")) {
p_335726_.moveTagToComponent("DebugProperty", "minecraft:debug_stick_state");
}
if (p_335726_.is(BUCKETED_MOB_IDS)) {
fixBucketedMobData(p_335726_, p_329007_);
}
if (p_335726_.is("minecraft:goat_horn")) {
p_335726_.moveTagToComponent("instrument", "minecraft:instrument");
}
if (p_335726_.is("minecraft:knowledge_book")) {
p_335726_.moveTagToComponent("Recipes", "minecraft:recipes");
}
if (p_335726_.is("minecraft:compass")) {
fixLodestoneTracker(p_335726_, p_329007_);
}
if (p_335726_.is("minecraft:firework_rocket")) {
fixFireworkRocket(p_335726_);
}
if (p_335726_.is("minecraft:firework_star")) {
fixFireworkStar(p_335726_);
}
if (p_335726_.is("minecraft:player_head")) {
p_335726_.removeTag("SkullOwner").result().ifPresent(p_328052_ -> p_335726_.setComponent("minecraft:profile", fixProfile((Dynamic<?>)p_328052_)));
}
}
private static Dynamic<?> fixBlockStateTag(Dynamic<?> p_329060_) {
return DataFixUtils.orElse(p_329060_.asMapOpt().result().map(p_331937_ -> p_331937_.collect(Collectors.toMap(Pair::getFirst, p_330078_ -> {
String s = ((Dynamic)p_330078_.getFirst()).asString("");
Dynamic<?> dynamic = (Dynamic<?>)p_330078_.getSecond();
if (BOOLEAN_BLOCK_STATE_PROPERTIES.contains(s)) {
Optional<Boolean> optional = dynamic.asBoolean().result();
if (optional.isPresent()) {
return dynamic.createString(String.valueOf(optional.get()));
}
}
Optional<Number> optional1 = dynamic.asNumber().result();
return optional1.isPresent() ? dynamic.createString(optional1.get().toString()) : dynamic;
}))).map(p_329060_::createMap), p_329060_);
}
private static Dynamic<?> fixDisplay(ItemStackComponentizationFix.ItemStackData p_333136_, Dynamic<?> p_329974_, int p_330088_) {
p_333136_.setComponent("minecraft:custom_name", p_329974_.get("Name"));
p_333136_.setComponent("minecraft:lore", p_329974_.get("Lore"));
Optional<Integer> optional = p_329974_.get("color").asNumber().result().map(Number::intValue);
boolean flag = (p_330088_ & 64) != 0;
if (optional.isPresent() || flag) {
Dynamic<?> dynamic = p_329974_.emptyMap().set("rgb", p_329974_.createInt(optional.orElse(10511680)));
if (flag) {
dynamic = dynamic.set("show_in_tooltip", p_329974_.createBoolean(false));
}
p_333136_.setComponent("minecraft:dyed_color", dynamic);
}
Optional<String> optional1 = p_329974_.get("LocName").asString().result();
if (optional1.isPresent()) {
p_333136_.setComponent("minecraft:item_name", LegacyComponentDataFixUtils.createTranslatableComponent(p_329974_.getOps(), optional1.get()));
}
if (p_333136_.is("minecraft:filled_map")) {
p_333136_.setComponent("minecraft:map_color", p_329974_.get("MapColor"));
p_329974_ = p_329974_.remove("MapColor");
}
return p_329974_.remove("Name").remove("Lore").remove("color").remove("LocName");
}
private static <T> Dynamic<T> fixBlockEntityTag(ItemStackComponentizationFix.ItemStackData p_334120_, Dynamic<T> p_332622_, String p_334133_) {
p_334120_.setComponent("minecraft:lock", p_332622_.get("Lock"));
p_332622_ = p_332622_.remove("Lock");
Optional<Dynamic<T>> optional = p_332622_.get("LootTable").result();
if (optional.isPresent()) {
Dynamic<T> dynamic = p_332622_.emptyMap().set("loot_table", optional.get());
long i = p_332622_.get("LootTableSeed").asLong(0L);
if (i != 0L) {
dynamic = dynamic.set("seed", p_332622_.createLong(i));
}
p_334120_.setComponent("minecraft:container_loot", dynamic);
p_332622_ = p_332622_.remove("LootTable").remove("LootTableSeed");
}
return switch (p_334133_) {
case "minecraft:skull" -> {
p_334120_.setComponent("minecraft:note_block_sound", p_332622_.get("note_block_sound"));
yield p_332622_.remove("note_block_sound");
}
case "minecraft:decorated_pot" -> {
p_334120_.setComponent("minecraft:pot_decorations", p_332622_.get("sherds"));
Optional<Dynamic<T>> optional2 = p_332622_.get("item").result();
if (optional2.isPresent()) {
p_334120_.setComponent(
"minecraft:container",
p_332622_.createList(Stream.of(p_332622_.emptyMap().set("slot", p_332622_.createInt(0)).set("item", optional2.get())))
);
}
yield p_332622_.remove("sherds").remove("item");
}
case "minecraft:banner" -> {
p_334120_.setComponent("minecraft:banner_patterns", p_332622_.get("patterns"));
Optional<Number> optional1 = p_332622_.get("Base").asNumber().result();
if (optional1.isPresent()) {
p_334120_.setComponent("minecraft:base_color", p_332622_.createString(ExtraDataFixUtils.dyeColorIdToName(optional1.get().intValue())));
}
yield p_332622_.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>> list = p_332622_.get("Items")
.asList(
p_334204_ -> p_334204_.emptyMap()
.set("slot", p_334204_.createInt(p_334204_.get("Slot").asByte((byte)0) & 255))
.set("item", p_334204_.remove("Slot"))
);
if (!list.isEmpty()) {
p_334120_.setComponent("minecraft:container", p_332622_.createList(list.stream()));
}
yield p_332622_.remove("Items");
}
case "minecraft:beehive" -> {
p_334120_.setComponent("minecraft:bees", p_332622_.get("bees"));
yield p_332622_.remove("bees");
}
default -> p_332622_;
};
}
private static void fixEnchantments(
ItemStackComponentizationFix.ItemStackData p_332552_, Dynamic<?> p_328849_, String p_333260_, String p_334340_, boolean p_329498_
) {
OptionalDynamic<?> optionaldynamic = p_332552_.removeTag(p_333260_);
List<Pair<String, Integer>> list = optionaldynamic.asList(Function.identity())
.stream()
.flatMap(p_331550_ -> parseEnchantment((Dynamic<?>)p_331550_).stream())
.toList();
if (!list.isEmpty() || p_329498_) {
Dynamic<?> dynamic = p_328849_.emptyMap();
Dynamic<?> dynamic1 = p_328849_.emptyMap();
for (Pair<String, Integer> pair : list) {
dynamic1 = dynamic1.set(pair.getFirst(), p_328849_.createInt(pair.getSecond()));
}
dynamic = dynamic.set("levels", dynamic1);
if (p_329498_) {
dynamic = dynamic.set("show_in_tooltip", p_328849_.createBoolean(false));
}
p_332552_.setComponent(p_334340_, dynamic);
}
if (optionaldynamic.result().isPresent() && list.isEmpty()) {
p_332552_.setComponent("minecraft:enchantment_glint_override", p_328849_.createBoolean(true));
}
}
private static Optional<Pair<String, Integer>> parseEnchantment(Dynamic<?> p_328387_) {
return p_328387_.get("id")
.asString()
.apply2stable((p_335475_, p_333076_) -> Pair.of(p_335475_, Mth.clamp(p_333076_.intValue(), 0, 255)), p_328387_.get("lvl").asNumber())
.result();
}
private static void fixAdventureModeChecks(ItemStackComponentizationFix.ItemStackData p_328938_, Dynamic<?> p_336252_, int p_331810_) {
fixBlockStatePredicates(p_328938_, p_336252_, "CanDestroy", "minecraft:can_break", (p_331810_ & 8) != 0);
fixBlockStatePredicates(p_328938_, p_336252_, "CanPlaceOn", "minecraft:can_place_on", (p_331810_ & 16) != 0);
}
private static void fixBlockStatePredicates(
ItemStackComponentizationFix.ItemStackData p_331433_, Dynamic<?> p_332377_, String p_332474_, String p_333138_, boolean p_334219_
) {
Optional<? extends Dynamic<?>> optional = p_331433_.removeTag(p_332474_).result();
if (!optional.isEmpty()) {
Dynamic<?> dynamic = p_332377_.emptyMap()
.set(
"predicates",
p_332377_.createList(
optional.get()
.asStream()
.map(
p_336172_ -> DataFixUtils.orElse(
p_336172_.asString().map(p_330317_ -> fixBlockStatePredicate((Dynamic<?>)p_336172_, p_330317_)).result(), p_336172_
)
)
)
);
if (p_334219_) {
dynamic = dynamic.set("show_in_tooltip", p_332377_.createBoolean(false));
}
p_331433_.setComponent(p_333138_, dynamic);
}
}
private static Dynamic<?> fixBlockStatePredicate(Dynamic<?> p_330250_, String p_335482_) {
int i = p_335482_.indexOf(91);
int j = p_335482_.indexOf(123);
int k = p_335482_.length();
if (i != -1) {
k = i;
}
if (j != -1) {
k = Math.min(k, j);
}
String s = p_335482_.substring(0, k);
Dynamic<?> dynamic = p_330250_.emptyMap().set("blocks", p_330250_.createString(s.trim()));
int l = p_335482_.indexOf(93);
if (i != -1 && l != -1) {
Dynamic<?> dynamic1 = p_330250_.emptyMap();
for (String s1 : PROPERTY_SPLITTER.split(p_335482_.substring(i + 1, l))) {
int i1 = s1.indexOf(61);
if (i1 != -1) {
String s2 = s1.substring(0, i1).trim();
String s3 = s1.substring(i1 + 1).trim();
dynamic1 = dynamic1.set(s2, p_330250_.createString(s3));
}
}
dynamic = dynamic.set("state", dynamic1);
}
int j1 = p_335482_.indexOf(125);
if (j != -1 && j1 != -1) {
dynamic = dynamic.set("nbt", p_330250_.createString(p_335482_.substring(j, j1 + 1)));
}
return dynamic;
}
private static void fixAttributeModifiers(ItemStackComponentizationFix.ItemStackData p_329869_, Dynamic<?> p_332943_, int p_330062_) {
OptionalDynamic<?> optionaldynamic = p_329869_.removeTag("AttributeModifiers");
if (!optionaldynamic.result().isEmpty()) {
boolean flag = (p_330062_ & 2) != 0;
List<? extends Dynamic<?>> list = optionaldynamic.asList(ItemStackComponentizationFix::fixAttributeModifier);
Dynamic<?> dynamic = p_332943_.emptyMap().set("modifiers", p_332943_.createList(list.stream()));
if (flag) {
dynamic = dynamic.set("show_in_tooltip", p_332943_.createBoolean(false));
}
p_329869_.setComponent("minecraft:attribute_modifiers", dynamic);
}
}
private static Dynamic<?> fixAttributeModifier(Dynamic<?> p_330280_) {
Dynamic<?> dynamic = p_330280_.emptyMap()
.set("name", p_330280_.createString(""))
.set("amount", p_330280_.createDouble(0.0))
.set("operation", p_330280_.createString("add_value"));
dynamic = Dynamic.copyField(p_330280_, "AttributeName", dynamic, "type");
dynamic = Dynamic.copyField(p_330280_, "Slot", dynamic, "slot");
dynamic = Dynamic.copyField(p_330280_, "UUID", dynamic, "uuid");
dynamic = Dynamic.copyField(p_330280_, "Name", dynamic, "name");
dynamic = Dynamic.copyField(p_330280_, "Amount", dynamic, "amount");
return Dynamic.copyAndFixField(p_330280_, "Operation", dynamic, "operation", p_334772_ -> {
return p_334772_.createString(switch (p_334772_.asInt(0)) {
case 1 -> "add_multiplied_base";
case 2 -> "add_multiplied_total";
default -> "add_value";
});
});
}
private static Pair<Dynamic<?>, Dynamic<?>> fixMapDecoration(Dynamic<?> p_329859_) {
Dynamic<?> dynamic = DataFixUtils.orElseGet(p_329859_.get("id").result(), () -> p_329859_.createString(""));
Dynamic<?> dynamic1 = p_329859_.emptyMap()
.set("type", p_329859_.createString(fixMapDecorationType(p_329859_.get("type").asInt(0))))
.set("x", p_329859_.createDouble(p_329859_.get("x").asDouble(0.0)))
.set("z", p_329859_.createDouble(p_329859_.get("z").asDouble(0.0)))
.set("rotation", p_329859_.createFloat((float)p_329859_.get("rot").asDouble(0.0)));
return Pair.of(dynamic, dynamic1);
}
private static String fixMapDecorationType(int p_328497_) {
return switch (p_328497_) {
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 p_329173_, Dynamic<?> p_331866_) {
Dynamic<?> dynamic = p_331866_.emptyMap();
Optional<String> optional = p_329173_.removeTag("Potion").asString().result().filter(p_334871_ -> !p_334871_.equals("minecraft:empty"));
if (optional.isPresent()) {
dynamic = dynamic.set("potion", p_331866_.createString(optional.get()));
}
dynamic = p_329173_.moveTagInto("CustomPotionColor", dynamic, "custom_color");
dynamic = p_329173_.moveTagInto("custom_potion_effects", dynamic, "custom_effects");
if (!dynamic.equals(p_331866_.emptyMap())) {
p_329173_.setComponent("minecraft:potion_contents", dynamic);
}
}
private static void fixWritableBook(ItemStackComponentizationFix.ItemStackData p_332414_, Dynamic<?> p_329764_) {
Dynamic<?> dynamic = fixBookPages(p_332414_, p_329764_);
if (dynamic != null) {
p_332414_.setComponent("minecraft:writable_book_content", p_329764_.emptyMap().set("pages", dynamic));
}
}
private static void fixWrittenBook(ItemStackComponentizationFix.ItemStackData p_333609_, Dynamic<?> p_330312_) {
Dynamic<?> dynamic = fixBookPages(p_333609_, p_330312_);
String s = p_333609_.removeTag("title").asString("");
Optional<String> optional = p_333609_.removeTag("filtered_title").asString().result();
Dynamic<?> dynamic1 = p_330312_.emptyMap();
dynamic1 = dynamic1.set("title", createFilteredText(p_330312_, s, optional));
dynamic1 = p_333609_.moveTagInto("author", dynamic1, "author");
dynamic1 = p_333609_.moveTagInto("resolved", dynamic1, "resolved");
dynamic1 = p_333609_.moveTagInto("generation", dynamic1, "generation");
if (dynamic != null) {
dynamic1 = dynamic1.set("pages", dynamic);
}
p_333609_.setComponent("minecraft:written_book_content", dynamic1);
}
@Nullable
private static Dynamic<?> fixBookPages(ItemStackComponentizationFix.ItemStackData p_335763_, Dynamic<?> p_328532_) {
List<String> list = p_335763_.removeTag("pages").asList(p_331615_ -> p_331615_.asString(""));
Map<String, String> map = p_335763_.removeTag("filtered_pages").asMap(p_335169_ -> p_335169_.asString("0"), p_329927_ -> p_329927_.asString(""));
if (list.isEmpty()) {
return null;
} else {
List<Dynamic<?>> list1 = new ArrayList<>(list.size());
for (int i = 0; i < list.size(); i++) {
String s = list.get(i);
String s1 = map.get(String.valueOf(i));
list1.add(createFilteredText(p_328532_, s, Optional.ofNullable(s1)));
}
return p_328532_.createList(list1.stream());
}
}
private static Dynamic<?> createFilteredText(Dynamic<?> p_330363_, String p_328510_, Optional<String> p_328222_) {
Dynamic<?> dynamic = p_330363_.emptyMap().set("raw", p_330363_.createString(p_328510_));
if (p_328222_.isPresent()) {
dynamic = dynamic.set("filtered", p_330363_.createString(p_328222_.get()));
}
return dynamic;
}
private static void fixBucketedMobData(ItemStackComponentizationFix.ItemStackData p_328428_, Dynamic<?> p_327719_) {
Dynamic<?> dynamic = p_327719_.emptyMap();
for (String s : BUCKETED_MOB_TAGS) {
dynamic = p_328428_.moveTagInto(s, dynamic, s);
}
if (!dynamic.equals(p_327719_.emptyMap())) {
p_328428_.setComponent("minecraft:bucket_entity_data", dynamic);
}
}
private static void fixLodestoneTracker(ItemStackComponentizationFix.ItemStackData p_330486_, Dynamic<?> p_329466_) {
Optional<? extends Dynamic<?>> optional = p_330486_.removeTag("LodestonePos").result();
Optional<? extends Dynamic<?>> optional1 = p_330486_.removeTag("LodestoneDimension").result();
if (!optional.isEmpty() || !optional1.isEmpty()) {
boolean flag = p_330486_.removeTag("LodestoneTracked").asBoolean(true);
Dynamic<?> dynamic = p_329466_.emptyMap();
if (optional.isPresent() && optional1.isPresent()) {
dynamic = dynamic.set("target", p_329466_.emptyMap().set("pos", (Dynamic<?>)optional.get()).set("dimension", (Dynamic<?>)optional1.get()));
}
if (!flag) {
dynamic = dynamic.set("tracked", p_329466_.createBoolean(false));
}
p_330486_.setComponent("minecraft:lodestone_tracker", dynamic);
}
}
private static void fixFireworkStar(ItemStackComponentizationFix.ItemStackData p_334817_) {
p_334817_.fixSubTag("Explosion", true, p_334469_ -> {
p_334817_.setComponent("minecraft:firework_explosion", fixFireworkExplosion(p_334469_));
return p_334469_.remove("Type").remove("Colors").remove("FadeColors").remove("Trail").remove("Flicker");
});
}
private static void fixFireworkRocket(ItemStackComponentizationFix.ItemStackData p_329939_) {
p_329939_.fixSubTag(
"Fireworks",
true,
p_335612_ -> {
Stream<? extends Dynamic<?>> stream = p_335612_.get("Explosions").asStream().map(ItemStackComponentizationFix::fixFireworkExplosion);
int i = p_335612_.get("Flight").asInt(0);
p_329939_.setComponent(
"minecraft:fireworks",
p_335612_.emptyMap().set("explosions", p_335612_.createList(stream)).set("flight_duration", p_335612_.createByte((byte)i))
);
return p_335612_.remove("Explosions").remove("Flight");
}
);
}
private static Dynamic<?> fixFireworkExplosion(Dynamic<?> p_327955_) {
p_327955_ = p_327955_.set("shape", p_327955_.createString(switch (p_327955_.get("Type").asInt(0)) {
case 1 -> "large_ball";
case 2 -> "star";
case 3 -> "creeper";
case 4 -> "burst";
default -> "small_ball";
})).remove("Type");
p_327955_ = p_327955_.renameField("Colors", "colors");
p_327955_ = p_327955_.renameField("FadeColors", "fade_colors");
p_327955_ = p_327955_.renameField("Trail", "has_trail");
return p_327955_.renameField("Flicker", "has_twinkle");
}
public static Dynamic<?> fixProfile(Dynamic<?> p_331244_) {
Optional<String> optional = p_331244_.asString().result();
if (optional.isPresent()) {
return isValidPlayerName(optional.get()) ? p_331244_.emptyMap().set("name", p_331244_.createString(optional.get())) : p_331244_.emptyMap();
} else {
String s = p_331244_.get("Name").asString("");
Optional<? extends Dynamic<?>> optional1 = p_331244_.get("Id").result();
Dynamic<?> dynamic = fixProfileProperties(p_331244_.get("Properties"));
Dynamic<?> dynamic1 = p_331244_.emptyMap();
if (isValidPlayerName(s)) {
dynamic1 = dynamic1.set("name", p_331244_.createString(s));
}
if (optional1.isPresent()) {
dynamic1 = dynamic1.set("id", (Dynamic<?>)optional1.get());
}
if (dynamic != null) {
dynamic1 = dynamic1.set("properties", dynamic);
}
return dynamic1;
}
}
private static boolean isValidPlayerName(String p_332205_) {
return p_332205_.length() > 16 ? false : p_332205_.chars().filter(p_331992_ -> p_331992_ <= 32 || p_331992_ >= 127).findAny().isEmpty();
}
@Nullable
private static Dynamic<?> fixProfileProperties(OptionalDynamic<?> p_329629_) {
Map<String, List<Pair<String, Optional<String>>>> map = p_329629_.asMap(
p_330311_ -> p_330311_.asString(""), p_331808_ -> p_331808_.asList(p_329294_ -> {
String s = p_329294_.get("Value").asString("");
Optional<String> optional = p_329294_.get("Signature").asString().result();
return Pair.of(s, optional);
})
);
return map.isEmpty()
? null
: p_329629_.createList(
map.entrySet()
.stream()
.flatMap(
p_334576_ -> p_334576_.getValue()
.stream()
.map(
p_335577_ -> {
Dynamic<?> dynamic = p_329629_.emptyMap()
.set("name", p_329629_.createString(p_334576_.getKey()))
.set("value", p_329629_.createString(p_335577_.getFirst()));
Optional<String> optional = p_335577_.getSecond();
return optional.isPresent() ? dynamic.set("signature", p_329629_.createString(optional.get())) : dynamic;
}
)
)
);
}
@Override
protected TypeRewriteRule makeRule() {
return this.writeFixAndRead(
"ItemStack componentization",
this.getInputSchema().getType(References.ITEM_STACK),
this.getOutputSchema().getType(References.ITEM_STACK),
p_332668_ -> {
Optional<? extends Dynamic<?>> optional = ItemStackComponentizationFix.ItemStackData.read(p_332668_).map(p_329220_ -> {
fixItemStack(p_329220_, p_329220_.tag);
return p_329220_.write();
});
return DataFixUtils.orElse(optional, p_332668_);
}
);
}
static class ItemStackData {
private final String item;
private final int count;
private Dynamic<?> components;
private final Dynamic<?> remainder;
Dynamic<?> tag;
private ItemStackData(String p_330519_, int p_328981_, Dynamic<?> p_329116_) {
this.item = NamespacedSchema.ensureNamespaced(p_330519_);
this.count = p_328981_;
this.components = p_329116_.emptyMap();
this.tag = p_329116_.get("tag").orElseEmptyMap();
this.remainder = p_329116_.remove("tag");
}
public static Optional<ItemStackComponentizationFix.ItemStackData> read(Dynamic<?> p_327873_) {
return p_327873_.get("id")
.asString()
.apply2stable(
(p_336038_, p_334919_) -> new ItemStackComponentizationFix.ItemStackData(
p_336038_, p_334919_.intValue(), p_327873_.remove("id").remove("Count")
),
p_327873_.get("Count").asNumber()
)
.result();
}
public OptionalDynamic<?> removeTag(String p_327670_) {
OptionalDynamic<?> optionaldynamic = this.tag.get(p_327670_);
this.tag = this.tag.remove(p_327670_);
return optionaldynamic;
}
public void setComponent(String p_334273_, Dynamic<?> p_334484_) {
this.components = this.components.set(p_334273_, p_334484_);
}
public void setComponent(String p_333518_, OptionalDynamic<?> p_335463_) {
p_335463_.result().ifPresent(p_334065_ -> this.components = this.components.set(p_333518_, (Dynamic<?>)p_334065_));
}
public Dynamic<?> moveTagInto(String p_333380_, Dynamic<?> p_332781_, String p_332207_) {
Optional<? extends Dynamic<?>> optional = this.removeTag(p_333380_).result();
return optional.isPresent() ? p_332781_.set(p_332207_, (Dynamic<?>)optional.get()) : p_332781_;
}
public void moveTagToComponent(String p_330725_, String p_334538_, Dynamic<?> p_328097_) {
Optional<? extends Dynamic<?>> optional = this.removeTag(p_330725_).result();
if (optional.isPresent() && !optional.get().equals(p_328097_)) {
this.setComponent(p_334538_, (Dynamic<?>)optional.get());
}
}
public void moveTagToComponent(String p_334513_, String p_335629_) {
this.removeTag(p_334513_).result().ifPresent(p_331999_ -> this.setComponent(p_335629_, (Dynamic<?>)p_331999_));
}
public void fixSubTag(String p_334224_, boolean p_331760_, UnaryOperator<Dynamic<?>> p_335156_) {
OptionalDynamic<?> optionaldynamic = this.tag.get(p_334224_);
if (!p_331760_ || !optionaldynamic.result().isEmpty()) {
Dynamic<?> dynamic = optionaldynamic.orElseEmptyMap();
dynamic = p_335156_.apply(dynamic);
if (dynamic.equals(dynamic.emptyMap())) {
this.tag = this.tag.remove(p_334224_);
} else {
this.tag = this.tag.set(p_334224_, dynamic);
}
}
}
public Dynamic<?> write() {
Dynamic<?> dynamic = 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())) {
dynamic = dynamic.set("components", this.components);
}
return mergeRemainder(dynamic, this.remainder);
}
private static <T> Dynamic<T> mergeRemainder(Dynamic<T> p_331283_, Dynamic<?> p_335645_) {
DynamicOps<T> dynamicops = p_331283_.getOps();
return dynamicops.getMap(p_331283_.getValue())
.flatMap(p_335224_ -> dynamicops.mergeToMap(p_335645_.convert(dynamicops).getValue(), (MapLike<T>)p_335224_))
.map(p_334956_ -> new Dynamic<>(dynamicops, (T)p_334956_))
.result()
.orElse(p_331283_);
}
public boolean is(String p_328447_) {
return this.item.equals(p_328447_);
}
public boolean is(Set<String> p_332697_) {
return p_332697_.contains(this.item);
}
public boolean hasComponent(String p_329543_) {
return this.components.get(p_329543_).result().isPresent();
}
}
}