diff options
Diffstat (limited to 'versions/1.16.2-fabric/src')
14 files changed, 464 insertions, 0 deletions
diff --git a/versions/1.16.2-fabric/src/main/java/cc/polyfrost/oneconfig/internal/hook/FramebufferHook.java b/versions/1.16.2-fabric/src/main/java/cc/polyfrost/oneconfig/internal/hook/FramebufferHook.java new file mode 100644 index 0000000..d0125ea --- /dev/null +++ b/versions/1.16.2-fabric/src/main/java/cc/polyfrost/oneconfig/internal/hook/FramebufferHook.java @@ -0,0 +1,6 @@ +package cc.polyfrost.oneconfig.internal.hook; + +public interface FramebufferHook { + boolean isStencilEnabled(); + void enableStencil(); +} diff --git a/versions/1.16.2-fabric/src/main/java/cc/polyfrost/oneconfig/internal/mixin/FramebufferMixin.java b/versions/1.16.2-fabric/src/main/java/cc/polyfrost/oneconfig/internal/mixin/FramebufferMixin.java new file mode 100644 index 0000000..5f182c5 --- /dev/null +++ b/versions/1.16.2-fabric/src/main/java/cc/polyfrost/oneconfig/internal/mixin/FramebufferMixin.java @@ -0,0 +1,62 @@ +package cc.polyfrost.oneconfig.internal.mixin; + +import cc.polyfrost.oneconfig.internal.hook.FramebufferHook; +import com.mojang.blaze3d.platform.FramebufferInfo; +import com.mojang.blaze3d.platform.GlStateManager; +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.gl.Framebuffer; +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.Redirect; + +import java.nio.IntBuffer; + +/** + * Modified from MinecraftForge + * <a href="https://github.com/MinecraftForge/MinecraftForge/blob/1.19.x/LICENSE.txt">...</a> + */ +@Mixin(Framebuffer.class) +public abstract class FramebufferMixin implements FramebufferHook { + @Shadow public int textureWidth; + @Shadow public int textureHeight; + @Shadow private int depthAttachment; + + @Shadow public abstract void resize(int width, int height, boolean getError); + + @Shadow public int viewportWidth; + @Shadow public int viewportHeight; + private boolean stencilEnabled = false; + + @Redirect(method = "initFbo", at = @At(value = "INVOKE", target = "Lcom/mojang/blaze3d/platform/GlStateManager;texImage2D(IIIIIIIILjava/nio/IntBuffer;)V", ordinal = 0)) + private void stencilSupport(int target, int level, int internalFormat, int width, int height, int border, int format, int type, IntBuffer pixels) { + if (stencilEnabled) { + GlStateManager.texImage2D(3553, 0, 36013, textureWidth, textureHeight, 0, 34041, 36269, null); + } else { + GlStateManager.texImage2D(3553, 0, 6402, textureWidth, textureHeight, 0, 6402, 5126, null); + } + } + + @Redirect(method = "initFbo", at = @At(value = "INVOKE", target = "Lcom/mojang/blaze3d/platform/GlStateManager;framebufferTexture2D(IIIII)V", ordinal = 1)) + private void stencilSupport(int target, int attachment, int textureTarget, int texture, int level) { + if (stencilEnabled) { + GlStateManager.framebufferTexture2D(FramebufferInfo.FRAME_BUFFER, 36096, 3553, depthAttachment, 0); + GlStateManager.framebufferTexture2D(FramebufferInfo.FRAME_BUFFER, 36128, 3553, depthAttachment, 0); + } else { + GlStateManager.framebufferTexture2D(FramebufferInfo.FRAME_BUFFER, FramebufferInfo.DEPTH_ATTACHMENT, 3553, depthAttachment, 0); + } + } + + @Override + public boolean isStencilEnabled() { + return stencilEnabled; + } + + @Override + public void enableStencil() { + if (!this.stencilEnabled) { + this.stencilEnabled = true; + resize(viewportWidth, viewportHeight, MinecraftClient.IS_SYSTEM_MAC); + } + } +} diff --git a/versions/1.16.2-fabric/src/main/java/cc/polyfrost/oneconfig/internal/mixin/GameRendererAccessor.java b/versions/1.16.2-fabric/src/main/java/cc/polyfrost/oneconfig/internal/mixin/GameRendererAccessor.java new file mode 100644 index 0000000..0ebe121 --- /dev/null +++ b/versions/1.16.2-fabric/src/main/java/cc/polyfrost/oneconfig/internal/mixin/GameRendererAccessor.java @@ -0,0 +1,12 @@ +package cc.polyfrost.oneconfig.internal.mixin; + +import net.minecraft.client.render.GameRenderer; +import net.minecraft.util.Identifier; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Invoker; + +@Mixin(GameRenderer.class) +public interface GameRendererAccessor { + @Invoker + void invokeLoadShader(Identifier identifier); +} diff --git a/versions/1.16.2-fabric/src/main/java/cc/polyfrost/oneconfig/internal/mixin/GuiIngameForgeMixin.java b/versions/1.16.2-fabric/src/main/java/cc/polyfrost/oneconfig/internal/mixin/GuiIngameForgeMixin.java new file mode 100644 index 0000000..6a8d283 --- /dev/null +++ b/versions/1.16.2-fabric/src/main/java/cc/polyfrost/oneconfig/internal/mixin/GuiIngameForgeMixin.java @@ -0,0 +1,19 @@ +package cc.polyfrost.oneconfig.internal.mixin; + +import cc.polyfrost.oneconfig.events.EventManager; +import cc.polyfrost.oneconfig.events.event.HudRenderEvent; +import cc.polyfrost.oneconfig.libs.universal.UMatrixStack; +import net.minecraft.client.gui.hud.InGameHud; +import net.minecraft.client.util.math.MatrixStack; +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.CallbackInfo; + +@Mixin(InGameHud.class) +public class GuiIngameForgeMixin { + @Inject(method = "render", at = @At("TAIL")) + private void onRenderGameOverlay(MatrixStack matrices, float tickDelta, CallbackInfo ci) { + EventManager.INSTANCE.post(new HudRenderEvent(new UMatrixStack(matrices), tickDelta)); + } +}
\ No newline at end of file diff --git a/versions/1.16.2-fabric/src/main/java/cc/polyfrost/oneconfig/internal/mixin/KeyboardMixin.java b/versions/1.16.2-fabric/src/main/java/cc/polyfrost/oneconfig/internal/mixin/KeyboardMixin.java new file mode 100644 index 0000000..7d0a33f --- /dev/null +++ b/versions/1.16.2-fabric/src/main/java/cc/polyfrost/oneconfig/internal/mixin/KeyboardMixin.java @@ -0,0 +1,20 @@ +package cc.polyfrost.oneconfig.internal.mixin; + +import cc.polyfrost.oneconfig.events.EventManager; +import cc.polyfrost.oneconfig.events.event.KeyInputEvent; +import net.minecraft.client.Keyboard; +import net.minecraft.client.MinecraftClient; +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.CallbackInfo; + +@Mixin(Keyboard.class) +public class KeyboardMixin { + @Inject(method = "onKey", at = @At("TAIL")) + private void onKeyEvent(long windowPointer, int key, int scanCode, int action, int modifiers, CallbackInfo ci) { + if (windowPointer == MinecraftClient.getInstance().getWindow().getHandle()) { + EventManager.INSTANCE.post(new KeyInputEvent()); + } + } +} diff --git a/versions/1.16.2-fabric/src/main/java/cc/polyfrost/oneconfig/internal/mixin/MinecraftMixin.java b/versions/1.16.2-fabric/src/main/java/cc/polyfrost/oneconfig/internal/mixin/MinecraftMixin.java new file mode 100644 index 0000000..0acb015 --- /dev/null +++ b/versions/1.16.2-fabric/src/main/java/cc/polyfrost/oneconfig/internal/mixin/MinecraftMixin.java @@ -0,0 +1,60 @@ +package cc.polyfrost.oneconfig.internal.mixin; + +import cc.polyfrost.oneconfig.events.EventManager; +import cc.polyfrost.oneconfig.events.event.*; + +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.gui.screen.Screen; +import net.minecraft.client.render.RenderTickCounter; +import org.spongepowered.asm.mixin.Final; +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; + +@Mixin(MinecraftClient.class) +public class MinecraftMixin { + @Final + @Shadow + private RenderTickCounter renderTickCounter; + + @Inject(method = "stop", at = @At("HEAD")) + private void onShutdown(CallbackInfo ci) { + EventManager.INSTANCE.post(new PreShutdownEvent()); + } + + @Inject(method = "render", at = @At(value = "INVOKE", target = "Lnet/minecraft/util/profiler/Profiler;swap(Ljava/lang/String;)V", ordinal = 0)) + private void onRenderTickStart(CallbackInfo ci) { + EventManager.INSTANCE.post(new RenderEvent(Stage.START, renderTickCounter.tickDelta)); + } + + @Inject(method = "render", at = @At(value = "INVOKE", target = "Lnet/minecraft/util/profiler/Profiler;pop()V", shift = At.Shift.AFTER, ordinal = 4)) + private void onRenderTickEnd(CallbackInfo ci) { + EventManager.INSTANCE.post(new RenderEvent(Stage.END, renderTickCounter.tickDelta)); + } + + @Inject(method = "tick", at = @At(value = "INVOKE", target = "Lnet/minecraft/util/profiler/Profiler;push(Ljava/lang/String;)V", ordinal = 0)) + private void onClientTickStart(CallbackInfo ci) { + EventManager.INSTANCE.post(new TickEvent(Stage.START)); + } + + @Inject(method = "tick", at = @At("TAIL")) + private void onClientTickEnd(CallbackInfo ci) { + EventManager.INSTANCE.post(new TickEvent(Stage.END)); + } + + @Inject(method = "openScreen", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/network/ClientPlayerEntity;requestRespawn()V", shift = At.Shift.BY, by = 2), cancellable = true) + private void onGuiOpenEvent(Screen screen, CallbackInfo ci) { + ScreenOpenEvent event = new ScreenOpenEvent(screen); + EventManager.INSTANCE.post(event); + if (event.isCancelled) { + ci.cancel(); + } + } + + @Inject(method = "render", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/render/RenderTickCounter;beginRenderTick(J)I", shift = At.Shift.AFTER)) + private void onDeltaTickTimerUpdate(CallbackInfo ci) { + EventManager.INSTANCE.post(new TimerUpdateEvent(renderTickCounter, true)); + } +}
\ No newline at end of file diff --git a/versions/1.16.2-fabric/src/main/java/cc/polyfrost/oneconfig/internal/mixin/MouseAccessor.java b/versions/1.16.2-fabric/src/main/java/cc/polyfrost/oneconfig/internal/mixin/MouseAccessor.java new file mode 100644 index 0000000..2765b3a --- /dev/null +++ b/versions/1.16.2-fabric/src/main/java/cc/polyfrost/oneconfig/internal/mixin/MouseAccessor.java @@ -0,0 +1,17 @@ +package cc.polyfrost.oneconfig.internal.mixin; + +import net.minecraft.client.Mouse; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Accessor; + +@Mixin(Mouse.class) +public interface MouseAccessor { + @Accessor("eventDeltaWheel") + double getEventDeltaWheel(); + + @Accessor + double getCursorDeltaX(); + + @Accessor + double getCursorDeltaY(); +} diff --git a/versions/1.16.2-fabric/src/main/java/cc/polyfrost/oneconfig/internal/mixin/MouseMixin.java b/versions/1.16.2-fabric/src/main/java/cc/polyfrost/oneconfig/internal/mixin/MouseMixin.java new file mode 100644 index 0000000..c088c32 --- /dev/null +++ b/versions/1.16.2-fabric/src/main/java/cc/polyfrost/oneconfig/internal/mixin/MouseMixin.java @@ -0,0 +1,20 @@ +package cc.polyfrost.oneconfig.internal.mixin; + +import cc.polyfrost.oneconfig.events.EventManager; +import cc.polyfrost.oneconfig.events.event.MouseInputEvent; +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.Mouse; +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.CallbackInfo; + +@Mixin(Mouse.class) +public class MouseMixin { + @Inject(method = "onMouseButton", at = @At("TAIL")) + private void onMouse(long handle, int button, int action, int mods, CallbackInfo ci) { + if (handle == MinecraftClient.getInstance().getWindow().getHandle()) { + EventManager.INSTANCE.post(new MouseInputEvent()); + } + } +} diff --git a/versions/1.16.2-fabric/src/main/java/cc/polyfrost/oneconfig/internal/mixin/NetHandlerPlayClientMixin.java b/versions/1.16.2-fabric/src/main/java/cc/polyfrost/oneconfig/internal/mixin/NetHandlerPlayClientMixin.java new file mode 100644 index 0000000..cdd673a --- /dev/null +++ b/versions/1.16.2-fabric/src/main/java/cc/polyfrost/oneconfig/internal/mixin/NetHandlerPlayClientMixin.java @@ -0,0 +1,25 @@ +package cc.polyfrost.oneconfig.internal.mixin; + +import cc.polyfrost.oneconfig.events.EventManager; +import cc.polyfrost.oneconfig.events.event.ChatReceiveEvent; +import net.minecraft.client.network.ClientPlayNetworkHandler; +import net.minecraft.network.packet.s2c.play.GameMessageS2CPacket; +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.CallbackInfo; + +@Mixin(value = ClientPlayNetworkHandler.class, priority = Integer.MAX_VALUE) +public class NetHandlerPlayClientMixin { + + @Inject(method = "onGameMessage", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/hud/InGameHud;addChatMessage(Lnet/minecraft/network/MessageType;Lnet/minecraft/text/Text;Ljava/util/UUID;)V"), cancellable = true) + private void onClientChat(GameMessageS2CPacket packet, CallbackInfo ci) { + if (packet.getLocation().getId() == 0) { + ChatReceiveEvent event = new ChatReceiveEvent(packet.getMessage()); + EventManager.INSTANCE.post(event); + if (event.isCancelled) { + ci.cancel(); + } + } + } +}
\ No newline at end of file diff --git a/versions/1.16.2-fabric/src/main/java/cc/polyfrost/oneconfig/internal/mixin/NetworkManagerMixin.java b/versions/1.16.2-fabric/src/main/java/cc/polyfrost/oneconfig/internal/mixin/NetworkManagerMixin.java new file mode 100644 index 0000000..825effa --- /dev/null +++ b/versions/1.16.2-fabric/src/main/java/cc/polyfrost/oneconfig/internal/mixin/NetworkManagerMixin.java @@ -0,0 +1,42 @@ +package cc.polyfrost.oneconfig.internal.mixin; + +import cc.polyfrost.oneconfig.events.EventManager; +import cc.polyfrost.oneconfig.events.event.ReceivePacketEvent; +import cc.polyfrost.oneconfig.events.event.SendPacketEvent; +import io.netty.channel.ChannelHandlerContext; +import io.netty.util.concurrent.Future; +import io.netty.util.concurrent.GenericFutureListener; +import net.minecraft.network.ClientConnection; +import net.minecraft.network.Packet; +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.CallbackInfo; + +@Mixin(value = ClientConnection.class, priority = Integer.MAX_VALUE) +public class NetworkManagerMixin { + + @Inject(method = "send(Lnet/minecraft/network/Packet;Lio/netty/util/concurrent/GenericFutureListener;)V", at = @At("HEAD"), cancellable = true) + private void onSendPacket(Packet<?> packet, GenericFutureListener<? extends Future<? super Void>> callback, CallbackInfo ci) { + onSendPacket(packet, ci); + } + + @Inject(method = "send(Lnet/minecraft/network/Packet;)V", at = @At("HEAD"), cancellable = true) + private void onSendPacket(Packet<?> packet, CallbackInfo ci) { + SendPacketEvent event = new SendPacketEvent(packet); + EventManager.INSTANCE.post(event); + if (event.isCancelled) { + ci.cancel(); + } + } + + + @Inject(method = "channelRead0(Lio/netty/channel/ChannelHandlerContext;Lnet/minecraft/network/Packet;)V", at = @At("HEAD"), cancellable = true) + private void onReceivePacket(ChannelHandlerContext channelHandlerContext, Packet<?> packet, CallbackInfo ci) { + ReceivePacketEvent event = new ReceivePacketEvent(packet); + EventManager.INSTANCE.post(event); + if (event.isCancelled) { + ci.cancel(); + } + } +}
\ No newline at end of file diff --git a/versions/1.16.2-fabric/src/main/java/cc/polyfrost/oneconfig/internal/mixin/TickTimeTrackerMixin.java b/versions/1.16.2-fabric/src/main/java/cc/polyfrost/oneconfig/internal/mixin/TickTimeTrackerMixin.java new file mode 100644 index 0000000..8b655d8 --- /dev/null +++ b/versions/1.16.2-fabric/src/main/java/cc/polyfrost/oneconfig/internal/mixin/TickTimeTrackerMixin.java @@ -0,0 +1,24 @@ +package cc.polyfrost.oneconfig.internal.mixin; + +import cc.polyfrost.oneconfig.events.EventManager; +import cc.polyfrost.oneconfig.events.event.ShutdownEvent; +import cc.polyfrost.oneconfig.events.event.StartEvent; +import net.minecraft.util.profiler.TickTimeTracker; +import cc.polyfrost.oneconfig.internal.OneConfig; +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.CallbackInfo; + +import java.util.function.IntSupplier; +import java.util.function.LongSupplier; + +@Mixin(TickTimeTracker.class) +public class TickTimeTrackerMixin { + @Inject(method = "<init>", at = @At("RETURN")) + private void onStart(LongSupplier longSupplier, IntSupplier intSupplier, CallbackInfo ci) { + OneConfig.init(); + EventManager.INSTANCE.post(new StartEvent()); + Runtime.getRuntime().addShutdownHook(new Thread(() -> EventManager.INSTANCE.post(new ShutdownEvent()))); + } +} diff --git a/versions/1.16.2-fabric/src/main/java/cc/polyfrost/oneconfig/internal/mixin/WorldClientMixin.java b/versions/1.16.2-fabric/src/main/java/cc/polyfrost/oneconfig/internal/mixin/WorldClientMixin.java new file mode 100644 index 0000000..4fc4ba5 --- /dev/null +++ b/versions/1.16.2-fabric/src/main/java/cc/polyfrost/oneconfig/internal/mixin/WorldClientMixin.java @@ -0,0 +1,24 @@ +package cc.polyfrost.oneconfig.internal.mixin; + +import cc.polyfrost.oneconfig.events.EventManager; +import cc.polyfrost.oneconfig.events.event.WorldLoadEvent; +import net.minecraft.client.network.ClientPlayNetworkHandler; +import net.minecraft.client.render.WorldRenderer; +import net.minecraft.client.world.ClientWorld; +import net.minecraft.util.registry.RegistryKey; +import net.minecraft.world.World; +import net.minecraft.world.dimension.DimensionType; +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.CallbackInfo; + +import java.util.function.Supplier; + +@Mixin(ClientWorld.class) +public class WorldClientMixin { + @Inject(method = "<init>", at = @At("RETURN")) + private void onWorldLoad(ClientPlayNetworkHandler clientPlayNetworkHandler, ClientWorld.Properties properties, RegistryKey<World> registryKey, DimensionType dimensionType, int i, Supplier<World> supplier, WorldRenderer worldRenderer, boolean bl, long l, CallbackInfo ci) { + EventManager.INSTANCE.post(new WorldLoadEvent()); + } +}
\ No newline at end of file diff --git a/versions/1.16.2-fabric/src/main/java/cc/polyfrost/oneconfig/internal/plugin/OneConfigPreLaunch.java b/versions/1.16.2-fabric/src/main/java/cc/polyfrost/oneconfig/internal/plugin/OneConfigPreLaunch.java new file mode 100644 index 0000000..ca57970 --- /dev/null +++ b/versions/1.16.2-fabric/src/main/java/cc/polyfrost/oneconfig/internal/plugin/OneConfigPreLaunch.java @@ -0,0 +1,11 @@ +package cc.polyfrost.oneconfig.internal.plugin; + +import cc.polyfrost.oneconfig.internal.init.OneConfigInit; +import net.fabricmc.loader.api.entrypoint.PreLaunchEntrypoint; + +public class OneConfigPreLaunch implements PreLaunchEntrypoint { + @Override + public void onPreLaunch() { + OneConfigInit.initialize(new String[]{}); + } +} diff --git a/versions/1.16.2-fabric/src/main/java/cc/polyfrost/oneconfig/utils/commands/PlatformCommandManagerImpl.java b/versions/1.16.2-fabric/src/main/java/cc/polyfrost/oneconfig/utils/commands/PlatformCommandManagerImpl.java new file mode 100644 index 0000000..674d7b9 --- /dev/null +++ b/versions/1.16.2-fabric/src/main/java/cc/polyfrost/oneconfig/utils/commands/PlatformCommandManagerImpl.java @@ -0,0 +1,122 @@ +package cc.polyfrost.oneconfig.utils.commands; + +import cc.polyfrost.oneconfig.libs.universal.ChatColor; +import cc.polyfrost.oneconfig.libs.universal.UChat; +import cc.polyfrost.oneconfig.utils.commands.annotations.Command; +import cc.polyfrost.oneconfig.utils.commands.annotations.Greedy; +import cc.polyfrost.oneconfig.utils.commands.arguments.ArgumentParser; +import cc.polyfrost.oneconfig.utils.commands.arguments.Arguments; +import com.mojang.brigadier.StringReader; +import com.mojang.brigadier.arguments.ArgumentType; +import com.mojang.brigadier.builder.LiteralArgumentBuilder; +import com.mojang.brigadier.context.CommandContext; +import com.mojang.brigadier.suggestion.Suggestions; +import com.mojang.brigadier.suggestion.SuggestionsBuilder; +import net.minecraft.server.command.ServerCommandSource; +import org.apache.commons.lang3.tuple.ImmutablePair; +import org.apache.commons.lang3.tuple.Pair; + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Parameter; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.concurrent.CompletableFuture; + +import static cc.polyfrost.oneconfig.utils.commands.CommandManager.METHOD_RUN_ERROR; + +public class PlatformCommandManagerImpl extends PlatformCommandManager { + + final HashMap<Class<?>, Pair<ArgumentType<Object>, ArgumentType<Object>>> parsers = new HashMap<>(); // non-greedy, greedy + + @Override + void createCommand(CommandManager.InternalCommand root, Command annotation) { + LiteralArgumentBuilder<ServerCommandSource> builder = net.minecraft.server.command.CommandManager.literal(annotation.value()); + if (!root.invokers.isEmpty()) { + builder.executes((context -> + { + try { + root.invokers.get(0).method.invoke(null); + return 1; + } catch (IllegalAccessException | InvocationTargetException | IllegalArgumentException | + ExceptionInInitializerError e) { + UChat.chat(ChatColor.RED.toString() + ChatColor.BOLD + METHOD_RUN_ERROR); + return 0; + } + })); + } + if (annotation.helpCommand()) { + builder.then(net.minecraft.server.command.CommandManager.literal("help").executes((context -> + { + UChat.chat(sendHelpCommand(root)); + return 1; + }))); + } + for (CommandManager.InternalCommand command : root.children) { + loopThroughChildren(command, builder, null); + } + } + + private void loopThroughChildren(CommandManager.InternalCommand command, LiteralArgumentBuilder<ServerCommandSource> root, LiteralArgumentBuilder<ServerCommandSource> builder) { + if (command.invokers.isEmpty() || command.children.isEmpty()) return; + if (builder == null) { + builder = root.then(net.minecraft.server.command.CommandManager.literal(command.name)); + } else { + builder = builder.then(net.minecraft.server.command.CommandManager.literal(command.name)); + } + for (CommandManager.InternalCommand.InternalCommandInvoker invoker : command.invokers) { + for (Parameter parameter : invoker.method.getParameters()) { + Pair<ArgumentType<Object>, ArgumentType<Object>> pair = parsers.get(parameter.getType()); + builder.then(net.minecraft.server.command.CommandManager.argument(parameter.getName(), parameter.isAnnotationPresent(Greedy.class) ? pair.getRight() : pair.getLeft())); + } + builder.executes((context -> + { + try { + ArrayList<Object> args = new ArrayList<>(invoker.method.getParameterCount()); + for (Parameter parameter: invoker.method.getParameters()) { + args.add(context.getArgument(parameter.getName(), Object.class)); + } + invoker.method.invoke(null, args); + return 1; + } catch (Exception e) { + e.printStackTrace(); + UChat.chat(ChatColor.RED.toString() + ChatColor.BOLD + METHOD_RUN_ERROR); + return 0; + } + })); + } + for (CommandManager.InternalCommand child : command.children) { + loopThroughChildren(child, root, builder); + } + } + + @Override + public void handleNewParser(ArgumentParser<?> parser, Class<?> clazz) { + parsers.put(clazz, new ImmutablePair<ArgumentType<Object>, ArgumentType<Object>>(new ArgumentType() { + + @Override + public Object parse(StringReader reader) { + final String text = reader.getRemaining(); + reader.setCursor(reader.getTotalLength()); + return parser.parse(new Arguments(text.split("\\s+"), false)); + } + + @Override + public CompletableFuture<Suggestions> listSuggestions(CommandContext context, SuggestionsBuilder builder) { + return ArgumentType.super.listSuggestions(context, builder); + } + }, new ArgumentType() { + + @Override + public Object parse(StringReader reader) { + final String text = reader.getRemaining(); + reader.setCursor(reader.getTotalLength()); + return parser.parse(new Arguments(text.split("\\s+"), true)); + } + + @Override + public CompletableFuture<Suggestions> listSuggestions(CommandContext context, SuggestionsBuilder builder) { + return ArgumentType.super.listSuggestions(context, builder); + } + })); + } +} |