package net.minecraft.util.datafix.schemas; import com.google.common.collect.Maps; import com.mojang.datafixers.DSL; import com.mojang.datafixers.DataFixUtils; import com.mojang.datafixers.schemas.Schema; import com.mojang.datafixers.types.templates.TypeTemplate; import com.mojang.datafixers.types.templates.Hook.HookFunction; import com.mojang.datafixers.util.Pair; import com.mojang.logging.LogUtils; import com.mojang.serialization.Dynamic; import com.mojang.serialization.DynamicOps; import java.util.Map; import java.util.function.Function; import java.util.function.Supplier; import net.minecraft.util.datafix.fixes.References; import org.slf4j.Logger; public class V99 extends Schema { private static final Logger LOGGER = LogUtils.getLogger(); static final Map ITEM_TO_BLOCKENTITY = DataFixUtils.make(Maps.newHashMap(), hashMap -> { hashMap.put("minecraft:furnace", "Furnace"); hashMap.put("minecraft:lit_furnace", "Furnace"); hashMap.put("minecraft:chest", "Chest"); hashMap.put("minecraft:trapped_chest", "Chest"); hashMap.put("minecraft:ender_chest", "EnderChest"); hashMap.put("minecraft:jukebox", "RecordPlayer"); hashMap.put("minecraft:dispenser", "Trap"); hashMap.put("minecraft:dropper", "Dropper"); hashMap.put("minecraft:sign", "Sign"); hashMap.put("minecraft:mob_spawner", "MobSpawner"); hashMap.put("minecraft:noteblock", "Music"); hashMap.put("minecraft:brewing_stand", "Cauldron"); hashMap.put("minecraft:enhanting_table", "EnchantTable"); hashMap.put("minecraft:command_block", "CommandBlock"); hashMap.put("minecraft:beacon", "Beacon"); hashMap.put("minecraft:skull", "Skull"); hashMap.put("minecraft:daylight_detector", "DLDetector"); hashMap.put("minecraft:hopper", "Hopper"); hashMap.put("minecraft:banner", "Banner"); hashMap.put("minecraft:flower_pot", "FlowerPot"); hashMap.put("minecraft:repeating_command_block", "CommandBlock"); hashMap.put("minecraft:chain_command_block", "CommandBlock"); hashMap.put("minecraft:standing_sign", "Sign"); hashMap.put("minecraft:wall_sign", "Sign"); hashMap.put("minecraft:piston_head", "Piston"); hashMap.put("minecraft:daylight_detector_inverted", "DLDetector"); hashMap.put("minecraft:unpowered_comparator", "Comparator"); hashMap.put("minecraft:powered_comparator", "Comparator"); hashMap.put("minecraft:wall_banner", "Banner"); hashMap.put("minecraft:standing_banner", "Banner"); hashMap.put("minecraft:structure_block", "Structure"); hashMap.put("minecraft:end_portal", "Airportal"); hashMap.put("minecraft:end_gateway", "EndGateway"); hashMap.put("minecraft:shield", "Banner"); }); public static final Map ITEM_TO_ENTITY = Map.of("minecraft:armor_stand", "ArmorStand", "minecraft:painting", "Painting"); protected static final HookFunction ADD_NAMES = new HookFunction() { @Override public T apply(DynamicOps dynamicOps, T object) { return V99.addNames(new Dynamic<>(dynamicOps, object), V99.ITEM_TO_BLOCKENTITY, V99.ITEM_TO_ENTITY); } }; public V99(int versionKey, Schema parent) { super(versionKey, parent); } protected static void registerThrowableProjectile(Schema schema, Map> map, String name) { schema.register(map, name, (Supplier)(() -> DSL.optionalFields("inTile", References.BLOCK_NAME.in(schema)))); } protected static void registerMinecart(Schema schema, Map> map, String name) { schema.register(map, name, (Supplier)(() -> DSL.optionalFields("DisplayTile", References.BLOCK_NAME.in(schema)))); } protected static void registerInventory(Schema schema, Map> map, String name) { schema.register(map, name, (Supplier)(() -> DSL.optionalFields("Items", DSL.list(References.ITEM_STACK.in(schema))))); } @Override public Map> registerEntities(Schema schema) { Map> map = Maps.>newHashMap(); schema.register(map, "Item", (Function)(string -> DSL.optionalFields("Item", References.ITEM_STACK.in(schema)))); schema.registerSimple(map, "XPOrb"); registerThrowableProjectile(schema, map, "ThrownEgg"); schema.registerSimple(map, "LeashKnot"); schema.registerSimple(map, "Painting"); schema.register(map, "Arrow", (Function)(string -> DSL.optionalFields("inTile", References.BLOCK_NAME.in(schema)))); schema.register(map, "TippedArrow", (Function)(string -> DSL.optionalFields("inTile", References.BLOCK_NAME.in(schema)))); schema.register(map, "SpectralArrow", (Function)(string -> DSL.optionalFields("inTile", References.BLOCK_NAME.in(schema)))); registerThrowableProjectile(schema, map, "Snowball"); registerThrowableProjectile(schema, map, "Fireball"); registerThrowableProjectile(schema, map, "SmallFireball"); registerThrowableProjectile(schema, map, "ThrownEnderpearl"); schema.registerSimple(map, "EyeOfEnderSignal"); schema.register( map, "ThrownPotion", (Function)(string -> DSL.optionalFields("inTile", References.BLOCK_NAME.in(schema), "Potion", References.ITEM_STACK.in(schema))) ); registerThrowableProjectile(schema, map, "ThrownExpBottle"); schema.register(map, "ItemFrame", (Function)(string -> DSL.optionalFields("Item", References.ITEM_STACK.in(schema)))); registerThrowableProjectile(schema, map, "WitherSkull"); schema.registerSimple(map, "PrimedTnt"); schema.register( map, "FallingSand", (Function)(string -> DSL.optionalFields( "Block", References.BLOCK_NAME.in(schema), "TileEntityData", References.BLOCK_ENTITY.in(schema) )) ); schema.register( map, "FireworksRocketEntity", (Function)(string -> DSL.optionalFields("FireworksItem", References.ITEM_STACK.in(schema))) ); schema.registerSimple(map, "Boat"); schema.register( map, "Minecart", (Supplier)(() -> DSL.optionalFields("DisplayTile", References.BLOCK_NAME.in(schema), "Items", DSL.list(References.ITEM_STACK.in(schema)))) ); registerMinecart(schema, map, "MinecartRideable"); schema.register( map, "MinecartChest", (Function)(string -> DSL.optionalFields( "DisplayTile", References.BLOCK_NAME.in(schema), "Items", DSL.list(References.ITEM_STACK.in(schema)) )) ); registerMinecart(schema, map, "MinecartFurnace"); registerMinecart(schema, map, "MinecartTNT"); schema.register( map, "MinecartSpawner", (Supplier)(() -> DSL.optionalFields("DisplayTile", References.BLOCK_NAME.in(schema), References.UNTAGGED_SPAWNER.in(schema))) ); schema.register( map, "MinecartHopper", (Function)(string -> DSL.optionalFields( "DisplayTile", References.BLOCK_NAME.in(schema), "Items", DSL.list(References.ITEM_STACK.in(schema)) )) ); schema.register( map, "MinecartCommandBlock", (Supplier)(() -> DSL.optionalFields("DisplayTile", References.BLOCK_NAME.in(schema), "LastOutput", References.TEXT_COMPONENT.in(schema))) ); schema.registerSimple(map, "ArmorStand"); schema.registerSimple(map, "Creeper"); schema.registerSimple(map, "Skeleton"); schema.registerSimple(map, "Spider"); schema.registerSimple(map, "Giant"); schema.registerSimple(map, "Zombie"); schema.registerSimple(map, "Slime"); schema.registerSimple(map, "Ghast"); schema.registerSimple(map, "PigZombie"); schema.register(map, "Enderman", (Function)(string -> DSL.optionalFields("carried", References.BLOCK_NAME.in(schema)))); schema.registerSimple(map, "CaveSpider"); schema.registerSimple(map, "Silverfish"); schema.registerSimple(map, "Blaze"); schema.registerSimple(map, "LavaSlime"); schema.registerSimple(map, "EnderDragon"); schema.registerSimple(map, "WitherBoss"); schema.registerSimple(map, "Bat"); schema.registerSimple(map, "Witch"); schema.registerSimple(map, "Endermite"); schema.registerSimple(map, "Guardian"); schema.registerSimple(map, "Pig"); schema.registerSimple(map, "Sheep"); schema.registerSimple(map, "Cow"); schema.registerSimple(map, "Chicken"); schema.registerSimple(map, "Squid"); schema.registerSimple(map, "Wolf"); schema.registerSimple(map, "MushroomCow"); schema.registerSimple(map, "SnowMan"); schema.registerSimple(map, "Ozelot"); schema.registerSimple(map, "VillagerGolem"); schema.register( map, "EntityHorse", (Function)(string -> DSL.optionalFields( "Items", DSL.list(References.ITEM_STACK.in(schema)), "ArmorItem", References.ITEM_STACK.in(schema), "SaddleItem", References.ITEM_STACK.in(schema) )) ); schema.registerSimple(map, "Rabbit"); schema.register( map, "Villager", (Function)(string -> DSL.optionalFields( "Inventory", DSL.list(References.ITEM_STACK.in(schema)), "Offers", DSL.optionalFields("Recipes", DSL.list(References.VILLAGER_TRADE.in(schema))) )) ); schema.registerSimple(map, "EnderCrystal"); schema.register(map, "AreaEffectCloud", (Function)(string -> DSL.optionalFields("Particle", References.PARTICLE.in(schema)))); schema.registerSimple(map, "ShulkerBullet"); schema.registerSimple(map, "DragonFireball"); schema.registerSimple(map, "Shulker"); return map; } @Override public Map> registerBlockEntities(Schema schema) { Map> map = Maps.>newHashMap(); registerInventory(schema, map, "Furnace"); registerInventory(schema, map, "Chest"); schema.registerSimple(map, "EnderChest"); schema.register(map, "RecordPlayer", (Function)(string -> DSL.optionalFields("RecordItem", References.ITEM_STACK.in(schema)))); registerInventory(schema, map, "Trap"); registerInventory(schema, map, "Dropper"); schema.register(map, "Sign", (Supplier)(() -> sign(schema))); schema.register(map, "MobSpawner", (Function)(string -> References.UNTAGGED_SPAWNER.in(schema))); schema.registerSimple(map, "Music"); schema.registerSimple(map, "Piston"); registerInventory(schema, map, "Cauldron"); schema.registerSimple(map, "EnchantTable"); schema.registerSimple(map, "Airportal"); schema.register(map, "Control", (Supplier)(() -> DSL.optionalFields("LastOutput", References.TEXT_COMPONENT.in(schema)))); schema.registerSimple(map, "Beacon"); schema.register(map, "Skull", (Supplier)(() -> DSL.optionalFields("custom_name", References.TEXT_COMPONENT.in(schema)))); schema.registerSimple(map, "DLDetector"); registerInventory(schema, map, "Hopper"); schema.registerSimple(map, "Comparator"); schema.register( map, "FlowerPot", (Function)(string -> DSL.optionalFields("Item", DSL.or(DSL.constType(DSL.intType()), References.ITEM_NAME.in(schema)))) ); schema.register(map, "Banner", (Supplier)(() -> DSL.optionalFields("CustomName", References.TEXT_COMPONENT.in(schema)))); schema.registerSimple(map, "Structure"); schema.registerSimple(map, "EndGateway"); return map; } public static TypeTemplate sign(Schema schema) { return DSL.optionalFields( Pair.of("Text1", References.TEXT_COMPONENT.in(schema)), Pair.of("Text2", References.TEXT_COMPONENT.in(schema)), Pair.of("Text3", References.TEXT_COMPONENT.in(schema)), Pair.of("Text4", References.TEXT_COMPONENT.in(schema)), Pair.of("FilteredText1", References.TEXT_COMPONENT.in(schema)), Pair.of("FilteredText2", References.TEXT_COMPONENT.in(schema)), Pair.of("FilteredText3", References.TEXT_COMPONENT.in(schema)), Pair.of("FilteredText4", References.TEXT_COMPONENT.in(schema)) ); } @Override public void registerTypes(Schema schema, Map> map, Map> map2) { schema.registerType( false, References.LEVEL, () -> DSL.optionalFields("CustomBossEvents", DSL.compoundList(DSL.optionalFields("Name", References.TEXT_COMPONENT.in(schema)))) ); schema.registerType( false, References.PLAYER, () -> DSL.optionalFields("Inventory", DSL.list(References.ITEM_STACK.in(schema)), "EnderItems", DSL.list(References.ITEM_STACK.in(schema))) ); schema.registerType( false, References.CHUNK, () -> DSL.fields( "Level", DSL.optionalFields( "Entities", DSL.list(References.ENTITY_TREE.in(schema)), "TileEntities", DSL.list(DSL.or(References.BLOCK_ENTITY.in(schema), DSL.remainder())), "TileTicks", DSL.list(DSL.fields("i", References.BLOCK_NAME.in(schema))) ) ) ); schema.registerType( true, References.BLOCK_ENTITY, () -> DSL.optionalFields("components", References.DATA_COMPONENTS.in(schema), DSL.taggedChoiceLazy("id", DSL.string(), map2)) ); schema.registerType(true, References.ENTITY_TREE, () -> DSL.optionalFields("Riding", References.ENTITY_TREE.in(schema), References.ENTITY.in(schema))); schema.registerType(false, References.ENTITY_NAME, () -> DSL.constType(NamespacedSchema.namespacedString())); schema.registerType( true, References.ENTITY, () -> DSL.and( References.ENTITY_EQUIPMENT.in(schema), DSL.optionalFields("CustomName", DSL.constType(DSL.string()), DSL.taggedChoiceLazy("id", DSL.string(), map)) ) ); schema.registerType( true, References.ITEM_STACK, () -> DSL.hook( DSL.optionalFields("id", DSL.or(DSL.constType(DSL.intType()), References.ITEM_NAME.in(schema)), "tag", itemStackTag(schema)), ADD_NAMES, HookFunction.IDENTITY ) ); schema.registerType(false, References.OPTIONS, DSL::remainder); schema.registerType(false, References.BLOCK_NAME, () -> DSL.or(DSL.constType(DSL.intType()), DSL.constType(NamespacedSchema.namespacedString()))); schema.registerType(false, References.ITEM_NAME, () -> DSL.constType(NamespacedSchema.namespacedString())); schema.registerType(false, References.STATS, DSL::remainder); schema.registerType(false, References.SAVED_DATA_COMMAND_STORAGE, DSL::remainder); schema.registerType(false, References.SAVED_DATA_TICKETS, DSL::remainder); schema.registerType( false, References.SAVED_DATA_MAP_DATA, () -> DSL.optionalFields("banners", DSL.list(DSL.optionalFields("Name", References.TEXT_COMPONENT.in(schema)))) ); schema.registerType(false, References.SAVED_DATA_MAP_INDEX, DSL::remainder); schema.registerType(false, References.SAVED_DATA_RAIDS, DSL::remainder); schema.registerType(false, References.SAVED_DATA_RANDOM_SEQUENCES, DSL::remainder); schema.registerType( false, References.SAVED_DATA_SCOREBOARD, () -> DSL.optionalFields( "data", DSL.optionalFields( "Objectives", DSL.list(References.OBJECTIVE.in(schema)), "Teams", DSL.list(References.TEAM.in(schema)), "PlayerScores", DSL.list(DSL.optionalFields("display", References.TEXT_COMPONENT.in(schema))) ) ) ); schema.registerType( false, References.SAVED_DATA_STRUCTURE_FEATURE_INDICES, () -> DSL.optionalFields("data", DSL.optionalFields("Features", DSL.compoundList(References.STRUCTURE_FEATURE.in(schema)))) ); schema.registerType(false, References.STRUCTURE_FEATURE, DSL::remainder); schema.registerType(false, References.OBJECTIVE, DSL::remainder); schema.registerType( false, References.TEAM, () -> DSL.optionalFields( "MemberNamePrefix", References.TEXT_COMPONENT.in(schema), "MemberNameSuffix", References.TEXT_COMPONENT.in(schema), "DisplayName", References.TEXT_COMPONENT.in(schema) ) ); schema.registerType(true, References.UNTAGGED_SPAWNER, DSL::remainder); schema.registerType(false, References.POI_CHUNK, DSL::remainder); schema.registerType(false, References.WORLD_GEN_SETTINGS, DSL::remainder); schema.registerType(false, References.ENTITY_CHUNK, () -> DSL.optionalFields("Entities", DSL.list(References.ENTITY_TREE.in(schema)))); schema.registerType(true, References.DATA_COMPONENTS, DSL::remainder); schema.registerType( true, References.VILLAGER_TRADE, () -> DSL.optionalFields("buy", References.ITEM_STACK.in(schema), "buyB", References.ITEM_STACK.in(schema), "sell", References.ITEM_STACK.in(schema)) ); schema.registerType(true, References.PARTICLE, () -> DSL.constType(DSL.string())); schema.registerType(true, References.TEXT_COMPONENT, () -> DSL.constType(DSL.string())); schema.registerType( false, References.STRUCTURE, () -> DSL.optionalFields( "entities", DSL.list(DSL.optionalFields("nbt", References.ENTITY_TREE.in(schema))), "blocks", DSL.list(DSL.optionalFields("nbt", References.BLOCK_ENTITY.in(schema))), "palette", DSL.list(References.BLOCK_STATE.in(schema)) ) ); schema.registerType(false, References.BLOCK_STATE, DSL::remainder); schema.registerType(false, References.FLAT_BLOCK_STATE, DSL::remainder); schema.registerType(true, References.ENTITY_EQUIPMENT, () -> DSL.optional(DSL.field("Equipment", DSL.list(References.ITEM_STACK.in(schema))))); } public static TypeTemplate itemStackTag(Schema schema) { return DSL.optionalFields( Pair.of("EntityTag", References.ENTITY_TREE.in(schema)), Pair.of("BlockEntityTag", References.BLOCK_ENTITY.in(schema)), Pair.of("CanDestroy", DSL.list(References.BLOCK_NAME.in(schema))), Pair.of("CanPlaceOn", DSL.list(References.BLOCK_NAME.in(schema))), Pair.of("Items", DSL.list(References.ITEM_STACK.in(schema))), Pair.of("ChargedProjectiles", DSL.list(References.ITEM_STACK.in(schema))), Pair.of("pages", DSL.list(References.TEXT_COMPONENT.in(schema))), Pair.of("filtered_pages", DSL.compoundList(References.TEXT_COMPONENT.in(schema))), Pair.of("display", DSL.optionalFields("Name", References.TEXT_COMPONENT.in(schema), "Lore", DSL.list(References.TEXT_COMPONENT.in(schema)))) ); } protected static T addNames(Dynamic tag, Map blockEntityRenames, Map entityRenames) { return tag.update("tag", dynamic2 -> dynamic2.update("BlockEntityTag", dynamic2x -> { String string = (String)tag.get("id").asString().result().map(NamespacedSchema::ensureNamespaced).orElse("minecraft:air"); if (!"minecraft:air".equals(string)) { String string2 = (String)blockEntityRenames.get(string); if (string2 != null) { return dynamic2x.set("id", tag.createString(string2)); } LOGGER.warn("Unable to resolve BlockEntity for ItemStack: {}", string); } return dynamic2x; }).update("EntityTag", dynamic2x -> { if (dynamic2x.get("id").result().isPresent()) { return dynamic2x; } else { String string = NamespacedSchema.ensureNamespaced(tag.get("id").asString("")); String string2 = (String)entityRenames.get(string); return string2 != null ? dynamic2x.set("id", tag.createString(string2)) : dynamic2x; } })).getValue(); } }