From b48047d2769db362477925f187fd8abdf2c96781 Mon Sep 17 00:00:00 2001 From: xtrm Date: Sun, 4 Jun 2023 01:02:23 +0200 Subject: [PATCH 1/6] =?UTF-8?q?=E2=9C=A8=20feature(worldedit):=20remove=20?= =?UTF-8?q?hard-dependency=20on=20worldedit,=20rework=20ReflectionUtils=20?= =?UTF-8?q?to=20except=20classloading,=20add=20worldedit=20dependency=20to?= =?UTF-8?q?=20some=20features?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../redstonetools/RedstoneToolsClient.java | 11 +++ .../redstonetools/RedstoneToolsGameRules.java | 6 +- .../features/AbstractFeature.java | 4 ++ .../redstonetools/features/Feature.java | 1 + .../commands/BinaryBlockReadFeature.java | 2 +- .../features/commands/ColorCodeFeature.java | 2 +- .../commands/MinSelectionFeature.java | 2 +- .../features/commands/RStackFeature.java | 2 +- .../gamerules/DoContainerDropsMixin.java | 7 +- .../redstonetools/utils/ReflectionUtils.java | 70 +++++++++++++++---- .../redstonetools/utils/WorldEditUtils.java | 20 ++++++ src/main/resources/fabric.mod.json | 8 ++- 12 files changed, 110 insertions(+), 25 deletions(-) diff --git a/src/main/java/tools/redstone/redstonetools/RedstoneToolsClient.java b/src/main/java/tools/redstone/redstonetools/RedstoneToolsClient.java index fb24c35a..768ce6b9 100644 --- a/src/main/java/tools/redstone/redstonetools/RedstoneToolsClient.java +++ b/src/main/java/tools/redstone/redstonetools/RedstoneToolsClient.java @@ -26,6 +26,17 @@ public void onInitializeClient() { ReflectionUtils.getFeatures().forEach(feature -> { LOGGER.trace("Registering feature {}", feature); + String[] modDependencies = feature.getModDependencies(); + if (modDependencies.length != 0) { + LOGGER.trace("Checking mod dependencies for feature {}", feature); + + for (String modDependency : modDependencies) { + if (!FabricLoader.getInstance().isModLoaded(modDependency)) { + LOGGER.warn("Mod dependency {} not found for feature {}, force disabling it", modDependency, feature); + return; + } + } + } feature.register(); }); diff --git a/src/main/java/tools/redstone/redstonetools/RedstoneToolsGameRules.java b/src/main/java/tools/redstone/redstonetools/RedstoneToolsGameRules.java index 7befef6e..5745b705 100644 --- a/src/main/java/tools/redstone/redstonetools/RedstoneToolsGameRules.java +++ b/src/main/java/tools/redstone/redstonetools/RedstoneToolsGameRules.java @@ -3,6 +3,7 @@ import net.fabricmc.fabric.api.gamerule.v1.GameRuleFactory; import net.fabricmc.fabric.api.gamerule.v1.GameRuleRegistry; import net.minecraft.world.GameRules; +import tools.redstone.redstonetools.utils.WorldEditUtils; public class RedstoneToolsGameRules { @@ -14,6 +15,9 @@ private RedstoneToolsGameRules() { public static void register() { DO_CONTAINER_DROPS = GameRuleRegistry.register("doContainerDrops", GameRules.Category.DROPS, GameRuleFactory.createBooleanRule(true)); - DO_BLOCK_UPDATES_AFTER_EDIT = GameRuleRegistry.register("doBlockUpdatesAfterEdit", GameRules.Category.UPDATES, GameRuleFactory.createBooleanRule(false)); + + if (WorldEditUtils.WORLDEDIT_LOADED) { + DO_BLOCK_UPDATES_AFTER_EDIT = GameRuleRegistry.register("doBlockUpdatesAfterEdit", GameRules.Category.UPDATES, GameRuleFactory.createBooleanRule(false)); + } } } diff --git a/src/main/java/tools/redstone/redstonetools/features/AbstractFeature.java b/src/main/java/tools/redstone/redstonetools/features/AbstractFeature.java index 74846035..1314ac74 100644 --- a/src/main/java/tools/redstone/redstonetools/features/AbstractFeature.java +++ b/src/main/java/tools/redstone/redstonetools/features/AbstractFeature.java @@ -27,6 +27,10 @@ public String getCommand() { return feature.command(); } + public String[] getModDependencies() { + return feature.modDependencies(); + } + /** * Register this feature. */ diff --git a/src/main/java/tools/redstone/redstonetools/features/Feature.java b/src/main/java/tools/redstone/redstonetools/features/Feature.java index ae3cbe53..a34fdfb1 100644 --- a/src/main/java/tools/redstone/redstonetools/features/Feature.java +++ b/src/main/java/tools/redstone/redstonetools/features/Feature.java @@ -11,4 +11,5 @@ String name(); String description(); String command(); + String[] modDependencies() default {}; } diff --git a/src/main/java/tools/redstone/redstonetools/features/commands/BinaryBlockReadFeature.java b/src/main/java/tools/redstone/redstonetools/features/commands/BinaryBlockReadFeature.java index 79e34fb9..b5151ffd 100644 --- a/src/main/java/tools/redstone/redstonetools/features/commands/BinaryBlockReadFeature.java +++ b/src/main/java/tools/redstone/redstonetools/features/commands/BinaryBlockReadFeature.java @@ -19,7 +19,7 @@ import static tools.redstone.redstonetools.features.arguments.serializers.NumberBaseSerializer.numberBase; @AutoService(AbstractFeature.class) -@Feature(name = "Binary Block Read", description = "Interprets your WorldEdit selection as a binary number.", command = "/read") +@Feature(name = "Binary Block Read", description = "Interprets your WorldEdit selection as a binary number.", command = "/read", modDependencies = "worldedit") public class BinaryBlockReadFeature extends CommandFeature { private static final BlockStateArgument LIT_LAMP_ARG = new BlockStateArgument( Blocks.REDSTONE_LAMP.getDefaultState().with(RedstoneLampBlock.LIT, true), null, null diff --git a/src/main/java/tools/redstone/redstonetools/features/commands/ColorCodeFeature.java b/src/main/java/tools/redstone/redstonetools/features/commands/ColorCodeFeature.java index 68460b00..66750e42 100644 --- a/src/main/java/tools/redstone/redstonetools/features/commands/ColorCodeFeature.java +++ b/src/main/java/tools/redstone/redstonetools/features/commands/ColorCodeFeature.java @@ -24,7 +24,7 @@ import static tools.redstone.redstonetools.features.arguments.serializers.BlockColorSerializer.blockColor; @AutoService(AbstractFeature.class) -@Feature(name = "Color Code", description = "Color codes all color-able blocks in your WorldEdit selection.", command = "/colorcode") +@Feature(name = "Color Code", description = "Color codes all color-able blocks in your WorldEdit selection.", command = "/colorcode", modDependencies = "worldedit") public class ColorCodeFeature extends CommandFeature { public static final Argument color = Argument .ofType(blockColor()); diff --git a/src/main/java/tools/redstone/redstonetools/features/commands/MinSelectionFeature.java b/src/main/java/tools/redstone/redstonetools/features/commands/MinSelectionFeature.java index 4829a018..d58f99f9 100644 --- a/src/main/java/tools/redstone/redstonetools/features/commands/MinSelectionFeature.java +++ b/src/main/java/tools/redstone/redstonetools/features/commands/MinSelectionFeature.java @@ -21,7 +21,7 @@ import java.util.List; @AutoService(AbstractFeature.class) -@Feature(command = "/minsel", description = "Removes all air-only layers from a selection", name = "Minimize Selection") +@Feature(command = "/minsel", description = "Removes all air-only layers from a selection", name = "Minimize Selection", modDependencies = "worldedit") public class MinSelectionFeature extends CommandFeature { @Override diff --git a/src/main/java/tools/redstone/redstonetools/features/commands/RStackFeature.java b/src/main/java/tools/redstone/redstonetools/features/commands/RStackFeature.java index 650a0ef0..8897027d 100644 --- a/src/main/java/tools/redstone/redstonetools/features/commands/RStackFeature.java +++ b/src/main/java/tools/redstone/redstonetools/features/commands/RStackFeature.java @@ -26,7 +26,7 @@ import static tools.redstone.redstonetools.utils.DirectionUtils.matchDirection; @AutoService(AbstractFeature.class) -@Feature(name = "RStack", description = "Stacks with custom distance", command = "/rstack") +@Feature(name = "RStack", description = "Stacks with custom distance", command = "/rstack", modDependencies = "worldedit") public class RStackFeature extends CommandFeature { public static final Argument count = Argument .ofType(integer()) diff --git a/src/main/java/tools/redstone/redstonetools/mixin/gamerules/DoContainerDropsMixin.java b/src/main/java/tools/redstone/redstonetools/mixin/gamerules/DoContainerDropsMixin.java index 007e49d2..bbccc2b3 100644 --- a/src/main/java/tools/redstone/redstonetools/mixin/gamerules/DoContainerDropsMixin.java +++ b/src/main/java/tools/redstone/redstonetools/mixin/gamerules/DoContainerDropsMixin.java @@ -7,13 +7,14 @@ import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; - -import static tools.redstone.redstonetools.RedstoneToolsGameRules.DO_CONTAINER_DROPS; +import tools.redstone.redstonetools.RedstoneToolsGameRules; @Mixin(ItemScatterer.class) public class DoContainerDropsMixin { @Inject(method = "spawn(Lnet/minecraft/world/World;DDDLnet/minecraft/item/ItemStack;)V", at = @At("HEAD"), cancellable = true) private static void spawn(World world, double x, double y, double z, ItemStack stack, CallbackInfo ci) { - if (!world.getGameRules().getBoolean(DO_CONTAINER_DROPS)) ci.cancel(); + if (RedstoneToolsGameRules.DO_CONTAINER_DROPS != null && !world.getGameRules().getBoolean(RedstoneToolsGameRules.DO_CONTAINER_DROPS)) { + ci.cancel(); + } } } diff --git a/src/main/java/tools/redstone/redstonetools/utils/ReflectionUtils.java b/src/main/java/tools/redstone/redstonetools/utils/ReflectionUtils.java index 09d1513f..f7b0bdb8 100644 --- a/src/main/java/tools/redstone/redstonetools/utils/ReflectionUtils.java +++ b/src/main/java/tools/redstone/redstonetools/utils/ReflectionUtils.java @@ -1,22 +1,22 @@ package tools.redstone.redstonetools.utils; import com.google.inject.AbstractModule; +import org.apache.commons.io.IOUtils; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.jetbrains.annotations.Nullable; import tools.redstone.redstonetools.features.AbstractFeature; import tools.redstone.redstonetools.features.Feature; import tools.redstone.redstonetools.features.arguments.Argument; +import java.io.IOException; import java.lang.reflect.Modifier; -import java.util.Arrays; -import java.util.List; -import java.util.ServiceLoader; -import java.util.Set; +import java.net.URL; +import java.util.*; import java.util.stream.Collectors; public class ReflectionUtils { - private static final ServiceLoader modulesLoader = - ServiceLoader.load(AbstractModule.class); - private static final ServiceLoader featuresLoader = - ServiceLoader.load(AbstractFeature.class); + private static final Logger LOGGER = LogManager.getLogger(); private static Set modules; private static Set features; @@ -26,22 +26,64 @@ private ReflectionUtils() { public static Set getModules() { if (modules == null) { - modules = modulesLoader.stream() - .map(ServiceLoader.Provider::get) - .collect(Collectors.toSet()); + try { + modules = serviceLoad(AbstractModule.class); + } catch (IOException e) { + throw new RuntimeException("Failed to load modules", e); + } } return modules; } public static Set getFeatures() { if (features == null) { - features = featuresLoader.stream() - .map(ServiceLoader.Provider::get) - .collect(Collectors.toSet()); + try { + features = serviceLoad(AbstractFeature.class); + } catch (IOException e) { + throw new RuntimeException("Failed to load features", e); + } } return features; } + private static Set serviceLoad(Class clazz) throws IOException { + ClassLoader cl = ReflectionUtils.class.getClassLoader(); + Enumeration serviceFiles = cl.getResources("META-INF/services/" + clazz.getName()); + Set classNames = new HashSet<>(); + while (serviceFiles.hasMoreElements()) { + URL serviceFile = serviceFiles.nextElement(); + try (var reader = serviceFile.openStream()) { + classNames.addAll(IOUtils.readLines(reader, "UTF-8")); + } + } + return classNames.stream() + .filter(it -> !it.isEmpty() && !it.isBlank()) + .map(ReflectionUtils::loadClass) + .filter(Objects::nonNull) + .filter(clazz::isAssignableFrom) + .map(it -> { + try { + return it.getDeclaredConstructor().newInstance(); + } catch (ReflectiveOperationException e) { + throw new RuntimeException("Failed to instantiate " + it, e); + } + }) + .map(clazz::cast) + .collect(Collectors.toSet()); + } + + @SuppressWarnings("unchecked") + private static @Nullable Class loadClass(String className) { + try { + return (Class) Class.forName(className); + } catch (ClassNotFoundException e) { + throw new RuntimeException("Failed to load class " + className, e); + } catch (NoClassDefFoundError e) { + LOGGER.warn("Failed to load class {}, required {}", className, e.getMessage()); + } + return null; + } + public static List> getArguments(Class featureClass) { return Arrays.stream(featureClass.getFields()) .filter(field -> Argument.class.isAssignableFrom(field.getType())) diff --git a/src/main/java/tools/redstone/redstonetools/utils/WorldEditUtils.java b/src/main/java/tools/redstone/redstonetools/utils/WorldEditUtils.java index 95967ff7..973ed4c2 100644 --- a/src/main/java/tools/redstone/redstonetools/utils/WorldEditUtils.java +++ b/src/main/java/tools/redstone/redstonetools/utils/WorldEditUtils.java @@ -13,6 +13,8 @@ import java.util.function.Consumer; public class WorldEditUtils { + public static final boolean WORLDEDIT_LOADED; + /** * Execute a function for each block in * the provided region. @@ -28,6 +30,10 @@ public class WorldEditUtils { */ public static void forEachBlockInRegion(Region region, Consumer consumer) { + if (!WORLDEDIT_LOADED) { + throw new IllegalStateException("WorldEdit is not loaded."); + } + CuboidRegion bb = region.getBoundingBox(); BlockVector3 min = bb.getMinimumPoint(); BlockVector3 max = bb.getMaximumPoint(); @@ -44,6 +50,10 @@ public static void forEachBlockInRegion(Region region, } public static Either getSelection(ServerPlayerEntity player) { + if (!WORLDEDIT_LOADED) { + return Either.right(Feedback.invalidUsage("WorldEdit is not loaded.")); + } + var actor = FabricAdapter.adaptPlayer(player); var localSession = WorldEdit.getInstance() @@ -58,4 +68,14 @@ public static Either getSelection(ServerPlayerEntity player) { return Either.right(Feedback.invalidUsage("Please make a selection with worldedit first.")); } } + + static { + boolean loaded = false; + try { + Class.forName("com.sk89q.worldedit.WorldEdit"); + loaded = true; + } catch (Throwable ignored) { + } + WORLDEDIT_LOADED = loaded; + } } diff --git a/src/main/resources/fabric.mod.json b/src/main/resources/fabric.mod.json index e8fb8913..c866dade 100644 --- a/src/main/resources/fabric.mod.json +++ b/src/main/resources/fabric.mod.json @@ -25,10 +25,12 @@ ], "depends": { - "fabricloader": ">=0.14.6", + "fabricloader": ">=0.13.0", "fabric": "*", "minecraft": "~1.18.2", - "java": ">=17", - "worldedit": "7.2.10" + "java": ">=17" + }, + "recommends": { + "worldedit": "*" } } From d090d3d3b1bffa066ceca75fdf12df80ae427b90 Mon Sep 17 00:00:00 2001 From: xtrm Date: Sun, 4 Jun 2023 01:05:13 +0200 Subject: [PATCH 2/6] =?UTF-8?q?=E2=9C=A8=20feature(worldedit):=20nicer=20m?= =?UTF-8?q?essage?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/tools/redstone/redstonetools/RedstoneToolsClient.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/tools/redstone/redstonetools/RedstoneToolsClient.java b/src/main/java/tools/redstone/redstonetools/RedstoneToolsClient.java index 768ce6b9..15b70a95 100644 --- a/src/main/java/tools/redstone/redstonetools/RedstoneToolsClient.java +++ b/src/main/java/tools/redstone/redstonetools/RedstoneToolsClient.java @@ -32,7 +32,7 @@ public void onInitializeClient() { for (String modDependency : modDependencies) { if (!FabricLoader.getInstance().isModLoaded(modDependency)) { - LOGGER.warn("Mod dependency {} not found for feature {}, force disabling it", modDependency, feature); + LOGGER.warn("Mod dependency '{}' not found for feature {}, force disabling it", modDependency, feature.getClass().getName()); return; } } From 51a80a0e30bbd83c422bfc7848a663c4f175f293 Mon Sep 17 00:00:00 2001 From: xtrm Date: Sun, 4 Jun 2023 03:31:16 +0200 Subject: [PATCH 3/6] =?UTF-8?q?=F0=9F=94=A8=20chore(worldedit):=20changes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../redstonetools/RedstoneToolsClient.java | 16 +++++----------- .../redstonetools/features/AbstractFeature.java | 4 ++-- .../redstone/redstonetools/features/Feature.java | 2 +- .../commands/BinaryBlockReadFeature.java | 2 +- .../features/commands/ColorCodeFeature.java | 2 +- .../features/commands/MinSelectionFeature.java | 2 +- .../features/commands/RStackFeature.java | 2 +- 7 files changed, 12 insertions(+), 18 deletions(-) diff --git a/src/main/java/tools/redstone/redstonetools/RedstoneToolsClient.java b/src/main/java/tools/redstone/redstonetools/RedstoneToolsClient.java index 3daf0bae..d4c558e4 100644 --- a/src/main/java/tools/redstone/redstonetools/RedstoneToolsClient.java +++ b/src/main/java/tools/redstone/redstonetools/RedstoneToolsClient.java @@ -8,6 +8,7 @@ import rip.hippo.inject.Injector; import tools.redstone.redstonetools.macros.WorldlessCommandHelper; import tools.redstone.redstonetools.utils.ReflectionUtils; +import tools.redstone.redstonetools.utils.WorldEditUtils; public class RedstoneToolsClient implements ClientModInitializer { public static final String MOD_ID = "redstonetools"; @@ -24,18 +25,11 @@ public void onInitializeClient() { // Register features ReflectionUtils.getFeatures().forEach(feature -> { - LOGGER.trace("Registering feature {}", feature); + LOGGER.trace("Registering feature {}", feature.getClass().getName()); - String[] modDependencies = feature.getModDependencies(); - if (modDependencies.length != 0) { - LOGGER.trace("Checking mod dependencies for feature {}", feature); - - for (String modDependency : modDependencies) { - if (!FabricLoader.getInstance().isModLoaded(modDependency)) { - LOGGER.warn("Mod dependency '{}' not found for feature {}, force disabling it", modDependency, feature.getClass().getName()); - return; - } - } + if (feature.requiresWorldEdit() && !WorldEditUtils.WORLDEDIT_LOADED) { + LOGGER.warn("Feature {} requires WorldEdit, but WorldEdit is not loaded. Skipping registration.", feature.getName()); + return; } feature.register(); }); diff --git a/src/main/java/tools/redstone/redstonetools/features/AbstractFeature.java b/src/main/java/tools/redstone/redstonetools/features/AbstractFeature.java index 1314ac74..94057d7f 100644 --- a/src/main/java/tools/redstone/redstonetools/features/AbstractFeature.java +++ b/src/main/java/tools/redstone/redstonetools/features/AbstractFeature.java @@ -27,8 +27,8 @@ public String getCommand() { return feature.command(); } - public String[] getModDependencies() { - return feature.modDependencies(); + public boolean requiresWorldEdit() { + return feature.worldedit(); } /** diff --git a/src/main/java/tools/redstone/redstonetools/features/Feature.java b/src/main/java/tools/redstone/redstonetools/features/Feature.java index a34fdfb1..83b6f5ec 100644 --- a/src/main/java/tools/redstone/redstonetools/features/Feature.java +++ b/src/main/java/tools/redstone/redstonetools/features/Feature.java @@ -11,5 +11,5 @@ String name(); String description(); String command(); - String[] modDependencies() default {}; + boolean worldedit() default false; } diff --git a/src/main/java/tools/redstone/redstonetools/features/commands/BinaryBlockReadFeature.java b/src/main/java/tools/redstone/redstonetools/features/commands/BinaryBlockReadFeature.java index b5151ffd..a5dc6d6c 100644 --- a/src/main/java/tools/redstone/redstonetools/features/commands/BinaryBlockReadFeature.java +++ b/src/main/java/tools/redstone/redstonetools/features/commands/BinaryBlockReadFeature.java @@ -19,7 +19,7 @@ import static tools.redstone.redstonetools.features.arguments.serializers.NumberBaseSerializer.numberBase; @AutoService(AbstractFeature.class) -@Feature(name = "Binary Block Read", description = "Interprets your WorldEdit selection as a binary number.", command = "/read", modDependencies = "worldedit") +@Feature(name = "Binary Block Read", description = "Interprets your WorldEdit selection as a binary number.", command = "/read", worldedit = true) public class BinaryBlockReadFeature extends CommandFeature { private static final BlockStateArgument LIT_LAMP_ARG = new BlockStateArgument( Blocks.REDSTONE_LAMP.getDefaultState().with(RedstoneLampBlock.LIT, true), null, null diff --git a/src/main/java/tools/redstone/redstonetools/features/commands/ColorCodeFeature.java b/src/main/java/tools/redstone/redstonetools/features/commands/ColorCodeFeature.java index 66750e42..61da6540 100644 --- a/src/main/java/tools/redstone/redstonetools/features/commands/ColorCodeFeature.java +++ b/src/main/java/tools/redstone/redstonetools/features/commands/ColorCodeFeature.java @@ -24,7 +24,7 @@ import static tools.redstone.redstonetools.features.arguments.serializers.BlockColorSerializer.blockColor; @AutoService(AbstractFeature.class) -@Feature(name = "Color Code", description = "Color codes all color-able blocks in your WorldEdit selection.", command = "/colorcode", modDependencies = "worldedit") +@Feature(name = "Color Code", description = "Color codes all color-able blocks in your WorldEdit selection.", command = "/colorcode", worldedit = true) public class ColorCodeFeature extends CommandFeature { public static final Argument color = Argument .ofType(blockColor()); diff --git a/src/main/java/tools/redstone/redstonetools/features/commands/MinSelectionFeature.java b/src/main/java/tools/redstone/redstonetools/features/commands/MinSelectionFeature.java index d58f99f9..d138973f 100644 --- a/src/main/java/tools/redstone/redstonetools/features/commands/MinSelectionFeature.java +++ b/src/main/java/tools/redstone/redstonetools/features/commands/MinSelectionFeature.java @@ -21,7 +21,7 @@ import java.util.List; @AutoService(AbstractFeature.class) -@Feature(command = "/minsel", description = "Removes all air-only layers from a selection", name = "Minimize Selection", modDependencies = "worldedit") +@Feature(command = "/minsel", description = "Removes all air-only layers from a selection", name = "Minimize Selection", worldedit = true) public class MinSelectionFeature extends CommandFeature { @Override diff --git a/src/main/java/tools/redstone/redstonetools/features/commands/RStackFeature.java b/src/main/java/tools/redstone/redstonetools/features/commands/RStackFeature.java index 8897027d..f7c0a700 100644 --- a/src/main/java/tools/redstone/redstonetools/features/commands/RStackFeature.java +++ b/src/main/java/tools/redstone/redstonetools/features/commands/RStackFeature.java @@ -26,7 +26,7 @@ import static tools.redstone.redstonetools.utils.DirectionUtils.matchDirection; @AutoService(AbstractFeature.class) -@Feature(name = "RStack", description = "Stacks with custom distance", command = "/rstack", modDependencies = "worldedit") +@Feature(name = "RStack", description = "Stacks with custom distance", command = "/rstack", worldedit = true) public class RStackFeature extends CommandFeature { public static final Argument count = Argument .ofType(integer()) From e65682cb3ec61906f70e980399e4a33e0574e6a1 Mon Sep 17 00:00:00 2001 From: xtrm Date: Fri, 9 Jun 2023 00:36:05 +0200 Subject: [PATCH 4/6] =?UTF-8?q?=F0=9F=90=9B=20fix(worldedit):=20fix=20cras?= =?UTF-8?q?hing=20when=20loading=20`WorldEditUtils.java`,=20added=20Depend?= =?UTF-8?q?encyLookup=20util=20class=20Co-authored-by:=20JayMensink?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../redstonetools/RedstoneToolsClient.java | 4 +-- .../redstonetools/RedstoneToolsGameRules.java | 4 +-- .../redstonetools/utils/DependencyLookup.java | 25 +++++++++++++++++++ .../redstonetools/utils/WorldEditUtils.java | 16 ++---------- 4 files changed, 31 insertions(+), 18 deletions(-) create mode 100644 src/main/java/tools/redstone/redstonetools/utils/DependencyLookup.java diff --git a/src/main/java/tools/redstone/redstonetools/RedstoneToolsClient.java b/src/main/java/tools/redstone/redstonetools/RedstoneToolsClient.java index d4c558e4..9bda59f8 100644 --- a/src/main/java/tools/redstone/redstonetools/RedstoneToolsClient.java +++ b/src/main/java/tools/redstone/redstonetools/RedstoneToolsClient.java @@ -7,8 +7,8 @@ import rip.hippo.inject.Doctor; import rip.hippo.inject.Injector; import tools.redstone.redstonetools.macros.WorldlessCommandHelper; +import tools.redstone.redstonetools.utils.DependencyLookup; import tools.redstone.redstonetools.utils.ReflectionUtils; -import tools.redstone.redstonetools.utils.WorldEditUtils; public class RedstoneToolsClient implements ClientModInitializer { public static final String MOD_ID = "redstonetools"; @@ -27,7 +27,7 @@ public void onInitializeClient() { ReflectionUtils.getFeatures().forEach(feature -> { LOGGER.trace("Registering feature {}", feature.getClass().getName()); - if (feature.requiresWorldEdit() && !WorldEditUtils.WORLDEDIT_LOADED) { + if (feature.requiresWorldEdit() && !DependencyLookup.WORLDEDIT_LOADED) { LOGGER.warn("Feature {} requires WorldEdit, but WorldEdit is not loaded. Skipping registration.", feature.getName()); return; } diff --git a/src/main/java/tools/redstone/redstonetools/RedstoneToolsGameRules.java b/src/main/java/tools/redstone/redstonetools/RedstoneToolsGameRules.java index 5745b705..9317af19 100644 --- a/src/main/java/tools/redstone/redstonetools/RedstoneToolsGameRules.java +++ b/src/main/java/tools/redstone/redstonetools/RedstoneToolsGameRules.java @@ -3,7 +3,7 @@ import net.fabricmc.fabric.api.gamerule.v1.GameRuleFactory; import net.fabricmc.fabric.api.gamerule.v1.GameRuleRegistry; import net.minecraft.world.GameRules; -import tools.redstone.redstonetools.utils.WorldEditUtils; +import tools.redstone.redstonetools.utils.DependencyLookup; public class RedstoneToolsGameRules { @@ -16,7 +16,7 @@ private RedstoneToolsGameRules() { public static void register() { DO_CONTAINER_DROPS = GameRuleRegistry.register("doContainerDrops", GameRules.Category.DROPS, GameRuleFactory.createBooleanRule(true)); - if (WorldEditUtils.WORLDEDIT_LOADED) { + if (DependencyLookup.WORLDEDIT_LOADED) { DO_BLOCK_UPDATES_AFTER_EDIT = GameRuleRegistry.register("doBlockUpdatesAfterEdit", GameRules.Category.UPDATES, GameRuleFactory.createBooleanRule(false)); } } diff --git a/src/main/java/tools/redstone/redstonetools/utils/DependencyLookup.java b/src/main/java/tools/redstone/redstonetools/utils/DependencyLookup.java new file mode 100644 index 00000000..61478cd9 --- /dev/null +++ b/src/main/java/tools/redstone/redstonetools/utils/DependencyLookup.java @@ -0,0 +1,25 @@ +package tools.redstone.redstonetools.utils; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class DependencyLookup { + private static final Logger LOGGER = + LoggerFactory.getLogger(DependencyLookup.class); + public static final boolean WORLDEDIT_LOADED = + require("com.sk89q.worldedit.WorldEdit"); + + private static boolean require(String... classNames) { + for (String className : classNames) { + try { + Class.forName(className); + } catch (ClassNotFoundException e) { + return false; + } catch (Throwable t) { + LOGGER.warn("Unexpected error while checking for dependency {}", className, t); + return false; + } + } + return true; + } +} diff --git a/src/main/java/tools/redstone/redstonetools/utils/WorldEditUtils.java b/src/main/java/tools/redstone/redstonetools/utils/WorldEditUtils.java index 57beabac..32f581ef 100644 --- a/src/main/java/tools/redstone/redstonetools/utils/WorldEditUtils.java +++ b/src/main/java/tools/redstone/redstonetools/utils/WorldEditUtils.java @@ -13,8 +13,6 @@ import java.util.function.Consumer; public class WorldEditUtils { - public static final boolean WORLDEDIT_LOADED; - /** * Execute a function for each block in * the provided region. @@ -30,7 +28,7 @@ public class WorldEditUtils { */ public static void forEachBlockInRegion(Region region, Consumer consumer) { - if (!WORLDEDIT_LOADED) { + if (!DependencyLookup.WORLDEDIT_LOADED) { throw new IllegalStateException("WorldEdit is not loaded."); } @@ -50,7 +48,7 @@ public static void forEachBlockInRegion(Region region, } public static Either getSelection(ServerPlayerEntity player) { - if (!WORLDEDIT_LOADED) { + if (!DependencyLookup.WORLDEDIT_LOADED) { return Either.right(Feedback.invalidUsage("WorldEdit is not loaded.")); } @@ -68,14 +66,4 @@ public static Either getSelection(ServerPlayerEntity player) { return Either.right(Feedback.invalidUsage("Please make a selection with WorldEdit first")); } } - - static { - boolean loaded = false; - try { - Class.forName("com.sk89q.worldedit.WorldEdit"); - loaded = true; - } catch (Throwable ignored) { - } - WORLDEDIT_LOADED = loaded; - } } From 1811f4d6b367574b7d6b1b361e11fdd4972b9132 Mon Sep 17 00:00:00 2001 From: xtrm Date: Fri, 9 Jun 2023 19:55:44 +0200 Subject: [PATCH 5/6] =?UTF-8?q?=F0=9F=94=A8=20chore(worldedit):=20requeste?= =?UTF-8?q?d=20changes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../tools/redstone/redstonetools/RedstoneToolsClient.java | 2 +- .../redstone/redstonetools/RedstoneToolsGameRules.java | 2 +- .../mixin/gamerules/DoContainerDropsMixin.java | 5 +++-- .../redstone/redstonetools/utils/DependencyLookup.java | 2 +- .../tools/redstone/redstonetools/utils/WorldEditUtils.java | 6 +++--- 5 files changed, 9 insertions(+), 8 deletions(-) diff --git a/src/main/java/tools/redstone/redstonetools/RedstoneToolsClient.java b/src/main/java/tools/redstone/redstonetools/RedstoneToolsClient.java index 9bda59f8..63bb5d55 100644 --- a/src/main/java/tools/redstone/redstonetools/RedstoneToolsClient.java +++ b/src/main/java/tools/redstone/redstonetools/RedstoneToolsClient.java @@ -27,7 +27,7 @@ public void onInitializeClient() { ReflectionUtils.getFeatures().forEach(feature -> { LOGGER.trace("Registering feature {}", feature.getClass().getName()); - if (feature.requiresWorldEdit() && !DependencyLookup.WORLDEDIT_LOADED) { + if (feature.requiresWorldEdit() && !DependencyLookup.WORLDEDIT_PRESENT) { LOGGER.warn("Feature {} requires WorldEdit, but WorldEdit is not loaded. Skipping registration.", feature.getName()); return; } diff --git a/src/main/java/tools/redstone/redstonetools/RedstoneToolsGameRules.java b/src/main/java/tools/redstone/redstonetools/RedstoneToolsGameRules.java index 9317af19..73a9e2f8 100644 --- a/src/main/java/tools/redstone/redstonetools/RedstoneToolsGameRules.java +++ b/src/main/java/tools/redstone/redstonetools/RedstoneToolsGameRules.java @@ -16,7 +16,7 @@ private RedstoneToolsGameRules() { public static void register() { DO_CONTAINER_DROPS = GameRuleRegistry.register("doContainerDrops", GameRules.Category.DROPS, GameRuleFactory.createBooleanRule(true)); - if (DependencyLookup.WORLDEDIT_LOADED) { + if (DependencyLookup.WORLDEDIT_PRESENT) { DO_BLOCK_UPDATES_AFTER_EDIT = GameRuleRegistry.register("doBlockUpdatesAfterEdit", GameRules.Category.UPDATES, GameRuleFactory.createBooleanRule(false)); } } diff --git a/src/main/java/tools/redstone/redstonetools/mixin/gamerules/DoContainerDropsMixin.java b/src/main/java/tools/redstone/redstonetools/mixin/gamerules/DoContainerDropsMixin.java index bbccc2b3..7f7a3f1d 100644 --- a/src/main/java/tools/redstone/redstonetools/mixin/gamerules/DoContainerDropsMixin.java +++ b/src/main/java/tools/redstone/redstonetools/mixin/gamerules/DoContainerDropsMixin.java @@ -7,13 +7,14 @@ import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; -import tools.redstone.redstonetools.RedstoneToolsGameRules; + +import static tools.redstone.redstonetools.RedstoneToolsGameRules.DO_CONTAINER_DROPS; @Mixin(ItemScatterer.class) public class DoContainerDropsMixin { @Inject(method = "spawn(Lnet/minecraft/world/World;DDDLnet/minecraft/item/ItemStack;)V", at = @At("HEAD"), cancellable = true) private static void spawn(World world, double x, double y, double z, ItemStack stack, CallbackInfo ci) { - if (RedstoneToolsGameRules.DO_CONTAINER_DROPS != null && !world.getGameRules().getBoolean(RedstoneToolsGameRules.DO_CONTAINER_DROPS)) { + if (!world.getGameRules().getBoolean(DO_CONTAINER_DROPS)) { ci.cancel(); } } diff --git a/src/main/java/tools/redstone/redstonetools/utils/DependencyLookup.java b/src/main/java/tools/redstone/redstonetools/utils/DependencyLookup.java index 61478cd9..a316d3b8 100644 --- a/src/main/java/tools/redstone/redstonetools/utils/DependencyLookup.java +++ b/src/main/java/tools/redstone/redstonetools/utils/DependencyLookup.java @@ -6,7 +6,7 @@ public class DependencyLookup { private static final Logger LOGGER = LoggerFactory.getLogger(DependencyLookup.class); - public static final boolean WORLDEDIT_LOADED = + public static final boolean WORLDEDIT_PRESENT = require("com.sk89q.worldedit.WorldEdit"); private static boolean require(String... classNames) { diff --git a/src/main/java/tools/redstone/redstonetools/utils/WorldEditUtils.java b/src/main/java/tools/redstone/redstonetools/utils/WorldEditUtils.java index 32f581ef..29e8ece7 100644 --- a/src/main/java/tools/redstone/redstonetools/utils/WorldEditUtils.java +++ b/src/main/java/tools/redstone/redstonetools/utils/WorldEditUtils.java @@ -28,7 +28,7 @@ public class WorldEditUtils { */ public static void forEachBlockInRegion(Region region, Consumer consumer) { - if (!DependencyLookup.WORLDEDIT_LOADED) { + if (!DependencyLookup.WORLDEDIT_PRESENT) { throw new IllegalStateException("WorldEdit is not loaded."); } @@ -48,8 +48,8 @@ public static void forEachBlockInRegion(Region region, } public static Either getSelection(ServerPlayerEntity player) { - if (!DependencyLookup.WORLDEDIT_LOADED) { - return Either.right(Feedback.invalidUsage("WorldEdit is not loaded.")); + if (!DependencyLookup.WORLDEDIT_PRESENT) { + throw new IllegalStateException("WorldEdit is not loaded."); } var actor = FabricAdapter.adaptPlayer(player); From 83aacee11d55ef0f0c81dcea7c7b540ce2dc3833 Mon Sep 17 00:00:00 2001 From: killian <26600206+xtrm-en@users.noreply.github.com> Date: Mon, 19 Jun 2023 00:57:03 +0200 Subject: [PATCH 6/6] Update RedstoneToolsClient.java bruh --- .../java/tools/redstone/redstonetools/RedstoneToolsClient.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/java/tools/redstone/redstonetools/RedstoneToolsClient.java b/src/main/java/tools/redstone/redstonetools/RedstoneToolsClient.java index 9670a606..ab0aa80e 100644 --- a/src/main/java/tools/redstone/redstonetools/RedstoneToolsClient.java +++ b/src/main/java/tools/redstone/redstonetools/RedstoneToolsClient.java @@ -6,7 +6,6 @@ import org.slf4j.LoggerFactory; import rip.hippo.inject.Doctor; import rip.hippo.inject.Injector; -import tools.redstone.redstonetools.macros.WorldlessCommandHelper; import tools.redstone.redstonetools.utils.DependencyLookup; import tools.redstone.redstonetools.utils.ReflectionUtils;