diff --git a/common/src/main/java/org/embeddedt/modernfix/ModernFix.java b/common/src/main/java/org/embeddedt/modernfix/ModernFix.java index 6f9904a7..d0ab0417 100644 --- a/common/src/main/java/org/embeddedt/modernfix/ModernFix.java +++ b/common/src/main/java/org/embeddedt/modernfix/ModernFix.java @@ -6,6 +6,7 @@ import net.minecraft.server.level.ChunkMap; import net.minecraft.server.level.ServerLevel; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import org.embeddedt.modernfix.command.ModernFixCommands; import org.embeddedt.modernfix.core.ModernFixMixinPlugin; import org.embeddedt.modernfix.platform.ModernFixPlatformHooks; import org.embeddedt.modernfix.util.ClassInfoManager; @@ -43,6 +44,7 @@ public class ModernFix { public ModernFix() { INSTANCE = this; + ModernFixPlatformHooks.onServerCommandRegister(ModernFixCommands::register); } public void onServerStarted() { diff --git a/common/src/main/java/org/embeddedt/modernfix/command/ModernFixCommands.java b/common/src/main/java/org/embeddedt/modernfix/command/ModernFixCommands.java new file mode 100644 index 00000000..a4431a35 --- /dev/null +++ b/common/src/main/java/org/embeddedt/modernfix/command/ModernFixCommands.java @@ -0,0 +1,57 @@ +package org.embeddedt.modernfix.command; + +import com.mojang.brigadier.CommandDispatcher; +import net.minecraft.commands.CommandSourceStack; +import net.minecraft.network.chat.Component; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.server.packs.resources.Resource; +import net.minecraft.server.packs.resources.ResourceManager; +import org.embeddedt.modernfix.structure.CachingStructureManager; + +import java.io.IOException; +import java.io.InputStream; +import java.util.Map; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import static net.minecraft.commands.Commands.*; + +public class ModernFixCommands { + public static void register(CommandDispatcher dispatcher) { + dispatcher.register(literal("modernfix") + .then(literal("upgradeStructures") + .requires(source -> source.hasPermission(3)) + .executes(context -> { + ServerLevel level = context.getSource().getLevel(); + if(level == null) { + context.getSource().sendFailure(Component.literal("Couldn't find server level")); + return 0; + } + + ResourceManager manager = level.getServer().resources.resourceManager(); + Map structures = manager.listResources("structures", p -> p.getPath().endsWith(".nbt")); + int upgradedNum = 0; + Pattern pathPattern = Pattern.compile("^structures/(.*)\\.nbt$"); + for(Map.Entry entry : structures.entrySet()) { + upgradedNum++; + ResourceLocation found = entry.getKey(); + Matcher matcher = pathPattern.matcher(found.getPath()); + if(!matcher.matches()) + continue; + ResourceLocation structureLocation = new ResourceLocation(found.getNamespace(), matcher.group(1)); + try(InputStream resource = entry.getValue().open()) { + CachingStructureManager.readStructureTag(structureLocation, level.getServer().getFixerUpper(), resource); + context.getSource().sendSuccess(Component.literal("checked " + structureLocation + " (" + upgradedNum + "/" + structures.size() + ")"), false); + } catch(IOException e) { + context.getSource().sendFailure(Component.literal("error reading " + structureLocation + " (" + upgradedNum + "/" + structures.size() + ")")); + } + } + + context.getSource().sendSuccess(Component.literal("All structures upgraded"), false); + + return 1; + })) + ); + } +} diff --git a/common/src/main/java/org/embeddedt/modernfix/platform/ModernFixPlatformHooks.java b/common/src/main/java/org/embeddedt/modernfix/platform/ModernFixPlatformHooks.java index a5735018..0c5d3234 100644 --- a/common/src/main/java/org/embeddedt/modernfix/platform/ModernFixPlatformHooks.java +++ b/common/src/main/java/org/embeddedt/modernfix/platform/ModernFixPlatformHooks.java @@ -1,11 +1,14 @@ package org.embeddedt.modernfix.platform; import dev.architectury.injectables.annotations.ExpectPlatform; +import com.mojang.brigadier.CommandDispatcher; +import net.minecraft.commands.CommandSourceStack; import net.minecraft.server.MinecraftServer; import net.minecraft.server.level.ServerPlayer; import org.objectweb.asm.tree.ClassNode; import java.nio.file.Path; +import java.util.function.Consumer; public class ModernFixPlatformHooks { @ExpectPlatform @@ -62,4 +65,9 @@ public class ModernFixPlatformHooks { public static void sendPacket(ServerPlayer player, Object packet) { throw new AssertionError(); } + + @ExpectPlatform + public static void onServerCommandRegister(Consumer> handler) { + throw new AssertionError(); + } } diff --git a/common/src/main/java/org/embeddedt/modernfix/structure/CachingStructureManager.java b/common/src/main/java/org/embeddedt/modernfix/structure/CachingStructureManager.java index 1da67d26..64f01bcc 100644 --- a/common/src/main/java/org/embeddedt/modernfix/structure/CachingStructureManager.java +++ b/common/src/main/java/org/embeddedt/modernfix/structure/CachingStructureManager.java @@ -46,7 +46,7 @@ public class CachingStructureManager { return sb.toString(); } - private static CompoundTag readStructureTag(ResourceLocation location, DataFixer datafixer, InputStream stream) throws IOException { + public static CompoundTag readStructureTag(ResourceLocation location, DataFixer datafixer, InputStream stream) throws IOException { byte[] structureBytes = toBytes(stream); CompoundTag currentTag = NbtIo.readCompressed(new ByteArrayInputStream(structureBytes)); if (!currentTag.contains("DataVersion", 99)) { diff --git a/common/src/main/resources/modernfix.accesswidener b/common/src/main/resources/modernfix.accesswidener index bf00e73b..2dc73a33 100644 --- a/common/src/main/resources/modernfix.accesswidener +++ b/common/src/main/resources/modernfix.accesswidener @@ -40,3 +40,5 @@ accessible class net/minecraft/client/resources/model/ModelBakery$ModelBakerImpl accessible method net/minecraft/client/resources/model/ModelBakery$ModelBakerImpl (Lnet/minecraft/client/resources/model/ModelBakery;Ljava/util/function/BiFunction;Lnet/minecraft/resources/ResourceLocation;)V accessible method net/minecraft/client/resources/model/ModelBakery$BakedCacheKey (Lnet/minecraft/resources/ResourceLocation;Lcom/mojang/math/Transformation;Z)V accessible class net/minecraft/world/level/chunk/PalettedContainer$Data +accessible field net/minecraft/server/MinecraftServer resources Lnet/minecraft/server/MinecraftServer$ReloadableResources; +accessible class net/minecraft/server/MinecraftServer$ReloadableResources diff --git a/fabric/build.gradle b/fabric/build.gradle index a7d20969..ec217638 100644 --- a/fabric/build.gradle +++ b/fabric/build.gradle @@ -32,6 +32,7 @@ dependencies { modIncludeImplementation(fabricApi.module("fabric-api-base", rootProject.fabric_api_version)) { exclude group: 'net.fabricmc', module: 'fabric-loader' } modIncludeImplementation(fabricApi.module("fabric-lifecycle-events-v1", rootProject.fabric_api_version)) { exclude group: 'net.fabricmc', module: 'fabric-loader' } modIncludeImplementation(fabricApi.module("fabric-screen-api-v1", rootProject.fabric_api_version)) { exclude group: 'net.fabricmc', module: 'fabric-loader' } + modIncludeImplementation(fabricApi.module("fabric-command-api-v2", rootProject.fabric_api_version)) { exclude group: 'net.fabricmc', module: 'fabric-loader' } modImplementation(fabricApi.module("fabric-resource-loader-v0", rootProject.fabric_api_version)) { exclude group: 'net.fabricmc', module: 'fabric-loader' } // Remove the next line if you don't want to depend on the API // modApi "me.shedaniel:architectury-fabric:${rootProject.architectury_version}" diff --git a/fabric/src/main/java/org/embeddedt/modernfix/platform/fabric/ModernFixPlatformHooksImpl.java b/fabric/src/main/java/org/embeddedt/modernfix/platform/fabric/ModernFixPlatformHooksImpl.java index c9179b95..01857624 100644 --- a/fabric/src/main/java/org/embeddedt/modernfix/platform/fabric/ModernFixPlatformHooksImpl.java +++ b/fabric/src/main/java/org/embeddedt/modernfix/platform/fabric/ModernFixPlatformHooksImpl.java @@ -1,15 +1,18 @@ package org.embeddedt.modernfix.platform.fabric; +import com.mojang.brigadier.CommandDispatcher; import net.fabricmc.api.EnvType; +import net.fabricmc.fabric.api.command.v2.CommandRegistrationCallback; import net.fabricmc.loader.api.FabricLoader; import net.fabricmc.loader.api.ModContainer; +import net.minecraft.commands.CommandSourceStack; import net.minecraft.server.MinecraftServer; import net.minecraft.server.level.ServerPlayer; import org.embeddedt.modernfix.ModernFixFabric; import org.objectweb.asm.tree.*; import java.nio.file.Path; -import java.util.*; +import java.util.function.Consumer; public class ModernFixPlatformHooksImpl { public static boolean isClient() { @@ -60,4 +63,8 @@ public class ModernFixPlatformHooksImpl { public static void applyASMTransformers(String mixinClassName, ClassNode targetClass) { } + + public static void onServerCommandRegister(Consumer> handler) { + CommandRegistrationCallback.EVENT.register((dispatcher, arg, env) -> handler.accept(dispatcher)); + } } diff --git a/forge/src/main/java/org/embeddedt/modernfix/platform/forge/ModernFixPlatformHooksImpl.java b/forge/src/main/java/org/embeddedt/modernfix/platform/forge/ModernFixPlatformHooksImpl.java index 31fe5505..7421781e 100644 --- a/forge/src/main/java/org/embeddedt/modernfix/platform/forge/ModernFixPlatformHooksImpl.java +++ b/forge/src/main/java/org/embeddedt/modernfix/platform/forge/ModernFixPlatformHooksImpl.java @@ -1,10 +1,13 @@ package org.embeddedt.modernfix.platform.forge; -import cpw.mods.modlauncher.*; import cpw.mods.modlauncher.api.INameMappingService; +import com.mojang.brigadier.CommandDispatcher; +import net.minecraft.commands.CommandSourceStack; import net.minecraft.server.MinecraftServer; import net.minecraft.server.level.ServerPlayer; import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.common.MinecraftForge; +import net.minecraftforge.event.RegisterCommandsEvent; import net.minecraftforge.fml.ModLoader; import net.minecraftforge.fml.loading.FMLLoader; import net.minecraftforge.fml.loading.FMLPaths; @@ -25,6 +28,7 @@ import org.spongepowered.asm.mixin.injection.struct.InjectorGroupInfo; import java.lang.reflect.Field; import java.nio.file.Path; import java.util.*; +import java.util.function.Consumer; import java.util.stream.Collectors; import java.util.stream.Stream; @@ -123,4 +127,10 @@ public class ModernFixPlatformHooksImpl { } } } + + public static void onServerCommandRegister(Consumer> handler) { + MinecraftForge.EVENT_BUS.addListener((RegisterCommandsEvent event) -> { + handler.accept(event.getDispatcher()); + }); + } }