rest
+ ) {
+ return optionalFields(
+ name1, element1,
+ name2, element2,
+ name3, element3,
+ optionalFields(
+ name4, element4,
+ name5, element5,
+ name6, element6,
+ rest
+ )
+ );
+ }
+}
+// spotless:on
diff --git a/src/main/java/com/gregtechceu/gtceu/api/machine/MetaMachine.java b/src/main/java/com/gregtechceu/gtceu/api/machine/MetaMachine.java
index b7c9731b56f..cf5924bcd45 100644
--- a/src/main/java/com/gregtechceu/gtceu/api/machine/MetaMachine.java
+++ b/src/main/java/com/gregtechceu/gtceu/api/machine/MetaMachine.java
@@ -155,12 +155,6 @@ public MetaMachine(BlockEntityCreationInfo info) {
// ***** Machine Lifecycle ******//
//////////////////////////////////////
- @Override
- public void load(CompoundTag tag) {
- TagCompatibilityFixer.fixMachineAutoOutputTag(tag);
- super.load(tag);
- }
-
/**
* Called when this machine is loaded.
* On the server side, the entire world may not be loaded when this method is called.
diff --git a/src/main/java/com/gregtechceu/gtceu/common/CommonEventListener.java b/src/main/java/com/gregtechceu/gtceu/common/CommonEventListener.java
index 354ff71ba48..e438c72aa06 100644
--- a/src/main/java/com/gregtechceu/gtceu/common/CommonEventListener.java
+++ b/src/main/java/com/gregtechceu/gtceu/common/CommonEventListener.java
@@ -19,12 +19,10 @@
import com.gregtechceu.gtceu.api.data.chemical.material.stack.MaterialStack;
import com.gregtechceu.gtceu.api.data.medicalcondition.MedicalCondition;
import com.gregtechceu.gtceu.api.data.medicalcondition.Symptom;
-import com.gregtechceu.gtceu.api.data.tag.TagPrefix;
import com.gregtechceu.gtceu.api.fluids.FluidBuilder;
import com.gregtechceu.gtceu.api.fluids.FluidState;
import com.gregtechceu.gtceu.api.fluids.store.FluidStorageKeys;
import com.gregtechceu.gtceu.api.item.armor.ArmorComponentItem;
-import com.gregtechceu.gtceu.api.item.tool.GTToolType;
import com.gregtechceu.gtceu.api.machine.MetaMachine;
import com.gregtechceu.gtceu.api.misc.virtualregistry.VirtualEnderRegistry;
import com.gregtechceu.gtceu.api.pattern.MultiblockWorldSavedData;
@@ -38,7 +36,6 @@
import com.gregtechceu.gtceu.common.commands.MedicalConditionCommands;
import com.gregtechceu.gtceu.common.cosmetics.GTCapes;
import com.gregtechceu.gtceu.common.data.*;
-import com.gregtechceu.gtceu.common.data.machines.GTAEMachines;
import com.gregtechceu.gtceu.common.fluid.potion.BottleItemFluidHandler;
import com.gregtechceu.gtceu.common.fluid.potion.PotionItemFluidHandler;
import com.gregtechceu.gtceu.common.item.armor.IJetpack;
@@ -64,9 +61,7 @@
import com.gregtechceu.gtceu.integration.map.cache.server.ServerCache;
import com.gregtechceu.gtceu.utils.TaskHandler;
-import net.minecraft.core.registries.Registries;
import net.minecraft.nbt.CompoundTag;
-import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.world.Difficulty;
@@ -78,13 +73,11 @@
import net.minecraft.world.entity.ai.attributes.Attributes;
import net.minecraft.world.entity.monster.Zombie;
import net.minecraft.world.entity.player.Player;
-import net.minecraft.world.item.Item;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.Items;
import net.minecraft.world.item.PotionItem;
import net.minecraft.world.item.enchantment.EnchantmentHelper;
import net.minecraft.world.level.ChunkPos;
-import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraftforge.common.ForgeMod;
import net.minecraftforge.common.capabilities.ForgeCapabilities;
@@ -104,17 +97,10 @@
import net.minecraftforge.fml.LogicalSide;
import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.items.IItemHandler;
-import net.minecraftforge.registries.MissingMappingsEvent;
-import com.tterrag.registrate.util.entry.BlockEntry;
-import com.tterrag.registrate.util.entry.ItemEntry;
import org.jetbrains.annotations.NotNull;
import java.util.List;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-import static com.gregtechceu.gtceu.utils.FormattingUtil.toLowerCaseUnderscore;
@Mod.EventBusSubscriber(modid = GTCEu.MOD_ID, bus = Mod.EventBusSubscriber.Bus.FORGE)
public class CommonEventListener {
@@ -583,164 +569,4 @@ public static void addAlloyBlastProperty(@NotNull Material material) {
private static boolean isMaterialStackFluidOnly(@NotNull MaterialStack ms) {
return !ms.material().hasProperty(PropertyKey.DUST) && ms.material().hasProperty(PropertyKey.FLUID);
}
-
- @SubscribeEvent
- public static void remapIds(MissingMappingsEvent event) {
- event.getMappings(Registries.BLOCK, GTCEu.MOD_ID).forEach(mapping -> {
- if (mapping.getKey().equals(GTCEu.id("tungstensteel_coil_block"))) {
- mapping.remap(GTBlocks.COIL_RTMALLOY.get());
- }
- if (mapping.getKey().equals(GTCEu.id("steam_miner"))) {
- mapping.remap(GTMachines.STEAM_MINER.first().getBlock());
- }
- });
- event.getMappings(Registries.ITEM, GTCEu.MOD_ID).forEach(mapping -> {
- if (mapping.getKey().equals(GTCEu.id("tungstensteel_coil_block"))) {
- mapping.remap(GTBlocks.COIL_RTMALLOY.get().asItem());
- }
- if (mapping.getKey().equals(GTCEu.id("steam_miner"))) {
- mapping.remap(GTMachines.STEAM_MINER.first().getItem());
- }
- if (mapping.getKey().equals(GTCEu.id("tungstensteel_fluid_cell"))) {
- mapping.remap(GTItems.FLUID_CELL_LARGE_TUNGSTEN_STEEL.get().asItem());
- }
- if (mapping.getKey().equals(GTCEu.id("avanced_nanomuscle_chestplate"))) {
- mapping.remap(GTItems.NANO_CHESTPLATE_ADVANCED.get());
- }
- String path = mapping.getKey().getPath();
- if (path.matches("[lhi]v_.+_wirecutter")) {
- String suffix = "_wirecutter";
- String typeString = path.substring(0, 2) + suffix; // [lhi]v_wirecutter -- tooltype name
- String matString = path.substring(3, path.length() - suffix.length()); // material name
-
- GTToolType type = GTToolType.getTypes().get(typeString);
- Material material = GTMaterials.get(matString);
- if (type == null || material.isNull()) {
- mapping.warn();
- return;
- }
- var tool = GTMaterialItems.TOOL_ITEMS.get(material, type);
- if (tool == null) {
- mapping.warn();
- return;
- }
- mapping.remap(tool.asItem());
- }
- });
- event.getMappings(Registries.BLOCK_ENTITY_TYPE, GTCEu.MOD_ID).forEach(mapping -> {
- if (mapping.getKey().equals(GTCEu.id("steam_miner"))) {
- mapping.remap(GTMachines.STEAM_MINER.first().getBlockEntityType());
- }
- });
-
- event.getMappings(Registries.BLOCK, "gregiceng").forEach(mapping -> {
- String path = mapping.getKey().getPath();
- switch (path) {
- case "stocking_bus", "adv_stocking_bus" -> mapping
- .remap(GTAEMachines.STOCKING_IMPORT_BUS_ME.getBlock());
- case "stocking_hatch", "adv_stocking_hatch" -> mapping
- .remap(GTAEMachines.STOCKING_IMPORT_HATCH_ME.getBlock());
- case "crafting_io_buffer" -> mapping.remap(GTAEMachines.ME_PATTERN_BUFFER.getBlock());
- case "crafting_io_slave" -> mapping.remap(GTAEMachines.ME_PATTERN_BUFFER_PROXY.getBlock());
- }
- if (path.contains("input_buffer")) {
- ResourceLocation newName = GTCEu.id(path.replace("input_buffer", "dual_input_hatch"));
- if (mapping.getRegistry().containsKey(newName)) {
- mapping.remap(mapping.getRegistry().getValue(newName));
- } else {
- mapping.remap(GTMachines.DUAL_IMPORT_HATCH[GTValues.LuV].getBlock());
- }
- } else if (path.contains("output_buffer")) {
- ResourceLocation newName = GTCEu.id(path.replace("output_buffer", "dual_output_hatch"));
- if (mapping.getRegistry().containsKey(newName)) {
- mapping.remap(mapping.getRegistry().getValue(newName));
- } else {
- mapping.remap(GTMachines.DUAL_EXPORT_HATCH[GTValues.LuV].getBlock());
- }
- }
- });
- event.getMappings(Registries.BLOCK_ENTITY_TYPE, "gregiceng").forEach(mapping -> {
- String path = mapping.getKey().getPath();
- switch (path) {
- case "stocking_bus", "adv_stocking_bus" -> mapping
- .remap(GTAEMachines.STOCKING_IMPORT_BUS_ME.getBlockEntityType());
- case "stocking_hatch", "adv_stocking_hatch" -> mapping
- .remap(GTAEMachines.STOCKING_IMPORT_HATCH_ME.getBlockEntityType());
- case "crafting_io_buffer" -> mapping.remap(GTAEMachines.ME_PATTERN_BUFFER.getBlockEntityType());
- case "crafting_io_slave" -> mapping.remap(GTAEMachines.ME_PATTERN_BUFFER_PROXY.getBlockEntityType());
- }
- if (path.contains("input_buffer")) {
- ResourceLocation newName = GTCEu.id(path.replace("input_buffer", "dual_input_hatch"));
- if (mapping.getRegistry().containsKey(newName)) {
- mapping.remap(mapping.getRegistry().getValue(newName));
- } else {
- mapping.remap(GTMachines.DUAL_IMPORT_HATCH[GTValues.LuV].getBlockEntityType());
- }
- } else if (path.contains("output_buffer")) {
- ResourceLocation newName = GTCEu.id(path.replace("output_buffer", "dual_output_hatch"));
- if (mapping.getRegistry().containsKey(newName)) {
- mapping.remap(mapping.getRegistry().getValue(newName));
- } else {
- mapping.remap(GTMachines.DUAL_EXPORT_HATCH[GTValues.LuV].getBlockEntityType());
- }
- }
- });
- event.getMappings(Registries.ITEM, "gregiceng").forEach(mapping -> {
- String path = mapping.getKey().getPath();
- switch (path) {
- case "stocking_bus", "adv_stocking_bus" -> mapping.remap(GTAEMachines.STOCKING_IMPORT_BUS_ME.getItem());
- case "stocking_hatch", "adv_stocking_hatch" -> mapping
- .remap(GTAEMachines.STOCKING_IMPORT_HATCH_ME.getItem());
- case "crafting_io_buffer" -> mapping.remap(GTAEMachines.ME_PATTERN_BUFFER.getItem());
- case "crafting_io_slave" -> mapping.remap(GTAEMachines.ME_PATTERN_BUFFER_PROXY.getItem());
- }
- if (path.contains("input_buffer")) {
- ResourceLocation newName = GTCEu.id(path.replace("input_buffer", "dual_input_hatch"));
- if (mapping.getRegistry().containsKey(newName)) {
- mapping.remap(mapping.getRegistry().getValue(newName));
- } else {
- mapping.remap(GTMachines.DUAL_IMPORT_HATCH[GTValues.LuV].getItem());
- }
- } else if (path.contains("output_buffer")) {
- ResourceLocation newName = GTCEu.id(path.replace("output_buffer", "dual_output_hatch"));
- if (mapping.getRegistry().containsKey(newName)) {
- mapping.remap(mapping.getRegistry().getValue(newName));
- } else {
- mapping.remap(GTMachines.DUAL_EXPORT_HATCH[GTValues.LuV].getItem());
- }
- }
- });
-
- for (TagPrefix prefix : TagPrefix.values()) {
- String first = prefix.invertedName ? toLowerCaseUnderscore(prefix.name) : "(.+?)";
- String last = prefix.invertedName ? "(.+?)" : toLowerCaseUnderscore(prefix.name);
- Pattern idPattern = Pattern.compile(first + "_" + last);
- event.getMappings(Registries.BLOCK, GTCEu.MOD_ID).forEach(mapping -> {
- Matcher matcher = idPattern.matcher(mapping.getKey().getPath());
- if (matcher.matches()) {
- BlockEntry extends Block> block = GTMaterialBlocks.MATERIAL_BLOCKS.get(prefix,
- GTRegistries.MATERIALS.get(GTCEu.id(matcher.group(1))));
- if (block != null && block.isPresent()) {
- mapping.remap(block.get());
- }
- }
- });
- event.getMappings(Registries.ITEM, GTCEu.MOD_ID).forEach(mapping -> {
- Matcher matcher = idPattern.matcher(mapping.getKey().getPath());
- if (matcher.matches()) {
- BlockEntry extends Block> block = GTMaterialBlocks.MATERIAL_BLOCKS.get(prefix,
- GTRegistries.MATERIALS.get(GTCEu.id(matcher.group(1))));
- if (block != null && block.isPresent()) {
- mapping.remap(block.asItem());
- } else {
- ItemEntry extends Item> item = GTMaterialItems.MATERIAL_ITEMS.get(prefix,
- GTRegistries.MATERIALS.get(GTCEu.id(matcher.group(1))));
- if (item != null && item.isPresent()) {
- mapping.remap(item.asItem());
- }
- }
- }
- });
- }
- }
}
diff --git a/src/main/java/com/gregtechceu/gtceu/common/CommonProxy.java b/src/main/java/com/gregtechceu/gtceu/common/CommonProxy.java
index 3f05df69dae..371ef70d1ce 100644
--- a/src/main/java/com/gregtechceu/gtceu/common/CommonProxy.java
+++ b/src/main/java/com/gregtechceu/gtceu/common/CommonProxy.java
@@ -27,6 +27,7 @@
import com.gregtechceu.gtceu.api.registry.registrate.GTRegistrate;
import com.gregtechceu.gtceu.common.data.*;
import com.gregtechceu.gtceu.common.data.GTPlaceholders;
+import com.gregtechceu.gtceu.common.data.datafixer.GTDataFixers;
import com.gregtechceu.gtceu.common.data.machines.GTMachineUtils;
import com.gregtechceu.gtceu.common.data.materials.GTFoods;
import com.gregtechceu.gtceu.common.item.tool.rotation.CustomBlockRotations;
@@ -183,6 +184,8 @@ public static void init() {
SyncedKeyMappings.init();
MachineOwner.init();
+ GTDataFixers.init();
+
FusionReactorMachine.registerFusionTier(GTValues.LuV, " (MKI)");
FusionReactorMachine.registerFusionTier(GTValues.ZPM, " (MKII)");
FusionReactorMachine.registerFusionTier(GTValues.UV, " (MKIII)");
diff --git a/src/main/java/com/gregtechceu/gtceu/common/data/datafixer/GTDataFixers.java b/src/main/java/com/gregtechceu/gtceu/common/data/datafixer/GTDataFixers.java
new file mode 100644
index 00000000000..485c87f4553
--- /dev/null
+++ b/src/main/java/com/gregtechceu/gtceu/common/data/datafixer/GTDataFixers.java
@@ -0,0 +1,150 @@
+package com.gregtechceu.gtceu.common.data.datafixer;
+
+import com.gregtechceu.gtceu.GTCEu;
+import com.gregtechceu.gtceu.api.datafixer.DataFixHelper;
+import com.gregtechceu.gtceu.api.datafixer.LazyDataFixer;
+import com.gregtechceu.gtceu.common.datafixer.fixes.AutoOutputTraitFix;
+import com.gregtechceu.gtceu.common.datafixer.schemas.*;
+import com.gregtechceu.gtceu.config.ConfigHolder;
+
+import net.minecraft.SharedConstants;
+import net.minecraft.util.datafix.fixes.*;
+import net.minecraft.util.datafix.schemas.NamespacedSchema;
+
+import com.google.common.util.concurrent.ThreadFactoryBuilder;
+import com.mojang.datafixers.DSL;
+import com.mojang.datafixers.DataFixUtils;
+import com.mojang.datafixers.DataFixer;
+import com.mojang.datafixers.DataFixerBuilder;
+import com.mojang.datafixers.schemas.Schema;
+import lombok.Getter;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.Map;
+import java.util.Objects;
+import java.util.Set;
+import java.util.concurrent.Executor;
+import java.util.concurrent.Executors;
+import java.util.function.BiFunction;
+import java.util.function.UnaryOperator;
+import java.util.regex.Pattern;
+
+/**
+ * Register new datafixers in {@link #addFixers(DataFixerBuilder)}. Remember to bump {@link GTCEu#GT_DATA_VERSION} in
+ * every PR that changes existing save data and add a schema & fixer for it here.
+ *
+ *
+ * For changes that do not change named types or add new (block) entities, use {@link #SAME_NAMESPACED} for the schema.
+ * Register machines (and other block entities) in a schema overriding {@link Schema#registerBlockEntities}.
+ *
+ *
+ *
DO NOT ADD NEW MACHINES TO {@link V0}!! THEY SHOULD BE IN NEW, CORRECTLY VERSIONED, SCHEMAS!!
+ * Reference vanilla schemas for more information on that, examples linked below. Also check how they're used in
+ * vanilla's {@link net.minecraft.util.datafix.DataFixers DataFixers}.
+ * {@link net.minecraft.util.datafix.schemas.V1460 V1460}, {@link net.minecraft.util.datafix.schemas.V1906 V1906}
+ *
+ *
+ * Note how only fields that use other registered types (such as item/fluid stacks) are defined. The same should be
+ * done for all types.
+ */
+@SuppressWarnings("SameParameterValue")
+public class GTDataFixers {
+
+ private static final BiFunction SAME_NAMESPACED = NamespacedSchema::new;
+
+ @Getter
+ private static final @Nullable DataFixer dataFixer = createFixer(SharedConstants.DATA_FIX_TYPES_TO_OPTIMIZE);
+
+ public static void init() {}
+
+ private static @Nullable DataFixer createFixer(final Set typesToOptimize) {
+ if (!ConfigHolder.INSTANCE.compat.doDataFixers) {
+ return null;
+ }
+
+ DataFixHelper.LOGGER.info("Registering data fixers");
+
+
+ return new LazyDataFixer(() -> {
+ try {
+ DataFixerBuilder builder = new DataFixerBuilder(GTCEu.GT_DATA_VERSION);
+ addFixers(builder);
+
+ if (typesToOptimize.isEmpty()) {
+ return builder.buildUnoptimized();
+ } else {
+ Executor executor = Executors.newSingleThreadExecutor(new ThreadFactoryBuilder()
+ .setNameFormat("GTCEu Datafixer Bootstrap").setDaemon(true).setPriority(1).build());
+ return builder.buildOptimized(typesToOptimize, executor);
+ }
+ } catch (Exception ex) {
+ DataFixHelper.LOGGER.warn("Failed to initialize! Either someone stopped DFU from initializing, or this Minecraft build is hosed.");
+ DataFixHelper.LOGGER.warn("Using no-op implementation.");
+ DataFixHelper.LOGGER.warn("Full error: ", ex);
+
+ return null;
+ }
+ });
+ }
+
+ public static void addFixers(DataFixerBuilder builder) {
+ builder.addSchema(new V0(DataFixUtils.makeKey(0), DataFixHelper.getLatestVanillaSchema()));
+
+ Schema v1 = builder.addSchema(1, V1::new);
+ createBlockItemRenameFix(builder, v1, "Rename RTM Alloy Coil Block",
+ createRenamer("tungstensteel_coil_block", "rtm_alloy_coil_block"));
+
+ builder.addFixer(ItemRenameFix.create(v1, "Rename Advanced Nanomuscle Chestplate",
+ createRenamer("gtceu:avanced_nanomuscle_chestplate", "gtceu:advanced_nanomuscle_chestplate")));
+
+ createBlockItemRenameFix(builder, v1, "Rename Palladium Substation Casing",
+ createRenamer("gtceu:palladium_substation", "gtceu:palladium_substation_casing"));
+
+ builder.addFixer(BlockRenameFix.create(v1, "Rename Tungstensteel Fluid Cell",
+ createRenamer("gtceu:tungstensteel_fluid_cell", "gtceu:tungsten_steel_fluid_cell")));
+
+ createBlockItemRenameFix(builder, v1, "Rename Low Pressure Steam Miner",
+ createRenamer("gtceu:steam_miner", "gtceu:lp_steam_miner"));
+
+ builder.addFixer(ItemRenameFix.create(v1, "Rename electric wire cutters",
+ createRenamer(Pattern.compile("([lhi])v_([a-z0-9/._-]+)_wirecutter"), "$1v_$2_wire_cutter")));
+
+ // separator
+
+ Schema v10 = builder.addSchema(10, SAME_NAMESPACED);
+ builder.addFixer(new AutoOutputTraitFix(v10));
+
+ /*
+ createBlockItemRenameFix(builder, schemaV11, "U238",
+ createRenamer(Pattern.compile("gtceu:(.*)uranium_"), "gtceu:$1uranium_238_"));
+ createBlockItemRenameFix(builder, schemaV11, "Pu239",
+ createRenamer(Pattern.compile("gtceu:(.*)plutonium_"), "gtceu:$1plutonium_239_"));
+ createBlockItemRenameFix(builder, schemaV11, "Red Granite",
+ createRenamer(Pattern.compile("gtceu:(.*)granite_red"), "gtceu:$1red_granite"));
+ createBlockItemRenameFix(builder, schemaV11, "Tungstensteel",
+ createRenamer(Pattern.compile("gtceu:(.*)tungstensteel"), "gtceu:$1tungsten_steel"));
+
+ createBlockItemRenameFix(builder, schemaV11, "Raw Oil",
+ createRenamer(OilVariantsRenameFix.RENAMED_ITEM_IDS));
+ */
+ }
+
+ private static void createBlockItemRenameFix(DataFixerBuilder builder, Schema schema, String name,
+ UnaryOperator renamer) {
+ builder.addFixer(ItemRenameFix.create(schema, name, renamer));
+ builder.addFixer(BlockRenameFix.create(schema, name, renamer));
+ builder.addFixer(BlockEntityRenameFix.create(schema, name, renamer));
+ }
+
+ private static UnaryOperator createRenamer(String oldName, String newName) {
+ return id -> Objects.equals(NamespacedSchema.ensureNamespaced(id), oldName) ? newName : id;
+ }
+
+ private static UnaryOperator createRenamer(Map renameMap) {
+ return id -> renameMap.getOrDefault(NamespacedSchema.ensureNamespaced(id), id);
+ }
+
+ private static UnaryOperator createRenamer(Pattern check, String replaceWith) {
+ return id -> check.matcher(NamespacedSchema.ensureNamespaced(id)).replaceAll(replaceWith);
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/com/gregtechceu/gtceu/common/data/datafixer/GTReferences.java b/src/main/java/com/gregtechceu/gtceu/common/data/datafixer/GTReferences.java
new file mode 100644
index 00000000000..16f34303073
--- /dev/null
+++ b/src/main/java/com/gregtechceu/gtceu/common/data/datafixer/GTReferences.java
@@ -0,0 +1,14 @@
+package com.gregtechceu.gtceu.common.data.datafixer;
+
+import com.mojang.datafixers.DSL;
+
+public class GTReferences {
+
+ public static final DSL.TypeReference MATERIAL_STACK = () -> "material_stack";
+ public static final DSL.TypeReference MATERIAL_NAME = () -> "material_name";
+
+ public static final DSL.TypeReference FLUID_STACK = () -> "fluid_stack";
+ public static final DSL.TypeReference FLUID_NAME = () -> "fluid_name";
+
+ public static final DSL.TypeReference FORGE_REGISTRY_DATA = () -> "forge_registry_data";
+}
\ No newline at end of file
diff --git a/src/main/java/com/gregtechceu/gtceu/common/data/datafixer/package-info.java b/src/main/java/com/gregtechceu/gtceu/common/data/datafixer/package-info.java
new file mode 100644
index 00000000000..d3f47b5873d
--- /dev/null
+++ b/src/main/java/com/gregtechceu/gtceu/common/data/datafixer/package-info.java
@@ -0,0 +1,4 @@
+@NotNullByDefault
+package com.gregtechceu.gtceu.common.data.datafixer;
+
+import org.jetbrains.annotations.NotNullByDefault;
diff --git a/src/main/java/com/gregtechceu/gtceu/common/datafixer/fixes/AutoOutputTraitFix.java b/src/main/java/com/gregtechceu/gtceu/common/datafixer/fixes/AutoOutputTraitFix.java
new file mode 100644
index 00000000000..b099b9e6747
--- /dev/null
+++ b/src/main/java/com/gregtechceu/gtceu/common/datafixer/fixes/AutoOutputTraitFix.java
@@ -0,0 +1,48 @@
+package com.gregtechceu.gtceu.common.datafixer.fixes;
+
+import net.minecraft.util.datafix.fixes.References;
+
+import com.mojang.datafixers.*;
+import com.mojang.datafixers.schemas.Schema;
+import com.mojang.serialization.Dynamic;
+
+import java.util.Map;
+
+public class AutoOutputTraitFix extends DataFix {
+
+ private static final Map FIELD_RENAMES = Map.of(
+ "outputFacingItems", "itemOutputDirection",
+ "outputFacingFluids", "fluidOutputDirection",
+ "autoOutputItems", "autoOutputItems",
+ "autoOutputFluids", "autoOutputFluids",
+ "allowInputFromOutputSideItems", "allowItemInputFromOutputSide",
+ "allowInputFromOutputSideFluids", "allowFluidInputFromOutputSide"
+ );
+
+ public AutoOutputTraitFix(Schema outputSchema) {
+ super(outputSchema, false);
+ }
+
+ @Override
+ protected TypeRewriteRule makeRule() {
+ return this.fixTypeEverywhereTyped("AutoOutputTraitFix", this.getInputSchema().getType(References.BLOCK_ENTITY), typed -> {
+ return typed.update(DSL.remainderFinder(), remainder -> {
+ Dynamic> traitValue = remainder.emptyMap();
+ for (var entry : FIELD_RENAMES.entrySet()) {
+ String oldName = entry.getKey();
+ String newName = entry.getValue();
+
+ var oldField = remainder.get(oldName).result();
+ if (oldField.isPresent()) {
+ traitValue = traitValue.set(newName, oldField.get());
+ remainder = remainder.remove(oldName);
+ }
+ }
+
+ remainder.set("autoOutput", traitValue);
+
+ return remainder;
+ });
+ });
+ }
+}
diff --git a/src/main/java/com/gregtechceu/gtceu/common/datafixer/fixes/OilVariantsRenameFix.java b/src/main/java/com/gregtechceu/gtceu/common/datafixer/fixes/OilVariantsRenameFix.java
new file mode 100644
index 00000000000..016fc5e7994
--- /dev/null
+++ b/src/main/java/com/gregtechceu/gtceu/common/datafixer/fixes/OilVariantsRenameFix.java
@@ -0,0 +1,17 @@
+package com.gregtechceu.gtceu.common.datafixer.fixes;
+
+import com.google.common.collect.ImmutableMap;
+
+import java.util.Map;
+
+public class OilVariantsRenameFix {
+
+ public static final Map RENAMED_IDS = ImmutableMap.builder()
+ .put("gtceu:oil_heavy", "gtceu:heavy_oil")
+ .put("gtceu:oil_light", "gtceu:light_oil")
+ .put("gtceu:oil_medium", "gtceu:raw_oil")
+ .put("gtceu:oil_heavy_bucket", "gtceu:heavy_oil_bucket")
+ .put("gtceu:oil_light_bucket", "gtceu:light_oil_bucket")
+ .put("gtceu:oil_medium_bucket", "gtceu:raw_oil_bucket")
+ .build();
+}
diff --git a/src/main/java/com/gregtechceu/gtceu/common/datafixer/fixes/package-info.java b/src/main/java/com/gregtechceu/gtceu/common/datafixer/fixes/package-info.java
new file mode 100644
index 00000000000..beb1ec92e54
--- /dev/null
+++ b/src/main/java/com/gregtechceu/gtceu/common/datafixer/fixes/package-info.java
@@ -0,0 +1,4 @@
+@NotNullByDefault
+package com.gregtechceu.gtceu.common.datafixer.fixes;
+
+import org.jetbrains.annotations.NotNullByDefault;
diff --git a/src/main/java/com/gregtechceu/gtceu/common/datafixer/schemas/V0.java b/src/main/java/com/gregtechceu/gtceu/common/datafixer/schemas/V0.java
new file mode 100644
index 00000000000..262551fc1da
--- /dev/null
+++ b/src/main/java/com/gregtechceu/gtceu/common/datafixer/schemas/V0.java
@@ -0,0 +1,501 @@
+package com.gregtechceu.gtceu.common.datafixer.schemas;
+
+import com.gregtechceu.gtceu.api.GTCEuAPI;
+import com.gregtechceu.gtceu.api.GTValues;
+import com.gregtechceu.gtceu.api.machine.MachineDefinition;
+import com.gregtechceu.gtceu.api.registry.GTRegistries;
+import com.gregtechceu.gtceu.common.data.datafixer.GTReferences;
+
+import com.mojang.datafixers.DSL;
+import com.mojang.datafixers.schemas.Schema;
+import com.mojang.datafixers.types.templates.TypeTemplate;
+
+import net.minecraft.util.datafix.fixes.References;
+import net.minecraft.util.datafix.schemas.NamespacedSchema;
+import net.minecraftforge.fml.loading.LoadingModList;
+
+import java.util.Locale;
+import java.util.Map;
+import java.util.function.Supplier;
+
+import static com.gregtechceu.gtceu.api.GTValues.*;
+import static com.gregtechceu.gtceu.common.data.machines.GTMachineUtils.*;
+import static com.gregtechceu.gtceu.common.data.machines.GTMachineUtils.ALL_TIERS;
+import static com.gregtechceu.gtceu.api.datafixer.types.ExtraDSL.*;
+import static com.mojang.datafixers.DSL.*;
+
+public class V0 extends NamespacedSchema {
+
+ public V0(int versionKey, Schema parent) {
+ super(versionKey, parent);
+ }
+
+ // spotless:off
+ @Override
+ public void registerTypes(Schema schema, Map> entityTypes,
+ Map> blockEntityTypes) {
+ super.registerTypes(schema, entityTypes, blockEntityTypes);
+
+ // add forge registry id map to the level schema
+ schema.registerType(false, GTReferences.FORGE_REGISTRY_DATA, () -> optionalFields(
+ "minecraft:block", optionalFields(
+ "ids", compoundList(References.BLOCK_NAME.in(schema), constType(intType())),
+ "aliases", compoundList(DSL.constType(namespacedString()), References.BLOCK_NAME.in(schema))
+ ),
+ "minecraft:item", optionalFields(
+ "ids", compoundList(References.ITEM_NAME.in(schema), constType(intType())),
+ "aliases", compoundList(DSL.constType(namespacedString()), References.ITEM_NAME.in(schema))
+ ),
+ "minecraft:fluid", optionalFields(
+ "ids", compoundList(GTReferences.FLUID_NAME.in(schema), constType(intType())),
+ "aliases", compoundList(DSL.constType(namespacedString()), GTReferences.FLUID_NAME.in(schema))
+ ),
+ "minecraft:entity_type", optionalFields(
+ "ids", compoundList(References.ENTITY_NAME.in(schema), constType(intType())),
+ "aliases", compoundList(DSL.constType(namespacedString()), References.ENTITY_NAME.in(schema))
+ )
+ ));
+
+
+ schema.registerType(false, GTReferences.MATERIAL_NAME, () -> constType(namespacedString()));
+
+ schema.registerType(true, GTReferences.FLUID_STACK, () -> optionalFields(
+ "FluidName", GTReferences.FLUID_NAME.in(schema),
+ "Tag", remainder()
+ ));
+ schema.registerType(false, GTReferences.FLUID_NAME, () -> constType(namespacedString()));
+ }
+
+ @Override
+ public Map> registerBlockEntities(Schema schema) {
+ Map> map = super.registerBlockEntities(schema);
+
+ // region steam
+ final Supplier steamMachine = () -> optionalFields(
+ "steamTank", notifiableFluidTank(schema)
+ );
+ final Supplier steamBoiler = () -> optionalFields(
+ "waterTank", notifiableFluidTank(schema),
+ steamMachine.get()
+ );
+ registerSteamMachine(schema, map, "steam_solid_boiler", () -> optionalFields(
+ "fuelHandler", notifiableItemHandler(schema),
+ "ashHandler", notifiableItemHandler(schema),
+ steamBoiler.get()
+ ));
+ registerSteamMachine(schema, map, "steam_liquid_boiler", () -> optionalFields(
+ "fuelTank", notifiableFluidTank(schema),
+ steamBoiler.get()
+ ));
+ registerSteamMachine(schema, map, "steam_solar_boiler", steamBoiler);
+ registerSimpleSteamMachine(schema, map, "extractor");
+ registerSimpleSteamMachine(schema, map, "steam_macerator");
+ registerSimpleSteamMachine(schema, map, "compressor");
+ registerSimpleSteamMachine(schema, map, "forge_hammer");
+ registerSimpleSteamMachine(schema, map, "furnace");
+ registerSimpleSteamMachine(schema, map, "alloy_smelter");
+ registerSimpleSteamMachine(schema, map, "rock_crusher");
+ schema.register(map, "steam_miner", () -> optionalFields(
+ "importItems", notifiableItemHandler(schema),
+ "exportItems", notifiableItemHandler(schema),
+ "steamTank", notifiableFluidTank(schema)
+ ));
+ // endregion
+
+ // region simple
+ registerForTiers(schema, map, "machine_hull", DSL::remainder, ALL_TIERS);
+ registerSimpleMachine(schema, map, "electric_furnace", ELECTRIC_TIERS);
+ registerSimpleMachine(schema, map, "alloy_smelter", ELECTRIC_TIERS);
+ registerSimpleMachine(schema, map, "arc_furnace", ELECTRIC_TIERS);
+ registerSimpleMachine(schema, map, "assembler", ELECTRIC_TIERS);
+ registerSimpleMachine(schema, map, "autoclave", ELECTRIC_TIERS);
+ registerSimpleMachine(schema, map, "bender", ELECTRIC_TIERS);
+ registerSimpleMachine(schema, map, "brewery", ELECTRIC_TIERS);
+ registerSimpleMachine(schema, map, "canner", ELECTRIC_TIERS);
+ registerSimpleMachine(schema, map, "centrifuge", ELECTRIC_TIERS);
+ registerSimpleMachine(schema, map, "chemical_bath", ELECTRIC_TIERS);
+ registerSimpleMachine(schema, map, "chemical_reactor", ELECTRIC_TIERS);
+ registerSimpleMachine(schema, map, "compressor", ELECTRIC_TIERS);
+ registerSimpleMachine(schema, map, "cutter", ELECTRIC_TIERS);
+ registerSimpleMachine(schema, map, "distillery", ELECTRIC_TIERS);
+ registerSimpleMachine(schema, map, "electrolyzer", ELECTRIC_TIERS);
+ registerSimpleMachine(schema, map, "electromagnetic_separator", ELECTRIC_TIERS);
+ registerSimpleMachine(schema, map, "extractor", ELECTRIC_TIERS);
+ registerSimpleMachine(schema, map, "extruder", ELECTRIC_TIERS);
+ registerSimpleMachine(schema, map, "fermenter", ELECTRIC_TIERS);
+ registerSimpleMachine(schema, map, "fluid_heater", ELECTRIC_TIERS);
+ registerSimpleMachine(schema, map, "fluid_solidifier", ELECTRIC_TIERS);
+ registerSimpleMachine(schema, map, "forge_hammer", ELECTRIC_TIERS);
+ registerSimpleMachine(schema, map, "forming_press", ELECTRIC_TIERS);
+ registerSimpleMachine(schema, map, "lathe", ELECTRIC_TIERS);
+ registerSimpleMachine(schema, map, "scanner", ELECTRIC_TIERS);
+ registerSimpleMachine(schema, map, "mixer", ELECTRIC_TIERS);
+ registerSimpleMachine(schema, map, "ore_washer", ELECTRIC_TIERS);
+ registerSimpleMachine(schema, map, "packer", ELECTRIC_TIERS);
+ registerSimpleMachine(schema, map, "polarizer", ELECTRIC_TIERS);
+ registerSimpleMachine(schema, map, "laser_engraver", ELECTRIC_TIERS);
+ registerSimpleMachine(schema, map, "sifter", ELECTRIC_TIERS);
+ registerSimpleMachine(schema, map, "thermal_centrifuge", ELECTRIC_TIERS);
+ registerSimpleMachine(schema, map, "wiremill", ELECTRIC_TIERS);
+ registerSimpleMachine(schema, map, "circuit_assembler", ELECTRIC_TIERS);
+ registerSimpleMachine(schema, map, "macerator", ELECTRIC_TIERS);
+ registerSimpleMachine(schema, map, "gas_collector", ELECTRIC_TIERS);
+ registerSimpleMachine(schema, map, "rock_crusher", ELECTRIC_TIERS);
+ registerSimpleMachine(schema, map, "air_scrubber", LOW_TIERS);
+ registerSimpleMachine(schema, map, "combustion", ELECTRIC_TIERS);
+ registerSimpleMachine(schema, map, "steam_turbine", ELECTRIC_TIERS);
+ registerSimpleMachine(schema, map, "gas_turbine", ELECTRIC_TIERS);
+ // endregion
+
+ // region electric
+ final int[] transformerTiers = GTValues.tiersBetween(ULV, GTCEuAPI.isHighTier() ? OpV : UV);
+ registerForTiers(schema, map, "transformer_1a", DSL::remainder, transformerTiers);
+ registerForTiers(schema, map, "transformer_2a", DSL::remainder, transformerTiers);
+ registerForTiers(schema, map, "transformer_4a", DSL::remainder, transformerTiers);
+ registerForTiers(schema, map, "transformer_16a", DSL::remainder, transformerTiers);
+
+ registerForTiers(schema, map, "1a_energy_converter", DSL::remainder, ALL_TIERS);
+ registerForTiers(schema, map, "4a_energy_converter", DSL::remainder, ALL_TIERS);
+ registerForTiers(schema, map, "8a_energy_converter", DSL::remainder, ALL_TIERS);
+ registerForTiers(schema, map, "16a_energy_converter", DSL::remainder, ALL_TIERS);
+
+ schema.registerSimple(map, "long_distance_item_pipeline_endpoint");
+ schema.registerSimple(map, "long_distance_fluid_pipeline_endpoint");
+ schema.registerSimple(map, "long_distance_fluid_pipeline_endpoint");
+
+ final Supplier batteryBuffer = () -> optionalFields(
+ "batteryInventory", itemHandler(schema)
+ );
+ registerForTiers(schema, map, "battery_buffer_4x", batteryBuffer, ALL_TIERS);
+ registerForTiers(schema, map, "battery_buffer_8x", batteryBuffer, ALL_TIERS);
+ registerForTiers(schema, map, "battery_buffer_16x", batteryBuffer, ALL_TIERS);
+ registerForTiers(schema, map, "charger_4x", batteryBuffer, ALL_TIERS);
+
+ registerForTiers(schema, map, "pump", () -> optionalFields(
+ "cache", notifiableFluidTank(schema)
+ ), LV, MV, HV, EV);
+ registerForTiers(schema, map, "fisher", () -> optionalFields(
+ "cache", notifiableItemHandler(schema),
+ "baitHandler", notifiableItemHandler(schema),
+ "chargerInventory", itemHandler(schema)
+ ), LV, MV, HV, EV, IV, LuV);
+ registerForTiers(schema, map, "block_breaker", () -> optionalFields(
+ "cache", notifiableItemHandler(schema),
+ "chargerInventory", itemHandler(schema)
+ ), LV, MV, HV, EV);
+ registerSimpleMachine(schema, map, "miner", LV, MV, HV);
+ registerForTiers(schema, map, "world_accelerator", DSL::remainder, LV, MV, HV, EV, IV, LuV, ZPM, UV);
+ registerForTiers(schema, map, "item_collector", () -> optionalFields(
+ "output", notifiableItemHandler(schema),
+ "chargerInventory", itemHandler(schema),
+ "filterInventory", itemHandler(schema)
+ ), LV, MV, HV, EV);
+ // endregion
+
+ // region storage
+ final Supplier itemStorage = () -> optionalFields(
+ "inventory", notifiableItemHandler(schema)
+ );
+ registerForTiers(schema, map, "buffer", () -> optionalFields(
+ "tank", notifiableFluidTank(schema),
+ itemStorage.get()
+ ), LV, MV, HV);
+ schema.registerSimple(map, "creative_energy");
+ schema.registerSimple(map, "creative_computation_provider");
+
+ final Supplier quantumChest = () -> optionalFields(
+ "lockedFluid", GTReferences.FLUID_STACK.in(schema),
+ "stored", GTReferences.FLUID_STACK.in(schema)
+ );
+ final Supplier quantumTank = () -> optionalFields(
+ "lockedItem", itemHandler(schema),
+ "stored", References.ITEM_STACK.in(schema)
+ );
+ schema.register(map, "creative_chest", quantumChest);
+ schema.register(map, "creative_tank", quantumTank);
+ registerForTiers(schema, map, "super_chest", quantumChest, LOW_TIERS);
+ registerForTiers(schema, map, "quantum_chest", quantumChest, HIGH_TIERS);
+ registerForTiers(schema, map, "super_tank", quantumTank, LOW_TIERS);
+ registerForTiers(schema, map, "quantum_tank", quantumTank, HIGH_TIERS);
+
+ schema.register(map, "wood_crate", itemStorage);
+ schema.register(map, "bronze_crate", itemStorage);
+ schema.register(map, "steel_crate", itemStorage);
+ schema.register(map, "aluminium_crate", itemStorage);
+ schema.register(map, "stainless_steel_crate", itemStorage);
+ schema.register(map, "titanium_crate", itemStorage);
+ schema.register(map, "tungsten_steel_crate", itemStorage);
+
+ final Supplier drum = () -> optionalFields(
+ "stored", GTReferences.FLUID_STACK.in(schema)
+ );
+ schema.register(map, "wood_drum", drum);
+ schema.register(map, "bronze_drum", drum);
+ schema.register(map, "steel_drum", drum);
+ schema.register(map, "aluminium_drum", drum);
+ schema.register(map, "stainless_steel_drum", drum);
+ schema.register(map, "gold_drum", drum);
+ schema.register(map, "titanium_drum", drum);
+ schema.register(map, "tungsten_steel_drum", drum);
+ // endregion
+
+ // region part
+ final Supplier itemBus = () -> optionalFields(
+ "circuitInventory", notifiableItemHandler(schema),
+ itemStorage.get()
+ );
+ registerForTiers(schema, map, "input_bus", itemBus, ALL_TIERS);
+ registerForTiers(schema, map, "output_bus", itemBus, ALL_TIERS);
+ final Supplier fluidHatch = () -> optionalFields(
+ "tank", notifiableFluidTank(schema),
+ "circuitInventory", notifiableItemHandler(schema)
+ );
+ registerForTiers(schema, map, "input_hatch", fluidHatch, ALL_TIERS);
+ registerForTiers(schema, map, "input_hatch_4x", fluidHatch, ALL_TIERS);
+ registerForTiers(schema, map, "input_hatch_9x", fluidHatch, ALL_TIERS);
+ registerForTiers(schema, map, "output_hatch", fluidHatch, ALL_TIERS);
+ registerForTiers(schema, map, "output_hatch_4x", fluidHatch, ALL_TIERS);
+ registerForTiers(schema, map, "output_hatch_9x", fluidHatch, ALL_TIERS);
+
+ registerForTiers(schema, map, "energy_input_hatch", DSL::remainder, ALL_TIERS);
+ registerForTiers(schema, map, "energy_output_hatch", DSL::remainder, ALL_TIERS);
+ registerForTiers(schema, map, "energy_input_hatch_4a", DSL::remainder, ALL_TIERS);
+ registerForTiers(schema, map, "energy_output_hatch_4a", DSL::remainder, ALL_TIERS);
+ registerForTiers(schema, map, "energy_input_hatch_16a", DSL::remainder, ALL_TIERS);
+ registerForTiers(schema, map, "energy_output_hatch_16a", DSL::remainder, ALL_TIERS);
+ registerForTiers(schema, map, "substation_input_hatch_64a", DSL::remainder, ALL_TIERS);
+ registerForTiers(schema, map, "substation_output_hatch_64a", DSL::remainder, ALL_TIERS);
+
+ registerForTiers(schema, map, "muffler_hatch", itemStorage, ELECTRIC_TIERS);
+
+ schema.register(map, "steam_input_bus", itemBus);
+ schema.register(map, "steam_output_bus", itemBus);
+ schema.register(map, "steam_input_hatch", fluidHatch);
+ schema.registerSimple(map, "coke_oven_hatch");
+ schema.register(map, "pump_hatch", fluidHatch);
+ final Supplier maintenanceHatch = () -> optionalFields(
+ "itemStackHandler", notifiableItemHandler(schema)
+ );
+ schema.register(map, "maintenance_hatch", maintenanceHatch);
+ schema.register(map, "configurable_maintenance_hatch", maintenanceHatch);
+ schema.register(map, "cleaning_maintenance_hatch", maintenanceHatch);
+ schema.register(map, "auto_maintenance_hatch", maintenanceHatch);
+
+ registerForTiers(schema, map, "item_passthrough_hatch", itemBus, ELECTRIC_TIERS);
+ registerForTiers(schema, map, "fluid_passthrough_hatch", fluidHatch, ELECTRIC_TIERS);
+ schema.register(map, "reservoir_hatch", fluidHatch);
+ final Supplier dualHatch = () -> optionalFields(
+ "tank", notifiableFluidTank(schema),
+ itemBus.get()
+ );
+ registerForTiers(schema, map, "dual_input_hatch", dualHatch, DUAL_HATCH_TIERS);
+ registerForTiers(schema, map, "dual_output_hatch", dualHatch, DUAL_HATCH_TIERS);
+
+ registerForTiers(schema, map, "diode", DSL::remainder, ELECTRIC_TIERS);
+ registerForTiers(schema, map, "rotor_holder", () -> optionalFields(
+ "rotorMaterial", GTReferences.MATERIAL_NAME.in(schema),
+ itemStorage.get()
+ ), GTValues.tiersBetween(HV, GTCEuAPI.isHighTier() ? OpV : UV));
+
+ registerForTiers(schema, map, "256a_laser_target_hatch", DSL::remainder, HIGH_TIERS);
+ registerForTiers(schema, map, "256a_laser_source_hatch", DSL::remainder, HIGH_TIERS);
+ registerForTiers(schema, map, "1024a_laser_target_hatch", DSL::remainder, HIGH_TIERS);
+ registerForTiers(schema, map, "1024a_laser_source_hatch", DSL::remainder, HIGH_TIERS);
+ registerForTiers(schema, map, "4096a_laser_target_hatch", DSL::remainder, HIGH_TIERS);
+ registerForTiers(schema, map, "4096a_laser_source_hatch", DSL::remainder, HIGH_TIERS);
+
+ schema.registerSimple(map, "monitor");
+ schema.registerSimple(map, "advanced_monitor");
+ // endregion
+
+ // region multiblock
+ schema.registerSimple(map, "bronze_large_boiler");
+ schema.registerSimple(map, "steel_large_boiler");
+ schema.registerSimple(map, "titanium_large_boiler");
+ schema.registerSimple(map, "tungstensteel_large_boiler");
+
+ final Supplier primitiveMachine = () -> optionalFields(
+ "importItems", notifiableItemHandler(schema),
+ "exportItems", notifiableItemHandler(schema),
+ "importFluids", notifiableFluidTank(schema),
+ "exportFluids", notifiableFluidTank(schema)
+ );
+ schema.register(map, "coke_oven", primitiveMachine);
+ schema.register(map, "primitive_blast_furnace", primitiveMachine);
+
+ schema.registerSimple(map, "electric_blast_furnace");
+ schema.registerSimple(map, "large_chemical_reactor");
+ schema.registerSimple(map, "implosion_compressor");
+ schema.registerSimple(map, "pyrolyse_oven");
+ schema.registerSimple(map, "multi_smelter");
+ schema.registerSimple(map, "cracker");
+ schema.registerSimple(map, "distillation_tower");
+ schema.registerSimple(map, "vacuum_freezer");
+ schema.registerSimple(map, "assembly_line");
+ schema.registerSimple(map, "primitive_pump");
+ schema.registerSimple(map, "steam_grinder");
+ schema.registerSimple(map, "steam_oven");
+ registerForTiers(schema, map, "fusion_reactor", DSL::remainder, LuV, ZPM, UV);
+ registerForTiers(schema, map, "fluid_drilling_rig", DSL::remainder, MV, HV, EV);
+ registerForTiers(schema, map, "large_miner", DSL::remainder, EV, IV, LuV);
+ schema.registerSimple(map, "cleanroom");
+ schema.registerSimple(map, "large_combustion_engine");
+ schema.registerSimple(map, "extreme_combustion_engine");
+ schema.registerSimple(map, "steam_large_turbine");
+ schema.registerSimple(map, "gas_large_turbine");
+ schema.registerSimple(map, "plasma_large_turbine");
+ schema.registerSimple(map, "active_transformer");
+ schema.registerSimple(map, "power_substation");
+ registerForTiers(schema, map, "bedrock_ore_miner", DSL::remainder, MV, HV, EV);
+ schema.registerSimple(map, "wooden_tank_valve");
+ schema.registerSimple(map, "wooden_multiblock_tank");
+ schema.registerSimple(map, "bronze_tank_valve");
+ schema.registerSimple(map, "bronze_multiblock_tank");
+ schema.registerSimple(map, "steel_tank_valve");
+ schema.registerSimple(map, "steel_multiblock_tank");
+
+ schema.registerSimple(map, "central_monitor");
+
+ // region GCYM
+ registerForTiers(schema, map, "parallel_hatch", DSL::remainder, IV, LuV, ZPM, UV);
+ schema.registerSimple(map, "large_maceration_tower");
+ schema.registerSimple(map, "large_chemical_bath");
+ schema.registerSimple(map, "large_centrifuge");
+ schema.registerSimple(map, "large_mixer");
+ schema.registerSimple(map, "large_electrolyzer");
+ schema.registerSimple(map, "large_electromagnet");
+ schema.registerSimple(map, "large_packer");
+ schema.registerSimple(map, "large_assembler");
+ schema.registerSimple(map, "large_circuit_assembler");
+ schema.registerSimple(map, "large_arc_smelter");
+ schema.registerSimple(map, "large_engraving_laser");
+ schema.registerSimple(map, "large_sifting_funnel");
+ schema.registerSimple(map, "alloy_blast_smelter");
+ schema.registerSimple(map, "large_autoclave");
+ schema.registerSimple(map, "large_material_press");
+ schema.registerSimple(map, "large_brewer");
+ schema.registerSimple(map, "large_cutter");
+ schema.registerSimple(map, "large_extractor");
+ schema.registerSimple(map, "large_extruder");
+ schema.registerSimple(map, "large_solidifier");
+ schema.registerSimple(map, "large_wiremill");
+ schema.registerSimple(map, "mega_blast_furnace"); // TODO add fixer to rename to "rotary_hearth_furnace"
+ schema.registerSimple(map, "mega_vacuum_freezer"); // TODO add fixer to rename to "bulk_blast_chiller"
+ // endregion
+ // endregion
+
+ // region research
+ schema.registerSimple(map, "research_station");
+ schema.register(map, "object_holder", () -> optionalFields(
+ "heldItems", notifiableItemHandler(schema)
+ ));
+ schema.registerSimple(map, "data_bank");
+ schema.registerSimple(map, "network_switch");
+ schema.registerSimple(map, "high_performance_computation_array");
+ schema.registerSimple(map, "computation_transmitter_hatch");
+ schema.registerSimple(map, "computation_receiver_hatch");
+ schema.registerSimple(map, "data_transmitter_hatch");
+ schema.registerSimple(map, "data_receiver_hatch");
+ final Supplier dataAccessHatch = () -> optionalFields(
+ "importItems", notifiableItemHandler(schema)
+ );
+ schema.register(map, "basic_data_access_hatch", dataAccessHatch);
+ schema.register(map, "data_access_hatch", dataAccessHatch);
+ schema.register(map, "advanced_data_access_hatch", dataAccessHatch);
+ schema.register(map, "creative_data_access_hatch", dataAccessHatch);
+ schema.registerSimple(map, "hpca_empty_component");
+ schema.registerSimple(map, "hpca_computation_component");
+ schema.registerSimple(map, "hpca_advanced_computation_component");
+ schema.registerSimple(map, "hpca_heat_sink_component");
+ schema.registerSimple(map, "hpca_active_cooler_component");
+ schema.registerSimple(map, "hpca_bridge_component");
+ // endregion
+
+ // region AE2 compat
+ if (LoadingModList.get().getModFileById(MODID_APPENG) != null) { // only add these if AE2 is loaded
+ schema.register(map, "me_input_bus", itemBus);
+ schema.register(map, "me_stocking_input_bus", itemBus);
+ schema.register(map, "me_output_bus", itemBus);
+ schema.register(map, "me_input_hatch", fluidHatch);
+ schema.register(map, "me_stocking_input_hatch", fluidHatch);
+ schema.register(map, "me_output_hatch", fluidHatch);
+ schema.register(map, "me_pattern_buffer", () -> optionalFields(
+ "patternInventory", itemHandler(schema),
+ "shareInventory", notifiableItemHandler(schema),
+ "shareTank", notifiableFluidTank(schema),
+ "internalInventory", list(
+ fields(
+ "inventory", list(References.ITEM_STACK.in(schema)),
+ "fluidInventory", list(GTReferences.FLUID_STACK.in(schema))
+ )
+ ),
+ itemBus.get()
+ ));
+ schema.registerSimple(map, "me_pattern_buffer_proxy");
+ }
+ // endregion
+
+ // register all remaining machines as very 'plain' types
+ for (MachineDefinition definition : GTRegistries.MACHINES) {
+ String id = definition.getId().toString();
+ if (!map.containsKey(id)) {
+ registerSimple(map, id);
+ }
+ }
+
+ return map;
+ }
+
+ @Override
+ public void register(final Map> map, String name, final Supplier template) {
+ if (name.indexOf(':') == -1) {
+ name = "gtceu:" + name;
+ }
+ map.put(name, template);
+ }
+
+ protected static void registerSimpleMachine(Schema schema, Map> map, String name, int... tiers) {
+ registerForTiers(schema, map, name, () -> optionalFields(
+ "importItems", notifiableItemHandler(schema),
+ "exportItems", notifiableItemHandler(schema),
+ "importFluids", notifiableFluidTank(schema),
+ "exportFluids", notifiableFluidTank(schema),
+ "chargerInventory", itemHandler(schema),
+ "circuitInventory", notifiableItemHandler(schema)
+ ), tiers);
+ }
+
+ protected static void registerForTiers(Schema schema, Map> map,
+ String name, Supplier template, int... tiers) {
+ for (int tier : tiers) {
+ schema.register(map, GTValues.VN[tier].toLowerCase(Locale.ROOT) + "_" + name, template);
+ }
+ }
+
+ protected static void registerSteamMachine(Schema schema, Map> map,
+ String name, Supplier template) {
+ schema.register(map, "lp_%s".formatted(name), template);
+ schema.register(map, "hp_%s".formatted(name), template);
+ }
+
+ protected static void registerSimpleSteamMachine(Schema schema, Map> map, String name) {
+ registerSteamMachine(schema, map, name, () -> optionalFields(
+ "importItems", notifiableItemHandler(schema),
+ "exportItems", notifiableItemHandler(schema),
+ "steamTank", notifiableFluidTank(schema)
+ ));
+ }
+
+ protected static TypeTemplate itemHandler(Schema schema) {
+ return field("Items", list(References.ITEM_STACK.in(schema)));
+ }
+
+ protected static TypeTemplate notifiableItemHandler(Schema schema) {
+ return field("storage", itemHandler(schema));
+ }
+
+ protected static TypeTemplate notifiableFluidTank(Schema schema) {
+ return field("storages", list(GTReferences.FLUID_STACK.in(schema)));
+ }
+ // spotless:on
+}
diff --git a/src/main/java/com/gregtechceu/gtceu/common/datafixer/schemas/V1.java b/src/main/java/com/gregtechceu/gtceu/common/datafixer/schemas/V1.java
new file mode 100644
index 00000000000..66feec14b07
--- /dev/null
+++ b/src/main/java/com/gregtechceu/gtceu/common/datafixer/schemas/V1.java
@@ -0,0 +1,28 @@
+package com.gregtechceu.gtceu.common.datafixer.schemas;
+
+import net.minecraft.util.datafix.schemas.NamespacedSchema;
+
+import com.mojang.datafixers.schemas.Schema;
+import com.mojang.datafixers.types.templates.TypeTemplate;
+
+import java.util.Map;
+import java.util.function.Supplier;
+
+import static com.gregtechceu.gtceu.common.datafixer.schemas.V0.*;
+
+public class V1 extends NamespacedSchema {
+
+ public V1(int versionKey, Schema parent) {
+ super(versionKey, parent);
+ }
+
+ @Override
+ public Map> registerBlockEntities(Schema schema) {
+ Map> map = super.registerBlockEntities(schema);
+
+ map.remove("steam_miner");
+ registerSimpleSteamMachine(schema, map, "steam_miner");
+
+ return map;
+ }
+}
diff --git a/src/main/java/com/gregtechceu/gtceu/common/datafixer/schemas/package-info.java b/src/main/java/com/gregtechceu/gtceu/common/datafixer/schemas/package-info.java
new file mode 100644
index 00000000000..a5712064fb1
--- /dev/null
+++ b/src/main/java/com/gregtechceu/gtceu/common/datafixer/schemas/package-info.java
@@ -0,0 +1,4 @@
+@NotNullByDefault
+package com.gregtechceu.gtceu.common.datafixer.schemas;
+
+import org.jetbrains.annotations.NotNullByDefault;
diff --git a/src/main/java/com/gregtechceu/gtceu/common/datafixers/TagFixer.java b/src/main/java/com/gregtechceu/gtceu/common/datafixers/TagFixer.java
deleted file mode 100644
index 7bf24e1a6a8..00000000000
--- a/src/main/java/com/gregtechceu/gtceu/common/datafixers/TagFixer.java
+++ /dev/null
@@ -1,39 +0,0 @@
-package com.gregtechceu.gtceu.common.datafixers;
-
-import com.gregtechceu.gtceu.utils.GTMath;
-
-import net.minecraft.nbt.CompoundTag;
-import net.minecraft.nbt.Tag;
-
-import java.util.Locale;
-
-public class TagFixer {
-
- public static final String[] FLUID_TAGS = {
- "currentMilliBucketsPerTick",
- "globalTransferSizeMillibuckets",
- "minValue",
- "maxValue",
- };
-
- // This is necessary for updating from old versions due to FluidStack long -> int changes
- // Any fluid-related long tags need to be turned into int tags
- public static void fixFluidTags(CompoundTag tag) {
- if (tag.contains("cover", Tag.TAG_COMPOUND)) {
- CompoundTag t = tag.getCompound("cover");
- for (String key : t.getAllKeys()) {
- var cover = t.getCompound(key);
- var id = cover.getCompound("uid").getString("id");
- if ((id.toLowerCase(Locale.ROOT).contains("fluid") || id.toLowerCase(Locale.ROOT).contains("pump"))) {
- var data = cover.getCompound("payload").getCompound("d");
- for (String fix_key : FLUID_TAGS) {
- if (data.contains(fix_key, Tag.TAG_LONG)) {
- var l = data.getLong(fix_key);
- data.putInt(fix_key, GTMath.saturatedCast(l));
- }
- }
- }
- }
- }
- }
-}
diff --git a/src/main/java/com/gregtechceu/gtceu/config/ConfigHolder.java b/src/main/java/com/gregtechceu/gtceu/config/ConfigHolder.java
index 8e617deda31..4ed7710a333 100644
--- a/src/main/java/com/gregtechceu/gtceu/config/ConfigHolder.java
+++ b/src/main/java/com/gregtechceu/gtceu/config/ConfigHolder.java
@@ -30,6 +30,11 @@ public static void init() {
}
}
+ public static ConfigHolder getInstance() {
+ init();
+ return INSTANCE;
+ }
+
@Configurable
public RecipeConfigs recipes = new RecipeConfigs();
@Configurable
@@ -186,6 +191,13 @@ public static class RecipeConfigs {
public static class CompatibilityConfigs {
+ @Configurable
+ @Configurable.Comment({ "Whether to run datafixers on world load.",
+ "Do note that mods like ModernFix will interfere with this.",
+ "Default: true" })
+ @Configurable.UpdateRestriction(UpdateRestrictions.MAIN_MENU)
+ public boolean doDataFixers = true;
+
@Configurable
@Configurable.Comment("Config options regarding GTEU compatibility with other energy systems")
public EnergyCompatConfig energy = new EnergyCompatConfig();
diff --git a/src/main/java/com/gregtechceu/gtceu/core/mixins/datafixer/DataFixTypesMixin.java b/src/main/java/com/gregtechceu/gtceu/core/mixins/datafixer/DataFixTypesMixin.java
new file mode 100644
index 00000000000..324c3678592
--- /dev/null
+++ b/src/main/java/com/gregtechceu/gtceu/core/mixins/datafixer/DataFixTypesMixin.java
@@ -0,0 +1,29 @@
+package com.gregtechceu.gtceu.core.mixins.datafixer;
+
+import com.gregtechceu.gtceu.api.datafixer.DataFixHelper;
+import com.llamalad7.mixinextras.injector.ModifyReturnValue;
+import com.mojang.datafixers.DSL;
+import com.mojang.serialization.Dynamic;
+import net.minecraft.util.datafix.DataFixTypes;
+import org.spongepowered.asm.mixin.Final;
+import org.spongepowered.asm.mixin.Mixin;
+import org.spongepowered.asm.mixin.Shadow;
+import org.spongepowered.asm.mixin.injection.At;
+
+@Mixin(DataFixTypes.class)
+public class DataFixTypesMixin {
+
+ @Shadow
+ @Final
+ private DSL.TypeReference type;
+
+ // ModifyReturnValue to inject our fixes *after* vanilla ones
+ @ModifyReturnValue(method = "update(Lcom/mojang/datafixers/DataFixer;Lcom/mojang/serialization/Dynamic;II)Lcom/mojang/serialization/Dynamic;",
+ at = @At(value = "RETURN"))
+ private Dynamic gtceu$injectDataFixers(Dynamic value) {
+ // skip applying datafixers to options.txt; doing that loads the fixers too early
+ if ((Object) this == DataFixTypes.OPTIONS) return value;
+
+ return DataFixHelper.updateToCurrentVersion(this.type, value);
+ }
+}
diff --git a/src/main/java/com/gregtechceu/gtceu/core/mixins/datafixer/ForgeHooksMixin.java b/src/main/java/com/gregtechceu/gtceu/core/mixins/datafixer/ForgeHooksMixin.java
new file mode 100644
index 00000000000..12fc7c77953
--- /dev/null
+++ b/src/main/java/com/gregtechceu/gtceu/core/mixins/datafixer/ForgeHooksMixin.java
@@ -0,0 +1,38 @@
+package com.gregtechceu.gtceu.core.mixins.datafixer;
+
+import com.gregtechceu.gtceu.GTCEu;
+import com.gregtechceu.gtceu.api.datafixer.DataFixHelper;
+import com.gregtechceu.gtceu.common.data.datafixer.GTReferences;
+
+import net.minecraft.nbt.CompoundTag;
+import net.minecraft.nbt.NbtUtils;
+import net.minecraftforge.common.ForgeHooks;
+
+import com.llamalad7.mixinextras.expression.Definition;
+import com.llamalad7.mixinextras.expression.Expression;
+import com.llamalad7.mixinextras.injector.ModifyExpressionValue;
+import com.llamalad7.mixinextras.sugar.Local;
+import org.spongepowered.asm.mixin.Mixin;
+import org.spongepowered.asm.mixin.injection.At;
+
+@Mixin(value = ForgeHooks.class, remap = false)
+public class ForgeHooksMixin {
+
+ @Definition(id = "CompoundTag", type = CompoundTag.class)
+ @Definition(id = "fmlData", local = @Local(name = "fmlData", type = CompoundTag.class), remap = false)
+ @Expression("fmlData = @(new CompoundTag())")
+ @ModifyExpressionValue(method = "writeAdditionalLevelSaveData", at = @At("MIXINEXTRAS:EXPRESSION"))
+ private static CompoundTag gtceu$addDataVersions(CompoundTag fmlData) {
+ return NbtUtils.addCurrentDataVersion(fmlData);
+ }
+
+ @Definition(id = "tag", local = @Local(type = CompoundTag.class, name = "tag"))
+ @Definition(id = "getCompound", method = "Lnet/minecraft/nbt/CompoundTag;getCompound(Ljava/lang/String;)Lnet/minecraft/nbt/CompoundTag;", remap = true)
+ @Expression("tag.getCompound('Registries')")
+ @ModifyExpressionValue(method = "readAdditionalLevelSaveData", at = @At(value = "MIXINEXTRAS:EXPRESSION"))
+ private static CompoundTag gtceu$fixRegistriesTag(CompoundTag regs,
+ @Local(name = "tag") CompoundTag tag) {
+ int currentVersion = DataFixHelper.getGTDataVersion(tag);
+ return DataFixHelper.update(GTReferences.FORGE_REGISTRY_DATA, regs, currentVersion, GTCEu.GT_DATA_VERSION);
+ }
+}
diff --git a/src/main/java/com/gregtechceu/gtceu/core/mixins/datafixer/NbtUtilsMixin.java b/src/main/java/com/gregtechceu/gtceu/core/mixins/datafixer/NbtUtilsMixin.java
new file mode 100644
index 00000000000..88f32528aa4
--- /dev/null
+++ b/src/main/java/com/gregtechceu/gtceu/core/mixins/datafixer/NbtUtilsMixin.java
@@ -0,0 +1,17 @@
+package com.gregtechceu.gtceu.core.mixins.datafixer;
+
+import com.gregtechceu.gtceu.api.datafixer.DataFixHelper;
+import com.llamalad7.mixinextras.injector.ModifyReturnValue;
+import net.minecraft.nbt.CompoundTag;
+import net.minecraft.nbt.NbtUtils;
+import org.spongepowered.asm.mixin.Mixin;
+import org.spongepowered.asm.mixin.injection.At;
+
+@Mixin(NbtUtils.class)
+public class NbtUtilsMixin {
+
+ @ModifyReturnValue(method = "addDataVersion", at = @At("RETURN"))
+ private static CompoundTag gtceu$addGTDataVersion(CompoundTag tag) {
+ return DataFixHelper.addGTDataVersion(tag);
+ }
+}
diff --git a/src/main/java/com/gregtechceu/gtceu/utils/data/TagCompatibilityFixer.java b/src/main/java/com/gregtechceu/gtceu/utils/data/TagCompatibilityFixer.java
index f6ee9efc56f..0333aa969a2 100644
--- a/src/main/java/com/gregtechceu/gtceu/utils/data/TagCompatibilityFixer.java
+++ b/src/main/java/com/gregtechceu/gtceu/utils/data/TagCompatibilityFixer.java
@@ -9,25 +9,7 @@
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public final class TagCompatibilityFixer {
- public static void fixMachineAutoOutputTag(CompoundTag machineTag) {
- if (!machineTag.contains("autoOutput")) {
- var outputTag = new CompoundTag();
- Tag itemOutputDirection = machineTag.get("outputFacingItems");
- Tag fluidOutputDirection = machineTag.get("outputFacingFluids");
- Tag autoOutputItems = machineTag.get("autoOutputItems");
- Tag autoOutputFluids = machineTag.get("autoOutputFluids");
- Tag allowInputItems = machineTag.get("allowInputFromOutputSideItems");
- Tag allowInputFluids = machineTag.get("allowInputFromOutputSideFluids");
- if (itemOutputDirection != null) outputTag.put("itemOutputDirection", itemOutputDirection);
- if (fluidOutputDirection != null) outputTag.put("fluidOutputDirection", fluidOutputDirection);
- if (autoOutputItems != null) outputTag.put("autoOutputItems", autoOutputItems);
- if (autoOutputFluids != null) outputTag.put("autoOutputFluids", autoOutputFluids);
- if (allowInputItems != null) outputTag.put("allowItemInputFromOutputSide", allowInputItems);
- if (allowInputFluids != null) outputTag.put("allowFluidInputFromOutputSide", allowInputFluids);
- machineTag.put("autoOutput", outputTag);
- }
- }
-
+ // TODO convert into datafixer
public static Tag stripLDLibPayloadWrapper(Tag t) {
if (!(t instanceof CompoundTag tag)) return t;
if (tag.contains("p") && tag.contains("t")) {
diff --git a/src/main/resources/gtceu.mixins.json b/src/main/resources/gtceu.mixins.json
index 4d4c326abf7..1088e9c73ba 100644
--- a/src/main/resources/gtceu.mixins.json
+++ b/src/main/resources/gtceu.mixins.json
@@ -1,6 +1,9 @@
{
"required": true,
"minVersion": "0.8",
+ "mixinextras": {
+ "minVersion": "0.5.0-rc.3"
+ },
"refmap": "gtceu.refmap.json",
"package": "com.gregtechceu.gtceu.core.mixins",
"compatibilityLevel": "JAVA_17",
@@ -65,6 +68,9 @@
"TagManagerMixin",
"TagValueAccessor",
"client.ItemEntityMixin",
+ "datafixer.DataFixTypesMixin",
+ "datafixer.ForgeHooksMixin",
+ "datafixer.NbtUtilsMixin",
"dev.datagen.FixParallelKeyMappingRegistrationMixin",
"dev.test.GameTestRegistryMixin",
"emi.EmiRecipeFillerMixin",