From 28c7be21390f153b13766600dff93bf8f166349d Mon Sep 17 00:00:00 2001 From: apple502j <33279053+apple502j@users.noreply.github.com> Date: Mon, 13 Feb 2023 18:30:09 +0900 Subject: [PATCH] GameTest: Improve structure loading (#2801) * GameTest: improve structure loading * Address issues * Re-run actions * Test missing template * Revert "Test missing template" This reverts commit 0e7189bf73505f7561393cc595b7c18cbf76c6a1. * Update fabric-gametest-api-v1/src/main/java/net/fabricmc/fabric/mixin/gametest/StructureTemplateManagerMixin.java Co-authored-by: Juuz <6596629+Juuxel@users.noreply.github.com> --------- Co-authored-by: Juuz <6596629+Juuxel@users.noreply.github.com> (cherry picked from commit 2ff127f537875ccbc1349603cccc0a70304a3235) --- fabric-gametest-api-v1/build.gradle | 4 + .../impl/gametest/FabricGameTestHelper.java | 5 ++ .../StructureTemplateManagerMixin.java | 82 +++++++++++++++++++ .../gametest/StructureTestUtilMixin.java | 68 --------------- .../fabric-gametest-api-v1.accesswidener | 4 + .../fabric-gametest-api-v1.mixins.json | 2 +- .../src/main/resources/fabric.mod.json | 1 + 7 files changed, 97 insertions(+), 69 deletions(-) create mode 100644 fabric-gametest-api-v1/src/main/java/net/fabricmc/fabric/mixin/gametest/StructureTemplateManagerMixin.java delete mode 100644 fabric-gametest-api-v1/src/main/java/net/fabricmc/fabric/mixin/gametest/StructureTestUtilMixin.java create mode 100644 fabric-gametest-api-v1/src/main/resources/fabric-gametest-api-v1.accesswidener diff --git a/fabric-gametest-api-v1/build.gradle b/fabric-gametest-api-v1/build.gradle index 25cdb5b0d..ea10eb466 100644 --- a/fabric-gametest-api-v1/build.gradle +++ b/fabric-gametest-api-v1/build.gradle @@ -1,6 +1,10 @@ archivesBaseName = "fabric-gametest-api-v1" version = getSubprojectVersion(project) +loom { + accessWidenerPath = file("src/main/resources/fabric-gametest-api-v1.accesswidener") +} + moduleDependencies(project, [ 'fabric-api-base', 'fabric-resource-loader-v0' diff --git a/fabric-gametest-api-v1/src/main/java/net/fabricmc/fabric/impl/gametest/FabricGameTestHelper.java b/fabric-gametest-api-v1/src/main/java/net/fabricmc/fabric/impl/gametest/FabricGameTestHelper.java index cd7b466bb..8aeb1b02c 100644 --- a/fabric-gametest-api-v1/src/main/java/net/fabricmc/fabric/impl/gametest/FabricGameTestHelper.java +++ b/fabric-gametest-api-v1/src/main/java/net/fabricmc/fabric/impl/gametest/FabricGameTestHelper.java @@ -28,6 +28,7 @@ import javax.xml.parsers.ParserConfigurationException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import net.minecraft.resource.ResourceFinder; import net.minecraft.resource.ResourcePackManager; import net.minecraft.server.MinecraftServer; import net.minecraft.server.command.TestCommand; @@ -59,6 +60,10 @@ public final class FabricGameTestHelper { private static final Logger LOGGER = LoggerFactory.getLogger(FabricGameTestHelper.class); + private static final String GAMETEST_STRUCTURE_PATH = "gametest/structures"; + + public static final ResourceFinder GAMETEST_STRUCTURE_FINDER = new ResourceFinder(GAMETEST_STRUCTURE_PATH, ".snbt"); + private FabricGameTestHelper() { } diff --git a/fabric-gametest-api-v1/src/main/java/net/fabricmc/fabric/mixin/gametest/StructureTemplateManagerMixin.java b/fabric-gametest-api-v1/src/main/java/net/fabricmc/fabric/mixin/gametest/StructureTemplateManagerMixin.java new file mode 100644 index 000000000..0fef61d94 --- /dev/null +++ b/fabric-gametest-api-v1/src/main/java/net/fabricmc/fabric/mixin/gametest/StructureTemplateManagerMixin.java @@ -0,0 +1,82 @@ +/* + * 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.mixin.gametest; + +import java.io.IOException; +import java.util.Optional; +import java.util.stream.Stream; + +import com.google.common.collect.ImmutableList; +import com.mojang.brigadier.exceptions.CommandSyntaxException; +import com.mojang.datafixers.DataFixer; +import org.apache.commons.io.IOUtils; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import org.spongepowered.asm.mixin.injection.callback.LocalCapture; + +import net.minecraft.block.Block; +import net.minecraft.nbt.NbtCompound; +import net.minecraft.nbt.NbtHelper; +import net.minecraft.registry.RegistryEntryLookup; +import net.minecraft.resource.Resource; +import net.minecraft.resource.ResourceFinder; +import net.minecraft.resource.ResourceManager; +import net.minecraft.structure.StructureTemplate; +import net.minecraft.structure.StructureTemplateManager; +import net.minecraft.util.Identifier; +import net.minecraft.world.level.storage.LevelStorage; + +import net.fabricmc.fabric.impl.gametest.FabricGameTestHelper; + +@Mixin(StructureTemplateManager.class) +public abstract class StructureTemplateManagerMixin { + @Shadow + private ResourceManager resourceManager; + + @Shadow + public abstract StructureTemplate createTemplate(NbtCompound nbt); + + private Optional<StructureTemplate> fabric_loadSnbtFromResource(Identifier id) { + Identifier path = FabricGameTestHelper.GAMETEST_STRUCTURE_FINDER.toResourcePath(id); + Optional<Resource> resource = this.resourceManager.getResource(path); + + if (resource.isPresent()) { + try { + String snbt = IOUtils.toString(resource.get().getReader()); + NbtCompound nbt = NbtHelper.fromNbtProviderString(snbt); + return Optional.of(this.createTemplate(nbt)); + } catch (IOException | CommandSyntaxException e) { + throw new RuntimeException("Failed to load GameTest structure " + id, e); + } + } + + return Optional.empty(); + } + + private Stream<Identifier> fabric_streamTemplatesFromResource() { + ResourceFinder finder = FabricGameTestHelper.GAMETEST_STRUCTURE_FINDER; + return finder.findResources(this.resourceManager).keySet().stream().map(finder::toResourceId); + } + + @Inject(method = "<init>", at = @At(value = "INVOKE", target = "Lcom/google/common/collect/ImmutableList$Builder;add(Ljava/lang/Object;)Lcom/google/common/collect/ImmutableList$Builder;", ordinal = 2, shift = At.Shift.AFTER), locals = LocalCapture.CAPTURE_FAILHARD) + private void addFabricTemplateProvider(ResourceManager resourceManager, LevelStorage.Session session, DataFixer dataFixer, RegistryEntryLookup<Block> blockLookup, CallbackInfo ci, ImmutableList.Builder<StructureTemplateManager.Provider> builder) { + builder.add(new StructureTemplateManager.Provider(this::fabric_loadSnbtFromResource, this::fabric_streamTemplatesFromResource)); + } +} diff --git a/fabric-gametest-api-v1/src/main/java/net/fabricmc/fabric/mixin/gametest/StructureTestUtilMixin.java b/fabric-gametest-api-v1/src/main/java/net/fabricmc/fabric/mixin/gametest/StructureTestUtilMixin.java deleted file mode 100644 index 26c23b9ba..000000000 --- a/fabric-gametest-api-v1/src/main/java/net/fabricmc/fabric/mixin/gametest/StructureTestUtilMixin.java +++ /dev/null @@ -1,68 +0,0 @@ -/* - * 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.mixin.gametest; - -import java.io.IOException; -import java.io.InputStream; -import java.nio.charset.StandardCharsets; - -import com.mojang.brigadier.exceptions.CommandSyntaxException; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; - -import net.minecraft.nbt.NbtCompound; -import net.minecraft.nbt.NbtHelper; -import net.minecraft.resource.Resource; -import net.minecraft.server.world.ServerWorld; -import net.minecraft.structure.StructureTemplate; -import net.minecraft.test.StructureTestUtil; -import net.minecraft.util.Identifier; - -@Mixin(StructureTestUtil.class) -public abstract class StructureTestUtilMixin { - private static final String GAMETEST_STRUCTURE_PATH = "gametest/structures/"; - - // Replace the default test structure loading with something that works a bit better for mods. - @Inject(at = @At("HEAD"), method = "createStructureTemplate(Ljava/lang/String;Lnet/minecraft/server/world/ServerWorld;)Lnet/minecraft/structure/StructureTemplate;", cancellable = true) - private static void createStructure(String id, ServerWorld world, CallbackInfoReturnable<StructureTemplate> cir) { - Identifier baseId = new Identifier(id); - Identifier structureId = new Identifier(baseId.getNamespace(), GAMETEST_STRUCTURE_PATH + baseId.getPath() + ".snbt"); - - try { - Resource resource = world.getServer().getResourceManager().getResource(structureId).orElse(null); - - if (resource == null) { - throw new RuntimeException("Unable to get resource: " + structureId); - } - - String snbt; - - try (InputStream inputStream = resource.getInputStream()) { - snbt = new String(inputStream.readAllBytes(), StandardCharsets.UTF_8); - } - - NbtCompound nbtCompound = NbtHelper.fromNbtProviderString(snbt); - StructureTemplate structure = world.getStructureTemplateManager().createTemplate(nbtCompound); - - cir.setReturnValue(structure); - } catch (IOException | CommandSyntaxException e) { - throw new RuntimeException("Error while trying to load structure: " + structureId, e); - } - } -} diff --git a/fabric-gametest-api-v1/src/main/resources/fabric-gametest-api-v1.accesswidener b/fabric-gametest-api-v1/src/main/resources/fabric-gametest-api-v1.accesswidener new file mode 100644 index 000000000..eb7f15b89 --- /dev/null +++ b/fabric-gametest-api-v1/src/main/resources/fabric-gametest-api-v1.accesswidener @@ -0,0 +1,4 @@ +accessWidener v2 named + +accessible class net/minecraft/structure/StructureTemplateManager$Provider +accessible method net/minecraft/structure/StructureTemplateManager$Provider <init> (Ljava/util/function/Function;Ljava/util/function/Supplier;)V diff --git a/fabric-gametest-api-v1/src/main/resources/fabric-gametest-api-v1.mixins.json b/fabric-gametest-api-v1/src/main/resources/fabric-gametest-api-v1.mixins.json index 8a7826430..9878ffc7d 100644 --- a/fabric-gametest-api-v1/src/main/resources/fabric-gametest-api-v1.mixins.json +++ b/fabric-gametest-api-v1/src/main/resources/fabric-gametest-api-v1.mixins.json @@ -6,7 +6,7 @@ "ArgumentTypesMixin", "CommandManagerMixin", "MinecraftServerMixin", - "StructureTestUtilMixin", + "StructureTemplateManagerMixin", "TestFunctionsMixin", "TestServerMixin" ], diff --git a/fabric-gametest-api-v1/src/main/resources/fabric.mod.json b/fabric-gametest-api-v1/src/main/resources/fabric.mod.json index 1a5271634..23e47fa51 100644 --- a/fabric-gametest-api-v1/src/main/resources/fabric.mod.json +++ b/fabric-gametest-api-v1/src/main/resources/fabric.mod.json @@ -27,6 +27,7 @@ "mixins": [ "fabric-gametest-api-v1.mixins.json" ], + "accessWidener": "fabric-gametest-api-v1.accesswidener", "custom": { "fabric-api:module-lifecycle": "stable" }