From bbae80faea5a35d2a522fb3814a79aef79cc898c Mon Sep 17 00:00:00 2001 From: ErrorCraft <51973682+ErrorCraft@users.noreply.github.com> Date: Mon, 18 Sep 2023 17:11:50 +0200 Subject: [PATCH] Add a method to data generator entrypoints to register custom keys with priorities (#3087) * Add JsonKeySortOrderCallback * Use an entry point rather than an event for sort keys and priorities * Resolve static imports * Add a bit of javadoc * Check if a key is null and modify the javadoc * Add a field reference in the javadoc * Rename JsonKeySortOrderAdder to JsonKeySortOrderCallback (cherry picked from commit 0883a8d4d9c2253a8fb394dccc7fdbda4f456a05) --- .../datagen/v1/DataGeneratorEntrypoint.java | 7 ++++ .../datagen/v1/JsonKeySortOrderCallback.java | 32 +++++++++++++++++++ .../impl/datagen/FabricDataGenHelper.java | 16 ++++++++++ .../datagen/DataGeneratorTestEntrypoint.java | 6 ++++ .../DataGeneratorClientTestEntrypoint.java | 6 ++++ 5 files changed, 67 insertions(+) create mode 100644 fabric-data-generation-api-v1/src/main/java/net/fabricmc/fabric/api/datagen/v1/JsonKeySortOrderCallback.java diff --git a/fabric-data-generation-api-v1/src/main/java/net/fabricmc/fabric/api/datagen/v1/DataGeneratorEntrypoint.java b/fabric-data-generation-api-v1/src/main/java/net/fabricmc/fabric/api/datagen/v1/DataGeneratorEntrypoint.java index a0290152d..48b739e15 100644 --- a/fabric-data-generation-api-v1/src/main/java/net/fabricmc/fabric/api/datagen/v1/DataGeneratorEntrypoint.java +++ b/fabric-data-generation-api-v1/src/main/java/net/fabricmc/fabric/api/datagen/v1/DataGeneratorEntrypoint.java @@ -60,4 +60,11 @@ public interface DataGeneratorEntrypoint { */ default void buildRegistry(RegistryBuilder registryBuilder) { } + + /** + * Provides a callback for setting the sort priority of object keys in generated JSON files. + * @param callback a callback for setting the sort priority for a given key + */ + default void addJsonKeySortOrders(JsonKeySortOrderCallback callback) { + } } diff --git a/fabric-data-generation-api-v1/src/main/java/net/fabricmc/fabric/api/datagen/v1/JsonKeySortOrderCallback.java b/fabric-data-generation-api-v1/src/main/java/net/fabricmc/fabric/api/datagen/v1/JsonKeySortOrderCallback.java new file mode 100644 index 000000000..a65425581 --- /dev/null +++ b/fabric-data-generation-api-v1/src/main/java/net/fabricmc/fabric/api/datagen/v1/JsonKeySortOrderCallback.java @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2016, 2017, 2018, 2019 FabricMC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package net.fabricmc.fabric.api.datagen.v1; + +/** + * Provides a callback for setting the sort priority of object keys in generated JSON files. + */ +@FunctionalInterface +public interface JsonKeySortOrderCallback { + /** + * Sets the sort priority for a given object key within generated JSON files. + * @param key the key to set priority for + * @param priority the priority for the key, where keys with lower priority are sorted before keys with higher priority + * @implNote The default priority is 2. + * @see net.minecraft.data.DataProvider#JSON_KEY_SORT_ORDER + */ + void add(String key, int priority); +} diff --git a/fabric-data-generation-api-v1/src/main/java/net/fabricmc/fabric/impl/datagen/FabricDataGenHelper.java b/fabric-data-generation-api-v1/src/main/java/net/fabricmc/fabric/impl/datagen/FabricDataGenHelper.java index 6cbf74ca3..e6cba0e02 100644 --- a/fabric-data-generation-api-v1/src/main/java/net/fabricmc/fabric/impl/datagen/FabricDataGenHelper.java +++ b/fabric-data-generation-api-v1/src/main/java/net/fabricmc/fabric/impl/datagen/FabricDataGenHelper.java @@ -20,6 +20,7 @@ import java.nio.file.Path; import java.nio.file.Paths; import java.util.ArrayList; import java.util.HashMap; +import java.util.HashSet; import java.util.IdentityHashMap; import java.util.List; import java.util.Map; @@ -28,11 +29,13 @@ import java.util.concurrent.CompletableFuture; import com.mojang.logging.LogUtils; import com.mojang.serialization.Lifecycle; +import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap; import org.apache.commons.lang3.ArrayUtils; import org.jetbrains.annotations.Nullable; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import net.minecraft.data.DataProvider; import net.minecraft.registry.BuiltinRegistries; import net.minecraft.registry.DynamicRegistryManager; import net.minecraft.registry.Registerable; @@ -107,6 +110,9 @@ public final class FabricDataGenHelper { final List entrypoints = dataGeneratorInitializers.stream().map(EntrypointContainer::getEntrypoint).toList(); CompletableFuture registriesFuture = CompletableFuture.supplyAsync(() -> createRegistryWrapper(entrypoints), Util.getMainWorkerExecutor()); + Object2IntOpenHashMap jsonKeySortOrders = (Object2IntOpenHashMap) DataProvider.JSON_KEY_SORT_ORDER; + Object2IntOpenHashMap defaultJsonKeySortOrders = new Object2IntOpenHashMap<>(jsonKeySortOrders); + for (EntrypointContainer entrypointContainer : dataGeneratorInitializers) { final String id = entrypointContainer.getProvider().getMetadata().getId(); @@ -123,6 +129,13 @@ public final class FabricDataGenHelper { final String effectiveModId = entrypoint.getEffectiveModId(); ModContainer modContainer = entrypointContainer.getProvider(); + HashSet keys = new HashSet<>(); + entrypoint.addJsonKeySortOrders((key, value) -> { + Objects.requireNonNull(key, "Tried to register a priority for a null key"); + jsonKeySortOrders.put(key, value); + keys.add(key); + }); + if (effectiveModId != null) { modContainer = FabricLoader.getInstance().getModContainer(effectiveModId).orElseThrow(() -> new RuntimeException("Failed to find effective mod container for mod id (%s)".formatted(effectiveModId))); } @@ -130,6 +143,9 @@ public final class FabricDataGenHelper { FabricDataGenerator dataGenerator = new FabricDataGenerator(outputDir, modContainer, STRICT_VALIDATION, registriesFuture); entrypoint.onInitializeDataGenerator(dataGenerator); dataGenerator.run(); + + jsonKeySortOrders.keySet().removeAll(keys); + jsonKeySortOrders.putAll(defaultJsonKeySortOrders); } catch (Throwable t) { throw new RuntimeException("Failed to run data generator from mod (%s)".formatted(id), t); } diff --git a/fabric-data-generation-api-v1/src/testmod/java/net/fabricmc/fabric/test/datagen/DataGeneratorTestEntrypoint.java b/fabric-data-generation-api-v1/src/testmod/java/net/fabricmc/fabric/test/datagen/DataGeneratorTestEntrypoint.java index 86f6f9942..7a34666aa 100644 --- a/fabric-data-generation-api-v1/src/testmod/java/net/fabricmc/fabric/test/datagen/DataGeneratorTestEntrypoint.java +++ b/fabric-data-generation-api-v1/src/testmod/java/net/fabricmc/fabric/test/datagen/DataGeneratorTestEntrypoint.java @@ -74,6 +74,7 @@ import net.fabricmc.api.EnvType; import net.fabricmc.fabric.api.datagen.v1.DataGeneratorEntrypoint; import net.fabricmc.fabric.api.datagen.v1.FabricDataGenerator; import net.fabricmc.fabric.api.datagen.v1.FabricDataOutput; +import net.fabricmc.fabric.api.datagen.v1.JsonKeySortOrderCallback; import net.fabricmc.fabric.api.datagen.v1.provider.FabricAdvancementProvider; import net.fabricmc.fabric.api.datagen.v1.provider.FabricBlockLootTableProvider; import net.fabricmc.fabric.api.datagen.v1.provider.FabricDynamicRegistryProvider; @@ -92,6 +93,11 @@ public class DataGeneratorTestEntrypoint implements DataGeneratorEntrypoint { private static final ConditionJsonProvider NEVER_LOADED = DefaultResourceConditions.allModsLoaded("a"); private static final ConditionJsonProvider ALWAYS_LOADED = DefaultResourceConditions.not(NEVER_LOADED); + @Override + public void addJsonKeySortOrders(JsonKeySortOrderCallback callback) { + callback.add("trigger", 0); + } + @Override public void onInitializeDataGenerator(FabricDataGenerator dataGenerator) { final FabricDataGenerator.Pack pack = dataGenerator.createPack(); diff --git a/fabric-data-generation-api-v1/src/testmodClient/java/net/fabricmc/fabric/test/datagen/client/DataGeneratorClientTestEntrypoint.java b/fabric-data-generation-api-v1/src/testmodClient/java/net/fabricmc/fabric/test/datagen/client/DataGeneratorClientTestEntrypoint.java index ee9e178cd..2d6ce1ce7 100644 --- a/fabric-data-generation-api-v1/src/testmodClient/java/net/fabricmc/fabric/test/datagen/client/DataGeneratorClientTestEntrypoint.java +++ b/fabric-data-generation-api-v1/src/testmodClient/java/net/fabricmc/fabric/test/datagen/client/DataGeneratorClientTestEntrypoint.java @@ -30,10 +30,16 @@ import net.minecraft.util.Identifier; import net.fabricmc.fabric.api.datagen.v1.DataGeneratorEntrypoint; import net.fabricmc.fabric.api.datagen.v1.FabricDataGenerator; import net.fabricmc.fabric.api.datagen.v1.FabricDataOutput; +import net.fabricmc.fabric.api.datagen.v1.JsonKeySortOrderCallback; import net.fabricmc.fabric.api.datagen.v1.provider.FabricCodecDataProvider; @SuppressWarnings("unused") public class DataGeneratorClientTestEntrypoint implements DataGeneratorEntrypoint { + @Override + public void addJsonKeySortOrders(JsonKeySortOrderCallback callback) { + callback.add("type", 100); // Force 'type' at the end + } + @Override public void onInitializeDataGenerator(FabricDataGenerator dataGenerator) { final FabricDataGenerator.Pack pack = dataGenerator.createBuiltinResourcePack(new Identifier(MOD_ID, "example_builtin"));