mirror of
https://github.com/SquidDev-CC/CC-Tweaked
synced 2025-01-10 01:10:30 +00:00
Reformat JSON by wrapping CachedOutput
Rather than mixing-in to CachedOutput, we just wrap our DataProviders to use a custom CachedOutput which reformats the JSON before writing. This allows us to drop mixins for common+non-client code.
This commit is contained in:
parent
1788afacfc
commit
359c8d6652
@ -0,0 +1,48 @@
|
|||||||
|
// SPDX-FileCopyrightText: 2024 The CC: Tweaked Developers
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: MPL-2.0
|
||||||
|
|
||||||
|
package dan200.computercraft.data;
|
||||||
|
|
||||||
|
import com.google.common.hash.HashCode;
|
||||||
|
import com.google.common.hash.HashFunction;
|
||||||
|
import com.google.common.hash.Hashing;
|
||||||
|
import net.minecraft.data.CachedOutput;
|
||||||
|
import net.minecraft.data.DataProvider;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.nio.file.Path;
|
||||||
|
import java.util.concurrent.CompletableFuture;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wraps an existing {@link DataProvider}, passing generated JSON through {@link PrettyJsonWriter}.
|
||||||
|
*
|
||||||
|
* @param provider The provider to wrap.
|
||||||
|
* @param <T> The type of the provider to wrap.
|
||||||
|
*/
|
||||||
|
public record PrettyDataProvider<T extends DataProvider>(T provider) implements DataProvider {
|
||||||
|
@Override
|
||||||
|
public CompletableFuture<?> run(CachedOutput cachedOutput) {
|
||||||
|
return provider.run(new Output(cachedOutput));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return provider.getName();
|
||||||
|
}
|
||||||
|
|
||||||
|
private record Output(CachedOutput output) implements CachedOutput {
|
||||||
|
@SuppressWarnings("unused")
|
||||||
|
private static final HashFunction HASH_FUNCTION = Hashing.sha1();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void writeIfNeeded(Path path, byte[] bytes, HashCode hashCode) throws IOException {
|
||||||
|
if (path.getFileName().toString().endsWith(".json")) {
|
||||||
|
bytes = PrettyJsonWriter.reformat(bytes);
|
||||||
|
hashCode = HASH_FUNCTION.hashBytes(bytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
output.writeIfNeeded(path, bytes, hashCode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -22,11 +22,10 @@ import java.util.List;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Alternative version of {@link JsonWriter} which attempts to lay out the JSON in a more compact format.
|
* Alternative version of {@link JsonWriter} which attempts to lay out the JSON in a more compact format.
|
||||||
* <p>
|
*
|
||||||
* Yes, this is at least a little deranged.
|
* @see PrettyDataProvider
|
||||||
*/
|
*/
|
||||||
public class PrettyJsonWriter extends JsonWriter {
|
public class PrettyJsonWriter extends JsonWriter {
|
||||||
public static final boolean ENABLED = System.getProperty("cct.pretty-json") != null;
|
|
||||||
private static final Gson GSON = new GsonBuilder().setPrettyPrinting().disableHtmlEscaping().create();
|
private static final Gson GSON = new GsonBuilder().setPrettyPrinting().disableHtmlEscaping().create();
|
||||||
|
|
||||||
private static final int MAX_WIDTH = 120;
|
private static final int MAX_WIDTH = 120;
|
||||||
@ -44,17 +43,6 @@ public class PrettyJsonWriter extends JsonWriter {
|
|||||||
this.out = out;
|
this.out = out;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a JSON writer. This will either be a pretty or normal version, depending on whether the global flag is
|
|
||||||
* set.
|
|
||||||
*
|
|
||||||
* @param out The writer to emit to.
|
|
||||||
* @return The constructed JSON writer.
|
|
||||||
*/
|
|
||||||
public static JsonWriter createWriter(Writer out) {
|
|
||||||
return ENABLED ? new PrettyJsonWriter(out) : new JsonWriter(out);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reformat a JSON string with our pretty printer.
|
* Reformat a JSON string with our pretty printer.
|
||||||
*
|
*
|
||||||
@ -62,8 +50,6 @@ public class PrettyJsonWriter extends JsonWriter {
|
|||||||
* @return The reformatted string.
|
* @return The reformatted string.
|
||||||
*/
|
*/
|
||||||
public static byte[] reformat(byte[] contents) {
|
public static byte[] reformat(byte[] contents) {
|
||||||
if (!ENABLED) return contents;
|
|
||||||
|
|
||||||
JsonElement object;
|
JsonElement object;
|
||||||
try (var reader = new InputStreamReader(new ByteArrayInputStream(contents), StandardCharsets.UTF_8)) {
|
try (var reader = new InputStreamReader(new ByteArrayInputStream(contents), StandardCharsets.UTF_8)) {
|
||||||
object = GSON.fromJson(reader, JsonElement.class);
|
object = GSON.fromJson(reader, JsonElement.class);
|
||||||
|
@ -1,25 +0,0 @@
|
|||||||
// SPDX-FileCopyrightText: 2022 The CC: Tweaked Developers
|
|
||||||
//
|
|
||||||
// SPDX-License-Identifier: MPL-2.0
|
|
||||||
|
|
||||||
package dan200.computercraft.mixin;
|
|
||||||
|
|
||||||
import dan200.computercraft.data.PrettyJsonWriter;
|
|
||||||
import org.spongepowered.asm.mixin.Mixin;
|
|
||||||
import org.spongepowered.asm.mixin.injection.At;
|
|
||||||
import org.spongepowered.asm.mixin.injection.ModifyArg;
|
|
||||||
|
|
||||||
@Mixin(targets = "net/minecraft/data/HashCache$CacheUpdater")
|
|
||||||
public class CacheUpdaterMixin {
|
|
||||||
@SuppressWarnings("UnusedMethod")
|
|
||||||
@ModifyArg(
|
|
||||||
method = "writeIfNeeded",
|
|
||||||
at = @At(value = "INVOKE", target = "Ljava/nio/file/Files;write(Ljava/nio/file/Path;[B[Ljava/nio/file/OpenOption;)Ljava/nio/file/Path;"),
|
|
||||||
require = 0
|
|
||||||
)
|
|
||||||
private byte[] reformatJson(byte[] contents) {
|
|
||||||
// It would be cleaner to do this inside DataProvider.saveStable, but Forge's version of Mixin doesn't allow us
|
|
||||||
// to inject into interfaces.
|
|
||||||
return PrettyJsonWriter.reformat(contents);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,13 +0,0 @@
|
|||||||
{
|
|
||||||
"required": true,
|
|
||||||
"package": "dan200.computercraft.mixin",
|
|
||||||
"minVersion": "0.8",
|
|
||||||
"compatibilityLevel": "JAVA_17",
|
|
||||||
"injectors": {
|
|
||||||
"defaultRequire": 1
|
|
||||||
},
|
|
||||||
"mixins": [
|
|
||||||
"CacheUpdaterMixin"
|
|
||||||
],
|
|
||||||
"refmap": "computercraft.refmap.json"
|
|
||||||
}
|
|
@ -146,7 +146,6 @@ loom {
|
|||||||
client()
|
client()
|
||||||
|
|
||||||
runDir("run/dataGen")
|
runDir("run/dataGen")
|
||||||
property("cct.pretty-json")
|
|
||||||
property("fabric-api.datagen")
|
property("fabric-api.datagen")
|
||||||
property("fabric-api.datagen.output-dir", file("src/generated/resources").absolutePath)
|
property("fabric-api.datagen.output-dir", file("src/generated/resources").absolutePath)
|
||||||
property("fabric-api.datagen.strict-validation")
|
property("fabric-api.datagen.strict-validation")
|
||||||
|
@ -36,20 +36,28 @@ import java.util.function.Consumer;
|
|||||||
public class FabricDataGenerators implements DataGeneratorEntrypoint {
|
public class FabricDataGenerators implements DataGeneratorEntrypoint {
|
||||||
@Override
|
@Override
|
||||||
public void onInitializeDataGenerator(FabricDataGenerator generator) {
|
public void onInitializeDataGenerator(FabricDataGenerator generator) {
|
||||||
var pack = generator.createPack();
|
var pack = new PlatformGeneratorsImpl(generator.createPack());
|
||||||
DataProviders.add(new PlatformGeneratorsImpl(pack));
|
DataProviders.add(pack);
|
||||||
pack.addProvider((out, reg) -> addName("Conventional Tags", new MoreConventionalTagsProvider(out, reg)));
|
pack.addWithRegistries((out, reg) -> addName("Conventional Tags", new MoreConventionalTagsProvider(out, reg)));
|
||||||
}
|
}
|
||||||
|
|
||||||
private record PlatformGeneratorsImpl(FabricDataGenerator.Pack generator) implements DataProviders.GeneratorSink {
|
private record PlatformGeneratorsImpl(FabricDataGenerator.Pack generator) implements DataProviders.GeneratorSink {
|
||||||
|
public <T extends DataProvider> T addWithFabricOutput(FabricDataGenerator.Pack.Factory<T> factory) {
|
||||||
|
return generator.addProvider((FabricDataOutput p) -> new PrettyDataProvider<>(factory.create(p))).provider();
|
||||||
|
}
|
||||||
|
|
||||||
|
public <T extends DataProvider> T addWithRegistries(FabricDataGenerator.Pack.RegistryDependentFactory<T> factory) {
|
||||||
|
return generator.addProvider((r, p) -> new PrettyDataProvider<>(factory.create(r, p))).provider();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <T extends DataProvider> T add(DataProvider.Factory<T> factory) {
|
public <T extends DataProvider> T add(DataProvider.Factory<T> factory) {
|
||||||
return generator.addProvider(factory);
|
return generator.addProvider((PackOutput p) -> new PrettyDataProvider<>(factory.create(p))).provider();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <T> void addFromCodec(String name, PackType type, String directory, Codec<T> codec, Consumer<BiConsumer<ResourceLocation, T>> output) {
|
public <T> void addFromCodec(String name, PackType type, String directory, Codec<T> codec, Consumer<BiConsumer<ResourceLocation, T>> output) {
|
||||||
generator.addProvider((FabricDataOutput out) -> {
|
addWithFabricOutput((FabricDataOutput out) -> {
|
||||||
var ourType = switch (type) {
|
var ourType = switch (type) {
|
||||||
case SERVER_DATA -> PackOutput.Target.DATA_PACK;
|
case SERVER_DATA -> PackOutput.Target.DATA_PACK;
|
||||||
case CLIENT_RESOURCES -> PackOutput.Target.RESOURCE_PACK;
|
case CLIENT_RESOURCES -> PackOutput.Target.RESOURCE_PACK;
|
||||||
@ -71,7 +79,7 @@ public class FabricDataGenerators implements DataGeneratorEntrypoint {
|
|||||||
@Override
|
@Override
|
||||||
public void lootTable(List<LootTableProvider.SubProviderEntry> tables) {
|
public void lootTable(List<LootTableProvider.SubProviderEntry> tables) {
|
||||||
for (var table : tables) {
|
for (var table : tables) {
|
||||||
generator.addProvider((FabricDataOutput out) -> new SimpleFabricLootTableProvider(out, table.paramSet()) {
|
addWithFabricOutput((FabricDataOutput out) -> new SimpleFabricLootTableProvider(out, table.paramSet()) {
|
||||||
@Override
|
@Override
|
||||||
public void generate(BiConsumer<ResourceLocation, LootTable.Builder> exporter) {
|
public void generate(BiConsumer<ResourceLocation, LootTable.Builder> exporter) {
|
||||||
table.provider().get().generate(exporter);
|
table.provider().get().generate(exporter);
|
||||||
@ -82,7 +90,7 @@ public class FabricDataGenerators implements DataGeneratorEntrypoint {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public TagsProvider<Block> blockTags(Consumer<TagProvider.TagConsumer<Block>> tags) {
|
public TagsProvider<Block> blockTags(Consumer<TagProvider.TagConsumer<Block>> tags) {
|
||||||
return generator.addProvider((out, registries) -> new FabricTagProvider.BlockTagProvider(out, registries) {
|
return addWithRegistries((out, registries) -> new FabricTagProvider.BlockTagProvider(out, registries) {
|
||||||
@Override
|
@Override
|
||||||
protected void addTags(HolderLookup.Provider registries) {
|
protected void addTags(HolderLookup.Provider registries) {
|
||||||
tags.accept(x -> new TagProvider.TagAppender<>(RegistryWrappers.BLOCKS, getOrCreateRawBuilder(x)));
|
tags.accept(x -> new TagProvider.TagAppender<>(RegistryWrappers.BLOCKS, getOrCreateRawBuilder(x)));
|
||||||
@ -92,7 +100,7 @@ public class FabricDataGenerators implements DataGeneratorEntrypoint {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public TagsProvider<Item> itemTags(Consumer<TagProvider.ItemTagConsumer> tags, TagsProvider<Block> blocks) {
|
public TagsProvider<Item> itemTags(Consumer<TagProvider.ItemTagConsumer> tags, TagsProvider<Block> blocks) {
|
||||||
return generator.addProvider((out, registries) -> new FabricTagProvider.ItemTagProvider(out, registries, (FabricTagProvider.BlockTagProvider) blocks) {
|
return addWithRegistries((out, registries) -> new FabricTagProvider.ItemTagProvider(out, registries, (FabricTagProvider.BlockTagProvider) blocks) {
|
||||||
@Override
|
@Override
|
||||||
protected void addTags(HolderLookup.Provider registries) {
|
protected void addTags(HolderLookup.Provider registries) {
|
||||||
var self = this;
|
var self = this;
|
||||||
@ -113,7 +121,7 @@ public class FabricDataGenerators implements DataGeneratorEntrypoint {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void models(Consumer<BlockModelGenerators> blocks, Consumer<ItemModelGenerators> items) {
|
public void models(Consumer<BlockModelGenerators> blocks, Consumer<ItemModelGenerators> items) {
|
||||||
generator.addProvider((FabricDataOutput out) -> new FabricModelProvider(out) {
|
addWithFabricOutput((FabricDataOutput out) -> new FabricModelProvider(out) {
|
||||||
@Override
|
@Override
|
||||||
public void generateBlockStateModels(BlockModelGenerators generator) {
|
public void generateBlockStateModels(BlockModelGenerators generator) {
|
||||||
blocks.accept(generator);
|
blocks.accept(generator);
|
||||||
|
@ -37,7 +37,6 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"mixins": [
|
"mixins": [
|
||||||
"computercraft.mixins.json",
|
|
||||||
"computercraft.fabric.mixins.json",
|
"computercraft.fabric.mixins.json",
|
||||||
{
|
{
|
||||||
"config": "computercraft-client.mixins.json",
|
"config": "computercraft-client.mixins.json",
|
||||||
|
@ -58,7 +58,6 @@ minecraft {
|
|||||||
"--existing", project(":common").file("src/main/resources/"),
|
"--existing", project(":common").file("src/main/resources/"),
|
||||||
"--existing", file("src/main/resources/"),
|
"--existing", file("src/main/resources/"),
|
||||||
)
|
)
|
||||||
property("cct.pretty-json", "true")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun RunConfig.configureForGameTest() {
|
fun RunConfig.configureForGameTest() {
|
||||||
@ -110,7 +109,6 @@ mixin {
|
|||||||
add(sourceSets.main.get(), "computercraft.refmap.json")
|
add(sourceSets.main.get(), "computercraft.refmap.json")
|
||||||
add(sourceSets.client.get(), "client-computercraft.refmap.json")
|
add(sourceSets.client.get(), "client-computercraft.refmap.json")
|
||||||
|
|
||||||
config("computercraft.mixins.json")
|
|
||||||
config("computercraft-client.mixins.json")
|
config("computercraft-client.mixins.json")
|
||||||
config("computercraft-client.forge.mixins.json")
|
config("computercraft-client.forge.mixins.json")
|
||||||
}
|
}
|
||||||
|
@ -51,12 +51,12 @@ public class Generators {
|
|||||||
) implements DataProviders.GeneratorSink {
|
) implements DataProviders.GeneratorSink {
|
||||||
@Override
|
@Override
|
||||||
public <T extends DataProvider> T add(DataProvider.Factory<T> factory) {
|
public <T extends DataProvider> T add(DataProvider.Factory<T> factory) {
|
||||||
return generator.addProvider(factory);
|
return generator.addProvider(p -> new PrettyDataProvider<>(factory.create(p))).provider();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public <T> void addFromCodec(String name, PackType type, String directory, Codec<T> codec, Consumer<BiConsumer<ResourceLocation, T>> output) {
|
public <T> void addFromCodec(String name, PackType type, String directory, Codec<T> codec, Consumer<BiConsumer<ResourceLocation, T>> output) {
|
||||||
generator.addProvider(out -> {
|
add(out -> {
|
||||||
Map<ResourceLocation, T> map = new HashMap<>();
|
Map<ResourceLocation, T> map = new HashMap<>();
|
||||||
output.accept(map::put);
|
output.accept(map::put);
|
||||||
return new JsonCodecProvider<>(out, existingFiles, ComputerCraftAPI.MOD_ID, JsonOps.INSTANCE, type, directory, codec, map);
|
return new JsonCodecProvider<>(out, existingFiles, ComputerCraftAPI.MOD_ID, JsonOps.INSTANCE, type, directory, codec, map);
|
||||||
|
Loading…
Reference in New Issue
Block a user