Add codec data provider (#2979)

This commit is contained in:
ErrorCraft 2023-04-23 14:02:49 +02:00 committed by GitHub
parent 77589c6df2
commit f4f4ac6445
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 111 additions and 0 deletions

View file

@ -0,0 +1,88 @@
/*
* 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.provider;
import java.nio.file.Path;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.function.BiConsumer;
import com.google.gson.JsonElement;
import com.mojang.serialization.Codec;
import com.mojang.serialization.DataResult;
import com.mojang.serialization.JsonOps;
import net.minecraft.data.DataOutput;
import net.minecraft.data.DataProvider;
import net.minecraft.data.DataWriter;
import net.minecraft.util.Identifier;
import net.fabricmc.fabric.api.datagen.v1.FabricDataGenerator;
import net.fabricmc.fabric.api.datagen.v1.FabricDataOutput;
/**
* Extend this class and implement {@link FabricCodecDataProvider#configure}.
*
* <p>Register an instance of the class with {@link FabricDataGenerator.Pack#addProvider} in a {@link net.fabricmc.fabric.api.datagen.v1.DataGeneratorEntrypoint}.
*/
public abstract class FabricCodecDataProvider<T> implements DataProvider {
private final DataOutput.PathResolver pathResolver;
private final Codec<T> codec;
protected FabricCodecDataProvider(FabricDataOutput dataOutput, DataOutput.OutputType outputType, String directoryName, Codec<T> codec) {
this.pathResolver = dataOutput.getResolver(outputType, directoryName);
this.codec = codec;
}
@Override
public CompletableFuture<?> run(DataWriter writer) {
Map<Identifier, JsonElement> entries = new HashMap<>();
BiConsumer<Identifier, T> provider = (id, value) -> {
JsonElement json = this.convert(id, value);
JsonElement existingJson = entries.put(id, json);
if (existingJson != null) {
throw new IllegalArgumentException("Duplicate entry " + id);
}
};
this.configure(provider);
return this.write(writer, entries);
}
/**
* Implement this method to register entries to generate.
*
* @param provider A consumer that accepts an {@link Identifier} and a value to register.
*/
protected abstract void configure(BiConsumer<Identifier, T> provider);
private JsonElement convert(Identifier id, T value) {
DataResult<JsonElement> dataResult = this.codec.encodeStart(JsonOps.INSTANCE, value);
return dataResult.get()
.mapRight(partial -> "Invalid entry %s: %s".formatted(id, partial.message()))
.orThrow();
}
private CompletableFuture<?> write(DataWriter writer, Map<Identifier, JsonElement> entries) {
return CompletableFuture.allOf(entries.entrySet().stream().map(entry -> {
Path path = this.pathResolver.resolveJson(entry.getKey());
return DataProvider.writeToPath(writer, entry.getValue(), path);
}).toArray(CompletableFuture[]::new));
}
}

View file

@ -26,6 +26,7 @@ import static net.fabricmc.fabric.test.datagen.DataGeneratorTestContent.SIMPLE_I
import java.io.IOException; import java.io.IOException;
import java.nio.file.Path; import java.nio.file.Path;
import java.util.List;
import java.util.Optional; import java.util.Optional;
import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletableFuture;
import java.util.function.BiConsumer; import java.util.function.BiConsumer;
@ -38,7 +39,11 @@ import net.minecraft.advancement.Advancement;
import net.minecraft.advancement.AdvancementFrame; import net.minecraft.advancement.AdvancementFrame;
import net.minecraft.advancement.criterion.OnKilledCriterion; import net.minecraft.advancement.criterion.OnKilledCriterion;
import net.minecraft.block.Blocks; import net.minecraft.block.Blocks;
import net.minecraft.client.texture.atlas.AtlasSource;
import net.minecraft.client.texture.atlas.AtlasSourceManager;
import net.minecraft.client.texture.atlas.DirectoryAtlasSource;
import net.minecraft.registry.RegistryKeys; import net.minecraft.registry.RegistryKeys;
import net.minecraft.data.DataOutput;
import net.minecraft.data.client.BlockStateModelGenerator; import net.minecraft.data.client.BlockStateModelGenerator;
import net.minecraft.data.client.ItemModelGenerator; import net.minecraft.data.client.ItemModelGenerator;
import net.minecraft.data.server.recipe.RecipeJsonProvider; import net.minecraft.data.server.recipe.RecipeJsonProvider;
@ -69,6 +74,7 @@ import net.fabricmc.fabric.api.datagen.v1.FabricDataGenerator;
import net.fabricmc.fabric.api.datagen.v1.FabricDataOutput; import net.fabricmc.fabric.api.datagen.v1.FabricDataOutput;
import net.fabricmc.fabric.api.datagen.v1.provider.FabricAdvancementProvider; 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.FabricBlockLootTableProvider;
import net.fabricmc.fabric.api.datagen.v1.provider.FabricCodecDataProvider;
import net.fabricmc.fabric.api.datagen.v1.provider.FabricLanguageProvider; import net.fabricmc.fabric.api.datagen.v1.provider.FabricLanguageProvider;
import net.fabricmc.fabric.api.datagen.v1.provider.FabricModelProvider; import net.fabricmc.fabric.api.datagen.v1.provider.FabricModelProvider;
import net.fabricmc.fabric.api.datagen.v1.provider.FabricRecipeProvider; import net.fabricmc.fabric.api.datagen.v1.provider.FabricRecipeProvider;
@ -98,6 +104,7 @@ public class DataGeneratorTestEntrypoint implements DataGeneratorEntrypoint {
TestBlockTagProvider blockTagProvider = pack.addProvider(TestBlockTagProvider::new); TestBlockTagProvider blockTagProvider = pack.addProvider(TestBlockTagProvider::new);
pack.addProvider((output, registries) -> new TestItemTagProvider(output, registries, blockTagProvider)); pack.addProvider((output, registries) -> new TestItemTagProvider(output, registries, blockTagProvider));
pack.addProvider(TestBiomeTagProvider::new); pack.addProvider(TestBiomeTagProvider::new);
pack.addProvider(TestAtlasSourceProvider::new);
} }
private static class TestRecipeProvider extends FabricRecipeProvider { private static class TestRecipeProvider extends FabricRecipeProvider {
@ -350,4 +357,20 @@ public class DataGeneratorTestEntrypoint implements DataGeneratorEntrypoint {
); );
} }
} }
private static class TestAtlasSourceProvider extends FabricCodecDataProvider<List<AtlasSource>> {
private TestAtlasSourceProvider(FabricDataOutput dataOutput) {
super(dataOutput, DataOutput.OutputType.RESOURCE_PACK, "atlases", AtlasSourceManager.LIST_CODEC);
}
@Override
protected void configure(BiConsumer<Identifier, List<AtlasSource>> provider) {
provider.accept(new Identifier(MOD_ID, "atlas_source_test"), List.of(new DirectoryAtlasSource("example", "example/")));
}
@Override
public String getName() {
return "Atlas Sources";
}
}
} }