diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index e2c0d218..6f9fcb4b 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -17,7 +17,7 @@ jobs: - uses: actions/setup-java@v4 with: distribution: temurin - java-version: 21 + java-version: 25 - uses: actions/cache@v4 with: diff --git a/.github/workflows/javadocs.yml b/.github/workflows/javadocs.yml deleted file mode 100644 index 4b083978..00000000 --- a/.github/workflows/javadocs.yml +++ /dev/null @@ -1,80 +0,0 @@ -name: javadocs - -on: - push: - tags: - - '**' - workflow_dispatch: - -jobs: - build: - name: Deploy Javadocs - runs-on: "ubuntu-latest" - if: github.repository == 'ChatTriggers/ctjs' - - steps: - - uses: actions/checkout@v4 - - - uses: actions/setup-java@v4 - with: - distribution: temurin - java-version: 21 - - - uses: actions/cache@v4 - with: - path: | - ~/.gradle/caches - ~/.gradle/wrapper - key: "${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties', 'gradle/*.versions.toml') }}" - restore-keys: | - ${{ runner.os }}-gradle- - - - name: Build Javadocs - run: ./gradlew --no-daemon generateDokkaDocs - - - name: Publish Javadocs - uses: appleboy/scp-action@master - with: - host: ${{ secrets.REMOTE_HOST }} - username: ${{ secrets.ACTIONS_DEPLOYER_USERNAME }} - key: ${{ secrets.ACTIONS_DEPLOYER_SSH_KEY }} - passphrase: ${{ secrets.ACTIONS_DEPLOYER_PASSPHRASE }} - source: ${{ github.workspace }}/build/javadocs/ - # TODO: Remove "new-" when we transition to 3.0.0 - target: /srv/www/static/home/new-javadocs - strip_components: 4 - rm: true - - - name: Set File Permissions - uses: appleboy/ssh-action@master - with: - host: ${{ secrets.REMOTE_HOST }} - username: ${{ secrets.ACTIONS_DEPLOYER_USERNAME }} - key: ${{ secrets.ACTIONS_DEPLOYER_SSH_KEY }} - passphrase: ${{ secrets.ACTIONS_DEPLOYER_PASSPHRASE }} - script: | - chmod -R g+w /srv/www/static/home/new-javadocs - chmod -R g+w /srv/www/static/home/javadocs-archive - - - name: Create archives zip file - if: startsWith(github.ref, 'refs/tags/') - uses: appleboy/ssh-action@master - with: - host: ${{ secrets.REMOTE_HOST }} - username: ${{ secrets.ACTIONS_DEPLOYER_USERNAME }} - key: ${{ secrets.ACTIONS_DEPLOYER_SSH_KEY }} - passphrase: ${{ secrets.ACTIONS_DEPLOYER_PASSPHRASE }} - script: | - tag=${{ github.ref_name }} - echo "Creating archive, tag=${tag}..." - - # Copy the current javadocs to a new dir, remove the "older" directory, and - # save it as a zip file in the archives folder - cd /srv/www/static/home - cp -r new-javadocs tmp - rm -rf tmp/older - zip -r "${tag}.zip" tmp - mv "${tag}.zip" javadocs-archive - rm -rf tmp - - echo "${tag}" >> javadocs-archive/versions diff --git a/README.md b/README.md index 9a0833ee..713b4dfc 100644 --- a/README.md +++ b/README.md @@ -8,81 +8,136 @@ Discord - - Releases - - - Build Status -

-ChatTriggers (CT) is a framework for Minecraft that enables live scripting and client modification using JavaScript. We provide libraries, wrappers, objects, and more to make your life as a modder as easy as possible. Even if we don't support something you need, you can still access any Java classes and native fields/methods. - -With CT, you have all the power of a modding environment with the benefit of an easy-to-use language and the ability to reload your scripts without restarting the game. CT also provides a way to [define your own Mixins](https://github.com/ChatTriggers/ctjs/wiki/Dynamic-Mixins)! - -CT is currently written for Fabric 1.19. See [this repo](https://github.com/ChatTriggers/ChatTriggers) for the deprecated Forge 1.8.9 version. - -### Examples +ChatTriggers (CT) is a framework for Minecraft that enables live scripting and client modification using JavaScript. -Want to hide an annoying server message that you see every time you join a world? +This version has been specifically written by me (srockw) for my own purposes, and it is NOT backwards compatible with +previous CT versions due to a couple of reasons: -```js -register('chat', event => { - cancel(event); -}).setCriteria("Check out our store at www.some-mc-server.com for 50% off!"); -``` - -How about automating a series of common commands into one? +- Most objects and libraries (such as ChatLib, TextComponent, Renderer) have been removed. +- Most of the registers have been removed. +- Custom mixins have been removed (but I might add them back later if I get the motivation). -```js -register('command', () => { - ChatLib.command('command1'); - ChatLib.command('command2'); - ChatLib.command('command3'); -}).setName('commandgroup'); -``` +These changes were made to keep the mod as simple as possible and easy to update to newer versions when they come out. +You can make your own libraries within modules or even fork the project to add them yourself if you want. +Making additional registers can require using Fabric events or sometimes mixins, so they're not able to be added through +modules currently, you can let me know in Discord if you have one you need, and I'll look into it. -Or even something silly like a calculator command - -```js -register('command', (...args) => { - // Evaluate all args the user gives us... - const result = new Function('return ' + args.join(' '))(); - - // ...and show the result is a nice green color - ChatLib.chat(`&aResult: ${result}`); -}).command('calc'); -``` - -With CT's register system, you can listen to custom events that we emit and react to them. For example, we emit events when you switch worlds, click on a GUI, hit a block, hover over an item and see its tooltip, and much more! You can even provide custom events for other module authors to use. +> [!NOTE] +> If you want these libraries and registers, I recommend going to [DocilElm's fork](https://github.com/Synnerz/ctjs), +> but note that as of writing this it is not being updated. ### Getting Started -To begin, [download and install Fabric](https://fabricmc.net/wiki/install) for one of the supported versions, then head over to our [releases page](https://github.com/ChatTriggers/ctjs/releases) and download the latest version. The mod is installed like any mod; just drag it into your mods folder. Once installed, you can import modules in-game by typing `/ct import `, where `` is the name of the module. You can browse the available modules on [our website](https://www.chattriggers.com/modules). +I don't currently have any plans to make releases, so the only way for you to download this mod would be +through [GitHub actions](https://github.com/srockw/ctjs/actions), which require you to login and will expire after a +certain period of time. + +The currently supported version is 26.1.2. ### Writing Modules -If you can't find any modules on the website that do exactly what you want, which is quite likely, you'll have you write your own! Here are the steps you'll want to take: +To create a module, follow these steps: -1. Navigate to the `.minecraft/config/ChatTriggers/modules` folder. If you don't know where this is, you can also execute `/ct files`, which will open the correct directory automatically. -1. Create a new directory with the name of your module -1. Inside the directory, create a file called `metadata.json`, and inside of that, put the following text: +1. Navigate to the `.minecraft/config/ChatTriggers/modules` folder. If you don't know where this is, you can also + execute `/ct files`, which will open the correct directory automatically. +2. Create a new directory with the name of your module. +3. Inside the directory, create a file called `metadata.json`, and inside of that, put the following text: ```json { "name": "", "entry": "index.js" } ``` - This means that when our module first runs, CT will run the `index.js` file + This means that when our module first runs, CT will run the `index.js` file - _Note that `` must match the name of your folder exactly!_ -1. Create the `index.js` file, and put some code in there. What exactly you write will depend on what you want CT to do. To learn more about the available APIs, take a look at the [Slate](https://chattriggers.com/slate/#introduction). - * Some things on the Slate may be outdated, we are working on improving this + _Note that `` must match the name of your folder exactly!_ +4. Create the `index.js` file, and put some code in there. +5. Do `/ct load` to reload all modules after modifying them. +6. (Optional, but recommended) After downloading the mod from the latest action you will have also gotten a file called + `typings.d.ts`, the purpose of this file is to provide autocompletions and suggestions in an IDE. For example, in + VSCode it is sufficient to have the file open while editing your JavaScript files, but it depends on the IDE. ### Documentation -- [Slate](https://chattriggers.com/slate/#introduction), a guided tutorial that covers the basics -- [Javadocs](https://chattriggers.com/javadocs/), a technical reference for all public APIs in the mod -- [MIGRATION.md](docs/MIGRATION.md), a guide for upgrading modules from CT 2.X to 3.0 -- [CONTRIBUTING.md](CONTRIBUTING.md) (TODO) +Since the game is no longer obfuscated, you can access all the vanilla MC classes and methods by just going through +their path, such as `net.minecraft.client.Minecraft` and use all their methods as normal. The `typings.d.ts` file +mentioned previously will help you through this, but note that it does NOT include all classes available to you, I +recommend +going to [mcsrc.dev](https://mcsrc.dev) if there is something you can't find. + +While most of the libraries have been removed, some essential ones still remain: + +#### Register + +You can easily view all available registers using the autocompletions from the `typings.d.ts` file, they should be +pretty self-explanatory, and besides `renderOverlay` the other ones starting with `render` are for 3D rendering. + +```js +// Hide all messages including "something" +register("chat", (msg, event) => { + if (msg.getString().includes("something")) { + cancel(event); + } +}); +``` + +#### CustomKeyMapping + +Allows you to create your own keybindings, which will show up in the options screen just as any other. + +```js +const GLFW = org.lwjgl.glfw.GLFW; + +// Create your own keybind. +// Note that the last parameter, the category, has to be a valid identifier, which cannot include spaces and it won't be translated. (So no nice looking categories, at least for now) +const myKey = CustomKeyMapping.register("My Key", GLFW.GLFW_KEY_P, "my_category"); // This returns a vanilla KeyMapping object. + +// Can also get the KeyMapping object of other keys. +const vanillaSneak = CustomKeyMapping.find("key.sneak"); + +register("tick", () => { + // Using the typings file you can easily see which methods are available through you. + if (myKey.consumeClick()) { + // Do something + } +}); +``` + +#### CustomCommand + +Allows you to create brigadier commands: + +```js +const IntegerArgumentType = com.mojang.brigadier.arguments.IntegerArgumentType; + +CustomCommand.register("mytime", (node) => { + node.literal("set", (node) => { + node.literal("day", (node) => { + node.exec((ctx) => { + // called when '/mytime set day' is used + }); + }); + + node.literal("night", (node) => { + node.exec((ctx) => { + // called when '/mytime set night' is used + }); + }); + }); + + node.literal("add", (node) => { + // here "time" is the name of this argument, 'IntegerArgumentType.integer()' defines the type of the argument, you can use any ArgumentType. + node.argument("time", IntegerArgumentType.integer(), (node) => { + node.exec((ctx) => { + // called when '/mytime add ' is used + + // access the time parameter we defined earlier + const time = IntegerArgumentType.getInteger(ctx, "time"); + }); + }); + }); +}); +``` diff --git a/api/ctjs.api b/api/ctjs.api index e74e34cd..572068ac 100644 --- a/api/ctjs.api +++ b/api/ctjs.api @@ -3,37 +3,24 @@ public final class com/chattriggers/ctjs/CTJS : net/fabricmc/api/ClientModInitia public static final field MODULES_FOLDER Ljava/lang/String; public static final field MOD_ID Ljava/lang/String; public static final field MOD_VERSION Ljava/lang/String; - public static final field WEBSITE_ROOT Ljava/lang/String; public fun ()V public static final fun isLoaded ()Z - public static final fun load (Z)V + public static final fun load ()V public fun onInitializeClient ()V - public static final fun unload (Z)V + public static final fun unload ()V } public final class com/chattriggers/ctjs/CTJS$Companion { public final fun getAssetsDir ()Ljava/io/File; public final fun getConfigLocation ()Ljava/io/File; public final fun isLoaded ()Z - public final fun load (Z)V - public static synthetic fun load$default (Lcom/chattriggers/ctjs/CTJS$Companion;ZILjava/lang/Object;)V + public final fun load ()V public final fun makeWebRequest$ctjs (Ljava/lang/String;)Ljava/net/URLConnection; - public final fun unload (Z)V - public static synthetic fun unload$default (Lcom/chattriggers/ctjs/CTJS$Companion;ZILjava/lang/Object;)V -} - -public abstract interface class com/chattriggers/ctjs/api/CTWrapper { - public abstract fun getMcValue ()Ljava/lang/Object; - public abstract fun toMC ()Ljava/lang/Object; -} - -public final class com/chattriggers/ctjs/api/CTWrapper$DefaultImpls { - public static fun toMC (Lcom/chattriggers/ctjs/api/CTWrapper;)Ljava/lang/Object; + public final fun unload ()V } public final class com/chattriggers/ctjs/api/Config : gg/essential/vigilance/Vigilant { public static final field INSTANCE Lcom/chattriggers/ctjs/api/Config; - public static final fun getAutoUpdateModules ()Z public static final fun getClearConsoleOnLoad ()Z public static final fun getConsoleBackgroundColor ()Ljava/awt/Color; public static final fun getConsoleErrorColor ()Ljava/awt/Color; @@ -43,11 +30,7 @@ public final class com/chattriggers/ctjs/api/Config : gg/essential/vigilance/Vig public static final fun getConsoleTheme ()I public static final fun getConsoleWarningColor ()Ljava/awt/Color; public static final fun getCustomTheme ()Z - public static final fun getModuleChangelog ()Z - public static final fun getModuleImportHelp ()Z public static final fun getOpenConsoleOnError ()Z - public static final fun getShowUpdatesInChat ()Z - public static final fun setAutoUpdateModules (Z)V public static final fun setClearConsoleOnLoad (Z)V public static final fun setConsoleBackgroundColor (Ljava/awt/Color;)V public static final fun setConsoleErrorColor (Ljava/awt/Color;)V @@ -57,10 +40,7 @@ public final class com/chattriggers/ctjs/api/Config : gg/essential/vigilance/Vig public static final fun setConsoleTheme (I)V public static final fun setConsoleWarningColor (Ljava/awt/Color;)V public static final fun setCustomTheme (Z)V - public static final fun setModuleChangelog (Z)V - public static final fun setModuleImportHelp (Z)V public static final fun setOpenConsoleOnError (Z)V - public static final fun setShowUpdatesInChat (Z)V } public final class com/chattriggers/ctjs/api/Config$ConsoleSettings { @@ -107,92 +87,8 @@ public final class com/chattriggers/ctjs/api/Config$ConsoleSettings$Companion { public final fun make ()Lcom/chattriggers/ctjs/api/Config$ConsoleSettings; } -public final class com/chattriggers/ctjs/api/Mappings { - public static final field INSTANCE Lcom/chattriggers/ctjs/api/Mappings; - public static final fun mapClassName (Ljava/lang/String;)Ljava/lang/String; - public static final fun unmapClass (Ljava/lang/Class;)Ljava/lang/String; - public static final fun unmapClassName (Ljava/lang/String;)Ljava/lang/String; -} - -public final class com/chattriggers/ctjs/api/client/CPS : com/chattriggers/ctjs/internal/utils/Initializer { - public static final field INSTANCE Lcom/chattriggers/ctjs/api/client/CPS; - public static final fun getLeftClicks ()I - public static final fun getLeftClicksAverage ()I - public static final fun getLeftClicksMax ()I - public static final fun getMiddleClicks ()I - public static final fun getMiddleClicksAverage ()I - public static final fun getMiddleClicksMax ()I - public static final fun getRightClicks ()I - public static final fun getRightClicksAverage ()I - public static final fun getRightClicksMax ()I - public fun init ()V -} - -public final class com/chattriggers/ctjs/api/client/Client { - public static final field INSTANCE Lcom/chattriggers/ctjs/api/client/Client; - public static final field camera Lcom/chattriggers/ctjs/api/client/Client$CameraWrapper; - public static final field currentGui Lcom/chattriggers/ctjs/api/client/Client$CurrentGuiWrapper; - public static final field settings Lcom/chattriggers/ctjs/api/client/Settings; - public static final fun connect (Ljava/lang/String;)V - public static final fun connect (Ljava/lang/String;I)V - public static synthetic fun connect$default (Ljava/lang/String;IILjava/lang/Object;)V - public static final fun copy ()V - public static final fun copy (Ljava/lang/String;)V - public static synthetic fun copy$default (Ljava/lang/String;ILjava/lang/Object;)V - public static final fun disconnect ()V - public static final fun getChatGui ()Lnet/minecraft/client/gui/hud/ChatHud; - public static final fun getConnection ()Lnet/minecraft/client/network/ClientPlayNetworkHandler; - public static final fun getCurrentChatMessage ()Ljava/lang/String; - public static final fun getFPS ()I - public static final fun getFreeMemory ()J - public static final fun getKeyBindFromDescription (Ljava/lang/String;)Lcom/chattriggers/ctjs/api/client/KeyBind; - public static final fun getKeyBindFromKey (I)Lcom/chattriggers/ctjs/api/client/KeyBind; - public static final fun getKeyBindFromKey (ILjava/lang/String;)Lcom/chattriggers/ctjs/api/client/KeyBind; - public static final fun getKeyBindFromKey (ILjava/lang/String;Ljava/lang/String;)Lcom/chattriggers/ctjs/api/client/KeyBind; - public static synthetic fun getKeyBindFromKey$default (ILjava/lang/String;Ljava/lang/String;ILjava/lang/Object;)Lcom/chattriggers/ctjs/api/client/KeyBind; - public static final fun getMaxMemory ()J - public static final fun getMemoryUsage ()I - public static final fun getMinecraft ()Lnet/minecraft/client/MinecraftClient; - public static final fun getMouseX ()D - public static final fun getMouseY ()D - public static final fun getSystemTime ()J - public static final fun getTabGui ()Lnet/minecraft/client/gui/hud/PlayerListHud; - public static final fun getTotalMemory ()J - public static final fun getVersion ()Ljava/lang/String; - public static final fun isAltDown ()Z - public static final fun isControlDown ()Z - public static final fun isInChat ()Z - public static final fun isInGui ()Z - public static final fun isInTab ()Z - public static final fun isShiftDown ()Z - public static final fun isTabbedIn ()Z - public static final fun paste ()Ljava/lang/String; - public static final fun scheduleTask (ILkotlin/jvm/functions/Function0;)V - public static final fun scheduleTask (Lkotlin/jvm/functions/Function0;)V - public static synthetic fun scheduleTask$default (ILkotlin/jvm/functions/Function0;ILjava/lang/Object;)V - public static final fun sendPacket (Lnet/minecraft/network/packet/Packet;)V - public static final fun setCurrentChatMessage (Ljava/lang/String;)V - public static final fun showTitle (Ljava/lang/String;Ljava/lang/String;III)V -} - -public final class com/chattriggers/ctjs/api/client/Client$CameraWrapper { - public fun ()V - public final fun getX ()D - public final fun getY ()D - public final fun getZ ()D -} - -public final class com/chattriggers/ctjs/api/client/Client$CurrentGuiWrapper { - public fun ()V - public final fun close ()V - public final fun get ()Lnet/minecraft/client/gui/screen/Screen; - public final fun getClassName ()Ljava/lang/String; - public final fun getSlotUnderMouse ()Lcom/chattriggers/ctjs/api/inventory/Slot; - public final fun set (Lnet/minecraft/client/gui/screen/Screen;)V -} - -public final class com/chattriggers/ctjs/api/client/FileLib { - public static final field INSTANCE Lcom/chattriggers/ctjs/api/client/FileLib; +public final class com/chattriggers/ctjs/api/FileLib { + public static final field INSTANCE Lcom/chattriggers/ctjs/api/FileLib; public static final fun append (Ljava/lang/String;Ljava/lang/String;)V public static final fun append (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V public static final fun decodeBase64 (Ljava/lang/String;)Ljava/lang/String; @@ -210,6 +106,7 @@ public final class com/chattriggers/ctjs/api/client/FileLib { public static final fun isDirectory (Ljava/lang/String;Ljava/lang/String;)Z public static final fun open (Ljava/io/File;)V public static final fun open (Ljava/lang/String;)V + public static final fun openModulesFolder ()V public static final fun read (Ljava/io/File;)Ljava/lang/String; public static final fun read (Ljava/lang/String;)Ljava/lang/String; public static final fun read (Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String; @@ -222,1694 +119,11 @@ public final class com/chattriggers/ctjs/api/client/FileLib { public static synthetic fun write$default (Ljava/lang/String;Ljava/lang/String;ZILjava/lang/Object;)V } -public final class com/chattriggers/ctjs/api/client/KeyBind { - public static final field Companion Lcom/chattriggers/ctjs/api/client/KeyBind$Companion; - public fun (Ljava/lang/String;I)V - public fun (Ljava/lang/String;ILjava/lang/String;)V - public synthetic fun (Ljava/lang/String;ILjava/lang/String;ILkotlin/jvm/internal/DefaultConstructorMarker;)V - public fun (Lnet/minecraft/client/option/KeyBinding;)V - public final fun getCategory ()Ljava/lang/String; - public final fun getDescription ()Ljava/lang/String; - public final fun getKeyCode ()I - public final fun isKeyDown ()Z - public final fun isPressed ()Z - public final fun registerKeyDown (Ljava/lang/Object;)Lcom/chattriggers/ctjs/api/client/KeyBind; - public final fun registerKeyPress (Ljava/lang/Object;)Lcom/chattriggers/ctjs/api/client/KeyBind; - public final fun registerKeyRelease (Ljava/lang/Object;)Lcom/chattriggers/ctjs/api/client/KeyBind; - public final fun setState (Z)V - public fun toString ()Ljava/lang/String; - public final fun unregisterKeyDown ()Lcom/chattriggers/ctjs/api/client/KeyBind; - public final fun unregisterKeyPress ()Lcom/chattriggers/ctjs/api/client/KeyBind; - public final fun unregisterKeyRelease ()Lcom/chattriggers/ctjs/api/client/KeyBind; -} - -public final class com/chattriggers/ctjs/api/client/KeyBind$Companion : com/chattriggers/ctjs/internal/utils/Initializer { - public fun init ()V -} - -public final class com/chattriggers/ctjs/api/client/MathLib { - public static final field INSTANCE Lcom/chattriggers/ctjs/api/client/MathLib; - public static final fun clamp (III)I - public static final fun clampFloat (FFF)F - public static final fun map (FFFFF)F -} - -public final class com/chattriggers/ctjs/api/client/Player { - public static final field INSTANCE Lcom/chattriggers/ctjs/api/client/Player; - public static final field armor Lcom/chattriggers/ctjs/api/client/Player$ArmorWrapper; - public static final fun asPlayerMP ()Lcom/chattriggers/ctjs/api/entity/PlayerMP; - public static final fun draw (Lorg/mozilla/javascript/NativeObject;)Lcom/chattriggers/ctjs/api/client/Player; - public static final fun facing ()Ljava/lang/String; - public static final fun getActivePotionEffects ()Ljava/util/List; - public static final fun getAirLevel ()I - public static final fun getArmorPoints ()I - public static final fun getBiome ()Ljava/lang/String; - public static final fun getContainer ()Lcom/chattriggers/ctjs/api/inventory/Inventory; - public static final fun getDisplayName ()Lcom/chattriggers/ctjs/api/message/TextComponent; - public static final fun getHP ()F - public static final fun getHeldItem ()Lcom/chattriggers/ctjs/api/inventory/Item; - public static final fun getHeldItem (Lnet/minecraft/util/Hand;)Lcom/chattriggers/ctjs/api/inventory/Item; - public static synthetic fun getHeldItem$default (Lnet/minecraft/util/Hand;ILjava/lang/Object;)Lcom/chattriggers/ctjs/api/inventory/Item; - public static final fun getHeldItemIndex ()I - public static final fun getHunger ()I - public static final fun getInventory ()Lcom/chattriggers/ctjs/api/inventory/Inventory; - public static final fun getLastX ()D - public static final fun getLastY ()D - public static final fun getLastZ ()D - public static final fun getLightLevel ()I - public static final fun getMotionX ()D - public static final fun getMotionY ()D - public static final fun getMotionZ ()D - public static final fun getName ()Ljava/lang/String; - public static final fun getPitch ()D - public static final fun getPlayer ()Lnet/minecraft/client/network/ClientPlayerEntity; - public static final fun getPos ()Lcom/chattriggers/ctjs/api/world/block/BlockPos; - public static final fun getRenderX ()D - public static final fun getRenderY ()D - public static final fun getRenderZ ()D - public static final fun getRotation ()Lnet/minecraft/util/math/Vec2f; - public static final fun getSaturation ()F - public static final fun getTeam ()Lcom/chattriggers/ctjs/api/entity/Team; - public static final fun getUUID ()Ljava/util/UUID; - public static final fun getX ()D - public static final fun getXPLevel ()I - public static final fun getXPProgress ()F - public static final fun getY ()D - public static final fun getYaw ()D - public static final fun getZ ()D - public static final fun isFlying ()Z - public static final fun isMoving ()Z - public static final fun isSleeping ()Z - public static final fun isSneaking ()Z - public static final fun isSprinting ()Z - public static final fun lookingAt ()Ljava/lang/Object; - public static final fun setHeldItemIndex (I)V - public static final fun setNametagName (Lcom/chattriggers/ctjs/api/message/TextComponent;)V - public static final fun setTabDisplayName (Lcom/chattriggers/ctjs/api/message/TextComponent;)V - public static final fun toMC ()Lnet/minecraft/client/network/ClientPlayerEntity; -} - -public final class com/chattriggers/ctjs/api/client/Player$ArmorWrapper { - public fun ()V - public final fun getBoots ()Lcom/chattriggers/ctjs/api/inventory/Item; - public final fun getChestplate ()Lcom/chattriggers/ctjs/api/inventory/Item; - public final fun getHelmet ()Lcom/chattriggers/ctjs/api/inventory/Item; - public final fun getLeggings ()Lcom/chattriggers/ctjs/api/inventory/Item; -} - -public final class com/chattriggers/ctjs/api/client/Settings { - public static final field INSTANCE Lcom/chattriggers/ctjs/api/client/Settings; - public static final field chat Lcom/chattriggers/ctjs/api/client/Settings$ChatWrapper; - public static final field skin Lcom/chattriggers/ctjs/api/client/Settings$SkinWrapper; - public static final field sound Lcom/chattriggers/ctjs/api/client/Settings$SoundWrapper; - public static final field video Lcom/chattriggers/ctjs/api/client/Settings$VideoWrapper; - public static final fun getDifficulty ()Lcom/chattriggers/ctjs/api/client/Settings$Difficulty; - public static final fun getFOV ()Ljava/lang/Integer; - public static final fun getSettings ()Lnet/minecraft/client/option/GameOptions; - public static final fun setFOV (I)V - public static final fun toMC ()Lnet/minecraft/client/option/GameOptions; -} - -public final class com/chattriggers/ctjs/api/client/Settings$ChatVisibility : java/lang/Enum, com/chattriggers/ctjs/api/CTWrapper { - public static final field Companion Lcom/chattriggers/ctjs/api/client/Settings$ChatVisibility$Companion; - public static final field FULL Lcom/chattriggers/ctjs/api/client/Settings$ChatVisibility; - public static final field HIDDEN Lcom/chattriggers/ctjs/api/client/Settings$ChatVisibility; - public static final field SYSTEM Lcom/chattriggers/ctjs/api/client/Settings$ChatVisibility; - public static final fun from (Ljava/lang/Object;)Lcom/chattriggers/ctjs/api/client/Settings$ChatVisibility; - public static final fun fromMC (Lnet/minecraft/network/message/ChatVisibility;)Lcom/chattriggers/ctjs/api/client/Settings$ChatVisibility; - public static fun getEntries ()Lkotlin/enums/EnumEntries; - public synthetic fun getMcValue ()Ljava/lang/Object; - public fun getMcValue ()Lnet/minecraft/network/message/ChatVisibility; - public synthetic fun toMC ()Ljava/lang/Object; - public fun toMC ()Lnet/minecraft/network/message/ChatVisibility; - public static fun valueOf (Ljava/lang/String;)Lcom/chattriggers/ctjs/api/client/Settings$ChatVisibility; - public static fun values ()[Lcom/chattriggers/ctjs/api/client/Settings$ChatVisibility; -} - -public final class com/chattriggers/ctjs/api/client/Settings$ChatVisibility$Companion { - public final fun from (Ljava/lang/Object;)Lcom/chattriggers/ctjs/api/client/Settings$ChatVisibility; - public final fun fromMC (Lnet/minecraft/network/message/ChatVisibility;)Lcom/chattriggers/ctjs/api/client/Settings$ChatVisibility; -} - -public final class com/chattriggers/ctjs/api/client/Settings$ChatWrapper { - public fun ()V - public final fun getColors ()Ljava/lang/Boolean; - public final fun getFocusedHeight ()Ljava/lang/Double; - public final fun getOpacity ()Ljava/lang/Double; - public final fun getPromptOnWebLinks ()Ljava/lang/Boolean; - public final fun getReducedDebugInfo ()Ljava/lang/Boolean; - public final fun getScale ()Ljava/lang/Double; - public final fun getUnfocusedHeight ()Ljava/lang/Double; - public final fun getVisibility ()Lcom/chattriggers/ctjs/api/client/Settings$ChatVisibility; - public final fun getWebLinks ()Ljava/lang/Boolean; - public final fun getWidth ()Ljava/lang/Double; - public final fun setColors (Z)V - public final fun setFocusedHeight (D)V - public final fun setOpacity (D)V - public final fun setPromptOnWebLinks (Z)V - public final fun setReducedDebugInfo (Z)V - public final fun setScale (D)V - public final fun setUnfocusedHeight (D)V - public final fun setVisibility (Lcom/chattriggers/ctjs/api/client/Settings$ChatVisibility;)V - public final fun setWebLinks (Z)V - public final fun setWidth (D)V -} - -public final class com/chattriggers/ctjs/api/client/Settings$CloudRenderMode : java/lang/Enum, com/chattriggers/ctjs/api/CTWrapper { - public static final field Companion Lcom/chattriggers/ctjs/api/client/Settings$CloudRenderMode$Companion; - public static final field FANCY Lcom/chattriggers/ctjs/api/client/Settings$CloudRenderMode; - public static final field FAST Lcom/chattriggers/ctjs/api/client/Settings$CloudRenderMode; - public static final field OFF Lcom/chattriggers/ctjs/api/client/Settings$CloudRenderMode; - public static final fun from (Ljava/lang/Object;)Lcom/chattriggers/ctjs/api/client/Settings$CloudRenderMode; - public static final fun fromMC (Lnet/minecraft/client/option/CloudRenderMode;)Lcom/chattriggers/ctjs/api/client/Settings$CloudRenderMode; - public static fun getEntries ()Lkotlin/enums/EnumEntries; - public synthetic fun getMcValue ()Ljava/lang/Object; - public fun getMcValue ()Lnet/minecraft/client/option/CloudRenderMode; - public synthetic fun toMC ()Ljava/lang/Object; - public fun toMC ()Lnet/minecraft/client/option/CloudRenderMode; - public static fun valueOf (Ljava/lang/String;)Lcom/chattriggers/ctjs/api/client/Settings$CloudRenderMode; - public static fun values ()[Lcom/chattriggers/ctjs/api/client/Settings$CloudRenderMode; -} - -public final class com/chattriggers/ctjs/api/client/Settings$CloudRenderMode$Companion { - public final fun from (Ljava/lang/Object;)Lcom/chattriggers/ctjs/api/client/Settings$CloudRenderMode; - public final fun fromMC (Lnet/minecraft/client/option/CloudRenderMode;)Lcom/chattriggers/ctjs/api/client/Settings$CloudRenderMode; -} - -public final class com/chattriggers/ctjs/api/client/Settings$Difficulty : java/lang/Enum, com/chattriggers/ctjs/api/CTWrapper { - public static final field Companion Lcom/chattriggers/ctjs/api/client/Settings$Difficulty$Companion; - public static final field EASY Lcom/chattriggers/ctjs/api/client/Settings$Difficulty; - public static final field HARD Lcom/chattriggers/ctjs/api/client/Settings$Difficulty; - public static final field NORMAL Lcom/chattriggers/ctjs/api/client/Settings$Difficulty; - public static final field PEACEFUL Lcom/chattriggers/ctjs/api/client/Settings$Difficulty; - public static final fun fromMC (Lnet/minecraft/world/Difficulty;)Lcom/chattriggers/ctjs/api/client/Settings$Difficulty; - public static fun getEntries ()Lkotlin/enums/EnumEntries; - public synthetic fun getMcValue ()Ljava/lang/Object; - public fun getMcValue ()Lnet/minecraft/world/Difficulty; - public synthetic fun toMC ()Ljava/lang/Object; - public fun toMC ()Lnet/minecraft/world/Difficulty; - public static fun valueOf (Ljava/lang/String;)Lcom/chattriggers/ctjs/api/client/Settings$Difficulty; - public static fun values ()[Lcom/chattriggers/ctjs/api/client/Settings$Difficulty; -} - -public final class com/chattriggers/ctjs/api/client/Settings$Difficulty$Companion { - public final fun fromMC (Lnet/minecraft/world/Difficulty;)Lcom/chattriggers/ctjs/api/client/Settings$Difficulty; -} - -public final class com/chattriggers/ctjs/api/client/Settings$GraphicsMode : java/lang/Enum, com/chattriggers/ctjs/api/CTWrapper { - public static final field Companion Lcom/chattriggers/ctjs/api/client/Settings$GraphicsMode$Companion; - public static final field FABULOUS Lcom/chattriggers/ctjs/api/client/Settings$GraphicsMode; - public static final field FANCY Lcom/chattriggers/ctjs/api/client/Settings$GraphicsMode; - public static final field FAST Lcom/chattriggers/ctjs/api/client/Settings$GraphicsMode; - public static final fun fromMC (Lnet/minecraft/client/option/GraphicsMode;)Lcom/chattriggers/ctjs/api/client/Settings$GraphicsMode; - public static fun getEntries ()Lkotlin/enums/EnumEntries; - public synthetic fun getMcValue ()Ljava/lang/Object; - public fun getMcValue ()Lnet/minecraft/client/option/GraphicsMode; - public synthetic fun toMC ()Ljava/lang/Object; - public fun toMC ()Lnet/minecraft/client/option/GraphicsMode; - public static fun valueOf (Ljava/lang/String;)Lcom/chattriggers/ctjs/api/client/Settings$GraphicsMode; - public static fun values ()[Lcom/chattriggers/ctjs/api/client/Settings$GraphicsMode; -} - -public final class com/chattriggers/ctjs/api/client/Settings$GraphicsMode$Companion { - public final fun fromMC (Lnet/minecraft/client/option/GraphicsMode;)Lcom/chattriggers/ctjs/api/client/Settings$GraphicsMode; -} - -public final class com/chattriggers/ctjs/api/client/Settings$ParticlesMode : java/lang/Enum, com/chattriggers/ctjs/api/CTWrapper { - public static final field ALL Lcom/chattriggers/ctjs/api/client/Settings$ParticlesMode; - public static final field Companion Lcom/chattriggers/ctjs/api/client/Settings$ParticlesMode$Companion; - public static final field DECREASED Lcom/chattriggers/ctjs/api/client/Settings$ParticlesMode; - public static final field MINIMAL Lcom/chattriggers/ctjs/api/client/Settings$ParticlesMode; - public static final fun from (Ljava/lang/Object;)Lcom/chattriggers/ctjs/api/client/Settings$ParticlesMode; - public static final fun fromMC (Lnet/minecraft/client/option/ParticlesMode;)Lcom/chattriggers/ctjs/api/client/Settings$ParticlesMode; - public static fun getEntries ()Lkotlin/enums/EnumEntries; - public synthetic fun getMcValue ()Ljava/lang/Object; - public fun getMcValue ()Lnet/minecraft/client/option/ParticlesMode; - public synthetic fun toMC ()Ljava/lang/Object; - public fun toMC ()Lnet/minecraft/client/option/ParticlesMode; - public static fun valueOf (Ljava/lang/String;)Lcom/chattriggers/ctjs/api/client/Settings$ParticlesMode; - public static fun values ()[Lcom/chattriggers/ctjs/api/client/Settings$ParticlesMode; -} - -public final class com/chattriggers/ctjs/api/client/Settings$ParticlesMode$Companion { - public final fun from (Ljava/lang/Object;)Lcom/chattriggers/ctjs/api/client/Settings$ParticlesMode; - public final fun fromMC (Lnet/minecraft/client/option/ParticlesMode;)Lcom/chattriggers/ctjs/api/client/Settings$ParticlesMode; -} - -public final class com/chattriggers/ctjs/api/client/Settings$SkinWrapper { - public fun ()V - public final fun isCapeEnabled ()Z - public final fun isHatEnabled ()Z - public final fun isJacketEnabled ()Z - public final fun isLeftPantsLegEnabled ()Z - public final fun isLeftSleeveEnabled ()Z - public final fun isRightPantsLegEnabled ()Z - public final fun isRightSleeveEnabled ()Z - public final fun setCapeEnabled (Z)V - public final fun setHatEnabled (Z)V - public final fun setJacketEnabled (Z)V - public final fun setLeftPantsLegEnabled (Z)V - public final fun setLeftSleeveEnabled (Z)V - public final fun setRightPantsLegEnabled (Z)V - public final fun setRightSleeveEnabled (Z)V -} - -public final class com/chattriggers/ctjs/api/client/Settings$SoundWrapper { - public fun ()V - public final fun getAmbient ()Ljava/lang/Double; - public final fun getBlocks ()Ljava/lang/Double; - public final fun getFriendlyCreatures ()Ljava/lang/Double; - public final fun getHostileCreatures ()Ljava/lang/Double; - public final fun getMasterVolume ()Ljava/lang/Double; - public final fun getMusicVolume ()Ljava/lang/Double; - public final fun getNoteblockVolume ()Ljava/lang/Double; - public final fun getPlayers ()Ljava/lang/Double; - public final fun getWeather ()Ljava/lang/Double; - public final fun setAmbient (D)V - public final fun setBlocks (D)V - public final fun setFriendlyCreatures (D)V - public final fun setHostileCreatures (D)V - public final fun setMasterVolume (D)V - public final fun setMusicVolume (D)V - public final fun setNoteblockVolume (D)V - public final fun setPlayers (D)V - public final fun setWeather (D)V -} - -public final class com/chattriggers/ctjs/api/client/Settings$VideoWrapper { - public fun ()V - public final fun getBobbing ()Ljava/lang/Boolean; - public final fun getBrightness ()Ljava/lang/Double; - public final fun getClouds ()Lcom/chattriggers/ctjs/api/client/Settings$CloudRenderMode; - public final fun getEntityShadows ()Ljava/lang/Boolean; - public final fun getFullscreen ()Ljava/lang/Boolean; - public final fun getGraphicsMode ()Lcom/chattriggers/ctjs/api/client/Settings$GraphicsMode; - public final fun getGuiScale ()Ljava/lang/Integer; - public final fun getMaxFrameRate ()Ljava/lang/Integer; - public final fun getMipmapLevels ()Ljava/lang/Integer; - public final fun getParticles ()Lcom/chattriggers/ctjs/api/client/Settings$ParticlesMode; - public final fun getRenderDistance ()Ljava/lang/Integer; - public final fun getSmoothLighting ()Ljava/lang/Boolean; - public final fun getVsync ()Ljava/lang/Boolean; - public final fun setBobbing (Z)V - public final fun setBrightness (D)V - public final fun setClouds (Lcom/chattriggers/ctjs/api/client/Settings$CloudRenderMode;)V - public final fun setEntityShadows (Z)V - public final fun setFullscreen (Z)V - public final fun setGraphicsMode (Lcom/chattriggers/ctjs/api/client/Settings$GraphicsMode;)V - public final fun setGuiScale (I)V - public final fun setMaxFrameRate (I)V - public final fun setMipmapLevels (I)V - public final fun setParticles (Lcom/chattriggers/ctjs/api/client/Settings$ParticlesMode;)V - public final fun setRenderDistance (I)V - public final fun setSmoothLighting (Z)V - public final fun setVsync (Z)V -} - -public final class com/chattriggers/ctjs/api/client/Sound { - public fun (Lorg/mozilla/javascript/NativeObject;)V - public final fun destroy ()V - public final fun getAttenuation ()I - public final fun getAttenuationType ()Lcom/chattriggers/ctjs/api/client/Sound$AttenuationType; - public final fun getCategory ()Lcom/chattriggers/ctjs/api/client/Sound$Category; - public final fun getLoop ()Z - public final fun getLoopDelay ()I - public final fun getPitch ()F - public final fun getPosition ()Lnet/minecraft/util/math/Vec3d; - public final fun getVolume ()F - public final fun getX ()D - public final fun getY ()D - public final fun getZ ()D - public final fun pause ()V - public final fun play ()V - public final fun play (I)V - public static synthetic fun play$default (Lcom/chattriggers/ctjs/api/client/Sound;IILjava/lang/Object;)V - public final fun rewind ()V - public final fun setAttenuation (I)Lcom/chattriggers/ctjs/api/client/Sound; - public final fun setAttenuationType (Lcom/chattriggers/ctjs/api/client/Sound$AttenuationType;)Lcom/chattriggers/ctjs/api/client/Sound; - public final fun setCategory (Lcom/chattriggers/ctjs/api/client/Sound$Category;)Lcom/chattriggers/ctjs/api/client/Sound; - public final fun setLoop (Z)Lcom/chattriggers/ctjs/api/client/Sound; - public final fun setLoopDelay (I)Lcom/chattriggers/ctjs/api/client/Sound; - public final fun setPitch (F)Lcom/chattriggers/ctjs/api/client/Sound; - public final fun setPosition (DDD)Lcom/chattriggers/ctjs/api/client/Sound; - public final fun setVolume (F)Lcom/chattriggers/ctjs/api/client/Sound; - public final fun setX (D)Lcom/chattriggers/ctjs/api/client/Sound; - public final fun setY (D)Lcom/chattriggers/ctjs/api/client/Sound; - public final fun setZ (D)Lcom/chattriggers/ctjs/api/client/Sound; - public final fun stop ()V -} - -public final class com/chattriggers/ctjs/api/client/Sound$AttenuationType : java/lang/Enum, com/chattriggers/ctjs/api/CTWrapper { - public static final field Companion Lcom/chattriggers/ctjs/api/client/Sound$AttenuationType$Companion; - public static final field LINEAR Lcom/chattriggers/ctjs/api/client/Sound$AttenuationType; - public static final field NONE Lcom/chattriggers/ctjs/api/client/Sound$AttenuationType; - public static final fun from (Ljava/lang/Object;)Lcom/chattriggers/ctjs/api/client/Sound$AttenuationType; - public static final fun fromMC (Lnet/minecraft/client/sound/SoundInstance$AttenuationType;)Lcom/chattriggers/ctjs/api/client/Sound$AttenuationType; - public static fun getEntries ()Lkotlin/enums/EnumEntries; - public synthetic fun getMcValue ()Ljava/lang/Object; - public fun getMcValue ()Lnet/minecraft/client/sound/SoundInstance$AttenuationType; - public synthetic fun toMC ()Ljava/lang/Object; - public fun toMC ()Lnet/minecraft/client/sound/SoundInstance$AttenuationType; - public static fun valueOf (Ljava/lang/String;)Lcom/chattriggers/ctjs/api/client/Sound$AttenuationType; - public static fun values ()[Lcom/chattriggers/ctjs/api/client/Sound$AttenuationType; -} - -public final class com/chattriggers/ctjs/api/client/Sound$AttenuationType$Companion { - public final fun from (Ljava/lang/Object;)Lcom/chattriggers/ctjs/api/client/Sound$AttenuationType; - public final fun fromMC (Lnet/minecraft/client/sound/SoundInstance$AttenuationType;)Lcom/chattriggers/ctjs/api/client/Sound$AttenuationType; -} - -public final class com/chattriggers/ctjs/api/client/Sound$Category : java/lang/Enum, com/chattriggers/ctjs/api/CTWrapper { - public static final field AMBIENT Lcom/chattriggers/ctjs/api/client/Sound$Category; - public static final field BLOCKS Lcom/chattriggers/ctjs/api/client/Sound$Category; - public static final field Companion Lcom/chattriggers/ctjs/api/client/Sound$Category$Companion; - public static final field HOSTILE Lcom/chattriggers/ctjs/api/client/Sound$Category; - public static final field MASTER Lcom/chattriggers/ctjs/api/client/Sound$Category; - public static final field MUSIC Lcom/chattriggers/ctjs/api/client/Sound$Category; - public static final field NEUTRAL Lcom/chattriggers/ctjs/api/client/Sound$Category; - public static final field PLAYERS Lcom/chattriggers/ctjs/api/client/Sound$Category; - public static final field RECORDS Lcom/chattriggers/ctjs/api/client/Sound$Category; - public static final field VOICE Lcom/chattriggers/ctjs/api/client/Sound$Category; - public static final field WEATHER Lcom/chattriggers/ctjs/api/client/Sound$Category; - public static final fun from (Ljava/lang/Object;)Lcom/chattriggers/ctjs/api/client/Sound$Category; - public static final fun fromMC (Lnet/minecraft/sound/SoundCategory;)Lcom/chattriggers/ctjs/api/client/Sound$Category; - public static fun getEntries ()Lkotlin/enums/EnumEntries; - public synthetic fun getMcValue ()Ljava/lang/Object; - public fun getMcValue ()Lnet/minecraft/sound/SoundCategory; - public synthetic fun toMC ()Ljava/lang/Object; - public fun toMC ()Lnet/minecraft/sound/SoundCategory; - public static fun valueOf (Ljava/lang/String;)Lcom/chattriggers/ctjs/api/client/Sound$Category; - public static fun values ()[Lcom/chattriggers/ctjs/api/client/Sound$Category; -} - -public final class com/chattriggers/ctjs/api/client/Sound$Category$Companion { - public final fun from (Ljava/lang/Object;)Lcom/chattriggers/ctjs/api/client/Sound$Category; - public final fun fromMC (Lnet/minecraft/sound/SoundCategory;)Lcom/chattriggers/ctjs/api/client/Sound$Category; -} - -public final class com/chattriggers/ctjs/api/commands/DynamicCommands : com/chattriggers/ctjs/internal/commands/CommandCollection { - public static final field INSTANCE Lcom/chattriggers/ctjs/api/commands/DynamicCommands; - public static final fun angle ()Lcom/mojang/brigadier/arguments/ArgumentType; - public static final fun argument (Ljava/lang/String;Lcom/mojang/brigadier/arguments/ArgumentType;Lorg/mozilla/javascript/Function;)V - public static final fun blockPos ()Lcom/mojang/brigadier/arguments/ArgumentType; - public static final fun blockPredicate ()Lcom/mojang/brigadier/arguments/ArgumentType; - public static final fun blockState ()Lcom/mojang/brigadier/arguments/ArgumentType; - public static final fun bool ()Lcom/mojang/brigadier/arguments/BoolArgumentType; - public static final fun buildCommand (Ljava/lang/String;)Lcom/chattriggers/ctjs/api/commands/RootCommand; - public static final fun buildCommand (Ljava/lang/String;Lorg/mozilla/javascript/Function;)Lcom/chattriggers/ctjs/api/commands/RootCommand; - public static synthetic fun buildCommand$default (Ljava/lang/String;Lorg/mozilla/javascript/Function;ILjava/lang/Object;)Lcom/chattriggers/ctjs/api/commands/RootCommand; - public static final fun choices ([Ljava/lang/String;)Lcom/mojang/brigadier/arguments/ArgumentType; - public static final fun color ()Lnet/minecraft/command/argument/ColorArgumentType; - public static final fun columnPos ()Lcom/mojang/brigadier/arguments/ArgumentType; - public static final fun custom (Lorg/mozilla/javascript/NativeObject;)Lcom/mojang/brigadier/arguments/ArgumentType; - public static final fun dimension ()Lcom/mojang/brigadier/arguments/ArgumentType; - public static final fun double ()Lcom/mojang/brigadier/arguments/DoubleArgumentType; - public static final fun double (D)Lcom/mojang/brigadier/arguments/DoubleArgumentType; - public static final fun double (DD)Lcom/mojang/brigadier/arguments/DoubleArgumentType; - public static synthetic fun double$default (DDILjava/lang/Object;)Lcom/mojang/brigadier/arguments/DoubleArgumentType; - public static final fun entities ()Lcom/mojang/brigadier/arguments/ArgumentType; - public static final fun entity ()Lcom/mojang/brigadier/arguments/ArgumentType; - public static final fun error (Lcom/mojang/brigadier/ImmutableStringReader;Lcom/chattriggers/ctjs/api/message/TextComponent;)Ljava/lang/Void; - public static final fun error (Lcom/mojang/brigadier/ImmutableStringReader;Ljava/lang/String;)Ljava/lang/Void; - public static final fun exec (Lorg/mozilla/javascript/Function;)V - public static final fun float ()Lcom/mojang/brigadier/arguments/FloatArgumentType; - public static final fun float (F)Lcom/mojang/brigadier/arguments/FloatArgumentType; - public static final fun float (FF)Lcom/mojang/brigadier/arguments/FloatArgumentType; - public static synthetic fun float$default (FFILjava/lang/Object;)Lcom/mojang/brigadier/arguments/FloatArgumentType; - public static final fun floatRange ()Lnet/minecraft/command/argument/NumberRangeArgumentType$FloatRangeArgumentType; - public static final fun gameMode ()Lnet/minecraft/command/argument/GameModeArgumentType; - public static final fun gameProfile ()Lcom/mojang/brigadier/arguments/ArgumentType; - public static final fun getDispatcherRoot ()Lcom/mojang/brigadier/tree/RootCommandNode; - public static final fun greedyString ()Lcom/mojang/brigadier/arguments/StringArgumentType; - public static final fun intRange ()Lnet/minecraft/command/argument/NumberRangeArgumentType$IntRangeArgumentType; - public static final fun integer ()Lcom/mojang/brigadier/arguments/IntegerArgumentType; - public static final fun integer (I)Lcom/mojang/brigadier/arguments/IntegerArgumentType; - public static final fun integer (II)Lcom/mojang/brigadier/arguments/IntegerArgumentType; - public static synthetic fun integer$default (IIILjava/lang/Object;)Lcom/mojang/brigadier/arguments/IntegerArgumentType; - public static final fun itemPredicate ()Lcom/mojang/brigadier/arguments/ArgumentType; - public static final fun itemSlot ()Lnet/minecraft/command/argument/ItemSlotArgumentType; - public static final fun itemStack ()Lcom/mojang/brigadier/arguments/ArgumentType; - public static final fun literal (Ljava/lang/String;Lorg/mozilla/javascript/Function;)V - public static final fun long ()Lcom/mojang/brigadier/arguments/LongArgumentType; - public static final fun long (J)Lcom/mojang/brigadier/arguments/LongArgumentType; - public static final fun long (JJ)Lcom/mojang/brigadier/arguments/LongArgumentType; - public static synthetic fun long$default (JJILjava/lang/Object;)Lcom/mojang/brigadier/arguments/LongArgumentType; - public static final fun message ()Lcom/mojang/brigadier/arguments/ArgumentType; - public static final fun nbtCompoundTag ()Lcom/mojang/brigadier/arguments/ArgumentType; - public static final fun nbtPath ()Lcom/mojang/brigadier/arguments/ArgumentType; - public static final fun nbtTag ()Lcom/mojang/brigadier/arguments/ArgumentType; - public static final fun player ()Lcom/mojang/brigadier/arguments/ArgumentType; - public static final fun players ()Lcom/mojang/brigadier/arguments/ArgumentType; - public static final fun redirect (Lcom/chattriggers/ctjs/api/commands/RootCommand;)V - public static final fun redirect (Lcom/mojang/brigadier/tree/CommandNode;)V - public static final fun registerCommand (Ljava/lang/String;)Lcom/chattriggers/ctjs/api/commands/RootCommand; - public static final fun registerCommand (Ljava/lang/String;Lorg/mozilla/javascript/Function;)Lcom/chattriggers/ctjs/api/commands/RootCommand; - public static synthetic fun registerCommand$default (Ljava/lang/String;Lorg/mozilla/javascript/Function;ILjava/lang/Object;)Lcom/chattriggers/ctjs/api/commands/RootCommand; - public static final fun resource ()Lnet/minecraft/command/argument/IdentifierArgumentType; - public static final fun rotation ()Lcom/mojang/brigadier/arguments/ArgumentType; - public static final fun string ()Lcom/mojang/brigadier/arguments/StringArgumentType; - public static final fun swizzle ()Lcom/mojang/brigadier/arguments/ArgumentType; - public static final fun time ()Lnet/minecraft/command/argument/TimeArgumentType; - public static final fun time (I)Lnet/minecraft/command/argument/TimeArgumentType; - public static synthetic fun time$default (IILjava/lang/Object;)Lnet/minecraft/command/argument/TimeArgumentType; - public static final fun uuid ()Lnet/minecraft/command/argument/UuidArgumentType; - public static final fun vec2 ()Lcom/mojang/brigadier/arguments/ArgumentType; - public static final fun vec2 (Z)Lcom/mojang/brigadier/arguments/ArgumentType; - public static synthetic fun vec2$default (ZILjava/lang/Object;)Lcom/mojang/brigadier/arguments/ArgumentType; - public static final fun vec3 ()Lcom/mojang/brigadier/arguments/ArgumentType; - public static final fun vec3 (Z)Lcom/mojang/brigadier/arguments/ArgumentType; - public static synthetic fun vec3$default (ZILjava/lang/Object;)Lcom/mojang/brigadier/arguments/ArgumentType; - public static final fun word ()Lcom/mojang/brigadier/arguments/StringArgumentType; -} - -public final class com/chattriggers/ctjs/api/commands/DynamicCommands$AngleArgumentWrapper { - public fun (Lnet/minecraft/command/argument/AngleArgumentType$Angle;)V - public final fun component1 ()Lnet/minecraft/command/argument/AngleArgumentType$Angle; - public final fun copy (Lnet/minecraft/command/argument/AngleArgumentType$Angle;)Lcom/chattriggers/ctjs/api/commands/DynamicCommands$AngleArgumentWrapper; - public static synthetic fun copy$default (Lcom/chattriggers/ctjs/api/commands/DynamicCommands$AngleArgumentWrapper;Lnet/minecraft/command/argument/AngleArgumentType$Angle;ILjava/lang/Object;)Lcom/chattriggers/ctjs/api/commands/DynamicCommands$AngleArgumentWrapper; - public fun equals (Ljava/lang/Object;)Z - public final fun getAngle ()F - public final fun getAngle ()Lnet/minecraft/command/argument/AngleArgumentType$Angle; - public final fun getAngle (Lcom/chattriggers/ctjs/api/entity/Entity;)F - public static synthetic fun getAngle$default (Lcom/chattriggers/ctjs/api/commands/DynamicCommands$AngleArgumentWrapper;Lcom/chattriggers/ctjs/api/entity/Entity;ILjava/lang/Object;)F - public fun hashCode ()I - public fun toString ()Ljava/lang/String; -} - -public final class com/chattriggers/ctjs/api/commands/DynamicCommands$BlockPredicateWrapper { - public fun (Lnet/minecraft/command/argument/BlockPredicateArgumentType$BlockPredicate;)V - public final fun component1 ()Lnet/minecraft/command/argument/BlockPredicateArgumentType$BlockPredicate; - public final fun copy (Lnet/minecraft/command/argument/BlockPredicateArgumentType$BlockPredicate;)Lcom/chattriggers/ctjs/api/commands/DynamicCommands$BlockPredicateWrapper; - public static synthetic fun copy$default (Lcom/chattriggers/ctjs/api/commands/DynamicCommands$BlockPredicateWrapper;Lnet/minecraft/command/argument/BlockPredicateArgumentType$BlockPredicate;ILjava/lang/Object;)Lcom/chattriggers/ctjs/api/commands/DynamicCommands$BlockPredicateWrapper; - public fun equals (Ljava/lang/Object;)Z - public final fun getImpl ()Lnet/minecraft/command/argument/BlockPredicateArgumentType$BlockPredicate; - public fun hashCode ()I - public final fun test (Lcom/chattriggers/ctjs/api/world/block/BlockPos;)Z - public fun toString ()Ljava/lang/String; -} - -public final class com/chattriggers/ctjs/api/commands/DynamicCommands$BlockStateArgumentWrapper { - public fun (Lnet/minecraft/command/argument/BlockStateArgument;)V - public final fun component1 ()Lnet/minecraft/command/argument/BlockStateArgument; - public final fun copy (Lnet/minecraft/command/argument/BlockStateArgument;)Lcom/chattriggers/ctjs/api/commands/DynamicCommands$BlockStateArgumentWrapper; - public static synthetic fun copy$default (Lcom/chattriggers/ctjs/api/commands/DynamicCommands$BlockStateArgumentWrapper;Lnet/minecraft/command/argument/BlockStateArgument;ILjava/lang/Object;)Lcom/chattriggers/ctjs/api/commands/DynamicCommands$BlockStateArgumentWrapper; - public fun equals (Ljava/lang/Object;)Z - public final fun getImpl ()Lnet/minecraft/command/argument/BlockStateArgument; - public fun hashCode ()I - public final fun test (Lcom/chattriggers/ctjs/api/world/block/BlockPos;)Z - public fun toString ()Ljava/lang/String; -} - -public final class com/chattriggers/ctjs/api/commands/DynamicCommands$EntitySelectorWrapper { - public fun (Lnet/minecraft/command/EntitySelector;)V - public final fun getEntities ()Ljava/util/List; - public final fun getEntity ()Lcom/chattriggers/ctjs/api/entity/Entity; - public final fun getPlayers ()Ljava/util/List; -} - -public final class com/chattriggers/ctjs/api/commands/DynamicCommands$ItemStackArgumentWrapper : java/util/function/Predicate { - public fun (Lnet/minecraft/command/argument/ItemStackArgument;)V - public final fun copy (Lnet/minecraft/command/argument/ItemStackArgument;)Lcom/chattriggers/ctjs/api/commands/DynamicCommands$ItemStackArgumentWrapper; - public static synthetic fun copy$default (Lcom/chattriggers/ctjs/api/commands/DynamicCommands$ItemStackArgumentWrapper;Lnet/minecraft/command/argument/ItemStackArgument;ILjava/lang/Object;)Lcom/chattriggers/ctjs/api/commands/DynamicCommands$ItemStackArgumentWrapper; - public fun equals (Ljava/lang/Object;)Z - public final fun getItemType ()Lcom/chattriggers/ctjs/api/inventory/ItemType; - public fun hashCode ()I - public fun test (Lcom/chattriggers/ctjs/api/inventory/Item;)Z - public final fun test (Lcom/chattriggers/ctjs/api/inventory/ItemType;)Z - public synthetic fun test (Ljava/lang/Object;)Z - public fun toString ()Ljava/lang/String; -} - -public final class com/chattriggers/ctjs/api/commands/DynamicCommands$MessageFormatArgumentWrapper { - public fun (Lnet/minecraft/command/argument/MessageArgumentType$MessageFormat;)V - public final fun copy (Lnet/minecraft/command/argument/MessageArgumentType$MessageFormat;)Lcom/chattriggers/ctjs/api/commands/DynamicCommands$MessageFormatArgumentWrapper; - public static synthetic fun copy$default (Lcom/chattriggers/ctjs/api/commands/DynamicCommands$MessageFormatArgumentWrapper;Lnet/minecraft/command/argument/MessageArgumentType$MessageFormat;ILjava/lang/Object;)Lcom/chattriggers/ctjs/api/commands/DynamicCommands$MessageFormatArgumentWrapper; - public fun equals (Ljava/lang/Object;)Z - public final fun format ()Lcom/chattriggers/ctjs/api/message/TextComponent; - public final fun getText ()Ljava/lang/String; - public fun hashCode ()I - public final fun setText (Ljava/lang/String;)V - public fun toString ()Ljava/lang/String; -} - -public final class com/chattriggers/ctjs/api/commands/DynamicCommands$NbtPathWrapper { - public fun (Lnet/minecraft/command/argument/NbtPathArgumentType$NbtPath;)V - public final fun copy (Lnet/minecraft/command/argument/NbtPathArgumentType$NbtPath;)Lcom/chattriggers/ctjs/api/commands/DynamicCommands$NbtPathWrapper; - public static synthetic fun copy$default (Lcom/chattriggers/ctjs/api/commands/DynamicCommands$NbtPathWrapper;Lnet/minecraft/command/argument/NbtPathArgumentType$NbtPath;ILjava/lang/Object;)Lcom/chattriggers/ctjs/api/commands/DynamicCommands$NbtPathWrapper; - public final fun count (Lcom/chattriggers/ctjs/api/inventory/nbt/NBTBase;)I - public fun equals (Ljava/lang/Object;)Z - public final fun get (Lcom/chattriggers/ctjs/api/inventory/nbt/NBTBase;)Ljava/util/List; - public final fun getOrInit (Lcom/chattriggers/ctjs/api/inventory/nbt/NBTBase;Lkotlin/jvm/functions/Function0;)Ljava/util/List; - public fun hashCode ()I - public final fun insert (ILcom/chattriggers/ctjs/api/inventory/nbt/NBTTagCompound;Ljava/util/List;)I - public final fun put (Lcom/chattriggers/ctjs/api/inventory/nbt/NBTBase;Lcom/chattriggers/ctjs/api/inventory/nbt/NBTBase;)I - public final fun remove (Lcom/chattriggers/ctjs/api/inventory/nbt/NBTBase;)I - public fun toString ()Ljava/lang/String; -} - -public final class com/chattriggers/ctjs/api/commands/DynamicCommands$PosArgumentWrapper : net/minecraft/command/argument/PosArgument { - public fun (Lnet/minecraft/command/argument/PosArgument;)V - public final fun component1 ()Lnet/minecraft/command/argument/PosArgument; - public final fun copy (Lnet/minecraft/command/argument/PosArgument;)Lcom/chattriggers/ctjs/api/commands/DynamicCommands$PosArgumentWrapper; - public static synthetic fun copy$default (Lcom/chattriggers/ctjs/api/commands/DynamicCommands$PosArgumentWrapper;Lnet/minecraft/command/argument/PosArgument;ILjava/lang/Object;)Lcom/chattriggers/ctjs/api/commands/DynamicCommands$PosArgumentWrapper; - public fun equals (Ljava/lang/Object;)Z - public final fun getImpl ()Lnet/minecraft/command/argument/PosArgument; - public fun hashCode ()I - public fun isXRelative ()Z - public fun isYRelative ()Z - public fun isZRelative ()Z - public final fun toAbsoluteBlockPos ()Lcom/chattriggers/ctjs/api/world/block/BlockPos; - public final fun toAbsolutePos ()Lnet/minecraft/util/math/Vec3d; - public fun toAbsolutePos (Lnet/minecraft/server/command/ServerCommandSource;)Lnet/minecraft/util/math/Vec3d; - public final fun toAbsoluteRotation ()Lnet/minecraft/util/math/Vec2f; - public fun toAbsoluteRotation (Lnet/minecraft/server/command/ServerCommandSource;)Lnet/minecraft/util/math/Vec2f; - public fun toString ()Ljava/lang/String; -} - -public abstract interface class com/chattriggers/ctjs/api/commands/RootCommand { - public abstract fun register ()V -} - -public final class com/chattriggers/ctjs/api/entity/BlockEntity : com/chattriggers/ctjs/api/CTWrapper { - public fun (Lnet/minecraft/block/entity/BlockEntity;)V - public final fun getBlock ()Lcom/chattriggers/ctjs/api/world/block/Block; - public final fun getBlockPos ()Lcom/chattriggers/ctjs/api/world/block/BlockPos; - public final fun getBlockType ()Lcom/chattriggers/ctjs/api/world/block/BlockType; - public synthetic fun getMcValue ()Ljava/lang/Object; - public fun getMcValue ()Lnet/minecraft/block/entity/BlockEntity; - public final fun getX ()I - public final fun getY ()I - public final fun getZ ()I - public synthetic fun toMC ()Ljava/lang/Object; - public fun toMC ()Lnet/minecraft/block/entity/BlockEntity; - public fun toString ()Ljava/lang/String; -} - -public class com/chattriggers/ctjs/api/entity/Entity : com/chattriggers/ctjs/api/CTWrapper { - public static final field Companion Lcom/chattriggers/ctjs/api/entity/Entity$Companion; - public fun (Lnet/minecraft/entity/Entity;)V - public final fun canBeCollidedWith ()Z - public final fun canBePushed ()Z - public final fun distanceTo (DDD)D - public final fun distanceTo (Lcom/chattriggers/ctjs/api/entity/Entity;)F - public final fun distanceTo (Lcom/chattriggers/ctjs/api/world/block/BlockPos;)D - public final fun distanceTo (Lnet/minecraft/entity/Entity;)F - public static final fun fromMC (Lnet/minecraft/entity/Entity;)Lcom/chattriggers/ctjs/api/entity/Entity; - public final fun getAir ()I - public final fun getChunk ()Lcom/chattriggers/ctjs/api/world/Chunk; - public final fun getClassName ()Ljava/lang/String; - public final fun getDimension ()Lcom/chattriggers/ctjs/api/entity/Entity$DimensionType; - public final fun getDistanceWalked ()F - public final fun getEyeHeight ()F - public final fun getEyePosition ()Lnet/minecraft/util/math/Vec3d; - public final fun getEyePosition (F)Lnet/minecraft/util/math/Vec3d; - public static synthetic fun getEyePosition$default (Lcom/chattriggers/ctjs/api/entity/Entity;FILjava/lang/Object;)Lnet/minecraft/util/math/Vec3d; - public final fun getFireResistance ()I - public final fun getHeight ()F - public final fun getLastX ()D - public final fun getLastY ()D - public final fun getLastZ ()D - public final fun getLookVector ()Lnet/minecraft/util/math/Vec3d; - public final fun getLookVector (F)Lnet/minecraft/util/math/Vec3d; - public static synthetic fun getLookVector$default (Lcom/chattriggers/ctjs/api/entity/Entity;FILjava/lang/Object;)Lnet/minecraft/util/math/Vec3d; - public final fun getMaxInPortalTime ()I - public synthetic fun getMcValue ()Ljava/lang/Object; - public fun getMcValue ()Lnet/minecraft/entity/Entity; - public final fun getMotionX ()D - public final fun getMotionY ()D - public final fun getMotionZ ()D - public final fun getName ()Ljava/lang/String; - public final fun getNameComponent ()Lcom/chattriggers/ctjs/api/message/TextComponent; - public final fun getPitch ()F - public final fun getPos ()Lcom/chattriggers/ctjs/api/world/block/BlockPos; - public final fun getRenderX ()D - public final fun getRenderY ()D - public final fun getRenderZ ()D - public final fun getRiders ()Ljava/util/List; - public final fun getRiding ()Lcom/chattriggers/ctjs/api/entity/Entity; - public final fun getRotation ()Lnet/minecraft/util/math/Vec2f; - public final fun getStepHeight ()F - public final fun getTicksExisted ()I - public final fun getUUID ()Ljava/util/UUID; - public final fun getWidth ()F - public final fun getWorld ()Lnet/minecraft/world/World; - public final fun getX ()D - public final fun getY ()D - public final fun getYaw ()F - public final fun getZ ()D - public final fun hasNoClip ()Z - public final fun isBurning ()Z - public final fun isCollided ()Z - public final fun isDead ()Z - public final fun isImmuneToFire ()Z - public final fun isInLava ()Z - public final fun isInWater ()Z - public final fun isInvisible ()Z - public final fun isOnGround ()Z - public final fun isOutsideBorder ()Z - public final fun isSilent ()Z - public final fun isSneaking ()Z - public final fun isSprinting ()Z - public final fun isWet ()Z - public synthetic fun toMC ()Ljava/lang/Object; - public fun toMC ()Lnet/minecraft/entity/Entity; - public fun toString ()Ljava/lang/String; -} - -public final class com/chattriggers/ctjs/api/entity/Entity$Companion { - public final fun fromMC (Lnet/minecraft/entity/Entity;)Lcom/chattriggers/ctjs/api/entity/Entity; -} - -public final class com/chattriggers/ctjs/api/entity/Entity$DimensionType : java/lang/Enum, com/chattriggers/ctjs/api/CTWrapper { - public static final field END Lcom/chattriggers/ctjs/api/entity/Entity$DimensionType; - public static final field NETHER Lcom/chattriggers/ctjs/api/entity/Entity$DimensionType; - public static final field OVERWORLD Lcom/chattriggers/ctjs/api/entity/Entity$DimensionType; - public static final field OVERWORLD_CAVES Lcom/chattriggers/ctjs/api/entity/Entity$DimensionType; - public static fun getEntries ()Lkotlin/enums/EnumEntries; - public synthetic fun getMcValue ()Ljava/lang/Object; - public fun getMcValue ()Lnet/minecraft/registry/RegistryKey; - public synthetic fun toMC ()Ljava/lang/Object; - public fun toMC ()Lnet/minecraft/registry/RegistryKey; - public static fun valueOf (Ljava/lang/String;)Lcom/chattriggers/ctjs/api/entity/Entity$DimensionType; - public static fun values ()[Lcom/chattriggers/ctjs/api/entity/Entity$DimensionType; -} - -public class com/chattriggers/ctjs/api/entity/LivingEntity : com/chattriggers/ctjs/api/entity/Entity { - public fun (Lnet/minecraft/entity/LivingEntity;)V - public final fun canSeeEntity (Lcom/chattriggers/ctjs/api/entity/Entity;)Z - public final fun canSeeEntity (Lnet/minecraft/entity/Entity;)Z - public final fun getAbsorption ()F - public final fun getActivePotionEffects ()Ljava/util/List; - public final fun getAge ()I - public final fun getArmorValue ()I - public final fun getHP ()F - public final fun getMaxHP ()F - public synthetic fun getMcValue ()Ljava/lang/Object; - public synthetic fun getMcValue ()Lnet/minecraft/entity/Entity; - public fun getMcValue ()Lnet/minecraft/entity/LivingEntity; - public final fun getStackInSlot (I)Lcom/chattriggers/ctjs/api/inventory/Item; - public final fun isPotionActive (I)Z - public final fun isPotionActive (Lcom/chattriggers/ctjs/api/world/PotionEffect;)Z - public final fun isPotionActive (Lcom/chattriggers/ctjs/api/world/PotionEffectType;)Z -} - -public final class com/chattriggers/ctjs/api/entity/Particle : com/chattriggers/ctjs/api/CTWrapper { - public fun (Lnet/minecraft/client/particle/Particle;)V - public final fun getAge ()I - public final fun getAlpha ()F - public final fun getBlue ()F - public final fun getColor ()Ljava/awt/Color; - public final fun getDead ()Z - public final fun getGreen ()F - public final fun getLastX ()D - public final fun getLastY ()D - public final fun getLastZ ()D - public synthetic fun getMcValue ()Ljava/lang/Object; - public fun getMcValue ()Lnet/minecraft/client/particle/Particle; - public final fun getMotionX ()D - public final fun getMotionY ()D - public final fun getMotionZ ()D - public final fun getRed ()F - public final fun getRenderX ()D - public final fun getRenderY ()D - public final fun getRenderZ ()D - public final fun getX ()D - public final fun getY ()D - public final fun getZ ()D - public final fun remove ()Lcom/chattriggers/ctjs/api/entity/Particle; - public final fun scale (F)Lcom/chattriggers/ctjs/api/entity/Particle; - public final fun setAge (I)V - public final fun setAlpha (F)Lcom/chattriggers/ctjs/api/entity/Particle; - public final fun setAlpha (F)V - public final fun setBlue (F)V - public final fun setColor (FFF)Lcom/chattriggers/ctjs/api/entity/Particle; - public final fun setColor (FFFF)Lcom/chattriggers/ctjs/api/entity/Particle; - public final fun setColor (J)Lcom/chattriggers/ctjs/api/entity/Particle; - public final fun setColor (Ljava/awt/Color;)Lcom/chattriggers/ctjs/api/entity/Particle; - public final fun setDead (Z)V - public final fun setGreen (F)V - public final fun setLastX (D)V - public final fun setLastY (D)V - public final fun setLastZ (D)V - public final fun setMaxAge (I)Lcom/chattriggers/ctjs/api/entity/Particle; - public final fun setMotionX (D)V - public final fun setMotionY (D)V - public final fun setMotionZ (D)V - public final fun setRed (F)V - public final fun setX (D)V - public final fun setY (D)V - public final fun setZ (D)V - public synthetic fun toMC ()Ljava/lang/Object; - public fun toMC ()Lnet/minecraft/client/particle/Particle; - public fun toString ()Ljava/lang/String; -} - -public abstract class com/chattriggers/ctjs/api/entity/PlayerInteraction { - public synthetic fun (Ljava/lang/String;ZLkotlin/jvm/internal/DefaultConstructorMarker;)V - public final fun getMainHand ()Z - public final fun getName ()Ljava/lang/String; - public fun toString ()Ljava/lang/String; -} - -public final class com/chattriggers/ctjs/api/entity/PlayerInteraction$AttackBlock : com/chattriggers/ctjs/api/entity/PlayerInteraction { - public static final field INSTANCE Lcom/chattriggers/ctjs/api/entity/PlayerInteraction$AttackBlock; -} - -public final class com/chattriggers/ctjs/api/entity/PlayerInteraction$AttackEntity : com/chattriggers/ctjs/api/entity/PlayerInteraction { - public static final field INSTANCE Lcom/chattriggers/ctjs/api/entity/PlayerInteraction$AttackEntity; -} - -public final class com/chattriggers/ctjs/api/entity/PlayerInteraction$BreakBlock : com/chattriggers/ctjs/api/entity/PlayerInteraction { - public static final field INSTANCE Lcom/chattriggers/ctjs/api/entity/PlayerInteraction$BreakBlock; -} - -public final class com/chattriggers/ctjs/api/entity/PlayerInteraction$UseBlock : com/chattriggers/ctjs/api/entity/PlayerInteraction { - public fun (Lnet/minecraft/util/Hand;)V -} - -public final class com/chattriggers/ctjs/api/entity/PlayerInteraction$UseEntity : com/chattriggers/ctjs/api/entity/PlayerInteraction { - public fun (Lnet/minecraft/util/Hand;)V -} - -public final class com/chattriggers/ctjs/api/entity/PlayerInteraction$UseItem : com/chattriggers/ctjs/api/entity/PlayerInteraction { - public fun (Lnet/minecraft/util/Hand;)V -} - -public final class com/chattriggers/ctjs/api/entity/PlayerMP : com/chattriggers/ctjs/api/entity/LivingEntity { - public fun (Lnet/minecraft/entity/player/PlayerEntity;)V - public final fun draw (Lorg/mozilla/javascript/NativeObject;)Lcom/chattriggers/ctjs/api/entity/PlayerMP; - public final fun getDisplayName ()Lcom/chattriggers/ctjs/api/message/TextComponent; - public synthetic fun getMcValue ()Ljava/lang/Object; - public synthetic fun getMcValue ()Lnet/minecraft/entity/Entity; - public synthetic fun getMcValue ()Lnet/minecraft/entity/LivingEntity; - public fun getMcValue ()Lnet/minecraft/entity/player/PlayerEntity; - public final fun getPing ()I - public final fun getTeam ()Lcom/chattriggers/ctjs/api/entity/Team; - public final fun isSpectator ()Z - public final fun setNametagName (Lcom/chattriggers/ctjs/api/message/TextComponent;)V - public final fun setTabDisplayName (Lcom/chattriggers/ctjs/api/message/TextComponent;)V -} - -public final class com/chattriggers/ctjs/api/entity/Team : com/chattriggers/ctjs/api/CTWrapper { - public fun (Lnet/minecraft/scoreboard/Team;)V - public final fun canSeeInvisibleTeammates ()Z - public final fun getColor ()Ljava/lang/String; - public final fun getDeathMessageVisibility ()Lcom/chattriggers/ctjs/api/entity/Team$Visibility; - public final fun getFriendlyFire ()Z - public synthetic fun getMcValue ()Ljava/lang/Object; - public fun getMcValue ()Lnet/minecraft/scoreboard/Team; - public final fun getMembers ()Ljava/util/List; - public final fun getName ()Ljava/lang/String; - public final fun getNameTagVisibility ()Lcom/chattriggers/ctjs/api/entity/Team$Visibility; - public final fun getPrefix ()Ljava/lang/String; - public final fun getRegisteredName ()Ljava/lang/String; - public final fun getSuffix ()Ljava/lang/String; - public final fun setColor (Ljava/lang/Object;)Lcom/chattriggers/ctjs/api/entity/Team; - public final fun setName (Lcom/chattriggers/ctjs/api/message/TextComponent;)Lcom/chattriggers/ctjs/api/entity/Team; - public final fun setName (Ljava/lang/String;)Lcom/chattriggers/ctjs/api/entity/Team; - public final fun setPrefix (Lcom/chattriggers/ctjs/api/message/TextComponent;)Lcom/chattriggers/ctjs/api/entity/Team; - public final fun setPrefix (Ljava/lang/String;)Lcom/chattriggers/ctjs/api/entity/Team; - public final fun setSuffix (Lcom/chattriggers/ctjs/api/message/TextComponent;)Lcom/chattriggers/ctjs/api/entity/Team; - public final fun setSuffix (Ljava/lang/String;)Lcom/chattriggers/ctjs/api/entity/Team; - public synthetic fun toMC ()Ljava/lang/Object; - public fun toMC ()Lnet/minecraft/scoreboard/Team; -} - -public final class com/chattriggers/ctjs/api/entity/Team$Visibility : java/lang/Enum, com/chattriggers/ctjs/api/CTWrapper { - public static final field ALWAYS Lcom/chattriggers/ctjs/api/entity/Team$Visibility; - public static final field Companion Lcom/chattriggers/ctjs/api/entity/Team$Visibility$Companion; - public static final field HIDE_FOR_OTHERS_TEAMS Lcom/chattriggers/ctjs/api/entity/Team$Visibility; - public static final field HIDE_FOR_OWN_TEAM Lcom/chattriggers/ctjs/api/entity/Team$Visibility; - public static final field NEVER Lcom/chattriggers/ctjs/api/entity/Team$Visibility; - public static final fun fromMC (Lnet/minecraft/scoreboard/AbstractTeam$VisibilityRule;)Lcom/chattriggers/ctjs/api/entity/Team$Visibility; - public static fun getEntries ()Lkotlin/enums/EnumEntries; - public synthetic fun getMcValue ()Ljava/lang/Object; - public fun getMcValue ()Lnet/minecraft/scoreboard/AbstractTeam$VisibilityRule; - public synthetic fun toMC ()Ljava/lang/Object; - public fun toMC ()Lnet/minecraft/scoreboard/AbstractTeam$VisibilityRule; - public static fun valueOf (Ljava/lang/String;)Lcom/chattriggers/ctjs/api/entity/Team$Visibility; - public static fun values ()[Lcom/chattriggers/ctjs/api/entity/Team$Visibility; -} - -public final class com/chattriggers/ctjs/api/entity/Team$Visibility$Companion { - public final fun fromMC (Lnet/minecraft/scoreboard/AbstractTeam$VisibilityRule;)Lcom/chattriggers/ctjs/api/entity/Team$Visibility; -} - -public final class com/chattriggers/ctjs/api/inventory/Inventory { - public fun (Lnet/minecraft/client/gui/screen/ingame/HandledScreen;)V - public fun (Lnet/minecraft/inventory/Inventory;)V - public final fun click (I)Lcom/chattriggers/ctjs/api/inventory/Inventory; - public final fun click (IZ)Lcom/chattriggers/ctjs/api/inventory/Inventory; - public final fun click (IZLjava/lang/String;)Lcom/chattriggers/ctjs/api/inventory/Inventory; - public static synthetic fun click$default (Lcom/chattriggers/ctjs/api/inventory/Inventory;IZLjava/lang/String;ILjava/lang/Object;)Lcom/chattriggers/ctjs/api/inventory/Inventory; - public final fun contains (I)Z - public final fun contains (Lcom/chattriggers/ctjs/api/inventory/Item;)Z - public final fun drag (Ljava/lang/String;[I)Lcom/chattriggers/ctjs/api/inventory/Inventory; - public final fun drop (IZ)Lcom/chattriggers/ctjs/api/inventory/Inventory; - public final fun getClassName ()Ljava/lang/String; - public final fun getInventory ()Lnet/minecraft/inventory/Inventory; - public final fun getItems ()Ljava/util/List; - public final fun getName ()Lcom/chattriggers/ctjs/api/message/TextComponent; - public final fun getScreen ()Lnet/minecraft/client/gui/screen/ingame/HandledScreen; - public final fun getSize ()I - public final fun getStackInSlot (I)Lcom/chattriggers/ctjs/api/inventory/Item; - public final fun getWindowId ()I - public final fun indexOf (I)I - public final fun indexOf (Lcom/chattriggers/ctjs/api/inventory/Item;)I - public final fun isItemValidForSlot (ILcom/chattriggers/ctjs/api/inventory/Item;)Z - public final fun isScreen ()Z - public fun toString ()Ljava/lang/String; -} - -public final class com/chattriggers/ctjs/api/inventory/Item : com/chattriggers/ctjs/api/CTWrapper { - public static final field Companion Lcom/chattriggers/ctjs/api/inventory/Item$Companion; - public fun (Lcom/chattriggers/ctjs/api/inventory/ItemType;)V - public fun (Lnet/minecraft/item/ItemStack;)V - public final fun canHarvest (Lcom/chattriggers/ctjs/api/world/block/Block;)Z - public final fun canHarvest (Lcom/chattriggers/ctjs/api/world/block/BlockPos;)Z - public final fun canPlaceOn (Lcom/chattriggers/ctjs/api/world/block/Block;)Z - public final fun canPlaceOn (Lcom/chattriggers/ctjs/api/world/block/BlockPos;)Z - public final fun draw ()V - public final fun draw (F)V - public final fun draw (FF)V - public final fun draw (FFF)V - public final fun draw (FFFF)V - public static synthetic fun draw$default (Lcom/chattriggers/ctjs/api/inventory/Item;FFFFILjava/lang/Object;)V - public static final fun fromMC (Lnet/minecraft/item/ItemStack;)Lcom/chattriggers/ctjs/api/inventory/Item; - public final fun getDamage ()I - public final fun getDurability ()I - public final fun getEnchantments ()Ljava/util/Map; - public final fun getHolder ()Lcom/chattriggers/ctjs/api/entity/Entity; - public final fun getLore ()Ljava/util/List; - public final fun getLore (Z)Ljava/util/List; - public static synthetic fun getLore$default (Lcom/chattriggers/ctjs/api/inventory/Item;ZILjava/lang/Object;)Ljava/util/List; - public final fun getMaxDamage ()I - public synthetic fun getMcValue ()Ljava/lang/Object; - public fun getMcValue ()Lnet/minecraft/item/ItemStack; - public final fun getNBT ()Lnet/minecraft/component/ComponentMap; - public final fun getName ()Ljava/lang/String; - public final fun getStackSize ()I - public final fun getType ()Lcom/chattriggers/ctjs/api/inventory/ItemType; - public final fun isDamageable ()Z - public final fun isEnchantable ()Z - public final fun isEnchanted ()Z - public final fun resetLore ()V - public final fun resetName ()V - public final fun setLore (Ljava/util/List;)V - public final fun setName (Lcom/chattriggers/ctjs/api/message/TextComponent;)Lcom/chattriggers/ctjs/api/inventory/Item; - public final fun setStackSize (I)Lcom/chattriggers/ctjs/api/inventory/Item; - public synthetic fun toMC ()Ljava/lang/Object; - public fun toMC ()Lnet/minecraft/item/ItemStack; - public fun toString ()Ljava/lang/String; -} - -public final class com/chattriggers/ctjs/api/inventory/Item$Companion { - public final fun fromMC (Lnet/minecraft/item/ItemStack;)Lcom/chattriggers/ctjs/api/inventory/Item; -} - -public final class com/chattriggers/ctjs/api/inventory/ItemType : com/chattriggers/ctjs/api/CTWrapper { - public static final field Companion Lcom/chattriggers/ctjs/api/inventory/ItemType$Companion; - public fun (I)V - public fun (Lcom/chattriggers/ctjs/api/world/block/BlockType;)V - public fun (Ljava/lang/String;)V - public fun (Lnet/minecraft/item/Item;)V - public final fun asItem ()Lcom/chattriggers/ctjs/api/inventory/Item; - public static final fun fromMC (Lnet/minecraft/item/Item;)Lcom/chattriggers/ctjs/api/inventory/ItemType; - public final fun getId ()I - public synthetic fun getMcValue ()Ljava/lang/Object; - public fun getMcValue ()Lnet/minecraft/item/Item; - public final fun getName ()Ljava/lang/String; - public final fun getNameComponent ()Lcom/chattriggers/ctjs/api/message/TextComponent; - public final fun getRegistryName ()Ljava/lang/String; - public final fun getTranslationKey ()Ljava/lang/String; - public synthetic fun toMC ()Ljava/lang/Object; - public fun toMC ()Lnet/minecraft/item/Item; -} - -public final class com/chattriggers/ctjs/api/inventory/ItemType$Companion { - public final fun fromMC (Lnet/minecraft/item/Item;)Lcom/chattriggers/ctjs/api/inventory/ItemType; -} - -public final class com/chattriggers/ctjs/api/inventory/Slot : com/chattriggers/ctjs/api/CTWrapper { - public fun (Lnet/minecraft/screen/slot/Slot;)V - public final fun getDisplayX ()I - public final fun getDisplayY ()I - public final fun getIndex ()I - public final fun getInventory ()Lcom/chattriggers/ctjs/api/inventory/Inventory; - public final fun getItem ()Lcom/chattriggers/ctjs/api/inventory/Item; - public synthetic fun getMcValue ()Ljava/lang/Object; - public fun getMcValue ()Lnet/minecraft/screen/slot/Slot; - public final fun isEnabled ()Z - public synthetic fun toMC ()Ljava/lang/Object; - public fun toMC ()Lnet/minecraft/screen/slot/Slot; - public fun toString ()Ljava/lang/String; -} - -public abstract class com/chattriggers/ctjs/api/inventory/action/Action { - public static final field Companion Lcom/chattriggers/ctjs/api/inventory/action/Action$Companion; - public fun (II)V - protected final fun doClick (ILnet/minecraft/screen/slot/SlotActionType;)V - public final fun getSlot ()I - public final fun getWindowId ()I - public static final fun of (Lcom/chattriggers/ctjs/api/inventory/Inventory;ILjava/lang/String;)Lcom/chattriggers/ctjs/api/inventory/action/Action; - public final fun setSlot (I)Lcom/chattriggers/ctjs/api/inventory/action/Action; - public final fun setSlot (I)V - public final fun setWindowId (I)Lcom/chattriggers/ctjs/api/inventory/action/Action; - public final fun setWindowId (I)V -} - -public final class com/chattriggers/ctjs/api/inventory/action/Action$Companion { - public final fun of (Lcom/chattriggers/ctjs/api/inventory/Inventory;ILjava/lang/String;)Lcom/chattriggers/ctjs/api/inventory/action/Action; -} - -public final class com/chattriggers/ctjs/api/inventory/action/Action$Type : java/lang/Enum { - public static final field CLICK Lcom/chattriggers/ctjs/api/inventory/action/Action$Type; - public static final field DRAG Lcom/chattriggers/ctjs/api/inventory/action/Action$Type; - public static final field DROP Lcom/chattriggers/ctjs/api/inventory/action/Action$Type; - public static final field KEY Lcom/chattriggers/ctjs/api/inventory/action/Action$Type; - public static fun getEntries ()Lkotlin/enums/EnumEntries; - public static fun valueOf (Ljava/lang/String;)Lcom/chattriggers/ctjs/api/inventory/action/Action$Type; - public static fun values ()[Lcom/chattriggers/ctjs/api/inventory/action/Action$Type; -} - -public final class com/chattriggers/ctjs/api/inventory/action/ClickAction : com/chattriggers/ctjs/api/inventory/action/Action { - public fun (II)V - public final fun getClickType ()Lcom/chattriggers/ctjs/api/inventory/action/ClickAction$ClickType; - public final fun getHoldingShift ()Z - public final fun getItemInHand ()Z - public final fun getPickupAll ()Z - public final fun setClickString (Ljava/lang/String;)Lcom/chattriggers/ctjs/api/inventory/action/ClickAction; - public final fun setClickType (Lcom/chattriggers/ctjs/api/inventory/action/ClickAction$ClickType;)Lcom/chattriggers/ctjs/api/inventory/action/ClickAction; - public final fun setHoldingShift (Z)Lcom/chattriggers/ctjs/api/inventory/action/ClickAction; - public final fun setItemInHand (Z)Lcom/chattriggers/ctjs/api/inventory/action/ClickAction; - public final fun setPickupAll (Z)Lcom/chattriggers/ctjs/api/inventory/action/ClickAction; -} - -public final class com/chattriggers/ctjs/api/inventory/action/ClickAction$ClickType : java/lang/Enum { - public static final field LEFT Lcom/chattriggers/ctjs/api/inventory/action/ClickAction$ClickType; - public static final field MIDDLE Lcom/chattriggers/ctjs/api/inventory/action/ClickAction$ClickType; - public static final field RIGHT Lcom/chattriggers/ctjs/api/inventory/action/ClickAction$ClickType; - public final fun getButton ()I - public static fun getEntries ()Lkotlin/enums/EnumEntries; - public static fun valueOf (Ljava/lang/String;)Lcom/chattriggers/ctjs/api/inventory/action/ClickAction$ClickType; - public static fun values ()[Lcom/chattriggers/ctjs/api/inventory/action/ClickAction$ClickType; -} - -public final class com/chattriggers/ctjs/api/inventory/action/DragAction : com/chattriggers/ctjs/api/inventory/action/Action { - public fun (II)V - public final fun getClickType ()Lcom/chattriggers/ctjs/api/inventory/action/DragAction$ClickType; - public final fun getStage ()Lcom/chattriggers/ctjs/api/inventory/action/DragAction$Stage; - public final fun setClickString (Ljava/lang/String;)Lcom/chattriggers/ctjs/api/inventory/action/DragAction; - public final fun setClickType (Lcom/chattriggers/ctjs/api/inventory/action/DragAction$ClickType;)Lcom/chattriggers/ctjs/api/inventory/action/DragAction; - public final fun setStage (Lcom/chattriggers/ctjs/api/inventory/action/DragAction$Stage;)Lcom/chattriggers/ctjs/api/inventory/action/DragAction; - public final fun setStageString (Ljava/lang/String;)Lcom/chattriggers/ctjs/api/inventory/action/DragAction; -} - -public final class com/chattriggers/ctjs/api/inventory/action/DragAction$ClickType : java/lang/Enum { - public static final field LEFT Lcom/chattriggers/ctjs/api/inventory/action/DragAction$ClickType; - public static final field MIDDLE Lcom/chattriggers/ctjs/api/inventory/action/DragAction$ClickType; - public static final field RIGHT Lcom/chattriggers/ctjs/api/inventory/action/DragAction$ClickType; - public final fun getButton ()I - public static fun getEntries ()Lkotlin/enums/EnumEntries; - public static fun valueOf (Ljava/lang/String;)Lcom/chattriggers/ctjs/api/inventory/action/DragAction$ClickType; - public static fun values ()[Lcom/chattriggers/ctjs/api/inventory/action/DragAction$ClickType; -} - -public final class com/chattriggers/ctjs/api/inventory/action/DragAction$Stage : java/lang/Enum { - public static final field BEGIN Lcom/chattriggers/ctjs/api/inventory/action/DragAction$Stage; - public static final field END Lcom/chattriggers/ctjs/api/inventory/action/DragAction$Stage; - public static final field SLOT Lcom/chattriggers/ctjs/api/inventory/action/DragAction$Stage; - public static fun getEntries ()Lkotlin/enums/EnumEntries; - public final fun getStage ()I - public static fun valueOf (Ljava/lang/String;)Lcom/chattriggers/ctjs/api/inventory/action/DragAction$Stage; - public static fun values ()[Lcom/chattriggers/ctjs/api/inventory/action/DragAction$Stage; -} - -public final class com/chattriggers/ctjs/api/inventory/action/DropAction : com/chattriggers/ctjs/api/inventory/action/Action { - public fun (II)V - public final fun getHoldingCtrl ()Z - public final fun setHoldingCtrl (Z)Lcom/chattriggers/ctjs/api/inventory/action/DropAction; -} - -public final class com/chattriggers/ctjs/api/inventory/action/KeyAction : com/chattriggers/ctjs/api/inventory/action/Action { - public fun (II)V - public final fun getKey ()I - public final fun setKey (I)Lcom/chattriggers/ctjs/api/inventory/action/KeyAction; -} - -public final class com/chattriggers/ctjs/api/inventory/nbt/NBT { - public static final field INSTANCE Lcom/chattriggers/ctjs/api/inventory/nbt/NBT; - public static final fun parse (Ljava/lang/Object;)Lcom/chattriggers/ctjs/api/inventory/nbt/NBTBase; - public static final fun parse (Ljava/lang/Object;Lorg/mozilla/javascript/NativeObject;)Lcom/chattriggers/ctjs/api/inventory/nbt/NBTBase; - public static synthetic fun parse$default (Ljava/lang/Object;Lorg/mozilla/javascript/NativeObject;ILjava/lang/Object;)Lcom/chattriggers/ctjs/api/inventory/nbt/NBTBase; - public static final fun toArray (Lcom/chattriggers/ctjs/api/inventory/nbt/NBTTagList;)Lorg/mozilla/javascript/NativeArray; - public static final fun toObject (Lcom/chattriggers/ctjs/api/inventory/nbt/NBTTagCompound;)Lorg/mozilla/javascript/NativeObject; -} - -public class com/chattriggers/ctjs/api/inventory/nbt/NBTBase : com/chattriggers/ctjs/api/CTWrapper { - public static final field Companion Lcom/chattriggers/ctjs/api/inventory/nbt/NBTBase$Companion; - public fun (Lnet/minecraft/nbt/NbtElement;)V - public final fun copy ()Lnet/minecraft/nbt/NbtElement; - public fun equals (Ljava/lang/Object;)Z - public static final fun fromMC (Lnet/minecraft/nbt/NbtElement;)Lcom/chattriggers/ctjs/api/inventory/nbt/NBTBase; - public final fun getId ()B - public synthetic fun getMcValue ()Ljava/lang/Object; - public fun getMcValue ()Lnet/minecraft/nbt/NbtElement; - public final fun hasNoTags ()Z - public final fun hasTags ()Z - public fun hashCode ()I - public synthetic fun toMC ()Ljava/lang/Object; - public fun toMC ()Lnet/minecraft/nbt/NbtElement; - public fun toString ()Ljava/lang/String; -} - -public final class com/chattriggers/ctjs/api/inventory/nbt/NBTBase$Companion { - public final fun fromMC (Lnet/minecraft/nbt/NbtElement;)Lcom/chattriggers/ctjs/api/inventory/nbt/NBTBase; - public final fun toObject (Lnet/minecraft/nbt/NbtCompound;)Lorg/mozilla/javascript/NativeObject; - public final fun toObject (Lnet/minecraft/nbt/NbtElement;)Ljava/lang/Object; - public final fun toObject (Lnet/minecraft/nbt/NbtList;)Lorg/mozilla/javascript/NativeArray; -} - -public final class com/chattriggers/ctjs/api/inventory/nbt/NBTTagCompound : com/chattriggers/ctjs/api/inventory/nbt/NBTBase { - public fun (Lnet/minecraft/nbt/NbtCompound;)V - public final fun get (Ljava/lang/String;)Lcom/chattriggers/ctjs/api/inventory/nbt/NBTBase; - public final fun get (Ljava/lang/String;Lcom/chattriggers/ctjs/api/inventory/nbt/NBTTagCompound$NBTDataType;Ljava/lang/Integer;)Ljava/lang/Object; - public final fun getBoolean (Ljava/lang/String;)Z - public final fun getByte (Ljava/lang/String;)B - public final fun getByteArray (Ljava/lang/String;)[B - public final fun getCompoundTag (Ljava/lang/String;)Lcom/chattriggers/ctjs/api/inventory/nbt/NBTTagCompound; - public final fun getDouble (Ljava/lang/String;)D - public final fun getFloat (Ljava/lang/String;)F - public final fun getIntArray (Ljava/lang/String;)[I - public final fun getInteger (Ljava/lang/String;)I - public final fun getKeySet ()Ljava/util/Set; - public final fun getLong (Ljava/lang/String;)J - public synthetic fun getMcValue ()Ljava/lang/Object; - public fun getMcValue ()Lnet/minecraft/nbt/NbtCompound; - public synthetic fun getMcValue ()Lnet/minecraft/nbt/NbtElement; - public final fun getShort (Ljava/lang/String;)S - public final fun getString (Ljava/lang/String;)Ljava/lang/String; - public final fun getTag (Ljava/lang/String;)Lcom/chattriggers/ctjs/api/inventory/nbt/NBTBase; - public final fun getTagId (Ljava/lang/String;)B - public final fun getTagList (Ljava/lang/String;I)Lcom/chattriggers/ctjs/api/inventory/nbt/NBTTagList; - public final fun getTagMap ()Ljava/util/Map; - public final fun putLongArray (Ljava/lang/String;[J)Lcom/chattriggers/ctjs/api/inventory/nbt/NBTTagCompound; - public final fun removeTag (Ljava/lang/String;)Lcom/chattriggers/ctjs/api/inventory/nbt/NBTTagCompound; - public final fun set (Ljava/lang/String;Ljava/lang/Object;)Lcom/chattriggers/ctjs/api/inventory/nbt/NBTTagCompound; - public final fun setBoolean (Ljava/lang/String;Z)Lcom/chattriggers/ctjs/api/inventory/nbt/NBTTagCompound; - public final fun setByte (Ljava/lang/String;B)Lcom/chattriggers/ctjs/api/inventory/nbt/NBTTagCompound; - public final fun setByteArray (Ljava/lang/String;[B)Lcom/chattriggers/ctjs/api/inventory/nbt/NBTTagCompound; - public final fun setDouble (Ljava/lang/String;D)Lcom/chattriggers/ctjs/api/inventory/nbt/NBTTagCompound; - public final fun setFloat (Ljava/lang/String;F)Lcom/chattriggers/ctjs/api/inventory/nbt/NBTTagCompound; - public final fun setIntArray (Ljava/lang/String;[I)Lcom/chattriggers/ctjs/api/inventory/nbt/NBTTagCompound; - public final fun setInteger (Ljava/lang/String;I)Lcom/chattriggers/ctjs/api/inventory/nbt/NBTTagCompound; - public final fun setLong (Ljava/lang/String;J)Lcom/chattriggers/ctjs/api/inventory/nbt/NBTTagCompound; - public final fun setNBTBase (Ljava/lang/String;Lcom/chattriggers/ctjs/api/inventory/nbt/NBTBase;)Lcom/chattriggers/ctjs/api/inventory/nbt/NBTTagCompound; - public final fun setNBTBase (Ljava/lang/String;Lnet/minecraft/nbt/NbtElement;)Lcom/chattriggers/ctjs/api/inventory/nbt/NBTTagCompound; - public final fun setShort (Ljava/lang/String;S)Lcom/chattriggers/ctjs/api/inventory/nbt/NBTTagCompound; - public final fun setString (Ljava/lang/String;Ljava/lang/String;)Lcom/chattriggers/ctjs/api/inventory/nbt/NBTTagCompound; - public final fun toObject ()Lorg/mozilla/javascript/NativeObject; -} - -public final class com/chattriggers/ctjs/api/inventory/nbt/NBTTagCompound$NBTDataType : java/lang/Enum { - public static final field BOOLEAN Lcom/chattriggers/ctjs/api/inventory/nbt/NBTTagCompound$NBTDataType; - public static final field BYTE Lcom/chattriggers/ctjs/api/inventory/nbt/NBTTagCompound$NBTDataType; - public static final field BYTE_ARRAY Lcom/chattriggers/ctjs/api/inventory/nbt/NBTTagCompound$NBTDataType; - public static final field COMPOUND_TAG Lcom/chattriggers/ctjs/api/inventory/nbt/NBTTagCompound$NBTDataType; - public static final field DOUBLE Lcom/chattriggers/ctjs/api/inventory/nbt/NBTTagCompound$NBTDataType; - public static final field FLOAT Lcom/chattriggers/ctjs/api/inventory/nbt/NBTTagCompound$NBTDataType; - public static final field INTEGER Lcom/chattriggers/ctjs/api/inventory/nbt/NBTTagCompound$NBTDataType; - public static final field INT_ARRAY Lcom/chattriggers/ctjs/api/inventory/nbt/NBTTagCompound$NBTDataType; - public static final field LONG Lcom/chattriggers/ctjs/api/inventory/nbt/NBTTagCompound$NBTDataType; - public static final field LONG_ARRAY Lcom/chattriggers/ctjs/api/inventory/nbt/NBTTagCompound$NBTDataType; - public static final field SHORT Lcom/chattriggers/ctjs/api/inventory/nbt/NBTTagCompound$NBTDataType; - public static final field STRING Lcom/chattriggers/ctjs/api/inventory/nbt/NBTTagCompound$NBTDataType; - public static final field TAG_LIST Lcom/chattriggers/ctjs/api/inventory/nbt/NBTTagCompound$NBTDataType; - public static fun getEntries ()Lkotlin/enums/EnumEntries; - public static fun valueOf (Ljava/lang/String;)Lcom/chattriggers/ctjs/api/inventory/nbt/NBTTagCompound$NBTDataType; - public static fun values ()[Lcom/chattriggers/ctjs/api/inventory/nbt/NBTTagCompound$NBTDataType; -} - -public final class com/chattriggers/ctjs/api/inventory/nbt/NBTTagList : com/chattriggers/ctjs/api/inventory/nbt/NBTBase { - public fun (Lnet/minecraft/nbt/NbtList;)V - public final fun appendTag (Lcom/chattriggers/ctjs/api/inventory/nbt/NBTBase;)Lcom/chattriggers/ctjs/api/inventory/nbt/NBTTagList; - public final fun appendTag (Lnet/minecraft/nbt/NbtElement;)Lcom/chattriggers/ctjs/api/inventory/nbt/NBTTagList; - public final fun get (I)Lnet/minecraft/nbt/NbtElement; - public final fun get (IB)Ljava/lang/Object; - public final fun getCompoundTagAt (I)Lcom/chattriggers/ctjs/api/inventory/nbt/NBTTagCompound; - public final fun getDoubleAt (I)D - public final fun getFloatAt (I)F - public final fun getIntArrayAt (I)[I - public final fun getIntAt (I)I - public final fun getListAt (I)Lcom/chattriggers/ctjs/api/inventory/nbt/NBTTagList; - public final fun getLongArrayAt (I)[J - public synthetic fun getMcValue ()Ljava/lang/Object; - public synthetic fun getMcValue ()Lnet/minecraft/nbt/NbtElement; - public fun getMcValue ()Lnet/minecraft/nbt/NbtList; - public final fun getShortAt (I)S - public final fun getStringTagAt (I)Ljava/lang/String; - public final fun getTagCount ()I - public final fun insertTag (ILcom/chattriggers/ctjs/api/inventory/nbt/NBTBase;)Lcom/chattriggers/ctjs/api/inventory/nbt/NBTTagList; - public final fun insertTag (ILnet/minecraft/nbt/NbtElement;)Lcom/chattriggers/ctjs/api/inventory/nbt/NBTTagList; - public final fun removeTag (I)Lcom/chattriggers/ctjs/api/inventory/nbt/NBTBase; - public final fun set (ILcom/chattriggers/ctjs/api/inventory/nbt/NBTBase;)Lcom/chattriggers/ctjs/api/inventory/nbt/NBTTagList; - public final fun set (ILnet/minecraft/nbt/NbtElement;)Lcom/chattriggers/ctjs/api/inventory/nbt/NBTTagList; - public final fun toArray ()Lorg/mozilla/javascript/NativeArray; -} - -public final class com/chattriggers/ctjs/api/message/ChatLib { - public static final field INSTANCE Lcom/chattriggers/ctjs/api/message/ChatLib; - public static final fun actionBar (Ljava/lang/Object;)V - public static final fun addColor (Ljava/lang/String;)Ljava/lang/String; - public static final fun addToSentMessageHistory (ILjava/lang/String;)V - public static final fun addToSentMessageHistory (Ljava/lang/String;)V - public static synthetic fun addToSentMessageHistory$default (ILjava/lang/String;ILjava/lang/Object;)V - public static final fun chat (Ljava/lang/Object;)V - public static final fun clearChat ()V - public static final fun command (Ljava/lang/String;)V - public static final fun command (Ljava/lang/String;Z)V - public static synthetic fun command$default (Ljava/lang/String;ZILjava/lang/Object;)V - public static final fun copyToClipboard (Ljava/lang/String;)V - public static final fun deleteChat (I)V - public static final fun deleteChat (Lcom/chattriggers/ctjs/api/message/TextComponent;)V - public static final fun deleteChat (Ljava/lang/String;)V - public static final fun deleteChat (Lkotlin/jvm/functions/Function1;)V - public static final fun deleteChat (Lorg/mozilla/javascript/regexp/NativeRegExp;)V - public static final fun editChat (I[Ljava/lang/Object;)V - public static final fun editChat (Lcom/chattriggers/ctjs/api/message/TextComponent;[Ljava/lang/Object;)V - public static final fun editChat (Ljava/lang/String;[Ljava/lang/Object;)V - public static final fun editChat (Lkotlin/jvm/functions/Function1;[Ljava/lang/Object;)V - public static final fun editChat (Lorg/mozilla/javascript/regexp/NativeRegExp;[Ljava/lang/Object;)V - public static final fun getCenteredText (Ljava/lang/String;)Ljava/lang/String; - public static final fun getChatBreak ()Ljava/lang/String; - public static final fun getChatBreak (Ljava/lang/String;)Ljava/lang/String; - public static synthetic fun getChatBreak$default (Ljava/lang/String;ILjava/lang/Object;)Ljava/lang/String; - public static final fun getChatLines ()Ljava/util/List; - public static final fun getChatWidth ()I - public static final fun removeFormatting (Ljava/lang/String;)Ljava/lang/String; - public static final fun replaceFormatting (Ljava/lang/String;)Ljava/lang/String; - public static final fun say (Ljava/lang/String;)Lkotlin/Unit; - public static final fun simulateChat (Ljava/lang/Object;)V -} - -public final class com/chattriggers/ctjs/api/message/TextComponent : java/lang/Iterable, kotlin/jvm/internal/markers/KMappedMarker, net/minecraft/text/Text { - public fun ()V - public fun ([Ljava/lang/Object;)V - public final fun actionBar ()Lcom/chattriggers/ctjs/api/message/TextComponent; - public fun asOrderedText ()Lnet/minecraft/text/OrderedText; - public final fun chat ()Lcom/chattriggers/ctjs/api/message/TextComponent; - public final fun contains (Lorg/mozilla/javascript/NativeObject;)Z - public final fun containsAll (Ljava/util/Collection;)Z - public final fun delete ()Lcom/chattriggers/ctjs/api/message/TextComponent; - public final fun edit (Lcom/chattriggers/ctjs/api/message/TextComponent;)Lcom/chattriggers/ctjs/api/message/TextComponent; - public final fun edit ([Ljava/lang/Object;)Lcom/chattriggers/ctjs/api/message/TextComponent; - public final fun get (I)Lorg/mozilla/javascript/NativeObject; - public final fun getChatLineId ()I - public fun getContent ()Lnet/minecraft/text/TextContent; - public final fun getFormattedText ()Ljava/lang/String; - public fun getSiblings ()Ljava/util/List; - public final fun getSize ()I - public fun getString ()Ljava/lang/String; - public fun getStyle ()Lnet/minecraft/text/Style; - public final fun getUnformattedText ()Ljava/lang/String; - public final fun indexOf (Lorg/mozilla/javascript/NativeObject;)I - public final fun isEmpty ()Z - public final fun isRecursive ()Z - public fun iterator ()Ljava/util/Iterator; - public fun toString ()Ljava/lang/String; - public final fun withChatLineId ()Lcom/chattriggers/ctjs/api/message/TextComponent; - public final fun withChatLineId (I)Lcom/chattriggers/ctjs/api/message/TextComponent; - public static synthetic fun withChatLineId$default (Lcom/chattriggers/ctjs/api/message/TextComponent;IILjava/lang/Object;)Lcom/chattriggers/ctjs/api/message/TextComponent; - public final fun withRecursive ()Lcom/chattriggers/ctjs/api/message/TextComponent; - public final fun withRecursive (Z)Lcom/chattriggers/ctjs/api/message/TextComponent; - public static synthetic fun withRecursive$default (Lcom/chattriggers/ctjs/api/message/TextComponent;ZILjava/lang/Object;)Lcom/chattriggers/ctjs/api/message/TextComponent; - public final fun withText (Ljava/lang/Object;)Lcom/chattriggers/ctjs/api/message/TextComponent; - public final fun withTextAt (ILjava/lang/Object;)Lcom/chattriggers/ctjs/api/message/TextComponent; - public final fun withoutTextAt (I)Lcom/chattriggers/ctjs/api/message/TextComponent; -} - -public final class com/chattriggers/ctjs/api/render/Book { - public fun ()V - public final fun addPage (Lcom/chattriggers/ctjs/api/message/TextComponent;)Lcom/chattriggers/ctjs/api/render/Book; - public final fun addPage (Ljava/lang/String;)Lcom/chattriggers/ctjs/api/render/Book; - public final fun display ()V - public final fun display (I)V - public static synthetic fun display$default (Lcom/chattriggers/ctjs/api/render/Book;IILjava/lang/Object;)V - public final fun getCurrentPage ()I - public final fun insertPage (ILcom/chattriggers/ctjs/api/message/TextComponent;)Lcom/chattriggers/ctjs/api/render/Book; - public final fun insertPage (ILjava/lang/String;)Lcom/chattriggers/ctjs/api/render/Book; - public final fun isOpen ()Z - public final fun setPage (ILcom/chattriggers/ctjs/api/message/TextComponent;)Lcom/chattriggers/ctjs/api/render/Book; - public final fun setPage (ILjava/lang/String;)Lcom/chattriggers/ctjs/api/render/Book; -} - -public final class com/chattriggers/ctjs/api/render/Display { - public fun ()V - public fun (Lorg/mozilla/javascript/NativeObject;)V - public final fun addLine (Ljava/lang/Object;)Lcom/chattriggers/ctjs/api/render/Display; - public final fun addLines ([Ljava/lang/Object;)Lcom/chattriggers/ctjs/api/render/Display; - public final fun clearLines ()Lcom/chattriggers/ctjs/api/render/Display; - public final fun draw ()V - public final fun getAlign ()Lcom/chattriggers/ctjs/api/render/Text$Align; - public final fun getBackground ()Lcom/chattriggers/ctjs/api/render/Display$Background; - public final fun getBackgroundColor ()J - public final fun getHeight ()F - public final fun getLine (I)Lcom/chattriggers/ctjs/api/render/Text; - public final fun getLines ()Ljava/util/List; - public final fun getMinWidth ()F - public final fun getOrder ()Lcom/chattriggers/ctjs/api/render/Display$Order; - public final fun getTextColor ()J - public final fun getWidth ()F - public final fun getX ()F - public final fun getY ()F - public final fun removeLine (I)Lcom/chattriggers/ctjs/api/render/Display; - public final fun setAlign (Ljava/lang/Object;)Lcom/chattriggers/ctjs/api/render/Display; - public final fun setBackground (Ljava/lang/Object;)Lcom/chattriggers/ctjs/api/render/Display; - public final fun setBackgroundColor (J)Lcom/chattriggers/ctjs/api/render/Display; - public final fun setLine (ILjava/lang/Object;)Lcom/chattriggers/ctjs/api/render/Display; - public final fun setLines (Ljava/util/List;)Lcom/chattriggers/ctjs/api/render/Display; - public final fun setMinWidth (F)Lcom/chattriggers/ctjs/api/render/Display; - public final fun setOrder (Ljava/lang/Object;)Lcom/chattriggers/ctjs/api/render/Display; - public final fun setTextColor (J)Lcom/chattriggers/ctjs/api/render/Display; - public final fun setX (F)Lcom/chattriggers/ctjs/api/render/Display; - public final fun setY (F)Lcom/chattriggers/ctjs/api/render/Display; - public fun toString ()Ljava/lang/String; -} - -public final class com/chattriggers/ctjs/api/render/Display$Background : java/lang/Enum { - public static final field FULL Lcom/chattriggers/ctjs/api/render/Display$Background; - public static final field NONE Lcom/chattriggers/ctjs/api/render/Display$Background; - public static final field PER_LINE Lcom/chattriggers/ctjs/api/render/Display$Background; - public static fun getEntries ()Lkotlin/enums/EnumEntries; - public static fun valueOf (Ljava/lang/String;)Lcom/chattriggers/ctjs/api/render/Display$Background; - public static fun values ()[Lcom/chattriggers/ctjs/api/render/Display$Background; -} - -public final class com/chattriggers/ctjs/api/render/Display$Order : java/lang/Enum { - public static final field NORMAL Lcom/chattriggers/ctjs/api/render/Display$Order; - public static final field REVERSED Lcom/chattriggers/ctjs/api/render/Display$Order; - public static fun getEntries ()Lkotlin/enums/EnumEntries; - public static fun valueOf (Ljava/lang/String;)Lcom/chattriggers/ctjs/api/render/Display$Order; - public static fun values ()[Lcom/chattriggers/ctjs/api/render/Display$Order; -} - -public final class com/chattriggers/ctjs/api/render/Gui : gg/essential/universal/UScreen { - public fun ()V - public fun (Lcom/chattriggers/ctjs/api/message/TextComponent;)V - public synthetic fun (Lcom/chattriggers/ctjs/api/message/TextComponent;ILkotlin/jvm/internal/DefaultConstructorMarker;)V - public final fun addButton (IIIILcom/chattriggers/ctjs/api/message/TextComponent;)I - public final fun addButton (IIIILjava/lang/String;)I - public final fun addButton (IIILcom/chattriggers/ctjs/api/message/TextComponent;)I - public final fun addButton (IILcom/chattriggers/ctjs/api/message/TextComponent;)I - public final fun addButton (Lnet/minecraft/client/gui/widget/ButtonWidget;)I - public static synthetic fun addButton$default (Lcom/chattriggers/ctjs/api/render/Gui;IIIILcom/chattriggers/ctjs/api/message/TextComponent;ILjava/lang/Object;)I - public static synthetic fun addButton$default (Lcom/chattriggers/ctjs/api/render/Gui;IIIILjava/lang/String;ILjava/lang/Object;)I - public final fun clearButtons ()Lcom/chattriggers/ctjs/api/render/Gui; - public fun close ()V - public final fun getButtonEnabled (I)Z - public final fun getButtonHeight (I)I - public final fun getButtonVisibility (I)Z - public final fun getButtonWidth (I)I - public final fun getButtonX (I)I - public final fun getButtonY (I)I - public fun initScreen (II)V - public final fun isOpen ()Z - public fun onDrawScreen (Lgg/essential/universal/UMatrixStack;IIF)V - public fun onKeyPressed (ICLgg/essential/universal/UKeyboard$Modifiers;)V - public fun onMouseClicked (DDI)V - public fun onMouseDragged (DDIJ)V - public fun onMouseReleased (DDI)V - public fun onScreenClose ()V - public final fun open ()V - public final fun registerActionPerformed (Ljava/lang/Object;)Lcom/chattriggers/ctjs/api/render/Gui; - public final fun registerClicked (Ljava/lang/Object;)Lcom/chattriggers/ctjs/api/render/Gui; - public final fun registerClosed (Ljava/lang/Object;)Lcom/chattriggers/ctjs/api/render/Gui; - public final fun registerDraw (Ljava/lang/Object;)Lcom/chattriggers/ctjs/api/render/Gui; - public final fun registerKeyTyped (Ljava/lang/Object;)Lcom/chattriggers/ctjs/api/render/Gui; - public final fun registerMouseDragged (Ljava/lang/Object;)Lcom/chattriggers/ctjs/api/render/Gui; - public final fun registerMouseReleased (Ljava/lang/Object;)Lcom/chattriggers/ctjs/api/render/Gui; - public final fun registerOpened (Ljava/lang/Object;)Lcom/chattriggers/ctjs/api/render/Gui; - public final fun registerScrolled (Ljava/lang/Object;)Lcom/chattriggers/ctjs/api/render/Gui; - public final fun removeButton (I)Lcom/chattriggers/ctjs/api/render/Gui; - public final fun setButtonEnabled (IZ)Lcom/chattriggers/ctjs/api/render/Gui; - public final fun setButtonHeight (II)Lcom/chattriggers/ctjs/api/render/Gui; - public final fun setButtonLoc (III)Lcom/chattriggers/ctjs/api/render/Gui; - public final fun setButtonText (ILcom/chattriggers/ctjs/api/message/TextComponent;)Lcom/chattriggers/ctjs/api/render/Gui; - public final fun setButtonText (ILjava/lang/String;)Lcom/chattriggers/ctjs/api/render/Gui; - public final fun setButtonVisibility (IZ)Lcom/chattriggers/ctjs/api/render/Gui; - public final fun setButtonWidth (II)Lcom/chattriggers/ctjs/api/render/Gui; - public final fun setButtonX (II)Lcom/chattriggers/ctjs/api/render/Gui; - public final fun setButtonY (II)Lcom/chattriggers/ctjs/api/render/Gui; - public final fun setDoesPauseGame (Z)Lcom/chattriggers/ctjs/api/render/Gui; - public final fun setTooltip (Lcom/chattriggers/ctjs/api/message/TextComponent;)Lcom/chattriggers/ctjs/api/render/Gui; - public final fun setTooltip (Ljava/lang/String;)Lcom/chattriggers/ctjs/api/render/Gui; - public fun shouldPause ()Z - public final fun unregisterActionPerformed ()Lcom/chattriggers/ctjs/api/render/Gui; - public final fun unregisterClicked ()Lcom/chattriggers/ctjs/api/render/Gui; - public final fun unregisterClosed ()Lcom/chattriggers/ctjs/api/render/Gui; - public final fun unregisterDraw ()Lcom/chattriggers/ctjs/api/render/Gui; - public final fun unregisterKeyTyped ()Lcom/chattriggers/ctjs/api/render/Gui; - public final fun unregisterMouseDragged ()Lcom/chattriggers/ctjs/api/render/Gui; - public final fun unregisterMouseReleased ()Lcom/chattriggers/ctjs/api/render/Gui; - public final fun unregisterOpened ()Lcom/chattriggers/ctjs/api/render/Gui; - public final fun unregisterScrolled ()Lcom/chattriggers/ctjs/api/render/Gui; -} - -public final class com/chattriggers/ctjs/api/render/Image { - public static final field Companion Lcom/chattriggers/ctjs/api/render/Image$Companion; - public fun (Ljava/awt/image/BufferedImage;)V - public final fun destroy ()V - public final fun draw (FF)Lcom/chattriggers/ctjs/api/render/Image; - public final fun draw (FFLjava/lang/Float;)Lcom/chattriggers/ctjs/api/render/Image; - public final fun draw (FFLjava/lang/Float;Ljava/lang/Float;)Lcom/chattriggers/ctjs/api/render/Image; - public static synthetic fun draw$default (Lcom/chattriggers/ctjs/api/render/Image;FFLjava/lang/Float;Ljava/lang/Float;ILjava/lang/Object;)Lcom/chattriggers/ctjs/api/render/Image; - public static final fun fromAsset (Ljava/lang/String;)Lcom/chattriggers/ctjs/api/render/Image; - public static final fun fromFile (Ljava/io/File;)Lcom/chattriggers/ctjs/api/render/Image; - public static final fun fromFile (Ljava/lang/String;)Lcom/chattriggers/ctjs/api/render/Image; - public static final fun fromUrl (Ljava/lang/String;)Lcom/chattriggers/ctjs/api/render/Image; - public static final fun fromUrl (Ljava/lang/String;Ljava/lang/String;)Lcom/chattriggers/ctjs/api/render/Image; - public final fun getImage ()Ljava/awt/image/BufferedImage; - public final fun getTexture ()Lnet/minecraft/client/texture/NativeImageBackedTexture; - public final fun getTextureHeight ()I - public final fun getTextureWidth ()I - public final fun setImage (Ljava/awt/image/BufferedImage;)V -} - -public final class com/chattriggers/ctjs/api/render/Image$Companion { - public final fun fromAsset (Ljava/lang/String;)Lcom/chattriggers/ctjs/api/render/Image; - public final fun fromFile (Ljava/io/File;)Lcom/chattriggers/ctjs/api/render/Image; - public final fun fromFile (Ljava/lang/String;)Lcom/chattriggers/ctjs/api/render/Image; - public final fun fromUrl (Ljava/lang/String;)Lcom/chattriggers/ctjs/api/render/Image; - public final fun fromUrl (Ljava/lang/String;Ljava/lang/String;)Lcom/chattriggers/ctjs/api/render/Image; - public static synthetic fun fromUrl$default (Lcom/chattriggers/ctjs/api/render/Image$Companion;Ljava/lang/String;Ljava/lang/String;ILjava/lang/Object;)Lcom/chattriggers/ctjs/api/render/Image; -} - -public final class com/chattriggers/ctjs/api/render/Rectangle { - public fun (JFFFF)V - public final fun draw ()Lcom/chattriggers/ctjs/api/render/Rectangle; - public final fun getColor ()J - public final fun getHeight ()F - public final fun getOutline ()Z - public final fun getOutlineColor ()J - public final fun getShadowColor ()J - public final fun getShadowOffset ()Lcom/chattriggers/ctjs/api/vec/Vec2f; - public final fun getShadowOffsetX ()F - public final fun getShadowOffsetY ()F - public final fun getThickness ()F - public final fun getWidth ()F - public final fun getX ()F - public final fun getY ()F - public final fun isShadow ()Z - public final fun setColor (J)Lcom/chattriggers/ctjs/api/render/Rectangle; - public final fun setHeight (F)Lcom/chattriggers/ctjs/api/render/Rectangle; - public final fun setOutline (JF)Lcom/chattriggers/ctjs/api/render/Rectangle; - public final fun setOutline (Z)Lcom/chattriggers/ctjs/api/render/Rectangle; - public final fun setOutlineColor (J)Lcom/chattriggers/ctjs/api/render/Rectangle; - public final fun setShadow (JFF)Lcom/chattriggers/ctjs/api/render/Rectangle; - public final fun setShadow (Z)Lcom/chattriggers/ctjs/api/render/Rectangle; - public final fun setShadowColor (J)Lcom/chattriggers/ctjs/api/render/Rectangle; - public final fun setShadowOffset (FF)Lcom/chattriggers/ctjs/api/render/Rectangle; - public final fun setShadowOffsetX (F)Lcom/chattriggers/ctjs/api/render/Rectangle; - public final fun setShadowOffsetY (F)Lcom/chattriggers/ctjs/api/render/Rectangle; - public final fun setThickness (F)Lcom/chattriggers/ctjs/api/render/Rectangle; - public final fun setWidth (F)Lcom/chattriggers/ctjs/api/render/Rectangle; - public final fun setX (F)Lcom/chattriggers/ctjs/api/render/Rectangle; - public final fun setY (F)Lcom/chattriggers/ctjs/api/render/Rectangle; -} - -public final class com/chattriggers/ctjs/api/render/Renderer { - public static final field AQUA J - public static final field BLACK J - public static final field BLUE J - public static final field DARK_AQUA J - public static final field DARK_BLUE J - public static final field DARK_GRAY J - public static final field DARK_GREEN J - public static final field DARK_PURPLE J - public static final field DARK_RED J - public static final field GOLD J - public static final field GRAY J - public static final field GREEN J - public static final field INSTANCE Lcom/chattriggers/ctjs/api/render/Renderer; - public static final field LIGHT_PURPLE J - public static final field RED J - public static final field WHITE J - public static final field YELLOW J - public static field colorized Ljava/lang/Long; - public static final field screen Lcom/chattriggers/ctjs/api/render/Renderer$ScreenWrapper; - public static final fun begin ()Lcom/chattriggers/ctjs/api/render/Renderer; - public static final fun begin (Lcom/chattriggers/ctjs/api/render/Renderer$DrawMode;)Lcom/chattriggers/ctjs/api/render/Renderer; - public static final fun begin (Lcom/chattriggers/ctjs/api/render/Renderer$DrawMode;Lcom/chattriggers/ctjs/api/render/Renderer$VertexFormat;)Lcom/chattriggers/ctjs/api/render/Renderer; - public static synthetic fun begin$default (Lcom/chattriggers/ctjs/api/render/Renderer$DrawMode;Lcom/chattriggers/ctjs/api/render/Renderer$VertexFormat;ILjava/lang/Object;)Lcom/chattriggers/ctjs/api/render/Renderer; - public static final fun bindTexture (Lcom/chattriggers/ctjs/api/render/Image;)Lcom/chattriggers/ctjs/api/render/Renderer; - public static final fun bindTexture (Lcom/chattriggers/ctjs/api/render/Image;I)Lcom/chattriggers/ctjs/api/render/Renderer; - public static synthetic fun bindTexture$default (Lcom/chattriggers/ctjs/api/render/Image;IILjava/lang/Object;)Lcom/chattriggers/ctjs/api/render/Renderer; - public static final fun blendFunc (I)Lcom/chattriggers/ctjs/api/render/Renderer; - public static final fun color (FFF)Lcom/chattriggers/ctjs/api/render/Renderer; - public static final fun color (FFFF)Lcom/chattriggers/ctjs/api/render/Renderer; - public static final fun color (I)J - public static final fun color (III)Lcom/chattriggers/ctjs/api/render/Renderer; - public static final fun color (IIII)Lcom/chattriggers/ctjs/api/render/Renderer; - public static final fun color (J)Lcom/chattriggers/ctjs/api/render/Renderer; - public static synthetic fun color$default (FFFFILjava/lang/Object;)Lcom/chattriggers/ctjs/api/render/Renderer; - public static synthetic fun color$default (IIIIILjava/lang/Object;)Lcom/chattriggers/ctjs/api/render/Renderer; - public static final fun colorize (FFF)Lcom/chattriggers/ctjs/api/render/Renderer; - public static final fun colorize (FFFF)Lcom/chattriggers/ctjs/api/render/Renderer; - public static final fun colorize (III)Lcom/chattriggers/ctjs/api/render/Renderer; - public static final fun colorize (IIII)Lcom/chattriggers/ctjs/api/render/Renderer; - public static synthetic fun colorize$default (FFFFILjava/lang/Object;)Lcom/chattriggers/ctjs/api/render/Renderer; - public static synthetic fun colorize$default (IIIIILjava/lang/Object;)Lcom/chattriggers/ctjs/api/render/Renderer; - public static final fun deleteTexture (Lcom/chattriggers/ctjs/api/render/Image;)Lcom/chattriggers/ctjs/api/render/Renderer; - public static final fun depthFunc (I)Lcom/chattriggers/ctjs/api/render/Renderer; - public static final fun depthMask (Z)Lcom/chattriggers/ctjs/api/render/Renderer; - public static final fun disableBlend ()Lcom/chattriggers/ctjs/api/render/Renderer; - public static final fun disableCull ()Lcom/chattriggers/ctjs/api/render/Renderer; - public static final fun disableDepth ()Lcom/chattriggers/ctjs/api/render/Renderer; - public static final fun disableLighting ()Lcom/chattriggers/ctjs/api/render/Renderer; - public static final fun draw ()V - public static final fun drawCircle (JFFFI)V - public static final fun drawImage (Lcom/chattriggers/ctjs/api/render/Image;FFFF)V - public static final fun drawLine (JFFFFF)V - public static final fun drawPlayer (Lorg/mozilla/javascript/NativeObject;)V - public static final fun drawRect (JFFFF)Lcom/chattriggers/ctjs/api/render/Renderer; - public static final fun drawString (Ljava/lang/String;FF)V - public static final fun drawString (Ljava/lang/String;FFJ)V - public static final fun drawString (Ljava/lang/String;FFJZ)V - public static synthetic fun drawString$default (Ljava/lang/String;FFJZILjava/lang/Object;)V - public static final fun drawStringWithShadow (Ljava/lang/String;FF)V - public static final fun drawStringWithShadow (Ljava/lang/String;FFJ)V - public static synthetic fun drawStringWithShadow$default (Ljava/lang/String;FFJILjava/lang/Object;)V - public static final fun enableBlend ()Lcom/chattriggers/ctjs/api/render/Renderer; - public static final fun enableCull ()Lcom/chattriggers/ctjs/api/render/Renderer; - public static final fun enableDepth ()Lcom/chattriggers/ctjs/api/render/Renderer; - public static final fun enableLighting ()Lcom/chattriggers/ctjs/api/render/Renderer; - public static final fun fixAlpha (J)J - public static final fun getColor (III)J - public static final fun getColor (IIII)J - public static synthetic fun getColor$default (IIIIILjava/lang/Object;)J - public static final fun getFontRenderer ()Lnet/minecraft/client/font/TextRenderer; - public static final fun getPartialTicks ()F - public static final fun getRainbow (F)J - public static final fun getRainbow (FF)J - public static synthetic fun getRainbow$default (FFILjava/lang/Object;)J - public static final fun getRainbowColors (F)[I - public static final fun getRainbowColors (FF)[I - public static synthetic fun getRainbowColors$default (FFILjava/lang/Object;)[I - public static final fun getRenderManager ()Lnet/minecraft/client/render/WorldRenderer; - public static final fun getRenderPos (FFF)Lcom/chattriggers/ctjs/api/vec/Vec3f; - public static final fun getStringWidth (Ljava/lang/String;)I - public static final fun light (II)Lcom/chattriggers/ctjs/api/render/Renderer; - public static final fun lineWidth (F)Lcom/chattriggers/ctjs/api/render/Renderer; - public static final fun multiply (Lorg/joml/Quaternionf;)Lcom/chattriggers/ctjs/api/render/Renderer; - public static final fun normal (FFF)Lcom/chattriggers/ctjs/api/render/Renderer; - public static final fun overlay (II)Lcom/chattriggers/ctjs/api/render/Renderer; - public static final fun popMatrix ()Lcom/chattriggers/ctjs/api/render/Renderer; - public static final fun pos (FF)Lcom/chattriggers/ctjs/api/render/Renderer; - public static final fun pos (FFF)Lcom/chattriggers/ctjs/api/render/Renderer; - public static synthetic fun pos$default (FFFILjava/lang/Object;)Lcom/chattriggers/ctjs/api/render/Renderer; - public static final fun pushMatrix ()Lcom/chattriggers/ctjs/api/render/Renderer; - public static final fun pushMatrix (Lgg/essential/universal/UMatrixStack;)Lcom/chattriggers/ctjs/api/render/Renderer; - public static synthetic fun pushMatrix$default (Lgg/essential/universal/UMatrixStack;ILjava/lang/Object;)Lcom/chattriggers/ctjs/api/render/Renderer; - public static final fun rotate (F)Lcom/chattriggers/ctjs/api/render/Renderer; - public static final fun rotate (FF)Lcom/chattriggers/ctjs/api/render/Renderer; - public static final fun rotate (FFF)Lcom/chattriggers/ctjs/api/render/Renderer; - public static final fun rotate (FFFF)Lcom/chattriggers/ctjs/api/render/Renderer; - public static synthetic fun rotate$default (FFFFILjava/lang/Object;)Lcom/chattriggers/ctjs/api/render/Renderer; - public static final fun scale (F)Lcom/chattriggers/ctjs/api/render/Renderer; - public static final fun scale (FF)Lcom/chattriggers/ctjs/api/render/Renderer; - public static final fun scale (FFF)Lcom/chattriggers/ctjs/api/render/Renderer; - public static synthetic fun scale$default (FFFILjava/lang/Object;)Lcom/chattriggers/ctjs/api/render/Renderer; - public static final fun tex (FF)Lcom/chattriggers/ctjs/api/render/Renderer; - public static final fun translate (FF)Lcom/chattriggers/ctjs/api/render/Renderer; - public static final fun translate (FFF)Lcom/chattriggers/ctjs/api/render/Renderer; - public static synthetic fun translate$default (FFFILjava/lang/Object;)Lcom/chattriggers/ctjs/api/render/Renderer; - public static final fun tryBlendFuncSeparate (IIII)Lcom/chattriggers/ctjs/api/render/Renderer; -} - -public final class com/chattriggers/ctjs/api/render/Renderer$DrawMode : java/lang/Enum { - public static final field Companion Lcom/chattriggers/ctjs/api/render/Renderer$DrawMode$Companion; - public static final field LINES Lcom/chattriggers/ctjs/api/render/Renderer$DrawMode; - public static final field LINE_STRIP Lcom/chattriggers/ctjs/api/render/Renderer$DrawMode; - public static final field QUADS Lcom/chattriggers/ctjs/api/render/Renderer$DrawMode; - public static final field TRIANGLES Lcom/chattriggers/ctjs/api/render/Renderer$DrawMode; - public static final field TRIANGLE_FAN Lcom/chattriggers/ctjs/api/render/Renderer$DrawMode; - public static final field TRIANGLE_STRIP Lcom/chattriggers/ctjs/api/render/Renderer$DrawMode; - public static final fun fromUC (Lgg/essential/universal/UGraphics$DrawMode;)Lcom/chattriggers/ctjs/api/render/Renderer$DrawMode; - public static fun getEntries ()Lkotlin/enums/EnumEntries; - public final fun toUC ()Lgg/essential/universal/UGraphics$DrawMode; - public static fun valueOf (Ljava/lang/String;)Lcom/chattriggers/ctjs/api/render/Renderer$DrawMode; - public static fun values ()[Lcom/chattriggers/ctjs/api/render/Renderer$DrawMode; -} - -public final class com/chattriggers/ctjs/api/render/Renderer$DrawMode$Companion { - public final fun fromUC (Lgg/essential/universal/UGraphics$DrawMode;)Lcom/chattriggers/ctjs/api/render/Renderer$DrawMode; -} - -public final class com/chattriggers/ctjs/api/render/Renderer$ScreenWrapper { - public fun ()V - public final fun getHeight ()I - public final fun getScale ()D - public final fun getWidth ()I -} - -public final class com/chattriggers/ctjs/api/render/Renderer$VertexFormat : java/lang/Enum { - public static final field Companion Lcom/chattriggers/ctjs/api/render/Renderer$VertexFormat$Companion; - public static final field LINES Lcom/chattriggers/ctjs/api/render/Renderer$VertexFormat; - public static final field POSITION Lcom/chattriggers/ctjs/api/render/Renderer$VertexFormat; - public static final field POSITION_COLOR Lcom/chattriggers/ctjs/api/render/Renderer$VertexFormat; - public static final field POSITION_COLOR_TEXTURE_LIGHT Lcom/chattriggers/ctjs/api/render/Renderer$VertexFormat; - public static final field POSITION_TEXTURE Lcom/chattriggers/ctjs/api/render/Renderer$VertexFormat; - public static final field POSITION_TEXTURE_COLOR Lcom/chattriggers/ctjs/api/render/Renderer$VertexFormat; - public static final field POSITION_TEXTURE_COLOR_LIGHT Lcom/chattriggers/ctjs/api/render/Renderer$VertexFormat; - public static final field POSITION_TEXTURE_COLOR_NORMAL Lcom/chattriggers/ctjs/api/render/Renderer$VertexFormat; - public static final field POSITION_TEXTURE_LIGHT_COLOR Lcom/chattriggers/ctjs/api/render/Renderer$VertexFormat; - public static final fun fromMC (Lnet/minecraft/client/render/VertexFormat;)Lcom/chattriggers/ctjs/api/render/Renderer$VertexFormat; - public static fun getEntries ()Lkotlin/enums/EnumEntries; - public final fun toMC ()Lnet/minecraft/client/render/VertexFormat; - public static fun valueOf (Ljava/lang/String;)Lcom/chattriggers/ctjs/api/render/Renderer$VertexFormat; - public static fun values ()[Lcom/chattriggers/ctjs/api/render/Renderer$VertexFormat; -} - -public final class com/chattriggers/ctjs/api/render/Renderer$VertexFormat$Companion { - public final fun fromMC (Lnet/minecraft/client/render/VertexFormat;)Lcom/chattriggers/ctjs/api/render/Renderer$VertexFormat; -} - -public final class com/chattriggers/ctjs/api/render/Renderer3d { - public static final field INSTANCE Lcom/chattriggers/ctjs/api/render/Renderer3d; - public static final fun begin ()Lcom/chattriggers/ctjs/api/render/Renderer3d; - public static final fun begin (Lcom/chattriggers/ctjs/api/render/Renderer$DrawMode;)Lcom/chattriggers/ctjs/api/render/Renderer3d; - public static final fun begin (Lcom/chattriggers/ctjs/api/render/Renderer$DrawMode;Lcom/chattriggers/ctjs/api/render/Renderer$VertexFormat;)Lcom/chattriggers/ctjs/api/render/Renderer3d; - public static synthetic fun begin$default (Lcom/chattriggers/ctjs/api/render/Renderer$DrawMode;Lcom/chattriggers/ctjs/api/render/Renderer$VertexFormat;ILjava/lang/Object;)Lcom/chattriggers/ctjs/api/render/Renderer3d; - public static final fun color (FFF)Lcom/chattriggers/ctjs/api/render/Renderer3d; - public static final fun color (FFFF)Lcom/chattriggers/ctjs/api/render/Renderer3d; - public static final fun color (III)Lcom/chattriggers/ctjs/api/render/Renderer3d; - public static final fun color (IIII)Lcom/chattriggers/ctjs/api/render/Renderer3d; - public static final fun color (J)Lcom/chattriggers/ctjs/api/render/Renderer3d; - public static synthetic fun color$default (FFFFILjava/lang/Object;)Lcom/chattriggers/ctjs/api/render/Renderer3d; - public static synthetic fun color$default (IIIIILjava/lang/Object;)Lcom/chattriggers/ctjs/api/render/Renderer3d; - public static final fun draw ()V - public static final fun drawLine (JFFFFFFF)V - public static final fun drawString (Ljava/lang/String;FFF)V - public static final fun drawString (Ljava/lang/String;FFFJ)V - public static final fun drawString (Ljava/lang/String;FFFJZ)V - public static final fun drawString (Ljava/lang/String;FFFJZF)V - public static final fun drawString (Ljava/lang/String;FFFJZFZ)V - public static final fun drawString (Ljava/lang/String;FFFJZFZZ)V - public static final fun drawString (Ljava/lang/String;FFFJZFZZZ)V - public static final fun drawString (Lorg/mozilla/javascript/NativeObject;)V - public static synthetic fun drawString$default (Ljava/lang/String;FFFJZFZZZILjava/lang/Object;)V - public static final fun light (II)Lcom/chattriggers/ctjs/api/render/Renderer3d; - public static final fun lineWidth (F)Lcom/chattriggers/ctjs/api/render/Renderer3d; - public static final fun normal (FFF)Lcom/chattriggers/ctjs/api/render/Renderer3d; - public static final fun overlay (II)Lcom/chattriggers/ctjs/api/render/Renderer3d; - public static final fun pos (FFF)Lcom/chattriggers/ctjs/api/render/Renderer3d; - public static final fun tex (FF)Lcom/chattriggers/ctjs/api/render/Renderer3d; -} - -public final class com/chattriggers/ctjs/api/render/Shape { - public fun (J)V - public final fun addVertex (FF)Lcom/chattriggers/ctjs/api/render/Shape; - public final fun clearVertices ()Lcom/chattriggers/ctjs/api/render/Shape; - public final fun clone ()Lcom/chattriggers/ctjs/api/render/Shape; - public final fun copy ()Lcom/chattriggers/ctjs/api/render/Shape; - public final fun draw ()Lcom/chattriggers/ctjs/api/render/Shape; - public final fun getColor ()J - public final fun getDrawMode ()Lcom/chattriggers/ctjs/api/render/Renderer$DrawMode; - public final fun getVertexes ()Ljava/util/List; - public final fun insertVertex (IFF)Lcom/chattriggers/ctjs/api/render/Shape; - public final fun removeVertex (I)Lcom/chattriggers/ctjs/api/render/Shape; - public final fun setCircle (FFFI)Lcom/chattriggers/ctjs/api/render/Shape; - public final fun setColor (J)Lcom/chattriggers/ctjs/api/render/Shape; - public final fun setDrawMode (Lcom/chattriggers/ctjs/api/render/Renderer$DrawMode;)Lcom/chattriggers/ctjs/api/render/Shape; - public final fun setLine (FFFFF)Lcom/chattriggers/ctjs/api/render/Shape; -} - -public final class com/chattriggers/ctjs/api/render/Text { - public fun (Ljava/lang/String;)V - public fun (Ljava/lang/String;F)V - public fun (Ljava/lang/String;FF)V - public synthetic fun (Ljava/lang/String;FFILkotlin/jvm/internal/DefaultConstructorMarker;)V - public fun (Ljava/lang/String;Lorg/mozilla/javascript/NativeObject;)V - public final fun draw ()Lcom/chattriggers/ctjs/api/render/Text; - public final fun draw (Ljava/lang/Float;)Lcom/chattriggers/ctjs/api/render/Text; - public final fun draw (Ljava/lang/Float;Ljava/lang/Float;)Lcom/chattriggers/ctjs/api/render/Text; - public static synthetic fun draw$default (Lcom/chattriggers/ctjs/api/render/Text;Ljava/lang/Float;Ljava/lang/Float;ILjava/lang/Object;)Lcom/chattriggers/ctjs/api/render/Text; - public final fun exceedsMaxLines ()Z - public final fun getAlign ()Lcom/chattriggers/ctjs/api/render/Text$Align; - public final fun getBackground ()Z - public final fun getBackgroundColor ()J - public final fun getColor ()J - public final fun getFormatted ()Z - public final fun getHeight ()F - public final fun getLines ()Ljava/util/List; - public final fun getMaxLines ()I - public final fun getMaxWidth ()I - public final fun getScale ()F - public final fun getShadow ()Z - public final fun getString ()Ljava/lang/String; - public final fun getWidth ()F - public final fun getX ()F - public final fun getY ()F - public final fun setAlign (Ljava/lang/Object;)Lcom/chattriggers/ctjs/api/render/Text; - public final fun setBackground (Z)Lcom/chattriggers/ctjs/api/render/Text; - public final fun setBackgroundColor (J)Lcom/chattriggers/ctjs/api/render/Text; - public final fun setColor (J)Lcom/chattriggers/ctjs/api/render/Text; - public final fun setFormatted (Z)Lcom/chattriggers/ctjs/api/render/Text; - public final fun setMaxLines (I)Lcom/chattriggers/ctjs/api/render/Text; - public final fun setMaxWidth (I)Lcom/chattriggers/ctjs/api/render/Text; - public final fun setScale (F)Lcom/chattriggers/ctjs/api/render/Text; - public final fun setShadow (Z)Lcom/chattriggers/ctjs/api/render/Text; - public final fun setString (Ljava/lang/String;)Lcom/chattriggers/ctjs/api/render/Text; - public final fun setX (F)Lcom/chattriggers/ctjs/api/render/Text; - public final fun setY (F)Lcom/chattriggers/ctjs/api/render/Text; - public fun toString ()Ljava/lang/String; -} - -public final class com/chattriggers/ctjs/api/render/Text$Align : java/lang/Enum { - public static final field CENTER Lcom/chattriggers/ctjs/api/render/Text$Align; - public static final field LEFT Lcom/chattriggers/ctjs/api/render/Text$Align; - public static final field RIGHT Lcom/chattriggers/ctjs/api/render/Text$Align; - public static fun getEntries ()Lkotlin/enums/EnumEntries; - public static fun valueOf (Ljava/lang/String;)Lcom/chattriggers/ctjs/api/render/Text$Align; - public static fun values ()[Lcom/chattriggers/ctjs/api/render/Text$Align; -} - -public final class com/chattriggers/ctjs/api/render/Toast : net/minecraft/client/toast/Toast { - public fun (Lorg/mozilla/javascript/NativeObject;)V - public fun draw (Lnet/minecraft/client/gui/DrawContext;Lnet/minecraft/client/toast/ToastManager;J)Lnet/minecraft/client/toast/Toast$Visibility; - public final fun getBackground ()Ljava/lang/Object; - public final fun getDescription ()Ljava/lang/Object; - public final fun getDisplayTime ()J - public fun getHeight ()I - public final fun getIcon ()Ljava/lang/Object; - public final fun getTitle ()Ljava/lang/Object; - public fun getWidth ()I - public final fun setBackground (Ljava/lang/Object;)V - public final fun setDescription (Ljava/lang/Object;)V - public final fun setDisplayTime (J)V - public final fun setIcon (Ljava/lang/Object;)V - public final fun setTitle (Ljava/lang/Object;)V - public final fun show ()Lcom/chattriggers/ctjs/api/render/Toast; +public final class com/chattriggers/ctjs/api/Mappings { + public static final field INSTANCE Lcom/chattriggers/ctjs/api/Mappings; + public static final fun mapClassName (Ljava/lang/String;)Ljava/lang/String; + public static final fun unmapClass (Ljava/lang/Class;)Ljava/lang/String; + public static final fun unmapClassName (Ljava/lang/String;)Ljava/lang/String; } public class com/chattriggers/ctjs/api/triggers/CancellableEvent { @@ -1926,50 +140,6 @@ public class com/chattriggers/ctjs/api/triggers/CancellableEvent { public static synthetic fun setCancelled$default (Lcom/chattriggers/ctjs/api/triggers/CancellableEvent;ZILjava/lang/Object;)V } -public final class com/chattriggers/ctjs/api/triggers/ChatTrigger : com/chattriggers/ctjs/api/triggers/Trigger { - public fun (Ljava/lang/Object;Lcom/chattriggers/ctjs/api/triggers/ITriggerType;)V - public final fun addParameter (Ljava/lang/String;)Lcom/chattriggers/ctjs/api/triggers/ChatTrigger; - public final fun addParameters ([Ljava/lang/String;)Lcom/chattriggers/ctjs/api/triggers/ChatTrigger; - public final fun setCaseInsensitive ()Lcom/chattriggers/ctjs/api/triggers/ChatTrigger; - public final fun setChatCriteria (Ljava/lang/Object;)Lcom/chattriggers/ctjs/api/triggers/ChatTrigger; - public final fun setContains ()Lcom/chattriggers/ctjs/api/triggers/ChatTrigger; - public final fun setCriteria (Ljava/lang/Object;)Lcom/chattriggers/ctjs/api/triggers/ChatTrigger; - public final fun setEnd ()Lcom/chattriggers/ctjs/api/triggers/ChatTrigger; - public final fun setExact ()Lcom/chattriggers/ctjs/api/triggers/ChatTrigger; - public final fun setFormatted ()V - public final fun setFormatted (Z)V - public static synthetic fun setFormatted$default (Lcom/chattriggers/ctjs/api/triggers/ChatTrigger;ZILjava/lang/Object;)V - public final fun setParameter (Ljava/lang/String;)Lcom/chattriggers/ctjs/api/triggers/ChatTrigger; - public final fun setParameters ([Ljava/lang/String;)Lcom/chattriggers/ctjs/api/triggers/ChatTrigger; - public final fun setStart ()Lcom/chattriggers/ctjs/api/triggers/ChatTrigger; - public final fun triggerIfCanceled (Z)Lcom/chattriggers/ctjs/api/triggers/ChatTrigger; -} - -public final class com/chattriggers/ctjs/api/triggers/ChatTrigger$Event : com/chattriggers/ctjs/api/triggers/CancellableEvent { - public final field message Lcom/chattriggers/ctjs/api/message/TextComponent; - public fun (Lcom/chattriggers/ctjs/api/message/TextComponent;)V -} - -public abstract class com/chattriggers/ctjs/api/triggers/ClassFilterTrigger : com/chattriggers/ctjs/api/triggers/Trigger { - public synthetic fun (Ljava/lang/Object;Lcom/chattriggers/ctjs/api/triggers/ITriggerType;Ljava/lang/Class;Lkotlin/jvm/internal/DefaultConstructorMarker;)V - public final fun setFilteredClass (Ljava/lang/Class;)Lcom/chattriggers/ctjs/api/triggers/ClassFilterTrigger; - public final fun setFilteredClasses (Ljava/util/List;)Lcom/chattriggers/ctjs/api/triggers/ClassFilterTrigger; - protected abstract fun unwrap (Ljava/lang/Object;)Ljava/lang/Object; -} - -public final class com/chattriggers/ctjs/api/triggers/CommandTrigger : com/chattriggers/ctjs/api/triggers/Trigger { - public fun (Ljava/lang/Object;)V - public final fun setAliases ([Ljava/lang/String;)Lcom/chattriggers/ctjs/api/triggers/CommandTrigger; - public final fun setCommandName (Ljava/lang/String;)Lcom/chattriggers/ctjs/api/triggers/CommandTrigger; - public final fun setCommandName (Ljava/lang/String;Z)Lcom/chattriggers/ctjs/api/triggers/CommandTrigger; - public static synthetic fun setCommandName$default (Lcom/chattriggers/ctjs/api/triggers/CommandTrigger;Ljava/lang/String;ZILjava/lang/Object;)Lcom/chattriggers/ctjs/api/triggers/CommandTrigger; - public final fun setName (Ljava/lang/String;)Lcom/chattriggers/ctjs/api/triggers/CommandTrigger; - public final fun setName (Ljava/lang/String;Z)Lcom/chattriggers/ctjs/api/triggers/CommandTrigger; - public static synthetic fun setName$default (Lcom/chattriggers/ctjs/api/triggers/CommandTrigger;Ljava/lang/String;ZILjava/lang/Object;)Lcom/chattriggers/ctjs/api/triggers/CommandTrigger; - public final fun setTabCompletions (Lkotlin/jvm/functions/Function1;)Lcom/chattriggers/ctjs/api/triggers/CommandTrigger; - public final fun setTabCompletions ([Ljava/lang/String;)Lcom/chattriggers/ctjs/api/triggers/CommandTrigger; -} - public final class com/chattriggers/ctjs/api/triggers/CustomTriggerType : com/chattriggers/ctjs/api/triggers/ITriggerType { public fun (Ljava/lang/String;)V public final fun component1 ()Ljava/lang/String; @@ -1996,37 +166,10 @@ public final class com/chattriggers/ctjs/api/triggers/ITriggerType$DefaultImpls public static fun triggerAll (Lcom/chattriggers/ctjs/api/triggers/ITriggerType;[Ljava/lang/Object;)V } -public final class com/chattriggers/ctjs/api/triggers/PacketTrigger : com/chattriggers/ctjs/api/triggers/ClassFilterTrigger { - public fun (Ljava/lang/Object;Lcom/chattriggers/ctjs/api/triggers/ITriggerType;)V - public synthetic fun unwrap (Ljava/lang/Object;)Ljava/lang/Object; -} - public final class com/chattriggers/ctjs/api/triggers/RegularTrigger : com/chattriggers/ctjs/api/triggers/Trigger { public fun (Ljava/lang/Object;Lcom/chattriggers/ctjs/api/triggers/ITriggerType;)V } -public final class com/chattriggers/ctjs/api/triggers/RenderBlockEntityTrigger : com/chattriggers/ctjs/api/triggers/ClassFilterTrigger { - public fun (Ljava/lang/Object;)V - public synthetic fun unwrap (Ljava/lang/Object;)Ljava/lang/Object; -} - -public final class com/chattriggers/ctjs/api/triggers/RenderEntityTrigger : com/chattriggers/ctjs/api/triggers/ClassFilterTrigger { - public fun (Ljava/lang/Object;)V - public synthetic fun unwrap (Ljava/lang/Object;)Ljava/lang/Object; -} - -public final class com/chattriggers/ctjs/api/triggers/SoundPlayTrigger : com/chattriggers/ctjs/api/triggers/Trigger { - public fun (Ljava/lang/Object;)V - public final fun setCriteria (Ljava/lang/String;)Lcom/chattriggers/ctjs/api/triggers/SoundPlayTrigger; -} - -public final class com/chattriggers/ctjs/api/triggers/StepTrigger : com/chattriggers/ctjs/api/triggers/Trigger { - public fun (Ljava/lang/Object;)V - public fun register ()Lcom/chattriggers/ctjs/api/triggers/Trigger; - public final fun setDelay (J)Lcom/chattriggers/ctjs/api/triggers/StepTrigger; - public final fun setFps (J)Lcom/chattriggers/ctjs/api/triggers/StepTrigger; -} - public abstract class com/chattriggers/ctjs/api/triggers/Trigger : java/lang/Comparable { protected fun (Ljava/lang/Object;Lcom/chattriggers/ctjs/api/triggers/ITriggerType;)V protected final fun callMethod ([Ljava/lang/Object;)V @@ -2055,44 +198,10 @@ public final class com/chattriggers/ctjs/api/triggers/Trigger$Priority : java/la public final class com/chattriggers/ctjs/api/triggers/TriggerType : java/lang/Enum, com/chattriggers/ctjs/api/triggers/ITriggerType { public static final field ACTION_BAR Lcom/chattriggers/ctjs/api/triggers/TriggerType; - public static final field BLOCK_HIGHLIGHT Lcom/chattriggers/ctjs/api/triggers/TriggerType; public static final field CHAT Lcom/chattriggers/ctjs/api/triggers/TriggerType; - public static final field CLICKED Lcom/chattriggers/ctjs/api/triggers/TriggerType; - public static final field COMMAND Lcom/chattriggers/ctjs/api/triggers/TriggerType; - public static final field DRAGGED Lcom/chattriggers/ctjs/api/triggers/TriggerType; - public static final field DROP_ITEM Lcom/chattriggers/ctjs/api/triggers/TriggerType; - public static final field ENTITY_DAMAGE Lcom/chattriggers/ctjs/api/triggers/TriggerType; - public static final field ENTITY_DEATH Lcom/chattriggers/ctjs/api/triggers/TriggerType; - public static final field GAME_LOAD Lcom/chattriggers/ctjs/api/triggers/TriggerType; - public static final field GAME_UNLOAD Lcom/chattriggers/ctjs/api/triggers/TriggerType; - public static final field GUI_CLOSED Lcom/chattriggers/ctjs/api/triggers/TriggerType; - public static final field GUI_KEY Lcom/chattriggers/ctjs/api/triggers/TriggerType; - public static final field GUI_MOUSE_CLICK Lcom/chattriggers/ctjs/api/triggers/TriggerType; - public static final field GUI_MOUSE_DRAG Lcom/chattriggers/ctjs/api/triggers/TriggerType; - public static final field GUI_OPENED Lcom/chattriggers/ctjs/api/triggers/TriggerType; - public static final field GUI_RENDER Lcom/chattriggers/ctjs/api/triggers/TriggerType; - public static final field ITEM_TOOLTIP Lcom/chattriggers/ctjs/api/triggers/TriggerType; public static final field MESSAGE_SENT Lcom/chattriggers/ctjs/api/triggers/TriggerType; - public static final field OTHER Lcom/chattriggers/ctjs/api/triggers/TriggerType; - public static final field PACKET_RECEIVED Lcom/chattriggers/ctjs/api/triggers/TriggerType; - public static final field PACKET_SENT Lcom/chattriggers/ctjs/api/triggers/TriggerType; - public static final field PLAYER_INTERACT Lcom/chattriggers/ctjs/api/triggers/TriggerType; - public static final field POST_GUI_RENDER Lcom/chattriggers/ctjs/api/triggers/TriggerType; - public static final field POST_RENDER_WORLD Lcom/chattriggers/ctjs/api/triggers/TriggerType; - public static final field PRE_RENDER_WORLD Lcom/chattriggers/ctjs/api/triggers/TriggerType; - public static final field RENDER_BLOCK_ENTITY Lcom/chattriggers/ctjs/api/triggers/TriggerType; - public static final field RENDER_ENTITY Lcom/chattriggers/ctjs/api/triggers/TriggerType; public static final field RENDER_OVERLAY Lcom/chattriggers/ctjs/api/triggers/TriggerType; - public static final field RENDER_PLAYER_LIST Lcom/chattriggers/ctjs/api/triggers/TriggerType; - public static final field SCROLLED Lcom/chattriggers/ctjs/api/triggers/TriggerType; - public static final field SERVER_CONNECT Lcom/chattriggers/ctjs/api/triggers/TriggerType; - public static final field SERVER_DISCONNECT Lcom/chattriggers/ctjs/api/triggers/TriggerType; - public static final field SOUND_PLAY Lcom/chattriggers/ctjs/api/triggers/TriggerType; - public static final field SPAWN_PARTICLE Lcom/chattriggers/ctjs/api/triggers/TriggerType; - public static final field STEP Lcom/chattriggers/ctjs/api/triggers/TriggerType; public static final field TICK Lcom/chattriggers/ctjs/api/triggers/TriggerType; - public static final field WORLD_LOAD Lcom/chattriggers/ctjs/api/triggers/TriggerType; - public static final field WORLD_UNLOAD Lcom/chattriggers/ctjs/api/triggers/TriggerType; public static fun getEntries ()Lkotlin/enums/EnumEntries; public synthetic fun getName ()Ljava/lang/String; public fun triggerAll ([Ljava/lang/Object;)V @@ -2100,556 +209,6 @@ public final class com/chattriggers/ctjs/api/triggers/TriggerType : java/lang/En public static fun values ()[Lcom/chattriggers/ctjs/api/triggers/TriggerType; } -public final class com/chattriggers/ctjs/api/vec/Vec2f { - public fun ()V - public fun (F)V - public fun (FF)V - public synthetic fun (FFILkotlin/jvm/internal/DefaultConstructorMarker;)V - public final fun angleTo (Lcom/chattriggers/ctjs/api/vec/Vec2f;)F - public final fun component1 ()F - public final fun component2 ()F - public final fun copy (FF)Lcom/chattriggers/ctjs/api/vec/Vec2f; - public static synthetic fun copy$default (Lcom/chattriggers/ctjs/api/vec/Vec2f;FFILjava/lang/Object;)Lcom/chattriggers/ctjs/api/vec/Vec2f; - public final fun dotProduct (Lcom/chattriggers/ctjs/api/vec/Vec2f;)F - public fun equals (Ljava/lang/Object;)Z - public final fun getX ()F - public final fun getY ()F - public fun hashCode ()I - public final fun magnitude ()F - public final fun magnitudeSquared ()F - public final fun minus (Lcom/chattriggers/ctjs/api/vec/Vec2f;)Lcom/chattriggers/ctjs/api/vec/Vec2f; - public final fun normalized ()Lcom/chattriggers/ctjs/api/vec/Vec2f; - public final fun plus (Lcom/chattriggers/ctjs/api/vec/Vec2f;)Lcom/chattriggers/ctjs/api/vec/Vec2f; - public final fun scaled (F)Lcom/chattriggers/ctjs/api/vec/Vec2f; - public final fun scaled (FF)Lcom/chattriggers/ctjs/api/vec/Vec2f; - public fun toString ()Ljava/lang/String; - public final fun translated (FF)Lcom/chattriggers/ctjs/api/vec/Vec2f; - public final fun unaryMinus ()Lcom/chattriggers/ctjs/api/vec/Vec2f; -} - -public final class com/chattriggers/ctjs/api/vec/Vec3f { - public fun ()V - public fun (F)V - public fun (FF)V - public fun (FFF)V - public synthetic fun (FFFILkotlin/jvm/internal/DefaultConstructorMarker;)V - public final fun angleTo (Lcom/chattriggers/ctjs/api/vec/Vec3f;)F - public final fun component1 ()F - public final fun component2 ()F - public final fun component3 ()F - public final fun copy (FFF)Lcom/chattriggers/ctjs/api/vec/Vec3f; - public static synthetic fun copy$default (Lcom/chattriggers/ctjs/api/vec/Vec3f;FFFILjava/lang/Object;)Lcom/chattriggers/ctjs/api/vec/Vec3f; - public final fun crossProduct (Lcom/chattriggers/ctjs/api/vec/Vec3f;)Lcom/chattriggers/ctjs/api/vec/Vec3f; - public final fun dotProduct (Lcom/chattriggers/ctjs/api/vec/Vec3f;)F - public fun equals (Ljava/lang/Object;)Z - public final fun getX ()F - public final fun getY ()F - public final fun getZ ()F - public fun hashCode ()I - public final fun magnitude ()F - public final fun magnitudeSquared ()F - public final fun minus (Lcom/chattriggers/ctjs/api/vec/Vec3f;)Lcom/chattriggers/ctjs/api/vec/Vec3f; - public final fun normalized ()Lcom/chattriggers/ctjs/api/vec/Vec3f; - public final fun plus (Lcom/chattriggers/ctjs/api/vec/Vec3f;)Lcom/chattriggers/ctjs/api/vec/Vec3f; - public final fun scaled (F)Lcom/chattriggers/ctjs/api/vec/Vec3f; - public final fun scaled (FFF)Lcom/chattriggers/ctjs/api/vec/Vec3f; - public fun toString ()Ljava/lang/String; - public final fun translated (FFF)Lcom/chattriggers/ctjs/api/vec/Vec3f; - public final fun unaryMinus ()Lcom/chattriggers/ctjs/api/vec/Vec3f; -} - -public class com/chattriggers/ctjs/api/vec/Vec3i { - public fun ()V - public fun (I)V - public fun (II)V - public fun (III)V - public synthetic fun (IIIILkotlin/jvm/internal/DefaultConstructorMarker;)V - public final fun angleTo (Lcom/chattriggers/ctjs/api/vec/Vec3i;)F - public fun crossProduct (Lcom/chattriggers/ctjs/api/vec/Vec3i;)Lcom/chattriggers/ctjs/api/vec/Vec3i; - public final fun dotProduct (Lcom/chattriggers/ctjs/api/vec/Vec3i;)I - public fun equals (Ljava/lang/Object;)Z - public final fun getX ()I - public final fun getY ()I - public final fun getZ ()I - public fun hashCode ()I - public final fun magnitude ()F - public final fun magnitudeSquared ()I - public fun minus (Lcom/chattriggers/ctjs/api/vec/Vec3i;)Lcom/chattriggers/ctjs/api/vec/Vec3i; - public final fun normalized ()Lcom/chattriggers/ctjs/api/vec/Vec3f; - public fun plus (Lcom/chattriggers/ctjs/api/vec/Vec3i;)Lcom/chattriggers/ctjs/api/vec/Vec3i; - public fun scaled (I)Lcom/chattriggers/ctjs/api/vec/Vec3i; - public fun scaled (III)Lcom/chattriggers/ctjs/api/vec/Vec3i; - public fun toString ()Ljava/lang/String; - public fun translated (III)Lcom/chattriggers/ctjs/api/vec/Vec3i; - public fun unaryMinus ()Lcom/chattriggers/ctjs/api/vec/Vec3i; -} - -public final class com/chattriggers/ctjs/api/world/BossBars { - public static final field INSTANCE Lcom/chattriggers/ctjs/api/world/BossBars; - public static final fun addBossBar (Lorg/mozilla/javascript/NativeObject;)Lcom/chattriggers/ctjs/api/world/BossBars$BossBar; - public static final fun clearBossBars ()V - public static final fun getBossBars ()Ljava/util/List; - public static final fun getBossBarsByName (Ljava/lang/String;)Ljava/util/List; - public static final fun removeBossBar (Lcom/chattriggers/ctjs/api/world/BossBars$BossBar;)V - public static final fun removeBossBarsByName (Ljava/lang/String;)V - public static final fun toMC ()Lnet/minecraft/client/gui/hud/BossBarHud; -} - -public final class com/chattriggers/ctjs/api/world/BossBars$BossBar : com/chattriggers/ctjs/api/CTWrapper { - public fun (Lnet/minecraft/client/gui/hud/ClientBossBar;)V - public final fun getColor ()Lcom/chattriggers/ctjs/api/world/BossBars$Color; - public synthetic fun getMcValue ()Ljava/lang/Object; - public fun getMcValue ()Lnet/minecraft/client/gui/hud/ClientBossBar; - public final fun getName ()Ljava/lang/String; - public final fun getPercent ()F - public final fun getStyle ()Lcom/chattriggers/ctjs/api/world/BossBars$Style; - public final fun getUUID ()Ljava/util/UUID; - public final fun hasDragonMusic ()Z - public final fun setColor (Ljava/lang/Object;)Lcom/chattriggers/ctjs/api/world/BossBars$BossBar; - public final fun setHasDragonMusic (Z)Lcom/chattriggers/ctjs/api/world/BossBars$BossBar; - public final fun setName (Ljava/lang/String;)Lcom/chattriggers/ctjs/api/world/BossBars$BossBar; - public final fun setPercent (F)Lcom/chattriggers/ctjs/api/world/BossBars$BossBar; - public final fun setShouldDarkenSky (Z)Lcom/chattriggers/ctjs/api/world/BossBars$BossBar; - public final fun setShouldThickenFog (Z)Lcom/chattriggers/ctjs/api/world/BossBars$BossBar; - public final fun setStyle (Ljava/lang/Object;)Lcom/chattriggers/ctjs/api/world/BossBars$BossBar; - public final fun shouldDarkenSky ()Z - public final fun shouldThickenFog ()Z - public synthetic fun toMC ()Ljava/lang/Object; - public fun toMC ()Lnet/minecraft/client/gui/hud/ClientBossBar; - public fun toString ()Ljava/lang/String; -} - -public final class com/chattriggers/ctjs/api/world/BossBars$Color : java/lang/Enum, com/chattriggers/ctjs/api/CTWrapper { - public static final field BLUE Lcom/chattriggers/ctjs/api/world/BossBars$Color; - public static final field Companion Lcom/chattriggers/ctjs/api/world/BossBars$Color$Companion; - public static final field GREEN Lcom/chattriggers/ctjs/api/world/BossBars$Color; - public static final field PINK Lcom/chattriggers/ctjs/api/world/BossBars$Color; - public static final field PURPLE Lcom/chattriggers/ctjs/api/world/BossBars$Color; - public static final field RED Lcom/chattriggers/ctjs/api/world/BossBars$Color; - public static final field WHITE Lcom/chattriggers/ctjs/api/world/BossBars$Color; - public static final field YELLOW Lcom/chattriggers/ctjs/api/world/BossBars$Color; - public static final fun from (Ljava/lang/Object;)Lcom/chattriggers/ctjs/api/world/BossBars$Color; - public static final fun fromMC (Lnet/minecraft/entity/boss/BossBar$Color;)Lcom/chattriggers/ctjs/api/world/BossBars$Color; - public static fun getEntries ()Lkotlin/enums/EnumEntries; - public synthetic fun getMcValue ()Ljava/lang/Object; - public fun getMcValue ()Lnet/minecraft/entity/boss/BossBar$Color; - public synthetic fun toMC ()Ljava/lang/Object; - public fun toMC ()Lnet/minecraft/entity/boss/BossBar$Color; - public static fun valueOf (Ljava/lang/String;)Lcom/chattriggers/ctjs/api/world/BossBars$Color; - public static fun values ()[Lcom/chattriggers/ctjs/api/world/BossBars$Color; -} - -public final class com/chattriggers/ctjs/api/world/BossBars$Color$Companion { - public final fun from (Ljava/lang/Object;)Lcom/chattriggers/ctjs/api/world/BossBars$Color; - public final fun fromMC (Lnet/minecraft/entity/boss/BossBar$Color;)Lcom/chattriggers/ctjs/api/world/BossBars$Color; -} - -public final class com/chattriggers/ctjs/api/world/BossBars$Style : java/lang/Enum, com/chattriggers/ctjs/api/CTWrapper { - public static final field Companion Lcom/chattriggers/ctjs/api/world/BossBars$Style$Companion; - public static final field ONE Lcom/chattriggers/ctjs/api/world/BossBars$Style; - public static final field SIX Lcom/chattriggers/ctjs/api/world/BossBars$Style; - public static final field TEN Lcom/chattriggers/ctjs/api/world/BossBars$Style; - public static final field TWELVE Lcom/chattriggers/ctjs/api/world/BossBars$Style; - public static final field TWENTY Lcom/chattriggers/ctjs/api/world/BossBars$Style; - public static final fun from (Ljava/lang/Object;)Lcom/chattriggers/ctjs/api/world/BossBars$Style; - public static final fun fromMC (Lnet/minecraft/entity/boss/BossBar$Style;)Lcom/chattriggers/ctjs/api/world/BossBars$Style; - public static fun getEntries ()Lkotlin/enums/EnumEntries; - public synthetic fun getMcValue ()Ljava/lang/Object; - public fun getMcValue ()Lnet/minecraft/entity/boss/BossBar$Style; - public final fun getSections ()I - public synthetic fun toMC ()Ljava/lang/Object; - public fun toMC ()Lnet/minecraft/entity/boss/BossBar$Style; - public static fun valueOf (Ljava/lang/String;)Lcom/chattriggers/ctjs/api/world/BossBars$Style; - public static fun values ()[Lcom/chattriggers/ctjs/api/world/BossBars$Style; -} - -public final class com/chattriggers/ctjs/api/world/BossBars$Style$Companion { - public final fun from (Ljava/lang/Object;)Lcom/chattriggers/ctjs/api/world/BossBars$Style; - public final fun fromMC (Lnet/minecraft/entity/boss/BossBar$Style;)Lcom/chattriggers/ctjs/api/world/BossBars$Style; -} - -public final class com/chattriggers/ctjs/api/world/Chunk : com/chattriggers/ctjs/api/CTWrapper { - public fun (Lnet/minecraft/world/chunk/Chunk;)V - public final fun getAllBlockEntities ()Ljava/util/List; - public final fun getAllBlockEntitiesOfType (Ljava/lang/Class;)Ljava/util/List; - public final fun getAllEntities ()Ljava/util/List; - public final fun getAllEntitiesOfType (Ljava/lang/Class;)Ljava/util/List; - public synthetic fun getMcValue ()Ljava/lang/Object; - public fun getMcValue ()Lnet/minecraft/world/chunk/Chunk; - public final fun getMinBlockX ()I - public final fun getMinBlockZ ()I - public final fun getX ()I - public final fun getZ ()I - public synthetic fun toMC ()Ljava/lang/Object; - public fun toMC ()Lnet/minecraft/world/chunk/Chunk; -} - -public final class com/chattriggers/ctjs/api/world/PotionEffect { - public fun (Lnet/minecraft/entity/effect/StatusEffectInstance;)V - public final fun getAmbient ()Z - public final fun getAmplifier ()I - public final fun getDuration ()I - public final fun getEffect ()Lnet/minecraft/entity/effect/StatusEffectInstance; - public final fun getId ()I - public final fun getLocalizedName ()Ljava/lang/String; - public final fun getName ()Ljava/lang/String; - public final fun getShowsParticles ()Z - public final fun getType ()Lcom/chattriggers/ctjs/api/world/PotionEffectType; - public final fun isInfinite ()Z - public fun toString ()Ljava/lang/String; -} - -public final class com/chattriggers/ctjs/api/world/PotionEffectType { - public fun (Lnet/minecraft/entity/effect/StatusEffect;)V - public final fun getCategory ()Lnet/minecraft/entity/effect/StatusEffectCategory; - public final fun getColor ()Ljava/awt/Color; - public final fun getName ()Lcom/chattriggers/ctjs/api/message/TextComponent; - public final fun getRawId ()I - public final fun getTranslationKey ()Ljava/lang/String; - public final fun getType ()Lnet/minecraft/entity/effect/StatusEffect; - public final fun isInstant ()Z -} - -public final class com/chattriggers/ctjs/api/world/Scoreboard { - public static final field INSTANCE Lcom/chattriggers/ctjs/api/world/Scoreboard; - public static final fun addLine (ILcom/chattriggers/ctjs/api/message/TextComponent;)V - public static final fun addLine (ILjava/lang/String;)V - public static final fun createTeam (Ljava/lang/String;)Lcom/chattriggers/ctjs/api/entity/Team; - public static final fun getLineByIndex (I)Lcom/chattriggers/ctjs/api/world/Scoreboard$Score; - public static final fun getLines ()Ljava/util/List; - public static final fun getLines (Z)Ljava/util/List; - public static synthetic fun getLines$default (ZILjava/lang/Object;)Ljava/util/List; - public static final fun getLinesByScore (I)Ljava/util/List; - public static final fun getScoreboard ()Lnet/minecraft/scoreboard/Scoreboard; - public static final fun getShouldRender ()Z - public static final fun getSidebar ()Lnet/minecraft/scoreboard/ScoreboardObjective; - public static final fun getTitle ()Lcom/chattriggers/ctjs/api/message/TextComponent; - public static final fun removeIndex (I)V - public static final fun removeIndex (IZ)V - public static synthetic fun removeIndex$default (IZILjava/lang/Object;)V - public static final fun removeScores (I)V - public static final fun setLine (ILcom/chattriggers/ctjs/api/message/TextComponent;)V - public static final fun setLine (ILcom/chattriggers/ctjs/api/message/TextComponent;Z)V - public static final fun setLine (ILjava/lang/String;)V - public static final fun setLine (ILjava/lang/String;Z)V - public static synthetic fun setLine$default (ILcom/chattriggers/ctjs/api/message/TextComponent;ZILjava/lang/Object;)V - public static synthetic fun setLine$default (ILjava/lang/String;ZILjava/lang/Object;)V - public static final fun setShouldRender (Z)V - public static final fun setTitle (Lcom/chattriggers/ctjs/api/message/TextComponent;)V - public static final fun setTitle (Ljava/lang/String;)V - public static final fun toMC ()Lnet/minecraft/scoreboard/Scoreboard; -} - -public final class com/chattriggers/ctjs/api/world/Scoreboard$Score : com/chattriggers/ctjs/api/CTWrapper { - public fun (Lnet/minecraft/scoreboard/ScoreAccess;)V - public synthetic fun getMcValue ()Ljava/lang/Object; - public fun getMcValue ()Lnet/minecraft/scoreboard/ScoreAccess; - public final fun getName ()Lcom/chattriggers/ctjs/api/message/TextComponent; - public final fun getNumberFormat ()Lnet/minecraft/scoreboard/number/NumberFormat; - public final fun getScore ()I - public final fun getTeam ()Lcom/chattriggers/ctjs/api/entity/Team; - public final fun remove ()V - public final fun setName (Lcom/chattriggers/ctjs/api/message/TextComponent;)Lcom/chattriggers/ctjs/api/world/Scoreboard$Score; - public final fun setNumberFormat (Ljava/lang/Object;)Lcom/chattriggers/ctjs/api/world/Scoreboard$Score; - public final fun setScore (I)Lcom/chattriggers/ctjs/api/world/Scoreboard$Score; - public final fun setTeam (Lcom/chattriggers/ctjs/api/entity/Team;)Lcom/chattriggers/ctjs/api/world/Scoreboard$Score; - public synthetic fun toMC ()Ljava/lang/Object; - public fun toMC ()Lnet/minecraft/scoreboard/ScoreAccess; - public fun toString ()Ljava/lang/String; -} - -public final class com/chattriggers/ctjs/api/world/Server { - public static final field INSTANCE Lcom/chattriggers/ctjs/api/world/Server; - public static final fun getIP ()Ljava/lang/String; - public static final fun getMOTD ()Ljava/lang/String; - public static final fun getName ()Ljava/lang/String; - public static final fun getPing ()J - public static final fun isSingleplayer ()Z - public static final fun toMC ()Lnet/minecraft/client/network/ServerInfo; -} - -public final class com/chattriggers/ctjs/api/world/TabList { - public static final field INSTANCE Lcom/chattriggers/ctjs/api/world/TabList; - public static final fun addName (Lcom/chattriggers/ctjs/api/message/TextComponent;)V - public static final fun addName (Lcom/chattriggers/ctjs/api/message/TextComponent;Z)V - public static final fun addName (Ljava/lang/String;)V - public static final fun addName (Ljava/lang/String;Z)V - public static synthetic fun addName$default (Lcom/chattriggers/ctjs/api/message/TextComponent;ZILjava/lang/Object;)V - public static synthetic fun addName$default (Ljava/lang/String;ZILjava/lang/Object;)V - public static final fun clearFooter ()V - public static final fun clearHeader ()V - public static final fun getFooter ()Ljava/lang/String; - public static final fun getFooterComponent ()Lcom/chattriggers/ctjs/api/message/TextComponent; - public static final fun getHeader ()Ljava/lang/String; - public static final fun getHeaderComponent ()Lcom/chattriggers/ctjs/api/message/TextComponent; - public static final fun getNames ()Ljava/util/List; - public static final fun getNamesByObjectives ()Ljava/util/List; - public static final fun getObjective ()Lnet/minecraft/scoreboard/ScoreboardObjective; - public static final fun getUnformattedNames ()Ljava/util/List; - public static final fun removeNames (Lcom/chattriggers/ctjs/api/message/TextComponent;)V - public static final fun removeNames (Ljava/lang/String;)V - public static final fun setFooter (Ljava/lang/Object;)V - public static final fun setHeader (Ljava/lang/Object;)V - public static final fun toMC ()Lnet/minecraft/client/gui/hud/PlayerListHud; -} - -public final class com/chattriggers/ctjs/api/world/TabList$Name : com/chattriggers/ctjs/api/CTWrapper { - public fun (Lnet/minecraft/client/network/PlayerListEntry;)V - public final fun getLatency ()I - public synthetic fun getMcValue ()Ljava/lang/Object; - public fun getMcValue ()Lnet/minecraft/client/network/PlayerListEntry; - public final fun getName ()Lcom/chattriggers/ctjs/api/message/TextComponent; - public final fun getTeam ()Lcom/chattriggers/ctjs/api/entity/Team; - public final fun remove ()V - public final fun setLatency (I)Lcom/chattriggers/ctjs/api/world/TabList$Name; - public final fun setName (Lcom/chattriggers/ctjs/api/message/TextComponent;)Lcom/chattriggers/ctjs/api/world/TabList$Name; - public final fun setTeam (Lcom/chattriggers/ctjs/api/entity/Team;)Lcom/chattriggers/ctjs/api/world/TabList$Name; - public synthetic fun toMC ()Ljava/lang/Object; - public fun toMC ()Lnet/minecraft/client/network/PlayerListEntry; - public fun toString ()Ljava/lang/String; -} - -public final class com/chattriggers/ctjs/api/world/World { - public static final field INSTANCE Lcom/chattriggers/ctjs/api/world/World; - public static final field border Lcom/chattriggers/ctjs/api/world/World$BorderWrapper; - public static final field particle Lcom/chattriggers/ctjs/api/world/World$ParticleWrapper; - public static final field spawn Lcom/chattriggers/ctjs/api/world/World$SpawnWrapper; - public static final fun getAllBlockEntities ()Ljava/util/List; - public static final fun getAllBlockEntitiesOfType (Ljava/lang/Class;)Ljava/util/List; - public static final fun getAllEntities ()Ljava/util/List; - public static final fun getAllEntitiesOfType (Ljava/lang/Class;)Ljava/util/List; - public static final fun getAllPlayers ()Ljava/util/List; - public static final fun getBlockAt (Lcom/chattriggers/ctjs/api/world/block/BlockPos;)Lcom/chattriggers/ctjs/api/world/block/Block; - public static final fun getBlockAt (Ljava/lang/Number;Ljava/lang/Number;Ljava/lang/Number;)Lcom/chattriggers/ctjs/api/world/block/Block; - public static final fun getBlockLightLevel (III)I - public static final fun getBlockLightLevel (Lcom/chattriggers/ctjs/api/world/block/BlockPos;)I - public static final fun getBlockStateAt (Lcom/chattriggers/ctjs/api/world/block/BlockPos;)Lnet/minecraft/block/BlockState; - public static final fun getChunk (III)Lcom/chattriggers/ctjs/api/world/Chunk; - public static final fun getDifficulty ()Lcom/chattriggers/ctjs/api/client/Settings$Difficulty; - public static final fun getMoonPhase ()I - public static final fun getPlayerByName (Ljava/lang/String;)Lcom/chattriggers/ctjs/api/entity/PlayerMP; - public static final fun getRainingStrength ()F - public static final fun getSkyLightLevel (III)I - public static final fun getSkyLightLevel (Lcom/chattriggers/ctjs/api/world/block/BlockPos;)I - public static final fun getTicksPerSecond ()I - public static final fun getTime ()J - public static final fun getWorld ()Lnet/minecraft/client/world/ClientWorld; - public static final fun hasPlayer (Ljava/lang/String;)Z - public static final fun isLoaded ()Z - public static final fun isRaining ()Z - public static final fun toMC ()Lnet/minecraft/client/world/ClientWorld; -} - -public final class com/chattriggers/ctjs/api/world/World$BorderWrapper { - public fun ()V - public final fun getCenterX ()D - public final fun getCenterZ ()D - public final fun getSize ()D - public final fun getTargetSize ()D - public final fun getTimeUntilTarget ()J -} - -public final class com/chattriggers/ctjs/api/world/World$ParticleWrapper { - public fun ()V - public final fun getParticleNames ()Ljava/util/List; - public final fun spawnParticle (Ljava/lang/String;DDDDDD)Lcom/chattriggers/ctjs/api/entity/Particle; - public final fun spawnParticle (Lnet/minecraft/client/particle/Particle;)Lcom/chattriggers/ctjs/api/entity/Particle; -} - -public final class com/chattriggers/ctjs/api/world/World$SpawnWrapper { - public fun ()V - public final fun getX ()I - public final fun getY ()I - public final fun getZ ()I -} - -public class com/chattriggers/ctjs/api/world/block/Block { - public fun (Lcom/chattriggers/ctjs/api/world/block/BlockType;Lcom/chattriggers/ctjs/api/world/block/BlockPos;Lcom/chattriggers/ctjs/api/world/block/BlockFace;)V - public synthetic fun (Lcom/chattriggers/ctjs/api/world/block/BlockType;Lcom/chattriggers/ctjs/api/world/block/BlockPos;Lcom/chattriggers/ctjs/api/world/block/BlockFace;ILkotlin/jvm/internal/DefaultConstructorMarker;)V - public final fun canBeHarvested ()Z - public final fun canBeHarvestedWith (Lcom/chattriggers/ctjs/api/inventory/Item;)Z - public final fun getEmittingPower ()I - public final fun getEmittingPower (Lcom/chattriggers/ctjs/api/world/block/BlockFace;)I - public static synthetic fun getEmittingPower$default (Lcom/chattriggers/ctjs/api/world/block/Block;Lcom/chattriggers/ctjs/api/world/block/BlockFace;ILjava/lang/Object;)I - public final fun getFace ()Lcom/chattriggers/ctjs/api/world/block/BlockFace; - public final fun getPos ()Lcom/chattriggers/ctjs/api/world/block/BlockPos; - public final fun getReceivingPower ()I - public final fun getState ()Lnet/minecraft/block/BlockState; - public final fun getType ()Lcom/chattriggers/ctjs/api/world/block/BlockType; - public final fun getX ()I - public final fun getY ()I - public final fun getZ ()I - public final fun isEmittingPower ()Z - public final fun isEmittingPower (Lcom/chattriggers/ctjs/api/world/block/BlockFace;)Z - public static synthetic fun isEmittingPower$default (Lcom/chattriggers/ctjs/api/world/block/Block;Lcom/chattriggers/ctjs/api/world/block/BlockFace;ILjava/lang/Object;)Z - public final fun isReceivingPower ()Z - public fun toString ()Ljava/lang/String; - public final fun withFace (Lcom/chattriggers/ctjs/api/world/block/BlockFace;)Lcom/chattriggers/ctjs/api/world/block/Block; - public final fun withPos (Lcom/chattriggers/ctjs/api/world/block/BlockPos;)Lcom/chattriggers/ctjs/api/world/block/Block; - public final fun withType (Lcom/chattriggers/ctjs/api/world/block/BlockType;)Lcom/chattriggers/ctjs/api/world/block/Block; -} - -public final class com/chattriggers/ctjs/api/world/block/BlockFace : java/lang/Enum, com/chattriggers/ctjs/api/CTWrapper, net/minecraft/util/StringIdentifiable { - public static final field Companion Lcom/chattriggers/ctjs/api/world/block/BlockFace$Companion; - public static final field DOWN Lcom/chattriggers/ctjs/api/world/block/BlockFace; - public static final field EAST Lcom/chattriggers/ctjs/api/world/block/BlockFace; - public static final field NORTH Lcom/chattriggers/ctjs/api/world/block/BlockFace; - public static final field SOUTH Lcom/chattriggers/ctjs/api/world/block/BlockFace; - public static final field UP Lcom/chattriggers/ctjs/api/world/block/BlockFace; - public static final field WEST Lcom/chattriggers/ctjs/api/world/block/BlockFace; - public fun asString ()Ljava/lang/String; - public static final fun fromMC (Lnet/minecraft/util/math/Direction;)Lcom/chattriggers/ctjs/api/world/block/BlockFace; - public final fun getAxis ()Lcom/chattriggers/ctjs/api/world/block/BlockFace$Axis; - public final fun getAxisDirection ()Lcom/chattriggers/ctjs/api/world/block/BlockFace$AxisDirection; - public final fun getDirectionVec ()Lcom/chattriggers/ctjs/api/vec/Vec3i; - public static fun getEntries ()Lkotlin/enums/EnumEntries; - public synthetic fun getMcValue ()Ljava/lang/Object; - public fun getMcValue ()Lnet/minecraft/util/math/Direction; - public final fun getOffsetX ()I - public final fun getOffsetY ()I - public final fun getOffsetZ ()I - public final fun getOpposite ()Lcom/chattriggers/ctjs/api/world/block/BlockFace; - public final fun rotateAround (Lcom/chattriggers/ctjs/api/world/block/BlockFace$Axis;)Lcom/chattriggers/ctjs/api/world/block/BlockFace; - public final fun rotateX ()Lcom/chattriggers/ctjs/api/world/block/BlockFace; - public final fun rotateY ()Lcom/chattriggers/ctjs/api/world/block/BlockFace; - public final fun rotateZ ()Lcom/chattriggers/ctjs/api/world/block/BlockFace; - public synthetic fun toMC ()Ljava/lang/Object; - public fun toMC ()Lnet/minecraft/util/math/Direction; - public static fun valueOf (Ljava/lang/String;)Lcom/chattriggers/ctjs/api/world/block/BlockFace; - public static fun values ()[Lcom/chattriggers/ctjs/api/world/block/BlockFace; -} - -public final class com/chattriggers/ctjs/api/world/block/BlockFace$Axis : java/lang/Enum, com/chattriggers/ctjs/api/CTWrapper, java/util/function/Predicate, net/minecraft/util/StringIdentifiable { - public static final field Companion Lcom/chattriggers/ctjs/api/world/block/BlockFace$Axis$Companion; - public static final field X Lcom/chattriggers/ctjs/api/world/block/BlockFace$Axis; - public static final field Y Lcom/chattriggers/ctjs/api/world/block/BlockFace$Axis; - public static final field Z Lcom/chattriggers/ctjs/api/world/block/BlockFace$Axis; - public fun asString ()Ljava/lang/String; - public static final fun fromMC (Lnet/minecraft/util/math/Direction$Axis;)Lcom/chattriggers/ctjs/api/world/block/BlockFace$Axis; - public static fun getEntries ()Lkotlin/enums/EnumEntries; - public synthetic fun getMcValue ()Ljava/lang/Object; - public fun getMcValue ()Lnet/minecraft/util/math/Direction$Axis; - public final fun getPlane ()Lcom/chattriggers/ctjs/api/world/block/BlockFace$Plane; - public final fun isHorizontal ()Z - public final fun isVertical ()Z - public fun test (Lcom/chattriggers/ctjs/api/world/block/BlockFace;)Z - public synthetic fun test (Ljava/lang/Object;)Z - public synthetic fun toMC ()Ljava/lang/Object; - public fun toMC ()Lnet/minecraft/util/math/Direction$Axis; - public static fun valueOf (Ljava/lang/String;)Lcom/chattriggers/ctjs/api/world/block/BlockFace$Axis; - public static fun values ()[Lcom/chattriggers/ctjs/api/world/block/BlockFace$Axis; -} - -public final class com/chattriggers/ctjs/api/world/block/BlockFace$Axis$Companion { - public final fun fromMC (Lnet/minecraft/util/math/Direction$Axis;)Lcom/chattriggers/ctjs/api/world/block/BlockFace$Axis; -} - -public final class com/chattriggers/ctjs/api/world/block/BlockFace$AxisDirection : java/lang/Enum, com/chattriggers/ctjs/api/CTWrapper { - public static final field Companion Lcom/chattriggers/ctjs/api/world/block/BlockFace$AxisDirection$Companion; - public static final field NEGATIVE Lcom/chattriggers/ctjs/api/world/block/BlockFace$AxisDirection; - public static final field POSITIVE Lcom/chattriggers/ctjs/api/world/block/BlockFace$AxisDirection; - public static final fun fromMC (Lnet/minecraft/util/math/Direction$AxisDirection;)Lcom/chattriggers/ctjs/api/world/block/BlockFace$AxisDirection; - public static fun getEntries ()Lkotlin/enums/EnumEntries; - public synthetic fun getMcValue ()Ljava/lang/Object; - public fun getMcValue ()Lnet/minecraft/util/math/Direction$AxisDirection; - public final fun getOffset ()I - public synthetic fun toMC ()Ljava/lang/Object; - public fun toMC ()Lnet/minecraft/util/math/Direction$AxisDirection; - public static fun valueOf (Ljava/lang/String;)Lcom/chattriggers/ctjs/api/world/block/BlockFace$AxisDirection; - public static fun values ()[Lcom/chattriggers/ctjs/api/world/block/BlockFace$AxisDirection; -} - -public final class com/chattriggers/ctjs/api/world/block/BlockFace$AxisDirection$Companion { - public final fun fromMC (Lnet/minecraft/util/math/Direction$AxisDirection;)Lcom/chattriggers/ctjs/api/world/block/BlockFace$AxisDirection; -} - -public final class com/chattriggers/ctjs/api/world/block/BlockFace$Companion { - public final fun fromMC (Lnet/minecraft/util/math/Direction;)Lcom/chattriggers/ctjs/api/world/block/BlockFace; -} - -public final class com/chattriggers/ctjs/api/world/block/BlockFace$Plane : java/lang/Enum, java/lang/Iterable, java/util/function/Predicate, kotlin/jvm/internal/markers/KMappedMarker { - public static final field HORIZONTAL Lcom/chattriggers/ctjs/api/world/block/BlockFace$Plane; - public static final field VERTICAL Lcom/chattriggers/ctjs/api/world/block/BlockFace$Plane; - public final fun facings ()[Lcom/chattriggers/ctjs/api/world/block/BlockFace; - public static fun getEntries ()Lkotlin/enums/EnumEntries; - public fun iterator ()Ljava/util/Iterator; - public fun test (Lcom/chattriggers/ctjs/api/world/block/BlockFace;)Z - public synthetic fun test (Ljava/lang/Object;)Z - public static fun valueOf (Ljava/lang/String;)Lcom/chattriggers/ctjs/api/world/block/BlockFace$Plane; - public static fun values ()[Lcom/chattriggers/ctjs/api/world/block/BlockFace$Plane; -} - -public final class com/chattriggers/ctjs/api/world/block/BlockPos : com/chattriggers/ctjs/api/vec/Vec3i, com/chattriggers/ctjs/api/CTWrapper { - public fun (III)V - public fun (Lcom/chattriggers/ctjs/api/entity/Entity;)V - public fun (Lcom/chattriggers/ctjs/api/vec/Vec3i;)V - public fun (Ljava/lang/Number;Ljava/lang/Number;Ljava/lang/Number;)V - public fun (Lnet/minecraft/util/math/BlockPos;)V - public synthetic fun crossProduct (Lcom/chattriggers/ctjs/api/vec/Vec3i;)Lcom/chattriggers/ctjs/api/vec/Vec3i; - public fun crossProduct (Lcom/chattriggers/ctjs/api/vec/Vec3i;)Lcom/chattriggers/ctjs/api/world/block/BlockPos; - public final fun distanceTo (Lcom/chattriggers/ctjs/api/world/block/BlockPos;)D - public final fun down ()Lcom/chattriggers/ctjs/api/world/block/BlockPos; - public final fun down (I)Lcom/chattriggers/ctjs/api/world/block/BlockPos; - public static synthetic fun down$default (Lcom/chattriggers/ctjs/api/world/block/BlockPos;IILjava/lang/Object;)Lcom/chattriggers/ctjs/api/world/block/BlockPos; - public final fun east ()Lcom/chattriggers/ctjs/api/world/block/BlockPos; - public final fun east (I)Lcom/chattriggers/ctjs/api/world/block/BlockPos; - public static synthetic fun east$default (Lcom/chattriggers/ctjs/api/world/block/BlockPos;IILjava/lang/Object;)Lcom/chattriggers/ctjs/api/world/block/BlockPos; - public synthetic fun getMcValue ()Ljava/lang/Object; - public fun getMcValue ()Lnet/minecraft/util/math/BlockPos; - public synthetic fun minus (Lcom/chattriggers/ctjs/api/vec/Vec3i;)Lcom/chattriggers/ctjs/api/vec/Vec3i; - public fun minus (Lcom/chattriggers/ctjs/api/vec/Vec3i;)Lcom/chattriggers/ctjs/api/world/block/BlockPos; - public final fun north ()Lcom/chattriggers/ctjs/api/world/block/BlockPos; - public final fun north (I)Lcom/chattriggers/ctjs/api/world/block/BlockPos; - public static synthetic fun north$default (Lcom/chattriggers/ctjs/api/world/block/BlockPos;IILjava/lang/Object;)Lcom/chattriggers/ctjs/api/world/block/BlockPos; - public final fun offset (Lcom/chattriggers/ctjs/api/world/block/BlockFace;)Lcom/chattriggers/ctjs/api/world/block/BlockPos; - public final fun offset (Lcom/chattriggers/ctjs/api/world/block/BlockFace;I)Lcom/chattriggers/ctjs/api/world/block/BlockPos; - public static synthetic fun offset$default (Lcom/chattriggers/ctjs/api/world/block/BlockPos;Lcom/chattriggers/ctjs/api/world/block/BlockFace;IILjava/lang/Object;)Lcom/chattriggers/ctjs/api/world/block/BlockPos; - public synthetic fun plus (Lcom/chattriggers/ctjs/api/vec/Vec3i;)Lcom/chattriggers/ctjs/api/vec/Vec3i; - public fun plus (Lcom/chattriggers/ctjs/api/vec/Vec3i;)Lcom/chattriggers/ctjs/api/world/block/BlockPos; - public synthetic fun scaled (I)Lcom/chattriggers/ctjs/api/vec/Vec3i; - public fun scaled (I)Lcom/chattriggers/ctjs/api/world/block/BlockPos; - public synthetic fun scaled (III)Lcom/chattriggers/ctjs/api/vec/Vec3i; - public fun scaled (III)Lcom/chattriggers/ctjs/api/world/block/BlockPos; - public final fun south ()Lcom/chattriggers/ctjs/api/world/block/BlockPos; - public final fun south (I)Lcom/chattriggers/ctjs/api/world/block/BlockPos; - public static synthetic fun south$default (Lcom/chattriggers/ctjs/api/world/block/BlockPos;IILjava/lang/Object;)Lcom/chattriggers/ctjs/api/world/block/BlockPos; - public synthetic fun toMC ()Ljava/lang/Object; - public fun toMC ()Lnet/minecraft/util/math/BlockPos; - public final fun toVec3d ()Lnet/minecraft/util/math/Vec3d; - public synthetic fun translated (III)Lcom/chattriggers/ctjs/api/vec/Vec3i; - public fun translated (III)Lcom/chattriggers/ctjs/api/world/block/BlockPos; - public synthetic fun unaryMinus ()Lcom/chattriggers/ctjs/api/vec/Vec3i; - public fun unaryMinus ()Lcom/chattriggers/ctjs/api/world/block/BlockPos; - public final fun up ()Lcom/chattriggers/ctjs/api/world/block/BlockPos; - public final fun up (I)Lcom/chattriggers/ctjs/api/world/block/BlockPos; - public static synthetic fun up$default (Lcom/chattriggers/ctjs/api/world/block/BlockPos;IILjava/lang/Object;)Lcom/chattriggers/ctjs/api/world/block/BlockPos; - public final fun west ()Lcom/chattriggers/ctjs/api/world/block/BlockPos; - public final fun west (I)Lcom/chattriggers/ctjs/api/world/block/BlockPos; - public static synthetic fun west$default (Lcom/chattriggers/ctjs/api/world/block/BlockPos;IILjava/lang/Object;)Lcom/chattriggers/ctjs/api/world/block/BlockPos; -} - -public final class com/chattriggers/ctjs/api/world/block/BlockType : com/chattriggers/ctjs/api/CTWrapper { - public fun (I)V - public fun (Lcom/chattriggers/ctjs/api/inventory/Item;)V - public fun (Lcom/chattriggers/ctjs/api/world/block/BlockType;)V - public fun (Ljava/lang/String;)V - public fun (Lnet/minecraft/block/Block;)V - public final fun canProvidePower ()Z - public final fun getDefaultState ()Lnet/minecraft/block/BlockState; - public final fun getID ()I - public final fun getLightValue ()I - public synthetic fun getMcValue ()Ljava/lang/Object; - public fun getMcValue ()Lnet/minecraft/block/Block; - public final fun getName ()Ljava/lang/String; - public final fun getRegistryName ()Ljava/lang/String; - public final fun getTranslationKey ()Ljava/lang/String; - public final fun isTranslucent ()Z - public synthetic fun toMC ()Ljava/lang/Object; - public fun toMC ()Lnet/minecraft/block/Block; - public fun toString ()Ljava/lang/String; - public final fun withBlockPos (Lcom/chattriggers/ctjs/api/world/block/BlockPos;)Lcom/chattriggers/ctjs/api/world/block/Block; -} - public final class com/chattriggers/ctjs/engine/Console { public static final field INSTANCE Lcom/chattriggers/ctjs/engine/Console; public final fun clear ()V @@ -2697,45 +256,6 @@ public final class com/chattriggers/ctjs/engine/Register { public static final field INSTANCE Lcom/chattriggers/ctjs/engine/Register; public static final fun createCustomTrigger (Ljava/lang/String;)Ljava/lang/Object; public static final fun register (Ljava/lang/String;Ljava/lang/Object;)Lcom/chattriggers/ctjs/api/triggers/Trigger; - public static final fun registerActionBar (Ljava/lang/Object;)Lcom/chattriggers/ctjs/api/triggers/Trigger; - public static final fun registerChat (Ljava/lang/Object;)Lcom/chattriggers/ctjs/api/triggers/Trigger; - public static final fun registerClicked (Ljava/lang/Object;)Lcom/chattriggers/ctjs/api/triggers/Trigger; - public static final fun registerCommand (Ljava/lang/Object;)Lcom/chattriggers/ctjs/api/triggers/Trigger; - public static final fun registerDragged (Ljava/lang/Object;)Lcom/chattriggers/ctjs/api/triggers/Trigger; - public static final fun registerDrawBlockHighlight (Ljava/lang/Object;)Lcom/chattriggers/ctjs/api/triggers/Trigger; - public static final fun registerDropItem (Ljava/lang/Object;)Lcom/chattriggers/ctjs/api/triggers/Trigger; - public static final fun registerEntityDamage (Ljava/lang/Object;)Lcom/chattriggers/ctjs/api/triggers/Trigger; - public static final fun registerEntityDeath (Ljava/lang/Object;)Lcom/chattriggers/ctjs/api/triggers/Trigger; - public static final fun registerGameLoad (Ljava/lang/Object;)Lcom/chattriggers/ctjs/api/triggers/Trigger; - public static final fun registerGameUnload (Ljava/lang/Object;)Lcom/chattriggers/ctjs/api/triggers/Trigger; - public static final fun registerGuiClosed (Ljava/lang/Object;)Lcom/chattriggers/ctjs/api/triggers/Trigger; - public static final fun registerGuiKey (Ljava/lang/Object;)Lcom/chattriggers/ctjs/api/triggers/Trigger; - public static final fun registerGuiMouseClick (Ljava/lang/Object;)Lcom/chattriggers/ctjs/api/triggers/Trigger; - public static final fun registerGuiMouseDrag (Ljava/lang/Object;)Lcom/chattriggers/ctjs/api/triggers/Trigger; - public static final fun registerGuiOpened (Ljava/lang/Object;)Lcom/chattriggers/ctjs/api/triggers/Trigger; - public static final fun registerGuiRender (Ljava/lang/Object;)Lcom/chattriggers/ctjs/api/triggers/Trigger; - public static final fun registerItemTooltip (Ljava/lang/Object;)Lcom/chattriggers/ctjs/api/triggers/Trigger; - public static final fun registerMessageSent (Ljava/lang/Object;)Lcom/chattriggers/ctjs/api/triggers/Trigger; - public static final fun registerPacketReceived (Ljava/lang/Object;)Lcom/chattriggers/ctjs/api/triggers/Trigger; - public static final fun registerPacketSent (Ljava/lang/Object;)Lcom/chattriggers/ctjs/api/triggers/Trigger; - public static final fun registerPlayerInteract (Ljava/lang/Object;)Lcom/chattriggers/ctjs/api/triggers/Trigger; - public static final fun registerPostGuiRender (Ljava/lang/Object;)Lcom/chattriggers/ctjs/api/triggers/Trigger; - public static final fun registerPostRenderWorld (Ljava/lang/Object;)Lcom/chattriggers/ctjs/api/triggers/Trigger; - public static final fun registerPreRenderWorld (Ljava/lang/Object;)Lcom/chattriggers/ctjs/api/triggers/Trigger; - public static final fun registerRenderBlockEntity (Ljava/lang/Object;)Lcom/chattriggers/ctjs/api/triggers/Trigger; - public static final fun registerRenderEntity (Ljava/lang/Object;)Lcom/chattriggers/ctjs/api/triggers/Trigger; - public static final fun registerRenderOverlay (Ljava/lang/Object;)Lcom/chattriggers/ctjs/api/triggers/Trigger; - public static final fun registerRenderPlayerList (Ljava/lang/Object;)Lcom/chattriggers/ctjs/api/triggers/Trigger; - public static final fun registerRenderWorld (Ljava/lang/Object;)Lcom/chattriggers/ctjs/api/triggers/Trigger; - public static final fun registerScrolled (Ljava/lang/Object;)Lcom/chattriggers/ctjs/api/triggers/Trigger; - public static final fun registerServerConnect (Ljava/lang/Object;)Lcom/chattriggers/ctjs/api/triggers/Trigger; - public static final fun registerServerDisconnect (Ljava/lang/Object;)Lcom/chattriggers/ctjs/api/triggers/Trigger; - public static final fun registerSoundPlay (Ljava/lang/Object;)Lcom/chattriggers/ctjs/api/triggers/Trigger; - public static final fun registerSpawnParticle (Ljava/lang/Object;)Lcom/chattriggers/ctjs/api/triggers/Trigger; - public static final fun registerStep (Ljava/lang/Object;)Lcom/chattriggers/ctjs/api/triggers/Trigger; - public static final fun registerTick (Ljava/lang/Object;)Lcom/chattriggers/ctjs/api/triggers/Trigger; - public static final fun registerWorldLoad (Ljava/lang/Object;)Lcom/chattriggers/ctjs/api/triggers/Trigger; - public static final fun registerWorldUnload (Ljava/lang/Object;)Lcom/chattriggers/ctjs/api/triggers/Trigger; } public final class com/chattriggers/ctjs/engine/WrappedThread { diff --git a/build.gradle.kts b/build.gradle.kts index 16685832..15763d4f 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,64 +1,33 @@ -import org.gradle.kotlin.dsl.support.unzipTo -import org.jetbrains.dokka.versioning.VersioningConfiguration -import org.jetbrains.dokka.versioning.VersioningPlugin import org.jetbrains.kotlin.gradle.dsl.JvmTarget -import java.net.HttpURLConnection -import java.net.URL -import java.io.ByteArrayOutputStream - -buildscript { - dependencies { - classpath(libs.versioning) - } -} plugins { alias(libs.plugins.kotlin) alias(libs.plugins.serialization) alias(libs.plugins.loom) - alias(libs.plugins.dokka) - alias(libs.plugins.validator) alias(libs.plugins.ksp) } -if (!project.hasProperty("full")) { - project.gradle.startParameter.excludedTaskNames.add("kspKotlin") -} - version = property("mod_version").toString() repositories { maven("https://jitpack.io") - maven("https://pkgs.dev.azure.com/djtheredstoner/DevAuth/_packaging/public/maven/v1") maven("https://maven.terraformersmc.com/releases") - maven("https://repo.essential.gg/repository/maven-public") } dependencies { // To change the versions see the gradle/libs.versions.toml minecraft(libs.minecraft) - mappings(variantOf(libs.yarn) { classifier("v2") }) - modImplementation(libs.bundles.fabric) + implementation(libs.bundles.fabric) - modImplementation(libs.bundles.included) { include(this) } - modImplementation(libs.bundles.essential) { - exclude("gg.essential", "universalcraft-1.18.1-fabric") - include(this) - } + implementation(libs.bundles.included) { include(this) } - modApi(libs.modmenu) - modRuntimeOnly(libs.devauth) - dokkaPlugin(libs.versioning) + api(libs.modmenu) implementation(kotlin("stdlib-jdk8")) implementation(project(":typing-generator")) ksp(project(":typing-generator")) } -loom { - accessWidenerPath.set(file("src/main/resources/ctjs.accesswidener")) -} - base { archivesName.set(property("archives_base_name") as String) } @@ -66,24 +35,23 @@ base { java { withSourcesJar() - sourceCompatibility = JavaVersion.VERSION_21 - targetCompatibility = JavaVersion.VERSION_21 + sourceCompatibility = JavaVersion.VERSION_25 + targetCompatibility = JavaVersion.VERSION_25 } -apiValidation { - ignoredProjects += "typing-generator" - ignoredPackages += "com.chattriggers.ctjs.internal" +kotlin { + compilerOptions { + jvmTarget.set(JvmTarget.JVM_25) + } } tasks { processResources { val flkVersion = libs.versions.fabric.kotlin.get() - val yarnVersion = libs.versions.yarn.get() val fapiVersion = libs.versions.fabric.api.get() val loaderVersion = libs.versions.loader.get() inputs.property("version", project.version) - inputs.property("yarn_mappings", yarnVersion) inputs.property("fabric_kotlin_version", flkVersion) inputs.property("fabric_api_version", fapiVersion) inputs.property("loader_version", loaderVersion) @@ -91,7 +59,6 @@ tasks { filesMatching("fabric.mod.json") { expand( "version" to project.version, - "yarn_mappings" to yarnVersion, "fabric_kotlin_version" to flkVersion, "fabric_api_version" to fapiVersion, "loader_version" to loaderVersion @@ -99,122 +66,9 @@ tasks { } } - withType().configureEach { - options.release.set(21) - } - - kotlin { - compilerOptions { - jvmTarget.set(JvmTarget.JVM_21) - freeCompilerArgs = listOf("-Xcontext-receivers") - } - } - jar { from("LICENSE") { rename { "${name}_${base.archivesName.get()}" } } } - - dokkaHtml { - // Just use the module name here since the MC version doesn't affect CT's API - // across the same mod version - moduleVersion.set(project.version.toString()) - moduleName.set("ctjs") - - val docVersionsDir = projectDir.resolve("build/javadocs") - val currentVersion = project.version.toString() - val currentDocsDir = docVersionsDir.resolve(currentVersion) - outputs.upToDateWhen { docVersionsDir.exists() } - - outputDirectory.set(file(currentDocsDir)) - - pluginConfiguration { - version = project.version.toString() - olderVersionsDir = docVersionsDir - renderVersionsNavigationOnAllPages = true - } - - suppressObviousFunctions.set(true) - suppressInheritedMembers.set(true) - - val branch = getBranch() - dokkaSourceSets { - configureEach { - jdkVersion.set(21) - - perPackageOption { - matchingRegex.set("com\\.chattriggers\\.ctjs\\.internal(\$|\\.).*") - suppress.set(true) - } - - sourceLink { - localDirectory.set(file("src/main/kotlin")) - remoteUrl.set(URL("https://github.com/ChatTriggers/ctjs/blob/$branch/src/main/kotlin")) - remoteLineSuffix.set("#L") - } - - externalDocumentationLink { - val yarnVersion = libs.versions.yarn.get() - - url.set(URL("https://maven.fabricmc.net/docs/yarn-$yarnVersion/")) - packageListUrl.set(URL("https://maven.fabricmc.net/docs/yarn-$yarnVersion/element-list")) - } - } - } - - doFirst { - val archiveBase = "https://www.chattriggers.com/javadocs-archive/" - val versions = String(downloadFile(archiveBase + "versions")).lines().map(String::trim) - val tmpFile = File(temporaryDir, "oldVersionsZip.zip") - - versions.filter(String::isNotEmpty).map(String::trim).forEach { version -> - val zipBytes = downloadFile("$archiveBase$version.zip") - tmpFile.writeBytes(zipBytes) - unzipTo(docVersionsDir, tmpFile) - } - - tmpFile.delete() - } - - doLast { - // At this point we have a structure that looks something like this: - // javadocs - // \-- 2.2.0-1.8.9 - // \-- 3.0.0 - // \-- older - // - // The "older" directory contains all old versions, so we want to - // delete the top-level older versions and move everything inside the - // latest directory to the top level so the GitHub actions workflow - // doesn't need to figure out the correct version name - - docVersionsDir.listFiles()?.forEach { - if (it.name != version) - it.deleteRecursively() - } - - val latestVersionDir = docVersionsDir.listFiles()!!.single() - latestVersionDir.listFiles()!!.forEach { - it.renameTo(File(it.parentFile.parentFile, it.name)) - } - latestVersionDir.deleteRecursively() - } - } -} - -fun downloadFile(url: String): ByteArray { - return (URL(url).openConnection() as HttpURLConnection).apply { - requestMethod = "GET" - doOutput = true - }.inputStream.readAllBytes() -} - -fun getBranch(): String { - val stdout = ByteArrayOutputStream() - exec { - commandLine("git", "rev-parse", "HEAD") - standardOutput = stdout - } - return stdout.toString().trim() } diff --git a/gradle.properties b/gradle.properties index 2732bee3..9c7e94f3 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,7 +1,6 @@ # Done to increase the memory available to gradle. org.gradle.jvmargs=-Xmx4G org.gradle.parallel=true - # Mod Properties -mod_version = 3.0.0-beta -archives_base_name = ctjs +mod_version=26.1.2-srock +archives_base_name=ctjs diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 6a0670eb..d0a783a7 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,68 +1,46 @@ [versions] # Library versions -minecraft = "1.21" -yarn = "1.21+build.2" +minecraft = "26.1.2" -loader = "0.15.11" -fabric-api = "0.100.3+1.21" -fabric-kotlin = "1.11.0+kotlin.2.0.0" +loader = "0.19.3" +fabric-api = "0.151.0+26.1.2" +fabric-kotlin = "1.13.9+kotlin.2.3.10" -mapping-io = "0.6.1" rhino = "7c7c509668" -jackson-core = "2.13.2" -textarea = "3.2.0" -serialization = "1.5.1" -koffee = "315bc11234" +jackson-core = "3.2.0" +textarea = "3.6.3" +serialization = "1.11.0" -universalcraft = "342" -elementa = "649" -vigilance = "297" - -modmenu = "11.0.1" -devauth = "1.2.1" -dokka = "1.9.20" +modmenu = "18.0.0-beta.1" # Plugin Versions -kotlin = "2.0.0" -loom = "1.7-SNAPSHOT" -validator = "0.14.0" -ksp = "2.0.0-1.0.22" +kotlin = "2.4.0" +loom = "1.16-SNAPSHOT" +ksp = "2.3.9" [libraries] minecraft = { module = "com.mojang:minecraft", version.ref = "minecraft" } -yarn = { module = "net.fabricmc:yarn", version.ref = "yarn" } fabric-loader = { module = "net.fabricmc:fabric-loader", version.ref = "loader" } fabric-api = { module = "net.fabricmc.fabric-api:fabric-api", version.ref = "fabric-api" } fabric-kotlin = { module = "net.fabricmc:fabric-language-kotlin", version.ref = "fabric-kotlin" } -mapping-io = { module = "net.fabricmc:mapping-io", version.ref = "mapping-io" } rhino = { module = "com.github.ChatTriggers:rhino", version.ref = "rhino" } -jackson-core = { module = "com.fasterxml.jackson.core:jackson-core", version.ref = "jackson-core" } +jackson-core = { module = "tools.jackson.core:jackson-core", version.ref = "jackson-core" } textarea = { module = "com.fifesoft:rsyntaxtextarea", version.ref = "textarea" } serialization = { module = "org.jetbrains.kotlinx:kotlinx-serialization-json", version.ref = "serialization" } -koffee = { module = "com.github.ChatTriggers:koffee", version.ref = "koffee" } - -universalcraft = { module = "gg.essential:universalcraft-1.21-fabric", version.ref = "universalcraft" } -elementa = { module = "gg.essential:elementa-1.18.1-fabric", version.ref = "elementa" } -vigilance = { module = "gg.essential:vigilance-1.18.1-fabric", version.ref = "vigilance" } modmenu = { module = "com.terraformersmc:modmenu", version.ref = "modmenu" } -devauth = { module = "me.djtheredstoner:DevAuth-fabric", version.ref = "devauth" } -versioning = { module = "org.jetbrains.dokka:versioning-plugin", version.ref = "dokka" } ksp = { module = "com.google.devtools.ksp:symbol-processing-api", version.ref = "ksp" } gradle-plugin = { module = "org.jetbrains.kotlin:kotlin-gradle-plugin", version.ref = "kotlin" } [bundles] fabric = ["fabric-loader", "fabric-api", "fabric-kotlin"] -included = ["mapping-io", "rhino", "jackson-core", "textarea", "serialization", "koffee"] -essential = ["universalcraft", "elementa", "vigilance"] +included = ["rhino", "jackson-core", "textarea", "serialization"] [plugins] kotlin = { id = "org.jetbrains.kotlin.jvm", version.ref = "kotlin" } serialization = { id = "org.jetbrains.kotlin.plugin.serialization", version.ref = "kotlin" } -loom = { id = "fabric-loom", version.ref = "loom" } -dokka = { id = "org.jetbrains.dokka", version.ref = "dokka" } -validator = { id = "org.jetbrains.kotlinx.binary-compatibility-validator", version.ref = "validator" } +loom = { id = "net.fabricmc.fabric-loom", version.ref = "loom" } ksp = { id = "com.google.devtools.ksp", version.ref = "ksp" } diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index a4413138..1a704683 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.8-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-9.5.0-bin.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME diff --git a/src/main/java/com/chattriggers/ctjs/internal/BoundKeyUpdater.java b/src/main/java/com/chattriggers/ctjs/internal/BoundKeyUpdater.java deleted file mode 100644 index 7d4cb9e5..00000000 --- a/src/main/java/com/chattriggers/ctjs/internal/BoundKeyUpdater.java +++ /dev/null @@ -1,7 +0,0 @@ -package com.chattriggers.ctjs.internal; - -import net.minecraft.client.option.KeyBinding; - -public interface BoundKeyUpdater { - void ctjs_updateBoundKey(KeyBinding keyBinding); -} diff --git a/src/main/java/com/chattriggers/ctjs/internal/CTClientCommandSource.java b/src/main/java/com/chattriggers/ctjs/internal/CTClientCommandSource.java deleted file mode 100644 index d320665f..00000000 --- a/src/main/java/com/chattriggers/ctjs/internal/CTClientCommandSource.java +++ /dev/null @@ -1,11 +0,0 @@ -package com.chattriggers.ctjs.internal; - -import net.minecraft.command.CommandSource; - -import java.util.HashMap; - -public interface CTClientCommandSource extends CommandSource { - void setContextValue(String key, Object value); - - HashMap getContextValues(); -} diff --git a/src/main/java/com/chattriggers/ctjs/internal/NameTagOverridable.java b/src/main/java/com/chattriggers/ctjs/internal/NameTagOverridable.java deleted file mode 100644 index 351705dc..00000000 --- a/src/main/java/com/chattriggers/ctjs/internal/NameTagOverridable.java +++ /dev/null @@ -1,8 +0,0 @@ -package com.chattriggers.ctjs.internal; - -import com.chattriggers.ctjs.api.message.TextComponent; -import org.jetbrains.annotations.Nullable; - -public interface NameTagOverridable { - void ctjs_setOverriddenNametagName(@Nullable TextComponent component); -} diff --git a/src/main/java/com/chattriggers/ctjs/internal/Skippable.java b/src/main/java/com/chattriggers/ctjs/internal/Skippable.java deleted file mode 100644 index 6ca3aaae..00000000 --- a/src/main/java/com/chattriggers/ctjs/internal/Skippable.java +++ /dev/null @@ -1,6 +0,0 @@ -package com.chattriggers.ctjs.internal; - - -public interface Skippable { - void ctjs_setShouldSkip(boolean shouldSkip); -} diff --git a/src/main/java/com/chattriggers/ctjs/internal/TooltipOverridable.java b/src/main/java/com/chattriggers/ctjs/internal/TooltipOverridable.java deleted file mode 100644 index e7868001..00000000 --- a/src/main/java/com/chattriggers/ctjs/internal/TooltipOverridable.java +++ /dev/null @@ -1,10 +0,0 @@ -package com.chattriggers.ctjs.internal; - -import net.minecraft.text.Text; - -import java.util.List; - -public interface TooltipOverridable { - void ctjs_setTooltip(List tooltip); - void ctjs_setShouldOverrideTooltip(boolean shouldOverrideTooltip); -} diff --git a/src/main/java/com/chattriggers/ctjs/internal/mixins/AbstractSoundInstanceAccessor.java b/src/main/java/com/chattriggers/ctjs/internal/mixins/AbstractSoundInstanceAccessor.java deleted file mode 100644 index ad2edb54..00000000 --- a/src/main/java/com/chattriggers/ctjs/internal/mixins/AbstractSoundInstanceAccessor.java +++ /dev/null @@ -1,14 +0,0 @@ -package com.chattriggers.ctjs.internal.mixins; - -import net.minecraft.client.sound.AbstractSoundInstance; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.gen.Accessor; - -@Mixin(AbstractSoundInstance.class) -public interface AbstractSoundInstanceAccessor { - @Accessor - void setRepeat(boolean repeat); - - @Accessor - void setRepeatDelay(int delay); -} diff --git a/src/main/java/com/chattriggers/ctjs/internal/mixins/BlockEntityRenderDispatcherMixin.java b/src/main/java/com/chattriggers/ctjs/internal/mixins/BlockEntityRenderDispatcherMixin.java deleted file mode 100644 index 2d36aa12..00000000 --- a/src/main/java/com/chattriggers/ctjs/internal/mixins/BlockEntityRenderDispatcherMixin.java +++ /dev/null @@ -1,31 +0,0 @@ -package com.chattriggers.ctjs.internal.mixins; - -import com.chattriggers.ctjs.internal.engine.CTEvents; -import net.minecraft.block.entity.BlockEntity; -import net.minecraft.client.render.VertexConsumerProvider; -import net.minecraft.client.render.block.entity.BlockEntityRenderDispatcher; -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; - -import java.util.Objects; - -@Mixin(BlockEntityRenderDispatcher.class) -public class BlockEntityRenderDispatcherMixin { - @Inject( - method = "render(Lnet/minecraft/block/entity/BlockEntity;FLnet/minecraft/client/util/math/MatrixStack;Lnet/minecraft/client/render/VertexConsumerProvider;)V", - at = @At( - value = "INVOKE", - target = "Lnet/minecraft/client/render/block/entity/BlockEntityRenderDispatcher;runReported(Lnet/minecraft/block/entity/BlockEntity;Ljava/lang/Runnable;)V" - ), - cancellable = true - ) - private void injectRender(BlockEntity blockEntity, float tickDelta, MatrixStack matrices, - VertexConsumerProvider vertexConsumers, CallbackInfo ci) { - if (blockEntity.hasWorld() && Objects.requireNonNull(blockEntity.getWorld()).isClient) { - CTEvents.RENDER_BLOCK_ENTITY.invoker().render(matrices, blockEntity, tickDelta, ci); - } - } -} diff --git a/src/main/java/com/chattriggers/ctjs/internal/mixins/BookScreenAccessor.java b/src/main/java/com/chattriggers/ctjs/internal/mixins/BookScreenAccessor.java deleted file mode 100644 index 41ad7b26..00000000 --- a/src/main/java/com/chattriggers/ctjs/internal/mixins/BookScreenAccessor.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.chattriggers.ctjs.internal.mixins; - -import net.minecraft.client.gui.screen.ingame.BookScreen; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.gen.Accessor; -import org.spongepowered.asm.mixin.gen.Invoker; - -@Mixin(BookScreen.class) -public interface BookScreenAccessor { - @Accessor - int getPageIndex(); - - @Invoker - void invokeUpdatePageButtons(); -} diff --git a/src/main/java/com/chattriggers/ctjs/internal/mixins/BossBarHudAccessor.java b/src/main/java/com/chattriggers/ctjs/internal/mixins/BossBarHudAccessor.java deleted file mode 100644 index 8dc8296c..00000000 --- a/src/main/java/com/chattriggers/ctjs/internal/mixins/BossBarHudAccessor.java +++ /dev/null @@ -1,17 +0,0 @@ -package com.chattriggers.ctjs.internal.mixins; - -import net.minecraft.client.gui.hud.BossBarHud; -import net.minecraft.client.gui.hud.ClientBossBar; -import org.spongepowered.asm.mixin.Final; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.gen.Accessor; - -import java.util.Map; -import java.util.UUID; - -@Mixin(BossBarHud.class) -public interface BossBarHudAccessor { - @Accessor - @Final - Map getBossBars(); -} diff --git a/src/main/java/com/chattriggers/ctjs/internal/mixins/ChatHudAccessor.java b/src/main/java/com/chattriggers/ctjs/internal/mixins/ChatHudAccessor.java deleted file mode 100644 index cfbe25aa..00000000 --- a/src/main/java/com/chattriggers/ctjs/internal/mixins/ChatHudAccessor.java +++ /dev/null @@ -1,18 +0,0 @@ -package com.chattriggers.ctjs.internal.mixins; - -import net.minecraft.client.gui.hud.ChatHud; -import net.minecraft.client.gui.hud.ChatHudLine; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.gen.Accessor; -import org.spongepowered.asm.mixin.gen.Invoker; - -import java.util.List; - -@Mixin(ChatHud.class) -public interface ChatHudAccessor { - @Accessor - List getMessages(); - - @Invoker - void invokeRefresh(); -} diff --git a/src/main/java/com/chattriggers/ctjs/internal/mixins/ChatHudMixin.java b/src/main/java/com/chattriggers/ctjs/internal/mixins/ChatHudMixin.java deleted file mode 100644 index 5bb87765..00000000 --- a/src/main/java/com/chattriggers/ctjs/internal/mixins/ChatHudMixin.java +++ /dev/null @@ -1,45 +0,0 @@ -package com.chattriggers.ctjs.internal.mixins; - -import com.chattriggers.ctjs.api.message.ChatLib; -import net.minecraft.client.gui.hud.ChatHud; -import net.minecraft.client.gui.hud.ChatHudLine; -import net.minecraft.client.gui.hud.MessageIndicator; -import net.minecraft.network.message.MessageSignatureData; -import net.minecraft.text.Text; -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; - -import java.util.List; - -@Mixin(ChatHud.class) -public class ChatHudMixin { - @Final - @Shadow - private List messages; - - @Inject(method = "clear", at = @At("TAIL")) - private void injectClear(boolean clearHistory, CallbackInfo ci) { - ChatLib.INSTANCE.onChatHudClearChat$ctjs(); - } - - // TODO: is it this or addVisibleMessage - @Inject( - method = "addMessage(Lnet/minecraft/client/gui/hud/ChatHudLine;)V", - at = @At( - value = "INVOKE", - target = "Ljava/util/List;remove(I)Ljava/lang/Object;", - shift = At.Shift.BEFORE - ) - ) - private void injectMessageRemovedForChatLimit(ChatHudLine message, CallbackInfo ci) { - ChatLib.INSTANCE.onChatHudLineRemoved$ctjs(messages.getLast()); - } - - // Note: ChatHudLine objects are also removed in queueForRemoval, however those are signature based. - // The Message objects that CT sends will always create ChatHudLine objects with null signatures, - // so objects removed in that method will never be in the ChatLib.chatLineIds map -} diff --git a/src/main/java/com/chattriggers/ctjs/internal/mixins/ChatScreenAccessor.java b/src/main/java/com/chattriggers/ctjs/internal/mixins/ChatScreenAccessor.java deleted file mode 100644 index 18ce2326..00000000 --- a/src/main/java/com/chattriggers/ctjs/internal/mixins/ChatScreenAccessor.java +++ /dev/null @@ -1,12 +0,0 @@ -package com.chattriggers.ctjs.internal.mixins; - -import net.minecraft.client.gui.screen.ChatScreen; -import net.minecraft.client.gui.widget.TextFieldWidget; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.gen.Accessor; - -@Mixin(ChatScreen.class) -public interface ChatScreenAccessor { - @Accessor - TextFieldWidget getChatField(); -} diff --git a/src/main/java/com/chattriggers/ctjs/internal/mixins/ChunkAccessor.java b/src/main/java/com/chattriggers/ctjs/internal/mixins/ChunkAccessor.java deleted file mode 100644 index ebfb3b8e..00000000 --- a/src/main/java/com/chattriggers/ctjs/internal/mixins/ChunkAccessor.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.chattriggers.ctjs.internal.mixins; - -import net.minecraft.block.entity.BlockEntity; -import net.minecraft.util.math.BlockPos; -import net.minecraft.world.chunk.Chunk; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.gen.Accessor; - -import java.util.Map; - -@Mixin(Chunk.class) -public interface ChunkAccessor { - @Accessor - Map getBlockEntities(); -} diff --git a/src/main/java/com/chattriggers/ctjs/internal/mixins/ClickableWidgetAccessor.java b/src/main/java/com/chattriggers/ctjs/internal/mixins/ClickableWidgetAccessor.java deleted file mode 100644 index 53e9f29d..00000000 --- a/src/main/java/com/chattriggers/ctjs/internal/mixins/ClickableWidgetAccessor.java +++ /dev/null @@ -1,11 +0,0 @@ -package com.chattriggers.ctjs.internal.mixins; - -import net.minecraft.client.gui.widget.ClickableWidget; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.gen.Accessor; - -@Mixin(ClickableWidget.class) -public interface ClickableWidgetAccessor { - @Accessor - void setHeight(int height); -} diff --git a/src/main/java/com/chattriggers/ctjs/internal/mixins/ClientChunkManagerAccessor.java b/src/main/java/com/chattriggers/ctjs/internal/mixins/ClientChunkManagerAccessor.java deleted file mode 100644 index 10357ae9..00000000 --- a/src/main/java/com/chattriggers/ctjs/internal/mixins/ClientChunkManagerAccessor.java +++ /dev/null @@ -1,11 +0,0 @@ -package com.chattriggers.ctjs.internal.mixins; - -import net.minecraft.client.world.ClientChunkManager; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.gen.Accessor; - -@Mixin(ClientChunkManager.class) -public interface ClientChunkManagerAccessor { - @Accessor - ClientChunkManager.ClientChunkMap getChunks(); -} diff --git a/src/main/java/com/chattriggers/ctjs/internal/mixins/ClientChunkMapAccessor.java b/src/main/java/com/chattriggers/ctjs/internal/mixins/ClientChunkMapAccessor.java deleted file mode 100644 index 9c814c84..00000000 --- a/src/main/java/com/chattriggers/ctjs/internal/mixins/ClientChunkMapAccessor.java +++ /dev/null @@ -1,14 +0,0 @@ -package com.chattriggers.ctjs.internal.mixins; - -import net.minecraft.client.world.ClientChunkManager.ClientChunkMap; -import net.minecraft.world.chunk.WorldChunk; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.gen.Accessor; - -import java.util.concurrent.atomic.AtomicReferenceArray; - -@Mixin(ClientChunkMap.class) -public interface ClientChunkMapAccessor { - @Accessor - AtomicReferenceArray getChunks(); -} diff --git a/src/main/java/com/chattriggers/ctjs/internal/mixins/ClientConnectionMixin.java b/src/main/java/com/chattriggers/ctjs/internal/mixins/ClientConnectionMixin.java deleted file mode 100644 index 1f63a11f..00000000 --- a/src/main/java/com/chattriggers/ctjs/internal/mixins/ClientConnectionMixin.java +++ /dev/null @@ -1,44 +0,0 @@ -package com.chattriggers.ctjs.internal.mixins; - -import com.chattriggers.ctjs.internal.engine.CTEvents; -import com.chattriggers.ctjs.api.triggers.TriggerType; -import io.netty.channel.ChannelHandlerContext; -import net.minecraft.network.ClientConnection; -import net.minecraft.network.NetworkSide; -import net.minecraft.network.PacketCallbacks; -import net.minecraft.network.packet.Packet; -import org.jetbrains.annotations.Nullable; -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(ClientConnection.class) -public abstract class ClientConnectionMixin { - @Shadow - public abstract NetworkSide getSide(); - - @Inject( - method = "channelRead0(Lio/netty/channel/ChannelHandlerContext;Lnet/minecraft/network/packet/Packet;)V", - at = @At( - value = "INVOKE", - target = "Lnet/minecraft/network/ClientConnection;handlePacket(Lnet/minecraft/network/packet/Packet;Lnet/minecraft/network/listener/PacketListener;)V", - shift = At.Shift.BEFORE - ), - cancellable = true - ) - private void injectHandlePacket(ChannelHandlerContext channelHandlerContext, Packet packet, CallbackInfo ci) { - if (getSide() == NetworkSide.CLIENTBOUND) - CTEvents.PACKET_RECEIVED.invoker().receive(packet, ci); - } - - @Inject( - method = "send(Lnet/minecraft/network/packet/Packet;Lnet/minecraft/network/PacketCallbacks;)V", - at = @At("HEAD"), - cancellable = true - ) - private void injectSendPacket(Packet packet, @Nullable PacketCallbacks callbacks, CallbackInfo ci) { - TriggerType.PACKET_SENT.triggerAll(packet, ci); - } -} diff --git a/src/main/java/com/chattriggers/ctjs/internal/mixins/ClientPacketListenerMixin.java b/src/main/java/com/chattriggers/ctjs/internal/mixins/ClientPacketListenerMixin.java new file mode 100644 index 00000000..51bb4abe --- /dev/null +++ b/src/main/java/com/chattriggers/ctjs/internal/mixins/ClientPacketListenerMixin.java @@ -0,0 +1,24 @@ +package com.chattriggers.ctjs.internal.mixins; + +import com.chattriggers.ctjs.api.CustomCommand; +import com.mojang.brigadier.CommandDispatcher; +import net.minecraft.client.multiplayer.ClientPacketListener; +import net.minecraft.client.multiplayer.ClientSuggestionProvider; +import net.minecraft.network.protocol.game.ClientboundCommandsPacket; +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(ClientPacketListener.class) +public class ClientPacketListenerMixin { + @Shadow + private CommandDispatcher commands; + + @SuppressWarnings({"unchecked", "rawtypes"}) + @Inject(method = "handleCommands", at = @At("RETURN")) + private void registerCustomCommands(ClientboundCommandsPacket packet, CallbackInfo ci) { + CustomCommand.INSTANCE.registerNetwork$ctjs((CommandDispatcher) commands); + } +} diff --git a/src/main/java/com/chattriggers/ctjs/internal/mixins/ClientPlayNetworkHandlerAccessor.java b/src/main/java/com/chattriggers/ctjs/internal/mixins/ClientPlayNetworkHandlerAccessor.java deleted file mode 100644 index 90e010ff..00000000 --- a/src/main/java/com/chattriggers/ctjs/internal/mixins/ClientPlayNetworkHandlerAccessor.java +++ /dev/null @@ -1,16 +0,0 @@ -package com.chattriggers.ctjs.internal.mixins; - -import net.minecraft.client.network.ClientPlayNetworkHandler; -import net.minecraft.client.network.PlayerListEntry; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.gen.Accessor; - -import java.util.Collection; -import java.util.Map; -import java.util.UUID; - -@Mixin(ClientPlayNetworkHandler.class) -public interface ClientPlayNetworkHandlerAccessor { - @Accessor - Map getPlayerListEntries(); -} diff --git a/src/main/java/com/chattriggers/ctjs/internal/mixins/ClientPlayerEntityMixin.java b/src/main/java/com/chattriggers/ctjs/internal/mixins/ClientPlayerEntityMixin.java deleted file mode 100644 index 3bb16cd3..00000000 --- a/src/main/java/com/chattriggers/ctjs/internal/mixins/ClientPlayerEntityMixin.java +++ /dev/null @@ -1,22 +0,0 @@ -package com.chattriggers.ctjs.internal.mixins; - -import com.chattriggers.ctjs.api.client.Player; -import com.chattriggers.ctjs.api.inventory.Item; -import com.chattriggers.ctjs.api.triggers.TriggerType; -import net.minecraft.client.network.ClientPlayerEntity; -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; - -@Mixin(ClientPlayerEntity.class) -public class ClientPlayerEntityMixin { - @Inject(method = "dropSelectedItem", at = @At("HEAD"), cancellable = true) - private void injectDropSelectedItem(boolean entireStack, CallbackInfoReturnable cir) { - // dropping item while not in gui - Item stack = Player.getHeldItem(); - if (stack != null && !stack.getMcValue().isEmpty()) { - TriggerType.DROP_ITEM.triggerAll(stack, entireStack, cir); - } - } -} diff --git a/src/main/java/com/chattriggers/ctjs/internal/mixins/ClientPlayerInteractionManagerMixin.java b/src/main/java/com/chattriggers/ctjs/internal/mixins/ClientPlayerInteractionManagerMixin.java deleted file mode 100644 index 1bb36371..00000000 --- a/src/main/java/com/chattriggers/ctjs/internal/mixins/ClientPlayerInteractionManagerMixin.java +++ /dev/null @@ -1,23 +0,0 @@ -package com.chattriggers.ctjs.internal.mixins; - -import com.chattriggers.ctjs.internal.engine.CTEvents; -import net.minecraft.client.network.ClientPlayerInteractionManager; -import net.minecraft.util.math.BlockPos; -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; - -@Mixin(ClientPlayerInteractionManager.class) -public class ClientPlayerInteractionManagerMixin { - @Inject( - method = "breakBlock", - at = @At( - value = "INVOKE", - target = "Lnet/minecraft/block/Block;onBroken(Lnet/minecraft/world/WorldAccess;Lnet/minecraft/util/math/BlockPos;Lnet/minecraft/block/BlockState;)V" - ) - ) - private void injectBreakBlock(BlockPos pos, CallbackInfoReturnable cir) { - CTEvents.BREAK_BLOCK.invoker().breakBlock(pos); - } -} diff --git a/src/main/java/com/chattriggers/ctjs/internal/mixins/ClientWorldAccessor.java b/src/main/java/com/chattriggers/ctjs/internal/mixins/ClientWorldAccessor.java deleted file mode 100644 index bbd7f4ab..00000000 --- a/src/main/java/com/chattriggers/ctjs/internal/mixins/ClientWorldAccessor.java +++ /dev/null @@ -1,12 +0,0 @@ -package com.chattriggers.ctjs.internal.mixins; - -import net.minecraft.client.world.ClientChunkManager; -import net.minecraft.client.world.ClientWorld; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.gen.Accessor; - -@Mixin(ClientWorld.class) -public interface ClientWorldAccessor { - @Accessor - ClientChunkManager getChunkManager(); -} diff --git a/src/main/java/com/chattriggers/ctjs/internal/mixins/commands/CommandNodeAccessor.java b/src/main/java/com/chattriggers/ctjs/internal/mixins/CommandNodeAccessor.java similarity index 66% rename from src/main/java/com/chattriggers/ctjs/internal/mixins/commands/CommandNodeAccessor.java rename to src/main/java/com/chattriggers/ctjs/internal/mixins/CommandNodeAccessor.java index b42ee755..2ea81a02 100644 --- a/src/main/java/com/chattriggers/ctjs/internal/mixins/commands/CommandNodeAccessor.java +++ b/src/main/java/com/chattriggers/ctjs/internal/mixins/CommandNodeAccessor.java @@ -1,4 +1,4 @@ -package com.chattriggers.ctjs.internal.mixins.commands; +package com.chattriggers.ctjs.internal.mixins; import com.mojang.brigadier.tree.CommandNode; import com.mojang.brigadier.tree.LiteralCommandNode; @@ -7,11 +7,11 @@ import java.util.Map; -@Mixin(value = CommandNode.class, remap = false) +@Mixin(CommandNode.class) public interface CommandNodeAccessor { @Accessor("children") - Map> getChildNodes(); + Map> getChildren(); - @Accessor + @Accessor("literals") Map> getLiterals(); } diff --git a/src/main/java/com/chattriggers/ctjs/internal/mixins/CreativeInventoryScreenMixin.java b/src/main/java/com/chattriggers/ctjs/internal/mixins/CreativeInventoryScreenMixin.java deleted file mode 100644 index 1ad949d6..00000000 --- a/src/main/java/com/chattriggers/ctjs/internal/mixins/CreativeInventoryScreenMixin.java +++ /dev/null @@ -1,68 +0,0 @@ -package com.chattriggers.ctjs.internal.mixins; - -import com.chattriggers.ctjs.api.triggers.CancellableEvent; -import com.chattriggers.ctjs.api.inventory.Item; -import com.chattriggers.ctjs.api.triggers.TriggerType; -import com.llamalad7.mixinextras.injector.ModifyExpressionValue; -import com.llamalad7.mixinextras.sugar.Local; -import net.minecraft.client.gui.screen.ingame.AbstractInventoryScreen; -import net.minecraft.client.gui.screen.ingame.CreativeInventoryScreen; -import net.minecraft.entity.player.PlayerInventory; -import net.minecraft.screen.slot.Slot; -import net.minecraft.screen.slot.SlotActionType; -import net.minecraft.text.Text; -import org.jetbrains.annotations.NotNull; -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.Slice; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; - -@Mixin(CreativeInventoryScreen.class) -public abstract class CreativeInventoryScreenMixin extends AbstractInventoryScreen { - private CreativeInventoryScreenMixin(CreativeInventoryScreen.CreativeScreenHandler screenHandler, PlayerInventory playerInventory, Text text) { - super(screenHandler, playerInventory, text); - } - - @ModifyExpressionValue( - method = "onMouseClick", - at = @At(value = "FIELD", target = "Lnet/minecraft/client/gui/screen/ingame/CreativeInventoryScreen;lastClickOutsideBounds:Z") - ) - private boolean injectOnMouseClick(boolean original, @Local(ordinal = 1) int button) { - // dropping by clicking outside creative tab - CancellableEvent event = new CancellableEvent(); - if (original) { - TriggerType.DROP_ITEM.triggerAll(Item.fromMC(handler.getCursorStack()), button == 0, event); - } - - return original && !event.isCanceled(); - } - - @ModifyExpressionValue( - method = "onMouseClick", - slice = @Slice( - from = @At( - value = "FIELD", - target = "Lnet/minecraft/client/gui/screen/ingame/CreativeInventoryScreen;deleteItemSlot:Lnet/minecraft/screen/slot/Slot;", - ordinal = 0 - ) - ), - at = @At(value = "INVOKE", target = "Lnet/minecraft/item/ItemStack;isEmpty()Z", ordinal = 0) - ) - private boolean injectOnMouseClick1(boolean original, @Local(ordinal = 1) int button) { - // dropping by clicking outside creative inventory - CancellableEvent event = new CancellableEvent(); - if (!original) { - TriggerType.DROP_ITEM.triggerAll(Item.fromMC(handler.getCursorStack()), button == 0, event); - } - - // !(original || eventCanceled) => !original && !canceled - return original || event.isCanceled(); - } - - @Inject(method = "onMouseClick", at = @At(value = "INVOKE", target = "Lnet/minecraft/screen/slot/Slot;takeStack(I)Lnet/minecraft/item/ItemStack;"), cancellable = true) - private void injectOnMouseClick2(@NotNull Slot slot, int slotId, int button, SlotActionType actionType, CallbackInfo ci) { - // dropping item from slot in creative inventory - TriggerType.DROP_ITEM.triggerAll(Item.fromMC(slot.getStack()), button == 0, ci); - } -} diff --git a/src/main/java/com/chattriggers/ctjs/internal/mixins/EntityRenderDispatcherAccessor.java b/src/main/java/com/chattriggers/ctjs/internal/mixins/EntityRenderDispatcherAccessor.java deleted file mode 100644 index b08362b7..00000000 --- a/src/main/java/com/chattriggers/ctjs/internal/mixins/EntityRenderDispatcherAccessor.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.chattriggers.ctjs.internal.mixins; - -import net.minecraft.client.render.VertexConsumerProvider; -import net.minecraft.client.render.entity.EntityRenderDispatcher; -import net.minecraft.client.util.math.MatrixStack; -import net.minecraft.entity.Entity; -import org.joml.Quaternionf; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.gen.Invoker; - -@Mixin(EntityRenderDispatcher.class) -public interface EntityRenderDispatcherAccessor { - @Invoker - void invokeRenderFire(MatrixStack matrices, VertexConsumerProvider vertexConsumers, Entity entity, Quaternionf rotation); -} diff --git a/src/main/java/com/chattriggers/ctjs/internal/mixins/EntityRenderDispatcherMixin.java b/src/main/java/com/chattriggers/ctjs/internal/mixins/EntityRenderDispatcherMixin.java deleted file mode 100644 index 5a9be4e5..00000000 --- a/src/main/java/com/chattriggers/ctjs/internal/mixins/EntityRenderDispatcherMixin.java +++ /dev/null @@ -1,30 +0,0 @@ -package com.chattriggers.ctjs.internal.mixins; - -import com.chattriggers.ctjs.internal.engine.CTEvents; -import com.chattriggers.ctjs.api.render.Renderer; -import com.llamalad7.mixinextras.sugar.Local; -import net.minecraft.client.render.VertexConsumerProvider; -import net.minecraft.client.render.entity.EntityRenderDispatcher; -import net.minecraft.client.render.entity.EntityRendererFactory; -import net.minecraft.client.util.math.MatrixStack; -import net.minecraft.entity.Entity; -import net.minecraft.resource.ResourceManager; -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(EntityRenderDispatcher.class) -public abstract class EntityRenderDispatcherMixin { - @Inject(method = "reload", at = @At("TAIL")) - private void injectReload(ResourceManager manager, CallbackInfo ci, @Local EntityRendererFactory.Context context) { - Renderer.initializePlayerRenderers$ctjs(context); - } - - @Inject(method = "render", at = @At("HEAD"), cancellable = true) - private void injectRender(Entity entity, double x, double y, double z, float yaw, float tickDelta, - MatrixStack matrices, VertexConsumerProvider vertexConsumers, int light, - CallbackInfo ci) { - CTEvents.RENDER_ENTITY.invoker().render(matrices, entity, tickDelta, ci); - } -} diff --git a/src/main/java/com/chattriggers/ctjs/internal/mixins/GameOptionsAccessor.java b/src/main/java/com/chattriggers/ctjs/internal/mixins/GameOptionsAccessor.java deleted file mode 100644 index b0a0d301..00000000 --- a/src/main/java/com/chattriggers/ctjs/internal/mixins/GameOptionsAccessor.java +++ /dev/null @@ -1,12 +0,0 @@ -package com.chattriggers.ctjs.internal.mixins; - -import net.minecraft.client.option.GameOptions; -import net.minecraft.client.option.KeyBinding; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.gen.Accessor; - -@Mixin(GameOptions.class) -public interface GameOptionsAccessor { - @Accessor - void setAllKeys(KeyBinding[] keys); -} diff --git a/src/main/java/com/chattriggers/ctjs/internal/mixins/GameOptionsMixin.java b/src/main/java/com/chattriggers/ctjs/internal/mixins/GameOptionsMixin.java deleted file mode 100644 index 3390341a..00000000 --- a/src/main/java/com/chattriggers/ctjs/internal/mixins/GameOptionsMixin.java +++ /dev/null @@ -1,31 +0,0 @@ -package com.chattriggers.ctjs.internal.mixins; - -import com.chattriggers.ctjs.internal.BoundKeyUpdater; -import net.minecraft.client.option.GameOptions; -import net.minecraft.client.option.KeyBinding; -import net.minecraft.client.util.InputUtil; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Unique; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; - -@Mixin(GameOptions.class) -public class GameOptionsMixin implements BoundKeyUpdater { - @Unique - private GameOptions.Visitor visitor; - - @Inject(method = "accept", at = @At("HEAD")) - private void captureVisitor(GameOptions.Visitor visitor, CallbackInfo ci) { - this.visitor = visitor; - } - - @Override - public void ctjs_updateBoundKey(KeyBinding keyBinding) { - String string = keyBinding.getBoundKeyTranslationKey(); - String string2 = visitor.visitString("key_" + keyBinding.getTranslationKey(), string); - if (!string.equals(string2)) { - keyBinding.setBoundKey(InputUtil.fromTranslationKey(string2)); - } - } -} diff --git a/src/main/java/com/chattriggers/ctjs/internal/mixins/HandledScreenAccessor.java b/src/main/java/com/chattriggers/ctjs/internal/mixins/HandledScreenAccessor.java deleted file mode 100644 index 5516155a..00000000 --- a/src/main/java/com/chattriggers/ctjs/internal/mixins/HandledScreenAccessor.java +++ /dev/null @@ -1,12 +0,0 @@ -package com.chattriggers.ctjs.internal.mixins; - -import net.minecraft.client.gui.screen.ingame.HandledScreen; -import net.minecraft.screen.slot.Slot; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.gen.Invoker; - -@Mixin(HandledScreen.class) -public interface HandledScreenAccessor { - @Invoker - Slot invokeGetSlotAt(double x, double y); -} diff --git a/src/main/java/com/chattriggers/ctjs/internal/mixins/HandledScreenMixin.java b/src/main/java/com/chattriggers/ctjs/internal/mixins/HandledScreenMixin.java deleted file mode 100644 index 2190d730..00000000 --- a/src/main/java/com/chattriggers/ctjs/internal/mixins/HandledScreenMixin.java +++ /dev/null @@ -1,65 +0,0 @@ -package com.chattriggers.ctjs.internal.mixins; - -import com.chattriggers.ctjs.api.inventory.Item; -import com.chattriggers.ctjs.api.message.TextComponent; -import com.chattriggers.ctjs.api.triggers.TriggerType; -import net.minecraft.client.gui.DrawContext; -import net.minecraft.client.gui.screen.Screen; -import net.minecraft.client.gui.screen.ingame.HandledScreen; -import net.minecraft.item.ItemStack; -import net.minecraft.screen.ScreenHandler; -import net.minecraft.screen.slot.Slot; -import net.minecraft.screen.slot.SlotActionType; -import net.minecraft.text.Text; -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; - -import java.util.Objects; - -@Mixin(HandledScreen.class) -public class HandledScreenMixin extends Screen { - @Shadow - protected Slot focusedSlot; - - @Shadow - @Final - protected ScreenHandler handler; - - private HandledScreenMixin(Text title) { - super(title); - } - - @Inject( - method = "drawMouseoverTooltip", - at = @At( - value = "INVOKE", - target = "Lnet/minecraft/client/gui/DrawContext;drawTooltip(Lnet/minecraft/client/font/TextRenderer;Ljava/util/List;Ljava/util/Optional;II)V" - ), - cancellable = true - ) - private void injectDrawMouseoverTooltip(DrawContext context, int x, int y, CallbackInfo ci) { - ItemStack stack = focusedSlot.getStack(); - TriggerType.ITEM_TOOLTIP.triggerAll( - getTooltipFromItem(Objects.requireNonNull(client), stack) - .stream() - .map(TextComponent::new) - .toList(), - Item.fromMC(stack), - ci - ); - } - - @Inject(method = "onMouseClick(Lnet/minecraft/screen/slot/Slot;IILnet/minecraft/screen/slot/SlotActionType;)V", at = @At("HEAD"), cancellable = true) - private void injectOnMouseClick(Slot slot, int slotId, int button, SlotActionType actionType, CallbackInfo ci) { - if ( - (slotId != -999 && actionType == SlotActionType.THROW) || // dropping item from slot - (slotId == -999 && actionType == SlotActionType.PICKUP) // dropping by clicking outside inventory - ) { - TriggerType.DROP_ITEM.triggerAll(Item.fromMC(handler.getCursorStack()), button == 0, ci); - } - } -} diff --git a/src/main/java/com/chattriggers/ctjs/internal/mixins/InGameHudMixin.java b/src/main/java/com/chattriggers/ctjs/internal/mixins/InGameHudMixin.java deleted file mode 100644 index 98e39aa4..00000000 --- a/src/main/java/com/chattriggers/ctjs/internal/mixins/InGameHudMixin.java +++ /dev/null @@ -1,34 +0,0 @@ -package com.chattriggers.ctjs.internal.mixins; - -import com.chattriggers.ctjs.api.world.Scoreboard; -import com.chattriggers.ctjs.internal.engine.CTEvents; -import net.minecraft.client.gui.DrawContext; -import net.minecraft.client.gui.hud.InGameHud; -import net.minecraft.client.render.RenderTickCounter; -import net.minecraft.scoreboard.ScoreboardObjective; -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 InGameHudMixin { - @Inject(method = "renderScoreboardSidebar(Lnet/minecraft/client/gui/DrawContext;Lnet/minecraft/scoreboard/ScoreboardObjective;)V", at = @At("HEAD"), cancellable = true) - private void injectRenderScoreboard(DrawContext matrices, ScoreboardObjective objective, CallbackInfo ci) { - if (!Scoreboard.getShouldRender()) - ci.cancel(); - } - - @Inject( - method = "render", - at = @At( - value = "INVOKE", - target = "Lnet/minecraft/client/gui/LayeredDrawer;render(Lnet/minecraft/client/gui/DrawContext;Lnet/minecraft/client/render/RenderTickCounter;)V", - shift = At.Shift.AFTER - ) - ) - private void injectRenderOverlay(DrawContext context, RenderTickCounter tickCounter, CallbackInfo ci) { - CTEvents.RENDER_OVERLAY.invoker().render(context.getMatrices(), tickCounter.getTickDelta(false)); - } -} diff --git a/src/main/java/com/chattriggers/ctjs/internal/mixins/ItemStackMixin.java b/src/main/java/com/chattriggers/ctjs/internal/mixins/ItemStackMixin.java deleted file mode 100644 index 24783d73..00000000 --- a/src/main/java/com/chattriggers/ctjs/internal/mixins/ItemStackMixin.java +++ /dev/null @@ -1,57 +0,0 @@ -package com.chattriggers.ctjs.internal.mixins; - -import com.chattriggers.ctjs.internal.Skippable; -import com.chattriggers.ctjs.internal.TooltipOverridable; -import com.llamalad7.mixinextras.sugar.Local; -import net.minecraft.entity.player.PlayerEntity; -import net.minecraft.item.Item; -import net.minecraft.item.ItemStack; -import net.minecraft.item.tooltip.TooltipType; -import net.minecraft.text.Text; -import org.jetbrains.annotations.Nullable; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Unique; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; - -import java.util.ArrayList; -import java.util.List; -import java.util.Objects; - -@Mixin(ItemStack.class) -public class ItemStackMixin implements TooltipOverridable, Skippable { - @Unique - private boolean shouldOverrideTooltip = false; - @Unique - private List overriddenTooltip = new ArrayList<>(); - @Unique - private boolean shouldSkipFabricEvent = false; - - @Inject(method = "getTooltip", at = @At("HEAD"), cancellable = true) - private void injectGetTooltip(Item.TooltipContext context, @Nullable PlayerEntity player, TooltipType type, CallbackInfoReturnable> cir) { - if (shouldOverrideTooltip) - cir.setReturnValue(Objects.requireNonNull(overriddenTooltip)); - } - - @Inject(method = "getTooltip", at = @At(value = "RETURN", ordinal = 1, shift = At.Shift.BEFORE), cancellable = true) - private void cancelFabricEvent(Item.TooltipContext context, @Nullable PlayerEntity player, TooltipType type, CallbackInfoReturnable> cir, @Local List list) { - if (shouldSkipFabricEvent) - cir.setReturnValue(list); - } - - @Override - public void ctjs_setTooltip(List tooltip) { - overriddenTooltip = tooltip; - } - - @Override - public void ctjs_setShouldOverrideTooltip(boolean shouldOverrideTooltip) { - this.shouldOverrideTooltip = shouldOverrideTooltip; - } - - @Override - public void ctjs_setShouldSkip(boolean shouldSkip) { - shouldSkipFabricEvent = shouldSkip; - } -} diff --git a/src/main/java/com/chattriggers/ctjs/internal/mixins/KeyBindingAccessor.java b/src/main/java/com/chattriggers/ctjs/internal/mixins/KeyBindingAccessor.java deleted file mode 100644 index 49cc504d..00000000 --- a/src/main/java/com/chattriggers/ctjs/internal/mixins/KeyBindingAccessor.java +++ /dev/null @@ -1,26 +0,0 @@ -package com.chattriggers.ctjs.internal.mixins; - -import net.minecraft.client.option.KeyBinding; -import net.minecraft.client.util.InputUtil; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.gen.Accessor; - -import java.util.Map; -import java.util.Set; - -@Mixin(KeyBinding.class) -public interface KeyBindingAccessor { - @Accessor("CATEGORY_ORDER_MAP") - static Map getCategoryMap() { throw new IllegalStateException(); } - - @Accessor("KEY_CATEGORIES") - static Set getKeyCategories() { - throw new IllegalStateException(); - } - - @Accessor - InputUtil.Key getBoundKey(); - - @Accessor - int getTimesPressed(); -} diff --git a/src/main/java/com/chattriggers/ctjs/internal/mixins/KeyBindsListMixin.java b/src/main/java/com/chattriggers/ctjs/internal/mixins/KeyBindsListMixin.java new file mode 100644 index 00000000..09739b3f --- /dev/null +++ b/src/main/java/com/chattriggers/ctjs/internal/mixins/KeyBindsListMixin.java @@ -0,0 +1,34 @@ +package com.chattriggers.ctjs.internal.mixins; + +import com.chattriggers.ctjs.api.CustomKeyMapping; +import com.llamalad7.mixinextras.injector.ModifyExpressionValue; +import net.minecraft.client.gui.screens.options.controls.KeyBindsList; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; + +import java.lang.reflect.Array; + +@Mixin(KeyBindsList.class) +public class KeyBindsListMixin { + @ModifyExpressionValue(method = "", at = @At( + value = "INVOKE", + target = "Lorg/apache/commons/lang3/ArrayUtils;clone([Ljava/lang/Object;)[Ljava/lang/Object;") + ) + public Object[] addCustomKeyMappings(Object[] original) { + var customKeyMappings = CustomKeyMapping.getKeyMappings(); + if (customKeyMappings.isEmpty()) return original; + + Class type = original.getClass().getComponentType(); + Object[] expanded = (Object[]) Array.newInstance(type, original.length + customKeyMappings.size()); + + // keep the original key mappings + System.arraycopy(original, 0, expanded, 0, original.length); + + // add the custom ones + for (int i = 0; i < customKeyMappings.size(); i++) { + expanded[i + original.length] = customKeyMappings.get(i); + } + + return expanded; + } +} diff --git a/src/main/java/com/chattriggers/ctjs/internal/mixins/LivingEntityMixin.java b/src/main/java/com/chattriggers/ctjs/internal/mixins/LivingEntityMixin.java deleted file mode 100644 index 33a3a0f3..00000000 --- a/src/main/java/com/chattriggers/ctjs/internal/mixins/LivingEntityMixin.java +++ /dev/null @@ -1,27 +0,0 @@ -package com.chattriggers.ctjs.internal.mixins; - -import com.chattriggers.ctjs.api.triggers.TriggerType; -import net.minecraft.entity.Entity; -import net.minecraft.entity.EntityType; -import net.minecraft.entity.LivingEntity; -import net.minecraft.entity.damage.DamageSource; -import net.minecraft.world.World; -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(LivingEntity.class) -public abstract class LivingEntityMixin extends Entity { - public LivingEntityMixin(EntityType type, World world) { - super(type, world); - } - - @Inject(method = "onDeath", at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/LivingEntity;setPose(Lnet/minecraft/entity/EntityPose;)V")) - private void chattriggers$entityDeath(DamageSource damageSource, CallbackInfo ci) { - if (getWorld().isClient) { - TriggerType.ENTITY_DEATH.triggerAll(this); - } - } -} diff --git a/src/main/java/com/chattriggers/ctjs/internal/mixins/MinecraftClientAccessor.java b/src/main/java/com/chattriggers/ctjs/internal/mixins/MinecraftClientAccessor.java deleted file mode 100644 index cdd03cc4..00000000 --- a/src/main/java/com/chattriggers/ctjs/internal/mixins/MinecraftClientAccessor.java +++ /dev/null @@ -1,12 +0,0 @@ -package com.chattriggers.ctjs.internal.mixins; - -import com.mojang.authlib.yggdrasil.YggdrasilAuthenticationService; -import net.minecraft.client.MinecraftClient; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.gen.Accessor; - -@Mixin(MinecraftClient.class) -public interface MinecraftClientAccessor { - @Accessor - YggdrasilAuthenticationService getAuthenticationService(); -} diff --git a/src/main/java/com/chattriggers/ctjs/internal/mixins/MinecraftClientMixin.java b/src/main/java/com/chattriggers/ctjs/internal/mixins/MinecraftClientMixin.java index f72600b2..0dca34c4 100644 --- a/src/main/java/com/chattriggers/ctjs/internal/mixins/MinecraftClientMixin.java +++ b/src/main/java/com/chattriggers/ctjs/internal/mixins/MinecraftClientMixin.java @@ -1,78 +1,16 @@ package com.chattriggers.ctjs.internal.mixins; -import com.chattriggers.ctjs.api.world.Scoreboard; -import com.chattriggers.ctjs.api.world.TabList; -import com.chattriggers.ctjs.internal.engine.CTEvents; -import com.chattriggers.ctjs.api.triggers.TriggerType; import com.chattriggers.ctjs.internal.engine.module.ModuleManager; -import net.minecraft.client.MinecraftClient; -import net.minecraft.client.gui.screen.DownloadingTerrainScreen; -import net.minecraft.client.gui.screen.Screen; -import net.minecraft.client.network.ServerInfo; -import net.minecraft.client.world.ClientWorld; -import org.jetbrains.annotations.Nullable; +import net.minecraft.client.Minecraft; 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 abstract class MinecraftClientMixin { - @Shadow @Nullable public ClientWorld world; - - @Shadow public abstract ServerInfo getCurrentServerEntry(); - @Shadow public abstract boolean isIntegratedServerRunning(); - - @Inject(method = "joinWorld", at = @At("HEAD")) - private void injectWorldUnload(ClientWorld world, DownloadingTerrainScreen.WorldEntryReason worldEntryReason, CallbackInfo ci) { - if (this.world == null && world != null) { - TriggerType.SERVER_CONNECT.triggerAll(); - } else if (this.world != null && world == null) { - TriggerType.SERVER_DISCONNECT.triggerAll(); - } - - if (this.world != null) { - TriggerType.WORLD_UNLOAD.triggerAll(); - Scoreboard.INSTANCE.clearCustom$ctjs(); - TabList.INSTANCE.clearCustom$ctjs(); - } - } - - @Inject(method = "joinWorld", at = @At("TAIL")) - private void injectWorldLoad(ClientWorld world, DownloadingTerrainScreen.WorldEntryReason worldEntryReason, CallbackInfo ci) { - if (world != null) - TriggerType.WORLD_LOAD.triggerAll(); - } - - @Inject(method = "disconnect(Lnet/minecraft/client/gui/screen/Screen;Z)V", at = @At("HEAD")) - private void injectDisconnect(Screen disconnectionScreen, boolean transferring, CallbackInfo ci) { - // disconnect() is also called when connecting, so we check that there is - // an existing server - if (this.isIntegratedServerRunning() || this.getCurrentServerEntry() != null) { - TriggerType.WORLD_UNLOAD.triggerAll(); - TriggerType.SERVER_DISCONNECT.triggerAll(); - Scoreboard.INSTANCE.clearCustom$ctjs(); - TabList.INSTANCE.clearCustom$ctjs(); - } - } - - @Inject(method = "setScreen", at = @At("HEAD")) - private void injectScreenOpened(Screen screen, CallbackInfo ci) { - if (screen != null) - TriggerType.GUI_OPENED.triggerAll(screen, ci); - } - +@Mixin(Minecraft.class) +public class MinecraftClientMixin { @Inject(method = "run", at = @At("HEAD")) private void injectRun(CallbackInfo ci) { - new Thread(() -> { - ModuleManager.INSTANCE.entryPass(); - TriggerType.GAME_LOAD.triggerAll(); - }).start(); - } - - @Inject(method = "render", at = @At("HEAD")) - private void injectRender(boolean tick, CallbackInfo ci) { - CTEvents.RENDER_GAME.invoker().run(); + new Thread(ModuleManager.INSTANCE::entryPass).start(); } } diff --git a/src/main/java/com/chattriggers/ctjs/internal/mixins/MouseMixin.java b/src/main/java/com/chattriggers/ctjs/internal/mixins/MouseMixin.java deleted file mode 100644 index 7da53990..00000000 --- a/src/main/java/com/chattriggers/ctjs/internal/mixins/MouseMixin.java +++ /dev/null @@ -1,56 +0,0 @@ -package com.chattriggers.ctjs.internal.mixins; - -import com.chattriggers.ctjs.internal.engine.CTEvents; -import com.chattriggers.ctjs.internal.listeners.MouseListener; -import net.minecraft.client.Mouse; -import net.minecraft.client.gui.screen.Screen; -import org.objectweb.asm.Opcodes; -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(Mouse.class) -public class MouseMixin { - @Shadow - private int activeButton; - - @Inject( - method = "onMouseButton", - at = @At( - value = "FIELD", - target = "Lnet/minecraft/client/MinecraftClient;currentScreen:Lnet/minecraft/client/gui/screen/Screen;", - opcode = Opcodes.GETFIELD - ) - ) - private void injectOnMouseButton(long window, int button, int action, int mods, CallbackInfo ci) { - MouseListener.onRawMouseInput(button, action); - } - - @Inject( - method = "onMouseScroll", - at = @At( - value = "FIELD", - target = "Lnet/minecraft/client/MinecraftClient;options:Lnet/minecraft/client/option/GameOptions;", - opcode = Opcodes.GETFIELD - ) - ) - private void injectOnMouseScroll(long window, double horizontal, double vertical, CallbackInfo ci) { - MouseListener.onRawMouseScroll(vertical); - } - - @Inject( - method = "method_55795(Lnet/minecraft/client/gui/screen/Screen;DDDD)V", - at = @At( - value = "INVOKE", - target = "Lnet/minecraft/client/gui/screen/Screen;mouseDragged(DDIDD)Z" - ), - cancellable = true - ) - private void injectOnGuiMouseDrag(Screen screen, double d, double e, double f, double g, CallbackInfo ci) { - if (screen != null) { - CTEvents.GUI_MOUSE_DRAG.invoker().process(f, g, d, e, activeButton, screen, ci); - } - } -} diff --git a/src/main/java/com/chattriggers/ctjs/internal/mixins/NbtCompoundAccessor.java b/src/main/java/com/chattriggers/ctjs/internal/mixins/NbtCompoundAccessor.java deleted file mode 100644 index 32eb5508..00000000 --- a/src/main/java/com/chattriggers/ctjs/internal/mixins/NbtCompoundAccessor.java +++ /dev/null @@ -1,14 +0,0 @@ -package com.chattriggers.ctjs.internal.mixins; - -import net.minecraft.nbt.NbtCompound; -import net.minecraft.nbt.NbtElement; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.gen.Accessor; - -import java.util.Map; - -@Mixin(NbtCompound.class) -public interface NbtCompoundAccessor { - @Accessor - Map getEntries(); -} diff --git a/src/main/java/com/chattriggers/ctjs/internal/mixins/OptionsMixin.java b/src/main/java/com/chattriggers/ctjs/internal/mixins/OptionsMixin.java new file mode 100644 index 00000000..901fe467 --- /dev/null +++ b/src/main/java/com/chattriggers/ctjs/internal/mixins/OptionsMixin.java @@ -0,0 +1,21 @@ +package com.chattriggers.ctjs.internal.mixins; + +import com.chattriggers.ctjs.api.CustomKeyMapping; +import net.minecraft.client.Options; +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(Options.class) +public class OptionsMixin { + @Inject(method = "save", at = @At("RETURN")) + public void save(CallbackInfo ci) { + CustomKeyMapping.INSTANCE.save(); + } + + @Inject(method = "load", at = @At("RETURN")) + public void load(CallbackInfo ci) { + CustomKeyMapping.INSTANCE.load(); + } +} diff --git a/src/main/java/com/chattriggers/ctjs/internal/mixins/ParticleAccessor.java b/src/main/java/com/chattriggers/ctjs/internal/mixins/ParticleAccessor.java deleted file mode 100644 index 1c3a9b07..00000000 --- a/src/main/java/com/chattriggers/ctjs/internal/mixins/ParticleAccessor.java +++ /dev/null @@ -1,98 +0,0 @@ -package com.chattriggers.ctjs.internal.mixins; - -import net.minecraft.client.particle.Particle; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.gen.Accessor; - -@Mixin(Particle.class) -public interface ParticleAccessor { - @Accessor(value = "x") - double getX(); - - @Accessor(value = "x") - void setX(double value); - - @Accessor(value = "y") - double getY(); - - @Accessor(value = "y") - void setY(double value); - - @Accessor(value = "z") - double getZ(); - - @Accessor(value = "z") - void setZ(double value); - - @Accessor - double getVelocityX(); - - @Accessor - void setVelocityX(double value); - - @Accessor - double getVelocityY(); - - @Accessor - void setVelocityY(double value); - - @Accessor - double getVelocityZ(); - - @Accessor - void setVelocityZ(double value); - - @Accessor - float getRed(); - - @Accessor - void setRed(float value); - - @Accessor - float getGreen(); - - @Accessor - void setGreen(float value); - - @Accessor - float getBlue(); - - @Accessor - void setBlue(float value); - - @Accessor - float getAlpha(); - - @Accessor - void setAlpha(float value); - - @Accessor - int getAge(); - - @Accessor - void setAge(int value); - - @Accessor - double getPrevPosX(); - - @Accessor - void setPrevPosX(double value); - - @Accessor - double getPrevPosY(); - - @Accessor - void setPrevPosY(double value); - - @Accessor - double getPrevPosZ(); - - @Accessor - void setPrevPosZ(double value); - - @Accessor - boolean getDead(); - - @Accessor - void setDead(boolean value); -} diff --git a/src/main/java/com/chattriggers/ctjs/internal/mixins/ParticleManagerMixin.java b/src/main/java/com/chattriggers/ctjs/internal/mixins/ParticleManagerMixin.java deleted file mode 100644 index f0c594b1..00000000 --- a/src/main/java/com/chattriggers/ctjs/internal/mixins/ParticleManagerMixin.java +++ /dev/null @@ -1,17 +0,0 @@ -package com.chattriggers.ctjs.internal.mixins; - -import com.chattriggers.ctjs.api.triggers.TriggerType; -import net.minecraft.client.particle.Particle; -import net.minecraft.client.particle.ParticleManager; -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(ParticleManager.class) -public class ParticleManagerMixin { - @Inject(method = "addParticle(Lnet/minecraft/client/particle/Particle;)V", at = @At("HEAD"), cancellable = true) - private void injectAddParticle(Particle particle, CallbackInfo ci) { - TriggerType.SPAWN_PARTICLE.triggerAll(new com.chattriggers.ctjs.api.entity.Particle(particle), ci); - } -} diff --git a/src/main/java/com/chattriggers/ctjs/internal/mixins/PlayerEntityMixin.java b/src/main/java/com/chattriggers/ctjs/internal/mixins/PlayerEntityMixin.java deleted file mode 100644 index 8e2ac39c..00000000 --- a/src/main/java/com/chattriggers/ctjs/internal/mixins/PlayerEntityMixin.java +++ /dev/null @@ -1,66 +0,0 @@ -package com.chattriggers.ctjs.internal.mixins; - -import com.chattriggers.ctjs.api.triggers.TriggerType; -import com.chattriggers.ctjs.internal.NameTagOverridable; -import com.chattriggers.ctjs.api.message.TextComponent; -import net.minecraft.entity.Entity; -import net.minecraft.entity.EntityType; -import net.minecraft.entity.LivingEntity; -import net.minecraft.entity.player.PlayerEntity; -import net.minecraft.text.MutableText; -import net.minecraft.world.World; -import org.jetbrains.annotations.Nullable; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Unique; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.ModifyVariable; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; - -@Mixin(PlayerEntity.class) -public abstract class PlayerEntityMixin extends LivingEntity implements NameTagOverridable { - @Unique - private TextComponent overriddenNametagName; - - protected PlayerEntityMixin(EntityType entityType, World world) { - super(entityType, world); - } - - @ModifyVariable(method = "getDisplayName", at = @At(value = "STORE", ordinal = 0)) - private MutableText injectGetName(MutableText original) { - if (overriddenNametagName != null) - return overriddenNametagName.toMutableText$ctjs(); - return original; - } - - @Inject( - method = "attack", - at = @At( - value = "INVOKE", - target = "Lnet/minecraft/entity/Entity;damage(Lnet/minecraft/entity/damage/DamageSource;F)Z" - ) - ) - private void chattriggers$entityDamage(Entity target, CallbackInfo ci) { - if (getWorld().isClient) { - TriggerType.ENTITY_DAMAGE.triggerAll(com.chattriggers.ctjs.api.entity.Entity.fromMC(target)); - } - } - - @Inject( - method = "attack", - at = @At( - value = "INVOKE", - target = "Lnet/minecraft/entity/LivingEntity;damage(Lnet/minecraft/entity/damage/DamageSource;F)Z" - ) - ) - private void chattriggers$entityDamageSweeping(Entity target, CallbackInfo ci) { - if (getWorld().isClient) { - TriggerType.ENTITY_DAMAGE.triggerAll(com.chattriggers.ctjs.api.entity.Entity.fromMC(target)); - } - } - - @Override - public void ctjs_setOverriddenNametagName(@Nullable TextComponent component) { - overriddenNametagName = component; - } -} diff --git a/src/main/java/com/chattriggers/ctjs/internal/mixins/PlayerListEntryAccessor.java b/src/main/java/com/chattriggers/ctjs/internal/mixins/PlayerListEntryAccessor.java deleted file mode 100644 index 1e23edcd..00000000 --- a/src/main/java/com/chattriggers/ctjs/internal/mixins/PlayerListEntryAccessor.java +++ /dev/null @@ -1,11 +0,0 @@ -package com.chattriggers.ctjs.internal.mixins; - -import net.minecraft.client.network.PlayerListEntry; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.gen.Invoker; - -@Mixin(PlayerListEntry.class) -public interface PlayerListEntryAccessor { - @Invoker - void invokeSetLatency(int latency); -} diff --git a/src/main/java/com/chattriggers/ctjs/internal/mixins/PlayerListHudAccessor.java b/src/main/java/com/chattriggers/ctjs/internal/mixins/PlayerListHudAccessor.java deleted file mode 100644 index 3ea0bebc..00000000 --- a/src/main/java/com/chattriggers/ctjs/internal/mixins/PlayerListHudAccessor.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.chattriggers.ctjs.internal.mixins; - -import net.minecraft.client.gui.hud.PlayerListHud; -import net.minecraft.text.Text; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.gen.Accessor; - -@Mixin(PlayerListHud.class) -public interface PlayerListHudAccessor { - @Accessor - Text getHeader(); - - @Accessor - Text getFooter(); -} diff --git a/src/main/java/com/chattriggers/ctjs/internal/mixins/PlayerListHudMixin.java b/src/main/java/com/chattriggers/ctjs/internal/mixins/PlayerListHudMixin.java deleted file mode 100644 index 521e2963..00000000 --- a/src/main/java/com/chattriggers/ctjs/internal/mixins/PlayerListHudMixin.java +++ /dev/null @@ -1,35 +0,0 @@ -package com.chattriggers.ctjs.internal.mixins; - -import com.chattriggers.ctjs.api.triggers.TriggerType; -import com.chattriggers.ctjs.api.world.TabList; -import net.minecraft.client.gui.DrawContext; -import net.minecraft.client.gui.hud.PlayerListHud; -import net.minecraft.scoreboard.Scoreboard; -import net.minecraft.scoreboard.ScoreboardObjective; -import net.minecraft.text.Text; -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(PlayerListHud.class) -public class PlayerListHudMixin { - @Inject(method = "render", at = @At("HEAD"), cancellable = true) - private void injectRenderPlayerList(DrawContext context, int scaledWindowWidth, Scoreboard scoreboard, ScoreboardObjective objective, CallbackInfo ci) { - TriggerType.RENDER_PLAYER_LIST.triggerAll(ci); - } - - @Inject(method = "setHeader", at = @At("HEAD"), cancellable = true) - private void ctjs$keepCustomHeader(Text header, CallbackInfo ci) { - if (TabList.INSTANCE.getCustomHeader$ctjs()) { - ci.cancel(); - } - } - - @Inject(method = "setFooter", at = @At("HEAD"), cancellable = true) - private void ctjs$keepCustomFooter(Text footer, CallbackInfo ci) { - if (TabList.INSTANCE.getCustomFooter$ctjs()) { - ci.cancel(); - } - } -} diff --git a/src/main/java/com/chattriggers/ctjs/internal/mixins/PlayerScreenHandlerMixin.java b/src/main/java/com/chattriggers/ctjs/internal/mixins/PlayerScreenHandlerMixin.java deleted file mode 100644 index e5a33e1c..00000000 --- a/src/main/java/com/chattriggers/ctjs/internal/mixins/PlayerScreenHandlerMixin.java +++ /dev/null @@ -1,43 +0,0 @@ -package com.chattriggers.ctjs.internal.mixins; - -import com.chattriggers.ctjs.api.inventory.Item; -import com.chattriggers.ctjs.api.triggers.CancellableEvent; -import com.chattriggers.ctjs.api.triggers.TriggerType; -import net.minecraft.entity.player.PlayerEntity; -import net.minecraft.inventory.RecipeInputInventory; -import net.minecraft.item.ItemStack; -import net.minecraft.screen.PlayerScreenHandler; -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(PlayerScreenHandler.class) -public class PlayerScreenHandlerMixin { - @Shadow - @Final - private RecipeInputInventory craftingInput; - - @Inject( - method = "onClosed", - at = @At( - value = "INVOKE", - target = "Lnet/minecraft/inventory/CraftingResultInventory;clear()V", - shift = At.Shift.AFTER - ) - ) - private void injectOnClosed(PlayerEntity player, CallbackInfo ci) { - // dropping items for player's crafting slots. needs a whole injection point due to there - // being an extra if to make sure it only calls dropInventory server-side - if (player.getWorld().isClient) { - for (int i = 0; i < craftingInput.size(); i++) { - ItemStack stack = craftingInput.getStack(i); - if (!stack.isEmpty()) { - TriggerType.DROP_ITEM.triggerAll(Item.fromMC(stack), true, new CancellableEvent()); - } - } - } - } -} diff --git a/src/main/java/com/chattriggers/ctjs/internal/mixins/RenderTickCounterMixin.java b/src/main/java/com/chattriggers/ctjs/internal/mixins/RenderTickCounterMixin.java deleted file mode 100644 index 4a0b2013..00000000 --- a/src/main/java/com/chattriggers/ctjs/internal/mixins/RenderTickCounterMixin.java +++ /dev/null @@ -1,16 +0,0 @@ -package com.chattriggers.ctjs.internal.mixins; - -import com.chattriggers.ctjs.internal.engine.CTEvents; -import net.minecraft.client.render.RenderTickCounter; -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; - -@Mixin(RenderTickCounter.Dynamic.class) -public class RenderTickCounterMixin { - @Inject(method = "beginRenderTick(J)I", at = @At("HEAD")) - private void injectBeginRenderTick(long timeMillis, CallbackInfoReturnable cir) { - CTEvents.RENDER_TICK.invoker().invoke(); - } -} diff --git a/src/main/java/com/chattriggers/ctjs/internal/mixins/Scoreboard$1Accessor.java b/src/main/java/com/chattriggers/ctjs/internal/mixins/Scoreboard$1Accessor.java deleted file mode 100644 index 3c9124bd..00000000 --- a/src/main/java/com/chattriggers/ctjs/internal/mixins/Scoreboard$1Accessor.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.chattriggers.ctjs.internal.mixins; - -import net.minecraft.scoreboard.ScoreHolder; -import net.minecraft.scoreboard.ScoreboardScore; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.gen.Accessor; - -@Mixin(targets = "net.minecraft.scoreboard.Scoreboard$1") -public interface Scoreboard$1Accessor { - @Accessor("field_47543") - ScoreboardScore getScore(); - - @Accessor("field_47547") - ScoreHolder getHolder(); -} diff --git a/src/main/java/com/chattriggers/ctjs/internal/mixins/ScoreboardObjectiveMixin.java b/src/main/java/com/chattriggers/ctjs/internal/mixins/ScoreboardObjectiveMixin.java deleted file mode 100644 index f8b2cffa..00000000 --- a/src/main/java/com/chattriggers/ctjs/internal/mixins/ScoreboardObjectiveMixin.java +++ /dev/null @@ -1,19 +0,0 @@ -package com.chattriggers.ctjs.internal.mixins; - -import com.chattriggers.ctjs.api.world.Scoreboard; -import net.minecraft.scoreboard.ScoreboardObjective; -import net.minecraft.text.Text; -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(ScoreboardObjective.class) -public class ScoreboardObjectiveMixin { - @Inject(method = "setDisplayName", at = @At("HEAD"), cancellable = true) - private void chattriggers$keepCustomName(Text name, CallbackInfo ci) { - if (Scoreboard.INSTANCE.getCustomTitle$ctjs()) { - ci.cancel(); - } - } -} diff --git a/src/main/java/com/chattriggers/ctjs/internal/mixins/ScreenHandlerMixin.java b/src/main/java/com/chattriggers/ctjs/internal/mixins/ScreenHandlerMixin.java deleted file mode 100644 index b42d303f..00000000 --- a/src/main/java/com/chattriggers/ctjs/internal/mixins/ScreenHandlerMixin.java +++ /dev/null @@ -1,29 +0,0 @@ -package com.chattriggers.ctjs.internal.mixins; - -import com.chattriggers.ctjs.api.triggers.CancellableEvent; -import com.chattriggers.ctjs.api.inventory.Item; -import com.chattriggers.ctjs.api.triggers.TriggerType; -import net.minecraft.entity.player.PlayerEntity; -import net.minecraft.inventory.Inventory; -import net.minecraft.item.ItemStack; -import net.minecraft.screen.ScreenHandler; -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(ScreenHandler.class) -public class ScreenHandlerMixin { - @Inject(method = "dropInventory", at = @At("HEAD")) - private void injectDropInventory(PlayerEntity player, Inventory inventory, CallbackInfo ci) { - // dropping items for guis that don't keep items in them while the gui is closed - if (inventory != player.playerScreenHandler.getCraftingInput()) { - for (int i = 0; i < inventory.size(); i++) { - ItemStack stack = inventory.getStack(i); - if (!stack.isEmpty()) { - TriggerType.DROP_ITEM.triggerAll(Item.fromMC(stack), true, new CancellableEvent()); - } - } - } - } -} diff --git a/src/main/java/com/chattriggers/ctjs/internal/mixins/SystemDetailsMixin.java b/src/main/java/com/chattriggers/ctjs/internal/mixins/SystemDetailsMixin.java index 1b69966f..28d17a98 100644 --- a/src/main/java/com/chattriggers/ctjs/internal/mixins/SystemDetailsMixin.java +++ b/src/main/java/com/chattriggers/ctjs/internal/mixins/SystemDetailsMixin.java @@ -3,7 +3,7 @@ import com.chattriggers.ctjs.internal.engine.module.Module; import com.chattriggers.ctjs.internal.engine.module.ModuleManager; import com.chattriggers.ctjs.internal.engine.module.ModuleMetadata; -import net.minecraft.util.SystemDetails; +import net.minecraft.SystemReport; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; @@ -15,14 +15,14 @@ import java.util.List; import java.util.function.Supplier; -@Mixin(SystemDetails.class) +@Mixin(SystemReport.class) public abstract class SystemDetailsMixin { @Shadow - public abstract void addSection(String string, Supplier supplier); + public abstract void setDetail(String string, Supplier supplier); @Inject(method = "", at = @At("RETURN")) private void addModules(CallbackInfo ci) { - addSection("ChatTriggers Modules", () -> { + setDetail("ChatTriggers Modules", () -> { List modules = new ArrayList<>(ModuleManager.INSTANCE.getCachedModules()); modules.sort(Comparator.comparing(Module::getName)); @@ -37,7 +37,7 @@ private void addModules(CallbackInfo ci) { ModuleMetadata metadata = module.getMetadata(); if (metadata.getVersion() != null) { - sb.append("v") + sb.append("v") .append(module.getMetadata().getVersion()); } else { sb.append("No module version specified"); diff --git a/src/main/java/com/chattriggers/ctjs/internal/mixins/commands/ClientCommandSourceMixin.java b/src/main/java/com/chattriggers/ctjs/internal/mixins/commands/ClientCommandSourceMixin.java deleted file mode 100644 index a50d752d..00000000 --- a/src/main/java/com/chattriggers/ctjs/internal/mixins/commands/ClientCommandSourceMixin.java +++ /dev/null @@ -1,25 +0,0 @@ -package com.chattriggers.ctjs.internal.mixins.commands; - -import com.chattriggers.ctjs.internal.CTClientCommandSource; -import net.minecraft.client.network.ClientCommandSource; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Unique; - -import java.util.HashMap; - -@SuppressWarnings("AddedMixinMembersNamePattern") -@Mixin(ClientCommandSource.class) -public abstract class ClientCommandSourceMixin implements CTClientCommandSource { - @Unique - private final HashMap contextValues = new HashMap<>(); - - @Override - public void setContextValue(String key, Object value) { - contextValues.put(key, value); - } - - @Override - public HashMap getContextValues() { - return contextValues; - } -} diff --git a/src/main/java/com/chattriggers/ctjs/internal/mixins/commands/ClientPlayNetworkHandlerMixin.java b/src/main/java/com/chattriggers/ctjs/internal/mixins/commands/ClientPlayNetworkHandlerMixin.java deleted file mode 100644 index 9b24597b..00000000 --- a/src/main/java/com/chattriggers/ctjs/internal/mixins/commands/ClientPlayNetworkHandlerMixin.java +++ /dev/null @@ -1,27 +0,0 @@ -package com.chattriggers.ctjs.internal.mixins.commands; - -import com.chattriggers.ctjs.internal.engine.CTEvents; -import com.mojang.brigadier.CommandDispatcher; -import net.fabricmc.fabric.api.client.command.v2.FabricClientCommandSource; -import net.minecraft.client.network.ClientPlayNetworkHandler; -import net.minecraft.command.CommandSource; -import net.minecraft.network.packet.s2c.play.CommandTreeS2CPacket; -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(ClientPlayNetworkHandler.class) -public class ClientPlayNetworkHandlerMixin { - @Shadow - private CommandDispatcher commandDispatcher; - - @Inject(method = "onCommandTree", at = @At("TAIL")) - private void injectOnCommandTree(CommandTreeS2CPacket packet, CallbackInfo ci) { - //noinspection unchecked - CTEvents.NETWORK_COMMAND_DISPATCHER_REGISTER.invoker().register( - (CommandDispatcher) (Object) commandDispatcher - ); - } -} diff --git a/src/main/java/com/chattriggers/ctjs/internal/mixins/commands/CommandContextAccessor.java b/src/main/java/com/chattriggers/ctjs/internal/mixins/commands/CommandContextAccessor.java deleted file mode 100644 index 29ce6c1c..00000000 --- a/src/main/java/com/chattriggers/ctjs/internal/mixins/commands/CommandContextAccessor.java +++ /dev/null @@ -1,14 +0,0 @@ -package com.chattriggers.ctjs.internal.mixins.commands; - -import com.mojang.brigadier.context.CommandContext; -import com.mojang.brigadier.context.ParsedArgument; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.gen.Accessor; - -import java.util.Map; - -@Mixin(value = CommandContext.class, remap = false) -public interface CommandContextAccessor { - @Accessor - Map> getArguments(); -} diff --git a/src/main/java/com/chattriggers/ctjs/internal/mixins/commands/CommandDispatcherMixin.java b/src/main/java/com/chattriggers/ctjs/internal/mixins/commands/CommandDispatcherMixin.java deleted file mode 100644 index b6fa19c0..00000000 --- a/src/main/java/com/chattriggers/ctjs/internal/mixins/commands/CommandDispatcherMixin.java +++ /dev/null @@ -1,37 +0,0 @@ -package com.chattriggers.ctjs.internal.mixins.commands; - -import com.llamalad7.mixinextras.sugar.Local; -import com.mojang.brigadier.CommandDispatcher; -import com.mojang.brigadier.ParseResults; -import com.mojang.brigadier.StringReader; -import com.mojang.brigadier.context.CommandContextBuilder; -import com.mojang.brigadier.tree.CommandNode; -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; - -@Mixin(value = CommandDispatcher.class, remap = false) -public class CommandDispatcherMixin { - @Inject( - method = "parseNodes", - at = @At( - value = "INVOKE", - target = "Lcom/mojang/brigadier/context/CommandContextBuilder;withCommand(Lcom/mojang/brigadier/Command;)Lcom/mojang/brigadier/context/CommandContextBuilder;", - shift = At.Shift.AFTER - ) - ) - private void addRedirectCommandToContextIfNecessary( - CommandNode node, - StringReader originalReader, - CommandContextBuilder contextSoFar, - CallbackInfoReturnable> cir, - @Local(ordinal = 1) CommandNode child, - @Local(ordinal = 1) CommandContextBuilder context - ) { - // TODO: If there is a redirect modifier, this fix will ignore it. - - if (context.getCommand() == null && child.getRedirect() != null && child.getRedirect().getCommand() != null) - context.withCommand(child.getRedirect().getCommand()); - } -} diff --git a/src/main/java/com/chattriggers/ctjs/internal/mixins/commands/EntitySelectorAccessor.java b/src/main/java/com/chattriggers/ctjs/internal/mixins/commands/EntitySelectorAccessor.java deleted file mode 100644 index 7e1e8f55..00000000 --- a/src/main/java/com/chattriggers/ctjs/internal/mixins/commands/EntitySelectorAccessor.java +++ /dev/null @@ -1,52 +0,0 @@ -package com.chattriggers.ctjs.internal.mixins.commands; - -import net.minecraft.command.EntitySelector; -import net.minecraft.entity.Entity; -import net.minecraft.predicate.NumberRange; -import net.minecraft.util.TypeFilter; -import net.minecraft.util.math.Box; -import net.minecraft.util.math.Vec3d; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.gen.Accessor; - -import java.util.List; -import java.util.UUID; -import java.util.function.BiConsumer; -import java.util.function.Function; -import java.util.function.Predicate; - -@Mixin(EntitySelector.class) -public interface EntitySelectorAccessor { - @Accessor - int getLimit(); - - @Accessor - boolean getIncludesNonPlayers(); - - @Accessor - List> getPredicates(); - - @Accessor - NumberRange.DoubleRange getDistance(); - - @Accessor - Function getPositionOffset(); - - @Accessor - Box getBox(); - - @Accessor - BiConsumer> getSorter(); - - @Accessor - boolean getSenderOnly(); - - @Accessor - String getPlayerName(); - - @Accessor - UUID getUuid(); - - @Accessor - TypeFilter getEntityFilter(); -} diff --git a/src/main/java/com/chattriggers/ctjs/internal/mixins/sound/SoundAccessor.java b/src/main/java/com/chattriggers/ctjs/internal/mixins/sound/SoundAccessor.java deleted file mode 100644 index 162ba6cd..00000000 --- a/src/main/java/com/chattriggers/ctjs/internal/mixins/sound/SoundAccessor.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.chattriggers.ctjs.internal.mixins.sound; - -import net.minecraft.client.sound.Sound; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Mutable; -import org.spongepowered.asm.mixin.gen.Accessor; - -@Mixin(Sound.class) -public interface SoundAccessor { - @Accessor - @Mutable - void setAttenuation(int attenuation); -} diff --git a/src/main/java/com/chattriggers/ctjs/internal/mixins/sound/SoundManagerAccessor.java b/src/main/java/com/chattriggers/ctjs/internal/mixins/sound/SoundManagerAccessor.java deleted file mode 100644 index 689e4a8d..00000000 --- a/src/main/java/com/chattriggers/ctjs/internal/mixins/sound/SoundManagerAccessor.java +++ /dev/null @@ -1,23 +0,0 @@ -package com.chattriggers.ctjs.internal.mixins.sound; - -import net.minecraft.client.sound.SoundManager; -import net.minecraft.client.sound.SoundSystem; -import net.minecraft.client.sound.WeightedSoundSet; -import net.minecraft.resource.Resource; -import net.minecraft.util.Identifier; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.gen.Accessor; - -import java.util.Map; - -@Mixin(SoundManager.class) -public interface SoundManagerAccessor { - @Accessor - SoundSystem getSoundSystem(); - - @Accessor - Map getSounds(); - - @Accessor - Map getSoundResources(); -} diff --git a/src/main/java/com/chattriggers/ctjs/internal/mixins/sound/SoundSystemAccessor.java b/src/main/java/com/chattriggers/ctjs/internal/mixins/sound/SoundSystemAccessor.java deleted file mode 100644 index d530dee3..00000000 --- a/src/main/java/com/chattriggers/ctjs/internal/mixins/sound/SoundSystemAccessor.java +++ /dev/null @@ -1,25 +0,0 @@ -package com.chattriggers.ctjs.internal.mixins.sound; - -import net.minecraft.client.sound.Channel; -import net.minecraft.client.sound.SoundInstance; -import net.minecraft.client.sound.SoundSystem; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.gen.Accessor; -import org.spongepowered.asm.mixin.gen.Invoker; - -import java.util.Map; - -@Mixin(SoundSystem.class) -public interface SoundSystemAccessor { - @Accessor - Channel getChannel(); - - @Accessor - Map getSources(); - - @Invoker - void invokeStart(); - - @Invoker - void invokeTick(); -} diff --git a/src/main/java/com/chattriggers/ctjs/internal/mixins/sound/SoundSystemMixin.java b/src/main/java/com/chattriggers/ctjs/internal/mixins/sound/SoundSystemMixin.java deleted file mode 100644 index 3337b61f..00000000 --- a/src/main/java/com/chattriggers/ctjs/internal/mixins/sound/SoundSystemMixin.java +++ /dev/null @@ -1,38 +0,0 @@ -package com.chattriggers.ctjs.internal.mixins.sound; - -import com.chattriggers.ctjs.api.triggers.TriggerType; -import com.chattriggers.ctjs.api.vec.Vec3f; -import net.minecraft.client.sound.SoundInstance; -import net.minecraft.client.sound.SoundSystem; -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(SoundSystem.class) -public class SoundSystemMixin { - @Inject(method = "play(Lnet/minecraft/client/sound/SoundInstance;)V", at = @At("HEAD"), cancellable = true) - private void injectPlay(SoundInstance sound, CallbackInfo ci) { - float volume = 0f; - float pitch = 0f; - - try { - volume = sound.getVolume(); - } catch (Throwable ignored) { - } - - try { - pitch = sound.getPitch(); - } catch (Throwable ignored) { - } - - TriggerType.SOUND_PLAY.triggerAll( - new Vec3f((float) sound.getX(), (float) sound.getY(), (float) sound.getZ()), - sound.getId().toString(), - volume, - pitch, - sound.getCategory(), - ci - ); - } -} diff --git a/src/main/java/com/chattriggers/ctjs/internal/mixins/sound/SourceAccessor.java b/src/main/java/com/chattriggers/ctjs/internal/mixins/sound/SourceAccessor.java deleted file mode 100644 index 3aae2c00..00000000 --- a/src/main/java/com/chattriggers/ctjs/internal/mixins/sound/SourceAccessor.java +++ /dev/null @@ -1,11 +0,0 @@ -package com.chattriggers.ctjs.internal.mixins.sound; - -import net.minecraft.client.sound.Source; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.gen.Invoker; - -@Mixin(Source.class) -public interface SourceAccessor { - @Invoker - int invokeGetSourceState(); -} diff --git a/src/main/java/com/chattriggers/ctjs/internal/mixins/stdio/BootstrapMixin.java b/src/main/java/com/chattriggers/ctjs/internal/mixins/stdio/BootstrapMixin.java deleted file mode 100644 index db84990e..00000000 --- a/src/main/java/com/chattriggers/ctjs/internal/mixins/stdio/BootstrapMixin.java +++ /dev/null @@ -1,18 +0,0 @@ -package com.chattriggers.ctjs.internal.mixins.stdio; - -import com.chattriggers.ctjs.internal.launch.CTMixinPlugin; -import net.minecraft.Bootstrap; -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(Bootstrap.class) -public class BootstrapMixin { - @Inject(method = "setOutputStreams", at = @At("HEAD")) - private static void injectSetOutputStreams(CallbackInfo ci) { - // MC will re-wrap the output streams, so we restore them to their original state - // so they don't end up double-wrapped. - CTMixinPlugin.restoreOutputStreams(); - } -} diff --git a/src/main/java/com/chattriggers/ctjs/internal/mixins/stdio/LoggerPrintStreamMixin.java b/src/main/java/com/chattriggers/ctjs/internal/mixins/stdio/LoggerPrintStreamMixin.java index 7a297e2f..cc635267 100644 --- a/src/main/java/com/chattriggers/ctjs/internal/mixins/stdio/LoggerPrintStreamMixin.java +++ b/src/main/java/com/chattriggers/ctjs/internal/mixins/stdio/LoggerPrintStreamMixin.java @@ -1,17 +1,17 @@ package com.chattriggers.ctjs.internal.mixins.stdio; -import net.minecraft.util.logging.LoggerPrintStream; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; import java.io.PrintStream; +import net.minecraft.server.LoggedPrintStream; // Add additional overrides so that org.spongepowered.asm.util.PrettyPrinter // will output to the log file. -@Mixin(LoggerPrintStream.class) +@Mixin(LoggedPrintStream.class) public class LoggerPrintStreamMixin { @Shadow - protected void log(String message) { + protected void logLine(String message) { throw new IllegalStateException(); } @@ -22,7 +22,7 @@ public PrintStream printf(String format, Object... args) { String formatted = format.formatted(args); if (!formatted.isEmpty() && formatted.charAt(formatted.length() - 1) == '\n') formatted = formatted.substring(0, formatted.length() - 1); - log(formatted); - return (LoggerPrintStream) (Object) this; + logLine(formatted); + return (LoggedPrintStream) (Object) this; } } diff --git a/src/main/kotlin/com/chattriggers/ctjs/CTJS.kt b/src/main/kotlin/com/chattriggers/ctjs/CTJS.kt index 84281017..00a3fe57 100644 --- a/src/main/kotlin/com/chattriggers/ctjs/CTJS.kt +++ b/src/main/kotlin/com/chattriggers/ctjs/CTJS.kt @@ -1,65 +1,30 @@ package com.chattriggers.ctjs -import com.chattriggers.ctjs.api.Config -import com.chattriggers.ctjs.api.client.Client -import com.chattriggers.ctjs.api.client.KeyBind -import com.chattriggers.ctjs.api.client.Player -import com.chattriggers.ctjs.api.client.Sound -import com.chattriggers.ctjs.api.commands.DynamicCommands -import com.chattriggers.ctjs.api.message.ChatLib -import com.chattriggers.ctjs.api.render.Image -import com.chattriggers.ctjs.api.triggers.TriggerType -import com.chattriggers.ctjs.api.world.Scoreboard -import com.chattriggers.ctjs.api.world.World +import com.chattriggers.ctjs.api.CustomCommand import com.chattriggers.ctjs.engine.Console import com.chattriggers.ctjs.engine.Register -import com.chattriggers.ctjs.internal.commands.StaticCommand import com.chattriggers.ctjs.internal.engine.module.ModuleManager import com.chattriggers.ctjs.internal.utils.Initializer import kotlinx.serialization.json.Json import net.fabricmc.api.ClientModInitializer import net.fabricmc.loader.api.FabricLoader +import net.minecraft.client.Minecraft import java.io.File import java.net.URI -import java.net.URL import java.net.URLConnection -import java.security.MessageDigest -import java.util.* import kotlin.concurrent.thread class CTJS : ClientModInitializer { override fun onInitializeClient() { - Client.referenceSystemTime = System.nanoTime() Initializer.initializers.forEach(Initializer::init) - thread { - reportHashedUUID() - } - - Config.loadData() - Runtime.getRuntime().addShutdownHook(Thread { - TriggerType.GAME_UNLOAD.triggerAll() Console.close() }) } - private fun reportHashedUUID() { - val uuid = Player.getUUID().toString().encodeToByteArray() - val salt = (System.getProperty("user.name") ?: "").encodeToByteArray() - val md = MessageDigest.getInstance("SHA-256") - md.update(salt) - val hashedUUID = md.digest(uuid) - val hash = Base64.getUrlEncoder().encodeToString(hashedUUID) - - val url = "$WEBSITE_ROOT/api/statistics/track?hash=$hash&version=$MOD_VERSION" - val connection = makeWebRequest(url) - connection.getInputStream() - } - companion object { const val MOD_ID = "ctjs" - const val WEBSITE_ROOT = "https://www.chattriggers.com" const val MOD_VERSION = "3.0.0-beta" const val MODULES_FOLDER = "./config/ChatTriggers/modules" @@ -70,8 +35,6 @@ class CTJS : ClientModInitializer { var isLoaded = true private set - internal val images = mutableListOf() - internal val sounds = mutableListOf() internal val isDevelopment = FabricLoader.getInstance().isDevelopmentEnvironment internal val json = Json { @@ -88,58 +51,30 @@ class CTJS : ClientModInitializer { } @JvmStatic - fun unload(asCommand: Boolean = true) { - TriggerType.WORLD_UNLOAD.triggerAll() - TriggerType.GAME_UNLOAD.triggerAll() - Scoreboard.clearCustom() - + fun unload() { isLoaded = false ModuleManager.teardown() - KeyBind.clearKeyBinds() Register.clearCustomTriggers() - StaticCommand.unregisterAll() - DynamicCommands.unregisterAll() - - if (Config.clearConsoleOnLoad) - Console.clear() + CustomCommand.unregisterAll() - Client.scheduleTask { - images.forEach(Image::destroy) - sounds.forEach(Sound::destroy) - - images.clear() - sounds.clear() - } - - if (asCommand) - ChatLib.chat("&7Unloaded ChatTriggers") + Console.clear() } @JvmStatic - fun load(asCommand: Boolean = true) { - Client.getMinecraft().options.write() - unload(asCommand = false) - - if (asCommand) - ChatLib.chat("&cReloading ChatTriggers...") + fun load() { + Minecraft.getInstance().options.save() + unload() thread { ModuleManager.setup() - Client.getMinecraft().options.load() + Minecraft.getInstance().options.load() // Need to set isLoaded to true before running modules, otherwise custom triggers // activated at the top level will not work isLoaded = true ModuleManager.entryPass() - - if (asCommand) - ChatLib.chat("&aDone reloading!") - - TriggerType.GAME_LOAD.triggerAll() - if (World.isLoaded()) - TriggerType.WORLD_LOAD.triggerAll() } } } diff --git a/src/main/kotlin/com/chattriggers/ctjs/api/CTWrapper.kt b/src/main/kotlin/com/chattriggers/ctjs/api/CTWrapper.kt deleted file mode 100644 index 6837b336..00000000 --- a/src/main/kotlin/com/chattriggers/ctjs/api/CTWrapper.kt +++ /dev/null @@ -1,7 +0,0 @@ -package com.chattriggers.ctjs.api - -interface CTWrapper { - val mcValue: MCClass - - fun toMC(): MCClass = mcValue -} diff --git a/src/main/kotlin/com/chattriggers/ctjs/api/Config.kt b/src/main/kotlin/com/chattriggers/ctjs/api/Config.kt deleted file mode 100644 index 29fc92f3..00000000 --- a/src/main/kotlin/com/chattriggers/ctjs/api/Config.kt +++ /dev/null @@ -1,209 +0,0 @@ -package com.chattriggers.ctjs.api - -import com.chattriggers.ctjs.CTJS -import com.chattriggers.ctjs.engine.Console -import com.chattriggers.ctjs.internal.utils.CategorySorting -import gg.essential.vigilance.Vigilant -import gg.essential.vigilance.data.Property -import gg.essential.vigilance.data.PropertyType -import java.awt.Color -import java.io.File -import kotlin.reflect.KProperty - -object Config : Vigilant(File(CTJS.configLocation, "ChatTriggers.toml"), sortingBehavior = CategorySorting) { - @JvmStatic - @Property( - PropertyType.SWITCH, - name = "Show module help on import", - category = "General", - description = "If a module is imported and it has a help message, display it in chat" - ) - var moduleImportHelp = true - - @JvmStatic - @Property( - PropertyType.SWITCH, - name = "Show module changelog on update", - category = "General", - description = "If a module is updated and it has a changelog, display it in chat" - ) - var moduleChangelog = true - - @JvmStatic - @Property( - PropertyType.SWITCH, - name = "Show updates in chat", - category = "General", - description = "Show CT module import/update messages in the chat", - ) - var showUpdatesInChat = true - - @JvmStatic - @Property( - PropertyType.SWITCH, - name = "Auto-update modules", - category = "General", - description = "Check for and download module updates every time CT loads", - ) - var autoUpdateModules = true - - @JvmStatic - @Property( - PropertyType.SWITCH, - name = "Clear console on CT load", - category = "Console", - ) - var clearConsoleOnLoad = true - - @JvmStatic - @Property( - PropertyType.SWITCH, - name = "Open console on error", - category = "Console", - description = "Opens the language-specific console if there is an error in a module", - ) - var openConsoleOnError = false - - @JvmStatic - @Property( - PropertyType.SWITCH, - name = "Use Fira Code font for console", - category = "Console", - ) - var consoleFiraCodeFont = true - - @JvmStatic - @Property( - PropertyType.NUMBER, - name = "Console font size", - category = "Console", - min = 6, - max = 32, - ) - var consoleFontSize = 12 - - @JvmStatic - @Property( - PropertyType.SWITCH, - name = "Use custom console theme", - category = "Console", - ) - var customTheme = false - - @JvmStatic - @Property( - PropertyType.SELECTOR, - name = "Console theme", - category = "Console", - options = [ - "Default Dark", - "Ashes Dark", - "Atelierforest Dark", - "Isotope Dark", - "Codeschool Dark", - "Gotham", - "Hybrid", - "3024 Light", - "Chalk Light", - "Blue", - "Slate", - "Red", - "Green", - "Aids" - ] - ) - var consoleTheme = 0 - - @JvmStatic - @Property( - PropertyType.COLOR, - name = "Console Text color", - category = "Console", - ) - var consoleTextColor = Color(208, 208, 208) - - @JvmStatic - @Property( - PropertyType.COLOR, - name = "Console background color", - category = "Console", - ) - var consoleBackgroundColor = Color(21, 21, 21) - - @JvmStatic - @Property( - PropertyType.COLOR, - name = "Console error color", - category = "Console", - ) - var consoleErrorColor = Color(225, 65, 73) - - @JvmStatic - @Property( - PropertyType.COLOR, - name = "Console warning color", - category = "Console", - ) - var consoleWarningColor = Color(248, 191, 84) - - init { - initialize() - - addDependency("consoleTextColor", "customTheme") - addDependency("consoleBackgroundColor", "customTheme") - addDependency("consoleErrorColor", "customTheme") - addDependency("consoleWarningColor", "customTheme") - - listenToConsoleProperty(::clearConsoleOnLoad) - listenToConsoleProperty(::openConsoleOnError) - listenToConsoleProperty(::consoleFiraCodeFont) - listenToConsoleProperty(::consoleFontSize) - listenToConsoleProperty(::customTheme) - listenToConsoleProperty(::consoleTheme) - listenToConsoleProperty(::consoleTextColor) - listenToConsoleProperty(::consoleBackgroundColor) - listenToConsoleProperty(::consoleErrorColor) - listenToConsoleProperty(::consoleWarningColor) - } - - private inline fun listenToConsoleProperty(property: KProperty) { - val field = ConsoleSettings::class.java.getDeclaredField(property.name) - field.isAccessible = true - - registerListener(property.name) { - val settings = ConsoleSettings.make() - field.set(settings, it) - Console.onConsoleSettingsChanged(settings) - } - } - - // The listener properties above get called before the property is updated, so we have - // to keep track of it ourselves and use the new value that is passed in - data class ConsoleSettings( - var clearConsoleOnLoad: Boolean, - var openConsoleOnError: Boolean, - var consoleFiraCodeFont: Boolean, - var consoleFontSize: Int, - var customTheme: Boolean, - var consoleTheme: Int, - var consoleTextColor: Color, - var consoleBackgroundColor: Color, - var consoleErrorColor: Color, - var consoleWarningColor: Color, - ) { - companion object { - fun make() = ConsoleSettings( - clearConsoleOnLoad, - openConsoleOnError, - consoleFiraCodeFont, - consoleFontSize, - customTheme, - consoleTheme, - consoleTextColor, - consoleBackgroundColor, - consoleErrorColor, - consoleWarningColor, - ) - } - } -} diff --git a/src/main/kotlin/com/chattriggers/ctjs/api/CustomCommand.kt b/src/main/kotlin/com/chattriggers/ctjs/api/CustomCommand.kt new file mode 100644 index 00000000..d455316a --- /dev/null +++ b/src/main/kotlin/com/chattriggers/ctjs/api/CustomCommand.kt @@ -0,0 +1,103 @@ +package com.chattriggers.ctjs.api + +import com.chattriggers.ctjs.engine.LogType +import com.chattriggers.ctjs.engine.printToConsole +import com.chattriggers.ctjs.internal.mixins.CommandNodeAccessor +import com.chattriggers.ctjs.internal.utils.Initializer +import com.mojang.brigadier.CommandDispatcher +import com.mojang.brigadier.arguments.ArgumentType +import com.mojang.brigadier.builder.ArgumentBuilder +import com.mojang.brigadier.builder.LiteralArgumentBuilder +import com.mojang.brigadier.builder.RequiredArgumentBuilder +import com.mojang.brigadier.context.CommandContext +import net.fabricmc.fabric.api.client.command.v2.ClientCommandRegistrationCallback +import net.fabricmc.fabric.api.client.networking.v1.ClientPlayConnectionEvents +import net.minecraft.commands.CommandSource + +object CustomCommand : Initializer { + private var commands: MutableSet Any>> = mutableSetOf() + private var clientDispatcher: CommandDispatcher? = null + private var networkDispatcher: CommandDispatcher? = null + + @Suppress("UNCHECKED_CAST") + override fun init() { + ClientCommandRegistrationCallback.EVENT.register { dispatcher, _ -> + this.clientDispatcher = dispatcher as CommandDispatcher + registerAll(dispatcher) + } + + ClientPlayConnectionEvents.DISCONNECT.register { _, _ -> + clientDispatcher = null + networkDispatcher = null + } + } + + internal fun registerNetwork(dispatcher: CommandDispatcher) { + networkDispatcher = dispatcher + registerAll(dispatcher) + } + + internal fun registerAll(dispatcher: CommandDispatcher) { + for ((name, callback) in commands) { + val cmd = CommandBuilder(name).apply { callback.invoke(builder()) } + dispatcher.register(cmd.build()) + } + } + + internal fun unregisterAll() { + for (dispatcher in listOfNotNull(clientDispatcher, networkDispatcher)) { + for ((name, _) in commands) { + (dispatcher.root as CommandNodeAccessor).let { + it.children.remove(name) + it.literals.remove(name) + } + } + } + + commands.clear() + } + + @JvmStatic + fun register(name: String, callback: (NodeBuilder) -> Any) { + commands.add(name to callback) + + if (clientDispatcher?.root?.getChild(name) != null || networkDispatcher?.root?.getChild(name) != null) { + "Command with $name already exists".printToConsole(LogType.WARN) + } else { + val cmd = CommandBuilder(name).apply { callback.invoke(builder()) } + clientDispatcher?.register(cmd.build()) + networkDispatcher?.register(cmd.build()) + } + } + + class CommandBuilder(val name: String) { + private val root = LiteralArgumentBuilder.literal(name) + + fun builder() = NodeBuilder(root) + + fun build(): LiteralArgumentBuilder = root + } + + open class NodeBuilder(val node: ArgumentBuilder) { + fun literal(s: String, callback: (NodeBuilder) -> Any): NodeBuilder { + val next = LiteralArgumentBuilder.literal(s) + callback.invoke(NodeBuilder(next)) + node.then(next) + return this + } + + fun argument(name: String, type: ArgumentType, callback: (NodeBuilder) -> Any): NodeBuilder { + val next = RequiredArgumentBuilder.argument(name, type) + callback.invoke(NodeBuilder(next)) + node.then(next) + return this + } + + fun exec(callback: (CommandContext) -> Any) { + node.executes { ctx -> + callback(ctx) + 1 + } + } + } +} diff --git a/src/main/kotlin/com/chattriggers/ctjs/api/CustomKeyMapping.kt b/src/main/kotlin/com/chattriggers/ctjs/api/CustomKeyMapping.kt new file mode 100644 index 00000000..22909b2e --- /dev/null +++ b/src/main/kotlin/com/chattriggers/ctjs/api/CustomKeyMapping.kt @@ -0,0 +1,86 @@ +package com.chattriggers.ctjs.api + +import com.chattriggers.ctjs.CTJS +import com.mojang.blaze3d.platform.InputConstants +import net.minecraft.client.KeyMapping +import net.minecraft.client.Minecraft +import net.minecraft.resources.Identifier + +object CustomKeyMapping { + private val SAVE_FILE = CTJS.configLocation.resolve("ctjs_key_mappings.txt") + private val KEY_MAP: HashMap = HashMap() + private val customKeyMappings: MutableList = mutableListOf() + private val customCategories: MutableList = mutableListOf() + + @JvmStatic + fun register(key: String, keyCode: Int, category: KeyMapping.Category): KeyMapping { + val customKeyMapping = customKeyMappings.find { it.name == key } + if (customKeyMapping != null) { + return customKeyMapping.load() + } + + if (!customCategories.contains(category)) { + customCategories.add(category) + } + + val keyMapping = KeyMapping(key, InputConstants.Type.KEYSYM, keyCode, category).load() + customKeyMappings.add(keyMapping) + return keyMapping + } + + @JvmStatic + fun register(key: String, keyCode: Int, category: String): KeyMapping { + val cat = customCategories.find { it.id.path == category }.let { + if (it == null) { + val parts = category.split(":", limit = 2) + val namespace = if (parts.size > 1) parts[0] else "ctjs" + val path = if (parts.size > 1) parts[1] else parts[0] + KeyMapping.Category(Identifier.fromNamespaceAndPath(namespace, path)) + } else it + } + + return register(key, keyCode, cat) + } + + @JvmStatic + fun find(key: String): KeyMapping? { + val vanilla = Minecraft.getInstance().options.keyMappings.find { it.name == key } + if (vanilla != null) return vanilla + + val custom = customKeyMappings.find { it.name == key } + if (custom != null) return custom + + return null + } + + @JvmStatic + fun getKeyMappings() = customKeyMappings.toList() + + @JvmStatic + fun getCategories() = customCategories.toList() + + fun save() { + val builder = StringBuilder() + for (key in customKeyMappings) { + builder.appendLine("${key.name}:${key.saveString()}") + } + SAVE_FILE.writeText(builder.toString()) + } + + fun load() { + if (!SAVE_FILE.exists()) return + + SAVE_FILE.readText().lines().forEach { line -> + val parts = line.split(":", limit = 2) + if (parts.size < 2) return@forEach + KEY_MAP[parts[0]] = parts[1] + } + } + + private fun KeyMapping.load() = apply { + KEY_MAP[name]?.let { + setKey(InputConstants.getKey(it)) + KeyMapping.resetMapping() + } + } +} diff --git a/src/main/kotlin/com/chattriggers/ctjs/api/client/FileLib.kt b/src/main/kotlin/com/chattriggers/ctjs/api/FileLib.kt similarity index 90% rename from src/main/kotlin/com/chattriggers/ctjs/api/client/FileLib.kt rename to src/main/kotlin/com/chattriggers/ctjs/api/FileLib.kt index 8edaef3b..33aa67b3 100644 --- a/src/main/kotlin/com/chattriggers/ctjs/api/client/FileLib.kt +++ b/src/main/kotlin/com/chattriggers/ctjs/api/FileLib.kt @@ -1,6 +1,10 @@ -package com.chattriggers.ctjs.api.client +package com.chattriggers.ctjs.api import com.chattriggers.ctjs.CTJS +import com.chattriggers.ctjs.engine.printTraceToConsole +import com.chattriggers.ctjs.internal.engine.module.ModuleManager +import net.minecraft.client.Minecraft +import net.minecraft.network.chat.Component import net.minecraft.util.Util import java.io.* import java.net.UnknownHostException @@ -164,7 +168,7 @@ object FileLib { @JvmStatic @JvmOverloads fun getUrlContent(theUrl: String, userAgent: String? = "Mozilla/5.0"): String { - val conn = CTJS.makeWebRequest(theUrl, userAgent) + val conn = CTJS.Companion.makeWebRequest(theUrl, userAgent) return conn.getInputStream().use { it.readBytes() @@ -221,7 +225,7 @@ object FileLib { * destDirectory (will be created if does not exist). * @param zipFilePath the zip file path * @param destDirectory the destination directory - * @throws IOException IOException + * @throws java.io.IOException IOException */ @Throws(IOException::class) @JvmStatic @@ -267,7 +271,7 @@ object FileLib { } private fun absoluteLocation(importName: String, fileLocation: String): String { - return CTJS.MODULES_FOLDER + File.separator + importName + File.separator + fileLocation + return CTJS.Companion.MODULES_FOLDER + File.separator + importName + File.separator + fileLocation } /** @@ -299,7 +303,7 @@ object FileLib { */ @JvmStatic fun open(url: String) { - Util.getOperatingSystem().open(url) + Util.getPlatform().openUri(url) } /** @@ -309,6 +313,19 @@ object FileLib { */ @JvmStatic fun open(path: File) { - Util.getOperatingSystem().open(path) + Util.getPlatform().openFile(path) } -} + + /** + * Opens the path to the modules folder in the file explorer + */ + @JvmStatic + fun openModulesFolder() { + try { + open(ModuleManager.modulesFolder) + } catch (exception: IOException) { + exception.printTraceToConsole() + Minecraft.getInstance().player?.sendSystemMessage(Component.nullToEmpty("&cCould not open file location")) + } + } +} \ No newline at end of file diff --git a/src/main/kotlin/com/chattriggers/ctjs/api/Mappings.kt b/src/main/kotlin/com/chattriggers/ctjs/api/Mappings.kt deleted file mode 100644 index aa012b5e..00000000 --- a/src/main/kotlin/com/chattriggers/ctjs/api/Mappings.kt +++ /dev/null @@ -1,260 +0,0 @@ -package com.chattriggers.ctjs.api - -import com.chattriggers.ctjs.CTJS -import com.chattriggers.ctjs.internal.utils.urlEncode -import net.fabricmc.loader.api.FabricLoader -import net.fabricmc.mappingio.MappingReader -import net.fabricmc.mappingio.tree.MappingTree.ElementMapping -import net.fabricmc.mappingio.tree.MappingTree.MethodArgMapping -import net.fabricmc.mappingio.tree.MappingTreeView -import net.fabricmc.mappingio.tree.MemoryMappingTree -import org.objectweb.asm.Opcodes -import org.objectweb.asm.Type -import org.spongepowered.asm.mixin.transformer.ClassInfo -import org.spongepowered.asm.service.MixinService -import java.io.ByteArrayInputStream -import java.net.URI -import java.net.URL -import java.nio.file.Files -import java.util.zip.ZipFile - -/** - * Allows runtime inspection of mappings - */ -object Mappings { - private const val YARN_MAPPINGS_URL_PREFIX = "https://maven.fabricmc.net/net/fabricmc/yarn/" - - // If this is changed, also change the Java.type function in mixinProvidedLibs.js - internal val mappedPackages = setOf("Lnet/minecraft/", "Lcom/mojang/blaze3d/") - - private val unmappedClasses = mutableMapOf() - private val mappedToUnmappedClassNames = mutableMapOf() - - internal fun initialize() { - val container = FabricLoader.getInstance().getModContainer(CTJS.MOD_ID) - val mappingVersion = container.get().metadata.getCustomValue("${CTJS.MOD_ID}:yarn-mappings").asString - val jarName = "yarn-$mappingVersion-v2.jar".urlEncode() - - val jarBytes = URI("$YARN_MAPPINGS_URL_PREFIX${mappingVersion.urlEncode()}/$jarName").toURL().readBytes() - val tempFile = Files.createTempFile(CTJS.MOD_ID, "mapping").toFile() - tempFile.writeBytes(jarBytes) - - val mappingBytes = ZipFile(tempFile).use { file -> - file.getInputStream(file.getEntry("mappings/mappings.tiny")).readAllBytes() - } - - val tree = MemoryMappingTree() - MappingReader.read(ByteArrayInputStream(mappingBytes).bufferedReader(), tree) - - tree.classes.forEach { clazz -> - val fields = mutableMapOf() - - clazz.fields.forEach { field -> - fields[field.unmappedName] = MappedField( - name = Mapping.fromMapped(field), - type = Mapping(field.unmappedType.descriptor, field.mappedType.descriptor) - ) - } - - val methods = mutableMapOf>() - - clazz.methods.forEach { method -> - val unmappedType = method.unmappedType - val mappedType = method.mappedType - - methods.getOrPut(method.unmappedName, ::mutableListOf).add( - MappedMethod( - name = Mapping.fromMapped(method), - parameters = method.args.sortedBy { it.lvIndex }.mapIndexed { index, param -> - MappedParameter( - Mapping(param.unmappedName, param.mappedName), - Mapping( - unmappedType.argumentTypes[index].descriptor, - mappedType.argumentTypes[index].descriptor, - ), - param.lvIndex, - ) - }, - returnType = Mapping(unmappedType.returnType.descriptor, mappedType.returnType.descriptor) - ) - ) - } - - unmappedClasses[clazz.unmappedName] = MappedClass( - name = Mapping.fromMapped(clazz), - fields, - methods - ) - - if (CTJS.isDevelopment) { - mappedToUnmappedClassNames[clazz.unmappedName] = clazz.unmappedName - } else { - mappedToUnmappedClassNames[clazz.mappedName] = clazz.unmappedName - } - } - } - - internal fun getMappedClass(unmappedClassName: String): MappedClass? { - var name = normalizeClassName(unmappedClassName) - mappedToUnmappedClassNames[name]?.also { name = it } - return unmappedClasses[name] - } - - internal fun getUnmappedClass(unmappedClassName: String): MappedClass { - val name = normalizeClassName(unmappedClassName) - val classNode = MixinService.getService().bytecodeProvider.getClassNode(unmappedClassName) - - val fields = classNode.fields.associate { - val type = it.desc - val fieldName = it.name - - fieldName to MappedField(Mapping(fieldName, fieldName), Mapping(type, mapClassName(type) ?: type)) - } - - val methods = mutableMapOf>() - for (method in classNode.methods) { - val isStatic = method.access and Opcodes.ACC_STATIC != 0 - var lvtIndex = if (isStatic) 0 else 1 - - val params = mutableListOf() - Type.getArgumentTypes(method.desc).forEachIndexed { index, type -> - val paramType = type.descriptor - val paramName = method.parameters?.get(index)?.name ?: return@forEachIndexed - - params.add( - MappedParameter( - Mapping(paramName, paramName), - Mapping(paramType, mapClassName(paramType) ?: paramType), - lvtIndex - ) - ) - - if (type == Type.DOUBLE_TYPE || type == Type.LONG_TYPE) { - lvtIndex += 2 - } else { - lvtIndex++ - } - } - - val returnType = Type.getReturnType(method.desc).descriptor - val methodName = method.name - methods.getOrPut(methodName, ::mutableListOf).add( - MappedMethod( - Mapping(methodName, methodName), - params, - Mapping(returnType, mapClassName(returnType) ?: returnType) - ) - ) - } - - mappedToUnmappedClassNames[name] = name - return MappedClass(Mapping(name, name), fields, methods).also { - unmappedClasses[name] = it - } - } - - internal fun getMappedClassName(unmappedClassName: String) = getMappedClass(unmappedClassName)?.name?.value - - /** - * Gets a classes unmapped class name, or throws an error if it is not mapped - */ - @JvmStatic - fun unmapClass(clazz: Class<*>) = unmapClassName(clazz.name) - - /** - * Gets an unmapped class name from a mapped class name, or returns null if - * it either does not exist or is not mapped. - */ - @JvmStatic - fun unmapClassName(className: String): String? { - return mappedToUnmappedClassNames[normalizeClassName(className)] - } - - /** - * Gets the mapped class name from an unmapped class name or null if the class - * name does not exist. Note that this is not required to use mapped classes, - * as Rhino performs this mapping automatically during runtime. - */ - @JvmStatic - fun mapClassName(className: String) = getMappedClassName(className) - - private fun normalizeClassName(className: String) = (if (className.startsWith('L') && className.endsWith(';')) { - className.drop(1).dropLast(1) - } else className).replace('.', '/') - - internal data class Mapping(val original: String, val mapped: String) { - val value: String - get() = if (CTJS.isDevelopment) original else mapped - - companion object { - fun fromMapped(mapped: ElementMapping) = Mapping(mapped.unmappedName, mapped.mappedName) - } - } - - internal data class MappedField(val name: Mapping, val type: Mapping) - - internal class MappedParameter( - val name: Mapping, - val type: Mapping, - val lvtIndex: Int, - ) - - internal class MappedMethod( - val name: Mapping, - val parameters: List, - val returnType: Mapping, - ) { - fun toDescriptor() = buildString { - append('(') - parameters.forEach { - append(it.type.value) - } - append(')') - append(returnType.value) - } - - fun toFullDescriptor() = name.value + toDescriptor() - } - - internal class MappedClass( - val name: Mapping, - val fields: Map, - val methods: Map>, - ) { - fun findMethods(name: String, classInfo: ClassInfo?): List? { - methods[name]?.let { return it } - - if (classInfo == null) - return null - - val unmappedSuperClass = mappedToUnmappedClassNames[classInfo.superName] - if (unmappedSuperClass != null) { - return unmappedClasses[unmappedSuperClass]?.findMethods(name, classInfo.superClass) - } - - val methods = mutableListOf() - for (itf in classInfo.interfaces) { - val unmappedInterface = mappedToUnmappedClassNames[itf] ?: continue - unmappedClasses[unmappedInterface]?.findMethods(name, null)?.let { methods += it } - } - - return if (methods.isEmpty()) null else methods - } - } - - private val ElementMapping.unmappedName: String - get() = getName("named")!! - - private val ElementMapping.mappedName: String - get() = getName("intermediary")!! - - // Parameters do not have "intermediary" mappings - private val MethodArgMapping.mappedName: String - get() = unmappedName - - private val MappingTreeView.MemberMappingView.unmappedType: Type - get() = Type.getType(getDesc("named")) - - private val MappingTreeView.MemberMappingView.mappedType: Type - get() = Type.getType(getDesc("intermediary")) -} diff --git a/src/main/kotlin/com/chattriggers/ctjs/api/client/CPS.kt b/src/main/kotlin/com/chattriggers/ctjs/api/client/CPS.kt deleted file mode 100644 index 937dc67f..00000000 --- a/src/main/kotlin/com/chattriggers/ctjs/api/client/CPS.kt +++ /dev/null @@ -1,93 +0,0 @@ -package com.chattriggers.ctjs.api.client - -import com.chattriggers.ctjs.api.world.World -import com.chattriggers.ctjs.internal.engine.CTEvents -import com.chattriggers.ctjs.internal.utils.Initializer -import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents -import java.util.* -import kotlin.math.max -import kotlin.math.roundToInt - -object CPS : Initializer { - private val leftClicks = ClicksTracker() - private val rightClicks = ClicksTracker() - private val middleClicks = ClicksTracker() - - override fun init() { - ClientTickEvents.START_CLIENT_TICK.register { - leftClicks.tick() - rightClicks.tick() - middleClicks.tick() - } - - CTEvents.MOUSE_CLICKED.register { _, _, button, pressed -> - if (pressed) { - when (button) { - 0 -> leftClicks.click() - 1 -> rightClicks.click() - 2 -> middleClicks.click() - } - } - } - } - - @JvmStatic - fun getLeftClicksMax(): Int = leftClicks.maxClicks - - @JvmStatic - fun getRightClicksMax(): Int = rightClicks.maxClicks - - @JvmStatic - fun getMiddleClicksMax(): Int = middleClicks.maxClicks - - @JvmStatic - fun getLeftClicks(): Int = leftClicks.clicks.size - - @JvmStatic - fun getRightClicks(): Int = rightClicks.clicks.size - - @JvmStatic - fun getMiddleClicks(): Int = middleClicks.clicks.size - - @JvmStatic - fun getLeftClicksAverage(): Int = leftClicks.average() - - @JvmStatic - fun getRightClicksAverage(): Int = rightClicks.average() - - @JvmStatic - fun getMiddleClicksAverage(): Int = middleClicks.average() - - private class ClicksTracker { - val clicks = mutableListOf() - var maxClicks = 0 - private val runningAverages = LinkedList() - - fun click() { - clicks.add(World.getTicksPerSecond()) - } - - fun tick() { - // Decrease all existing click values - for (i in clicks.indices) - clicks[i]-- - clicks.removeIf { it <= 0 } - - // Save the current CPS - runningAverages.add(clicks.size) - if (runningAverages.size > 100) - runningAverages.removeAt(0) - - maxClicks = if (runningAverages.lastOrNull() == 0) { - runningAverages.clear() - 0 - } else { - max(maxClicks, clicks.size) - } - } - - fun average() = if (runningAverages.isNotEmpty()) { - runningAverages.average().roundToInt() - } else 0 - } -} diff --git a/src/main/kotlin/com/chattriggers/ctjs/api/client/Client.kt b/src/main/kotlin/com/chattriggers/ctjs/api/client/Client.kt deleted file mode 100644 index e8357a67..00000000 --- a/src/main/kotlin/com/chattriggers/ctjs/api/client/Client.kt +++ /dev/null @@ -1,337 +0,0 @@ -package com.chattriggers.ctjs.api.client - -import com.chattriggers.ctjs.api.inventory.Slot -import com.chattriggers.ctjs.api.message.TextComponent -import com.chattriggers.ctjs.api.world.World -import com.chattriggers.ctjs.internal.listeners.ClientListener -import com.chattriggers.ctjs.internal.mixins.ChatScreenAccessor -import com.chattriggers.ctjs.internal.mixins.HandledScreenAccessor -import com.chattriggers.ctjs.internal.mixins.KeyBindingAccessor -import com.chattriggers.ctjs.internal.utils.asMixin -import gg.essential.universal.UKeyboard -import gg.essential.universal.UMinecraft -import gg.essential.universal.UMouse -import net.minecraft.client.MinecraftClient -import net.minecraft.client.gui.hud.ChatHud -import net.minecraft.client.gui.hud.PlayerListHud -import net.minecraft.client.gui.screen.ChatScreen -import net.minecraft.client.gui.screen.Screen -import net.minecraft.client.gui.screen.TitleScreen -import net.minecraft.client.gui.screen.ingame.HandledScreen -import net.minecraft.client.gui.screen.multiplayer.ConnectScreen -import net.minecraft.client.gui.screen.multiplayer.MultiplayerScreen -import net.minecraft.client.network.ClientPlayNetworkHandler -import net.minecraft.client.network.ServerAddress -import net.minecraft.client.network.ServerInfo -import net.minecraft.client.option.KeyBinding -import net.minecraft.client.realms.gui.screen.RealmsMainScreen -import net.minecraft.network.packet.Packet -import kotlin.math.roundToInt - -object Client { - internal var referenceSystemTime: Long = 0 - - @JvmField - val currentGui = CurrentGuiWrapper() - - @JvmField - val camera = CameraWrapper() - - @JvmField - val settings = Settings - - /** - * Gets Minecraft's Minecraft object - * - * @return The Minecraft object - */ - @JvmStatic - fun getMinecraft(): MinecraftClient = UMinecraft.getMinecraft() - - /** - * Gets Minecraft's NetHandlerPlayClient object - * - * @return The NetHandlerPlayClient object - */ - @JvmStatic - fun getConnection(): ClientPlayNetworkHandler? = getMinecraft().networkHandler - - /** - * Schedule's a task to run on Minecraft's main thread in [delay] ticks. - * Defaults to the next tick. - * @param delay The delay in ticks - * @param callback The task to run on the main thread - */ - @JvmStatic - @JvmOverloads - fun scheduleTask(delay: Int = 0, callback: () -> Unit) { - ClientListener.addTask(delay, callback) - } - - /** - * Quits the client back to the main menu. - * This acts just like clicking the "Disconnect" or "Save and quit to title" button. - */ - @JvmStatic - fun disconnect() { - scheduleTask { - World.toMC()?.disconnect() - getMinecraft().disconnect() - - getMinecraft().setScreen( - when { - getMinecraft().isInSingleplayer -> TitleScreen() - getMinecraft().currentServerEntry?.isRealm == true -> RealmsMainScreen(TitleScreen()) - else -> MultiplayerScreen(TitleScreen()) - } - ) - } - } - - /** - * Connects to the server with the given ip. - * @param ip The ip to connect to - */ - @JvmStatic - @JvmOverloads - fun connect(ip: String, port: Int = 25565) { - scheduleTask { - ConnectScreen.connect( - MultiplayerScreen(TitleScreen()), - getMinecraft(), - ServerAddress(ip, port), - ServerInfo("Server", ip, ServerInfo.ServerType.OTHER), - false, - null, - ) - } - } - - /** - * Gets the Minecraft ChatHud object for the chat gui - * - * @return The GuiNewChat object for the chat gui - */ - @JvmStatic - fun getChatGui(): ChatHud? = getMinecraft().inGameHud?.chatHud - - @JvmStatic - fun isInChat(): Boolean = getMinecraft().currentScreen is ChatScreen - - @JvmStatic - fun getTabGui(): PlayerListHud? = getMinecraft().inGameHud?.playerListHud - - @JvmStatic - fun isInTab(): Boolean = getMinecraft().options.playerListKey.isPressed - - /** - * Gets whether the Minecraft window is active - * and in the foreground of the user's screen. - * - * @return true if the game is active, false otherwise - */ - @JvmStatic - fun isTabbedIn(): Boolean = getMinecraft().isWindowFocused - - @JvmStatic - fun isControlDown(): Boolean = UKeyboard.isCtrlKeyDown() - - @JvmStatic - fun isShiftDown(): Boolean = UKeyboard.isShiftKeyDown() - - @JvmStatic - fun isAltDown(): Boolean = UKeyboard.isAltKeyDown() - - @JvmStatic - fun getFPS(): Int = getMinecraft().currentFps - - @JvmStatic - fun getVersion(): String = getMinecraft().gameVersion - - @JvmStatic - fun getMaxMemory(): Long = Runtime.getRuntime().maxMemory() - - @JvmStatic - fun getTotalMemory(): Long = Runtime.getRuntime().totalMemory() - - @JvmStatic - fun getFreeMemory(): Long = Runtime.getRuntime().freeMemory() - - @JvmStatic - fun getMemoryUsage(): Int = ((getTotalMemory() - getFreeMemory()) * 100 / getMaxMemory().toFloat()).roundToInt() - - @JvmStatic - fun getSystemTime(): Long = (System.nanoTime() - referenceSystemTime) / 1_000_000 - - @JvmStatic - fun getMouseX() = UMouse.Scaled.x - - @JvmStatic - fun getMouseY() = UMouse.Scaled.y - - @JvmStatic - fun isInGui(): Boolean = currentGui.get() != null - - /** - * Gets the chat message currently typed into the chat gui. - * - * @return A blank string if the gui isn't open, otherwise, the message - */ - @JvmStatic - fun getCurrentChatMessage(): String { - return if (isInChat()) { - val chatGui = getMinecraft().currentScreen as ChatScreen - chatGui.asMixin().chatField.text - } else "" - } - - /** - * Sets the current chat message, if the chat gui is not open, one will be opened. - * - * @param message the message to put in the chat text box. - */ - @JvmStatic - fun setCurrentChatMessage(message: String) { - if (isInChat()) { - val chatGui = getMinecraft().currentScreen as ChatScreen - chatGui.asMixin().chatField.text = message - } else currentGui.set(ChatScreen(message)) - } - - @JvmStatic - fun sendPacket(packet: Packet<*>) { - getConnection()?.connection?.send(packet) - } - - /** - * Display a title. - * - * @param title title text - * @param subtitle subtitle text - * @param fadeIn time to fade in - * @param time time to stay on screen - * @param fadeOut time to fade out - */ - @JvmStatic - fun showTitle(title: String?, subtitle: String?, fadeIn: Int, time: Int, fadeOut: Int) { - getMinecraft().inGameHud.apply { - setTitleTicks(fadeIn, time, fadeOut) - if (title != null) - setTitle(TextComponent(title)) - if (subtitle != null) - setSubtitle(TextComponent(subtitle)) - } - } - - /** - * Copies a string to the clipboard - * - * @param text The text to copy - */ - @JvmStatic - @JvmOverloads - fun copy(text: String = "") { - getMinecraft().keyboard.clipboard = text - } - - /** - * Get the string currently on the clipboard - */ - @JvmStatic - fun paste(): String = getMinecraft().keyboard.clipboard - - /** - * Get the [KeyBinding] from an already existing Minecraft KeyBinding, otherwise, returns null. - * - * @param keyCode the keycode to search for, see Keyboard below. Ex. Keyboard.KEY_A - * @return the [KeyBinding] from a Minecraft KeyBinding, or null if one doesn't exist - * @see [org.lwjgl.input.Keyboard](http://legacy.lwjgl.org/javadoc/org/lwjgl/input/Keyboard.html) - */ - @JvmStatic - fun getKeyBindFromKey(keyCode: Int): KeyBind? { - return KeyBind.getKeyBinds().find { it.getKeyCode() == keyCode } - ?: getMinecraft().options.allKeys - .find { it.asMixin().boundKey.code == keyCode } - ?.let(::KeyBind) - } - - /** - * Get the [KeyBinding] from an already existing Minecraft KeyBinding, else, return a new one. - * - * @param keyCode the keycode which the keybind will respond to, see Keyboard below. Ex. Keyboard.KEY_A - * @param description the description of the keybind - * @param category the keybind category the keybind will be in - * @return the [KeyBinding] from a Minecraft KeyBinding, or a new one if one doesn't exist - * @see [org.lwjgl.input.Keyboard](http://legacy.lwjgl.org/javadoc/org/lwjgl/input/Keyboard.html) - */ - @JvmStatic - @JvmOverloads - fun getKeyBindFromKey(keyCode: Int, description: String, category: String = "ChatTriggers"): KeyBind { - return getKeyBindFromKey(keyCode) ?: KeyBind(description, keyCode, category) - } - - /** - * Get the [KeyBinding] from an already existing - * Minecraft KeyBinding, otherwise, returns null. - * - * @param description the description of the keybind - * @return the [KeyBinding], or null if one doesn't exist - */ - @JvmStatic - fun getKeyBindFromDescription(description: String): KeyBind? { - return KeyBind.getKeyBinds() - .find { it.getDescription() == description } - ?: getMinecraft().options.allKeys - .find { it.translationKey == description } - ?.let(::KeyBind) - } - - class CurrentGuiWrapper { - /** - * Gets the Java class name of the currently open gui, for example, "GuiChest" - * - * @return the class name of the current gui - */ - fun getClassName(): String = get()?.javaClass?.simpleName ?: "null" - - /** - * Gets the Minecraft gui class that is currently open - * - * @return the Minecraft gui - */ - fun get(): Screen? = getMinecraft().currentScreen - - fun set(screen: Screen?) { - scheduleTask { - getMinecraft().setScreen(screen) - } - } - - /** - * Gets the slot under the mouse in the current gui, if one exists. - * - * @return the [Slot] under the mouse - */ - fun getSlotUnderMouse(): Slot? { - val screen: Screen? = get() - return if (screen is HandledScreen<*>) { - screen.asMixin().invokeGetSlotAt(getMouseX(), getMouseY())?.let(::Slot) - } else null - } - - /** - * Closes the currently open gui - */ - fun close() { - scheduleTask { Player.toMC()?.closeScreen() } - } - } - - class CameraWrapper { - fun getX(): Double = getMinecraft().gameRenderer.camera.pos.x - - fun getY(): Double = getMinecraft().gameRenderer.camera.pos.y - - fun getZ(): Double = getMinecraft().gameRenderer.camera.pos.z - } -} diff --git a/src/main/kotlin/com/chattriggers/ctjs/api/client/KeyBind.kt b/src/main/kotlin/com/chattriggers/ctjs/api/client/KeyBind.kt deleted file mode 100644 index 7d25f919..00000000 --- a/src/main/kotlin/com/chattriggers/ctjs/api/client/KeyBind.kt +++ /dev/null @@ -1,243 +0,0 @@ -package com.chattriggers.ctjs.api.client - -import com.chattriggers.ctjs.api.triggers.RegularTrigger -import com.chattriggers.ctjs.api.triggers.TriggerType -import com.chattriggers.ctjs.api.world.World -import com.chattriggers.ctjs.internal.BoundKeyUpdater -import com.chattriggers.ctjs.internal.mixins.GameOptionsAccessor -import com.chattriggers.ctjs.internal.mixins.KeyBindingAccessor -import com.chattriggers.ctjs.internal.utils.Initializer -import com.chattriggers.ctjs.internal.utils.asMixin -import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents -import net.minecraft.client.option.KeyBinding -import net.minecraft.client.resource.language.I18n -import org.apache.commons.lang3.ArrayUtils -import java.util.concurrent.CopyOnWriteArrayList - -class KeyBind { - private val keyBinding: KeyBinding - private var onKeyPress: RegularTrigger? = null - private var onKeyRelease: RegularTrigger? = null - private var onKeyDown: RegularTrigger? = null - - private var down: Boolean = false - - /** - * Creates a new keybind, editable in the user's controls. - * - * @param description what the keybind does - * @param keyCode the keycode which the keybind will respond to, see Keyboard below. Ex. Keyboard.KEY_A - * @param category the keybind category the keybind will be in - * @see [org.lwjgl.input.Keyboard](http://legacy.lwjgl.org/javadoc/org/lwjgl/input/Keyboard.html) - */ - @JvmOverloads - constructor(description: String, keyCode: Int, category: String = "ChatTriggers") { - val possibleDuplicate = Client.getMinecraft().options.allKeys.find { - I18n.translate(it.translationKey) == I18n.translate(description) && - I18n.translate(it.category) == I18n.translate(category) - } - - if (possibleDuplicate != null) { - require(possibleDuplicate in customKeyBindings) { - "KeyBind already exists! To get a KeyBind from an existing Minecraft KeyBinding, " + - "use the other KeyBind constructor or Client.getKeyBindFromKey." - } - keyBinding = possibleDuplicate - } else { - if (category !in KeyBindingAccessor.getKeyCategories()) { - uniqueCategories[category] = 0 - } - uniqueCategories[category] = uniqueCategories[category]!! + 1 - keyBinding = KeyBinding(description, keyCode, category) - - // We need to update the bound key for the KeyBind we just made to the previous binding, - // just in case it existed last time the game was opened. This will only matter for the first - // time launching the game, as subsequent CT loads will cause possibleDuplicate to be found. - Client.getMinecraft().options.asMixin().ctjs_updateBoundKey(keyBinding) - KeyBinding.updateKeysByCode() - - addKeyBinding(keyBinding) - customKeyBindings.add(keyBinding) - } - - keyBinds.add(this) - } - - constructor(keyBinding: KeyBinding) { - this.keyBinding = keyBinding - keyBinds.add(this) - } - - fun registerKeyPress(method: Any) = apply { - onKeyPress = RegularTrigger(method, TriggerType.OTHER) - } - - fun registerKeyRelease(method: Any) = apply { - onKeyRelease = RegularTrigger(method, TriggerType.OTHER) - } - - fun registerKeyDown(method: Any) = apply { - onKeyDown = RegularTrigger(method, TriggerType.OTHER) - } - - fun unregisterKeyPress() = apply { - onKeyPress?.unregister() - onKeyPress = null - } - - fun unregisterKeyRelease() = apply { - onKeyRelease?.unregister() - onKeyRelease = null - } - - fun unregisterKeyDown() = apply { - onKeyDown?.unregister() - onKeyDown = null - } - - internal fun onTick() { - if (isPressed() && !down) { - if (keyBinding in customKeyBindings) { - while (keyBinding.wasPressed()) { - // consume the key press if not built-in keybinding - } - } - - onKeyPress?.trigger(arrayOf()) - down = true - } - - if (isKeyDown()) { - onKeyDown?.trigger(arrayOf()) - down = true - } - - if (down && !isKeyDown()) { - while (keyBinding.wasPressed()) { - // consume the rest of the key presses - } - - onKeyRelease?.trigger(arrayOf()) - down = false - } - } - - /** - * Returns true if the key is pressed (used for continuous querying). - * - * @return whether the key is pressed - */ - fun isKeyDown(): Boolean = keyBinding.isPressed - - /** - * Returns true on the initial key press. For continuous querying use [isKeyDown]. - * - * @return whether the key has just been pressed - */ - fun isPressed(): Boolean = keyBinding.asMixin().timesPressed > 0 - - /** - * Gets the description of the key. - * - * @return the description - */ - fun getDescription(): String = keyBinding.translationKey - - /** - * Gets the key code of the key. - * - * @return the integer key code - */ - fun getKeyCode(): Int = keyBinding.asMixin().boundKey.code - - /** - * Gets the category of the key. - * - * @return the category - */ - fun getCategory(): String = keyBinding.category - - /** - * Sets the state of the key. - * - * @param pressed True to press, False to release - */ - fun setState(pressed: Boolean) = - KeyBinding.setKeyPressed(keyBinding.asMixin().boundKey, pressed) - - override fun toString() = "KeyBind{" + - "description=${getDescription()}, " + - "keyCode=${getKeyCode()}, " + - "category=${getCategory()}" + - "}" - - companion object : Initializer { - private val customKeyBindings = mutableSetOf() - private val uniqueCategories = mutableMapOf() - private val keyBinds = CopyOnWriteArrayList() - - internal fun getKeyBinds() = keyBinds - - override fun init() { - ClientTickEvents.START_CLIENT_TICK.register { - if (!World.isLoaded()) - return@register - - keyBinds.forEach { - // This used to cause crashes on legacy sometimes. If it starts crashing again, - // we'll add the empty try-catch block back - it.onTick() - } - } - } - - internal fun clearKeyBinds() { - keyBinds.toList().forEach(::removeKeyBind) - customKeyBindings.clear() - keyBinds.clear() - } - - private fun removeKeyBinding(keyBinding: KeyBinding) { - Client.getMinecraft().options.asMixin().setAllKeys( - ArrayUtils.removeElement( - Client.getMinecraft().options.allKeys, - keyBinding - ) - ) - val category = keyBinding.category - - if (category in uniqueCategories) { - uniqueCategories[category] = uniqueCategories[category]!! - 1 - - if (uniqueCategories[category] == 0) { - uniqueCategories.remove(category) - KeyBindingAccessor.getKeyCategories().remove(category) - } - } - } - - private fun removeKeyBind(keyBind: KeyBind) { - val keyBinding = keyBind.keyBinding - if (keyBinding !in customKeyBindings) return - - removeKeyBinding(keyBinding) - customKeyBindings.remove(keyBinding) - keyBinds.remove(keyBind) - } - - private fun addKeyBinding(keyBinding: KeyBinding): KeyBinding { - Client.getMinecraft().options.asMixin().setAllKeys( - ArrayUtils.add( - Client.getMinecraft().options.allKeys, - keyBinding - ) - ) - - val categoryMap = KeyBindingAccessor.getCategoryMap() - val maxInt = categoryMap.values.max() ?: 0 - categoryMap[keyBinding.category] = maxInt + 1 - - return keyBinding - } - } -} diff --git a/src/main/kotlin/com/chattriggers/ctjs/api/client/MathLib.kt b/src/main/kotlin/com/chattriggers/ctjs/api/client/MathLib.kt deleted file mode 100644 index 32aee7d4..00000000 --- a/src/main/kotlin/com/chattriggers/ctjs/api/client/MathLib.kt +++ /dev/null @@ -1,44 +0,0 @@ -package com.chattriggers.ctjs.api.client - -object MathLib { - /** - * Maps a number from one range to another. - * - * @param number the number to map - * @param in_min the original range min - * @param in_max the original range max - * @param out_min the final range min - * @param out_max the final range max - * @return the re-mapped number - */ - @JvmStatic - fun map(number: Float, in_min: Float, in_max: Float, out_min: Float, out_max: Float): Float { - return (number - in_min) * (out_max - out_min) / (in_max - in_min) + out_min - } - - /** - * Clamps a floating number between two values. - * - * @param number the number to clamp - * @param min the minimum - * @param max the maximum - * @return the clamped number - */ - @JvmStatic - fun clampFloat(number: Float, min: Float, max: Float): Float { - return number.coerceIn(min, max) - } - - /** - * Clamps an integer number between two values. - * - * @param number the number to clamp - * @param min the minimum - * @param max the maximum - * @return the clamped number - */ - @JvmStatic - fun clamp(number: Int, min: Int, max: Int): Int { - return number.coerceIn(min, max) - } -} diff --git a/src/main/kotlin/com/chattriggers/ctjs/api/client/Player.kt b/src/main/kotlin/com/chattriggers/ctjs/api/client/Player.kt deleted file mode 100644 index a84ec220..00000000 --- a/src/main/kotlin/com/chattriggers/ctjs/api/client/Player.kt +++ /dev/null @@ -1,374 +0,0 @@ -package com.chattriggers.ctjs.api.client - -import com.chattriggers.ctjs.api.entity.Entity -import com.chattriggers.ctjs.api.entity.PlayerMP -import com.chattriggers.ctjs.api.entity.Team -import com.chattriggers.ctjs.api.inventory.Inventory -import com.chattriggers.ctjs.api.inventory.Item -import com.chattriggers.ctjs.api.message.TextComponent -import com.chattriggers.ctjs.api.render.Renderer -import com.chattriggers.ctjs.api.world.PotionEffect -import com.chattriggers.ctjs.api.world.Scoreboard -import com.chattriggers.ctjs.api.world.World -import com.chattriggers.ctjs.api.world.block.BlockFace -import com.chattriggers.ctjs.api.world.block.BlockPos -import gg.essential.universal.UMath -import gg.essential.universal.UMinecraft -import net.minecraft.client.gui.screen.ingame.HandledScreen -import net.minecraft.util.Hand -import net.minecraft.util.hit.BlockHitResult -import net.minecraft.util.hit.EntityHitResult -import net.minecraft.util.hit.HitResult -import net.minecraft.util.math.Vec2f -import org.mozilla.javascript.NativeObject -import java.util.* - -object Player { - @JvmStatic - fun toMC() = UMinecraft.getMinecraft().player - - @JvmField - val armor = ArmorWrapper() - - /** - * Gets Minecraft's EntityPlayerSP object representing the user - * - * @return The Minecraft EntityPlayerSP object representing the user - */ - @Deprecated("Use toMC", ReplaceWith("toMC()")) - @JvmStatic - fun getPlayer() = toMC() - - @JvmStatic - fun getTeam(): Team? = Scoreboard.toMC()?.getTeam(getName())?.let(::Team) - - @JvmStatic - fun asPlayerMP(): PlayerMP? = toMC()?.let(::PlayerMP) - - @JvmStatic - fun getX(): Double = toMC()?.x ?: 0.0 - - @JvmStatic - fun getY(): Double = toMC()?.y ?: 0.0 - - @JvmStatic - fun getZ(): Double = toMC()?.z ?: 0.0 - - @JvmStatic - fun getPos(): BlockPos = BlockPos(getX(), getY(), getZ()) - - @JvmStatic - fun getRotation() = toMC()?.rotationClient ?: Vec2f(0f, 0f) - - @JvmStatic - fun getLastX(): Double = toMC()?.lastRenderX ?: 0.0 - - @JvmStatic - fun getLastY(): Double = toMC()?.lastRenderY ?: 0.0 - - @JvmStatic - fun getLastZ(): Double = toMC()?.lastRenderZ ?: 0.0 - - @JvmStatic - fun getRenderX(): Double = getLastX() + (getX() - getLastX()) * Renderer.partialTicks - - @JvmStatic - fun getRenderY(): Double = getLastY() + (getY() - getLastY()) * Renderer.partialTicks - - @JvmStatic - fun getRenderZ(): Double = getLastZ() + (getZ() - getLastZ()) * Renderer.partialTicks - - /** - * Gets the player's x motion. - * This is the amount the player will move in the x direction next tick. - * - * @return the player's x motion - */ - @JvmStatic - fun getMotionX(): Double = toMC()?.velocity?.x ?: 0.0 - - /** - * Gets the player's y motion. - * This is the amount the player will move in the y direction next tick. - * - * @return the player's y motion - */ - @JvmStatic - fun getMotionY(): Double = toMC()?.velocity?.y ?: 0.0 - - /** - * Gets the player's z motion. - * This is the amount the player will move in the z direction next tick. - * - * @return the player's z motion - */ - @JvmStatic - fun getMotionZ(): Double = toMC()?.velocity?.z ?: 0.0 - - /** - * Gets the player's camera pitch. - * - * @return the player's camera pitch - */ - @JvmStatic - fun getPitch(): Double = UMath.wrapAngleTo180(toMC()?.pitch?.toDouble() ?: 0.0) - - /** - * Gets the player's camera yaw. - * - * @return the player's camera yaw - */ - @JvmStatic - fun getYaw(): Double = UMath.wrapAngleTo180(toMC()?.yaw?.toDouble() ?: 0.0) - - /** - * Gets the player's username. - * - * @return the player's username - */ - @JvmStatic - fun getName(): String = UMinecraft.getMinecraft().session.username - - /** - * Gets the Java UUID object of the player. - * Use of [UUID.toString] in conjunction is recommended. - * - * @return the player's uuid - */ - @JvmStatic - fun getUUID(): UUID = UMinecraft.getMinecraft().gameProfile.id - - @JvmStatic - fun getHP(): Float = toMC()?.health ?: 0f - - @JvmStatic - fun getHunger(): Int = toMC()?.hungerManager?.foodLevel ?: 0 - - @JvmStatic - fun getSaturation(): Float = toMC()?.hungerManager?.saturationLevel ?: 0f - - @JvmStatic - fun getArmorPoints(): Int = toMC()?.armor ?: 0 - - /** - * Gets the player's air level. - * - * The returned value will be an integer. If the player is not taking damage, it - * will be between 300 (not in water) and 0. If the player is taking damage, it - * will be between -20 and 0, getting reset to 0 every time the player takes damage. - * - * @return the player's air level - */ - @JvmStatic - fun getAirLevel(): Int = toMC()?.air ?: 0 - - @JvmStatic - fun getXPLevel(): Int = toMC()?.experienceLevel ?: 0 - - @JvmStatic - fun getXPProgress(): Float = toMC()?.experienceProgress ?: 0f - - @JvmStatic - fun getBiome(): String { - val pos = toMC()?.blockPos ?: return "" - val biomeEntry = World.toMC()?.getBiome(pos) ?: return "" - - return biomeEntry.key.get().value.path - } - - /** - * Gets the light level at the player's current position. - * - * @return the light level at the player's current position - */ - @JvmStatic - fun getLightLevel(): Int = World.toMC()?.getLightLevel(toMC()?.blockPos) ?: 0 - - @JvmStatic - fun isMoving(): Boolean = toMC()?.movementSpeed?.let { it != 0f } ?: false - - @JvmStatic - fun isSneaking(): Boolean = toMC()?.isSneaking ?: false - - @JvmStatic - fun isSprinting(): Boolean = toMC()?.isSprinting ?: false - - /** - * Checks if player can be pushed by water. - * - * @return true if the player is flying, false otherwise - */ - @JvmStatic - fun isFlying(): Boolean = toMC()?.abilities?.flying ?: false - - @JvmStatic - fun isSleeping(): Boolean = toMC()?.isSleeping ?: false - - /** - * Gets the direction the player is facing. - * Example: "South West" - * - * @return The direction the player is facing, one of the four cardinal directions - */ - @JvmStatic - fun facing(): String { - if (toMC() == null) return "" - - val yaw = getYaw() - - return when { - yaw in -22.5..22.5 -> "South" - yaw in 22.5..67.5 -> "South West" - yaw in 67.5..112.5 -> "West" - yaw in 112.5..157.5 -> "North West" - yaw < -157.5 || yaw > 157.5 -> "North" - yaw in -157.5..-112.5 -> "North East" - yaw in -112.5..-67.5 -> "East" - yaw in -67.5..-22.5 -> "South East" - else -> "" - } - } - - /** - * Gets the current active potion effects. Returns an empty list - * if the player has no active potion effects. - * - * @return a list of the active [PotionEffect]s - */ - @JvmStatic - fun getActivePotionEffects(): List = - toMC()?.activeStatusEffects?.values?.map(::PotionEffect).orEmpty() - - /** - * Gets the current object that the player is looking at, - * whether that be a block or an entity. Returns null when not looking - * at anything. - * - * @return the [Block] or [Entity] being looked at, or null if air - */ - @JvmStatic - fun lookingAt(): Any? { - val target = Client.getMinecraft().crosshairTarget - - return when (target?.type) { - HitResult.Type.MISS -> null - HitResult.Type.BLOCK -> { - val block = target as BlockHitResult - World.getBlockAt(BlockPos(block.blockPos)).withFace(BlockFace.fromMC(block.side)) - } - HitResult.Type.ENTITY -> { - Entity.fromMC((target as EntityHitResult).entity) - } - null -> null - } - } - - /** - * Gets the current item in the player's hand. - * - * @param hand the hand of the item - * @return the current held [Item] - */ - @JvmOverloads - @JvmStatic - fun getHeldItem(hand: Hand = Hand.MAIN_HAND): Item? { - return toMC()?.getStackInHand(hand)?.let(Item::fromMC) - } - - /** - * Sets the current held item based on the provided index. - * - * @param index the new held item index - */ - @JvmStatic - fun setHeldItemIndex(index: Int) { - toMC()?.inventory?.selectedSlot = index - } - - /** - * Gets the current index of the held item. - * - * @return the current index - */ - @JvmStatic - fun getHeldItemIndex(): Int = toMC()?.inventory?.selectedSlot ?: -1 - - /** - * Gets the inventory of the player, i.e. the inventory accessed by 'e'. - * - * @return the player's inventory - */ - @JvmStatic - fun getInventory(): Inventory? = toMC()?.inventory?.let(::Inventory) - - /** - * Gets the display name for the player, - * i.e. the name shown in tab list and in the player's nametag. - * @return the display name - */ - @JvmStatic - fun getDisplayName(): TextComponent = asPlayerMP()?.getDisplayName() ?: TextComponent("") - - /** - * Sets the name for this player shown in tab list - * - * @param textComponent the new name to display - */ - @JvmStatic - fun setTabDisplayName(textComponent: TextComponent) { - asPlayerMP()?.setTabDisplayName(textComponent) - } - - /** - * Sets the name for this player shown above their head, - * in their name tag - * - * @param textComponent the new name to display - */ - @JvmStatic - fun setNametagName(textComponent: TextComponent) { - asPlayerMP()?.setNametagName(textComponent) - } - - /** - * Gets the container the user currently has open, i.e. a chest. - * - * @return the currently opened container - */ - @JvmStatic - fun getContainer(): Inventory? = (Client.getMinecraft().currentScreen as? HandledScreen<*>)?.let(::Inventory) - - /** - * Draws the player in the GUI. Takes the same parameters as [Renderer.drawPlayer] - * minus `player`. - * - * @see Renderer.drawPlayer - */ - @JvmStatic - fun draw(obj: NativeObject) = apply { - obj["player"] = this - Renderer.drawPlayer(obj) - } - - class ArmorWrapper { - /** - * @return the [Item] in the player's helmet slot or null if the slot is empty - */ - fun getHelmet(): Item? = getInventory()?.getStackInSlot(39) - - /** - * @return the [Item] in the player's chestplate slot or null if the slot is empty - */ - fun getChestplate(): Item? = getInventory()?.getStackInSlot(38) - - /** - * @return the [Item] in the player's leggings slot or null if the slot is empty - */ - fun getLeggings(): Item? = getInventory()?.getStackInSlot(37) - - /** - * @return the [Item] in the player's boots slot or null if the slot is empty - */ - fun getBoots(): Item? = getInventory()?.getStackInSlot(36) - } -} diff --git a/src/main/kotlin/com/chattriggers/ctjs/api/client/Settings.kt b/src/main/kotlin/com/chattriggers/ctjs/api/client/Settings.kt deleted file mode 100644 index 37ee3250..00000000 --- a/src/main/kotlin/com/chattriggers/ctjs/api/client/Settings.kt +++ /dev/null @@ -1,362 +0,0 @@ -package com.chattriggers.ctjs.api.client - -import com.chattriggers.ctjs.* -import com.chattriggers.ctjs.api.CTWrapper -import com.chattriggers.ctjs.api.world.World -import gg.essential.universal.UMinecraft -import net.minecraft.entity.player.PlayerModelPart -import net.minecraft.sound.SoundCategory - -object Settings { - @JvmStatic - fun toMC() = UMinecraft.getSettings() - - @JvmStatic - @Deprecated("Use toMC", ReplaceWith("toMC()")) - fun getSettings() = toMC() - - @JvmStatic - fun getFOV() = toMC().fov.value - - @JvmStatic - fun setFOV(fov: Int) { - toMC().fov.value = fov - } - - @JvmStatic - fun getDifficulty() = World.getDifficulty() - - @JvmField - val skin = SkinWrapper() - - @JvmField - val sound = SoundWrapper() - - @JvmField - val chat = ChatWrapper() - - @JvmField - val video = VideoWrapper() - - class SkinWrapper { - fun isCapeEnabled() = toMC().isPlayerModelPartEnabled(PlayerModelPart.CAPE) - - fun setCapeEnabled(toggled: Boolean) { - toMC().togglePlayerModelPart(PlayerModelPart.CAPE, toggled) - } - - fun isJacketEnabled() = toMC().isPlayerModelPartEnabled(PlayerModelPart.JACKET) - - fun setJacketEnabled(toggled: Boolean) { - toMC().togglePlayerModelPart(PlayerModelPart.JACKET, toggled) - } - - fun isLeftSleeveEnabled() = toMC().isPlayerModelPartEnabled(PlayerModelPart.LEFT_SLEEVE) - - fun setLeftSleeveEnabled(toggled: Boolean) { - toMC().togglePlayerModelPart(PlayerModelPart.LEFT_SLEEVE, toggled) - } - - fun isRightSleeveEnabled() = toMC().isPlayerModelPartEnabled(PlayerModelPart.RIGHT_SLEEVE) - - fun setRightSleeveEnabled(toggled: Boolean) { - toMC().togglePlayerModelPart(PlayerModelPart.RIGHT_SLEEVE, toggled) - } - - fun isLeftPantsLegEnabled() = toMC().isPlayerModelPartEnabled(PlayerModelPart.LEFT_PANTS_LEG) - - fun setLeftPantsLegEnabled(toggled: Boolean) { - toMC().togglePlayerModelPart(PlayerModelPart.LEFT_PANTS_LEG, toggled) - } - - fun isRightPantsLegEnabled() = toMC().isPlayerModelPartEnabled(PlayerModelPart.RIGHT_PANTS_LEG) - - fun setRightPantsLegEnabled(toggled: Boolean) { - toMC().togglePlayerModelPart(PlayerModelPart.RIGHT_PANTS_LEG, toggled) - } - - fun isHatEnabled() = toMC().isPlayerModelPartEnabled(PlayerModelPart.HAT) - - fun setHatEnabled(toggled: Boolean) { - toMC().togglePlayerModelPart(PlayerModelPart.HAT, toggled) - } - } - - class SoundWrapper { - fun getMasterVolume() = toMC().getSoundVolumeOption(SoundCategory.MASTER).value - - fun setMasterVolume(level: Double) { - toMC().getSoundVolumeOption(SoundCategory.MASTER).value = level - } - - fun getMusicVolume() = toMC().getSoundVolumeOption(SoundCategory.MUSIC).value - - fun setMusicVolume(level: Double) { - toMC().getSoundVolumeOption(SoundCategory.MUSIC).value = level - } - - fun getNoteblockVolume() = toMC().getSoundVolumeOption(SoundCategory.RECORDS).value - - fun setNoteblockVolume(level: Double) { - toMC().getSoundVolumeOption(SoundCategory.RECORDS).value = level - } - - fun getWeather() = toMC().getSoundVolumeOption(SoundCategory.WEATHER).value - - fun setWeather(level: Double) { - toMC().getSoundVolumeOption(SoundCategory.WEATHER).value = level - } - - fun getBlocks() = toMC().getSoundVolumeOption(SoundCategory.BLOCKS).value - - fun setBlocks(level: Double) { - toMC().getSoundVolumeOption(SoundCategory.BLOCKS).value = level - } - - fun getHostileCreatures() = toMC().getSoundVolumeOption(SoundCategory.HOSTILE).value - - fun setHostileCreatures(level: Double) { - toMC().getSoundVolumeOption(SoundCategory.HOSTILE).value = level - } - - fun getFriendlyCreatures() = toMC().getSoundVolumeOption(SoundCategory.NEUTRAL).value - - fun setFriendlyCreatures(level: Double) { - toMC().getSoundVolumeOption(SoundCategory.NEUTRAL).value = level - } - - fun getPlayers() = toMC().getSoundVolumeOption(SoundCategory.PLAYERS).value - - fun setPlayers(level: Double) { - toMC().getSoundVolumeOption(SoundCategory.PLAYERS).value = level - } - - fun getAmbient() = toMC().getSoundVolumeOption(SoundCategory.AMBIENT).value - - fun setAmbient(level: Double) { - toMC().getSoundVolumeOption(SoundCategory.AMBIENT).value = level - } - } - - class VideoWrapper { - fun getGraphicsMode() = GraphicsMode.fromMC(toMC().graphicsMode.value) - - fun setGraphicsMode(mode: GraphicsMode) { - toMC().graphicsMode.value = mode.toMC() - } - - fun getRenderDistance() = toMC().viewDistance.value - - fun setRenderDistance(distance: Int) { - toMC().viewDistance.value = distance - } - - fun getSmoothLighting() = toMC().ao.value - - fun setSmoothLighting(enabled: Boolean) { - toMC().ao.value = enabled - } - - fun getMaxFrameRate() = toMC().maxFps.value - - fun setMaxFrameRate(frameRate: Int) { - toMC().maxFps.value = frameRate - } - - fun getBobbing() = toMC().bobView.value - - fun setBobbing(toggled: Boolean) { - toMC().bobView.value = toggled - } - - fun getGuiScale() = toMC().guiScale.value - - fun setGuiScale(scale: Int) { - toMC().guiScale.value = scale - } - - fun getBrightness() = toMC().gamma.value - - fun setBrightness(brightness: Double) { - toMC().gamma.value = brightness - } - - fun getClouds() = CloudRenderMode.fromMC(toMC().cloudRenderMode.value) - - fun setClouds(clouds: CloudRenderMode) { - toMC().cloudRenderMode.value = clouds.toMC() - } - - fun getParticles() = ParticlesMode.fromMC(toMC().particles.value) - - fun setParticles(particles: ParticlesMode) { - toMC().particles.value = particles.toMC() - } - - fun getFullscreen() = toMC().fullscreen.value - - fun setFullscreen(toggled: Boolean) { - toMC().fullscreen.value = toggled - } - - fun getVsync() = toMC().enableVsync.value - - fun setVsync(toggled: Boolean) { - toMC().enableVsync.value = toggled - } - - fun getMipmapLevels() = toMC().mipmapLevels.value - - fun setMipmapLevels(mipmapLevels: Int) { - toMC().mipmapLevels.value = mipmapLevels - } - - fun getEntityShadows() = toMC().entityShadows.value - - fun setEntityShadows(toggled: Boolean) { - toMC().entityShadows.value = toggled - } - } - - class ChatWrapper { - fun getVisibility() = ChatVisibility.fromMC(toMC().chatVisibility.value) - - fun setVisibility(visibility: ChatVisibility) { - toMC().chatVisibility.value = visibility.toMC() - } - - fun getColors() = toMC().chatColors.value - - fun setColors(toggled: Boolean) { - toMC().chatColors.value = toggled - } - - fun getWebLinks() = toMC().chatLinks.value - - fun setWebLinks(toggled: Boolean) { - toMC().chatLinks.value = toggled - } - - fun getOpacity() = toMC().chatOpacity.value - - fun setOpacity(opacity: Double) { - toMC().chatOpacity.value = opacity - } - - fun getPromptOnWebLinks() = toMC().chatLinksPrompt.value - - fun setPromptOnWebLinks(toggled: Boolean) { - toMC().chatLinksPrompt.value = toggled - } - - fun getScale() = toMC().chatScale.value - - fun setScale(scale: Double) { - toMC().chatScale.value = scale - } - - fun getFocusedHeight() = toMC().chatHeightFocused.value - - fun setFocusedHeight(height: Double) { - toMC().chatHeightFocused.value = height - } - - fun getUnfocusedHeight() = toMC().chatHeightUnfocused.value - - fun setUnfocusedHeight(height: Double) { - toMC().chatHeightUnfocused.value = height - } - - fun getWidth() = toMC().chatWidth.value - - fun setWidth(width: Double) { - toMC().chatWidth.value = width - } - - fun getReducedDebugInfo() = toMC().reducedDebugInfo.value - - fun setReducedDebugInfo(toggled: Boolean) { - toMC().reducedDebugInfo.value = toggled - } - } - - enum class CloudRenderMode(override val mcValue: MCCloudRenderMode) : CTWrapper { - OFF(MCCloudRenderMode.OFF), - FAST(MCCloudRenderMode.FAST), - FANCY(MCCloudRenderMode.FANCY); - - companion object { - @JvmStatic - fun fromMC(mcValue: MCCloudRenderMode) = entries.first { it.mcValue == mcValue } - - @JvmStatic - fun from(value: Any) = when (value) { - is CharSequence -> valueOf(value.toString()) - is MCCloudRenderMode -> fromMC(value) - is CloudRenderMode -> value - else -> throw IllegalArgumentException("Cannot create CloudRenderMode from $value") - } - } - } - - enum class ParticlesMode(override val mcValue: MCParticlesMode) : CTWrapper { - ALL(MCParticlesMode.ALL), - DECREASED(MCParticlesMode.DECREASED), - MINIMAL(MCParticlesMode.MINIMAL); - - companion object { - @JvmStatic - fun fromMC(mcValue: MCParticlesMode) = entries.first { it.mcValue == mcValue } - - @JvmStatic - fun from(value: Any) = when (value) { - is CharSequence -> valueOf(value.toString()) - is MCParticlesMode -> fromMC(value) - is ParticlesMode -> value - else -> throw IllegalArgumentException("Cannot create ParticlesMode from $value") - } - } - } - - enum class ChatVisibility(override val mcValue: MCChatVisibility) : CTWrapper { - FULL(MCChatVisibility.FULL), - SYSTEM(MCChatVisibility.SYSTEM), - HIDDEN(MCChatVisibility.HIDDEN); - - companion object { - @JvmStatic - fun fromMC(mcValue: MCChatVisibility) = entries.first { it.mcValue == mcValue } - - @JvmStatic - fun from(value: Any) = when (value) { - is CharSequence -> valueOf(value.toString()) - is MCChatVisibility -> fromMC(value) - is ChatVisibility -> value - else -> throw IllegalArgumentException("Cannot create ChatVisibility from $value") - } - } - } - - enum class Difficulty(override val mcValue: MCDifficulty) : CTWrapper { - PEACEFUL(MCDifficulty.PEACEFUL), - EASY(MCDifficulty.EASY), - NORMAL(MCDifficulty.NORMAL), - HARD(MCDifficulty.HARD); - - companion object { - @JvmStatic - fun fromMC(mcValue: MCDifficulty) = entries.first { it.mcValue == mcValue } - } - } - - enum class GraphicsMode(override val mcValue: MCGraphicsMode) : CTWrapper { - FAST(MCGraphicsMode.FAST), - FANCY(MCGraphicsMode.FANCY), - FABULOUS(MCGraphicsMode.FABULOUS); - - companion object { - @JvmStatic - fun fromMC(mcValue: MCGraphicsMode) = entries.first { it.mcValue == mcValue } - } - } -} diff --git a/src/main/kotlin/com/chattriggers/ctjs/api/client/Sound.kt b/src/main/kotlin/com/chattriggers/ctjs/api/client/Sound.kt deleted file mode 100644 index e5c31393..00000000 --- a/src/main/kotlin/com/chattriggers/ctjs/api/client/Sound.kt +++ /dev/null @@ -1,548 +0,0 @@ -package com.chattriggers.ctjs.api.client - -import com.chattriggers.ctjs.CTJS -import com.chattriggers.ctjs.api.CTWrapper -import com.chattriggers.ctjs.api.world.World -import com.chattriggers.ctjs.internal.mixins.AbstractSoundInstanceAccessor -import com.chattriggers.ctjs.internal.mixins.sound.SoundAccessor -import com.chattriggers.ctjs.internal.mixins.sound.SoundManagerAccessor -import com.chattriggers.ctjs.internal.mixins.sound.SoundSystemAccessor -import com.chattriggers.ctjs.MCAttenuationType -import com.chattriggers.ctjs.MCSound -import com.chattriggers.ctjs.internal.utils.asMixin -import gg.essential.universal.UMinecraft -import net.minecraft.client.sound.MovingSoundInstance -import net.minecraft.client.sound.Sound.RegistrationType -import net.minecraft.client.sound.WeightedSoundSet -import net.minecraft.resource.* -import net.minecraft.resource.metadata.ResourceMetadata -import net.minecraft.resource.metadata.ResourceMetadataReader -import net.minecraft.sound.SoundCategory -import net.minecraft.sound.SoundEvent -import net.minecraft.util.Identifier -import net.minecraft.util.math.Vec3d -import net.minecraft.util.math.random.Random -import org.mozilla.javascript.NativeObject -import java.io.File -import java.io.InputStream -import kotlin.io.path.Path -import kotlin.io.path.nameWithoutExtension - -/** - * Instances a new Sound with certain properties. These properties - * should be passed through as a normal JavaScript object. - * - * REQUIRED: - * - source (String) - a namespaced-identifier (e.g. `minecraft:music_disc.cat`) for a Minecraft sound, or a filename - * relative to ChatTriggers assets directory - * - * OPTIONAL: - * - stream (boolean) - whether to stream this sound rather than preload it (should be true for large files), defaults to false - * - * CONFIGURABLE (can be set in config object, or changed later): - * - category (SoundCategory) - which category this sound should be a part of, see [setCategory]. - * - volume (float) - volume of the sound, see [setVolume] - * - pitch (float) - pitch of the sound, see [setPitch] - * - x, y, z (float) - location of the sound, see [setPosition]. Defaults to the players position. - * - attenuationType (AttenuationType) - fade out type of the sound, see [setAttenuationType] - * - attenuation (int) - The attenuation distance, see [setAttenuation] - * - loop (boolean) - whether to loop this sound over and over, defaults to false - * - loopDelay (int) - Ticks to delay between looping this sound - * - * @param config the JavaScript config object - */ -class Sound(private val config: NativeObject) { - private lateinit var identifier: Identifier - private lateinit var soundImpl: SoundImpl - private lateinit var sound: MCSound - private var isCustom = false - - private var isPaused = false - - private val source = config["source"]?.toString() ?: throw IllegalArgumentException("Sound source is null.") - - // Before bootstrap, we need to store the values ourselves. Afterward, however, we should - // derive the values from the actual sound object. This switches implementations at the - // end of bootstrap() - private var soundData: SoundData = InitialSoundData(config) - - private fun bootstrap() { - if (::sound.isInitialized) - return - - CTJS.sounds.add(this) - - val soundManagerAccessor = UMinecraft.getMinecraft().soundManager.asMixin() - val soundFile = File(CTJS.assetsDir, source) - if (soundFile.exists()) { - isCustom = true - identifier = makeIdentifier(source) - val resource = Resource(CTResourcePack, soundFile::inputStream, ResourceMetadata::NONE) - soundManagerAccessor.soundResources[identifier.withPrefixedPath("sounds/").withSuffixedPath(".ogg")] = - resource - } else { - identifier = Identifier.of(source) - } - - soundImpl = SoundImpl(SoundEvent.of(identifier), soundData.category.toMC(), soundData.attenuationType.toMC()) - sound = MCSound( - identifier, - { 1f }, - { 1f }, - 1, - RegistrationType.FILE, - soundData.stream, - false, - soundData.attenuation, - ) - - if (isCustom) { - soundManagerAccessor.sounds[identifier] = WeightedSoundSet(identifier, null).apply { - add(sound) - } - } - - val initialData = soundData - soundData = BootstrappedSoundData(sound, soundImpl) - - // Apply all initial values as the user may have changed them - soundData.loop = initialData.loop - soundData.loopDelay = initialData.loopDelay - soundData.x = initialData.x - soundData.y = initialData.y - soundData.z = initialData.z - soundData.attenuation = initialData.attenuation - soundData.category = initialData.category - soundData.attenuationType = initialData.attenuationType - soundData.volume = initialData.volume - soundData.pitch = initialData.pitch - } - - fun destroy() { - stop() - if (isCustom) { - val soundManagerAccessor = UMinecraft.getMinecraft().soundManager.asMixin() - soundManagerAccessor.sounds.remove(identifier) - soundManagerAccessor.soundResources.remove(identifier) - } - } - - /** - * Gets the category of this sound, making it respect the Player's sound volume sliders. - * - * @return the category - */ - fun getCategory() = soundData.category - - /** - * Sets the category of this sound, making it respect the Player's sound volume sliders. - * - * @param category the category - */ - fun setCategory(category: Category) = apply { - soundData.category = category - } - - /** - * Gets this sound's volume. - * - * @return A float value (0.0f - 1.0f). - */ - fun getVolume() = soundData.volume - - /** - * Sets this sound's volume. - * - * @param volume A float value (0.0f - 1.0f). - */ - fun setVolume(volume: Float) = apply { - soundData.volume = volume - } - - fun getX() = soundData.x - - fun getY() = soundData.y - - fun getZ() = soundData.z - - fun setX(x: Double) = apply { - soundData.x = x - } - - fun setY(y: Double) = apply { - soundData.y = y - } - - fun setZ(z: Double) = apply { - soundData.z = z - } - - fun getPosition() = Vec3d(getX(), getY(), getZ()) - - fun setPosition(x: Double, y: Double, z: Double) = apply { - soundData.x = x - soundData.y = y - soundData.z = z - } - - /** - * Gets this sound's pitch. - * - * @return A float value (0.5f - 2.0f). - */ - fun getPitch() = soundData.pitch - - /** - * Sets this sound's pitch. - * - * @param pitch A float value (0.5f - 2.0f). - */ - fun setPitch(pitch: Float) = apply { - soundData.pitch = pitch - } - - /** - * Gets the attenuation type (fade out over space) of the sound - * - * @return The type of Attenuation - */ - fun getAttenuationType() = soundData.attenuationType - - /** - * Sets the attenuation type (fade out over space) of the sound - * - * @param attenuationType The type of Attenuation - */ - fun setAttenuationType(attenuationType: AttenuationType) = apply { - soundData.attenuationType = attenuationType - } - - /** - * Gets the attenuation distance of the sound - */ - fun getAttenuation() = soundData.attenuation - - /** - * Sets the attenuation distance of the sound - */ - fun setAttenuation(attenuation: Int) = apply { - soundData.attenuation = attenuation - } - - /** - * Gets whether the sound should repeat after finishing - */ - fun getLoop() = soundData.loop - - /** - * Sets whether the sound should repeat after finishing - */ - fun setLoop(loop: Boolean) = apply { - soundData.loop = loop - } - - /** - * Gets the tick delay after finishing before looping again (if getLoop() is true) - */ - fun getLoopDelay() = soundData.loopDelay - - /** - * Sets the tick delay after finishing before looping again (if getLoop() is true) - */ - fun setLoopDelay(loopDelay: Int) = apply { - soundData.loopDelay = loopDelay - } - - /** - * Plays/resumes the sound. This requires the world to be loaded - */ - @JvmOverloads - fun play(delay: Int = 0) { - // TODO: Figure out how to work without a world - require (World.isLoaded()) { "Can not play a custom sound outside the world" } - - bootstrap() - - // soundSystem.play() does a lot of setup and, most importantly, creates a new - // source for the sound. If we have previously paused, we avoid all that setup - // and instead directly invoke the play method from OpenAL via Source.play - if (!isPaused) { - soundSystem.play(soundImpl, delay) - } else { - Client.scheduleTask(delay) { - isPaused = false - soundSystem.asMixin().sources[soundImpl]?.run { - it.resume() - } - } - } - } - - /** - * Pauses the sound, to be resumed later. This requires the world to be loaded - */ - fun pause() { - // TODO: Figure out how to work without a world - require (World.isLoaded()) { "Can not pause a custom sound outside the world" } - - bootstrap() - - Client.scheduleTask { - isPaused = true - soundSystem.asMixin().sources[soundImpl]?.run { - it.pause() - } - } - } - - /** - * Completely stops the sound. This requires the world to be loaded - */ - fun stop() { - // TODO: Figure out how to work without a world - require (World.isLoaded()) { "Can not stop a custom sound outside the world" } - - bootstrap() - soundSystem.stop(soundImpl) - isPaused = false - } - - /** - * Immediately restarts the sound. This requires the world to be loaded - */ - fun rewind() { - stop() - play() - } - - private fun makeIdentifier(source: String): Identifier { - return Identifier.of( - CTJS.MOD_ID, - Path(source).nameWithoutExtension.lowercase().filter { it in validIdentChars } + "_${counter++}", - ) - } - - private interface SoundData { - var loop: Boolean - var loopDelay: Int - var stream: Boolean - var volume: Float - var pitch: Float - var x: Double - var y: Double - var z: Double - var attenuation: Int - var category: Category - var attenuationType: AttenuationType - } - - private class InitialSoundData(config: NativeObject) : SoundData { - override var loop = config.getOrDefault("loop", false) as Boolean - override var loopDelay = (config.getOrDefault("loopDelay", 0) as Number).toInt() - override var stream = config.getOrDefault("stream", false) as Boolean - override var volume = (config.getOrDefault("volume", 1f) as Number).toFloat() - override var pitch = (config.getOrDefault("pitch", 1f) as Number).toFloat() - override var x = (config.getOrDefault("x", Player.getX()) as Number).toDouble() - override var y = (config.getOrDefault("y", Player.getY()) as Number).toDouble() - override var z = (config.getOrDefault("z", Player.getZ()) as Number).toDouble() - override var attenuation = (config.getOrDefault("attenuation", 16) as Number).toInt() - override var category = config["category"]?.let(Category::from) ?: Category.MASTER - override var attenuationType = config["attenuationType"]?.let(AttenuationType::from) ?: AttenuationType.LINEAR - } - - private class BootstrappedSoundData( - private val sound: MCSound, - private val impl: SoundImpl, - ) : SoundData { - private val mixedSound: SoundAccessor = sound.asMixin() - private val mixedImpl: AbstractSoundInstanceAccessor = impl.asMixin() - - override var volume by impl::volume - override var pitch by impl::pitch - - override var loop: Boolean - get() = impl.isRepeatable - set(value) { - mixedImpl.setRepeat(value) - } - - override var loopDelay: Int - get() = impl.repeatDelay - set(value) { - mixedImpl.setRepeatDelay(value) - } - - override var stream: Boolean - get() = error("stream should not be accessed after bootstrap") - set(_) = error("stream should not be accessed after bootstrap") - - override var x: Double - get() = impl.x - set(value) { - impl.setPosition(value, y, z) - } - - override var y: Double - get() = impl.y - set(value) { - impl.setPosition(x, value, z) - } - - override var z: Double - get() = impl.z - set(value) { - impl.setPosition(x, y, value) - } - - override var attenuation: Int - get() = sound.attenuation - set(value) { - mixedSound.setAttenuation(value) - } - - override var category: Category - get() = Category.fromMC(impl.categoryOverride) - set(value) { - impl.categoryOverride = value.toMC() - } - - override var attenuationType: AttenuationType - get() = AttenuationType.fromMC(impl.attenuationType) - set(value) { - impl.attenuationType = value.toMC() - } - } - - private class SoundImpl( - soundEvent: SoundEvent, - soundCategory: SoundCategory, - attenuationType: MCAttenuationType, - ) : MovingSoundInstance(soundEvent, soundCategory, Random.create()) { - var categoryOverride: SoundCategory = super.category - - init { - this.attenuationType = attenuationType - } - - override fun tick() { - if (!World.isLoaded()) - setDone() - } - - override fun getCategory(): SoundCategory { - return categoryOverride - } - - fun setPosition(x: Double, y: Double, z: Double) { - this.x = x - this.y = y - this.z = z - } - - fun setAttenuationType(attenuationType: MCAttenuationType) { - this.attenuationType = attenuationType - } - - fun setVolume(volume: Float) { - this.volume = volume.coerceIn(0f, 1f) - } - - fun setPitch(pitch: Float) { - this.pitch = pitch.coerceIn(0.5f, 2f) - } - } - - enum class Category(override val mcValue: SoundCategory) : CTWrapper { - MASTER(SoundCategory.MASTER), - MUSIC(SoundCategory.MUSIC), - RECORDS(SoundCategory.RECORDS), - WEATHER(SoundCategory.WEATHER), - BLOCKS(SoundCategory.BLOCKS), - HOSTILE(SoundCategory.HOSTILE), - NEUTRAL(SoundCategory.NEUTRAL), - PLAYERS(SoundCategory.PLAYERS), - AMBIENT(SoundCategory.AMBIENT), - VOICE(SoundCategory.VOICE); - - companion object { - @JvmStatic - fun fromMC(mcValue: SoundCategory) = entries.first { it.mcValue == mcValue } - - @JvmStatic - fun from(value: Any) = when (value) { - is CharSequence -> valueOf(value.toString()) - is SoundCategory -> fromMC(value) - is Category -> value - else -> throw IllegalArgumentException("Cannot create Sound.Category from $value") - } - } - } - - enum class AttenuationType(override val mcValue: MCAttenuationType) : CTWrapper { - NONE(MCAttenuationType.NONE), - LINEAR(MCAttenuationType.LINEAR); - - companion object { - @JvmStatic - fun fromMC(mcValue: MCAttenuationType) = entries.first { it.mcValue == mcValue } - - @JvmStatic - fun from(value: Any) = when (value) { - is CharSequence -> valueOf(value.toString()) - is MCAttenuationType -> fromMC(value) - is AttenuationType -> value - else -> throw IllegalArgumentException("Cannot create Sound.Category from $value") - } - } - } - - private object CTResourcePack : ResourcePack { - override fun getId() = CTJS.MOD_ID - - override fun close() { - throw UnsupportedOperationException() - } - - override fun openRoot(vararg segments: String?): InputSupplier? { - throw UnsupportedOperationException() - } - - override fun open(type: ResourceType?, id: Identifier?): InputSupplier? { - throw UnsupportedOperationException() - } - - override fun findResources( - type: ResourceType?, - namespace: String?, - prefix: String?, - consumer: ResourcePack.ResultConsumer? - ) { - throw UnsupportedOperationException() - } - - override fun getNamespaces(type: ResourceType?): MutableSet { - throw UnsupportedOperationException() - } - - override fun parseMetadata(metaReader: ResourceMetadataReader?): T? { - throw UnsupportedOperationException() - } - - override fun getInfo(): ResourcePackInfo { - throw NotImplementedError() - } - } - - private companion object { - private val soundSystem by lazy { - Client.getMinecraft().soundManager.asMixin().soundSystem - } - - private val validIdentChars = setOf( - *('a'..'z').toList().toTypedArray(), - *('0'..'9').toList().toTypedArray(), - '_', '.', '-', '/', - ) - private var counter = 0 - } -} diff --git a/src/main/kotlin/com/chattriggers/ctjs/api/commands/DynamicCommands.kt b/src/main/kotlin/com/chattriggers/ctjs/api/commands/DynamicCommands.kt deleted file mode 100644 index 957bf025..00000000 --- a/src/main/kotlin/com/chattriggers/ctjs/api/commands/DynamicCommands.kt +++ /dev/null @@ -1,902 +0,0 @@ -package com.chattriggers.ctjs.api.commands - -import com.chattriggers.ctjs.api.client.Player -import com.chattriggers.ctjs.api.commands.DynamicCommands.argument -import com.chattriggers.ctjs.api.commands.DynamicCommands.buildCommand -import com.chattriggers.ctjs.api.commands.DynamicCommands.custom -import com.chattriggers.ctjs.api.commands.DynamicCommands.literal -import com.chattriggers.ctjs.api.commands.DynamicCommands.message -import com.chattriggers.ctjs.api.commands.DynamicCommands.redirect -import com.chattriggers.ctjs.api.entity.Entity -import com.chattriggers.ctjs.api.entity.PlayerMP -import com.chattriggers.ctjs.api.inventory.Item -import com.chattriggers.ctjs.api.inventory.ItemType -import com.chattriggers.ctjs.api.inventory.nbt.NBTBase -import com.chattriggers.ctjs.api.inventory.nbt.NBTTagCompound -import com.chattriggers.ctjs.api.message.TextComponent -import com.chattriggers.ctjs.api.world.World -import com.chattriggers.ctjs.api.world.block.BlockFace -import com.chattriggers.ctjs.api.world.block.BlockPos -import com.chattriggers.ctjs.internal.commands.CommandCollection -import com.chattriggers.ctjs.internal.commands.DynamicCommand -import com.chattriggers.ctjs.internal.engine.JSLoader -import com.chattriggers.ctjs.internal.mixins.commands.EntitySelectorAccessor -import com.chattriggers.ctjs.MCEntity -import com.chattriggers.ctjs.MCNbtCompound -import com.chattriggers.ctjs.api.client.Client -import com.chattriggers.ctjs.internal.utils.asMixin -import com.mojang.brigadier.CommandDispatcher -import com.mojang.brigadier.ImmutableStringReader -import com.mojang.brigadier.StringReader -import com.mojang.brigadier.arguments.* -import com.mojang.brigadier.context.CommandContext -import com.mojang.brigadier.exceptions.SimpleCommandExceptionType -import com.mojang.brigadier.suggestion.Suggestions -import com.mojang.brigadier.suggestion.SuggestionsBuilder -import com.mojang.brigadier.tree.CommandNode -import net.minecraft.block.pattern.CachedBlockPosition -import net.minecraft.command.CommandSource -import net.minecraft.command.EntitySelector -import net.minecraft.command.argument.* -import net.minecraft.command.argument.AngleArgumentType.Angle -import net.minecraft.entity.player.PlayerEntity -import net.minecraft.item.ItemStack -import net.minecraft.registry.BuiltinRegistries -import net.minecraft.server.command.CommandManager -import net.minecraft.server.command.ServerCommandSource -import net.minecraft.util.math.Box -import net.minecraft.util.math.Vec2f -import net.minecraft.util.math.Vec3d -import org.mozilla.javascript.Function -import org.mozilla.javascript.NativeObject -import org.mozilla.javascript.WrappedException -import java.util.concurrent.CompletableFuture -import java.util.function.Predicate -import kotlin.math.min - -/** - * An alternative to the command register that allows full use of the - * functionality provided by Brigadier. - * - * For more information about Brigadier, see - * their GitHub page. - * Also see [CTCommand] for an example Brigadier command. - * - * ## General - * - * This API works similarly to Brigadier, however much of the annoyance - * of using the Brigadier API has been eliminated, mainly the excessive - * use of nested function calls. It works via a global context, so function - * calls are free. However, this means that multiples commands cannot be - * built at once. This means that commands should only ever be built on the - * main thread. If two commands are built at the same time, an error will be - * thrown. - * - * ## Argument Types - * - * The [ArgumentType] interface is a fundamental part of Brigadier, and - * most of the MC argument types have been exposed via helper function - * in this class. It is also possible to build new instances of - * [ArgumentType] via [custom]. - * - * When possible, the argument types returned from the helper function on - * this class resolve in a way that their Minecraft variants do. For example, - * the [message] type will replace selectors with their target entity, if - * possible. - * - * ## Basic Example - * - * Here is an example command that recreates the `/advancement` command - * (without any of the actual functionality, of course): - * - * ```js - * // The `Commands` object supports destructuring, which makes assembling long - * // commands much nicer - * const { argument, choices, exec, greedyString, literal, registerCommand, resource, players } = Commands; - * - * registerCommand('ctadvancement', () => { - * // Note the use of choices to avoid having to copy-paste two separate literal() trees - * argument('kind', choices('grant', 'revoke'), () => { - * argument('targets', players(), () => { - * literal('everything', () => { - * // exec() receives a single object with all of the arguments, which means we can - * // destructure it to pull out the ones we want. Only values from argument() calls - * // are included here; the literal nodes are ignored and have no impact on this object. - * exec(({ kind, targets }) => { - * ChatLib.chat(`${kind} everything from ${targets}`); - * }); - * }); - * - * literal('only', () => { - * argument('advancement', resource(), () => { - * argument('criterion', greedyString(), () => { - * exec(({ kind, targets, advancement, criterion }) => { - * ChatLib.chat(`${kind} only ${advancement} applied to ${targets} (criterion = ${criterion})`); - * }); - * }); - * }); - * }); - * - * argument('subkind', choices('from', 'through', 'until'), () => { - * argument('advancement', resource(), () => { - * exec(({ kind, subkind, targets, advancement }) => { - * ChatLib.chat(`kind = ${kind}, subkind = ${subkind}, advancement = ${advancement}, targets = ${targets}`); - * }); - * }); - * }); - * }); - * }); - * }); - * ``` - * - * ## Redirect - * - * Like Brigadier, this API supports assembling partial command nodes for use - * in redirection. To do this, use [buildCommand], which returns the command node - * (well, an internal representation of it). This object can then be passed to - * further calls to [redirect] inside of a [literal] or [argument] block. - * - * Examples: - * - * ```js - * // destructuring omitted - * - * const testCmdNode = buildCommand('testcmd', () => { - * exec(({ arg }) => { - * if (arg) { - * ChatLib.chat(`arg supplied, value = ${arg}`); - * } else { - * ChatLib.chat('no arg supplied'); - * } - * }); - * }); - * - * // Manually register it since we used buildCommand() instead of registerCommand() - * testCmdNode.register() - * - * registerCommand('testcmd', () => { - * argument('arg', greedyString(), () => { - * redirect(testCmdNode); - * }); - * }); - * ``` - */ -object DynamicCommands : CommandCollection() { - private var currentNode: DynamicCommand.Node? = null - - //////////////////// - // Tree Functions // - //////////////////// - - @JvmStatic - @JvmOverloads - fun registerCommand(name: String, builder: Function? = null) = buildCommand(name, builder).also { - it.register() - } - - @JvmStatic - @JvmOverloads - fun buildCommand(name: String, builder: Function? = null): RootCommand { - require(currentNode == null) { "Command.buildCommand() called while already building a command" } - val node = DynamicCommand.Node.Root(name) - if (builder != null) - processNode(node, builder) - return node - } - - @JvmStatic - fun argument(name: String, type: ArgumentType, builder: Function) { - requireNotNull(currentNode) { "Call to Commands.argument() outside of Commands.buildCommand()" } - require(!currentNode!!.hasRedirect) { "Cannot redirect node with children" } - val node = DynamicCommand.Node.Argument(currentNode, name, type) - processNode(node, builder) - currentNode!!.children.add(node) - } - - @JvmStatic - fun literal(name: String, builder: Function) { - requireNotNull(currentNode) { "Call to Commands.literal() outside of Commands.buildCommand()" } - require(!currentNode!!.hasRedirect) { "Cannot redirect node with children" } - val node = DynamicCommand.Node.Literal(currentNode, name) - processNode(node, builder) - currentNode!!.children.add(node) - } - - @JvmStatic - fun redirect(node: RootCommand) { - requireNotNull(currentNode) { "Call to Commands.redirect() outside of Commands.buildCommand()" } - require(!currentNode!!.hasRedirect) { "Duplicate call to Commands.redirect()" } - currentNode!!.children.add(DynamicCommand.Node.Redirect(currentNode, node as DynamicCommand.Node.Root)) - currentNode!!.hasRedirect = true - } - - @JvmStatic - fun redirect(node: CommandNode) { - requireNotNull(currentNode) { "Call to Commands.redirect() outside of Commands.buildCommand()" } - require(!currentNode!!.hasRedirect) { "Duplicate call to Commands.redirect()" } - currentNode!!.children.add(DynamicCommand.Node.RedirectToCommandNode(currentNode, node)) - currentNode!!.hasRedirect = true - } - - @JvmStatic - fun exec(method: Function) { - requireNotNull(currentNode) { "Call to Commands.argument() outside of Commands.buildCommand()" } - require(!currentNode!!.hasRedirect) { "Cannot execute node with children" } - require(currentNode!!.method == null) { "Duplicate call to Commands.exec()" } - currentNode!!.method = method - } - - /** - * A helper method for getting Fabric's client CommandDispatcher root node. This allows user - * commands to be redirected to the root node in the same way that "/execute run ..." does. - * - * As the result is a CommandNode, `.getChild(name)` can be used to access sub-command nodes - * to, for example, redirect to just `/advancement` instead of `/`. - */ - @JvmStatic - fun getDispatcherRoot() = Client.getConnection()?.commandDispatcher?.root - - ///////////////////////// - // Brigadier Arg Types // - ///////////////////////// - - /** - * @see Argument Types: bool - */ - @JvmStatic - fun bool(): BoolArgumentType = BoolArgumentType.bool() - - /** - * @see brigadier:double - */ - @JvmStatic - @JvmOverloads - fun double(min: Double = Double.MIN_VALUE, max: Double = Double.MAX_VALUE): DoubleArgumentType = - DoubleArgumentType.doubleArg(min, max) - - /** - * @see brigadier:float - */ - @JvmStatic - @JvmOverloads - fun float(min: Float = Float.MIN_VALUE, max: Float = Float.MAX_VALUE): FloatArgumentType = - FloatArgumentType.floatArg(min, max) - - /** - * @see brigadier:integer - */ - @JvmStatic - @JvmOverloads - fun integer(min: Int = Int.MIN_VALUE, max: Int = Int.MAX_VALUE): IntegerArgumentType = - IntegerArgumentType.integer(min, max) - - /** - * @see brigadier:long - */ - @JvmStatic - @JvmOverloads - fun long(min: Long = Long.MIN_VALUE, max: Long = Long.MAX_VALUE): LongArgumentType = - LongArgumentType.longArg(min, max) - - /** - * @see brigadier:string - */ - @JvmStatic - fun string(): StringArgumentType = StringArgumentType.string() - - /** - * @see brigadier:string - */ - @JvmStatic - fun greedyString(): StringArgumentType = StringArgumentType.greedyString() - - /** - * @see brigadier:string - */ - @JvmStatic - fun word(): StringArgumentType = StringArgumentType.word() - - ////////////////// - // MC Arg Types // - ////////////////// - - /** - * @see minecraft:angle - */ - @JvmStatic - fun angle() = wrapArgument(AngleArgumentType.angle(), ::AngleArgumentWrapper) - - /** - * @see minecraft:block_pos - */ - @JvmStatic - fun blockPos(): ArgumentType { - return wrapArgument(BlockPosArgumentType.blockPos(), ::PosArgumentWrapper) - } - - /** - * @see minecraft:block_predicate - */ - @JvmStatic - fun blockPredicate(): ArgumentType { - val registryAccess = CommandManager.createRegistryAccess(BuiltinRegistries.createWrapperLookup()) - val predicate = BlockPredicateArgumentType.blockPredicate(registryAccess) - return wrapArgument(predicate, ::BlockPredicateWrapper) - } - - /** - * @see minecraft:block_state - */ - @JvmStatic - fun blockState(): ArgumentType { - val registryAccess = CommandManager.createRegistryAccess(BuiltinRegistries.createWrapperLookup()) - val predicate = BlockStateArgumentType.blockState(registryAccess) - return wrapArgument(predicate, ::BlockStateArgumentWrapper) - } - - /** - * @see minecraft:color - */ - @JvmStatic - fun color() = ColorArgumentType.color() - - /** - * @see minecraft:column_pos - */ - @JvmStatic - fun columnPos() = wrapArgument(ColumnPosArgumentType.columnPos(), ::PosArgumentWrapper) - - /** - * @see minecraft:dimension - */ - @JvmStatic - fun dimension() = wrapArgument( - choices( - "minecraft:overworld", - "minecraft:the_nether", - "minecraft:the_end", - "minecraft:overworld_caves", - ) - ) { name -> - Entity.DimensionType.entries.first { it.toMC().value.toString() == name } - } - - /** - * @see minecraft:entity - */ - @JvmStatic - fun entity() = wrapArgument(EntityArgumentType.entity()) { EntitySelectorWrapper(it).getEntity() } - - /** - * @see minecraft:entity - */ - @JvmStatic - fun entities() = wrapArgument(EntityArgumentType.entities()) { EntitySelectorWrapper(it).getEntities() } - - /** - * @see minecraft:float_range - */ - @JvmStatic - fun floatRange() = NumberRangeArgumentType.floatRange() - - /** - * @see minecraft:game_profile - */ - @JvmStatic - fun gameProfile() = players() - - /** - * @see minecraft:game_profile - */ - @JvmStatic - fun player() = wrapArgument(EntityArgumentType.player()) { - EntitySelectorWrapper(it).getPlayers().let { players -> - when { - players.isEmpty() -> throw EntityArgumentType.PLAYER_NOT_FOUND_EXCEPTION.create() - players.size > 1 -> throw EntityArgumentType.TOO_MANY_PLAYERS_EXCEPTION.create() - else -> players[0] - } - } - } - - /** - * @see minecraft:game_profile - */ - @JvmStatic - fun players() = wrapArgument(EntityArgumentType.players()) { EntitySelectorWrapper(it).getPlayers() } - - /** - * @see minecraft:gamemode - */ - @JvmStatic - fun gameMode() = GameModeArgumentType.gameMode() - - /** - * @see minecraft:int_range - */ - @JvmStatic - fun intRange() = NumberRangeArgumentType.intRange() - - /** - * @see minecraft:item_predicate - */ - @JvmStatic - fun itemPredicate(): ArgumentType<(Item) -> Boolean> { - val registryAccess = CommandManager.createRegistryAccess(BuiltinRegistries.createWrapperLookup()) - val predicate = ItemPredicateArgumentType.itemPredicate(registryAccess) - return wrapArgument(predicate) { pred -> { pred.test(it.mcValue) } } - } - - /** - * @see minecraft:item_slot - */ - @JvmStatic - fun itemSlot() = ItemSlotArgumentType.itemSlot() - - /** - * @see minecraft:item_stack - */ - @JvmStatic - fun itemStack(): ArgumentType { - val registryAccess = CommandManager.createRegistryAccess(BuiltinRegistries.createWrapperLookup()) - val arg = ItemStackArgumentType.itemStack(registryAccess) - return wrapArgument(arg, ::ItemStackArgumentWrapper) - } - - /** - * @see minecraft:message - */ - @JvmStatic - fun message() = wrapArgument(MessageArgumentType.message(), ::MessageFormatArgumentWrapper) - - /** - * @see minecraft:nbt_compound_tag - */ - @JvmStatic - fun nbtCompoundTag() = wrapArgument(NbtCompoundArgumentType.nbtCompound(), ::NBTTagCompound) - - /** - * @see minecraft:nbt_path - */ - @JvmStatic - fun nbtPath() = wrapArgument(NbtPathArgumentType.nbtPath(), ::NbtPathWrapper) - - /** - * @see minecraft:nbt_tag - */ - @JvmStatic - fun nbtTag() = wrapArgument(NbtElementArgumentType.nbtElement(), NBTBase::fromMC) - - /** - * @see minecraft:resource - */ - @JvmStatic - fun resource() = IdentifierArgumentType.identifier() - - /** - * @see minecraft:rotation - */ - @JvmStatic - fun rotation() = wrapArgument(RotationArgumentType.rotation(), ::PosArgumentWrapper) - - /** - * @see minecraft:swizzle - */ - @JvmStatic - fun swizzle() = wrapArgument(SwizzleArgumentType.swizzle()) { it.map(BlockFace.Axis::fromMC) } - - /** - * @see minecraft:time - */ - @JvmStatic - @JvmOverloads - fun time(minimum: Int = 0) = TimeArgumentType.time(minimum) - - /** - * @see minecraft:uuid - */ - @JvmStatic - fun uuid() = UuidArgumentType.uuid() - - /** - * @see minecraft:vec2 - */ - @JvmStatic - @JvmOverloads - fun vec2(centerIntegers: Boolean = true) = - wrapArgument(Vec2ArgumentType.vec2(centerIntegers), ::PosArgumentWrapper) - - /** - * @see minecraft:vec3 - */ - @JvmStatic - @JvmOverloads - fun vec3(centerIntegers: Boolean = true) = - wrapArgument(Vec3ArgumentType.vec3(centerIntegers), ::PosArgumentWrapper) - - /** - * Allows choosing from a set list of strings. When suggested to the user, this - * will look as though this argument is multiple "literal()" nodes. - */ - @JvmStatic - fun choices(vararg options: String): ArgumentType { - require(options.isNotEmpty()) { - "No strings passed to Commands.choices()" - } - require(options.all { CommandDispatcher.ARGUMENT_SEPARATOR_CHAR !in it }) { - "Commands.choices() cannot accept strings with spaces" - } - require(options.none(String::isEmpty)) { - "Commands.choices() cannot accept empty strings" - } - - return object : ArgumentType { - override fun parse(reader: StringReader): String { - val start = reader.cursor - val optionChars = options.toMutableList() - - var offset = 0 - while (reader.canRead()) { - val ch = reader.read() - optionChars.removeIf { it[offset] != ch } - if (optionChars.isEmpty()) - reader.fail(start) - offset += 1 - - val found = optionChars.find { it.length == offset } - if (found != null) - return found - } - - reader.fail(start) - } - - override fun listSuggestions( - context: CommandContext, - builder: SuggestionsBuilder - ): CompletableFuture { - options.forEach(builder::suggest) - return builder.buildFuture() - } - - override fun getExamples(): MutableCollection = options.toMutableList() - - private fun StringReader.fail(originalOffset: Int): Nothing { - cursor = originalOffset - error(this, "Expected one of: ${options.joinToString(", ")}") - } - } - } - - /** - * Allows easy creation of a custom ArgumentType without needing to use - * JavaAdapter. Example: - * - * ```js - * const HEADS = 0; - * const TAILS = 1; - * - * const coinFlipArgType = Commands.custom({ - * parse(reader) { - * // `reader` is a com.mojang.brigadier.StringReader - * - * const savedCursor = reader.getCursor(); - * const str = reader.readString(); - * if (str === 'heads') - * return HEADS; - * if (str === 'tails') - * return TAILS; - * Commands.error(reader, `Expected one of: 'heads', 'tails'`); - * }, - * suggest(ctx, builder) { - * // ctx is a com.mojang.brigadier.context.CommandContext - * // builder is a com.mojang.brigadier.suggestion.SuggestionsBuilder - * builder.suggest('heads'); - * builder.suggest('tails'); - * return builder.buildFuture(); - * }, - * getExamples() { - * return ['heads', 'tails']; - * } - * }); - * ``` - * - * @see StringReader - * @see CommandContext - * @see SuggestionsBuilder - */ - @JvmStatic - fun custom(obj: NativeObject): ArgumentType { - val parse = obj["parse"] as? Function ?: error( - "Object provided to Commands.custom() must contain a \"parse\" function" - ) - - val suggest = obj["suggest"]?.let { - require(it is Function) { "A \"suggest\" key in a custom command argument type must be a Function" } - it - } - - val getExamples = obj["getExamples"]?.let { - require(it is Function) { "A \"getExamples\" key in a custom command argument type must be a Function" } - it - } - - return object : ArgumentType { - override fun parse(reader: StringReader?): Any? { - return try { - JSLoader.invoke(parse, arrayOf(reader)) - } catch (e: WrappedException) { - throw e.wrappedException - } - } - - override fun listSuggestions( - context: CommandContext?, - builder: SuggestionsBuilder? - ): CompletableFuture { - return if (suggest != null) { - @Suppress("UNCHECKED_CAST") - JSLoader.invoke(suggest, arrayOf(context, builder)) as CompletableFuture - } else super.listSuggestions(context, builder) - } - - override fun getExamples(): MutableCollection { - return if (getExamples != null) { - @Suppress("UNCHECKED_CAST") - JSLoader.invoke(getExamples, emptyArray()) as MutableCollection - } else super.getExamples() - } - - override fun toString() = obj.toString() - } - } - - /** - * Throw a detailed error given the reader, meant to be used with [custom] - */ - @JvmStatic - fun error(reader: ImmutableStringReader, message: String): Nothing { - throw SimpleCommandExceptionType(TextComponent(message)).createWithContext(reader) - } - - /** - * Throw a detailed error given the reader, meant to be used with [custom] - */ - @JvmStatic - fun error(reader: ImmutableStringReader, message: TextComponent): Nothing = - throw SimpleCommandExceptionType(message).createWithContext(reader) - - private fun getMockCommandSource(): ServerCommandSource { - return ServerCommandSource( - Player.toMC(), - Player.getPos().toVec3d(), - Player.getRotation(), - null, - 0, - Player.getName(), - Player.getDisplayName(), - null, - Player.toMC(), - ) - } - - private fun wrapArgument(base: ArgumentType, block: (T) -> U): ArgumentType { - return object : ArgumentType { - override fun parse(reader: StringReader): U = block(base.parse(reader)) - - override fun listSuggestions( - context: CommandContext, - builder: SuggestionsBuilder, - ) = base.listSuggestions(context, builder) - - override fun getExamples() = base.examples - - override fun toString() = base.toString() - } - } - - data class AngleArgumentWrapper(val angle: Angle) { - @JvmOverloads - fun getAngle(entity: Entity = Player.asPlayerMP()!!) = angle.getAngle( - getMockCommandSource().withRotation(entity.getRotation()) - ) - } - - data class PosArgumentWrapper(val impl: PosArgument) : PosArgument by impl { - fun toAbsolutePos(): Vec3d = impl.toAbsolutePos(getMockCommandSource()) - - fun toAbsoluteBlockPos(): BlockPos = BlockPos(impl.toAbsoluteBlockPos(getMockCommandSource())) - - fun toAbsoluteRotation(): Vec2f = impl.toAbsoluteRotation(getMockCommandSource()) - - override fun toString() = "PosArgument" - } - - data class BlockPredicateWrapper(val impl: BlockPredicateArgumentType.BlockPredicate) { - fun test(blockPos: BlockPos): Boolean { - return impl.test(CachedBlockPosition(World.toMC(), blockPos.toMC(), true)) - } - - override fun toString() = "BlockPredicateArgument" - } - - data class BlockStateArgumentWrapper(val impl: BlockStateArgument) { - fun test(blockPos: BlockPos): Boolean = - impl.test(CachedBlockPosition(World.toMC(), blockPos.toMC(), true)) - - override fun toString() = "BlockStateArgument" - } - - class EntitySelectorWrapper(private val impl: EntitySelector) { - private val mixed get() = impl.asMixin() - - fun getEntity(): Entity { - val entities = getEntities() - return when { - entities.isEmpty() -> throw EntityArgumentType.ENTITY_NOT_FOUND_EXCEPTION.create() - entities.size > 1 -> throw EntityArgumentType.TOO_MANY_ENTITIES_EXCEPTION.create() - else -> entities[0] - } - } - - fun getEntities(): List { - return getUnfilteredEntities().filter { - it.toMC().type.isEnabled(World.toMC()!!.enabledFeatures) - } - } - - private fun getUnfilteredEntities(): List { - if (!mixed.includesNonPlayers) - return getPlayers() - - if (mixed.playerName != null) { - val entity = World.getAllEntitiesOfType(PlayerEntity::class.java).find { - it.getName() == mixed.playerName - } - return listOfNotNull(entity) - } - - if (mixed.uuid != null) { - val entity = World.getAllEntitiesOfType(PlayerEntity::class.java).find { - it.getUUID() == mixed.uuid - } - return listOfNotNull(entity) - } - - val position = mixed.positionOffset.apply(Player.getPos().toVec3d()) - val predicate = getPositionPredicate(position) - if (mixed.senderOnly) { - if (predicate.test(Player.toMC()!!)) - return listOf(Player.asPlayerMP()!!) - return emptyList() - } - - val entities = mutableListOf() - appendEntitiesFromWorld(entities, position, predicate) - return getEntities(position, entities).map(Entity::fromMC) - } - - fun getPlayers(): List { - if (mixed.playerName != null) { - val entity = World.getAllEntitiesOfType(PlayerEntity::class.java).find { - it.getName() == mixed.playerName - } - @Suppress("UNCHECKED_CAST") - return listOfNotNull(entity) as List - } - - if (mixed.uuid != null) { - val entity = World.getAllEntitiesOfType(PlayerEntity::class.java).find { - it.getUUID() == mixed.uuid - } - @Suppress("UNCHECKED_CAST") - return listOfNotNull(entity) as List - } - - val position = mixed.positionOffset.apply(Player.getPos().toVec3d()) - val predicate = getPositionPredicate(position) - if (mixed.senderOnly) { - if (predicate.test(Player.toMC()!!)) - return listOf(Player.asPlayerMP()!!) - return emptyList() - } - - val limit = if (mixed.sorter == EntitySelector.ARBITRARY) mixed.limit else Int.MAX_VALUE - val players = World.toMC()!!.players.filter(predicate::test).take(limit).toMutableList() - return getEntities(position, players).map { PlayerMP(it as PlayerEntity) } - } - - private fun getEntities(pos: Vec3d, entities: MutableList): List { - if (entities.size > 1) - mixed.sorter.accept(pos, entities) - return entities.subList(0, min(mixed.limit, entities.size)) - } - - private fun appendEntitiesFromWorld( - entities: MutableList, - pos: Vec3d, - predicate: Predicate - ) { - val limit = if (mixed.sorter == EntitySelector.ARBITRARY) mixed.limit else Int.MAX_VALUE - if (entities.size >= limit) - return - - val min = pos.add(Vec3d(-1000.0, -1000.0, -1000.0)) - val max = pos.add(Vec3d(1000.0, 1000.0, 1000.0)) - val box = mixed.box?.offset(pos) ?: Box(min, max) - World.toMC()!!.collectEntitiesByType(mixed.entityFilter, box, predicate, entities, limit) - } - - private fun getPositionPredicate(pos: Vec3d): Predicate { - var predicate = mixed.predicates.reduceOrNull { acc, predicate -> acc.and(predicate) } ?: Predicate { true } - if (mixed.box != null) { - val box = mixed.box!!.offset(pos) - predicate = predicate.and { box.intersects(it.boundingBox) } - } - if (!mixed.distance.isDummy) - predicate = predicate.and { mixed.distance.testSqrt(it.squaredDistanceTo(pos)) } - return predicate - } - } - - data class ItemStackArgumentWrapper(private val impl: ItemStackArgument) : Predicate { - val itemType = ItemType(impl.item) - - override fun test(item: Item) = ItemStack.areItemsAndComponentsEqual(itemType.asItem().toMC(), item.toMC()) - - fun test(type: ItemType) = itemType.getRegistryName() == type.getRegistryName() - } - - data class MessageFormatArgumentWrapper(private val impl: MessageArgumentType.MessageFormat) { - var text = impl.contents - - fun format(): TextComponent { - if (impl.selectors.isEmpty()) - return TextComponent(text) - - var component = TextComponent(text.substring(0, impl.selectors[0].start)) - var i = impl.selectors[0].start - - for (selector in impl.selectors) { - val entities = EntitySelectorWrapper(selector.selector).getEntities() - val nameComponent = EntitySelector.getNames(entities.map(Entity::toMC)) - if (i < selector.start) - component = component.withText(text.substring(i, selector.start)) - - if (nameComponent != null) - component = component.withText(nameComponent) - - i = selector.end - } - - if (i < text.length) - component = component.withText(text.drop(i)) - - return component - } - - override fun toString() = text - } - - data class NbtPathWrapper(private val impl: NbtPathArgumentType.NbtPath) { - fun get(nbt: NBTBase) = impl.get(nbt.toMC()) - fun count(nbt: NBTBase) = impl.count(nbt.toMC()) - fun getOrInit(nbt: NBTBase, supplier: () -> NBTBase) = impl.getOrInit(nbt.toMC()) { supplier().toMC() } - fun put(nbt: NBTBase, source: NBTBase) = impl.put(nbt.toMC(), source.toMC()) - fun insert(index: Int, compound: NBTTagCompound, elements: List) = - impl.insert(index, compound.toMC() as MCNbtCompound, elements.map(NBTBase::toMC)) - - fun remove(element: NBTBase) = impl.remove(element.toMC()) - - override fun toString() = impl.toString() - } - - private fun processNode(node: DynamicCommand.Node, builder: Function) { - currentNode = node - try { - JSLoader.invoke(builder, emptyArray()) - } finally { - currentNode = node.parent - } - } -} diff --git a/src/main/kotlin/com/chattriggers/ctjs/api/commands/RootCommand.kt b/src/main/kotlin/com/chattriggers/ctjs/api/commands/RootCommand.kt deleted file mode 100644 index d600c51a..00000000 --- a/src/main/kotlin/com/chattriggers/ctjs/api/commands/RootCommand.kt +++ /dev/null @@ -1,7 +0,0 @@ -package com.chattriggers.ctjs.api.commands - -// This really only exists so that we can hide away the DynamicCommand internals -// in the internals package -interface RootCommand { - fun register() -} diff --git a/src/main/kotlin/com/chattriggers/ctjs/api/entity/BlockEntity.kt b/src/main/kotlin/com/chattriggers/ctjs/api/entity/BlockEntity.kt deleted file mode 100644 index 47e29394..00000000 --- a/src/main/kotlin/com/chattriggers/ctjs/api/entity/BlockEntity.kt +++ /dev/null @@ -1,27 +0,0 @@ -package com.chattriggers.ctjs.api.entity - -import com.chattriggers.ctjs.api.CTWrapper -import com.chattriggers.ctjs.api.world.block.Block -import com.chattriggers.ctjs.api.world.block.BlockPos -import com.chattriggers.ctjs.api.world.block.BlockType -import com.chattriggers.ctjs.MCBlockEntity -import net.minecraft.block.entity.BlockEntityType - -class BlockEntity(override val mcValue: MCBlockEntity) : CTWrapper { - - fun getX(): Int = getBlockPos().x - - fun getY(): Int = getBlockPos().y - - fun getZ(): Int = getBlockPos().z - - fun getBlockType(): BlockType = BlockType(BlockEntityType.getId(mcValue.type)!!.toString()) - - fun getBlockPos(): BlockPos = BlockPos(mcValue.pos) - - fun getBlock(): Block = Block(getBlockType(), getBlockPos()) - - override fun toString(): String { - return "BlockEntity(type=${getBlockType()}, pos=[${getX()}, ${getY()}, ${getZ()}])" - } -} diff --git a/src/main/kotlin/com/chattriggers/ctjs/api/entity/Entity.kt b/src/main/kotlin/com/chattriggers/ctjs/api/entity/Entity.kt deleted file mode 100644 index 7ea3b638..00000000 --- a/src/main/kotlin/com/chattriggers/ctjs/api/entity/Entity.kt +++ /dev/null @@ -1,258 +0,0 @@ -package com.chattriggers.ctjs.api.entity - -import com.chattriggers.ctjs.api.CTWrapper -import com.chattriggers.ctjs.api.message.TextComponent -import com.chattriggers.ctjs.api.render.Renderer -import com.chattriggers.ctjs.api.world.Chunk -import com.chattriggers.ctjs.api.world.World -import com.chattriggers.ctjs.api.world.block.BlockPos -import com.chattriggers.ctjs.MCDimensionType -import com.chattriggers.ctjs.MCEntity -import com.chattriggers.ctjs.MCLivingEntity -import net.minecraft.entity.player.PlayerEntity -import net.minecraft.registry.RegistryKey -import net.minecraft.util.math.MathHelper -import net.minecraft.world.dimension.DimensionTypes -import java.util.* -import kotlin.math.sqrt - -open class Entity(override val mcValue: MCEntity) : CTWrapper { - fun getX() = mcValue.pos.x - - fun getY() = mcValue.pos.y - - fun getZ() = mcValue.pos.z - - fun getPos() = BlockPos(getX(), getY(), getZ()) - - fun getRotation() = mcValue.rotationClient - - fun getLastX() = mcValue.lastRenderX - - fun getLastY() = mcValue.lastRenderY - - fun getLastZ() = mcValue.lastRenderZ - - fun getRenderX() = getLastX() + (getX() - getLastX()) * Renderer.partialTicks - - fun getRenderY() = getLastY() + (getY() - getLastY()) * Renderer.partialTicks - - fun getRenderZ() = getLastZ() + (getZ() - getLastZ()) * Renderer.partialTicks - - /** - * Gets the pitch, the horizontal direction the entity is facing towards. - * This has a range of -180 to 180. - * - * @return the entity's pitch - */ - fun getPitch() = MathHelper.wrapDegrees(mcValue.getPitch(Renderer.partialTicks)) - - /** - * Gets the yaw, the vertical direction the entity is facing towards. - * This has a range of -180 to 180. - * - * @return the entity's yaw - */ - fun getYaw() = MathHelper.wrapDegrees(mcValue.getYaw(Renderer.partialTicks)) - - /** - * Gets the entity's x motion. - * This is the amount the entity will move in the x direction next tick. - * - * @return the entity's x motion - */ - fun getMotionX(): Double = mcValue.velocity.x - - /** - * Gets the entity's y motion. - * This is the amount the entity will move in the y direction next tick. - * - * @return the entity's y motion - */ - fun getMotionY(): Double = mcValue.velocity.y - - /** - * Gets the entity's z motion. - * This is the amount the entity will move in the z direction next tick. - * - * @return the entity's z motion - */ - fun getMotionZ(): Double = mcValue.velocity.z - - /** - * Returns the entity this entity is riding, if one exists - * - * @return an Entity or null - */ - fun getRiding(): Entity? { - return mcValue.vehicle?.let(::fromMC) - } - - /** - * Returns a list of all entity riding this entity - * - * @return List of entities, empty if there are no riders - */ - fun getRiders() = mcValue.passengerList?.map(::fromMC).orEmpty() - - /** - * Checks whether the entity is dead. - * This is a fairly loose term, dead for a particle could mean it has faded, - * while dead for an entity means it has no health. - * - * @return whether an entity is dead - */ - fun isDead(): Boolean = !mcValue.isAlive - - /** - * Gets the entire width of the entity's hitbox - * - * @return the entity's width - */ - fun getWidth(): Float = mcValue.width - - /** - * Gets the entire height of the entity's hitbox - * - * @return the entity's height - */ - fun getHeight(): Float = mcValue.height - - /** - * Gets the height of the eyes on the entity, - * can be added to its Y coordinate to get the actual Y location of the eyes. - * This value defaults to 85% of an entity's height, however is different for some entities. - * - * @return the height of the entity's eyes - */ - fun getEyeHeight(): Float = mcValue.standingEyeHeight - - /** - * Gets the name of the entity, could be "Villager", - * or, if the entity has a custom name, it returns that. - * - * @return the (custom) name of the entity as a String - */ - fun getName(): String = getNameComponent().unformattedText - - /** - * Gets the name of the entity, could be "Villager", - * or, if the entity has a custom name, it returns that. - * - * @return the (custom) name of the entity as a [TextComponent] - */ - fun getNameComponent(): TextComponent = TextComponent(mcValue.name) - - /** - * Gets the Java class name of the entity, for example "EntityVillager" - * - * @return the entity's class name - */ - fun getClassName(): String = mcValue.javaClass.simpleName - - /** - * Gets the Java UUID object of this entity. - * Use of [UUID.toString] in conjunction is recommended. - * - * @return the entity's uuid - */ - fun getUUID(): UUID = mcValue.uuid - - /** - * Gets the entity's air level. - * - * The returned value will be an integer. If the player is not taking damage, it - * will be between 300 (not in water) and 0. If the player is taking damage, it - * will be between -20 and 0, getting reset to 0 every time the player takes damage. - * - * @return the entity's air level - */ - fun getAir(): Int = mcValue.air - - fun distanceTo(other: Entity): Float = distanceTo(other.mcValue) - - fun distanceTo(other: MCEntity): Float = mcValue.distanceTo(other) - - fun distanceTo(blockPos: BlockPos): Double = distanceTo( - blockPos.x.toDouble(), blockPos.y.toDouble(), blockPos.z.toDouble(), - ) - - fun distanceTo(x: Double, y: Double, z: Double): Double = sqrt(mcValue.squaredDistanceTo(x, y, z)) - - fun isOnGround() = mcValue.isOnGround - - fun isCollided() = World.toMC()?.getOtherEntities(mcValue, mcValue.boundingBox)?.isNotEmpty() ?: false - - fun getDistanceWalked() = mcValue.distanceTraveled / 0.6f - - fun getStepHeight() = mcValue.stepHeight - - fun hasNoClip() = mcValue.noClip - - fun getTicksExisted() = mcValue.age - - fun getFireResistance() = mcValue.fireTicks - - fun isImmuneToFire() = mcValue.isFireImmune - - fun isInWater() = mcValue.isTouchingWater - - fun isWet() = mcValue.isWet - - fun getDimension() = mcValue.world.dimensionEntry.key.let { key -> - DimensionType.entries.first { it.toMC() == key } - } - - fun getMaxInPortalTime() = mcValue.portalCooldown - - fun isSilent() = mcValue.isSilent - - fun isInLava() = mcValue.isInLava - - @JvmOverloads - fun getLookVector(partialTicks: Float = Renderer.partialTicks) = mcValue.getRotationVec(partialTicks) - - @JvmOverloads - fun getEyePosition(partialTicks: Float = Renderer.partialTicks) = mcValue.eyePos - - fun canBeCollidedWith() = mcValue.isCollidable - - fun canBePushed() = mcValue.isPushable - - fun isSneaking() = mcValue.isSneaking - - fun isSprinting() = mcValue.isSprinting - - fun isInvisible() = mcValue.isInvisible - - fun isOutsideBorder() = World.toMC()?.worldBorder?.contains(mcValue.blockPos) ?: false - - fun isBurning(): Boolean = mcValue.isOnFire - - fun getWorld() = mcValue.entityWorld - - fun getChunk(): Chunk = Chunk(getWorld().getWorldChunk(mcValue.blockPos)) - - override fun toString(): String { - val coordStrings = listOf(getX(), getY(), getZ()).map { "%.3f".format(it) } - return "${this::class.simpleName}(name=${getName()}, pos=[${coordStrings.joinToString()}])" - } - - enum class DimensionType( - override val mcValue: RegistryKey, - ) : CTWrapper> { - OVERWORLD(DimensionTypes.OVERWORLD), - NETHER(DimensionTypes.THE_NETHER), - END(DimensionTypes.THE_END), - OVERWORLD_CAVES(DimensionTypes.OVERWORLD_CAVES), - } - - companion object { - @JvmStatic - fun fromMC(entity: MCEntity): Entity = when (entity) { - is PlayerEntity -> PlayerMP(entity) - is MCLivingEntity -> LivingEntity(entity) - else -> Entity(entity) - } - } -} diff --git a/src/main/kotlin/com/chattriggers/ctjs/api/entity/LivingEntity.kt b/src/main/kotlin/com/chattriggers/ctjs/api/entity/LivingEntity.kt deleted file mode 100644 index 55dcb718..00000000 --- a/src/main/kotlin/com/chattriggers/ctjs/api/entity/LivingEntity.kt +++ /dev/null @@ -1,46 +0,0 @@ -package com.chattriggers.ctjs.api.entity - -import com.chattriggers.ctjs.api.inventory.Item -import com.chattriggers.ctjs.api.world.PotionEffect -import com.chattriggers.ctjs.api.world.PotionEffectType -import com.chattriggers.ctjs.MCEntity -import com.chattriggers.ctjs.MCLivingEntity -import net.minecraft.entity.EquipmentSlot -import net.minecraft.registry.Registries - -open class LivingEntity(override val mcValue: MCLivingEntity) : Entity(mcValue) { - fun getActivePotionEffects(): List { - return mcValue.statusEffects.map(::PotionEffect) - } - - fun canSeeEntity(other: MCEntity) = mcValue.canSee(other) - - fun canSeeEntity(other: Entity) = canSeeEntity(other.toMC()) - - /** - * Gets the item currently in the entity's specified inventory slot. - * 0 for main hand, 1 for offhand, 2-5 for armor - * - * @param slot the slot to access - * @return the item in said slot - */ - fun getStackInSlot(slot: Int): Item? { - return mcValue.getEquippedStack(EquipmentSlot.entries[slot])?.let(Item::fromMC) - } - - fun getHP() = mcValue.health - - fun getMaxHP() = mcValue.maxHealth - - fun getAbsorption() = mcValue.absorptionAmount - - fun getAge() = mcValue.age - - fun getArmorValue() = mcValue.armor - - fun isPotionActive(id: Int) = mcValue.hasStatusEffect(Registries.STATUS_EFFECT.getEntry(id).get()) - - fun isPotionActive(type: PotionEffectType) = mcValue.hasStatusEffect(Registries.STATUS_EFFECT.getEntry(type.type)) - - fun isPotionActive(effect: PotionEffect) = isPotionActive(effect.type) -} diff --git a/src/main/kotlin/com/chattriggers/ctjs/api/entity/Particle.kt b/src/main/kotlin/com/chattriggers/ctjs/api/entity/Particle.kt deleted file mode 100644 index 1b6cfd36..00000000 --- a/src/main/kotlin/com/chattriggers/ctjs/api/entity/Particle.kt +++ /dev/null @@ -1,104 +0,0 @@ -package com.chattriggers.ctjs.api.entity - -import com.chattriggers.ctjs.api.CTWrapper -import com.chattriggers.ctjs.api.render.Renderer -import com.chattriggers.ctjs.internal.mixins.ParticleAccessor -import com.chattriggers.ctjs.MCParticle -import com.chattriggers.ctjs.internal.utils.asMixin -import java.awt.Color - -class Particle(override val mcValue: MCParticle) : CTWrapper { - private val mixed: ParticleAccessor = mcValue.asMixin() - - var x by mixed::x - var y by mixed::y - var z by mixed::z - - var lastX by mixed::prevPosX - var lastY by mixed::prevPosY - var lastZ by mixed::prevPosZ - - val renderX get() = lastX + (x - lastX) * Renderer.partialTicks - val renderY get() = lastY + (y - lastY) * Renderer.partialTicks - val renderZ get() = lastZ + (z - lastZ) * Renderer.partialTicks - - var motionX by mixed::velocityX - var motionY by mixed::velocityY - var motionZ by mixed::velocityZ - - var red by mixed::red - var green by mixed::green - var blue by mixed::blue - var alpha by mixed::alpha - - var age by mixed::age - var dead by mixed::dead - - fun scale(scale: Float) = apply { - mcValue.scale(scale) - } - - /** - * Sets the color of the particle. - * @param red the red value between 0 and 1. - * @param green the green value between 0 and 1. - * @param blue the blue value between 0 and 1. - */ - fun setColor(red: Float, green: Float, blue: Float) = apply { - mcValue.setColor(red, green, blue) - } - - /** - * Sets the color of the particle. - * @param red the red value between 0 and 1. - * @param green the green value between 0 and 1. - * @param blue the blue value between 0 and 1. - * @param alpha the alpha value between 0 and 1. - */ - fun setColor(red: Float, green: Float, blue: Float, alpha: Float) = apply { - setColor(red, green, blue) - setAlpha(alpha) - } - - fun setColor(color: Long) = apply { - val red = (color shr 16 and 255).toFloat() / 255.0f - val blue = (color shr 8 and 255).toFloat() / 255.0f - val green = (color and 255).toFloat() / 255.0f - val alpha = (color shr 24 and 255).toFloat() / 255.0f - - setColor(red, green, blue, alpha) - } - - /** - * Sets the alpha of the particle. - * @param alpha the alpha value between 0 and 1. - */ - fun setAlpha(alpha: Float) = apply { - mixed.alpha = alpha - } - - /** - * Returns the color of the Particle - * - * @return A [Color] with the R, G, B and A values - */ - fun getColor() = Color(red, green, blue, alpha) - - fun setColor(color: Color) = setColor(color.rgb.toLong()) - - /** - * Sets the amount of ticks this particle will live for - * - * @param maxAge the particle's max age (in ticks) - */ - fun setMaxAge(maxAge: Int) = apply { - mcValue.maxAge = maxAge - } - - fun remove() = apply { - mcValue.markDead() - } - - override fun toString() = - "Particle(type=${mcValue.javaClass.simpleName}, pos=($x, $y, $z), color=[$red, $green, $blue, $alpha], age=$age)" -} diff --git a/src/main/kotlin/com/chattriggers/ctjs/api/entity/PlayerInteraction.kt b/src/main/kotlin/com/chattriggers/ctjs/api/entity/PlayerInteraction.kt deleted file mode 100644 index 50011068..00000000 --- a/src/main/kotlin/com/chattriggers/ctjs/api/entity/PlayerInteraction.kt +++ /dev/null @@ -1,14 +0,0 @@ -package com.chattriggers.ctjs.api.entity - -import net.minecraft.util.Hand - -sealed class PlayerInteraction(val name: String, val mainHand: Boolean) { - object AttackBlock : PlayerInteraction("AttackBlock", true) - object AttackEntity : PlayerInteraction("AttackEntity", true) - object BreakBlock : PlayerInteraction("BreakBlock", true) - class UseBlock(hand: Hand) : PlayerInteraction("UseBlock", hand == Hand.MAIN_HAND) - class UseEntity(hand: Hand) : PlayerInteraction("UseEntity", hand == Hand.MAIN_HAND) - class UseItem(hand: Hand) : PlayerInteraction("UseItem", hand == Hand.MAIN_HAND) - - override fun toString(): String = name -} diff --git a/src/main/kotlin/com/chattriggers/ctjs/api/entity/PlayerMP.kt b/src/main/kotlin/com/chattriggers/ctjs/api/entity/PlayerMP.kt deleted file mode 100644 index b395ac8b..00000000 --- a/src/main/kotlin/com/chattriggers/ctjs/api/entity/PlayerMP.kt +++ /dev/null @@ -1,68 +0,0 @@ -package com.chattriggers.ctjs.api.entity - -import com.chattriggers.ctjs.api.client.Client -import com.chattriggers.ctjs.api.message.TextComponent -import com.chattriggers.ctjs.api.render.Renderer -import com.chattriggers.ctjs.internal.NameTagOverridable -import com.chattriggers.ctjs.MCTeam -import com.chattriggers.ctjs.internal.utils.asMixin -import net.minecraft.client.network.PlayerListEntry -import net.minecraft.entity.player.PlayerEntity -import net.minecraft.text.Text -import org.mozilla.javascript.NativeObject - -class PlayerMP(override val mcValue: PlayerEntity) : LivingEntity(mcValue) { - fun isSpectator() = mcValue.isSpectator - - fun getPing(): Int { - return getPlayerInfo()?.latency ?: -1 - } - - fun getTeam(): Team? { - return getPlayerInfo()?.scoreboardTeam?.let(::Team) - } - - /** - * Gets the display name for this player, - * i.e. the name shown in tab list and in the player's nametag. - * @return the display name - */ - fun getDisplayName() = getPlayerName(getPlayerInfo()) - - fun setTabDisplayName(textComponent: TextComponent) { - getPlayerInfo()?.displayName = textComponent - } - - /** - * Sets the name for this player shown above their head, - * in their name tag - * - * @param textComponent the new name to display - */ - fun setNametagName(textComponent: TextComponent) { - mcValue.asMixin().ctjs_setOverriddenNametagName(textComponent) - } - - /** - * Draws the player in the GUI. Takes the same parameters as [Renderer.drawPlayer] - * minus `player`. - * - * @see Renderer.drawPlayer - */ - fun draw(obj: NativeObject) = apply { - obj["player"] = this - Renderer.drawPlayer(obj) - } - - private fun getPlayerName(playerListEntry: PlayerListEntry?): TextComponent { - return playerListEntry?.displayName?.let { TextComponent(it) } - ?: TextComponent( - MCTeam.decorateName( - playerListEntry?.scoreboardTeam, - Text.of(playerListEntry?.profile?.name) - ) - ) - } - - private fun getPlayerInfo() = Client.getConnection()?.getPlayerListEntry(mcValue.uuid) -} diff --git a/src/main/kotlin/com/chattriggers/ctjs/api/entity/Team.kt b/src/main/kotlin/com/chattriggers/ctjs/api/entity/Team.kt deleted file mode 100644 index 76f04cd7..00000000 --- a/src/main/kotlin/com/chattriggers/ctjs/api/entity/Team.kt +++ /dev/null @@ -1,134 +0,0 @@ -package com.chattriggers.ctjs.api.entity - -import com.chattriggers.ctjs.api.CTWrapper -import com.chattriggers.ctjs.api.message.TextComponent -import com.chattriggers.ctjs.MCTeam -import com.chattriggers.ctjs.api.message.ChatLib -import net.minecraft.scoreboard.AbstractTeam -import net.minecraft.text.TextColor -import net.minecraft.util.Formatting - -class Team(override val mcValue: MCTeam) : CTWrapper { - /** - * Gets the registered name of the team - */ - fun getRegisteredName(): String = mcValue.name - - /** - * Gets the display name of the team - */ - fun getName() = TextComponent(mcValue.displayName).formattedText - - /** - * Sets the display name of the team - * @param name the new display name - * @return the team for method chaining - */ - fun setName(name: TextComponent) = apply { - mcValue.displayName = name - } - - /** - * Sets the display name of the team - * @param name the new display name - * @return the team for method chaining - */ - fun setName(name: String) = setName(TextComponent(name)) - - /** - * Gets the list of names on the team - */ - fun getMembers(): List = mcValue.playerList.toList() - - /** - * Gets the team prefix - */ - fun getPrefix() = TextComponent(mcValue.prefix).formattedText - - /** - * Sets the team prefix - * @param prefix the prefix to set - * @return the team for method chaining - */ - fun setPrefix(prefix: TextComponent) = apply { - mcValue.prefix = prefix - } - - /** - * Sets the team prefix - * @param prefix the prefix to set - * @return the team for method chaining - */ - fun setPrefix(prefix: String) = setPrefix(TextComponent(prefix)) - - /** - * Gets the team suffix - */ - fun getSuffix() = TextComponent(mcValue.suffix).formattedText - - /** - * Sets the team suffix - * @param suffix the suffix to set - * @return the team for method chaining - */ - fun setSuffix(suffix: TextComponent) = apply { - mcValue.suffix = suffix - } - - /** - * Sets the team suffix - * @param suffix the suffix to set - * @return the team for method chaining - */ - fun setSuffix(suffix: String) = setSuffix(TextComponent(suffix)) - - fun getColor() = mcValue.color.toString() - - /** - * Sets the team color - * @param color a string format of a [Formatting], or a hex value - * @return the team for method chaining - */ - fun setColor(color: Any?) = apply { - mcValue.color = when (color) { - is Number -> Formatting.byColorIndex(color.toInt()) - is CharSequence -> Formatting.entries.find { - it.toString() == ChatLib.addColor(color.toString()) - } ?: Formatting.RESET - null -> Formatting.RESET - else -> throw IllegalArgumentException("Could not convert type ${color::class.simpleName} to a Formatting") - } - } - - /** - * Gets the team's friendly fire setting - */ - fun getFriendlyFire(): Boolean = mcValue.isFriendlyFireAllowed - - /** - * Gets whether the team can see invisible players on the same team - */ - fun canSeeInvisibleTeammates(): Boolean = mcValue.shouldShowFriendlyInvisibles() - - /** - * Gets the team's name tag visibility - */ - fun getNameTagVisibility() = Visibility.fromMC(mcValue.nameTagVisibilityRule) - - /** - * Gets the team's death message visibility - */ - fun getDeathMessageVisibility() = Visibility.fromMC(mcValue.deathMessageVisibilityRule) - - enum class Visibility(override val mcValue: AbstractTeam.VisibilityRule) : CTWrapper { - ALWAYS(AbstractTeam.VisibilityRule.ALWAYS), - NEVER(AbstractTeam.VisibilityRule.NEVER), - HIDE_FOR_OTHERS_TEAMS(AbstractTeam.VisibilityRule.HIDE_FOR_OTHER_TEAMS), - HIDE_FOR_OWN_TEAM(AbstractTeam.VisibilityRule.HIDE_FOR_OWN_TEAM); - - companion object { - @JvmStatic - fun fromMC(mcValue: AbstractTeam.VisibilityRule) = entries.first { it.mcValue == mcValue } - } - } -} diff --git a/src/main/kotlin/com/chattriggers/ctjs/api/inventory/Inventory.kt b/src/main/kotlin/com/chattriggers/ctjs/api/inventory/Inventory.kt deleted file mode 100644 index c1150e7b..00000000 --- a/src/main/kotlin/com/chattriggers/ctjs/api/inventory/Inventory.kt +++ /dev/null @@ -1,178 +0,0 @@ -package com.chattriggers.ctjs.api.inventory - -import com.chattriggers.ctjs.api.inventory.action.ClickAction -import com.chattriggers.ctjs.api.inventory.action.DragAction -import com.chattriggers.ctjs.api.inventory.action.DropAction -import com.chattriggers.ctjs.api.message.TextComponent -import com.chattriggers.ctjs.MCInventory -import net.minecraft.client.gui.screen.ingame.HandledScreen -import net.minecraft.util.Nameable - -class Inventory { - val inventory: MCInventory? - val screen: HandledScreen<*>? - - constructor(inventory: MCInventory) { - this.inventory = inventory - this.screen = null - } - - constructor(container: HandledScreen<*>) { - this.inventory = null - this.screen = container - } - - /** - * Gets the total size of the Inventory. - * The player's inventory size is 36, 27 for the main inventory, plus 9 for the hotbar. - * A single chest's size would be 63, because it also counts the player's inventory. - * - * @return the size of the Inventory - */ - val size: Int get() = inventory?.size() ?: screen!!.screenHandler.slots.size - - /** - * Gets the item in any slot, starting from 0. - * - * @param slot the slot index - * @return the [Item] in that slot, or null if there is no item - */ - fun getStackInSlot(slot: Int): Item? { - val stack = inventory?.getStack(slot) - ?: screen!!.screenHandler.getSlot(slot).stack - - return stack?.let(Item::fromMC) - } - - /** - * Returns the window identifier number of this Inventory. - * This Inventory must be backed by a HandledScreen [isScreen] - * - * @return the window id - */ - fun getWindowId(): Int = screen?.screenHandler?.syncId ?: -1 - - /** - * Checks if an item can be shift clicked into a certain slot, i.e. coal into the bottom of a furnace. - * - * @param slot the slot index - * @param item the item for checking - * @return whether it can be shift clicked in - */ - fun isItemValidForSlot(slot: Int, item: Item) = inventory?.isValid(slot, item.mcValue) ?: true - - /** - * @return a list of the [Item]s in an inventory - */ - fun getItems() = (0 until size).map(::getStackInSlot) - - /** - * Checks whether the inventory contains the given item. - * - * @param item the item to check for - * @return whether the inventory contains the item - */ - fun contains(item: Item) = getItems().contains(item) - - /** - * Checks whether the inventory contains an item with ID. - * - * @param id the ID of the item to match - * @return whether the inventory contains an item with ID - */ - fun contains(id: Int) = getItems().any { it?.type?.getId() == id } - - /** - * Gets the index of any item in the inventory, and returns the slot number. - * Returns -1 if the inventory does not contain the item. - * - * @param item the item to check for - * @return the index of the given item - */ - fun indexOf(item: Item) = getItems().indexOf(item) - - /** - * Gets the index of any item in the inventory with matching ID, and returns the slot number. - * Returns -1 if the inventory does not contain the item. - * - * @param id the item ID to check for - * @return the index of the given item with ID - */ - fun indexOf(id: Int) = getItems().indexOfFirst { it?.type?.getId() == id } - - /** - * Returns true if this Inventory wraps a [HandledScreen] object - * rather than an [MCInventory] object - * - * @return if this is a container - */ - fun isScreen(): Boolean = screen != null - - /** - * Shorthand for [ClickAction] - * - * @param slot the slot to click on - * @param button the mouse button to use. "LEFT" by default. - * @param shift whether shift is being held. False by default - * @return this inventory for method chaining - */ - @JvmOverloads - fun click(slot: Int, shift: Boolean = false, button: String = "LEFT") = apply { - ClickAction(slot, getWindowId()) - .setClickString(button) - .setHoldingShift(shift) - .complete() - } - - /** - * Shorthand for [DropAction] - * - * @param slot the slot to drop - * @param ctrl whether control should be held (drops whole stack) - * @return this inventory for method chaining - */ - fun drop(slot: Int, ctrl: Boolean) = apply { - DropAction(slot, getWindowId()) - .setHoldingCtrl(ctrl) - .complete() - } - - /** - * Shorthand for [DragAction] - * - * @param type what click type this should be: LEFT, MIDDLE, RIGHT - * @param slots all of the slots to drag onto - * @return this inventory for method chaining - */ - fun drag(type: String, vararg slots: Int) = apply { - DragAction(-999, getWindowId()).run { - setStage(DragAction.Stage.BEGIN) - .setClickType(DragAction.ClickType.valueOf(type.uppercase())) - .complete() - - setStage(DragAction.Stage.SLOT) - slots.forEach { setSlot(it).complete() } - - setStage(DragAction.Stage.END) - .setSlot(-999) - .complete() - } - } - - /** - * Gets the name of the inventory, simply "container" for most chest-like blocks. - * - * @return the name of the inventory - */ - fun getName(): TextComponent { - return when { - inventory is Nameable -> TextComponent(inventory.name) - inventory != null -> TextComponent("inventory") - else -> TextComponent(screen!!.title) - } - } - - fun getClassName(): String = inventory?.javaClass?.simpleName ?: screen!!.javaClass.simpleName - - override fun toString(): String = "Inventory(name=${getName()}, size=$size, isScreen=${isScreen()})" -} diff --git a/src/main/kotlin/com/chattriggers/ctjs/api/inventory/Item.kt b/src/main/kotlin/com/chattriggers/ctjs/api/inventory/Item.kt deleted file mode 100644 index 99d9349c..00000000 --- a/src/main/kotlin/com/chattriggers/ctjs/api/inventory/Item.kt +++ /dev/null @@ -1,184 +0,0 @@ -package com.chattriggers.ctjs.api.inventory - -import com.chattriggers.ctjs.api.CTWrapper -import com.chattriggers.ctjs.api.client.Client -import com.chattriggers.ctjs.api.client.Player -import com.chattriggers.ctjs.api.entity.Entity -import com.chattriggers.ctjs.api.inventory.nbt.NBTTagCompound -import com.chattriggers.ctjs.api.message.TextComponent -import com.chattriggers.ctjs.api.render.Renderer -import com.chattriggers.ctjs.api.world.World -import com.chattriggers.ctjs.api.world.block.Block -import com.chattriggers.ctjs.api.world.block.BlockPos -import com.chattriggers.ctjs.internal.Skippable -import com.chattriggers.ctjs.internal.TooltipOverridable -import com.chattriggers.ctjs.MCNbtCompound -import com.chattriggers.ctjs.internal.utils.asMixin -import net.minecraft.block.pattern.CachedBlockPosition -import net.minecraft.client.render.DiffuseLighting -import net.minecraft.client.render.OverlayTexture -import net.minecraft.client.render.model.json.ModelTransformationMode -import net.minecraft.component.DataComponentTypes -import net.minecraft.enchantment.EnchantmentHelper -import net.minecraft.item.Item.TooltipContext -import net.minecraft.item.ItemStack -import net.minecraft.item.tooltip.TooltipType -import net.minecraft.util.crash.CrashException -import net.minecraft.util.crash.CrashReport -import kotlin.jvm.optionals.getOrNull - -class Item(override val mcValue: ItemStack) : CTWrapper { - val type: ItemType = ItemType(mcValue.item) - - init { - require(!mcValue.isEmpty) { - "Can not wrap empty ItemStack as an Item" - } - } - - constructor(type: ItemType) : this(type.toMC().defaultStack) - - fun getHolder(): Entity? = mcValue.holder?.let(Entity::fromMC) - - fun getStackSize(): Int = mcValue.count - - fun setStackSize(size: Int) = apply { - mcValue.count = size - } - - fun getEnchantments() = EnchantmentHelper.getEnchantments(mcValue).enchantments.associate { - it.key.getOrNull() to EnchantmentHelper.getLevel(it, mcValue) - } - - fun isEnchantable() = mcValue.isEnchantable - - fun isEnchanted() = mcValue.hasEnchantments() - - fun canPlaceOn(pos: BlockPos) = - mcValue.canPlaceOn(CachedBlockPosition(World.toMC(), pos.toMC(), false)) - - fun canPlaceOn(block: Block) = canPlaceOn(block.pos) - - fun canHarvest(pos: BlockPos) = - mcValue.canBreak(CachedBlockPosition(World.toMC(), pos.toMC(), false)) - - fun canHarvest(block: Block) = canHarvest(block.pos) - - fun getDurability() = getMaxDamage() - getDamage() - - fun getMaxDamage() = mcValue.maxDamage - - fun getDamage() = mcValue.damage - - fun isDamageable() = mcValue.isDamageable - - fun getName(): String = TextComponent(mcValue.name).formattedText - - fun setName(name: TextComponent?) = apply { - mcValue.set(DataComponentTypes.CUSTOM_NAME, name) - } - - fun resetName() { - setName(null) - } - - @JvmOverloads - fun getLore(advanced: Boolean = false): List { - mcValue.asMixin().ctjs_setShouldSkip(true) - val tooltip = mcValue.getTooltip( - TooltipContext.DEFAULT, - Player.toMC(), - if (advanced) TooltipType.ADVANCED else TooltipType.BASIC, - ).mapTo(mutableListOf()) { TextComponent(it) } - - mcValue.asMixin().ctjs_setShouldSkip(false) - - return tooltip - } - - fun setLore(lore: List) { - mcValue.asMixin().apply { - ctjs_setTooltip(lore) - ctjs_setShouldOverrideTooltip(true) - } - } - - fun resetLore() { - mcValue.asMixin().ctjs_setShouldOverrideTooltip(false) - } - - // TODO: make a component wrapper? - fun getNBT() = mcValue.components - - /** - * Renders the item icon to the client's overlay, with customizable overlay information. - * - * @param x the x location - * @param y the y location - * @param scale the scale - * @param z the z level to draw the item at - */ - @JvmOverloads - fun draw(x: Float = 0f, y: Float = 0f, scale: Float = 1f, z: Float = 200f) { - val itemRenderer = Client.getMinecraft().itemRenderer - - Renderer.pushMatrix() - .scale(scale, scale, 1f) - .translate(x / scale, y / scale, z) - - // The item draw method moved to DrawContext in 1.20, which we don't have access - // to here, so its drawItem method has been copy-pasted here instead - if (mcValue.isEmpty) - return - val bakedModel = itemRenderer.getModel(mcValue, World.toMC(), null, 0) - Renderer.pushMatrix() - Renderer.translate(x + 8, y + 8, (150f + if (bakedModel.hasDepth()) z else 0f)) - try { - Renderer.scale(1.0f, -1.0f, 1.0f) - Renderer.scale(16.0f, 16.0f, 16.0f) - if (!bakedModel.isSideLit) - DiffuseLighting.disableGuiDepthLighting() - val vertexConsumers = Client.getMinecraft().bufferBuilders.entityVertexConsumers - itemRenderer.renderItem( - mcValue, - ModelTransformationMode.GUI, - false, - Renderer.matrixStack.toMC(), - vertexConsumers, - 0xF000F0, - OverlayTexture.DEFAULT_UV, - bakedModel, - ) - Renderer.disableDepth() - vertexConsumers.draw() - Renderer.enableDepth() - if (!bakedModel.isSideLit) { - DiffuseLighting.enableGuiDepthLighting() - } - } catch (e: Throwable) { - val crashReport = CrashReport.create(e, "Rendering item") - val crashReportSection = crashReport.addElement("Item being rendered") - crashReportSection.add("Item Type") { mcValue.item.toString() } - crashReportSection.add("Item Damage") { mcValue.damage.toString() } - crashReportSection.add("Item Components") { mcValue.components.toString() } - crashReportSection.add("Item Foil") { mcValue.hasGlint().toString() } - throw CrashException(crashReport) - } finally { - Renderer.popMatrix() - Renderer.popMatrix() - } - } - - override fun toString(): String = "Item{name=${getName()}, type=${type.getRegistryName()}, size=${getStackSize()}}" - - companion object { - @JvmStatic - fun fromMC(mcValue: ItemStack): Item? { - return if (mcValue.isEmpty) { - null - } else { - Item(mcValue) - } - } - } -} diff --git a/src/main/kotlin/com/chattriggers/ctjs/api/inventory/ItemType.kt b/src/main/kotlin/com/chattriggers/ctjs/api/inventory/ItemType.kt deleted file mode 100644 index 4745d123..00000000 --- a/src/main/kotlin/com/chattriggers/ctjs/api/inventory/ItemType.kt +++ /dev/null @@ -1,46 +0,0 @@ -package com.chattriggers.ctjs.api.inventory - -import com.chattriggers.ctjs.api.CTWrapper -import com.chattriggers.ctjs.api.message.TextComponent -import com.chattriggers.ctjs.api.world.block.BlockType -import com.chattriggers.ctjs.MCItem -import com.chattriggers.ctjs.internal.utils.toIdentifier -import net.minecraft.item.Items -import net.minecraft.registry.Registries - -class ItemType(override val mcValue: MCItem) : CTWrapper { - init { - require(mcValue !== Items.AIR) { - "Can not wrap air as an ItemType" - } - } - - constructor(itemName: String) : this(Registries.ITEM[itemName.toIdentifier()]) - - constructor(id: Int) : this(Registries.ITEM[id]) - - constructor(blockType: BlockType) : this(blockType.toMC().asItem()) - - fun getName(): String = getNameComponent().formattedText - - fun getNameComponent(): TextComponent = TextComponent(mcValue.name) - - fun getId(): Int = MCItem.getRawId(mcValue) - - fun getTranslationKey(): String = mcValue.translationKey - - fun getRegistryName(): String = Registries.ITEM.getId(mcValue).toString() - - fun asItem(): Item = Item(this) - - companion object { - @JvmStatic - fun fromMC(mcValue: MCItem): ItemType? { - return if (mcValue === Items.AIR) { - null - } else { - ItemType(mcValue) - } - } - } -} diff --git a/src/main/kotlin/com/chattriggers/ctjs/api/inventory/Slot.kt b/src/main/kotlin/com/chattriggers/ctjs/api/inventory/Slot.kt deleted file mode 100644 index 834feb72..00000000 --- a/src/main/kotlin/com/chattriggers/ctjs/api/inventory/Slot.kt +++ /dev/null @@ -1,20 +0,0 @@ -package com.chattriggers.ctjs.api.inventory - -import com.chattriggers.ctjs.api.CTWrapper -import com.chattriggers.ctjs.MCSlot - -class Slot(override val mcValue: MCSlot) : CTWrapper { - val index by mcValue::index - - val displayX by mcValue::x - - val displayY by mcValue::y - - val inventory get() = Inventory(mcValue.inventory) - - val item get(): Item? = Item.fromMC(mcValue.stack) - - val isEnabled get() = mcValue.isEnabled - - override fun toString() = "Slot(inventory=$inventory, index=$index, item=$item)" -} diff --git a/src/main/kotlin/com/chattriggers/ctjs/api/inventory/action/Action.kt b/src/main/kotlin/com/chattriggers/ctjs/api/inventory/action/Action.kt deleted file mode 100644 index d19e284a..00000000 --- a/src/main/kotlin/com/chattriggers/ctjs/api/inventory/action/Action.kt +++ /dev/null @@ -1,53 +0,0 @@ -package com.chattriggers.ctjs.api.inventory.action - -import com.chattriggers.ctjs.api.client.Client -import com.chattriggers.ctjs.api.client.Player -import com.chattriggers.ctjs.api.inventory.Inventory -import net.minecraft.screen.slot.SlotActionType - -abstract class Action(var slot: Int, var windowId: Int) { - fun setSlot(slot: Int) = apply { - this.slot = slot - } - - fun setWindowId(windowId: Int) = apply { - this.windowId = windowId - } - - internal abstract fun complete() - - protected fun doClick(button: Int, mode: SlotActionType) { - Client.getMinecraft().interactionManager?.clickSlot( - windowId, - slot, - button, - mode, - Player.toMC(), - ) - } - - companion object { - /** - * Creates a new action. - * The Inventory must be a container, see [Inventory.isContainer]. - * The slot can be -999 for outside of the gui - * - * @param inventory the inventory to complete the action on - * @param slot the slot to complete the action on - * @param typeString the type of action to do (CLICK, DRAG, DROP, KEY) - * @return the new action - */ - @JvmStatic - fun of(inventory: Inventory, slot: Int, typeString: String) = - when (Type.valueOf(typeString.uppercase())) { - Type.CLICK -> ClickAction(slot, inventory.getWindowId()) - Type.DRAG -> DragAction(slot, inventory.getWindowId()) - Type.KEY -> KeyAction(slot, inventory.getWindowId()) - Type.DROP -> DropAction(slot, inventory.getWindowId()) - } - } - - enum class Type { - CLICK, DRAG, KEY, DROP - } -} diff --git a/src/main/kotlin/com/chattriggers/ctjs/api/inventory/action/ClickAction.kt b/src/main/kotlin/com/chattriggers/ctjs/api/inventory/action/ClickAction.kt deleted file mode 100644 index 4549fdc4..00000000 --- a/src/main/kotlin/com/chattriggers/ctjs/api/inventory/action/ClickAction.kt +++ /dev/null @@ -1,83 +0,0 @@ -package com.chattriggers.ctjs.api.inventory.action - -import com.chattriggers.ctjs.api.client.Player -import net.minecraft.screen.slot.SlotActionType - -class ClickAction(slot: Int, windowId: Int) : Action(slot, windowId) { - private lateinit var clickType: ClickType - private var holdingShift = false - private var itemInHand = Player.getHeldItem() != null - private var pickupAll = false - - fun getClickType(): ClickType = clickType - - /** - * The type of click (REQUIRED) - * - * @param clickType the new click type - */ - fun setClickType(clickType: ClickType) = apply { - this.clickType = clickType - } - - fun getHoldingShift(): Boolean = holdingShift - - /** - * Whether the click should act as if shift is being held (defaults to false) - * - * @param holdingShift to hold shift or not - */ - fun setHoldingShift(holdingShift: Boolean) = apply { - this.holdingShift = holdingShift - } - - fun getItemInHand(): Boolean = itemInHand - - /** - * Whether the click should act as if an item is being held - * (defaults to whether there actually is an item in the hand) - * - * @param itemInHand to be holding an item or not - */ - fun setItemInHand(itemInHand: Boolean) = apply { - this.itemInHand = itemInHand - } - - fun getPickupAll() = pickupAll - - /** - * Whether the click should try to pick up all items of said type in the inventory (essentially double clicking) - * (defaults to whether there actually is an item in the hand) - * - * @param pickupAll to pick up all items of the same type - */ - fun setPickupAll(pickupAll: Boolean) = apply { - this.pickupAll = pickupAll - } - - /** - * Sets the type of click. - * Possible values are: LEFT, RIGHT, MIDDLE - * - * @param clickType the click type - * @return the current Action for method chaining - */ - fun setClickString(clickType: String) = apply { - this.clickType = ClickType.valueOf(clickType.uppercase()) - } - - override fun complete() { - val mode = when { - clickType == ClickType.MIDDLE -> SlotActionType.CLONE - holdingShift -> SlotActionType.QUICK_MOVE - pickupAll -> SlotActionType.PICKUP_ALL - else -> SlotActionType.PICKUP - } - - doClick(clickType.button, mode) - } - - enum class ClickType(val button: Int) { - LEFT(0), RIGHT(1), MIDDLE(2) - } -} diff --git a/src/main/kotlin/com/chattriggers/ctjs/api/inventory/action/DragAction.kt b/src/main/kotlin/com/chattriggers/ctjs/api/inventory/action/DragAction.kt deleted file mode 100644 index 9fe77b05..00000000 --- a/src/main/kotlin/com/chattriggers/ctjs/api/inventory/action/DragAction.kt +++ /dev/null @@ -1,74 +0,0 @@ -package com.chattriggers.ctjs.api.inventory.action - -import net.minecraft.screen.slot.SlotActionType - -class DragAction(slot: Int, windowId: Int) : Action(slot, windowId) { - private lateinit var clickType: ClickType - private lateinit var stage: Stage - - fun getClickType(): ClickType = clickType - - /** - * The type of click (REQUIRED) - * - * @param clickType the new click type - */ - fun setClickType(clickType: ClickType) = apply { - this.clickType = clickType - } - - fun getStage(): Stage = stage - - /** - * The stage of this drag (REQUIRED) - * BEGIN is when beginning the drag - * SLOT is for each slot being dragged into - * END is for ending the drag - * - * @param stage the stage - */ - fun setStage(stage: Stage) = apply { - this.stage = stage - } - - /** - * Sets the type of click. - * Possible values are: LEFT, RIGHT, MIDDLE - * - * @param clickType the click type - * @return the current Action for method chaining - */ - fun setClickString(clickType: String) = apply { - this.clickType = ClickType.valueOf(clickType.uppercase()) - } - - /** - * Sets the stage of this drag. - * Possible values are: BEGIN, SLOT, END [stage] - * - * @param stage the stage - * @return the current Action for method chaining - */ - fun setStageString(stage: String) = apply { - this.stage = Stage.valueOf(stage.uppercase()) - } - - override fun complete() { - val button = stage.stage and 3 or (clickType.button and 3) shl 2 - - if (stage != Stage.SLOT) { - slot = -999 - println("Enforcing slot of -999") - } - - doClick(button, SlotActionType.QUICK_CRAFT) - } - - enum class ClickType(val button: Int) { - LEFT(0), RIGHT(1), MIDDLE(2) - } - - enum class Stage(val stage: Int) { - BEGIN(0), SLOT(1), END(2) - } -} diff --git a/src/main/kotlin/com/chattriggers/ctjs/api/inventory/action/DropAction.kt b/src/main/kotlin/com/chattriggers/ctjs/api/inventory/action/DropAction.kt deleted file mode 100644 index 769e0cb7..00000000 --- a/src/main/kotlin/com/chattriggers/ctjs/api/inventory/action/DropAction.kt +++ /dev/null @@ -1,22 +0,0 @@ -package com.chattriggers.ctjs.api.inventory.action - -import net.minecraft.screen.slot.SlotActionType - -class DropAction(slot: Int, windowId: Int) : Action(slot, windowId) { - private var holdingCtrl = false - - fun getHoldingCtrl(): Boolean = holdingCtrl - - /** - * Whether the click should act as if control is being held (defaults to false) - * - * @param holdingCtrl to hold ctrl or not - */ - fun setHoldingCtrl(holdingCtrl: Boolean) = apply { - this.holdingCtrl = holdingCtrl - } - - override fun complete() { - doClick(if (holdingCtrl) 1 else 0, SlotActionType.THROW) - } -} diff --git a/src/main/kotlin/com/chattriggers/ctjs/api/inventory/action/KeyAction.kt b/src/main/kotlin/com/chattriggers/ctjs/api/inventory/action/KeyAction.kt deleted file mode 100644 index d44205a4..00000000 --- a/src/main/kotlin/com/chattriggers/ctjs/api/inventory/action/KeyAction.kt +++ /dev/null @@ -1,23 +0,0 @@ -package com.chattriggers.ctjs.api.inventory.action - -import net.minecraft.screen.slot.SlotActionType - -class KeyAction(slot: Int, windowId: Int) : Action(slot, windowId) { - private var key: Int = -1 - - fun getKey(): Int = key - - /** - * Which key to act as if has been clicked (REQUIRED). - * Options currently are 0-8, representing the hotbar keys - * - * @param key which key to "click" - */ - fun setKey(key: Int) = apply { - this.key = key - } - - override fun complete() { - doClick(key, SlotActionType.SWAP) - } -} diff --git a/src/main/kotlin/com/chattriggers/ctjs/api/inventory/nbt/NBT.kt b/src/main/kotlin/com/chattriggers/ctjs/api/inventory/nbt/NBT.kt deleted file mode 100644 index ec236bc0..00000000 --- a/src/main/kotlin/com/chattriggers/ctjs/api/inventory/nbt/NBT.kt +++ /dev/null @@ -1,125 +0,0 @@ -package com.chattriggers.ctjs.api.inventory.nbt - -import com.chattriggers.ctjs.MCNbtBase -import com.chattriggers.ctjs.MCNbtCompound -import com.chattriggers.ctjs.MCNbtList -import com.chattriggers.ctjs.internal.utils.getOption -import net.minecraft.nbt.* -import org.mozilla.javascript.NativeArray -import org.mozilla.javascript.NativeObject - -object NBT { - /** - * Creates a new [NBTBase] from the given [nbt] - * - * @param nbt the value to convert to NBT - * @param options optional argument to allow refinement of the NBT data. - * Possible options include: - * - coerceNumericStrings: Boolean, default false. - * E.g. "10b" as a byte, "20s" as a short, "30f" as a float, "40d" as a double, - * "50l" as a long - * - preferArraysOverLists: Boolean, default false - * E.g. a list with all bytes or integers will be converted to an NBTTagByteArray or - * NBTTagIntArray accordingly - * - * @return [NBTTagCompound] if [nbt] is an object, [NBTTagList] if [nbt] - * is an array and preferArraysOverLists is false, or [NBTBase] otherwise. - */ - @JvmStatic - @JvmOverloads - fun parse(nbt: Any, options: NativeObject? = null): NBTBase { - return when (nbt) { - is NativeObject -> NBTTagCompound(nbt.toNBT(options) as MCNbtCompound) - is NativeArray -> { - nbt.toNBT(options).let { - if (it is MCNbtList) { - NBTTagList(it) - } else { - NBTBase(it) - } - } - } - else -> NBTBase(nbt.toNBT(options)) - } - } - - @JvmStatic - fun toObject(nbt: NBTTagCompound): NativeObject = nbt.toObject() - - @JvmStatic - fun toArray(nbt: NBTTagList): NativeArray = nbt.toArray() - - private fun Any.toNBT(options: NativeObject?): MCNbtBase { - val preferArraysOverLists = options.getOption("preferArraysOverLists", false).toBoolean() - val coerceNumericStrings = options.getOption("coerceNumericStrings", false).toBoolean() - - return when (this) { - is NativeObject -> MCNbtCompound().apply { - entries.forEach { entry -> - put(entry.key.toString(), entry.value.toNBT(options)) - } - } - is NativeArray -> { - val normalized = map { it?.toNBT(options) } - - if (!preferArraysOverLists || normalized.isEmpty()) { - return MCNbtList().apply { addAll(normalized) } - } - - return when { - (normalized.all { it is NbtByte }) -> { - NbtByteArray(normalized.map { (it as NbtByte).byteValue() }.toByteArray()) - } - - (normalized.all { it is NbtInt }) -> { - NbtIntArray(normalized.map { (it as NbtInt).intValue() }.toIntArray()) - } - - (normalized.all { it is NbtLong }) -> { - NbtLongArray(normalized.map { (it as NbtLong).longValue() }.toLongArray()) - } - - else -> MCNbtList().apply { addAll(normalized) } - } - } - is Boolean -> NbtByte.of(if (this) 1 else 0) - is CharSequence -> parseString(this.toString(), coerceNumericStrings) - is Byte -> NbtByte.of(this) - is Short -> NbtShort.of(this) - is Int -> NbtInt.of(this) - is Long -> NbtLong.of(this) - is Float -> NbtFloat.of(this) - is Double -> NbtDouble.of(this) - else -> throw IllegalArgumentException("Invalid NBT. Value provided: $this") - } - } - - private val numberNBTFormat = Regex("^([+-]?\\d+\\.?\\d*)([bslfd])?\$", RegexOption.IGNORE_CASE) - - private fun parseString(nbtData: String, coerceNumericStrings: Boolean): MCNbtBase { - if (!coerceNumericStrings) { - return NbtString.of(nbtData) - } - - val res = numberNBTFormat.matchEntire(nbtData)?.groupValues ?: return NbtString.of(nbtData) - - val number = res[1] - val suffix = res[2] - - return when (suffix.lowercase()) { - "" -> { - if (number.contains(".")) { - NbtDouble.of(number.toDouble()) - } else { - NbtInt.of(number.toInt()) - } - } - "b" -> NbtByte.of(number.toByte()) - "s" -> NbtShort.of(number.toShort()) - "l" -> NbtLong.of(number.toLong()) - "f" -> NbtFloat.of(number.toFloat()) - "d" -> NbtDouble.of(number.toDouble()) - else -> NbtString.of(nbtData) - } - } -} diff --git a/src/main/kotlin/com/chattriggers/ctjs/api/inventory/nbt/NBTBase.kt b/src/main/kotlin/com/chattriggers/ctjs/api/inventory/nbt/NBTBase.kt deleted file mode 100644 index 77b5b18d..00000000 --- a/src/main/kotlin/com/chattriggers/ctjs/api/inventory/nbt/NBTBase.kt +++ /dev/null @@ -1,99 +0,0 @@ -package com.chattriggers.ctjs.api.inventory.nbt - -import com.chattriggers.ctjs.api.CTWrapper -import com.chattriggers.ctjs.MCNbtBase -import com.chattriggers.ctjs.MCNbtCompound -import com.chattriggers.ctjs.MCNbtList -import net.minecraft.nbt.* -import org.mozilla.javascript.NativeArray -import org.mozilla.javascript.NativeObject - -open class NBTBase(override val mcValue: MCNbtBase) : CTWrapper { - /** - * Gets the type byte for the tag. - */ - val id: Byte - get() = mcValue.type - - /** - * Creates a clone of the tag. - */ - fun copy() = mcValue.copy() - - /** - * Return whether this compound has no tags. - */ - fun hasNoTags() = when (this) { - is NBTTagCompound -> tagMap.isEmpty() - is NBTTagList -> mcValue.isEmpty() - else -> false - } - - fun hasTags() = !hasNoTags() - - override fun equals(other: Any?) = mcValue == other - - override fun hashCode() = mcValue.hashCode() - - override fun toString() = mcValue.toString() - - companion object { - @JvmStatic - fun fromMC(nbt: MCNbtBase): NBTBase = when (nbt) { - is MCNbtCompound -> NBTTagCompound(nbt) - is MCNbtList -> NBTTagList(nbt) - else -> NBTBase(nbt) - } - - fun MCNbtBase.toObject(): Any? { - return when (this) { - is NbtString -> asString() - is NbtByte -> byteValue() - is NbtShort -> shortValue() - is NbtInt -> intValue() - is NbtLong -> longValue() - is NbtFloat -> floatValue() - is NbtDouble -> doubleValue() - is MCNbtCompound -> toObject() - is MCNbtList -> toObject() - is NbtByteArray -> NativeArray(byteArray.toTypedArray()).expose() - is NbtIntArray -> NativeArray(intArray.toTypedArray()).expose() - else -> error("Unknown tag type $javaClass") - } - } - - fun MCNbtCompound.toObject(): NativeObject { - val o = NativeObject() - o.expose() - - for (key in keys) { - val value = this[key] - if (value != null) { - o.put(key, o, value.toObject()) - } - } - - return o - } - - fun MCNbtList.toObject(): NativeArray { - val tags = mutableListOf() - for (i in 0 until count()) { - tags.add(get(i).toObject()) - } - val array = NativeArray(tags.toTypedArray()) - array.expose() - return array - } - - private fun NativeArray.expose() = apply { - // Taken from the private NativeArray#init method - exportAsJSClass(32, this, false) - } - - private fun NativeObject.expose() = apply { - // Taken from the private NativeObject#init method - exportAsJSClass(12, this, false) - } - } -} diff --git a/src/main/kotlin/com/chattriggers/ctjs/api/inventory/nbt/NBTTagCompound.kt b/src/main/kotlin/com/chattriggers/ctjs/api/inventory/nbt/NBTTagCompound.kt deleted file mode 100644 index 1a1b05b4..00000000 --- a/src/main/kotlin/com/chattriggers/ctjs/api/inventory/nbt/NBTTagCompound.kt +++ /dev/null @@ -1,177 +0,0 @@ -package com.chattriggers.ctjs.api.inventory.nbt - -import com.chattriggers.ctjs.internal.mixins.NbtCompoundAccessor -import com.chattriggers.ctjs.MCNbtBase -import com.chattriggers.ctjs.MCNbtCompound -import com.chattriggers.ctjs.internal.utils.asMixin -import net.minecraft.nbt.NbtByteArray -import net.minecraft.nbt.NbtElement -import net.minecraft.nbt.NbtIntArray -import net.minecraft.nbt.NbtLongArray -import org.mozilla.javascript.NativeObject - -class NBTTagCompound(override val mcValue: MCNbtCompound) : NBTBase(mcValue) { - val tagMap: Map - get() = mcValue.asMixin().entries - - val keySet: Set - get() = mcValue.keys - - enum class NBTDataType { - BYTE, - SHORT, - INTEGER, - LONG, - FLOAT, - DOUBLE, - STRING, - BYTE_ARRAY, - INT_ARRAY, - LONG_ARRAY, - BOOLEAN, - COMPOUND_TAG, - TAG_LIST, - } - - fun getTag(key: String): NBTBase? = mcValue.get(key)?.let(::fromMC) - - fun getTagId(key: String) = mcValue.getType(key) - - fun getByte(key: String) = mcValue.getByte(key) - - fun getShort(key: String) = mcValue.getShort(key) - - fun getInteger(key: String) = mcValue.getInt(key) - - fun getLong(key: String) = mcValue.getLong(key) - - fun getFloat(key: String) = mcValue.getFloat(key) - - fun getDouble(key: String) = mcValue.getDouble(key) - - fun getString(key: String) = mcValue.getString(key) - - fun getByteArray(key: String) = mcValue.getByteArray(key) - - fun getIntArray(key: String) = mcValue.getIntArray(key) - - fun getBoolean(key: String) = mcValue.getBoolean(key) - - fun getCompoundTag(key: String) = NBTTagCompound(mcValue.getCompound(key)) - - fun getTagList(key: String, type: Int) = NBTTagList(mcValue.getList(key, type)) - - fun get(key: String, type: NBTDataType, tagType: Int?): Any? { - return when (type) { - NBTDataType.BYTE -> getByte(key) - NBTDataType.SHORT -> getShort(key) - NBTDataType.INTEGER -> getInteger(key) - NBTDataType.LONG -> getLong(key) - NBTDataType.FLOAT -> getFloat(key) - NBTDataType.DOUBLE -> getDouble(key) - NBTDataType.STRING -> { - if (mcValue.contains(key, NbtElement.STRING_TYPE.toInt())) - tagMap[key]?.let { NBTBase(it).toString() } - else null - } - NBTDataType.BYTE_ARRAY -> { - if (mcValue.contains(key, NbtElement.BYTE_TYPE.toInt())) - (tagMap[key] as NbtByteArray).byteArray - else null - } - NBTDataType.INT_ARRAY -> { - if (mcValue.contains(key, NbtElement.INT_ARRAY_TYPE.toInt())) - (tagMap[key] as NbtIntArray).intArray - else null - } - NBTDataType.LONG_ARRAY -> { - if (mcValue.contains(key, NbtElement.LONG_ARRAY_TYPE.toInt())) - (tagMap[key] as NbtLongArray).longArray - else null - } - NBTDataType.BOOLEAN -> getBoolean(key) - NBTDataType.COMPOUND_TAG -> getCompoundTag(key) - NBTDataType.TAG_LIST -> getTagList( - key, - tagType - ?: throw IllegalArgumentException("For accessing a tag list you need to provide the tagType argument") - ) - } - } - - operator fun get(key: String): NBTBase? = getTag(key) - - fun setNBTBase(key: String, value: NBTBase) = setNBTBase(key, value.toMC()) - - fun setNBTBase(key: String, value: MCNbtBase) = apply { - mcValue.put(key, value) - } - - fun setBoolean(key: String, value: Boolean) = apply { - mcValue.putBoolean(key, value) - } - - fun setByte(key: String, value: Byte) = apply { - mcValue.putByte(key, value) - } - - fun setShort(key: String, value: Short) = apply { - mcValue.putShort(key, value) - } - - fun setInteger(key: String, value: Int) = apply { - mcValue.putInt(key, value) - } - - fun setLong(key: String, value: Long) = apply { - mcValue.putLong(key, value) - } - - fun setFloat(key: String, value: Float) = apply { - mcValue.putFloat(key, value) - } - - fun setDouble(key: String, value: Double) = apply { - mcValue.putDouble(key, value) - } - - fun setString(key: String, value: String) = apply { - mcValue.putString(key, value) - } - - fun setByteArray(key: String, value: ByteArray) = apply { - mcValue.putByteArray(key, value) - } - - fun setIntArray(key: String, value: IntArray) = apply { - mcValue.putIntArray(key, value) - } - - fun putLongArray(key: String, value: LongArray) = apply { - mcValue.putLongArray(key, value) - } - - operator fun set(key: String, value: Any) = apply { - when (value) { - is NBTBase -> setNBTBase(key, value) - is MCNbtBase -> setNBTBase(key, value) - is Byte -> setByte(key, value) - is Short -> setShort(key, value) - is Int -> setInteger(key, value) - is Long -> setLong(key, value) - is Float -> setFloat(key, value) - is Double -> setDouble(key, value) - is CharSequence -> setString(key, value.toString()) - is ByteArray -> setByteArray(key, value) - is IntArray -> setIntArray(key, value) - is Boolean -> setBoolean(key, value) - else -> throw IllegalArgumentException("Unsupported NBT type: ${value.javaClass.simpleName}") - } - } - - fun removeTag(key: String) = apply { - mcValue.remove(key) - } - - fun toObject(): NativeObject = mcValue.toObject() -} diff --git a/src/main/kotlin/com/chattriggers/ctjs/api/inventory/nbt/NBTTagList.kt b/src/main/kotlin/com/chattriggers/ctjs/api/inventory/nbt/NBTTagList.kt deleted file mode 100644 index fc7ff774..00000000 --- a/src/main/kotlin/com/chattriggers/ctjs/api/inventory/nbt/NBTTagList.kt +++ /dev/null @@ -1,66 +0,0 @@ -package com.chattriggers.ctjs.api.inventory.nbt - -import com.chattriggers.ctjs.MCNbtBase -import com.chattriggers.ctjs.MCNbtList -import net.minecraft.nbt.NbtElement -import org.mozilla.javascript.NativeArray - -class NBTTagList(override val mcValue: MCNbtList) : NBTBase(mcValue) { - val tagCount: Int - get() = mcValue.size - - fun appendTag(nbt: NBTBase) = appendTag(nbt.toMC()) - - fun appendTag(nbt: MCNbtBase) = apply { - mcValue.add(nbt) - } - - operator fun set(id: Int, nbt: NBTBase) = set(id, nbt.toMC()) - - operator fun set(id: Int, nbt: MCNbtBase) = apply { - mcValue[id] = nbt - } - - fun insertTag(index: Int, nbt: NBTBase) = insertTag(index, nbt.toMC()) - - fun insertTag(index: Int, nbt: MCNbtBase) = apply { - mcValue.add(index, nbt) - } - - fun removeTag(index: Int) = fromMC(mcValue.removeAt(index)) - - fun getShortAt(index: Int) = mcValue.getShort(index) - - fun getIntAt(index: Int) = mcValue.getInt(index) - - fun getFloatAt(index: Int) = mcValue.getFloat(index) - - fun getDoubleAt(index: Int) = mcValue.getDouble(index) - - fun getStringTagAt(index: Int): String = mcValue.getString(index) - - fun getListAt(index: Int) = NBTTagList(mcValue.getList(index)) - - fun getCompoundTagAt(index: Int) = NBTTagCompound(mcValue.getCompound(index)) - - fun getIntArrayAt(index: Int): IntArray = mcValue.getIntArray(index) - - fun getLongArrayAt(index: Int): LongArray = mcValue.getLongArray(index) - - operator fun get(index: Int): NbtElement = mcValue[index] - - fun get(index: Int, type: Byte): Any = when (type) { - NbtElement.SHORT_TYPE -> getShortAt(index) - NbtElement.INT_TYPE -> getIntAt(index) - NbtElement.FLOAT_TYPE -> getFloatAt(index) - NbtElement.DOUBLE_TYPE -> getDoubleAt(index) - NbtElement.STRING_TYPE -> getStringTagAt(index) - NbtElement.LIST_TYPE -> getListAt(index) - NbtElement.COMPOUND_TYPE -> getCompoundTagAt(index) - NbtElement.INT_ARRAY_TYPE -> getIntArrayAt(index) - NbtElement.LONG_ARRAY_TYPE -> getLongArrayAt(index) - else -> get(index) - } - - fun toArray(): NativeArray = mcValue.toObject() -} diff --git a/src/main/kotlin/com/chattriggers/ctjs/api/message/ChatLib.kt b/src/main/kotlin/com/chattriggers/ctjs/api/message/ChatLib.kt deleted file mode 100644 index 1133d876..00000000 --- a/src/main/kotlin/com/chattriggers/ctjs/api/message/ChatLib.kt +++ /dev/null @@ -1,422 +0,0 @@ -package com.chattriggers.ctjs.api.message - -import com.chattriggers.ctjs.api.client.Client -import com.chattriggers.ctjs.api.render.Renderer -import com.chattriggers.ctjs.internal.listeners.ClientListener -import com.chattriggers.ctjs.internal.mixins.ChatHudAccessor -import com.chattriggers.ctjs.internal.utils.asMixin -import net.fabricmc.fabric.impl.command.client.ClientCommandInternals -import net.minecraft.client.gui.hud.ChatHudLine -import net.minecraft.client.gui.hud.MessageIndicator -import org.mozilla.javascript.regexp.NativeRegExp -import java.awt.Toolkit -import java.awt.datatransfer.StringSelection -import java.util.regex.Pattern -import kotlin.math.roundToInt - -object ChatLib { - private val chatLineIds = mutableMapOf() - private val chatHudAccessor get() = Client.getChatGui()?.asMixin() - - /** - * Prints text in the chat. - * The text can be a String or a [TextComponent] - * - * @param text the text to be printed - */ - @JvmStatic - fun chat(text: Any?) { - when (text) { - is TextComponent -> text - is CharSequence -> TextComponent(text) - else -> TextComponent(text.toString()) - }.chat() - } - - /** - * Shows text in the action bar. - * The text can be a String or a [TextComponent] - * - * @param text the text to show - */ - @JvmStatic - fun actionBar(text: Any?) { - when (text) { - is TextComponent -> text - is CharSequence -> TextComponent(text) - else -> TextComponent(text.toString()) - }.actionBar() - } - - /** - * Simulates a chat message to be caught by other triggers for testing. - * The text can be a String or a [TextComponent] - * - * @param text The message to simulate - */ - @JvmStatic - fun simulateChat(text: Any?) { - when (text) { - is TextComponent -> text - is CharSequence -> TextComponent(text) - else -> TextComponent(text.toString()) - }.withRecursive().chat() - } - - - /** - * Replaces the easier to type '&' color codes with proper color codes in a string. - * - * @param message The string to add color codes to - * @return the formatted message - */ - @JvmStatic - fun addColor(message: String?): String { - return message.toString().replace("(?= chatWidth) - return text - - val spaceWidth = (chatWidth - textWidth) / 2f - val spaceBuilder = StringBuilder().apply { - repeat((spaceWidth / Renderer.getStringWidth(" ")).roundToInt()) { - append(' ') - } - } - - return spaceBuilder.append(text).toString() - } - - /** - * Copies the given String to the user's clipboard - * - * @param text the text to copy - */ - @JvmStatic - fun copyToClipboard(text: String) { - Toolkit.getDefaultToolkit().systemClipboard.setContents(StringSelection(text), null) - } - - - /** - * Edits an already sent chat message matched by [regexp]. - * - * @param regexp the regex object to match to the message - * @param replacements the new message(s) to be put in replace of the old one - */ - @JvmStatic - fun editChat(regexp: NativeRegExp, vararg replacements: Any) { - val global = regexp["global"] as Boolean - val ignoreCase = regexp["ignoreCase"] as Boolean - val multiline = regexp["multiline"] as Boolean - - val flags = (if (ignoreCase) Pattern.CASE_INSENSITIVE else 0) or if (multiline) Pattern.MULTILINE else 0 - val pattern = Pattern.compile(regexp["source"] as String, flags) - - editLines(replacements) { - val matcher = pattern.matcher(TextComponent(it.content).unformattedText) - if (global) matcher.find() else matcher.matches() - } - } - - /** - * Edits an already sent chat message by the text of the chat - * - * @param toReplace the unformatted text of the message to be replaced - * @param replacements the new message(s) to be put in place of the old one - */ - @JvmStatic - fun editChat(toReplace: String, vararg replacements: Any) { - editLines(replacements) { - removeFormatting(TextComponent(it.content).unformattedText) == toReplace - } - } - - /** - * Edits an already sent chat message by the [TextComponent] - * - * @param toReplace the message to be replaced - * @param replacements the new message(s) to be put in place of the old one - */ - @JvmStatic - fun editChat(toReplace: TextComponent, vararg replacements: Any) { - editLines(replacements) { - toReplace.formattedText == TextComponent(it.content).formattedText - } - } - - /** - * Edits an already sent chat message by its chat line id - * - * @param chatLineId the chat line id of the message to be replaced - * @param replacements the new message(s) to be put in place of the old one - */ - @JvmStatic - fun editChat(chatLineId: Int, vararg replacements: Any) { - editLines(replacements) { - chatLineIds[it] == chatLineId - } - } - - /** - * Edits an already sent chat message by given a callback that receives - * [TextComponent] instances - * - * @param matcher a function that accepts a [TextComponent] and returns a boolean - * @param replacements the new message(s) to be put in place of the old one - */ - @JvmStatic - fun editChat(matcher: (TextComponent) -> Boolean, vararg replacements: Any) { - editLines(replacements) { matcher(TextComponent(it.content)) } - } - - private fun editLines(replacements: Array, matcher: (ChatHudLine) -> Boolean) { - val mc = Client.getMinecraft() - val indicator = if (mc.isConnectedToLocalServer) MessageIndicator.singlePlayer() else MessageIndicator.system() - var edited = false - val it = chatHudAccessor?.messages?.listIterator() ?: return - - while (it.hasNext()) { - val next = it.next() - if (matcher(next)) { - edited = true - it.remove() - chatLineIds.remove(next) - for (replacement in replacements) { - val message = replacement as? TextComponent ?: TextComponent(replacement) - val line = ChatHudLine(next.creationTick, message, null, indicator) - if (message.getChatLineId() != -1) - chatLineIds[line] = message.getChatLineId() - - it.add(line) - } - } - } - - if (edited) - chatHudAccessor!!.invokeRefresh() - } - - /** - * Deletes an already sent chat message matching [regexp]. - * - * @param regexp the regex object to match to the message - */ - @JvmStatic - fun deleteChat(regexp: NativeRegExp) { - val global = regexp["global"] as Boolean - val ignoreCase = regexp["ignoreCase"] as Boolean - val multiline = regexp["multiline"] as Boolean - - val flags = (if (ignoreCase) Pattern.CASE_INSENSITIVE else 0) or if (multiline) Pattern.MULTILINE else 0 - val pattern = Pattern.compile(regexp["source"] as String, flags) - - removeLines { - val matcher = pattern.matcher(TextComponent(it.content).unformattedText) - if (global) matcher.find() else matcher.matches() - } - } - - /** - * Deletes an already sent chat message by the text of the chat - * - * @param toDelete the unformatted text of the message to be deleted - */ - @JvmStatic - fun deleteChat(toDelete: String) { - removeLines { - removeFormatting(TextComponent(it.content).unformattedText) == toDelete - } - } - - /** - * Deletes an already sent chat message by the [TextComponent] - * - * @param toDelete the message to be deleted - */ - @JvmStatic - fun deleteChat(toDelete: TextComponent) { - removeLines { - toDelete.formattedText == TextComponent(it.content).formattedText - } - } - - /** - * Deletes an already sent chat message by its chat line id - * - * @param chatLineId the chat line id of the message to be deleted - */ - @JvmStatic - fun deleteChat(chatLineId: Int) { - removeLines { chatLineIds[it] == chatLineId } - } - - /** - * Deletes an already sent chat message given a callback that receives - * [TextComponent] instances - * - * @param matcher a function that accepts a [TextComponent] and returns a boolean - */ - @JvmStatic - fun deleteChat(matcher: (TextComponent) -> Boolean) { - removeLines { matcher(TextComponent(it.content)) } - } - - private fun removeLines(matcher: (ChatHudLine) -> Boolean) { - var removed = false - val it = chatHudAccessor?.messages?.listIterator() ?: return - - while (it.hasNext()) { - val next = it.next() - if (matcher(next)) { - it.remove() - chatLineIds.remove(next) - removed = true - } - } - - if (removed) - chatHudAccessor!!.invokeRefresh() - } - - /** - * Gets the previous 1000 lines of chat - * - * @return A list of the last 1000 chat lines - */ - @JvmStatic - fun getChatLines(): List { - val hist = ClientListener.chatHistory.toMutableList() - return hist.asReversed().map { it.formattedText } - } - - /** - * Adds a message to the player's chat history. This allows the message to - * show up for the player when pressing the up/down keys while in the chat gui - * - * @param index the index to insert the message - * @param message the message to add to chat history - */ - @JvmStatic - @JvmOverloads - fun addToSentMessageHistory(index: Int = -1, message: String) { - if (index == -1) { - Client.getMinecraft().inGameHud.chatHud.addToMessageHistory(message) - } else { - Client.getMinecraft().inGameHud.chatHud.messageHistory.add(index, message) - } - } - - internal fun sendMessageWithId(message: TextComponent) { - require(message.getChatLineId() != -1) - - val chatGui = Client.getChatGui() ?: return - chatGui.addMessage(message) - val newChatLine = chatHudAccessor!!.messages[0] - - check(message == newChatLine.content()) { - "Expected new chat message to be at index 0" - } - - chatLineIds[newChatLine] = message.getChatLineId() - } - - internal fun onChatHudClearChat() { - chatLineIds.clear() - } - - internal fun onChatHudLineRemoved(line: ChatHudLine) { - chatLineIds.remove(line) - } -} diff --git a/src/main/kotlin/com/chattriggers/ctjs/api/message/TextComponent.kt b/src/main/kotlin/com/chattriggers/ctjs/api/message/TextComponent.kt deleted file mode 100644 index 7f7cb912..00000000 --- a/src/main/kotlin/com/chattriggers/ctjs/api/message/TextComponent.kt +++ /dev/null @@ -1,565 +0,0 @@ -package com.chattriggers.ctjs.api.message - -import com.chattriggers.ctjs.CTJS -import com.chattriggers.ctjs.MCEntity -import com.chattriggers.ctjs.api.client.Client -import com.chattriggers.ctjs.api.client.Player -import com.chattriggers.ctjs.api.entity.Entity -import com.chattriggers.ctjs.api.inventory.Item -import com.chattriggers.ctjs.api.inventory.ItemType -import com.chattriggers.ctjs.internal.utils.toIdentifier -import com.mojang.serialization.Codec -import com.mojang.serialization.MapCodec -import com.mojang.serialization.codecs.RecordCodecBuilder -import gg.essential.universal.UChat -import net.minecraft.item.ItemStack -import net.minecraft.network.packet.s2c.play.GameMessageS2CPacket -import net.minecraft.text.* -import net.minecraft.util.Formatting -import org.mozilla.javascript.Context -import org.mozilla.javascript.NativeObject -import org.mozilla.javascript.ScriptRuntime -import java.util.* -import java.util.concurrent.ThreadLocalRandom -import kotlin.streams.toList - -/** - * A wrapper around the Minecraft Text class and it's various inheritors. - * - * This class acts as a container for "pairs". A pair is a string of text - * that is associated with a particular [Style]. Unlike Minecraft's Text - * class, this container is a list, not a tree, which makes them much easier - * to work with. It implements [List]<[NativeObject]>, so it can be iterated - * over. - * - * Importantly, instances of [TextComponent] are immutable. Methods for - * "mutation" exist, but they return new instances of [TextComponent]. See - * [withText] for an example. - * - * @see Text - */ -// Note: For the sake of the Text implementations, parts[0] is the "self" part, -// and parts[1..] are the siblings, but the exposed CT API treats this as -// a container of individual parts -class TextComponent private constructor( - private val parts: MutableList, - private val chatLineId: Int = -1, - private val isRecursive: Boolean = false, -) : Text, Iterable { - /** - * Creates an empty [TextComponent] with a single, unstyled, empty part. - */ - constructor() : this(listOf(Part("", Style.EMPTY))) - - /** - * Creates a [TextComponent] from a variable number of objects. These - * objects can be: - * - A plain string possibly containing formatting codes. If the string has - * formatting codes, it will be split into different parts accordingly - * - A [TextComponent], whose parts will be appended in sequence to this - * [TextComponent]'s list of parts - * - A [Text] object, which acts as a single part - * - A JS object, which must contain a "text" key, and can optionally contain - * any of the [Style] keys: - * - color: a [TextColor] or string format of a [TextColor], [Formatting], or a hex value - * - bold: boolean - * - italic: boolean - * - underline: boolean - * - strikethrough: boolean - * - obfuscated: boolean - * - clickEvent: object with { action: [ClickEvent.Action] or string format of a [ClickEvent.Action], value: string or null } - * - hoverEvent: object with { action: [HoverEvent.Action], string format of a [HoverEvent.Action], or null, value: string or null } - * - insertion: string or null - * - font: string format of an [net.minecraft.util.Identifier] - * - * @see Style - */ - constructor(vararg parts: Any) : this(parts.flatMap(Part::of).toMutableList().let { - if (it.isEmpty()) mutableListOf(Part("", Style.EMPTY)) else it - }) - - /** - * Returns the text of all parts concatenated without formatting codes. - */ - val unformattedText by lazy { - parts.fold("") { prev, curr -> prev + curr.text } - } - - /** - * Returns the text of all parts concatenated with formatting codes. - */ - val formattedText by lazy { - parts.fold("") { prev, curr -> prev + curr.style_.formatCodes() + curr.text } - } - - /** - * Get the chat line ID of this message, if it exists. The chat line can be used - * to easily edit or delete a message later via [ChatLib.editChat] and - * [ChatLib.deleteChat]. - * - * @return the chat line ID of the message, or -1 if this [TextComponent] does - * not have an associated chat line ID. - */ - fun getChatLineId() = chatLineId - - /** - * @return a new [TextComponent] with the given chat line id - */ - @JvmOverloads - fun withChatLineId(id: Int = ThreadLocalRandom.current().nextInt()) = copy(chatLineId = id) - - /** - * If this [TextComponent] is recursive, sending this instance (via [chat] or - * [actionBar]) may trigger other `chat` triggers as if it had been received by - * the server. [TextComponent]s are non-recursive by default. - * - * @return true if the message can trigger other triggers. - */ - fun isRecursive(): Boolean = isRecursive - - /** - * Sets whether the message can trigger other triggers. - * - * @param recursive true if message can trigger other triggers. - */ - @JvmOverloads - fun withRecursive(recursive: Boolean = true) = copy(isRecursive = recursive) - - /** - * @return a new [TextComponent] with the specified [value] appended to the end. - * This accepts all types of objects that the vararg constructor does. - */ - fun withText(value: Any) = copy(parts = (parts + Part.of(value)).toMutableList()) - - /** - * @return a new [TextComponent] with the specified [value] inserted at [index]. - * This accepts all types of objects that the vararg constructor does. - */ - fun withTextAt(index: Int, value: Any) = - copy(parts = (parts.take(index) + Part.of(value) + parts.drop(index)).toMutableList()) - - /** - * @return a new [TextComponent] without the part at [index] - */ - fun withoutTextAt(index: Int) = - copy(parts = (parts.take(index) + parts.drop(index + 1)).toMutableList()) - - /** - * Edits this text component, replacing it with the given [newText]. Note that - * this compares [TextComponent]s based on [formattedText]; if an exact match - * is needed, use [ChatLib.editChat] in conjunction with a chat line ID. - */ - fun edit(newText: TextComponent) = apply { - ChatLib.editChat(this, newText) - } - - /** - * Edits this text component, replacing it with a new [TextComponent] from the - * given [parts]. Note that this compares [TextComponent]s based on - * [formattedText]; if an exact match is needed, use [ChatLib.editChat] in - * conjunction with a chat line ID. - */ - fun edit(vararg parts: Any) = edit(TextComponent(*parts)) - - /** - * Deletes this text component. Note that this compares [TextComponent]s based on - * [formattedText]; if an exact match is needed, use [ChatLib.editChat] in conjunction - * with a chat line ID. - */ - fun delete() = apply { - ChatLib.deleteChat(this) - } - - /** - * Sends this [TextComponent] to the players chat. - * - * Note that this is purely client-side, and will not be sent to the server. If [isRecursive], - * will trigger any matching `chat` triggers - * - * @see ChatLib.chat - * @see ChatLib.say - */ - fun chat() = apply { - if (Player.toMC() == null) - return@apply - - if (chatLineId != -1) { - ChatLib.sendMessageWithId(this) - return@apply - } - - if (isRecursive) { - Client.scheduleTask { - Client.getMinecraft().networkHandler?.onGameMessage(GameMessageS2CPacket(this, false)) - } - } else { - Player.toMC()?.sendMessage(this) - } - } - - /** - * Sends this [TextComponent] to the players action bar. - * - * If [isRecursive], will trigger any matching `actionBar` triggers - * - * @see ChatLib.actionBar - */ - fun actionBar() = apply { - if (Player.toMC() == null) - return@apply - - if (isRecursive) { - Client.scheduleTask { - Client.getMinecraft().networkHandler?.onGameMessage(GameMessageS2CPacket(this, true)) - } - } else { - Player.toMC()?.sendMessage(this, true) - } - } - - override fun toString() = formattedText - - internal fun toMutableText() = Text.empty().apply { - parts.forEach(::append) - } - - // Make this method manually to avoid exposing it as a public API - private fun copy( - parts: MutableList = this.parts, - chatLineId: Int = this.chatLineId, - isRecursive: Boolean = this.isRecursive - ) = TextComponent(parts, chatLineId, isRecursive) - - ////////// - // Text // - ////////// - - override fun getContent(): TextContent = parts[0].content - - override fun getString(): String = parts[0].text - - override fun getStyle(): Style = parts[0].style_ - - override fun getSiblings(): MutableList = parts.drop(1).toMutableList() - - override fun asOrderedText(): OrderedText = OrderedText { visitor -> - var i = 0 - parts.all { - it.text.codePoints().toList().all { cp -> - visitor.accept(i++, it.style, cp) - } - } - } - - // "List" impl - // This interface doesn't actually implement List, as that would cause Rhino to convert it to a JS - // array when returned from a Java API - val size by parts::size - - operator fun contains(element: NativeObject) = parts.any { ScriptRuntime.eq(element, it.nativeObject) } - - fun containsAll(elements: Collection) = elements.all(::contains) - - operator fun get(index: Int) = parts[index].nativeObject - - fun indexOf(element: NativeObject) = parts.indexOfFirst { it.nativeObject == element } - - fun isEmpty() = parts.isEmpty() - - override fun iterator() = parts.map(Part::nativeObject).iterator() - - private class Part(val content: PartContent) : Text { - val text by content::text - val style_ by content::style_ - - val nativeObject: NativeObject by lazy { - val cx = Context.getContext() - cx.newObject(cx.topCallScope).also { - it.put("text", it, text) - if (style_.color != null) - it.put("color", it, style_.color) - if (style_.isBold) - it.put("bold", it, true) - if (style_.isItalic) - it.put("italic", it, true) - if (style_.isUnderlined) - it.put("underline", it, true) - if (style_.isStrikethrough) - it.put("strikethrough", it, true) - if (style_.isObfuscated) - it.put("obfuscated", it, true) - style_.clickEvent?.let { event -> - if (event.action != null) { - val clickEvent = NativeObject() - clickEvent.put("action", clickEvent, event.action.asString()) - clickEvent.put("value", clickEvent, event.value) - - it.put("clickEvent", it, clickEvent) - } - } - style_.hoverEvent?.let { event -> - if (event.action != null) { - val hoverEvent = NativeObject() - hoverEvent.put("action", hoverEvent, event.action.asString()) - event.getValue(event.action!!)?.let { value -> - hoverEvent.put("value", hoverEvent, value) - } - - it.put("hoverEvent", it, hoverEvent) - } - } - if (style_.insertion != null) - it.put("insertion", it, style_.insertion) - if (style_.font != null && style_.font.toString() != "minecraft:default") - it.put("font", it, style_.font) - } - } - - constructor(text: String, style: Style) : this(PartContent(text, style)) - - override fun getContent(): TextContent = content - - override fun getString(): String = text - - override fun getStyle(): Style = style_ - - override fun getSiblings(): MutableList = mutableListOf() - - override fun asTruncatedString(length: Int): String = text.take(length) - - override fun asOrderedText(): OrderedText = OrderedText { visitor -> - text.codePoints().toList().withIndex().all { (index, cp) -> - visitor.accept(index, style_, cp) - } - } - - companion object { - fun of(obj: Any?): List = when (obj) { - is NativeObject -> { - val text = obj["text"] - ?: throw IllegalArgumentException("Expected TextComponent part to have a \"text\" key") - require(text is CharSequence) { "TextComponent part's \"text\" key must be a string" } - listOf(Part(ChatLib.addColor(text.toString()), jsObjectToStyle(obj))) - } - is Part -> listOf(obj) - is TextComponent -> obj.parts - is Text -> { - val parts = mutableListOf() - - obj.content.visit({ style, text -> - parts.add(Part(text, style)) - Optional.empty() - }, obj.style) - - parts + obj.siblings.flatMap(::of) - } - is CharSequence -> { - val parts = mutableListOf() - val builder = StringBuilder() - var lastStyle = Style.EMPTY - - TextVisitFactory.visitFormatted(ChatLib.addColor(obj.toString()), 0, Style.EMPTY) { _, style, cp -> - if (style != lastStyle) { - parts.add(Part(builder.toString(), lastStyle)) - lastStyle = style - builder.clear() - } - builder.appendCodePoint(cp) - true - } - - if (builder.isNotEmpty()) - parts.add(Part(builder.toString(), lastStyle)) - - parts - } - is List<*> -> obj.flatMap(::of) - null -> emptyList() - else -> throw IllegalArgumentException("Cannot convert ${obj::class.simpleName} to TextComponent part") - } - } - } - - // Must be a separate class since Text and TextContent have an identical "visit" method which fails loom remapping - private class PartContent(val text: String, val style_: Style) : TextContent { - override fun visit(visitor: StringVisitable.Visitor): Optional = visitor.accept(text) - - override fun visit(visitor: StringVisitable.StyledVisitor, style: Style): Optional { - return visitor.accept(this.style_.withParent(style), text) - } - - override fun getType(): TextContent.Type<*> = TextContent.Type(CODEC, "${CTJS.MOD_ID}_part") - - companion object { - private val CODEC: MapCodec = RecordCodecBuilder.mapCodec { builder -> - builder.group( - Codec.STRING.fieldOf("text").forGetter(PartContent::text), - net.minecraft.text.Style.Codecs.CODEC.fieldOf("style").forGetter(PartContent::style_), - ).apply(builder) { text, style -> PartContent(text, style) } - } - } - } - - internal companion object { - private val colorToFormatChar = Formatting.entries.mapNotNull { format -> - TextColor.fromFormatting(format)?.let { it to format } - }.toMap() - - internal fun jsObjectToStyle(obj: NativeObject): Style { - return Style.EMPTY - .withColor(obj["color"]?.let { color -> - when (color) { - is TextColor -> color - is Formatting -> TextColor.fromFormatting(color) - is Number -> TextColor.fromRgb(color.toInt()) - is CharSequence -> TextColor.parse(color.toString()).result().orElseThrow { - IllegalArgumentException("Could not parse \"$color\" as a text color") - } - else -> throw IllegalArgumentException("Could not convert type ${color::class.simpleName} to a text color") - } - }) - .withBold( - obj.getOrDefault("bold", false) as? Boolean - ?: error("Expected \"bold\" key to be a boolean") - ) - .withItalic( - obj.getOrDefault("italic", false) as? Boolean - ?: error("Expected \"italic\" key to be a boolean") - ) - .withUnderline( - obj.getOrDefault("underline", false) as? Boolean - ?: error("Expected \"underline\" key to be a boolean") - ) - .withStrikethrough( - obj.getOrDefault("strikethrough", false) as? Boolean - ?: error("Expected \"strikethrough\" key to be a boolean") - ) - .withObfuscated( - obj.getOrDefault("obfuscated", false) as? Boolean - ?: error("Expected \"obfuscated\" key to be a boolean") - ) - .withClickEvent(makeClickEvent(obj["clickEvent"])) - .withHoverEvent(makeHoverEvent(obj["hoverEvent"])) - .withInsertion( - when (val insertion = obj["insertion"]) { - null -> null - is CharSequence -> insertion.toString() - else -> error("Expected \"insertion\" key to be a String") - } - ) - .withFont( - when (val font = obj["font"]) { - null -> null - is CharSequence -> font.toString().toIdentifier() - else -> error("Expected \"font\" key to be a String") - } - ) - } - - private fun Style.formatCodes() = buildString { - append("§r") - - when { - isBold -> append("§l") - isItalic -> append("§o") - isUnderlined -> append("§n") - isStrikethrough -> append("§m") - isObfuscated -> append("§k") - } - - color?.let(colorToFormatChar::get)?.run(::append) - } - - private fun makeClickEvent(clickEvent: Any?): ClickEvent? { - if (clickEvent is ClickEvent?) - return clickEvent - - require(clickEvent is NativeObject) { "Expected \"clickEvent\" key to be an object or ClickEvent" } - - val action = clickEvent["action"] - val value = clickEvent["value"] - - val clickAction = when (action) { - is ClickEvent.Action -> action - is CharSequence -> ClickEvent.Action.valueOf(action.toString().uppercase()) - null -> if (value != null) { - error("Cannot set Style's click value without a click action") - } else return null - else -> error("Style.withClickAction() expects a String, ClickEvent.Action, or null, but got ${action::class.simpleName}") - } - - val clickValue = when (value) { - null -> null - is CharSequence -> value.toString().let { - if (clickAction == ClickEvent.Action.OPEN_URL) { - if (!it.startsWith("http://") && !it.startsWith("https://")) { - return@let "http://$it" - } - } - it - } - else -> error("Expected \"value\" key to be a string") - } - - return ClickEvent(clickAction, clickValue.orEmpty()) - } - - private fun makeHoverEvent(hoverEvent: Any?): HoverEvent? { - if (hoverEvent is HoverEvent?) - return hoverEvent - - require(hoverEvent is NativeObject) { "Expected \"hoverEvent\" key to be an object or HoverEvent" } - - val action = hoverEvent["action"] - val value = hoverEvent["value"] - - val hoverAction = when (action) { - is HoverEvent.Action<*> -> action - is CharSequence -> when (action.toString().uppercase()) { - "SHOW_TEXT" -> HoverEvent.Action.SHOW_TEXT - "SHOW_ITEM" -> HoverEvent.Action.SHOW_ITEM - "SHOW_ENTITY" -> HoverEvent.Action.SHOW_ENTITY - else -> throw IllegalStateException("Unknown hover event action \"$action\"") - } - null -> if (value != null) { - error("Cannot set Style's hover value without a hover action") - } else return null - else -> error("Style.withHoverAction() expects a String, HoverEvent.Action, or null, but got ${action::class.simpleName}") - } - - if (value == null) - return HoverEvent(hoverAction, null) - - val hoverValue: Any? = when (hoverAction) { - HoverEvent.Action.SHOW_TEXT -> TextComponent(value) - HoverEvent.Action.SHOW_ITEM -> parseItemContent(value) - HoverEvent.Action.SHOW_ENTITY -> parseEntityContent(value) - else -> error("unreachable") - } - - @Suppress("UNCHECKED_CAST") - return HoverEvent(hoverAction as HoverEvent.Action, hoverValue) - } - - private fun parseItemContent(obj: Any): HoverEvent.ItemStackContent { - return when (obj) { - is ItemStack -> obj - is Item -> obj.toMC() - is CharSequence -> ItemType(obj.toString()).asItem().toMC() - is HoverEvent.ItemStackContent -> return obj - else -> error("${obj::class} cannot be parsed as an item HoverEvent") - }.let(HoverEvent::ItemStackContent) - } - - private fun parseEntityContent(obj: Any): HoverEvent.EntityContent? { - return when (obj) { - is MCEntity -> obj - is Entity -> obj.toMC() - is CharSequence -> return HoverEvent.EntityContent.legacySerializer(TextComponent(obj), null) - .getOrThrow() - is HoverEvent.EntityContent -> return obj - else -> error("${obj::class} cannot be parsed as an entity HoverEvent") - }.let { HoverEvent.EntityContent(it.type, it.uuid, it.name) } - } - } -} diff --git a/src/main/kotlin/com/chattriggers/ctjs/api/render/Book.kt b/src/main/kotlin/com/chattriggers/ctjs/api/render/Book.kt deleted file mode 100644 index 515cb2e3..00000000 --- a/src/main/kotlin/com/chattriggers/ctjs/api/render/Book.kt +++ /dev/null @@ -1,86 +0,0 @@ -package com.chattriggers.ctjs.api.render - -import com.chattriggers.ctjs.api.client.Client -import com.chattriggers.ctjs.api.message.TextComponent -import com.chattriggers.ctjs.internal.mixins.BookScreenAccessor -import com.chattriggers.ctjs.internal.utils.asMixin -import net.minecraft.client.gui.screen.ingame.BookScreen -import net.minecraft.text.StringVisitable - -class Book { - private var screen: BookScreen? = null - private val customContents = BookScreen.Contents(emptyList()) - - /** - * Add a page to the book. - * - * @param contents the entire message for what the page should be - * @return the current book to allow method chaining - */ - fun addPage(contents: TextComponent) = apply { - customContents.pages.add(contents) - } - - /** - * Overloaded method for adding a simple page to the book. - * - * @param message a simple string to make the page - * @return the current book to allow method chaining - */ - fun addPage(message: String) = apply { - addPage(TextComponent(message)) - } - - /** - * Inserts a page at the specified index of the book - * - * @param pageIndex the index of the page to set - * @param message the message to set the page to - * @return the current book to allow method chaining - */ - fun insertPage(pageIndex: Int, message: TextComponent) = apply { - require(pageIndex in customContents.pages.indices) { - println("Invalid index $pageIndex for Book with ${customContents.pageCount} pages") - } - - customContents.pages.add(pageIndex, message) - screen?.asMixin()?.invokeUpdatePageButtons() - } - - fun insertPage(pageIndex: Int, message: String) = insertPage(pageIndex, TextComponent(message)) - - /** - * Sets a page of the book to the specified message. - * - * @param pageIndex the index of the page to set - * @param message the message to set the page to - * @return the current book to allow method chaining - */ - fun setPage(pageIndex: Int, message: TextComponent) = apply { - require(pageIndex in customContents.pages.indices) { - println("Invalid index $pageIndex for Book with ${customContents.pageCount} pages") - } - - customContents.pages[pageIndex] = message - screen?.asMixin()?.invokeUpdatePageButtons() - } - - fun setPage(pageIndex: Int, message: String) = setPage(pageIndex, TextComponent(message)) - - @JvmOverloads - fun display(pageIndex: Int = 0) { - screen = BookScreen(customContents) - Client.scheduleTask { - Client.getMinecraft().setScreen(screen) - screen!!.setPage(pageIndex) - } - } - - fun isOpen(): Boolean { - return Client.currentGui.get() === screen - } - - fun getCurrentPage(): Int { - return if (!isOpen() || screen == null) -1 else screen!!.asMixin().pageIndex - } -} diff --git a/src/main/kotlin/com/chattriggers/ctjs/api/render/CTPlayerRenderer.kt b/src/main/kotlin/com/chattriggers/ctjs/api/render/CTPlayerRenderer.kt deleted file mode 100644 index a5a51efd..00000000 --- a/src/main/kotlin/com/chattriggers/ctjs/api/render/CTPlayerRenderer.kt +++ /dev/null @@ -1,124 +0,0 @@ -package com.chattriggers.ctjs.api.render - -import net.minecraft.client.network.AbstractClientPlayerEntity -import net.minecraft.client.render.VertexConsumerProvider -import net.minecraft.client.render.entity.EntityRendererFactory -import net.minecraft.client.render.entity.PlayerEntityRenderer -import net.minecraft.client.render.entity.feature.* -import net.minecraft.client.render.entity.model.ArmorEntityModel -import net.minecraft.client.render.entity.model.EntityModelLayers -import net.minecraft.client.util.math.MatrixStack -import net.minecraft.text.Text - -internal class CTPlayerRenderer( - private val ctx: EntityRendererFactory.Context, - private val slim: Boolean, -) : PlayerEntityRenderer(ctx, slim) { - var showArmor = true - set(value) { - field = value - reset() - } - var showHeldItem = true - set(value) { - field = value - reset() - } - var showArrows = true - set(value) { - field = value - reset() - } - var showCape = true - set(value) { - field = value - reset() - } - var showElytra = true - set(value) { - field = value - reset() - } - var showParrot = true - set(value) { - field = value - reset() - } - var showStingers = true - set(value) { - field = value - reset() - } - var showNametag = true - set(value) { - field = value - reset() - } - - fun setOptions( - showNametag: Boolean = true, - showArmor: Boolean = true, - showCape: Boolean = true, - showHeldItem: Boolean = true, - showArrows: Boolean = true, - showElytra: Boolean = true, - showParrot: Boolean = true, - showStingers: Boolean = true, - ) { - this.showNametag = showNametag - this.showArmor = showArmor - this.showCape = showCape - this.showHeldItem = showHeldItem - this.showArrows = showArrows - this.showElytra = showElytra - this.showParrot = showParrot - this.showStingers = showStingers - - reset() - } - - override fun hasLabel(livingEntity: AbstractClientPlayerEntity?) = showNametag - - override fun renderLabelIfPresent( - abstractClientPlayerEntity: AbstractClientPlayerEntity?, - text: Text?, - matrixStack: MatrixStack?, - vertexConsumerProvider: VertexConsumerProvider?, - i: Int, - f: Float - ) { - if (showNametag) - super.renderLabelIfPresent(abstractClientPlayerEntity, text, matrixStack, vertexConsumerProvider, i, f) - } - - private fun reset() { - features.clear() - - if (showArmor) { - addFeature( - ArmorFeatureRenderer( - this, - ArmorEntityModel(ctx.getPart(if (slim) EntityModelLayers.PLAYER_SLIM_INNER_ARMOR else EntityModelLayers.PLAYER_INNER_ARMOR)), - ArmorEntityModel(ctx.getPart(if (slim) EntityModelLayers.PLAYER_SLIM_OUTER_ARMOR else EntityModelLayers.PLAYER_OUTER_ARMOR)), - ctx.modelManager - ) - ) - } - if (showHeldItem) - addFeature(PlayerHeldItemFeatureRenderer(this, ctx.heldItemRenderer)) - if (showArrows) - addFeature(StuckArrowsFeatureRenderer(ctx, this)) - addFeature(Deadmau5FeatureRenderer(this)) - if (showCape) - addFeature(CapeFeatureRenderer(this)) - if (showArmor) - addFeature(HeadFeatureRenderer(this, ctx.modelLoader, ctx.heldItemRenderer)) - if (showElytra) - addFeature(ElytraFeatureRenderer(this, ctx.modelLoader)) - if (showParrot) - addFeature(ShoulderParrotFeatureRenderer(this, ctx.modelLoader)) - addFeature(TridentRiptideFeatureRenderer(this, ctx.modelLoader)) - if (showStingers) - addFeature(StuckStingersFeatureRenderer(this)) - } -} diff --git a/src/main/kotlin/com/chattriggers/ctjs/api/render/Display.kt b/src/main/kotlin/com/chattriggers/ctjs/api/render/Display.kt deleted file mode 100644 index ae0a9a44..00000000 --- a/src/main/kotlin/com/chattriggers/ctjs/api/render/Display.kt +++ /dev/null @@ -1,194 +0,0 @@ -package com.chattriggers.ctjs.api.render - -import com.chattriggers.ctjs.internal.utils.getOption -import org.mozilla.javascript.NativeObject -import java.util.concurrent.CopyOnWriteArrayList - -class Display() { - private var lines = CopyOnWriteArrayList() - - private var x = 0f - private var y = 0f - private var order = Order.NORMAL - - private var backgroundColor: Long = 0x50000000 - private var textColor: Long = 0xffffffff - private var background = Background.NONE - private var align = Text.Align.LEFT - - private var minWidth = 0f - private var width = 0f - private var height = 0f - - constructor(config: NativeObject?) : this() { - setBackgroundColor(config.getOption("backgroundColor", 0x50000000).toLong()) - setTextColor(config.getOption("textColor", 0xffffffff).toLong()) - setBackground(config.getOption("background", Background.NONE)) - setAlign(config.getOption("align", Text.Align.LEFT)) - setOrder(config.getOption("order", Order.NORMAL)) - setX(config.getOption("x", 0f).toFloat()) - setY(config.getOption("y", 0f).toFloat()) - setMinWidth(config.getOption("minWidth", 0f).toFloat()) - } - - fun getTextColor(): Long = textColor - - /** - * Sets the color of the texts - * - * Overrides the color of the individual texts - */ - fun setTextColor(textColor: Long) = apply { - this.textColor = textColor - } - - fun getAlign(): Text.Align = align - - /** - * Set the alignment of the texts in the display - * - * Overrides alignment of the individual texts - */ - fun setAlign(align: Any) = apply { - this.align = when (align) { - is CharSequence -> Text.Align.valueOf(align.toString().uppercase()) - is Text.Align -> align - else -> Text.Align.LEFT - } - } - - fun getOrder(): Order = order - - fun setOrder(order: Any) = apply { - this.order = when (order) { - is CharSequence -> Order.valueOf(order.toString().uppercase()) - is Order -> order - else -> Order.NORMAL - } - } - - fun getBackground(): Background = background - - fun setBackground(background: Any) = apply { - this.background = when (background) { - is CharSequence -> Background.valueOf(background.toString().uppercase().replace(" ", "_")) - is Background -> background - else -> Background.NONE - } - } - - fun getBackgroundColor(): Long = backgroundColor - - fun setBackgroundColor(backgroundColor: Long) = apply { - this.backgroundColor = backgroundColor - } - - fun setLine(index: Int, line: Any) = apply { - while (lines.size - 1 < index) - lines.add(Text("")) - - when (line) { - is CharSequence -> lines[index].setString(line.toString()) - is Text -> lines[index] = line - else -> lines[index] = Text("") - } - } - - fun getLine(index: Int): Text = lines[index] - - fun getLines(): List = lines - - fun setLines(lines: MutableList) = apply { - this.lines = CopyOnWriteArrayList(lines) - } - - fun addLine(line: Any) = apply { - setLine(this.lines.size, line) - } - - fun addLines(vararg lines: Any) = apply { - lines.forEach { addLine(it) } - } - - fun removeLine(index: Int) = apply { - lines.removeAt(index) - } - - fun clearLines() = apply { - lines.clear() - } - - fun getX(): Float = x - - fun setX(x: Float) = apply { this.x = x } - - fun getY(): Float = y - - fun setY(y: Float) = apply { this.y = y } - - fun getWidth(): Float = width - - fun getHeight(): Float = height - - fun getMinWidth(): Float = minWidth - - fun setMinWidth(minWidth: Float) = apply { - this.minWidth = minWidth - } - - fun draw() { - width = lines.maxOfOrNull { it.getWidth() }?.coerceAtLeast(minWidth) ?: minWidth - - val textBackgroundWidth = when (background) { - Background.FULL -> width - Background.PER_LINE -> width - Background.NONE -> null - } - - var currentHeight = 0f - - val linesX = when (align) { - Text.Align.CENTER -> x + width / 2 - Text.Align.RIGHT -> x + width - else -> x - } - - val linesToDraw = when (order) { - Order.NORMAL -> lines - Order.REVERSED -> lines.asReversed() - } - - linesToDraw.forEach { - if (background === Background.FULL) - it - .setBackground(true) - .setBackgroundColor(backgroundColor) - - it - .setColor(textColor) - .setAlign(align) - .draw(linesX, y + currentHeight, x, textBackgroundWidth) - - currentHeight += it.getHeight() - } - - height = currentHeight - } - - override fun toString() = - "Display{" + - "renderX=$x, renderY=$y, " + - "background=$background, backgroundColor=$backgroundColor, " + - "textColor=$textColor, align=$align, order=$order, " + - "minWidth=$minWidth, width=$width, height=$height, " + - "lines=$lines" + - "}" - - enum class Background { - NONE, FULL, PER_LINE - } - - enum class Order { - REVERSED, NORMAL - } -} diff --git a/src/main/kotlin/com/chattriggers/ctjs/api/render/Gui.kt b/src/main/kotlin/com/chattriggers/ctjs/api/render/Gui.kt deleted file mode 100644 index 2b0035c2..00000000 --- a/src/main/kotlin/com/chattriggers/ctjs/api/render/Gui.kt +++ /dev/null @@ -1,506 +0,0 @@ -package com.chattriggers.ctjs.api.render - -import com.chattriggers.ctjs.api.client.Client -import com.chattriggers.ctjs.api.message.TextComponent -import com.chattriggers.ctjs.api.triggers.RegularTrigger -import com.chattriggers.ctjs.api.triggers.TriggerType -import com.chattriggers.ctjs.internal.mixins.ClickableWidgetAccessor -import com.chattriggers.ctjs.internal.utils.asMixin -import gg.essential.universal.UKeyboard -import gg.essential.universal.UMatrixStack -import gg.essential.universal.UScreen -import net.fabricmc.fabric.api.client.screen.v1.ScreenMouseEvents -import net.minecraft.client.gui.DrawContext -import net.minecraft.client.gui.tooltip.Tooltip -import net.minecraft.client.gui.widget.ButtonWidget - -class Gui @JvmOverloads constructor( - title: TextComponent = TextComponent(""), -) : UScreen(unlocalizedName = title.formattedText) { - private var onDraw: RegularTrigger? = null - private var onClick: RegularTrigger? = null - private var onScroll: RegularTrigger? = null - private var onKeyTyped: RegularTrigger? = null - private var onMouseReleased: RegularTrigger? = null - private var onMouseDragged: RegularTrigger? = null - private var onActionPerformed: RegularTrigger? = null - private var onOpened: RegularTrigger? = null - private var onClosed: RegularTrigger? = null - - private var mouseX = 0 - private var mouseY = 0 - - private val buttons = mutableMapOf() - private var nextButtonId = 0 - private var doesPauseGame = false - - fun open() { - Client.currentGui.set(this) - } - - override fun close() { - Client.currentGui.set(null) - - } - - fun isOpen(): Boolean = Client.getMinecraft().currentScreen === this - - /** - * Registers a method to be run while gui is open. - * Registered method runs on draw. - * Arguments passed through to method: - * - int mouseX - * - int mouseY - * - float partialTicks - * - * @param method the method to run - * @return the trigger - */ - fun registerDraw(method: Any) = apply { - onDraw = RegularTrigger(method, TriggerType.OTHER) - } - - /** - * Registers a method to be run while gui is open. - * Registered method runs on mouse click. - * Arguments passed through to method: - * - int mouseX - * - int mouseY - * - int button - * - * @param method the method to run - * @return the trigger - */ - fun registerClicked(method: Any) = apply { - onClick = RegularTrigger(method, TriggerType.OTHER) - } - - /** - * Registers a method to be run while the gui is open. - * Registered method runs on mouse scroll. - * Arguments passed through to method: - * - int mouseX - * - int mouseY - * - int scroll direction - */ - fun registerScrolled(method: Any) = apply { - onScroll = RegularTrigger(method, TriggerType.OTHER) - } - - /** - * Registers a method to be run while gui is open. - * Registered method runs on key input. - * Arguments passed through to method: - * - char typed character - * - int key code - * - * @param method the method to run - * @return the trigger - */ - fun registerKeyTyped(method: Any) = apply { - onKeyTyped = RegularTrigger(method, TriggerType.OTHER) - } - - /** - * Registers a method to be run while gui is open. - * Registered method runs on key input. - * Arguments passed through to method: - * - int mouseX - * - int mouseY - * - int clickedMouseButton - * - long timeSinceLastClick - * - * @param method the method to run - * @return the trigger - */ - fun registerMouseDragged(method: Any) = apply { - onMouseDragged = RegularTrigger(method, TriggerType.OTHER) - } - - /** - * Registers a method to be run while gui is open. - * Registered method runs on mouse release. - * Arguments passed through to method: - * - int mouseX - * - int mouseY - * - int button - * - * @param method the method to run - * @return the trigger - */ - fun registerMouseReleased(method: Any) = apply { - onMouseReleased = RegularTrigger(method, TriggerType.OTHER) - } - - /** - * Registers a method to be run while gui is open. - * Registered method runs when an action is performed (clicking a button) - * Arguments passed through to method: - * - the button that is clicked - * - * @param method the method to run - * @return the trigger - */ - fun registerActionPerformed(method: Any) = apply { - onActionPerformed = RegularTrigger(method, TriggerType.OTHER) - } - - /** - * Registers a method to be run when the gui is opened. - * Arguments passed through to method: - * - the gui that is opened - * - * @param method the method to run - * @return the trigger - */ - fun registerOpened(method: Any) = apply { - onOpened = RegularTrigger(method, TriggerType.OTHER) - } - - /** - * Registers a method to be run when the gui is closed. - * Arguments passed through to method: - * - the gui that is closed - * - * @param method the method to run - * @return the trigger - */ - fun registerClosed(method: Any) = apply { - onClosed = RegularTrigger(method, TriggerType.OTHER) - } - - fun unregisterDraw() = apply { - onDraw?.unregister() - onDraw = null - } - - fun unregisterClicked() = apply { - onClick?.unregister() - onClick = null - } - - fun unregisterScrolled() = apply { - onScroll?.unregister() - onScroll = null - } - - fun unregisterKeyTyped() = apply { - onKeyTyped?.unregister() - onKeyTyped = null - } - - fun unregisterMouseDragged() = apply { - onMouseDragged?.unregister() - onMouseDragged = null - } - - fun unregisterMouseReleased() = apply { - onMouseReleased?.unregister() - onMouseReleased = null - } - - fun unregisterActionPerformed() = apply { - onActionPerformed?.unregister() - onActionPerformed = null - } - - fun unregisterOpened() = apply { - onOpened?.unregister() - onOpened = null - } - - fun unregisterClosed() = apply { - onClosed?.unregister() - onClosed = null - } - - override fun initScreen(width: Int, height: Int) { - super.initScreen(width, height) - - ScreenMouseEvents.afterMouseScroll(this).register { _, x, y, _, dy -> - onScroll?.trigger(arrayOf(x, y, dy)) - } - - buttons.values.forEach(::addDrawableChild) - onOpened?.trigger(arrayOf(this)) - } - - /** - * Internal method to run trigger. Not meant for public use - */ - override fun onScreenClose() { - super.onScreenClose() - onClosed?.trigger(arrayOf(this)) - } - - /** - * Internal method to run trigger. Not meant for public use - */ - override fun onMouseClicked(mouseX: Double, mouseY: Double, mouseButton: Int) { - super.onMouseClicked(mouseX, mouseY, mouseButton) - onClick?.trigger(arrayOf(mouseX, mouseY, mouseButton)) - } - - /** - * Internal method to run trigger. Not meant for public use - * - * Note: [state] is actually the mouse button, no clue why it's named that - */ - override fun onMouseReleased(mouseX: Double, mouseY: Double, state: Int) { - super.onMouseReleased(mouseX, mouseY, state) - onMouseReleased?.trigger(arrayOf(mouseX, mouseY, state)) - } - - /** - * Internal method to run trigger. Not meant for public use - */ - override fun onMouseDragged( - x: Double, - y: Double, - clickedButton: Int, - timeSinceLastClick: Long, - ) { - super.onMouseDragged(x, y, clickedButton, timeSinceLastClick) - onMouseDragged?.trigger(arrayOf(mouseX, mouseY, clickedButton)) - } - - /** - * Internal method to run trigger. Not meant for public use - */ - override fun onDrawScreen( - matrixStack: UMatrixStack, - mouseX: Int, - mouseY: Int, - partialTicks: Float, - ) { - super.onDrawScreen(matrixStack, mouseX, mouseY, partialTicks) - - @Suppress("UNCHECKED_CAST") - val drawContexts = drawContextsField.get(this) as List - Renderer.pushMatrix(UMatrixStack(drawContexts.last().matrices)) - - Renderer.partialTicks = partialTicks - - this.mouseX = mouseX - this.mouseY = mouseY - onDraw?.trigger(arrayOf(mouseX, mouseY, partialTicks)) - - Renderer.popMatrix() - } - - /** - * Internal method to run trigger. Not meant for public use - */ - override fun onKeyPressed(keyCode: Int, typedChar: Char, modifiers: UKeyboard.Modifiers?) { - super.onKeyPressed(keyCode, typedChar, modifiers) - - if (keyCode != 0) { - var char = keyCode.toChar() - if (modifiers?.isShift != true) - char = char.lowercaseChar() - onKeyTyped?.trigger(arrayOf(char, keyCode)) - } - } - - /** - * Internal method to run trigger. Not meant for public use - */ - - override fun shouldPause() = doesPauseGame - - fun setDoesPauseGame(doesPauseGame: Boolean) = apply { this.doesPauseGame = doesPauseGame } - - /** - * Add a base Minecraft button to the gui - * - * @param button the button to add - * @return the button ID for use in actionPerformed - */ - fun addButton(button: ButtonWidget): Int { - val id = nextButtonId++ - buttons[id] = button - addDrawableChild(button) - return id - } - - /** - * Add a base Minecraft button to the gui - * - * @param x the x position of the button - * @param y the y position of the button - * @param width the width of the button - * @param height the height of the button - * @param buttonText the label of the button - * @return the button ID for use in actionPerformed - */ - @JvmOverloads - fun addButton( - x: Int, - y: Int, - width: Int = 200, - height: Int = 20, - buttonText: TextComponent, - ): Int { - val id = nextButtonId++ - val button = ButtonWidget.builder(buttonText) { - onActionPerformed?.trigger(arrayOf(id)) - }.dimensions(x, y, width, height).build() - buttons[id] = button - addDrawableChild(button) - return id - } - - fun addButton(x: Int, y: Int, width: Int = 200, height: Int = 20, buttonText: String) = - addButton(x, y, width, height, TextComponent(buttonText)) - - /** - * Removes a button from the gui with the given id - * - * @param buttonId the id of the button to remove - * @return the Gui for method chaining - */ - fun removeButton(buttonId: Int) = apply { - remove(buttons[buttonId] ?: return@apply) - buttons.remove(buttonId) - } - - fun clearButtons() = apply { - buttons.values.forEach(::remove) - buttons.clear() - } - - fun getButtonVisibility(buttonId: Int): Boolean = buttons[buttonId]?.visible ?: false - - /** - * Sets the visibility of a button - * - * @param buttonId the id of the button to change - * @param visible the new visibility of the button - * @return the Gui for method chaining - */ - fun setButtonVisibility(buttonId: Int, visible: Boolean) = apply { - buttons[buttonId]?.visible = visible - } - - fun getButtonEnabled(buttonId: Int): Boolean = buttons[buttonId]?.active ?: false - - /** - * Sets the enabled state of a button - * - * @param buttonId the id of the button to set - * @param enabled the enabled state of the button - * @return the Gui for method chaining - */ - fun setButtonEnabled(buttonId: Int, enabled: Boolean) = apply { - buttons[buttonId]?.active = enabled - } - - fun getButtonWidth(buttonId: Int): Int = buttons[buttonId]?.width ?: 0 - - /** - * Sets the button's width. Button textures break if the width is greater than 200 - * - * @param buttonId id of the button - * @param width the new width - * @return the Gui for method chaining - */ - fun setButtonWidth(buttonId: Int, width: Int) = apply { - buttons[buttonId]?.width = width - } - - fun getButtonHeight(buttonId: Int): Int = buttons[buttonId]?.height ?: 0 - - /** - * Sets the button's height. Button textures break if the height is not 20 - * - * @param buttonId id of the button - * @param height the new height - * @return the Gui for method chaining - */ - fun setButtonHeight(buttonId: Int, height: Int) = apply { - buttons[buttonId]?.asMixin()?.setHeight(height) - } - - fun getButtonX(buttonId: Int): Int = buttons[buttonId]?.x ?: 0 - - /** - * Sets the button's x position - * - * @param buttonId id of the button - * @param x the new x position - * @return the Gui for method chaining - */ - fun setButtonX(buttonId: Int, x: Int) = apply { - buttons[buttonId]?.x = x - } - - fun getButtonY(buttonId: Int): Int = buttons[buttonId]?.y ?: 0 - - /** - * Sets the button's y position - * - * @param buttonId id of the button - * @param y the new y position - * @return the Gui for method chaining - */ - fun setButtonY(buttonId: Int, y: Int) = apply { - buttons[buttonId]?.y = y - } - - /** - * Sets the button's position - * - * @param buttonId id of the button - * @param x the new x position - * @param y the new y position - * @return the Gui for method chaining - */ - fun setButtonLoc(buttonId: Int, x: Int, y: Int) = apply { - buttons[buttonId]?.apply { - this.x = x - this.y = y - } - } - - /** - * Sets the button's text - * - * @param buttonId id of the button - * @param text the new text - */ - fun setButtonText(buttonId: Int, text: TextComponent) = apply { - buttons[buttonId]?.message = text - } - - /** - * Sets the button's text - * - * @param buttonId id of the button - * @param text the new text - */ - fun setButtonText(buttonId: Int, text: String) = setButtonText(buttonId, TextComponent(text)) - - /** - * Sets the gui's tooltip, this will be visible on top of the cursor - * when the gui is open. - * - * @param text the contents of the tooltip - */ - fun setTooltip(text: TextComponent) = apply { - setTooltip(Tooltip.wrapLines(Client.getMinecraft(), text)) - } - - /** - * Sets the gui's tooltip, this will be visible on top of the cursor - * when the gui is open. - * - * @param text the contents of the tooltip - */ - fun setTooltip(text: String) = setTooltip(TextComponent(text)) - - private companion object { - private val drawContextsField = UScreen::class.java.getDeclaredField("drawContexts").also { - it.isAccessible = true - } - } -} diff --git a/src/main/kotlin/com/chattriggers/ctjs/api/render/Image.kt b/src/main/kotlin/com/chattriggers/ctjs/api/render/Image.kt deleted file mode 100644 index d8c29d3f..00000000 --- a/src/main/kotlin/com/chattriggers/ctjs/api/render/Image.kt +++ /dev/null @@ -1,147 +0,0 @@ -package com.chattriggers.ctjs.api.render - -import com.chattriggers.ctjs.CTJS -import com.chattriggers.ctjs.api.client.Client -import net.minecraft.client.texture.NativeImage -import net.minecraft.client.texture.NativeImageBackedTexture -import net.minecraft.util.Identifier -import org.lwjgl.system.MemoryUtil -import java.awt.image.BufferedImage -import java.io.ByteArrayOutputStream -import java.io.File -import java.net.HttpURLConnection -import java.nio.ByteBuffer -import javax.imageio.ImageIO - -class Image(var image: BufferedImage?) { - private var texture: Texture? = null - private val textureWidth = image?.width ?: 0 - private val textureHeight = image?.height ?: 0 - private val aspectRatio = if (textureHeight != 0) textureHeight.toFloat() / textureWidth else 0f - private var identifier: Identifier? = null - - init { - CTJS.images.add(this) - - Client.scheduleTask { - texture = image!!.toNativeTexture() - } - } - - fun getTextureWidth(): Int = textureWidth - - fun getTextureHeight(): Int = textureHeight - - fun getTexture(): NativeImageBackedTexture? = texture?.texture - - internal fun getIdOrRegister(): Identifier { - if (identifier == null) { - identifier = Identifier.of(CTJS.MOD_ID,"image${nextIdentifierIndex++}") - if (texture != null) { - Client.getMinecraft().textureManager.registerTexture(identifier!!, texture!!.texture) - } else { - Client.scheduleTask { - Client.getMinecraft().textureManager.registerTexture(identifier!!, texture!!.texture) - } - } - } - - return identifier!! - } - - /** - * Clears the image from GPU memory and removes its references CT side - * that way it can be garbage collected if not referenced in js code. - */ - fun destroy() { - texture?.texture?.close() - texture?.buffer?.let(MemoryUtil::memFree) - texture = null - image = null - } - - @JvmOverloads - fun draw( - x: Float, - y: Float, - width: Float? = null, - height: Float? = null, - ) = apply { - val (drawWidth, drawHeight) = when { - width == null && height == null -> textureWidth.toFloat() to textureHeight.toFloat() - width == null -> height!! / aspectRatio to height - height == null -> width to width * aspectRatio - else -> width to height - } - - if (texture != null) - Renderer.drawImage(this, x, y, drawWidth, drawHeight) - } - - private data class Texture(val texture: NativeImageBackedTexture, val buffer: ByteBuffer) - - companion object { - private var nextIdentifierIndex = 0 - - /** - * Create an image object from a java.io.File object. Throws an exception - * if the file cannot be found. - */ - @JvmStatic - fun fromFile(file: File) = Image(ImageIO.read(file)) - - /** - * Create an image object from a file path. Throws an exception - * if the file cannot be found. - */ - @JvmStatic - fun fromFile(file: String) = Image(ImageIO.read(File(file))) - - /** - * Create an image object from a file path, relative to the assets directory. - * Throws an exception if the file cannot be found. - */ - @JvmStatic - fun fromAsset(name: String) = Image(ImageIO.read(File(CTJS.assetsDir, name))) - - /** - * Creates an image object from a URL. Throws an exception if an image - * cannot be created from the URL. Will cache the image in the assets - */ - @JvmStatic - @JvmOverloads - fun fromUrl(url: String, cachedImageName: String? = null): Image { - if (cachedImageName == null) - return Image(getImageFromUrl(url)) - - val resourceFile = File(CTJS.assetsDir, cachedImageName) - - if (resourceFile.exists()) - return Image(ImageIO.read(resourceFile)) - - val image = getImageFromUrl(url) - ImageIO.write(image, "png", resourceFile) - return Image(image) - } - - private fun getImageFromUrl(url: String): BufferedImage { - val req = CTJS.makeWebRequest(url) - if (req is HttpURLConnection) { - req.requestMethod = "GET" - req.doOutput = true - } - - return ImageIO.read(req.inputStream) - } - - private fun BufferedImage.toNativeTexture(): Texture { - return ByteArrayOutputStream().use { - ImageIO.write(this, "png", it) - val buffer = MemoryUtil.memAlloc(it.size()) - buffer.put(it.toByteArray()) - buffer.rewind() - Texture(NativeImageBackedTexture(NativeImage.read(buffer)), buffer) - } - } - } -} diff --git a/src/main/kotlin/com/chattriggers/ctjs/api/render/Rectangle.kt b/src/main/kotlin/com/chattriggers/ctjs/api/render/Rectangle.kt deleted file mode 100644 index b0d06745..00000000 --- a/src/main/kotlin/com/chattriggers/ctjs/api/render/Rectangle.kt +++ /dev/null @@ -1,130 +0,0 @@ -package com.chattriggers.ctjs.api.render - -import com.chattriggers.ctjs.api.vec.Vec2f - -class Rectangle( - private var color: Long, - private var x: Float, - private var y: Float, - private var width: Float, - private var height: Float -) { - - private val shadow = Shadow(this) - private val outline = Outline(this) - - fun getColor(): Long = color - - fun setColor(color: Long) = apply { this.color = Renderer.fixAlpha(color) } - - fun getX(): Float = x - - fun setX(x: Float) = apply { this.x = x } - - fun getY(): Float = y - - fun setY(y: Float) = apply { this.y = y } - - fun getWidth(): Float = width - - fun setWidth(width: Float) = apply { this.width = width } - - fun getHeight(): Float = height - - fun setHeight(height: Float) = apply { this.height = height } - - fun isShadow(): Boolean = shadow.on - - fun setShadow(shadow: Boolean) = apply { this.shadow.on = shadow } - - fun getShadowOffset(): Vec2f = shadow.offset - - fun getShadowOffsetX(): Float = shadow.offset.x - - fun getShadowOffsetY(): Float = shadow.offset.y - - fun setShadowOffset(x: Float, y: Float) = apply { - shadow.offset = Vec2f(x, y) - } - - fun setShadowOffsetX(x: Float) = apply { shadow.offset = Vec2f(x, shadow.offset.y) } - - fun setShadowOffsetY(y: Float) = apply { shadow.offset = Vec2f(shadow.offset.y, y) } - - fun getShadowColor(): Long = shadow.color - - fun setShadowColor(color: Long) = apply { shadow.color = color } - - fun setShadow(color: Long, x: Float, y: Float) = apply { - setShadow(true) - setShadowColor(color) - setShadowOffset(x, y) - } - - fun getOutline(): Boolean = outline.on - - fun setOutline(outline: Boolean) = apply { this.outline.on = outline } - - fun getOutlineColor(): Long = outline.color - - fun setOutlineColor(color: Long) = apply { outline.color = color } - - fun getThickness(): Float = outline.thickness - - fun setThickness(thickness: Float) = apply { outline.thickness = thickness } - - fun setOutline(color: Long, thickness: Float) = apply { - setOutline(true) - setOutlineColor(color) - setThickness(thickness) - } - - fun draw() = apply { - shadow.draw() - outline.draw() - Renderer.drawRect(color, x, y, width, height) - } - - private class Shadow( - val rect: Rectangle, - var on: Boolean = false, - var color: Long = 0x50000000, - var offset: Vec2f = Vec2f(5f, 5f) - ) { - fun draw() { - if (!on) return - Renderer.drawRect( - color, - rect.x + offset.x, - rect.y + rect.height, - rect.width, - offset.y - ) - Renderer.drawRect( - color, - rect.x + rect.width, - rect.y + offset.y, - offset.x, - rect.height - offset.y - ) - } - } - - private class Outline( - val rect: Rectangle, - var on: Boolean = false, - var color: Long = 0xffF000000, - var thickness: Float = 5f - ) { - fun draw() { - if (!on) return - Renderer.drawRect( - color, - rect.x - thickness, - rect.y - thickness, - rect.width + thickness * 2, - rect.height + thickness * 2 - ) - } - } -} diff --git a/src/main/kotlin/com/chattriggers/ctjs/api/render/Renderer.kt b/src/main/kotlin/com/chattriggers/ctjs/api/render/Renderer.kt deleted file mode 100644 index be42229d..00000000 --- a/src/main/kotlin/com/chattriggers/ctjs/api/render/Renderer.kt +++ /dev/null @@ -1,804 +0,0 @@ -package com.chattriggers.ctjs.api.render - -import com.chattriggers.ctjs.api.client.Client -import com.chattriggers.ctjs.api.client.Player -import com.chattriggers.ctjs.api.entity.PlayerMP -import com.chattriggers.ctjs.api.message.ChatLib -import com.chattriggers.ctjs.api.vec.Vec3f -import com.chattriggers.ctjs.internal.mixins.EntityRenderDispatcherAccessor -import com.chattriggers.ctjs.MCVertexFormat -import com.chattriggers.ctjs.engine.LogType -import com.chattriggers.ctjs.engine.printToConsole -import com.chattriggers.ctjs.internal.utils.asMixin -import com.chattriggers.ctjs.internal.utils.getOrDefault -import com.chattriggers.ctjs.internal.utils.toRadians -import com.mojang.blaze3d.systems.RenderSystem -import gg.essential.elementa.dsl.component1 -import gg.essential.elementa.dsl.component2 -import gg.essential.elementa.dsl.component3 -import gg.essential.elementa.dsl.component4 -import gg.essential.universal.UGraphics -import gg.essential.universal.UMatrixStack -import gg.essential.universal.UMinecraft -import net.minecraft.client.MinecraftClient -import net.minecraft.client.font.TextRenderer -import net.minecraft.client.network.AbstractClientPlayerEntity -import net.minecraft.client.render.DiffuseLighting -import net.minecraft.client.render.Tessellator -import net.minecraft.client.render.VertexConsumerProvider -import net.minecraft.client.render.VertexFormats -import net.minecraft.client.render.entity.EntityRendererFactory -import net.minecraft.client.util.math.MatrixStack -import org.joml.Matrix4f -import org.joml.Quaternionf -import org.mozilla.javascript.NativeObject -import java.awt.Color -import java.util.* -import kotlin.collections.ArrayDeque -import kotlin.math.PI -import kotlin.math.atan -import kotlin.math.atan2 -import kotlin.math.cos -import kotlin.math.sin - -object Renderer { - private val NEWLINE_REGEX = """\n|\r\n?""".toRegex() - - @JvmField - var colorized: Long? = null - - // The currently-active matrix stack - internal lateinit var matrixStack: UMatrixStack - private val matrixStackStack = ArrayDeque() - - private lateinit var slimCTRenderPlayer: CTPlayerRenderer - private lateinit var normalCTRenderPlayer: CTPlayerRenderer - - internal var matrixPushCounter = 0 - - @JvmField - val screen = ScreenWrapper() - - // The current partialTicks value - @JvmStatic - var partialTicks = 0f - internal set - - @JvmField - val BLACK = getColor(0, 0, 0, 255) - - @JvmField - val DARK_BLUE = getColor(0, 0, 190, 255) - - @JvmField - val DARK_GREEN = getColor(0, 190, 0, 255) - - @JvmField - val DARK_AQUA = getColor(0, 190, 190, 255) - - @JvmField - val DARK_RED = getColor(190, 0, 0, 255) - - @JvmField - val DARK_PURPLE = getColor(190, 0, 190, 255) - - @JvmField - val GOLD = getColor(217, 163, 52, 255) - - @JvmField - val GRAY = getColor(190, 190, 190, 255) - - @JvmField - val DARK_GRAY = getColor(63, 63, 63, 255) - - @JvmField - val BLUE = getColor(63, 63, 254, 255) - - @JvmField - val GREEN = getColor(63, 254, 63, 255) - - @JvmField - val AQUA = getColor(63, 254, 254, 255) - - @JvmField - val RED = getColor(254, 63, 63, 255) - - @JvmField - val LIGHT_PURPLE = getColor(254, 63, 254, 255) - - @JvmField - val YELLOW = getColor(254, 254, 63, 255) - - @JvmField - val WHITE = getColor(255, 255, 255, 255) - - @JvmStatic - fun color(color: Int): Long { - return when (color) { - 0 -> BLACK - 1 -> DARK_BLUE - 2 -> DARK_GREEN - 3 -> DARK_AQUA - 4 -> DARK_RED - 5 -> DARK_PURPLE - 6 -> GOLD - 7 -> GRAY - 8 -> DARK_GRAY - 9 -> BLUE - 10 -> GREEN - 11 -> AQUA - 12 -> RED - 13 -> LIGHT_PURPLE - 14 -> YELLOW - else -> WHITE - } - } - - @JvmStatic - internal fun initializePlayerRenderers(context: EntityRendererFactory.Context) { - normalCTRenderPlayer = CTPlayerRenderer(context, slim = false) - slimCTRenderPlayer = CTPlayerRenderer(context, slim = true) - } - - @JvmStatic - fun getFontRenderer() = UMinecraft.getFontRenderer() - - @JvmStatic - fun getRenderManager() = UMinecraft.getMinecraft().worldRenderer - - @JvmStatic - fun getStringWidth(text: String) = getFontRenderer().getWidth(ChatLib.addColor(text)) - - @JvmStatic - @JvmOverloads - fun getColor(red: Int, green: Int, blue: Int, alpha: Int = 255): Long { - return ((alpha.coerceIn(0, 255) shl 24) or - (red.coerceIn(0, 255) shl 16) or - (green.coerceIn(0, 255) shl 8) or - blue.coerceIn(0, 255)).toLong() - } - - @JvmStatic - @JvmOverloads - fun getRainbow(step: Float, speed: Float = 1f): Long { - val red = ((sin(step / speed) + 0.75) * 170).toInt() - val green = ((sin(step / speed + 2 * PI / 3) + 0.75) * 170).toInt() - val blue = ((sin(step / speed + 4 * PI / 3) + 0.75) * 170).toInt() - return getColor(red, green, blue) - } - - @JvmStatic - @JvmOverloads - fun getRainbowColors(step: Float, speed: Float = 1f): IntArray { - val red = ((sin(step / speed) + 0.75) * 170).toInt() - val green = ((sin(step / speed + 2 * PI / 3) + 0.75) * 170).toInt() - val blue = ((sin(step / speed + 4 * PI / 3) + 0.75) * 170).toInt() - return intArrayOf(red, green, blue) - } - - @JvmStatic - fun disableCull() = apply { RenderSystem.disableCull() } - - @JvmStatic - fun enableCull() = apply { RenderSystem.enableCull() } - - @JvmStatic - fun disableLighting() = apply { UGraphics.disableLighting() } - - @JvmStatic - fun enableLighting() = apply { UGraphics.enableLighting() } - - @JvmStatic - fun disableDepth() = apply { UGraphics.disableDepth() } - - @JvmStatic - fun enableDepth() = apply { UGraphics.enableDepth() } - - @JvmStatic - fun depthFunc(func: Int) = apply { UGraphics.depthFunc(func) } - - @JvmStatic - fun depthMask(flag: Boolean) = apply { UGraphics.depthMask(flag) } - - @JvmStatic - fun disableBlend() = apply { UGraphics.disableBlend() } - - @JvmStatic - fun enableBlend() = apply { UGraphics.enableBlend() } - - @JvmStatic - fun blendFunc(func: Int) = apply { UGraphics.blendEquation(func) } - - @JvmStatic - fun tryBlendFuncSeparate( - sourceFactor: Int, - destFactor: Int, - sourceFactorAlpha: Int, - destFactorAlpha: Int, - ) = apply { - UGraphics.tryBlendFuncSeparate(sourceFactor, destFactor, sourceFactorAlpha, destFactorAlpha) - } - - @JvmStatic - @JvmOverloads - fun bindTexture(texture: Image, textureIndex: Int = 0) = apply { - UGraphics.bindTexture(textureIndex, texture.getTexture()?.glId ?: 0) - } - - @JvmStatic - fun deleteTexture(texture: Image) = apply { - UGraphics.deleteTexture(texture.getTexture()?.glId ?: 0) - } - - @JvmStatic - @JvmOverloads - fun pushMatrix(stack: UMatrixStack = matrixStack) = apply { - matrixPushCounter++ - matrixStackStack.addLast(stack) - matrixStack = stack - stack.push() - } - - @JvmStatic - fun popMatrix() = apply { - matrixPushCounter-- - matrixStackStack.removeLast() - matrixStack.pop() - } - - @JvmStatic - @JvmOverloads - fun translate(x: Float, y: Float, z: Float = 0.0F) = apply { - matrixStack.translate(x, y, z) - } - - @JvmStatic - @JvmOverloads - fun scale(scaleX: Float, scaleY: Float = scaleX, scaleZ: Float = 1f) = apply { - matrixStack.scale(scaleX, scaleY, scaleZ) - } - - @JvmStatic - @JvmOverloads - fun rotate(angle: Float, x: Float = 0f, y: Float = 0f, z: Float = 1f) = apply { - matrixStack.rotate(angle, x, y, z) - } - - @JvmStatic - fun multiply(quaternion: Quaternionf) = apply { - matrixStack.multiply(quaternion) - } - - @JvmStatic - @JvmOverloads - fun colorize(red: Float, green: Float, blue: Float, alpha: Float = 1f) = - colorize( - (red * 255).toInt(), - (green * 255).toInt(), - (blue * 255).toInt(), - (alpha * 255).toInt() - ) - - @JvmStatic - @JvmOverloads - fun colorize(red: Int, green: Int, blue: Int, alpha: Int = 255) = apply { - colorized = fixAlpha(getColor(red, green, blue, alpha)) - val color = Color(colorized!!.toInt(), true) - - RenderSystem.setShaderColor( - color.red / 255f, - color.green / 255f, - color.blue / 255f, - color.alpha / 255f - ) - } - - @JvmStatic - fun fixAlpha(color: Long): Long { - val alpha = color ushr 24 and 255 - return if (alpha < 10) - (color and 0xFF_FF_FF) or 0xA_FF_FF_FF - else color - } - - /** - * Begin drawing with the world renderer - * - * @param drawMode the GL draw mode - * @param vertexFormat The [VertexFormat] to use for drawing - * @return [Renderer] to allow for method chaining - * @see DrawMode - */ - @JvmStatic - @JvmOverloads - fun begin( - drawMode: DrawMode = Renderer.DrawMode.QUADS, - vertexFormat: VertexFormat = Renderer.VertexFormat.POSITION, - ) = apply { - Renderer3d.begin(drawMode, vertexFormat) - } - - /** - * Sets a new vertex in the world renderer. - * - * @param x the x position - * @param y the y position - * @param z the z position - * @return [Renderer] to allow for method chaining - */ - @JvmStatic - @JvmOverloads - fun pos(x: Float, y: Float, z: Float = 0f) = apply { - val camera = Client.getMinecraft().gameRenderer.camera.pos - Renderer3d.pos(x + camera.x.toFloat(), y + camera.y.toFloat(), z + camera.z.toFloat()) - } - - /** - * Sets the texture location on the last defined vertex. - * - * @param u the u position in the texture - * @param v the v position in the texture - * @return [Renderer] to allow for method chaining - */ - @JvmStatic - fun tex(u: Float, v: Float) = apply { - Renderer3d.tex(u, v) - } - - /** - * Sets the color for the last defined vertex. - * - * @param r the red value of the color, between 0 and 1 - * @param g the green value of the color, between 0 and 1 - * @param b the blue value of the color, between 0 and 1 - * @param a the alpha value of the color, between 0 and 1 - * @return [Renderer] to allow for method chaining - */ - @JvmStatic - @JvmOverloads - fun color(r: Float, g: Float, b: Float, a: Float = 1f) = apply { - Renderer3d.color(r, g, b, a) - } - - /** - * Sets the color for the last defined vertex. - * - * @param r the red value of the color, between 0 and 255 - * @param g the green value of the color, between 0 and 255 - * @param b the blue value of the color, between 0 and 255 - * @param a the alpha value of the color, between 0 and 255 - * @return [Renderer] to allow for method chaining - */ - @JvmStatic - @JvmOverloads - fun color(r: Int, g: Int, b: Int, a: Int = 255) = apply { - Renderer3d.color(r, g, b, a) - } - - /** - * Sets the color for the last defined vertex. - * - * @param color the color value, can use [getColor] to get this - * @return [Renderer] to allow for method chaining - */ - @JvmStatic - fun color(color: Long) = apply { - val (r, g, b, a) = Color(color.toInt(), true) - Renderer3d.color(r, g, b, a) - } - - /** - * Sets the normal of the vertex. This is mostly used with [VertexFormat.LINES] - * - * @param x the x position of the normal vector - * @param y the y position of the normal vector - * @param z the z position of the normal vector - * @return [Renderer] to allow for method chaining - */ - @JvmStatic - fun normal(x: Float, y: Float, z: Float) = apply { - Renderer3d.normal(x, y, z) - } - - /** - * Sets the overlay location on the last defined vertex. - * - * @param u the u position in the overlay - * @param v the v position in the overlay - * @return [Renderer] to allow for method chaining - */ - @JvmStatic - fun overlay(u: Int, v: Int) = apply { - Renderer3d.overlay(u, v) - } - - /** - * Sets the light location on the last defined vertex. - * - * @param u the u position in the light - * @param v the v position in the light - * @return [Renderer] to allow for method chaining - */ - @JvmStatic - fun light(u: Int, v: Int) = apply { - Renderer3d.light(u, v) - } - - /** - * Sets the line width when rendering [DrawMode.LINES] - * - * @param width the width of the line - * @return [Renderer] to allow for method chaining - */ - @JvmStatic - fun lineWidth(width: Float) = apply { - Renderer3d.lineWidth(width) - } - - /** - * Finalizes vertices and draws the world renderer. - */ - @JvmStatic - fun draw() = Renderer3d.draw() - - /** - * Gets a fixed render position from x, y, and z inputs adjusted with partial ticks - * @param x the X coordinate - * @param y the Y coordinate - * @param z the Z coordinate - * @return the Vec3f position to render at - */ - @JvmStatic - fun getRenderPos(x: Float, y: Float, z: Float): Vec3f { - return Vec3f( - x - Player.getRenderX().toFloat(), - y - Player.getRenderY().toFloat(), - z - Player.getRenderZ().toFloat() - ) - } - - @JvmStatic - fun drawRect(color: Long, x: Float, y: Float, width: Float, height: Float) = apply { - val pos = mutableListOf(x, y, x + width, y + height) - if (pos[0] > pos[2]) - Collections.swap(pos, 0, 2) - if (pos[1] > pos[3]) - Collections.swap(pos, 1, 3) - - begin(vertexFormat = VertexFormat.POSITION_COLOR) - pos(pos[0], pos[3], 0f).color(color) - pos(pos[2], pos[3], 0f).color(color) - pos(pos[2], pos[1], 0f).color(color) - pos(pos[0], pos[1], 0f).color(color) - draw() - } - - @JvmStatic - fun drawLine( - color: Long, - x1: Float, - y1: Float, - x2: Float, - y2: Float, - thickness: Float, - ) { - val theta = -atan2(y2 - y1, x2 - x1) - val i = sin(theta) * (thickness / 2) - val j = cos(theta) * (thickness / 2) - - begin(vertexFormat = VertexFormat.POSITION_COLOR) - pos(x1 + i, y1 + j, 0f).color(color) - pos(x2 + i, y2 + j, 0f).color(color) - pos(x2 - i, y2 - j, 0f).color(color) - pos(x1 - i, y1 - j, 0f).color(color) - draw() - } - - @JvmStatic - fun drawCircle( - color: Long, - x: Float, - y: Float, - radius: Float, - steps: Int, - ) { - val theta = 2 * PI / steps - val cos = cos(theta).toFloat() - val sin = sin(theta).toFloat() - - var xHolder: Float - var circleX = 1f - var circleY = 0f - - begin(DrawMode.TRIANGLE_STRIP, VertexFormat.POSITION_COLOR) - - for (i in 0..steps) { - pos(x, y, 0f).color(color) - pos(circleX * radius + x, circleY * radius + y, 0f).color(color) - xHolder = circleX - circleX = cos * circleX - sin * circleY - circleY = sin * xHolder + cos * circleY - - pos(circleX * radius + x, circleY * radius + y, 0f).color(color) - } - - draw() - } - - @JvmStatic - @JvmOverloads - fun drawString( - text: String, - x: Float, - y: Float, - color: Long = colorized ?: WHITE, - shadow: Boolean = false, - ) { - val fr = getFontRenderer() - var newY = y - - val immediate = Client.getMinecraft().bufferBuilders.entityVertexConsumers - splitText(text).lines.forEach { - fr.draw( - it, - x, - newY, - color.toInt(), - shadow, - matrixStack.toMC().peek().positionMatrix, - immediate, - TextRenderer.TextLayerType.NORMAL, - 0, - 0xf000f0, - ) - - newY += fr.fontHeight - } - immediate.draw() - } - - @JvmStatic - @JvmOverloads - fun drawStringWithShadow(text: String, x: Float, y: Float, color: Long = colorized ?: WHITE) = - drawString(text, x, y, color, shadow = true) - - internal data class TextLines(val lines: List, val width: Float, val height: Float) - - internal fun splitText(text: String): TextLines { - val lines = ChatLib.addColor(text).split(NEWLINE_REGEX) - return TextLines( - lines, - lines.maxOf { getFontRenderer().getWidth(it) }.toFloat(), - (getFontRenderer().fontHeight * lines.size + (lines.size - 1)).toFloat(), - ) - } - - @JvmStatic - fun drawImage(image: Image, x: Float, y: Float, width: Float, height: Float) { - if (colorized == null) - colorize(1f, 1f, 1f, 1f) - - scale(1f, 1f, 50f) - - RenderSystem.setShaderTexture(0, image.getTexture()?.glId ?: 0) - - begin(DrawMode.QUADS, VertexFormat.POSITION_TEXTURE) - pos(x, y + height, 0f).tex(0f, 1f) - pos(x + width, y + height, 0f).tex(1f, 1f) - pos(x + width, y, 0f).tex(1f, 0f) - pos(x, y, 0f).tex(0f, 0f) - draw() - } - - /** - * Draws a player entity to the screen, similar to the one displayed in the inventory screen. - * - * Takes a parameter with the following options: - * - player: The player entity to draw. Can be a [PlayerMP] or [AbstractClientPlayerEntity]. - * Defaults to Player.toMC() - * - x: The x position on the screen to render the player - * - y: The y position on the screen to render the player - * - size: The size of the rendered player - * - rotate: Whether the player should look at the mouse cursor, similar to the inventory screen - * - pitch: THe pitch the rendered player will face, if rotate is false - * - yaw: The yaw the rendered player will face, if rotate is false - * - showNametag: Whether the nametag of the player should be rendered - * - showArmor: Whether the armor of the player should be rendered - * - showCape: Whether the cape of the player should be rendered - * - showHeldItem: Whether the held item of the player should be rendered - * - showArrows: Whether any arrows stuck in the player's model should be rendered - * - showElytra: Whether the player's Elytra should be rendered - * - showParrot: Whether a perched parrot should be rendered - * - showBeeStinger: Whether any stuck bee stingers should be rendered - * - * @param obj An options bag - */ - @JvmStatic - fun drawPlayer(obj: NativeObject) { - val entity = obj["player"].let { - it as? AbstractClientPlayerEntity - ?: ((it as? PlayerMP)?.toMC() as? AbstractClientPlayerEntity) - ?: Player.toMC() - ?: return - } - - val x = obj.getOrDefault("x", 0).toInt() - val y = obj.getOrDefault("y", 0).toInt() - val size = obj.getOrDefault("size", 20).toDouble() - val rotate = obj.getOrDefault("rotate", false) - val pitch = obj.getOrDefault("pitch", 0f).toFloat() - val yaw = obj.getOrDefault("yaw", 0f).toFloat() - val slim = obj.getOrDefault("slim", false) - val showNametag = obj.getOrDefault("showNametag", false) - val showArmor = obj.getOrDefault("showArmor", false) - val showCape = obj.getOrDefault("showCape", false) - val showHeldItem = obj.getOrDefault("showHeldItem", false) - val showArrows = obj.getOrDefault("showArrows", false) - val showElytra = obj.getOrDefault("showElytra", false) - val showParrot = obj.getOrDefault("showParrot", false) - val showStingers = obj.getOrDefault("showBeeStinger", false) - - matrixStack.push() - - val (entityYaw, entityPitch) = if (rotate) { - val mouseX = x - Client.getMouseX() - val mouseY = y - Client.getMouseY() - (entity.standingEyeHeight * size) - atan((mouseX / 40.0f)).toFloat() to atan((mouseY / 40.0f)).toFloat() - } else { - val scaleFactor = 130f / 180f - (yaw * scaleFactor).toRadians() to pitch.toRadians() - } - - val flipModelRotation = Quaternionf().rotateZ(Math.PI.toFloat()) - val pitchModelRotation = - Quaternionf().rotateX(entityPitch * 20.0f * (Math.PI / 180.0).toFloat()) - flipModelRotation.mul(pitchModelRotation) - - val oldBodyYaw = entity.bodyYaw - val oldYaw = entity.yaw - val oldPitch = entity.pitch - val oldPrevHeadYaw = entity.prevHeadYaw - val oldHeadYaw = entity.headYaw - - entity.bodyYaw = 180.0f + entityYaw * 20.0f - entity.yaw = 180.0f + entityYaw * 40.0f - entity.pitch = -entityPitch * 20.0f - entity.headYaw = entity.yaw - entity.prevHeadYaw = entity.yaw - - matrixStack.push() - matrixStack.translate(0.0, 0.0, 1000.0) - matrixStack.push() - matrixStack.translate(x.toDouble(), y.toDouble(), -950.0) - - // UC's version of multiplyPositionMatrix - matrixStack.peek().model.mul( - Matrix4f().scaling( - size.toFloat(), - size.toFloat(), - (-size).toFloat() - ) - ) - - matrixStack.multiply(flipModelRotation) - DiffuseLighting.method_34742() - - val entityRenderDispatcher = MinecraftClient.getInstance().entityRenderDispatcher - - if (pitchModelRotation != null) { - pitchModelRotation.conjugate() - entityRenderDispatcher.rotation = pitchModelRotation - } - - entityRenderDispatcher.setRenderShadows(false) - val vertexConsumers = MinecraftClient.getInstance().bufferBuilders.entityVertexConsumers - - val light = 0xf000f0 - - val entityRenderer = if (slim) slimCTRenderPlayer else normalCTRenderPlayer - entityRenderer.setOptions( - showNametag, - showArmor, - showCape, - showHeldItem, - showArrows, - showElytra, - showParrot, - showStingers - ) - - val vec3d = entityRenderer.getPositionOffset(entity, partialTicks) - val d = vec3d.getX() - val e = vec3d.getY() - val f = vec3d.getZ() - matrixStack.push() - matrixStack.translate(d, e, f) - RenderSystem.runAsFancy { - entityRenderer.render(entity, 0.0f, 1.0f, matrixStack.toMC(), vertexConsumers, light) - if (entity.doesRenderOnFire()) { - entityRenderDispatcher.asMixin() - .invokeRenderFire(matrixStack.toMC(), vertexConsumers, entity, Quaternionf()) - } - } - - matrixStack.pop() - - vertexConsumers.draw() - entityRenderDispatcher.setRenderShadows(true) - matrixStack.pop() - DiffuseLighting.enableGuiDepthLighting() - matrixStack.pop() - - entity.bodyYaw = oldBodyYaw - entity.yaw = oldYaw - entity.pitch = oldPitch - entity.prevHeadYaw = oldPrevHeadYaw - entity.headYaw = oldHeadYaw - - matrixStack.pop() - } - - internal fun withMatrix(stack: MatrixStack?, partialTicks: Float = Renderer.partialTicks, block: () -> Unit) { - Renderer.partialTicks = partialTicks - matrixPushCounter = 0 - - try { - if (stack != null) - pushMatrix(UMatrixStack(stack)) - - block() - } finally { - if (stack != null) - popMatrix() - } - - if (matrixPushCounter > 0) { - "Warning: Render function missing a call to Renderer.popMatrix()".printToConsole(LogType.WARN) - } else if (matrixPushCounter < 0) { - "Warning: Render function has too many calls to Renderer.popMatrix()".printToConsole(LogType.WARN) - } - } - - enum class DrawMode(private val ucValue: UGraphics.DrawMode) { - LINES(UGraphics.DrawMode.LINES), - LINE_STRIP(UGraphics.DrawMode.LINE_STRIP), - TRIANGLES(UGraphics.DrawMode.TRIANGLES), - TRIANGLE_STRIP(UGraphics.DrawMode.TRIANGLE_STRIP), - TRIANGLE_FAN(UGraphics.DrawMode.TRIANGLE_FAN), - QUADS(UGraphics.DrawMode.QUADS); - - fun toUC() = ucValue - - companion object { - @JvmStatic - fun fromUC(ucValue: UGraphics.DrawMode) = entries.first { it.ucValue == ucValue } - } - } - - enum class VertexFormat(private val mcValue: MCVertexFormat) { - LINES(VertexFormats.LINES), - POSITION(VertexFormats.POSITION), - POSITION_COLOR(VertexFormats.POSITION_COLOR), - POSITION_TEXTURE(VertexFormats.POSITION_TEXTURE), - POSITION_TEXTURE_COLOR(VertexFormats.POSITION_TEXTURE_COLOR), - POSITION_COLOR_TEXTURE_LIGHT(VertexFormats.POSITION_COLOR_TEXTURE_LIGHT), - POSITION_TEXTURE_LIGHT_COLOR(VertexFormats.POSITION_TEXTURE_LIGHT_COLOR), - POSITION_TEXTURE_COLOR_LIGHT(VertexFormats.POSITION_TEXTURE_COLOR_LIGHT), - POSITION_TEXTURE_COLOR_NORMAL(VertexFormats.POSITION_TEXTURE_COLOR_NORMAL); - - fun toMC() = mcValue - - companion object { - @JvmStatic - fun fromMC(ucValue: MCVertexFormat) = entries.first { it.mcValue == ucValue } - } - } - - class ScreenWrapper { - fun getWidth(): Int = UMinecraft.getMinecraft().window.scaledWidth - - fun getHeight(): Int = UMinecraft.getMinecraft().window.scaledHeight - - fun getScale(): Double = UMinecraft.getMinecraft().window.scaleFactor - } -} diff --git a/src/main/kotlin/com/chattriggers/ctjs/api/render/Renderer3d.kt b/src/main/kotlin/com/chattriggers/ctjs/api/render/Renderer3d.kt deleted file mode 100644 index c6c352df..00000000 --- a/src/main/kotlin/com/chattriggers/ctjs/api/render/Renderer3d.kt +++ /dev/null @@ -1,372 +0,0 @@ -package com.chattriggers.ctjs.api.render - -import com.chattriggers.ctjs.api.client.Client -import com.chattriggers.ctjs.api.client.Settings -import com.chattriggers.ctjs.api.vec.Vec3f -import com.chattriggers.ctjs.internal.utils.get -import com.mojang.blaze3d.systems.RenderSystem -import gg.essential.elementa.dsl.component1 -import gg.essential.elementa.dsl.component2 -import gg.essential.elementa.dsl.component3 -import gg.essential.elementa.dsl.component4 -import gg.essential.universal.UGraphics -import net.minecraft.client.MinecraftClient -import net.minecraft.client.font.TextRenderer -import net.minecraft.client.render.LightmapTextureManager -import net.minecraft.client.render.Tessellator -import net.minecraft.client.render.VertexConsumerProvider -import net.minecraft.client.render.VertexFormat -import org.joml.Vector3f -import org.lwjgl.opengl.GL11 -import org.mozilla.javascript.NativeObject -import java.awt.Color - -object Renderer3d { - private var firstVertex = true - private var began = false - - private val tessellator = Tessellator.getInstance() - private val worldRenderer = UGraphics.getFromTessellator() - - /** - * Begin drawing with the world renderer - * - * @param drawMode the GL draw mode - * @param vertexFormat The [VertexFormat] to use for drawing - * @return [Renderer3d] to allow for method chaining - * @see Renderer.DrawMode - */ - @JvmStatic - @JvmOverloads - fun begin( - drawMode: Renderer.DrawMode = Renderer.DrawMode.QUADS, - vertexFormat: Renderer.VertexFormat = Renderer.VertexFormat.POSITION, - ) = apply { - Renderer.pushMatrix() - .enableBlend() - .disableCull() - Renderer.tryBlendFuncSeparate(770, 771, 1, 0) - - worldRenderer.beginWithDefaultShader(drawMode.toUC(), vertexFormat.toMC()) - - firstVertex = true - began = true - } - - /** - * Sets a new vertex in the world renderer. - * - * @param x the x position - * @param y the y position - * @param z the z position - * @return [Renderer3d] to allow for method chaining - */ - @JvmStatic - fun pos(x: Float, y: Float, z: Float) = apply { - if (!began) - begin() - if (!firstVertex) - worldRenderer.endVertex() - val camera = Client.getMinecraft().gameRenderer.camera.pos - worldRenderer.pos(Renderer.matrixStack, x.toDouble() - camera.x, y.toDouble() - camera.y, z.toDouble() - camera.z) - firstVertex = false - } - - /** - * Sets the texture location on the last defined vertex. - * - * @param u the u position in the texture - * @param v the v position in the texture - * @return [Renderer3d] to allow for method chaining - */ - @JvmStatic - fun tex(u: Float, v: Float) = apply { - worldRenderer.tex(u.toDouble(), v.toDouble()) - } - - /** - * Sets the color for the last defined vertex. - * - * @param r the red value of the color, between 0 and 1 - * @param g the green value of the color, between 0 and 1 - * @param b the blue value of the color, between 0 and 1 - * @param a the alpha value of the color, between 0 and 1 - * @return [Renderer3d] to allow for method chaining - */ - @JvmStatic - @JvmOverloads - fun color(r: Float, g: Float, b: Float, a: Float = 1f) = apply { - worldRenderer.color(r, g, b, a) - } - - /** - * Sets the color for the last defined vertex. - * - * @param r the red value of the color, between 0 and 255 - * @param g the green value of the color, between 0 and 255 - * @param b the blue value of the color, between 0 and 255 - * @param a the alpha value of the color, between 0 and 255 - * @return [Renderer3d] to allow for method chaining - */ - @JvmStatic - @JvmOverloads - fun color(r: Int, g: Int, b: Int, a: Int = 255) = apply { - worldRenderer.color(r, g, b, a) - } - - /** - * Sets the color for the last defined vertex. - * - * @param color the color value, can use [Renderer.getColor] to get this - * @return [Renderer3d] to allow for method chaining - */ - @JvmStatic - fun color(color: Long) = apply { - val (r, g, b, a) = Color(color.toInt()) - color(r, g, b, a) - } - - /** - * Sets the normal of the vertex. This is mostly used with [Renderer.VertexFormat.LINES] - * - * @param x the x position of the normal vector - * @param y the y position of the normal vector - * @param z the z position of the normal vector - * @return [Renderer3d] to allow for method chaining - */ - @JvmStatic - fun normal(x: Float, y: Float, z: Float) = apply { - worldRenderer.norm(Renderer.matrixStack, x, y, z) - } - - /** - * Sets the overlay location on the last defined vertex. - * - * @param u the u position in the overlay - * @param v the v position in the overlay - * @return [Renderer3d] to allow for method chaining - */ - @JvmStatic - fun overlay(u: Int, v: Int) = apply { - worldRenderer.overlay(u, v) - } - - /** - * Sets the light location on the last defined vertex. - * - * @param u the u position in the light - * @param v the v position in the light - * @return [Renderer3d] to allow for method chaining - */ - @JvmStatic - fun light(u: Int, v: Int) = apply { - worldRenderer.light(u, v) - } - - /** - * Sets the line width when rendering [Renderer.DrawMode.LINES] - * - * @param width the width of the line - * @return [Renderer3d] to allow for method chaining - */ - @JvmStatic - fun lineWidth(width: Float) = apply { - RenderSystem.lineWidth(width) - } - - /** - * Finalizes vertices and draws the world renderer. - */ - @JvmStatic - fun draw() { - if (!began) - return - began = false - - worldRenderer.endVertex() - - worldRenderer.drawDirect() - Renderer.colorize(1f, 1f, 1f, 1f) - .disableBlend() - .enableCull() - .popMatrix() - } - - /** - * Renders floating lines of text in the 3D world at a specific position. - * This should be placed inside a `preRenderWorld` trigger. - * - * @param text The string array of text to render - * @param x X coordinate in the game world - * @param y Y coordinate in the game world - * @param z Z coordinate in the game world - * @param color the color of the text - * @param renderBlackBox render a pretty black border behind the text - * @param scale the scale of the text - * @param increase whether to scale the text up as the player moves away - * @param centered whether to center each line based on the longest line (this has no effect if there are no newline characters) - * @param renderThroughBlocks whether to render the text through blocks - */ - @JvmStatic - @JvmOverloads - fun drawString( - text: String, - x: Float, - y: Float, - z: Float, - color: Long = Renderer.colorized ?: Renderer.WHITE, - renderBlackBox: Boolean = true, - scale: Float = 1f, - increase: Boolean = false, - centered: Boolean = true, - renderThroughBlocks: Boolean = true, - ) { - val (lines, width, height) = Renderer.splitText(text) - - val fontRenderer = Renderer.getFontRenderer() - val camera = Client.getMinecraft().gameRenderer.camera - val renderPos = Vec3f( - x - camera.pos.x.toFloat(), - y - camera.pos.y.toFloat(), - z - camera.pos.z.toFloat(), - ) - - val lScale = scale * if (increase) { - renderPos.magnitude() / 120f //mobs only render ~120 blocks away - } else { - 0.025f - } - - Renderer.pushMatrix() - Renderer.translate(renderPos.x, renderPos.y, renderPos.z) - Renderer.multiply(camera.rotation) - Renderer.scale(-lScale, -lScale, lScale) - - if (renderThroughBlocks) { - Renderer.depthMask(true) - Renderer.depthFunc(GL11.GL_ALWAYS) - RenderSystem.clear(GL11.GL_DEPTH_BUFFER_BIT, MinecraftClient.IS_SYSTEM_MAC) - } - - val opacity = (Settings.toMC().getTextBackgroundOpacity(0.25f) * 255).toInt() shl 24 - - val xShift = -width / 2 - val yShift = -height / 2 - - val vertexConsumers = Client.getMinecraft().bufferBuilders.entityVertexConsumers - var yOffset = 0 - - for (line in lines) { - val centerShift = if (centered) { - xShift + (fontRenderer.getWidth(line) / 2f) - } else 0f - - Renderer.pushMatrix() - val matrix = Renderer.matrixStack.toMC().peek().positionMatrix - - if (renderBlackBox) { - fontRenderer.draw( - line, - xShift - centerShift, - yShift + yOffset, - 0x20FFFFFF, - false, - matrix, - vertexConsumers, - TextRenderer.TextLayerType.NORMAL, - opacity, - LightmapTextureManager.MAX_LIGHT_COORDINATE - ) - Renderer.translate(0f, 0f, -0.03f) - } - - fontRenderer.draw( - line, - xShift - centerShift, - yShift + yOffset, - color.toInt(), - false, - matrix, - vertexConsumers, - TextRenderer.TextLayerType.NORMAL, - 0, - LightmapTextureManager.MAX_LIGHT_COORDINATE - ) - vertexConsumers.draw() - Renderer.popMatrix() - - yOffset += fontRenderer.fontHeight + 1 - } - - if (renderThroughBlocks) { - Renderer.depthFunc(GL11.GL_LEQUAL) - } - Renderer.popMatrix() - } - - /** - * A variant of drawString that takes an object instead of positional parameters - */ - @JvmStatic - fun drawString(obj: NativeObject) { - drawString( - obj.get("text") ?: error("Expected \"text\" property in object passed to Renderer3d.drawString"), - obj.get("x")?.toFloat() - ?: error("Expected \"x\" property in object passed to Renderer3d.drawString"), - obj.get("y")?.toFloat() - ?: error("Expected \"y\" property in object passed to Renderer3d.drawString"), - obj.get("z")?.toFloat() - ?: error("Expected \"z\" property in object passed to Renderer3d.drawString"), - obj.get("color")?.toLong() ?: Renderer.colorized ?: Renderer.WHITE, - obj.get("renderBlackBox") ?: true, - obj.get("scale")?.toFloat() ?: 1f, - obj.get("increase") ?: false, - obj.get("centered") ?: true, - obj.get("renderThroughBlocks") ?: true, - ) - } - - /** - * Draws a line in the world from (x1, y1, z1) to (x2, y2, z2) - * - * @param color the color of the line - * @param x1 the starting x coordinate - * @param y1 the starting y coordinate - * @param z1 the starting z coordinate - * @param x2 the ending x coordinate - * @param y2 the ending y coordinate - * @param z2 the ending z coordinate - * @param thickness how thick the line should be - */ - @JvmStatic - fun drawLine( - color: Long, - x1: Float, - y1: Float, - z1: Float, - x2: Float, - y2: Float, - z2: Float, - thickness: Float, - ) { - Renderer.pushMatrix() - .disableDepth() - .disableCull() - RenderSystem.lineWidth(thickness) - - val (r, g, b, a) = Color(color.toInt(), true) - - val normalVec = Vector3f(x2 - x1, y2 - y1, z2 - z1).normalize() - - begin(Renderer.DrawMode.LINES, Renderer.VertexFormat.LINES) - pos(x1, y1, z1).color(r, g, b, a).normal(normalVec.x, normalVec.y, normalVec.z) - pos(x2, y2, z2).color(r, g, b, a).normal(normalVec.x, normalVec.y, normalVec.z) - draw() - - RenderSystem.lineWidth(1f) - Renderer - .enableCull() - .enableDepth() - .popMatrix() - } -} diff --git a/src/main/kotlin/com/chattriggers/ctjs/api/render/Shape.kt b/src/main/kotlin/com/chattriggers/ctjs/api/render/Shape.kt deleted file mode 100644 index 16514df0..00000000 --- a/src/main/kotlin/com/chattriggers/ctjs/api/render/Shape.kt +++ /dev/null @@ -1,128 +0,0 @@ -package com.chattriggers.ctjs.api.render - -import com.chattriggers.ctjs.api.vec.Vec2f -import kotlin.math.PI -import kotlin.math.atan2 -import kotlin.math.cos -import kotlin.math.sin - -class Shape(private var color: Long) { - private val vertexes = mutableListOf() - private val reversedVertexes = vertexes.asReversed() - private var drawMode = Renderer.DrawMode.QUADS - private var area = 0f - - fun copy(): Shape = clone() - - fun clone(): Shape { - val clone = Shape(color) - clone.vertexes.addAll(vertexes) - clone.setDrawMode(drawMode) - return clone - } - - fun getColor(): Long = color - - fun setColor(color: Long) = apply { this.color = Renderer.fixAlpha(color) } - - fun getDrawMode(): Renderer.DrawMode = drawMode - - /** - * Sets the GL draw mode of the shape - */ - fun setDrawMode(drawMode: Renderer.DrawMode) = apply { this.drawMode = drawMode } - - fun getVertexes(): List = vertexes - - fun addVertex(x: Float, y: Float) = apply { - vertexes.add(Vec2f(x, y)) - updateArea() - } - - fun insertVertex(index: Int, x: Float, y: Float) = apply { - vertexes.add(index, Vec2f(x, y)) - updateArea() - } - - fun removeVertex(index: Int) = apply { - vertexes.removeAt(index) - updateArea() - } - - fun clearVertices() = apply { - vertexes.clear() - area = 0f - } - - /** - * Sets the shape as a line pointing from [x1, y1] to [x2, y2] with a thickness - */ - fun setLine(x1: Float, y1: Float, x2: Float, y2: Float, thickness: Float) = apply { - vertexes.clear() - - val theta = -atan2(y2 - y1, x2 - x1) - val i = sin(theta) * (thickness / 2) - val j = cos(theta) * (thickness / 2) - - addVertex(x1 + i, y1 + j) - addVertex(x2 + i, y2 + j) - addVertex(x2 - i, y2 - j) - addVertex(x1 - i, y1 - j) - - drawMode = Renderer.DrawMode.QUADS - } - - /** - * Sets the shape as a circle with a center at [x, y] - * with radius and number of steps around the circle - */ - fun setCircle(x: Float, y: Float, radius: Float, steps: Int) = apply { - vertexes.clear() - - val theta = 2 * PI / steps - val cos = cos(theta).toFloat() - val sin = sin(theta).toFloat() - - var xHolder: Float - var circleX = 1f - var circleY = 0f - - for (i in 0..steps) { - addVertex(x, y) - addVertex(circleX * radius + x, circleY * radius + y) - xHolder = circleX - circleX = cos * circleX - sin * circleY - circleY = sin * xHolder + cos * circleY - addVertex(circleX * radius + x, circleY * radius + y) - } - - drawMode = Renderer.DrawMode.TRIANGLE_STRIP - } - - fun draw() = apply { - Renderer.apply { - begin(drawMode, Renderer.VertexFormat.POSITION_COLOR) - - if (area < 0) { - vertexes.forEach { pos(it.x, it.y).color(color) } - } else { - reversedVertexes.forEach { pos(it.x, it.y).color(color) } - } - - draw() - } - } - - private fun updateArea() { - area = 0f - - for (i in vertexes.indices) { - val p1 = vertexes[i] - val p2 = vertexes[(i + 1) % vertexes.size] - - area += p1.x * p2.y - p2.x * p1.y - } - - area /= 2 - } -} diff --git a/src/main/kotlin/com/chattriggers/ctjs/api/render/Text.kt b/src/main/kotlin/com/chattriggers/ctjs/api/render/Text.kt deleted file mode 100644 index 106403b1..00000000 --- a/src/main/kotlin/com/chattriggers/ctjs/api/render/Text.kt +++ /dev/null @@ -1,218 +0,0 @@ -package com.chattriggers.ctjs.api.render - -import com.chattriggers.ctjs.api.message.ChatLib -import com.chattriggers.ctjs.internal.utils.getOption -import net.minecraft.text.Style -import org.mozilla.javascript.NativeObject - -class Text { - private lateinit var string: String - private var x: Float = 0f - private var y: Float = 0f - - private val lines = mutableListOf() - - private var color = 0xffffffff - private var backgroundColor = 0xff000000 - private var formatted = true - private var shadow = false - private var align = Align.LEFT - private var background = false - - private var width = 0f - private var maxWidth = 0 - private var maxLines = Int.MAX_VALUE - private var scale = 1f - - @JvmOverloads - constructor(string: String, x: Float = 0f, y: Float = 0f) { - setString(string) - setX(x) - setY(y) - } - - constructor(string: String, config: NativeObject) { - setString(string) - setColor(config.getOption("color", 0xffffffff).toLong()) - setFormatted(config.getOption("formatted", true).toBoolean()) - setShadow(config.getOption("shadow", false).toBoolean()) - setAlign(config.getOption("align", Align.LEFT)) - setBackground(config.getOption("background", false).toBoolean()) - setBackgroundColor(config.getOption("backgroundColor", 0x00000000).toLong()) - setX(config.getOption("x", 0f).toFloat()) - setY(config.getOption("y", 0f).toFloat()) - setMaxLines((config.getOption("maxLines", Int.MAX_VALUE)).toDouble().toInt()) - setScale(config.getOption("scale", 1f).toFloat()) - setMaxWidth(config.getOption("maxWidth", 0).toInt()) - } - - fun getString(): String = string - - fun setString(string: String) = apply { - this.string = string - updateFormatting() - } - - fun getColor(): Long = color - - fun setColor(color: Long) = apply { this.color = Renderer.fixAlpha(color) } - - fun getFormatted(): Boolean = formatted - - fun setFormatted(formatted: Boolean) = apply { - this.formatted = formatted - updateFormatting() - } - - fun getShadow(): Boolean = shadow - - fun setShadow(shadow: Boolean) = apply { this.shadow = shadow } - - fun getAlign(): Align = align - - fun setAlign(align: Any) = apply { - this.align = when (align) { - is CharSequence -> Align.valueOf(align.toString().uppercase()) - is Align -> align - else -> Align.LEFT - } - } - - fun getBackground(): Boolean = background - - /** - * Set the background - * - * true: Background is enabled - * false: Background is disabled - */ - fun setBackground(background: Boolean) = apply { - this.background = background - } - - fun getBackgroundColor(): Long = backgroundColor - - fun setBackgroundColor(backgroundColor: Long) = apply { - this.backgroundColor = backgroundColor - } - - fun getX(): Float = x - - fun setX(x: Float) = apply { this.x = x } - - fun getY(): Float = y - - fun setY(y: Float) = apply { this.y = y } - - /** - * Gets the width of the text - * This is automatically updated when the text is drawn. - * - * @return the width of the text - */ - fun getWidth(): Float = width - - fun getLines(): List = lines - - fun getMaxLines(): Int = maxLines - - fun setMaxLines(maxLines: Int) = apply { this.maxLines = maxLines } - - fun getScale(): Float = scale - - fun setScale(scale: Float) = apply { this.scale = scale } - - /** - * Sets the maximum width of the text, splitting it into multiple lines if necessary. - * - * @param maxWidth the maximum width of the text - * @return the Text object for method chaining - */ - fun setMaxWidth(maxWidth: Int) = apply { - this.maxWidth = maxWidth - updateFormatting() - } - - fun getMaxWidth(): Int = maxWidth - - fun getHeight(): Float { - return if (lines.size > 1) - lines.size.coerceAtMost(maxLines) * scale * 10 - else scale * 10 - } - - fun exceedsMaxLines(): Boolean { - return lines.size > maxLines - } - - @JvmOverloads - fun draw(x: Float? = null, y: Float? = null) = apply { - draw(x, y, null, null) - } - - internal fun draw(x: Float? = null, y: Float? = null, backgroundX: Float? = null, backgroundWidth: Float? = null) = - apply { - Renderer.pushMatrix() - Renderer.enableBlend() - Renderer.scale(scale, scale, scale) - - var longestLine = lines.maxOf { Renderer.getStringWidth(it) * scale } - if (maxWidth != 0) - longestLine = longestLine.coerceAtMost(maxWidth.toFloat()) - width = longestLine - - var yHolder = y ?: this.y - - val xHolder = when (align) { - Align.CENTER -> (x ?: this.x) - width / 2 - Align.RIGHT -> (x ?: this.x) - width - else -> x ?: this.x - } - - if (background) - Renderer.drawRect( - backgroundColor, - backgroundX ?: xHolder, - yHolder, - backgroundWidth ?: width, - getHeight() - ) - - for (i in 0 until maxLines) { - if (i >= lines.size) break - Renderer.drawString(lines[i], xHolder, yHolder, color, shadow) - yHolder += scale * 10 - } - Renderer.disableBlend() - Renderer.popMatrix() - } - private fun updateFormatting() { - string = - if (formatted) ChatLib.addColor(string) - else ChatLib.replaceFormatting(string) - - lines.clear() - - string.split("\n").forEach { line -> - if (maxWidth > 0) { - lines.addAll( - Renderer.getFontRenderer().textHandler.wrapLines(line, maxWidth, Style.EMPTY).map { it.string } - ) - } else { - lines.add(line) - } - } - } - - override fun toString() = - "Text{" + - "string=$string, x=$x, y=$y, " + - "lines=$lines, color=$color, scale=$scale, " + - "formatted=$formatted, shadow=$shadow, " + //align=$align, " + - "width=$width, maxWidth=$maxWidth, maxLines=$maxLines" + - "}" - - enum class Align { - LEFT, CENTER, RIGHT - } -} diff --git a/src/main/kotlin/com/chattriggers/ctjs/api/render/Toast.kt b/src/main/kotlin/com/chattriggers/ctjs/api/render/Toast.kt deleted file mode 100644 index 6edf6a9b..00000000 --- a/src/main/kotlin/com/chattriggers/ctjs/api/render/Toast.kt +++ /dev/null @@ -1,144 +0,0 @@ -package com.chattriggers.ctjs.api.render - -import com.chattriggers.ctjs.api.client.Client -import com.chattriggers.ctjs.api.message.TextComponent -import com.chattriggers.ctjs.engine.printTraceToConsole -import com.chattriggers.ctjs.internal.engine.JSLoader -import com.chattriggers.ctjs.internal.utils.getOrNull -import com.chattriggers.ctjs.internal.utils.toIdentifier -import com.mojang.blaze3d.systems.RenderSystem -import net.minecraft.client.gui.DrawContext -import net.minecraft.client.toast.ToastManager -import net.minecraft.util.Identifier -import org.mozilla.javascript.* -import net.minecraft.client.toast.Toast - -// https://github.com/Edgeburn/Toasts -/** - * Displays a toast in the top left corner similar to the MC advancement toast - * - * Object properties that can be passed to the constructor: - * - title: A TextComponent (or anything that can be passed to the TextComponent constructor) - * - description: A TextComponent (or anything that can be passed to the TextComponent constructor) - * - background: An Image or a String/Identifier that points to a texture. Defaults to the advancement background - * - icon: An Image or a String/Identifier that points to a texture - * - width: The width of the toast, defaults to 160 - * - height: The height of the toast, defaults to 32 - * - displayTime: The time in ms the toast will be displayed, defaults to 5000 - * - render: An optional function that will be called to render the toast. By default, it renders the same - * way that advancement toasts do. If this function is called, it will not render anything by default. - * It takes no parameters and is called with the Toast object as its receiver. - */ -class Toast(config: NativeObject) : Toast { - private var titleBacker: TextComponent? = null - var title: Any? - get() = titleBacker - set(value) { titleBacker = value?.let { TextComponent(it) } } - - private var descriptionBacker: TextComponent? = null - var description: Any? - get() = descriptionBacker - set(value) { descriptionBacker = value?.let { TextComponent(it) } } - - private var backgroundBacker: Identifier? = Identifier.ofVanilla("toast/advancement") - var background: Any? - get() = backgroundBacker - set(value) { backgroundBacker = toIdentifier(value) } - - private var iconBacker: Identifier? = null - var icon: Any? - get() = iconBacker - set(value) { iconBacker = toIdentifier(value) } - - private var toastWidth = config.getOrNull("width")?.let { - require(it is Number) { "Toast \"width\" must be a number" } - it.toInt() - } ?: super.getWidth() - - private var toastHeight = config.getOrNull("height")?.let { - require(it is Number) { "Toast \"height\" must be a number" } - it.toInt() - } ?: super.getHeight() - - var displayTime = config.getOrNull("displayTime")?.let { - require(it is Number) { "Toast \"displayTime\" must be a number" } - it.toLong() - } ?: 5000L - - private var customRenderFunction = config.getOrNull("render")?.let { - check(it is Callable) { "Toast \"render\" function must be undefined or callable" } - it - } - private val jsReceiver = if (customRenderFunction != null) { - Context.javaToJS(this, Context.getContext().topCallScope) as Scriptable - } else null - - init { - title = config.getOrNull("title") - description = config.getOrNull("description") - background = config.getOrDefault("background", backgroundBacker) - icon = config.getOrNull("icon") - } - - override fun getWidth() = toastWidth - override fun getHeight() = toastHeight - - fun show() = apply { - Client.getMinecraft().toastManager.add(this) - } - - override fun draw(context: DrawContext, manager: ToastManager, startTime: Long): Toast.Visibility { - if (customRenderFunction != null) { - Renderer.withMatrix(context.matrices) { - try { - JSLoader.invoke(customRenderFunction!!, emptyArray(), thisObj = jsReceiver!!) - } catch (e: Throwable) { - e.printTraceToConsole() - - // If the method threw, don't invoke it again - customRenderFunction = Callable { _, _, _, _ -> Undefined.instance } - } - } - } else { - backgroundBacker?.let { - RenderSystem.setShaderColor(1.0f, 1.0f, 1.0f, 1.0f) - context.drawTexture(it, 0, 0, 0.0f, 0.0f, width, height, width, height) - } - - iconBacker?.let { - RenderSystem.setShaderColor(1.0f, 1.0f, 1.0f, 1.0f) - val iconSize = height - ICON_PADDING * 2 - context.drawTexture(it, ICON_PADDING, ICON_PADDING, 0.0f, 0.0f, iconSize, iconSize, iconSize, iconSize) - } - - val textX = if (icon == null) ICON_PADDING else height - var textY = ICON_PADDING - val textRenderer = Client.getMinecraft().textRenderer - - titleBacker?.let { - context.drawText(textRenderer, it, textX, textY, 0xffffff, false) - textY += textRenderer.fontHeight + 1 - } - - descriptionBacker?.let { - context.drawText(textRenderer, it, textX, textY, 0xffffff, false) - } - } - - return if (startTime > displayTime) Toast.Visibility.HIDE else Toast.Visibility.SHOW - } - - private companion object { - private const val ICON_PADDING = 7 - - private fun toIdentifier(value: Any?): Identifier? = when (value) { - is Image -> value.getIdOrRegister() - is CharSequence -> value.toString().toIdentifier() - is Identifier -> value - null -> null - else -> throw IllegalArgumentException( - "Toast \"background\" must be an Image or a string corresponding to a resource identifier" - ) - } - } -} diff --git a/src/main/kotlin/com/chattriggers/ctjs/api/triggers/ChatTrigger.kt b/src/main/kotlin/com/chattriggers/ctjs/api/triggers/ChatTrigger.kt deleted file mode 100644 index 7f284d08..00000000 --- a/src/main/kotlin/com/chattriggers/ctjs/api/triggers/ChatTrigger.kt +++ /dev/null @@ -1,262 +0,0 @@ -package com.chattriggers.ctjs.api.triggers - -import com.chattriggers.ctjs.api.message.TextComponent -import org.mozilla.javascript.regexp.NativeRegExp - -class ChatTrigger(method: Any, type: ITriggerType) : Trigger(method, type) { - private lateinit var chatCriteria: Any - private var formatted: Boolean = false - private var formattedForced = false - private var caseInsensitive: Boolean = false - private lateinit var criteriaPattern: Regex - private val parameters = mutableListOf() - private var triggerIfCanceled: Boolean = true - - /** - * Sets if the chat trigger should run if the chat event has already been canceled. - * True by default. - * @param bool Boolean to set - * @return the trigger object for method chaining - */ - fun triggerIfCanceled(bool: Boolean) = apply { triggerIfCanceled = bool } - - /** - * Sets the chat criteria for [matchesChatCriteria]. - * Arguments for the trigger's method can be passed in using ${variable}. - * Example: `setChatCriteria("<${name}> ${message}");` - * Use ${*} to match a chat message but ignore the pass through. - * @param chatCriteria the chat criteria to set - * @return the trigger object for method chaining - */ - fun setChatCriteria(chatCriteria: Any) = apply { - this.chatCriteria = chatCriteria - val flags = mutableSetOf() - var source = ".+" - - when (chatCriteria) { - is CharSequence -> { - if (!formattedForced) - formatted = Regex("[&\u00a7]") in chatCriteria - - val replacedCriteria = Regex.escape(chatCriteria.toString().replace("\n", "->newLine<-")) - .replace(Regex("\\\$\\{[^*]+?}"), "\\\\E(.+)\\\\Q") - .replace(Regex("\\$\\{\\*?}"), "\\\\E(?:.+)\\\\Q") - - if (caseInsensitive) - flags.add(RegexOption.IGNORE_CASE) - - if ("" != chatCriteria) - source = replacedCriteria - } - is NativeRegExp -> { - if (chatCriteria["ignoreCase"] as Boolean || caseInsensitive) - flags.add(RegexOption.IGNORE_CASE) - - if (chatCriteria["multiline"] as Boolean) - flags.add(RegexOption.MULTILINE) - - source = (chatCriteria["source"] as String).let { - if ("" == it) ".+" else it - } - - if (!formattedForced) - formatted = Regex("[&\u00a7]") in source - } - else -> throw IllegalArgumentException("Expected String or Regexp Object") - } - - criteriaPattern = Regex(source, flags) - } - - /** - * Alias for [setChatCriteria]. - * @param chatCriteria the chat criteria to set - * @return the trigger object for method chaining - */ - fun setCriteria(chatCriteria: Any) = setChatCriteria(chatCriteria) - - /** - * Sets the chat parameter for [Parameter]. - * Clears current parameter list. - * @param parameter the chat parameter to set - * @return the trigger object for method chaining - */ - fun setParameter(parameter: String) = apply { - parameters.clear() - addParameter(parameter) - } - - /** - * Sets multiple chat parameters for [Parameter]. - * Clears current parameter list. - * @param parameters the chat parameters to set - * @return the trigger object for method chaining - */ - fun setParameters(vararg parameters: String) = apply { - this.parameters.clear() - addParameters(*parameters) - } - - /** - * Adds chat parameter for [Parameter]. - * @param parameter the chat parameter to add - * @return the trigger object for method chaining - */ - fun addParameter(parameter: String) = apply { - parameters.add(Parameter.getParameterByName(parameter)) - } - - /** - * Adds multiple chat parameters for [Parameter]. - * @param parameters the chat parameters to add - * @return the trigger object for method chaining - */ - fun addParameters(vararg parameters: String) = apply { - parameters.forEach(::addParameter) - } - - /** - * Adds the "start" parameter - * @return the trigger object for method chaining - */ - fun setStart() = apply { - setParameter("start") - } - - /** - * Adds the "contains" parameter - * @return the trigger object for method chaining - */ - fun setContains() = apply { - setParameter("contains") - } - - /** - * Adds the "end" parameter - * @return the trigger object for method chaining - */ - fun setEnd() = apply { - setParameter("end") - } - - /** - * Forces this trigger to be formatted or unformatted. If no argument is - * provided, it will be set to formatted. This method overrides the - * behavior of inferring the formatted status from the criteria. - */ - @JvmOverloads - fun setFormatted(formatted: Boolean = true) { - this.formatted = formatted - this.formattedForced = true - } - - /** - * Makes the trigger match the entire chat message - * @return the trigger object for method chaining - */ - fun setExact() = apply { - parameters.clear() - } - - /** - * Makes the chat criteria case insensitive - * @return the trigger object for method chaining - */ - fun setCaseInsensitive() = apply { - caseInsensitive = true - - // Reparse criteria if setCriteria has already been called - if (::chatCriteria.isInitialized) - setCriteria(chatCriteria) - } - - /** - * Argument 1 (String) The chat message received - * Argument 2 (ClientChatReceivedEvent) the chat event fired - * @param args list of arguments as described - */ - override fun trigger(args: Array) { - require(args[0] is Event) { - "Argument 1 must be a ChatTrigger.Event" - } - - val chatEvent = args[0] as Event - - if (!triggerIfCanceled && chatEvent.isCancelled()) return - - val chatMessage = getChatMessage(chatEvent.message) - - val variables = getVariables(chatMessage) ?: return - variables.add(chatEvent) - - callMethod(variables.toTypedArray()) - } - - // helper method to get the proper chat message based on the presence of color codes - private fun getChatMessage(chatMessage: TextComponent) = - if (formatted) - chatMessage.formattedText.replace("\u00a7", "&") - else chatMessage.unformattedText - - // helper method to get the variables to pass through - private fun getVariables(chatMessage: String) = - if (::criteriaPattern.isInitialized) - matchesChatCriteria(chatMessage.replace("\n", "->newLine<-")) - else ArrayList() - - /** - * A method to check whether a received chat message - * matches this trigger's definition criteria. - * Ex. "FalseHonesty joined Cops vs Crims" would match `${playername} joined ${gamejoined}` - * @param chat the chat message to compare against - * @return a list of the variables, in order or null if it doesn't match - */ - private fun matchesChatCriteria(chat: String): MutableList? { - val regex = criteriaPattern - - if (parameters.isEmpty()) { - if (!(regex matches chat)) return null - } else { - parameters.forEach { parameter -> - val first = try { - regex.find(chat)?.groups?.get(0) - } catch (e: IndexOutOfBoundsException) { - return null - } - - when (parameter) { - Parameter.CONTAINS -> if (first == null) return null - Parameter.START -> if (first == null || first.range.first != 0) return null - Parameter.END -> if (first?.range?.last != chat.length) return null - null -> if (!(regex matches chat)) return null - } - } - } - - return regex.find(chat)?.groupValues?.drop(1)?.toMutableList() - } - - /** - * The parameter to match chat criteria to. - * Location parameters - * - contains - * - start - * - end - */ - private enum class Parameter(vararg names: String) { - CONTAINS("", "", "c", "contains"), - START("", "", "s", "start"), - END("", "", "e", "end"); - - var names: List = names.asList() - - companion object { - fun getParameterByName(name: String) = - entries.find { param -> - param.names.any { it.lowercase() == name } - } - } - } - - class Event(@JvmField val message: TextComponent) : CancellableEvent() -} diff --git a/src/main/kotlin/com/chattriggers/ctjs/api/triggers/ClassFilterTrigger.kt b/src/main/kotlin/com/chattriggers/ctjs/api/triggers/ClassFilterTrigger.kt deleted file mode 100644 index 6e36a18e..00000000 --- a/src/main/kotlin/com/chattriggers/ctjs/api/triggers/ClassFilterTrigger.kt +++ /dev/null @@ -1,74 +0,0 @@ -package com.chattriggers.ctjs.api.triggers - -import com.chattriggers.ctjs.api.entity.BlockEntity -import com.chattriggers.ctjs.api.entity.Entity -import com.chattriggers.ctjs.MCBlockEntity -import com.chattriggers.ctjs.MCEntity -import net.minecraft.network.packet.Packet - -sealed class ClassFilterTrigger( - method: Any, - private val triggerType: ITriggerType, - private val wrappedClass: Class, -) : Trigger(method, triggerType) { - private var triggerClasses: List> = emptyList() - - /** - * Alias for `setFilteredClasses([A.class])` - * - * @param clazz The class for which this trigger should run for - */ - fun setFilteredClass(clazz: Class) = setFilteredClasses(listOf(clazz)) - - /** - * Sets which classes this trigger should run for. If the list is empty, it runs - * for every class. - * - * @param classes The classes for which this trigger should run for - * @return This trigger object for chaining - */ - fun setFilteredClasses(classes: List>) = apply { triggerClasses = classes } - - override fun trigger(args: Array) { - val placeholder = evalTriggerType(args) - if (triggerClasses.isEmpty() || triggerClasses.any { it.isInstance(placeholder) }) - callMethod(args) - } - - private fun evalTriggerType(args: Array): Unwrapped { - val arg = args.getOrNull(0) ?: error("First argument of $triggerType trigger can not be null") - - check(wrappedClass.isInstance(arg)) { - "Expected first argument of $triggerType trigger to be instance of $wrappedClass" - } - - @Suppress("UNCHECKED_CAST") - return unwrap(arg as Wrapped) - } - - protected abstract fun unwrap(wrapped: Wrapped): Unwrapped -} - -class RenderEntityTrigger(method: Any) : ClassFilterTrigger( - method, - TriggerType.RENDER_ENTITY, - Entity::class.java, -) { - override fun unwrap(wrapped: Entity): MCEntity = wrapped.toMC() -} - -class RenderBlockEntityTrigger(method: Any) : ClassFilterTrigger( - method, - TriggerType.RENDER_BLOCK_ENTITY, - BlockEntity::class.java -) { - override fun unwrap(wrapped: BlockEntity): MCBlockEntity = wrapped.toMC() -} - -class PacketTrigger(method: Any, triggerType: ITriggerType) : ClassFilterTrigger, Packet<*>>( - method, - triggerType, - Packet::class.java, -) { - override fun unwrap(wrapped: Packet<*>): Packet<*> = wrapped -} diff --git a/src/main/kotlin/com/chattriggers/ctjs/api/triggers/CommandTrigger.kt b/src/main/kotlin/com/chattriggers/ctjs/api/triggers/CommandTrigger.kt deleted file mode 100644 index e627030a..00000000 --- a/src/main/kotlin/com/chattriggers/ctjs/api/triggers/CommandTrigger.kt +++ /dev/null @@ -1,99 +0,0 @@ -package com.chattriggers.ctjs.api.triggers - -import com.chattriggers.ctjs.internal.commands.Command -import com.chattriggers.ctjs.internal.commands.StaticCommand - -class CommandTrigger(method: Any) : Trigger(method, TriggerType.COMMAND) { - private lateinit var commandName: String - private var overrideExisting: Boolean = false - private val staticCompletions = mutableListOf() - private val aliases = mutableSetOf() - private var command: Command? = null - private var dynamicCompletions: ((List) -> List)? = null - - override fun trigger(args: Array) { - callMethod(args) - } - - /** - * Sets the tab completion options for the command. - * This method must be used before setting the command name, otherwise, the tab completions will not be set. - * - * @param args all the tab completion options. - */ - fun setTabCompletions(vararg args: String) = apply { - staticCompletions.clear() - staticCompletions.addAll(args) - } - - /** - * This sets the possible tab completions for the command. - * This method must be used before setting the command name, otherwise, the tab completions will not be set. - * - * @param callback the callback that returns the tab completion options. - * - * For example: - * ```js - * register("command", () => { - * - * }).setTabCompletions((args) => { - * return ["option1", "option2"]; - * }).setName("test"); - *``` - * The `args` parameter of the callback are the arguments currently passed to the command. - * For instance, if you want to not show the options after the user tabs the first time, just add a check - * for the length of the arguments and return an empty array. - * - * The return value of the callback **must be an array of strings**, and in this case will always return the 2 - * options in the array. - */ - fun setTabCompletions(callback: (List) -> List) = apply { - this.dynamicCompletions = callback - } - - /** - * Sets the aliases for the command. - * - * @param args all the aliases. - */ - fun setAliases(vararg args: String) = apply { - check(::commandName.isInitialized) { "Command name must be set before aliases!" } - - aliases.clear() - aliases.addAll(args) - reInstance() - } - - /** - * Sets the command name. - * Example: - * setCommandName("test") - * would result in the command being /test - * - * @param commandName The command name - * @param overrideExisting Whether existing commands with the same name should be overridden - * @return the trigger for additional modification - */ - @JvmOverloads - fun setCommandName(commandName: String, overrideExisting: Boolean = false) = apply { - this.commandName = commandName - this.overrideExisting = overrideExisting - reInstance() - } - - /** - * Alias for [setCommandName] - * - * @param commandName The command name - * @param overrideExisting Whether existing commands with the same name should be overridden - * @return the trigger for additional modification - */ - @JvmOverloads - fun setName(commandName: String, overrideExisting: Boolean = false) = setCommandName(commandName, overrideExisting) - - private fun reInstance() { - command?.let(StaticCommand::unregister) - command = StaticCommand(this, commandName, aliases, overrideExisting, staticCompletions, dynamicCompletions) - StaticCommand.register(command!!) - } -} diff --git a/src/main/kotlin/com/chattriggers/ctjs/api/triggers/SoundPlayTrigger.kt b/src/main/kotlin/com/chattriggers/ctjs/api/triggers/SoundPlayTrigger.kt deleted file mode 100644 index d8c2e8d4..00000000 --- a/src/main/kotlin/com/chattriggers/ctjs/api/triggers/SoundPlayTrigger.kt +++ /dev/null @@ -1,24 +0,0 @@ -package com.chattriggers.ctjs.api.triggers - - -class SoundPlayTrigger(method: Any) : Trigger(method, TriggerType.SOUND_PLAY) { - private var soundNameCriteria = "" - - /** - * Sets the sound name criteria. - * - * @param soundNameCriteria the sound name - * @return the trigger for method chaining - */ - fun setCriteria(soundNameCriteria: String) = apply { this.soundNameCriteria = soundNameCriteria } - - override fun trigger(args: Array) { - if (args[1] is CharSequence - && soundNameCriteria != "" - && !args[1].toString().equals(soundNameCriteria, ignoreCase = true) - ) - return - - callMethod(args) - } -} diff --git a/src/main/kotlin/com/chattriggers/ctjs/api/triggers/StepTrigger.kt b/src/main/kotlin/com/chattriggers/ctjs/api/triggers/StepTrigger.kt deleted file mode 100644 index c858c7a8..00000000 --- a/src/main/kotlin/com/chattriggers/ctjs/api/triggers/StepTrigger.kt +++ /dev/null @@ -1,53 +0,0 @@ -package com.chattriggers.ctjs.api.triggers - -import com.chattriggers.ctjs.api.client.Client - -class StepTrigger(method: Any) : Trigger(method, TriggerType.STEP) { - private var fps: Long = 60L - private var delay: Long = -1 - private var systemTime: Long = Client.getSystemTime() - private var elapsed: Long = 0L - - /** - * Sets the frames per second that the trigger activates. - * This has a maximum one step per second. - * @param fps the frames per second to set - * @return the trigger for method chaining - */ - fun setFps(fps: Long) = apply { - this.fps = if (fps < 1) 1L else fps - systemTime = Client.getSystemTime() + 1000 / this.fps - } - - /** - * Sets the delay in seconds between the trigger activation. - * This has a minimum of one step every second. This will override [setFps]. - * @param delay The delay in seconds - * @return the trigger for method chaining - */ - fun setDelay(delay: Long) = apply { - this.delay = if (delay < 1) 1L else delay - systemTime = Client.getSystemTime() - this.delay * 1000 - } - - override fun register(): Trigger { - systemTime = Client.getSystemTime() - return super.register() - } - - override fun trigger(args: Array) { - if (delay < 0) { - // run trigger based on set fps value (60 per second by default) - while (systemTime < Client.getSystemTime() + 1000 / fps) { - callMethod(arrayOf(++elapsed)) - systemTime += 1000 / fps - } - } else { - // run trigger based on set delay in seconds - while (Client.getSystemTime() > systemTime + delay * 1000) { - callMethod(arrayOf(++elapsed)) - systemTime += delay * 1000 - } - } - } -} diff --git a/src/main/kotlin/com/chattriggers/ctjs/api/triggers/TriggerType.kt b/src/main/kotlin/com/chattriggers/ctjs/api/triggers/TriggerType.kt index 3f9e9cd3..b108918f 100644 --- a/src/main/kotlin/com/chattriggers/ctjs/api/triggers/TriggerType.kt +++ b/src/main/kotlin/com/chattriggers/ctjs/api/triggers/TriggerType.kt @@ -1,6 +1,8 @@ package com.chattriggers.ctjs.api.triggers import com.chattriggers.ctjs.internal.engine.JSLoader +import net.fabricmc.fabric.api.client.rendering.v1.level.LevelRenderContext +import net.fabricmc.fabric.api.client.rendering.v1.level.LevelRenderEvents sealed interface ITriggerType { val name: String @@ -11,52 +13,23 @@ sealed interface ITriggerType { } enum class TriggerType : ITriggerType { - // client + RENDER_OVERLAY, + RENDER_LEVEL_EXTRACTION, + CHAT, ACTION_BAR, - TICK, - STEP, - GAME_UNLOAD, - GAME_LOAD, - CLICKED, - SCROLLED, - DRAGGED, - GUI_OPENED, MESSAGE_SENT, - ITEM_TOOLTIP, - PLAYER_INTERACT, - GUI_KEY, - GUI_MOUSE_CLICK, - GUI_MOUSE_DRAG, - PACKET_SENT, - PACKET_RECEIVED, - SERVER_CONNECT, - SERVER_DISCONNECT, - GUI_CLOSED, - DROP_ITEM, - - // rendering - PRE_RENDER_WORLD, - POST_RENDER_WORLD, - BLOCK_HIGHLIGHT, - RENDER_OVERLAY, - RENDER_PLAYER_LIST, - RENDER_ENTITY, - RENDER_BLOCK_ENTITY, - GUI_RENDER, - POST_GUI_RENDER, - - // world - SOUND_PLAY, - WORLD_LOAD, - WORLD_UNLOAD, - SPAWN_PARTICLE, - ENTITY_DEATH, - ENTITY_DAMAGE, - - // misc - COMMAND, - OTHER + + TICK, +} + +enum class RenderContextTriggerType(val register: ((LevelRenderContext) -> Unit) -> Unit) : ITriggerType { + END_MAIN({ LevelRenderEvents.END_MAIN.register(it) }), + BEFORE_GIZMOS({ LevelRenderEvents.BEFORE_GIZMOS.register(it) }), + AFTER_TRANSLUCENT_TERRAIN({ LevelRenderEvents.AFTER_TRANSLUCENT_TERRAIN.register(it) }), + AFTER_SOLID_FEATURES({ LevelRenderEvents.AFTER_SOLID_FEATURES.register(it) }), + AFTER_TRANSLUCENT_FEATURES({ LevelRenderEvents.AFTER_TRANSLUCENT_FEATURES.register(it) }), + BEFORE_TRANSLUCENT_TERRAIN({ LevelRenderEvents.BEFORE_TRANSLUCENT_TERRAIN.register(it) }), } data class CustomTriggerType(override val name: String) : ITriggerType diff --git a/src/main/kotlin/com/chattriggers/ctjs/api/vec/Vec2f.kt b/src/main/kotlin/com/chattriggers/ctjs/api/vec/Vec2f.kt deleted file mode 100644 index 743f0e20..00000000 --- a/src/main/kotlin/com/chattriggers/ctjs/api/vec/Vec2f.kt +++ /dev/null @@ -1,34 +0,0 @@ -package com.chattriggers.ctjs.api.vec - -import kotlin.math.acos -import kotlin.math.sqrt - -data class Vec2f @JvmOverloads constructor(val x: Float = 0f, val y: Float = 0f) { - fun magnitudeSquared() = x * x + y * y - - fun magnitude() = sqrt(magnitudeSquared()) - - fun translated(dx: Float, dy: Float) = Vec2f(x + dx, y + dy) - - fun scaled(scale: Float) = Vec2f(x * scale, y * scale) - - fun scaled(xScale: Float, yScale: Float) = Vec2f(x * xScale, y * yScale) - - fun dotProduct(other: Vec2f) = x * other.x + y * other.y - - fun angleTo(other: Vec2f): Float { - return acos(dotProduct(other) / (magnitude() * other.magnitude()).coerceIn(-1f, 1f)) - } - - fun normalized() = magnitude().let { - Vec2f(x / it, y / it) - } - - operator fun unaryMinus() = Vec2f(-x, -y) - - operator fun plus(other: Vec2f) = Vec2f(x + other.x, y + other.y) - - operator fun minus(other: Vec2f) = this + (-other) - - override fun toString() = "Vec2f($x, $y)" -} diff --git a/src/main/kotlin/com/chattriggers/ctjs/api/vec/Vec3f.kt b/src/main/kotlin/com/chattriggers/ctjs/api/vec/Vec3f.kt deleted file mode 100644 index d0084fe9..00000000 --- a/src/main/kotlin/com/chattriggers/ctjs/api/vec/Vec3f.kt +++ /dev/null @@ -1,42 +0,0 @@ -package com.chattriggers.ctjs.api.vec - -import kotlin.math.acos -import kotlin.math.sqrt - -data class Vec3f @JvmOverloads constructor( - val x: Float = 0f, val y: Float = 0f, val z: Float = 0f, -) { - fun magnitudeSquared() = x * x + y * y + z * z - - fun magnitude() = sqrt(magnitudeSquared()) - - fun translated(dx: Float, dy: Float, dz: Float) = Vec3f(x + dx, y + dy, z + dz) - - fun scaled(scale: Float) = Vec3f(x * scale, y * scale, z * scale) - - fun scaled(xScale: Float, yScale: Float, zScale: Float) = Vec3f(x * xScale, y * yScale, z * zScale) - - fun crossProduct(other: Vec3f) = Vec3f( - y * other.z - z * other.y, - z * other.x - x * other.z, - x * other.y - y * other.x, - ) - - fun dotProduct(other: Vec3f) = x * other.x + y * other.y + z * other.z - - fun angleTo(other: Vec3f): Float { - return acos(dotProduct(other) / (magnitude() * other.magnitude()).coerceIn(-1f, 1f)) - } - - fun normalized() = magnitude().let { - Vec3f(x / it, y / it, z / it) - } - - operator fun unaryMinus() = Vec3f(-x, -y, -z) - - operator fun plus(other: Vec3f) = Vec3f(x + other.x, y + other.y, z + other.z) - - operator fun minus(other: Vec3f) = this + (-other) - - override fun toString() = "Vec3f($x, $y, $z)" -} diff --git a/src/main/kotlin/com/chattriggers/ctjs/api/vec/Vec3i.kt b/src/main/kotlin/com/chattriggers/ctjs/api/vec/Vec3i.kt deleted file mode 100644 index dcc4c805..00000000 --- a/src/main/kotlin/com/chattriggers/ctjs/api/vec/Vec3i.kt +++ /dev/null @@ -1,47 +0,0 @@ -package com.chattriggers.ctjs.api.vec - -import java.util.* -import kotlin.math.acos -import kotlin.math.sqrt - -open class Vec3i @JvmOverloads constructor( - val x: Int = 0, val y: Int = 0, val z: Int = 0, -) { - fun magnitudeSquared() = x * x + y * y + z * z - - fun magnitude() = sqrt(magnitudeSquared().toFloat()) - - open fun translated(dx: Int, dy: Int, dz: Int) = Vec3i(x + dx, y + dy, z + dz) - - open fun scaled(scale: Int) = Vec3i(x * scale, y * scale, z * scale) - - open fun scaled(xScale: Int, yScale: Int, zScale: Int) = Vec3i(x * xScale, y * yScale, z * zScale) - - open fun crossProduct(other: Vec3i) = Vec3i( - y * other.z - z * other.y, - z * other.x - x * other.z, - x * other.y - y * other.x, - ) - - fun dotProduct(other: Vec3i) = x * other.x + y * other.y + z * other.z - - fun angleTo(other: Vec3i): Float { - return acos(dotProduct(other) / (magnitude() * other.magnitude()).coerceIn(-1f, 1f)) - } - - fun normalized() = magnitude().let { - Vec3f(x / it, y / it, z / it) - } - - open operator fun unaryMinus() = Vec3i(-x, -y, -z) - - open operator fun plus(other: Vec3i) = Vec3i(x + other.x, y + other.y, z + other.z) - - open operator fun minus(other: Vec3i) = this + (-other) - - override fun hashCode() = Objects.hash(x, y, z) - - override fun equals(other: Any?) = other is Vec3i && x == other.x && y == other.y && z == other.z - - override fun toString() = "Vec3i($x, $y, $z)" -} diff --git a/src/main/kotlin/com/chattriggers/ctjs/api/world/BossBars.kt b/src/main/kotlin/com/chattriggers/ctjs/api/world/BossBars.kt deleted file mode 100644 index ba14e961..00000000 --- a/src/main/kotlin/com/chattriggers/ctjs/api/world/BossBars.kt +++ /dev/null @@ -1,283 +0,0 @@ -package com.chattriggers.ctjs.api.world - -import com.chattriggers.ctjs.api.CTWrapper -import com.chattriggers.ctjs.api.client.Client -import com.chattriggers.ctjs.api.message.ChatLib -import com.chattriggers.ctjs.api.message.TextComponent -import com.chattriggers.ctjs.internal.mixins.BossBarHudAccessor -import com.chattriggers.ctjs.MCBossBarColor -import com.chattriggers.ctjs.MCBossBarStyle -import com.chattriggers.ctjs.internal.utils.asMixin -import com.chattriggers.ctjs.internal.utils.getOption -import net.minecraft.client.gui.hud.ClientBossBar -import org.mozilla.javascript.NativeObject -import java.util.* - -object BossBars { - @JvmStatic - fun toMC() = Client.getMinecraft().inGameHud.bossBarHud - - /** - * Gets the list of currently shown [BossBar]s - * - * @return the currently displayed [BossBar]s - */ - @JvmStatic - fun getBossBars(): List { - return toMC().asMixin().bossBars.values.map(::BossBar) - } - - /** - * Gets all [BossBar]s with a given name - * - * @param name the name to match - * @return the [BossBar]s - */ - @JvmStatic - fun getBossBarsByName(name: String): List { - return getBossBars().filter { it.getName() == name } - } - - /** - * Adds a new [BossBar] to be displayed - * - * Takes a parameter with the following options: - * - name: The name to appear above the BossBar. Defaults to an empty string - * - percent: The percent full the BossBar is. Defaults to 1 (full health) - * - color: The color of the BossBar. Can be any [Color], but defaults to white - * - sections: The number of notches/sections to appear on the BossBar. Can be any [Style], but - * defaults to 1 entire section - * - darkenSky: Whether the BossBar should darken the screen of the player. Defaults to false - * - dragonMusic: Whether the BossBar should play dragon music while in the End. Defaults to false - * - thickenFog: Whether the BossBar should thicken the fog around the player. Defaults to false - * - * @param obj An options bag - * - * @return the [BossBar] for further modification - */ - @JvmStatic - fun addBossBar(obj: NativeObject): BossBar { - val name = obj.getOption("name", "") - val percent = obj.getOption("percent", 1f).toFloat().coerceIn(0f..1f) - val color = Color.from(obj.getOption("color", Color.WHITE)) - val style = Style.from(obj.getOption("sections", Style.ONE)) - val shouldDarkenSky = obj.getOption("darkenSky", false).toBoolean() - val dragonMusic = obj.getOption("dragonMusic", false).toBoolean() - val shouldThickenFog = obj.getOption("thickenFog", false).toBoolean() - - val uuid = UUID.randomUUID() - - val bossBar = ClientBossBar( - uuid, - TextComponent(name), - percent, - color.toMC(), - style.toMC(), - shouldDarkenSky, - dragonMusic, - shouldThickenFog - ) - - toMC().asMixin().bossBars[uuid] = bossBar - - return BossBar(bossBar) - } - - /** - * Clears all [BossBar]s on screen - */ - @JvmStatic - fun clearBossBars() { - toMC().clear() - } - - /** - * Removes all [BossBar]s with the given name - * - * @param name the name to match - */ - @JvmStatic - fun removeBossBarsByName(name: String) { - toMC().asMixin().bossBars.values.removeIf { - TextComponent(it.name).formattedText == ChatLib.addColor(name) - } - } - - /** - * Removes the given [BossBar] - * - * @param bossBar the BossBar to remove - */ - @JvmStatic - fun removeBossBar(bossBar: BossBar) { - toMC().asMixin().bossBars.remove(bossBar.getUUID()) - } - - class BossBar(override val mcValue: ClientBossBar) : CTWrapper { - /** - * Gets the UUID of this BossBar - * - * @return the uuid - */ - fun getUUID(): UUID { - return mcValue.uuid - } - - /** - * Gets the name of this BossBar - * - * @return the name - */ - fun getName(): String { - return TextComponent(mcValue.name).formattedText - } - - /** - * Sets the name of this BossBar - * - * @param name the name to set - */ - fun setName(name: String) = apply { - mcValue.name = TextComponent(name) - } - - /** - * Gets how full this BossBar is - * - * @return how full the BossBar is - */ - fun getPercent(): Float = mcValue.percent - - /** - * Sets how full this BossBar is - * - * @param percent how full to set this BossBar. Must be between 0 and 1 - */ - fun setPercent(percent: Float) = apply { - mcValue.percent = percent.coerceIn(0f..1f) - } - - /** - * Gets the [Color] of this BossBar - */ - fun getColor(): Color = Color.fromMC(mcValue.color) - - /** - * Sets the [Color] of this BossBar - * - * @param color the color to set. Can be [Color], [MCBossBarColor], or a string - */ - fun setColor(color: Any) = apply { - mcValue.color = Color.from(color).toMC() - } - - /** - * Gets the style of this BossBar. e.g. how many notches are displayed - */ - fun getStyle(): Style = Style.fromMC(mcValue.style) - - /** - * Sets the style of this BossBar - * - * @param style the style to set. Can be [Style], [MCBossBarStyle], a string, - * or a number of how many notches to put - */ - fun setStyle(style: Any) = apply { - mcValue.style = Style.from(style).toMC() - } - - /** - * Gets whether this BossBar darkens the sky - */ - fun shouldDarkenSky(): Boolean = mcValue.shouldDarkenSky() - - /** - * Sets whether this BossBar should darken the sky - * - * @param darken whether to darken the sky - */ - fun setShouldDarkenSky(darken: Boolean) = apply { - mcValue.setDarkenSky(darken) - } - - /** - * Gets whether this BossBar will play dragon music. - * This will do nothing when the player is not in the end dimension - */ - fun hasDragonMusic(): Boolean = mcValue.hasDragonMusic() - - /** - * Sets whether this BossBar will play dragon music - * - * @param music whether to play dragon music - */ - fun setHasDragonMusic(music: Boolean) = apply { - mcValue.setDragonMusic(music) - } - - /** - * Gets whether this BossBar should thicken the fog around the player - */ - fun shouldThickenFog(): Boolean = mcValue.shouldThickenFog() - - /** - * Sets whether this BossBar should thicken the fog around the player - * - * @param fog whether to thicken the fog - */ - fun setShouldThickenFog(fog: Boolean) = apply { - mcValue.setThickenFog(fog) - } - - override fun toString(): String { - return "BossBar{name=${getName()}, percent=${getPercent()}, color=${getColor()}, " + - "style=${getStyle()}, shouldDarkenSky=${shouldDarkenSky()}, " + - "hasDragonMusic=${hasDragonMusic()}, shouldThickenFog=${shouldThickenFog()}}" - } - } - - enum class Color(override val mcValue: MCBossBarColor) : CTWrapper { - PINK(MCBossBarColor.PINK), - BLUE(MCBossBarColor.BLUE), - RED(MCBossBarColor.RED), - GREEN(MCBossBarColor.GREEN), - YELLOW(MCBossBarColor.YELLOW), - PURPLE(MCBossBarColor.PURPLE), - WHITE(MCBossBarColor.WHITE); - - companion object { - @JvmStatic - fun fromMC(mcValue: MCBossBarColor) = entries.first { it.mcValue == mcValue } - - @JvmStatic - fun from(value: Any) = when (value) { - is CharSequence -> valueOf(value.toString()) - is MCBossBarColor -> fromMC(value) - is Color -> value - else -> throw IllegalArgumentException("Cannot create BossBars.Color from $value") - } - } - } - - enum class Style(override val mcValue: MCBossBarStyle, val sections: Int) : CTWrapper { - ONE(MCBossBarStyle.PROGRESS, 1), - SIX(MCBossBarStyle.NOTCHED_6, 6), - TEN(MCBossBarStyle.NOTCHED_10, 10), - TWELVE(MCBossBarStyle.NOTCHED_12, 12), - TWENTY(MCBossBarStyle.NOTCHED_20, 20); - - companion object { - @JvmStatic - fun fromMC(mcValue: MCBossBarStyle) = entries.first { it.mcValue == mcValue } - - @JvmStatic - fun from(value: Any) = when (value) { - is CharSequence -> valueOf(value.toString()) - is MCBossBarStyle -> fromMC(value) - is Style -> value - is Number -> entries.first { it.sections == value } - else -> throw IllegalArgumentException("Cannot create BossBars.Style from $value") - } - } - } -} diff --git a/src/main/kotlin/com/chattriggers/ctjs/api/world/Chunk.kt b/src/main/kotlin/com/chattriggers/ctjs/api/world/Chunk.kt deleted file mode 100644 index c13d0b5d..00000000 --- a/src/main/kotlin/com/chattriggers/ctjs/api/world/Chunk.kt +++ /dev/null @@ -1,80 +0,0 @@ -package com.chattriggers.ctjs.api.world - -import com.chattriggers.ctjs.api.CTWrapper -import com.chattriggers.ctjs.api.entity.BlockEntity -import com.chattriggers.ctjs.api.entity.Entity -import com.chattriggers.ctjs.internal.mixins.ChunkAccessor -import com.chattriggers.ctjs.MCBlockPos -import com.chattriggers.ctjs.MCChunk -import com.chattriggers.ctjs.MCEntity -import com.chattriggers.ctjs.internal.utils.asMixin -import net.minecraft.util.math.Box - -// TODO: Add more methods here? -class Chunk(override val mcValue: MCChunk) : CTWrapper { - /** - * Gets the x position of the chunk - */ - fun getX() = mcValue.pos.x - - /** - * Gets the z position of the chunk - */ - fun getZ() = mcValue.pos.z - - /** - * Gets the minimum x coordinate of a block in the chunk - * - * @return the minimum x coordinate - */ - fun getMinBlockX() = getX() * 16 - - /** - * Gets the minimum z coordinate of a block in the chunk - * - * @return the minimum z coordinate - */ - fun getMinBlockZ() = getZ() * 16 - - /** - * Gets every entity in this chunk - * - * @return the entity list - */ - fun getAllEntities(): List = getAllEntitiesOfType(MCEntity::class.java) - - /** - * Gets every entity in this chunk of a certain class - * - * @param clazz the class to filter for (Use `Java.type().class` to get this) - * @return the entity list - */ - fun getAllEntitiesOfType(clazz: Class): List { - val box = Box( - MCBlockPos(getMinBlockX(), mcValue.bottomY, getMinBlockZ()) - ).stretch(16.0, mcValue.topY.toDouble(), 16.0) - - return World.toMC()?.getEntitiesByClass(clazz, box) { true }?.map(Entity::fromMC) ?: listOf() - } - - /** - * Gets every block entity in this chunk - * - * @return the block entity list - */ - fun getAllBlockEntities(): List { - return mcValue.asMixin().blockEntities.values.map(::BlockEntity) - } - - /** - * Gets every block entity in this chunk of a certain class - * - * @param clazz the class to filter for (Use `Java.type().class` to get this) - * @return the block entity list - */ - fun getAllBlockEntitiesOfType(clazz: Class<*>): List { - return getAllBlockEntities().filter { - clazz.isInstance(it.toMC()) - } - } -} diff --git a/src/main/kotlin/com/chattriggers/ctjs/api/world/PotionEffect.kt b/src/main/kotlin/com/chattriggers/ctjs/api/world/PotionEffect.kt deleted file mode 100644 index be29d599..00000000 --- a/src/main/kotlin/com/chattriggers/ctjs/api/world/PotionEffect.kt +++ /dev/null @@ -1,43 +0,0 @@ -package com.chattriggers.ctjs.api.world - -import com.chattriggers.ctjs.api.message.TextComponent -import net.minecraft.entity.effect.StatusEffect -import net.minecraft.entity.effect.StatusEffectInstance -import net.minecraft.registry.Registries - -/** - * Represents a specific instance of a [PotionEffectType] - */ -class PotionEffect(val effect: StatusEffectInstance) { - /** - * The type of this potion - */ - val type get() = PotionEffectType(effect.effectType.value()) - - /** - * Returns the translation key of the potion. - * Ex: "potion.poison" - */ - val name get() = effect.translationKey - - /** - * Returns the localized name of the potion that - * is displayed in the player's inventory. - * Ex: "Poison" - */ - val localizedName get() = TextComponent(effect.effectType.value().name).unformattedText - - val amplifier get() = effect.amplifier - - val duration get() = effect.duration - - val id get() = Registries.STATUS_EFFECT.getRawId(effect.effectType.value()) - - val ambient get() = effect.isAmbient - - val isInfinite get() = effect.isInfinite - - val showsParticles get() = effect.shouldShowParticles() - - override fun toString(): String = effect.toString() -} diff --git a/src/main/kotlin/com/chattriggers/ctjs/api/world/PotionEffectType.kt b/src/main/kotlin/com/chattriggers/ctjs/api/world/PotionEffectType.kt deleted file mode 100644 index 944ba5bf..00000000 --- a/src/main/kotlin/com/chattriggers/ctjs/api/world/PotionEffectType.kt +++ /dev/null @@ -1,38 +0,0 @@ -package com.chattriggers.ctjs.api.world - -import com.chattriggers.ctjs.api.message.TextComponent -import net.minecraft.entity.effect.StatusEffect -import net.minecraft.registry.Registries -import java.awt.Color - -class PotionEffectType(val type: StatusEffect) { - /** - * The Int associated with this type - */ - val rawId get() = Registries.STATUS_EFFECT.getRawId(type) - - /** - * Whether this effect is instant (e.g. instant health) - */ - val isInstant get() = type.isInstant - - /** - * The raw key used for this effect type - */ - val translationKey get() = type.translationKey - - /** - * The user-friendly name of this type as a [TextComponent] - */ - val name get() = TextComponent(type.name) - - /** - * The [net.minecraft.entity.effect.StatusEffectCategory] of this type - */ - val category get() = type.category - - /** - * The color of this type - */ - val color get() = Color(type.color) -} diff --git a/src/main/kotlin/com/chattriggers/ctjs/api/world/Scoreboard.kt b/src/main/kotlin/com/chattriggers/ctjs/api/world/Scoreboard.kt deleted file mode 100644 index d8c57188..00000000 --- a/src/main/kotlin/com/chattriggers/ctjs/api/world/Scoreboard.kt +++ /dev/null @@ -1,360 +0,0 @@ -package com.chattriggers.ctjs.api.world - -import com.chattriggers.ctjs.MCTeam -import com.chattriggers.ctjs.api.CTWrapper -import com.chattriggers.ctjs.api.entity.Team -import com.chattriggers.ctjs.api.message.TextComponent -import com.chattriggers.ctjs.internal.mixins.`Scoreboard$1Accessor` -import com.chattriggers.ctjs.internal.utils.asMixin -import gg.essential.elementa.state.BasicState -import net.minecraft.scoreboard.ScoreAccess -import net.minecraft.scoreboard.ScoreboardDisplaySlot -import net.minecraft.scoreboard.ScoreboardObjective -import net.minecraft.scoreboard.ScoreboardScore -import net.minecraft.scoreboard.number.NumberFormat -import net.minecraft.scoreboard.number.StyledNumberFormat -import net.minecraft.text.Style -import org.mozilla.javascript.NativeObject - -object Scoreboard { - private var needsUpdate = true - private var scoreboardNames = mutableListOf() - private var scoreboardTitle = TextComponent("") - private var shouldRender = true - internal var customTitle = false - - @JvmStatic - fun toMC() = World.toMC()?.scoreboard - - @Deprecated("Use toMC", ReplaceWith("toMC()")) - @JvmStatic - fun getScoreboard() = toMC() - - @JvmStatic - fun getSidebar(): ScoreboardObjective? = toMC()?.getObjectiveForSlot(ScoreboardDisplaySlot.SIDEBAR) - - /** - * Gets the top-most string which is displayed on the scoreboard. (doesn't have a score on the side). - * Be aware that this can contain color codes. - * - * @return the scoreboard title - */ - @JvmStatic - fun getTitle(): TextComponent { - if (needsUpdate) { - updateNames() - needsUpdate = false - } - - return scoreboardTitle - } - - /** - * Sets the scoreboard title. - * - * @param title the new title - * @return the scoreboard title - */ - @JvmStatic - fun setTitle(title: TextComponent) { - customTitle = false - getSidebar()?.displayName = title - scoreboardTitle = title - customTitle = true - } - - @JvmStatic - fun setTitle(title: String) = setTitle(TextComponent(title)) - - /** - * Get all currently visible strings on the scoreboard. (excluding title) - * Be aware that this can contain color codes. - * - * @return the list of lines - */ - @JvmStatic - @JvmOverloads - fun getLines(descending: Boolean = true): List { - // the array will only be updated upon request - if (needsUpdate) { - updateNames() - needsUpdate = false - } - - return if (descending) scoreboardNames else scoreboardNames.asReversed() - } - - /** - * Gets the line at the specified index (0 based) - * Equivalent to Scoreboard.getLines().get(index) - * - * @param index the line index - * @return the score object at the index - */ - @JvmStatic - fun getLineByIndex(index: Int): Score = getLines()[index] - - /** - * Gets a list of lines that have a certain score, - * i.e. the numbers shown on the right - * - * @param score the score to look for - * @return a list of actual score objects - */ - @JvmStatic - fun getLinesByScore(score: Int): List = getLines().filter { - it.getScore() == score - } - - /** - * Sets a line in the scoreboard to the specified name and score. - * - * @param score the score value for this item - * @param line the [TextComponent] to display on said line - * @param override whether to remove old lines with the same score - */ - @JvmStatic - @JvmOverloads - fun setLine(score: Int, line: TextComponent, override: Boolean = false) { - val scoreboard = toMC() ?: return - val sidebarObjective = getSidebar() ?: return - - if (override) { - removeScores(score) - addLine(score, line) - return - } - - scoreboard.knownScoreHolders.forEach { - val scoreboardScore = scoreboard.getScore({ it.nameForScoreboard }, sidebarObjective) as? ScoreboardScore - if (scoreboardScore?.score == score) { - scoreboardScore.displayText = line - } - } - } - - @JvmStatic - @JvmOverloads - fun setLine(score: Int, line: String, override: Boolean = false) = setLine(score, TextComponent(line), override) - - /** - * Adds a line to the scoreboard - * - * @param score the score value for this item - * @param line the [TextComponent] to display on said line - */ - @JvmStatic - fun addLine(score: Int, line: TextComponent) { - val scoreboard = toMC() ?: return - val sidebarObjective = getSidebar() ?: return - - val newLine = scoreboard.getOrCreateScore({ Math.random().toString() }, sidebarObjective, true) - newLine.displayText = line - newLine.score = score - - updateNames() - } - - @JvmStatic - fun addLine(score: Int, line: String) = addLine(score, TextComponent(line)) - - /** - * Removes all lines from the scoreboard matching with a certain score - * - * @param score the score of the lines to remove - */ - @JvmStatic - fun removeScores(score: Int) { - getLinesByScore(score).forEach(Score::remove) - } - - /** - * Removes the line at a certain index - * - * @param index the index of the line to remove - */ - @JvmStatic - @JvmOverloads - fun removeIndex(index: Int, descending: Boolean = true) { - val names = if (descending) scoreboardNames else scoreboardNames.asReversed() - val line = names.removeAt(index) - line.remove() - } - - @JvmStatic - fun setShouldRender(shouldRender: Boolean) { - Scoreboard.shouldRender = shouldRender - } - - @JvmStatic - fun getShouldRender() = shouldRender - - /** - * Creates or gets a [Team] with a given name - * - * @param name the name of the team - */ - @JvmStatic - fun createTeam(name: String): Team = Team(toMC()!!.addTeam(name)) - - private fun updateNames() { - scoreboardNames.clear() - - if (!customTitle) - scoreboardTitle = TextComponent("") - - val scoreboard = toMC() ?: return - val objective = getSidebar() ?: return - - if (!customTitle) - scoreboardTitle = TextComponent(objective.displayName) - - val newScores = scoreboard.knownScoreHolders.asSequence().filter { - objective in scoreboard.getScoreHolderObjectives(it) - }.map { - scoreboard.getOrCreateScore(it, objective, true) - }.mapTo(mutableListOf(), ::Score) - - scoreboardNames = newScores.sortedWith(compareBy { - it.getScore() - }.reversed().thenBy { - it.getName().formattedText.lowercase() - }).toMutableList() - } - - internal fun resetCache() { - needsUpdate = true - } - - internal fun clearCustom() { - scoreboardNames.clear() - customTitle = false - scoreboardTitle = TextComponent("") - } - - class Score(override val mcValue: ScoreAccess) : CTWrapper { - private val scoreState = BasicState(mcValue.score) - private val nameState = BasicState(mcValue.displayText) - private val formatState = BasicState(mcValue.asMixin<`Scoreboard$1Accessor`>().score.numberFormat) - private val teamState = run { - val scoreboard = Scoreboard.toMC()!! - val name = mcValue.asMixin<`Scoreboard$1Accessor`>().holder.nameForScoreboard - - BasicState(scoreboard.getScoreHolderTeam(name)) - } - - /** - * Gets the team associated with this score, if it exists - * - * @return the team, or null if it does not exist - */ - fun getTeam(): Team? = teamState.get()?.let(::Team) - - /** - * Sets the team associated with this score - * - * @param team the new team to set for this line. Custom teams can be created using [createTeam] - * @return the score to allow for method chaining - */ - fun setTeam(team: Team?) = apply { - val scoreboard = Scoreboard.toMC()!! - val name = mcValue.asMixin<`Scoreboard$1Accessor`>().holder.nameForScoreboard - - if (team == null) { - scoreboard.clearTeam(name) - } else { - scoreboard.addScoreHolderToTeam(name, team.toMC()) - } - - teamState.set(team?.toMC()) - } - - /** - * Gets the score value for this score, - * i.e. the number on the right of the board - * - * @return the actual point value - */ - fun getScore(): Int = scoreState.get() - - /** - * Sets the score value for this score - * - * @param score the new point value - * @return the score to allow for method chaining - */ - fun setScore(score: Int) = apply { - scoreState.set(score) - mcValue.score = score - } - - /** - * Gets the display text of this score - * - * @return the display name - */ - fun getName(): TextComponent { - val name = mcValue.asMixin<`Scoreboard$1Accessor`>().holder.nameForScoreboard - - return TextComponent( - MCTeam.decorateName( - getTeam()?.mcValue, - TextComponent(nameState.get() ?: name), - ) - ) - } - - /** - * Sets the name of this score - * - * @param name the new name - * @return the score to allow for method chaining - */ - fun setName(name: TextComponent?) = apply { - nameState.set(name) - mcValue.displayText = name - } - - /** - * Gets the number format of this score - * - * @return the number format - */ - fun getNumberFormat(): NumberFormat? = formatState.get() - - /** - * Sets the number format of this score - * - * @param format either a formatting string, i.e. "&6", style in the form of an object, see [TextComponent], a - * [NumberFormat], or hex value - * @return the score to allow for method chaining - * - * @see [TextComponent] - */ - fun setNumberFormat(format: Any?) = apply { - val style = when (format) { - is CharSequence -> StyledNumberFormat(TextComponent(format.toString()).style) - is NativeObject -> StyledNumberFormat(TextComponent.jsObjectToStyle(format)) - is NumberFormat -> format - is Number -> StyledNumberFormat(Style.EMPTY.withColor(format.toInt())) - else -> null - } - - formatState.set(style) - mcValue.setNumberFormat(style) - } - - /** - * Removes this score from the scoreboard - */ - fun remove() { - val scoreboard = Scoreboard.toMC() ?: return - val sidebarObjective = getSidebar() ?: return - - scoreboard.removeScore(toMC().asMixin<`Scoreboard$1Accessor`>().holder, sidebarObjective) - updateNames() - } - - override fun toString(): String = getName().formattedText - } -} diff --git a/src/main/kotlin/com/chattriggers/ctjs/api/world/Server.kt b/src/main/kotlin/com/chattriggers/ctjs/api/world/Server.kt deleted file mode 100644 index 410f7bd0..00000000 --- a/src/main/kotlin/com/chattriggers/ctjs/api/world/Server.kt +++ /dev/null @@ -1,74 +0,0 @@ -package com.chattriggers.ctjs.api.world - -import com.chattriggers.ctjs.api.client.Client -import com.chattriggers.ctjs.api.client.Player -import com.chattriggers.ctjs.api.message.TextComponent - -object Server { - @JvmStatic - fun toMC() = Client.getMinecraft().currentServerEntry - - @JvmStatic - fun isSingleplayer(): Boolean = Client.getMinecraft().isInSingleplayer - - /** - * Gets the current server's IP, or "localhost" if the player - * is in a single-player world. - * - * @return The IP of the current server - */ - @JvmStatic - fun getIP(): String { - if (isSingleplayer()) - return "localhost" - - return toMC()?.address ?: "" - } - - /** - * Gets the current server's name, or "SinglePlayer" if the player - * is in a single-player world. - * - * @return The name of the current server - */ - @JvmStatic - fun getName(): String { - if (isSingleplayer()) - return "SinglePlayer" - - return toMC()?.name ?: "" - } - - /** - * Gets the current server's MOTD, or "SinglePlayer" if the player - * is in a single-player world. - * - * @return The MOTD of the current server - */ - @JvmStatic - fun getMOTD(): String { - if (isSingleplayer()) - return "SinglePlayer" - - return toMC()?.label?.let { TextComponent(it) }?.formattedText ?: "" - } - - /** - * Gets the ping to the current server, or 5 if the player - * is in a single-player world. Returns -1 if not in a world - * - * @return The ping to the current server - */ - @JvmStatic - fun getPing(): Long { - if (isSingleplayer()) { - return 5L - } - - val player = Player.toMC() ?: return -1L - - return Client.getConnection()?.getPlayerListEntry(player.uuid)?.latency?.toLong() - ?: toMC()?.ping - ?: -1L - } -} diff --git a/src/main/kotlin/com/chattriggers/ctjs/api/world/TabList.kt b/src/main/kotlin/com/chattriggers/ctjs/api/world/TabList.kt deleted file mode 100644 index 9f000c9a..00000000 --- a/src/main/kotlin/com/chattriggers/ctjs/api/world/TabList.kt +++ /dev/null @@ -1,413 +0,0 @@ -package com.chattriggers.ctjs.api.world - -import com.chattriggers.ctjs.MCTeam -import com.chattriggers.ctjs.api.CTWrapper -import com.chattriggers.ctjs.api.client.Client -import com.chattriggers.ctjs.api.client.Player -import com.chattriggers.ctjs.api.entity.Team -import com.chattriggers.ctjs.api.message.TextComponent -import com.chattriggers.ctjs.internal.mixins.ClientPlayNetworkHandlerAccessor -import com.chattriggers.ctjs.internal.mixins.MinecraftClientAccessor -import com.chattriggers.ctjs.internal.mixins.PlayerListEntryAccessor -import com.chattriggers.ctjs.internal.mixins.PlayerListHudAccessor -import com.chattriggers.ctjs.internal.utils.asMixin -import com.google.common.collect.ComparisonChain -import com.google.common.collect.Ordering -import com.mojang.authlib.GameProfile -import gg.essential.elementa.state.BasicState -import net.minecraft.client.network.PlayerListEntry -import net.minecraft.scoreboard.ScoreboardDisplaySlot -import net.minecraft.scoreboard.ScoreboardObjective -import net.minecraft.text.Text -import net.minecraft.util.ApiServices -import net.minecraft.world.GameMode -import java.util.* - -object TabList { - private var needsUpdate = true - private var tabListNames = mutableListOf() - private val playerComparator = Ordering.from(PlayerComparator()) - internal var customHeader = false - internal var customFooter = false - private var tabListHeader: TextComponent? = null - private var tabListFooter: TextComponent? = null - - @JvmStatic - fun toMC() = Client.getTabGui() - - /** - * Gets the scoreboard objective corresponding to the tab list, or null if it doesn't exist - */ - @JvmStatic - fun getObjective(): ScoreboardObjective? = Scoreboard.toMC()?.getObjectiveForSlot(ScoreboardDisplaySlot.LIST) - - /** - * Gets the tab list header as a [TextComponent] - * - * @return the header - */ - @JvmStatic - fun getHeaderComponent(): TextComponent? { - if (needsUpdate) { - updateNames() - needsUpdate = false - } - - return tabListHeader - } - - /** - * Gets the tab list header as a formatted string. - * - * @return the header - */ - @JvmStatic - fun getHeader() = getHeaderComponent()?.formattedText - - /** - * Sets the header text for the TabList. - * If [header] is null, it will remove the header entirely - * - * @param header the header to set, or null to clear - */ - @JvmStatic - fun setHeader(header: Any?) { - customHeader = false - when (header) { - is TextComponent? -> { - tabListHeader = header - toMC()?.setHeader(header) - } - is CharSequence, is Text -> { - tabListHeader = TextComponent(header) - toMC()?.setHeader(tabListHeader) - } - } - customHeader = true - } - - @JvmStatic - fun clearHeader() = setHeader(null) - - /** - * Gets the tab list footer as a [TextComponent] - * - * @return the footer - */ - @JvmStatic - fun getFooterComponent(): TextComponent? { - if (needsUpdate) { - updateNames() - needsUpdate = false - } - - return tabListFooter - } - - /** - * Gets the tab list footer as a string. - * Be aware that this can contain color codes. - * - * @return the footer - */ - @JvmStatic - fun getFooter() = getFooterComponent()?.formattedText - - /** - * Sets the footer text for the TabList. - * If [footer] is null, it will remove the footer entirely - * - * @param footer the footer to set, or null to clear - */ - @JvmStatic - fun setFooter(footer: Any?) { - customFooter = false - when (footer) { - is TextComponent? -> { - tabListHeader = footer - toMC()?.setFooter(footer) - } - is CharSequence, is Text -> { - tabListHeader = TextComponent(footer) - toMC()?.setFooter(tabListHeader) - } - } - customFooter = true - } - - @JvmStatic - fun clearFooter() = setFooter(null) - - /** - * Gets names set in scoreboard objectives - * - * @return The formatted names - */ - @JvmStatic - fun getNamesByObjectives(): List { - val scoreboard = Scoreboard.toMC() ?: return emptyList() - val tabListObjective = getObjective() ?: return emptyList() - - val scores = scoreboard.getScoreboardEntries(tabListObjective) - - return scores.map { - val team = scoreboard.getTeam(it.owner) - TextComponent(MCTeam.decorateName(team, TextComponent(it.owner))).formattedText - } - } - - /** - * Get all names on the tab list - * - * @return the list of names - */ - @JvmStatic - fun getNames(): List { - if (needsUpdate) { - updateNames() - needsUpdate = false - } - - return tabListNames - } - - /** - * Gets all names in tabs without formatting - * - * @return the unformatted names - */ - @JvmStatic - fun getUnformattedNames(): List { - if (needsUpdate) { - updateNames() - needsUpdate = false - } - - return tabListNames.map { it.toMC().profile.name } - } - - /** - * Adds a new name to the tab list - * - * @param name the formatted name to add - * @param useExistingSkin whether to use the skin of the associated Minecraft account using [name]. - * If false, will use a random default skin (Steve, Alex, etc) - */ - @JvmStatic - @JvmOverloads - fun addName(name: TextComponent, useExistingSkin: Boolean = true) { - val connection = Client.getConnection() ?: return - val listedPlayerListEntries = connection.listedPlayerListEntries - val playerListEntries = connection.asMixin().playerListEntries - - val username = name.unformattedText - - val uuid = UUID.randomUUID() - val fakeEntry = PlayerListEntry(GameProfile(uuid, name.unformattedText), false) - fakeEntry.displayName = name - - listedPlayerListEntries += fakeEntry - playerListEntries[uuid] = fakeEntry - - if (!useExistingSkin) { - updateNames() - return - } - - val mc = Client.getMinecraft() - val apiServices = - ApiServices.create(mc.asMixin().authenticationService, mc.runDirectory) - apiServices.userCache.setExecutor(mc) - - apiServices.userCache.findByNameAsync(username).thenAcceptAsync { - if (it.isPresent) { - val result = apiServices.sessionService.fetchProfile(it.get().id, true) ?: return@thenAcceptAsync - - val entry = PlayerListEntry(result.profile, true) - entry.displayName = name - - listedPlayerListEntries += entry - playerListEntries[result.profile.id] = entry - - listedPlayerListEntries -= fakeEntry - playerListEntries.remove(uuid) - - updateNames() - } - } - } - - @JvmStatic - @JvmOverloads - fun addName(name: String, useExistingSkin: Boolean = true) = addName(TextComponent(name), useExistingSkin) - - /** - * Removes all names from the tab list with a certain name - * - * @param name the name of the entry to remove - */ - @JvmStatic - fun removeNames(name: TextComponent) { - tabListNames.filter { - it.getName().style == name.style && it.getName().string == name.string - }.forEach(Name::remove) - } - - @JvmStatic - fun removeNames(name: String) { - tabListNames.filter { - it.getName().string == name - }.forEach(Name::remove) - } - - private fun updateNames() { - tabListNames.clear() - - if (!customHeader) - tabListHeader = null - - if (!customFooter) - tabListFooter = null - - val hud = toMC()?.asMixin() ?: return - val player = Player.toMC() ?: return - - if (!customHeader) - tabListHeader = hud.header?.let { TextComponent(it) } - - if (!customFooter) - tabListFooter = hud.footer?.let { TextComponent(it) } - - tabListNames = playerComparator - .sortedCopy(player.networkHandler.playerList) - .mapTo(mutableListOf(), ::Name) - } - - internal fun resetCache() { - needsUpdate = true - } - - internal fun clearCustom() { - tabListNames.clear() - customHeader = false - customFooter = false - tabListHeader = null - tabListFooter = null - } - - class Name(override val mcValue: PlayerListEntry) : CTWrapper { - private val latencyState = BasicState(mcValue.latency) - private val teamState = BasicState(mcValue.scoreboardTeam) - private val nameState = BasicState(mcValue.displayName) - - /** - * Gets the latency associated with this name - * - * @return the latency - */ - fun getLatency(): Int = latencyState.get() - - /** - * Sets the latency associated with this name. - * - latency between 0 and 149 represents all 5 bars - * - latency between 150 and 299 represents 4 bars - * - latency between 300 and 599 represents 3 bars - * - latency between 600 and 999 represents 2 bars - * - latency between 1000 and more represents 1 bar - * - * @param latency the latency to set - * @return the name to allow for method chaining - */ - fun setLatency(latency: Int) = apply { - latencyState.set(latency) - mcValue.asMixin().invokeSetLatency(latency) - } - - /** - * Gets the team associated with this name, if it exists - * - * @return the team, or null if it does not exist - */ - fun getTeam(): Team? = teamState.get()?.let(::Team) - - /** - * Sets the team associated with this name - * - * @param team the new team to set for this name. Custom teams can be created - * using [Scoreboard.createTeam] - * @return the score to allow for method chaining - */ - fun setTeam(team: Team?) = apply { - val scoreboard = Scoreboard.toMC()!! - val name = mcValue.profile.name - - if (team == null) { - scoreboard.clearTeam(name) - } else { - scoreboard.addScoreHolderToTeam(name, team.toMC()) - } - - teamState.set(team?.toMC()) - } - - /** - * Gets the display text of this name - * - * @return the display name - */ - fun getName(): TextComponent { - val name = mcValue.profile.name - - return TextComponent( - MCTeam.decorateName( - getTeam()?.mcValue, - TextComponent(nameState.get() ?: name), - ) - ) - } - - /** - * Sets the display name of this name - * - * @param name the new name - * @return the name to allow for method chaining - */ - fun setName(name: TextComponent?) = apply { - nameState.set(name) - mcValue.displayName = name - } - - /** - * Removes this name from the tab list - */ - fun remove() { - val connection = Client.getConnection() ?: return - val listedPlayerListEntries = connection.listedPlayerListEntries - val playerListEntries = connection.asMixin().playerListEntries - - listedPlayerListEntries.remove(mcValue) - playerListEntries.remove(mcValue.profile.id) - - updateNames() - } - - override fun toString(): String = getName().formattedText - } - - internal class PlayerComparator internal constructor() : Comparator { - override fun compare(playerOne: PlayerListEntry, playerTwo: PlayerListEntry): Int { - val teamOne = playerOne.scoreboardTeam - val teamTwo = playerTwo.scoreboardTeam - - return ComparisonChain - .start() - .compareTrueFirst( - playerOne.gameMode != GameMode.SPECTATOR, - playerTwo.gameMode != GameMode.SPECTATOR - ) - .compare(teamOne?.name ?: "", teamTwo?.name ?: "") - .compare(playerOne.profile.name, playerTwo.profile.name) - .result() - } - } -} diff --git a/src/main/kotlin/com/chattriggers/ctjs/api/world/World.kt b/src/main/kotlin/com/chattriggers/ctjs/api/world/World.kt deleted file mode 100644 index c7423f8e..00000000 --- a/src/main/kotlin/com/chattriggers/ctjs/api/world/World.kt +++ /dev/null @@ -1,376 +0,0 @@ -package com.chattriggers.ctjs.api.world - -import com.chattriggers.ctjs.MCBlockPos -import com.chattriggers.ctjs.MCParticle -import com.chattriggers.ctjs.api.client.Client -import com.chattriggers.ctjs.api.client.Settings -import com.chattriggers.ctjs.api.entity.BlockEntity -import com.chattriggers.ctjs.api.entity.Entity -import com.chattriggers.ctjs.api.entity.Particle -import com.chattriggers.ctjs.api.entity.PlayerMP -import com.chattriggers.ctjs.api.render.Renderer -import com.chattriggers.ctjs.api.world.block.Block -import com.chattriggers.ctjs.api.world.block.BlockPos -import com.chattriggers.ctjs.api.world.block.BlockType -import com.chattriggers.ctjs.internal.mixins.ClientChunkManagerAccessor -import com.chattriggers.ctjs.internal.mixins.ClientChunkMapAccessor -import com.chattriggers.ctjs.internal.mixins.ClientWorldAccessor -import com.chattriggers.ctjs.internal.utils.asMixin -import com.chattriggers.ctjs.internal.utils.toIdentifier -import gg.essential.universal.UMinecraft -import net.minecraft.block.BlockState -import net.minecraft.client.world.ClientWorld -import net.minecraft.item.ItemStack -import net.minecraft.item.Items -import net.minecraft.particle.BlockStateParticleEffect -import net.minecraft.particle.DustColorTransitionParticleEffect -import net.minecraft.particle.DustParticleEffect -import net.minecraft.particle.EntityEffectParticleEffect -import net.minecraft.particle.ItemStackParticleEffect -import net.minecraft.particle.ParticleEffect -import net.minecraft.particle.ParticleTypes -import net.minecraft.particle.SculkChargeParticleEffect -import net.minecraft.particle.ShriekParticleEffect -import net.minecraft.particle.VibrationParticleEffect -import net.minecraft.registry.Registries -import net.minecraft.world.LightType -import net.minecraft.world.event.BlockPositionSource -import kotlin.math.roundToInt - -object World { - @JvmStatic - fun toMC() = UMinecraft.getMinecraft().world - - @JvmField - val spawn = SpawnWrapper() - - @JvmField - val particle = ParticleWrapper() - - @JvmField - val border = BorderWrapper() - - /** - * Gets Minecraft's [ClientWorld] object - * - * @return The Minecraft [ClientWorld] object - */ - @Deprecated("Use toMC", ReplaceWith("toMC()")) - @JvmStatic - fun getWorld(): ClientWorld? = toMC() - - @JvmStatic - fun isLoaded(): Boolean = toMC() != null - - @JvmStatic - fun isRaining(): Boolean = toMC()?.isRaining ?: false - - @JvmStatic - fun getRainingStrength(): Float = toMC()?.getRainGradient(Renderer.partialTicks) ?: -1f - - @JvmStatic - fun getTime(): Long = toMC()?.time ?: -1L - - @JvmStatic - fun getDifficulty(): Settings.Difficulty? = toMC()?.difficulty?.let(Settings.Difficulty::fromMC) - - @JvmStatic - fun getMoonPhase(): Int = toMC()?.moonPhase ?: -1 - - /** - * Gets the [Block] at a location in the world. - * - * @param x the x position - * @param y the y position - * @param z the z position - * @return the [Block] at the location - */ - @JvmStatic - fun getBlockAt(x: Number, y: Number, z: Number) = getBlockAt(BlockPos(x, y, z)) - - /** - * Gets the [Block] at a location in the world. - * - * @param pos The block position - * @return the [Block] at the location - */ - @JvmStatic - fun getBlockAt(pos: BlockPos): Block { - return Block(BlockType(getBlockStateAt(pos).block), pos) - } - - /** - * Gets the [BlockState] at a location in the world. - * - * @param pos The block position - * @return the [BlockState] at the location - */ - @JvmStatic - fun getBlockStateAt(pos: BlockPos): BlockState { - return toMC()!!.getBlockState(pos.toMC()) - } - - /** - * Gets the skylight level at the given position. This is the value seen in the debug (F3) menu - * - * @param x the x coordinate - * @param y the y coordinate - * @param z the z coordinate - * @return the skylight level at the location - */ - @JvmStatic - fun getSkyLightLevel(x: Int, y: Int, z: Int): Int = getSkyLightLevel(BlockPos(x, y, z)) - - /** - * Gets the skylight level at the given position. This is the value seen in the debug (F3) menu - * - * @param pos The block position - * @return the skylight level at the location - */ - @JvmStatic - fun getSkyLightLevel(pos: BlockPos): Int { - return toMC()?.getLightLevel(LightType.SKY, pos.toMC()) ?: 0 - } - - /** - * Gets the block light level at the given position. This is the value seen in the debug (F3) menu - * - * @param x the x coordinate - * @param y the y coordinate - * @param z the z coordinate - * @return the block light level at the location - */ - @JvmStatic - fun getBlockLightLevel(x: Int, y: Int, z: Int): Int = getBlockLightLevel(BlockPos(x, y, z)) - - /** - * Gets the block light level at the given position. This is the value seen in the debug (F3) menu - * - * @param pos The block position - * @return the block light level at the location - */ - @JvmStatic - fun getBlockLightLevel(pos: BlockPos): Int { - return toMC()?.getLightLevel(LightType.BLOCK, pos.toMC()) ?: 0 - } - - /** - * Gets all of the players in the world, and returns their wrapped versions. - * - * @return the players - */ - @JvmStatic - fun getAllPlayers(): List = toMC()?.players?.map(::PlayerMP) ?: listOf() - - /** - * Gets a player by their username, must be in the currently loaded chunks! - * - * @param name the username - * @return the player with said username, or null if they don't exist. - */ - @JvmStatic - fun getPlayerByName(name: String) = getAllPlayers().firstOrNull { it.getName() == name } - - @JvmStatic - fun hasPlayer(name: String) = getPlayerByName(name) != null - - @JvmStatic - fun getChunk(x: Int, y: Int, z: Int) = Chunk(toMC()!!.getWorldChunk(MCBlockPos(x, y, z))) - - @JvmStatic - fun getAllEntities() = toMC()?.entities?.map(Entity::fromMC) ?: listOf() - - /** - * Gets every entity loaded in the world of a certain class - * - * @param clazz the class to filter for (Use `Java.type().class` to get this) - * @return the entity list - */ - @JvmStatic - fun getAllEntitiesOfType(clazz: Class<*>): List { - return getAllEntities().filter { - clazz.isInstance(it.toMC()) - } - } - - @JvmStatic - fun getAllBlockEntities(): List { - val chunks = toMC() - ?.asMixin() - ?.chunkManager?.asMixin() - ?.chunks?.asMixin() - ?.chunks ?: return emptyList() - - val blockEntities = mutableListOf() - - for (i in 0 until chunks.length()) { - blockEntities += Chunk(chunks.getPlain(i) ?: continue).getAllBlockEntities() - } - - return blockEntities - } - - @JvmStatic - fun getAllBlockEntitiesOfType(clazz: Class<*>): List { - return getAllBlockEntities().filter { - clazz.isInstance(it.toMC()) - } - } - - /** - * Returns the TPS of the current world. - * - * On modern version (1.20.3+), this is variable. On earlier versions, - * it is always 20. - */ - @JvmStatic - fun getTicksPerSecond(): Int { - val mpt = toMC()?.tickManager?.millisPerTick ?: return 20 - return (1000.0 / mpt).roundToInt() - } - - /** - * World border object to get border parameters - */ - class BorderWrapper { - /** - * Gets the border center x location. - * - * @return the border center x location - */ - fun getCenterX(): Double = toMC()!!.worldBorder.centerX - - /** - * Gets the border center z location. - * - * @return the border center z location - */ - fun getCenterZ(): Double = toMC()!!.worldBorder.centerZ - - /** - * Gets the border size. - * - * @return the border size - */ - fun getSize(): Double = toMC()!!.worldBorder.size - - /** - * Gets the border target size. - * - * @return the border target size - */ - fun getTargetSize(): Double = toMC()!!.worldBorder.sizeLerpTarget - - /** - * Gets the border time until the target size is met. - * - * @return the border time until target - */ - fun getTimeUntilTarget(): Long = toMC()!!.worldBorder.sizeLerpTime - } - - /** - * World spawn object for getting spawn location. - */ - class SpawnWrapper { - /** - * Gets the spawn x location. - * - * @return the spawn x location. - */ - fun getX(): Int = toMC()!!.spawnPos.x - - /** - * Gets the spawn y location. - * - * @return the spawn y location. - */ - fun getY(): Int = toMC()!!.spawnPos.y - - /** - * Gets the spawn z location. - * - * @return the spawn z location. - */ - fun getZ(): Int = toMC()!!.spawnPos.z - } - - class ParticleWrapper { - /** - * Gets an array of all the different particle names you can pass - * to [spawnParticle] - * - * @return the array of name strings - */ - fun getParticleNames(): List = Registries.PARTICLE_TYPE.keys.map { it.value.path }.toList() - - /** - * Spawns a particle into the world with the given attributes, - * which can be configured further with the returned [com.chattriggers.ctjs.api.entity.Particle] - * - * @param particle the name of the particle to spawn, see [getParticleNames] - * @param x the x coordinate to spawn the particle at - * @param y the y coordinate to spawn the particle at - * @param z the z coordinate to spawn the particle at - * @param xSpeed the motion the particle should have in the x direction - * @param ySpeed the motion the particle should have in the y direction - * @param zSpeed the motion the particle should have in the z direction - * @return the newly spawned particle for further configuration - */ - fun spawnParticle( - particle: String, - x: Double, - y: Double, - z: Double, - xSpeed: Double, - ySpeed: Double, - zSpeed: Double, - ): Particle? { - val particleType = Registries.PARTICLE_TYPE.get(particle.toIdentifier()) - - requireNotNull(particleType) { - "Invalid particle parameter" - } - - val effect = if (particleType is ParticleEffect) { - particleType - } else { - val blockPos = BlockPos(x, y, z) - val blockState = getBlockStateAt(blockPos) - - when (particleType) { - ParticleTypes.BLOCK -> BlockStateParticleEffect(ParticleTypes.BLOCK, blockState) - ParticleTypes.BLOCK_MARKER -> BlockStateParticleEffect(ParticleTypes.BLOCK_MARKER, blockState) - ParticleTypes.DUST -> DustParticleEffect.DEFAULT - ParticleTypes.DUST_COLOR_TRANSITION -> DustColorTransitionParticleEffect.DEFAULT - ParticleTypes.DUST_PILLAR -> BlockStateParticleEffect(ParticleTypes.DUST_PILLAR, blockState) - ParticleTypes.ENTITY_EFFECT -> EntityEffectParticleEffect.create(ParticleTypes.ENTITY_EFFECT, 1f, 0f, 0f) - ParticleTypes.FALLING_DUST -> BlockStateParticleEffect(ParticleTypes.FALLING_DUST, blockState) - ParticleTypes.ITEM -> ItemStackParticleEffect(ParticleTypes.ITEM, ItemStack(Items.STONE, 1)) - ParticleTypes.SCULK_CHARGE -> SculkChargeParticleEffect(0f) - ParticleTypes.SHRIEK -> ShriekParticleEffect(0) - ParticleTypes.VIBRATION -> VibrationParticleEffect(BlockPositionSource(blockPos.toMC()), 0) - - else -> throw IllegalStateException("Particle not accounted for: $particle") - } - } - - val fx = Client.getMinecraft().particleManager.addParticle( - effect, - x, - y, - z, - xSpeed, - ySpeed, - zSpeed - ) - - return fx?.let(::Particle) - } - - fun spawnParticle(particle: MCParticle): Particle { - Client.getMinecraft().particleManager.addParticle(particle) - return Particle(particle) - } - } -} diff --git a/src/main/kotlin/com/chattriggers/ctjs/api/world/block/Block.kt b/src/main/kotlin/com/chattriggers/ctjs/api/world/block/Block.kt deleted file mode 100644 index ec06dddc..00000000 --- a/src/main/kotlin/com/chattriggers/ctjs/api/world/block/Block.kt +++ /dev/null @@ -1,61 +0,0 @@ -package com.chattriggers.ctjs.api.world.block - -import com.chattriggers.ctjs.api.client.Player -import com.chattriggers.ctjs.api.inventory.Item -import com.chattriggers.ctjs.api.world.World - -/** - * An immutable reference to a placed block in the world. It - * has a block type, a position, and optionally a specific face. - */ -open class Block( - val type: BlockType, - val pos: BlockPos, - val face: BlockFace? = null, -) { - val x: Int get() = pos.x - val y: Int get() = pos.y - val z: Int get() = pos.z - - fun withType(type: BlockType) = Block(type, pos, face) - - fun withPos(pos: BlockPos) = Block(type, pos, face) - - /** - * Narrows this block to reference a certain face. Used by - * [Player.lookingAt] to specify the block face - * being looked at. - */ - fun withFace(face: BlockFace) = Block(type, pos, face) - - fun getState() = World.toMC()?.getBlockState(pos.toMC()) - - @JvmOverloads - fun isEmittingPower(face: BlockFace? = null): Boolean { - if (face != null) - return World.toMC()!!.isEmittingRedstonePower(pos.toMC(), face.toMC()) - return BlockFace.entries.any { isEmittingPower(it) } - } - - @JvmOverloads - fun getEmittingPower(face: BlockFace? = null): Int { - if (face != null) - return World.toMC()!!.getEmittedRedstonePower(pos.toMC(), face.toMC()) - return BlockFace.entries.asSequence().map(::getEmittingPower).firstOrNull { it != 0 } ?: 0 - } - - fun isReceivingPower() = World.toMC()!!.isReceivingRedstonePower(pos.toMC()) - - fun getReceivingPower() = World.toMC()!!.getReceivedRedstonePower(pos.toMC()) - - /** - * Checks whether the block can be mined with the tool in the player's hand - * - * @return whether the block can be mined - */ - fun canBeHarvested(): Boolean = Player.getHeldItem()?.let(::canBeHarvestedWith) ?: false - - fun canBeHarvestedWith(item: Item): Boolean = item.canHarvest(this) - - override fun toString() = "Block{type=$type, pos=($x, $y, $z), face=$face}" -} diff --git a/src/main/kotlin/com/chattriggers/ctjs/api/world/block/BlockFace.kt b/src/main/kotlin/com/chattriggers/ctjs/api/world/block/BlockFace.kt deleted file mode 100644 index 291eaf6a..00000000 --- a/src/main/kotlin/com/chattriggers/ctjs/api/world/block/BlockFace.kt +++ /dev/null @@ -1,132 +0,0 @@ -package com.chattriggers.ctjs.api.world.block - -import com.chattriggers.ctjs.api.CTWrapper -import com.chattriggers.ctjs.api.vec.Vec3i -import net.minecraft.util.StringIdentifiable -import net.minecraft.util.math.Direction -import java.util.function.Predicate - -enum class BlockFace( - private val oppositeIndex: Int, - val axisDirection: AxisDirection, - val axis: Axis, - val directionVec: Vec3i, - override val mcValue: Direction -) : StringIdentifiable, CTWrapper { - DOWN(1, AxisDirection.NEGATIVE, Axis.Y, Vec3i(0, -1, 0), Direction.DOWN), - UP(0, AxisDirection.POSITIVE, Axis.Y, Vec3i(0, 1, 0), Direction.UP), - NORTH(3, AxisDirection.NEGATIVE, Axis.Z, Vec3i(0, 0, -1), Direction.NORTH), - SOUTH(2, AxisDirection.POSITIVE, Axis.Z, Vec3i(0, 0, 1), Direction.SOUTH), - WEST(5, AxisDirection.NEGATIVE, Axis.X, Vec3i(-1, 0, 0), Direction.WEST), - EAST(4, AxisDirection.POSITIVE, Axis.X, Vec3i(1, 0, 0), Direction.EAST); - - fun getOpposite() = entries[oppositeIndex] - - fun getOffsetX() = directionVec.x - - fun getOffsetY() = directionVec.y - - fun getOffsetZ() = directionVec.z - - fun rotateAround(axis: Axis): BlockFace { - return when (axis) { - Axis.X -> if (this != WEST && this != EAST) rotateX() else this - Axis.Y -> if (this != UP && this != DOWN) rotateY() else this - Axis.Z -> if (this != NORTH && this != SOUTH) rotateZ() else this - } - } - - fun rotateX() = when (this) { - DOWN -> SOUTH - UP -> NORTH - NORTH -> DOWN - SOUTH -> UP - else -> throw IllegalStateException("Cannot rotate $this around x-axis") - } - - fun rotateY() = when (this) { - NORTH -> EAST - SOUTH -> WEST - WEST -> NORTH - EAST -> SOUTH - else -> throw IllegalStateException("Cannot rotate $this around y-axis") - } - - fun rotateZ() = when (this) { - DOWN -> WEST - UP -> EAST - WEST -> UP - EAST -> DOWN - else -> throw IllegalStateException("Cannot rotate $this around z-axis") - } - - override fun asString() = name.lowercase() - - enum class Plane : Predicate, Iterable { - HORIZONTAL, - VERTICAL; - - override fun test(t: BlockFace) = t.axis.plane == this - - fun facings() = when (this) { - HORIZONTAL -> arrayOf(NORTH, EAST, WEST, SOUTH) - VERTICAL -> arrayOf(UP, DOWN) - } - - override fun iterator() = facings().iterator() - } - - enum class AxisDirection( - val offset: Int, - override val mcValue: Direction.AxisDirection, - ) : CTWrapper { - POSITIVE(1, Direction.AxisDirection.POSITIVE), - NEGATIVE(-1, Direction.AxisDirection.NEGATIVE); - - companion object { - @JvmStatic - fun fromMC(axisDirection: Direction.AxisDirection) = when (axisDirection) { - Direction.AxisDirection.POSITIVE -> POSITIVE - Direction.AxisDirection.NEGATIVE -> NEGATIVE - } - } - } - - enum class Axis( - val plane: Plane, - override val mcValue: Direction.Axis, - ) : Predicate, StringIdentifiable, CTWrapper { - X(Plane.HORIZONTAL, Direction.Axis.X), - Y(Plane.VERTICAL, Direction.Axis.Y), - Z(Plane.HORIZONTAL, Direction.Axis.Z); - - fun isHorizontal() = plane == Plane.HORIZONTAL - - fun isVertical() = plane == Plane.VERTICAL - - override fun test(t: BlockFace) = t.axis == this - - override fun asString() = name.lowercase() - - companion object { - @JvmStatic - fun fromMC(axis: Direction.Axis) = when (axis) { - Direction.Axis.X -> X - Direction.Axis.Y -> Y - Direction.Axis.Z -> Z - } - } - } - - companion object { - @JvmStatic - fun fromMC(facing: Direction) = when (facing) { - Direction.DOWN -> DOWN - Direction.UP -> UP - Direction.NORTH -> NORTH - Direction.SOUTH -> SOUTH - Direction.WEST -> WEST - Direction.EAST -> EAST - } - } -} diff --git a/src/main/kotlin/com/chattriggers/ctjs/api/world/block/BlockPos.kt b/src/main/kotlin/com/chattriggers/ctjs/api/world/block/BlockPos.kt deleted file mode 100644 index 3a0f5aef..00000000 --- a/src/main/kotlin/com/chattriggers/ctjs/api/world/block/BlockPos.kt +++ /dev/null @@ -1,71 +0,0 @@ -package com.chattriggers.ctjs.api.world.block - -import com.chattriggers.ctjs.api.CTWrapper -import com.chattriggers.ctjs.api.entity.Entity -import com.chattriggers.ctjs.api.vec.Vec3i -import com.chattriggers.ctjs.MCBlockPos -import net.minecraft.util.math.Vec3d -import kotlin.math.floor -import kotlin.math.sqrt - -class BlockPos(x: Int, y: Int, z: Int) : Vec3i(x, y, z), CTWrapper { - override val mcValue = MCBlockPos(x, y, z) - - constructor(x: Number, y: Number, z: Number) : this( - floor(x.toDouble()).toInt(), - floor(y.toDouble()).toInt(), - floor(z.toDouble()).toInt() - ) - - constructor(pos: Vec3i) : this(pos.x, pos.y, pos.z) - - constructor(pos: MCBlockPos) : this(pos.x, pos.y, pos.z) - - constructor(source: Entity) : this(source.getPos()) - - override fun translated(dx: Int, dy: Int, dz: Int) = BlockPos(super.translated(dx, dy, dz)) - - override fun scaled(scale: Int) = BlockPos(super.scaled(scale)) - - override fun scaled(xScale: Int, yScale: Int, zScale: Int) = BlockPos(super.scaled(xScale, yScale, zScale)) - - override fun crossProduct(other: Vec3i) = BlockPos(super.crossProduct(other)) - - override operator fun unaryMinus() = BlockPos(super.unaryMinus()) - - override operator fun plus(other: Vec3i) = BlockPos(super.plus(other)) - - override operator fun minus(other: Vec3i) = BlockPos(super.minus(other)) - - @JvmOverloads - fun up(n: Int = 1) = offset(BlockFace.UP, n) - - @JvmOverloads - fun down(n: Int = 1) = offset(BlockFace.DOWN, n) - - @JvmOverloads - fun north(n: Int = 1) = offset(BlockFace.NORTH, n) - - @JvmOverloads - fun south(n: Int = 1) = offset(BlockFace.SOUTH, n) - - @JvmOverloads - fun east(n: Int = 1) = offset(BlockFace.EAST, n) - - @JvmOverloads - fun west(n: Int = 1) = offset(BlockFace.WEST, n) - - @JvmOverloads - fun offset(facing: BlockFace, n: Int = 1): BlockPos { - return BlockPos(x + facing.getOffsetX() * n, y + facing.getOffsetY() * n, z + facing.getOffsetZ() * n) - } - - fun distanceTo(other: BlockPos): Double { - val x = (mcValue.x - other.x).toDouble() - val y = (mcValue.y - other.y).toDouble() - val z = (mcValue.z - other.z).toDouble() - return sqrt(x * x + y * y + z * z) - } - - fun toVec3d() = Vec3d(x.toDouble(), y.toDouble(), z.toDouble()) -} diff --git a/src/main/kotlin/com/chattriggers/ctjs/api/world/block/BlockType.kt b/src/main/kotlin/com/chattriggers/ctjs/api/world/block/BlockType.kt deleted file mode 100644 index cbda3351..00000000 --- a/src/main/kotlin/com/chattriggers/ctjs/api/world/block/BlockType.kt +++ /dev/null @@ -1,71 +0,0 @@ -package com.chattriggers.ctjs.api.world.block - -import com.chattriggers.ctjs.api.CTWrapper -import com.chattriggers.ctjs.api.inventory.Item -import com.chattriggers.ctjs.api.inventory.ItemType -import com.chattriggers.ctjs.api.message.TextComponent -import com.chattriggers.ctjs.MCBlock -import com.chattriggers.ctjs.MCItem -import com.chattriggers.ctjs.internal.utils.toIdentifier -import net.minecraft.registry.Registries - -/** - * An immutable wrapper around Minecraft's Block object. Note - * that this references a block "type", and not an actual block - * in the world. If a reference to a particular block is needed, - * use [Block] - */ -class BlockType(override val mcValue: MCBlock) : CTWrapper { - constructor(block: BlockType) : this(block.mcValue) - - constructor(blockName: String) : this(Registries.BLOCK[blockName.toIdentifier()]) - - constructor(blockID: Int) : this(ItemType(MCItem.byRawId(blockID)).getRegistryName()) - - constructor(item: Item) : this(MCBlock.getBlockFromItem(item.mcValue.item)) - - /** - * Returns a [Block] based on this block and the - * provided BlockPos - * - * @param blockPos the block position - * @return a [Block] object - */ - fun withBlockPos(blockPos: BlockPos) = Block(this, blockPos) - - fun getID(): Int = Registries.BLOCK.indexOf(mcValue) - - /** - * Gets the block's registry name. - * Example: minecraft:oak_planks - * - * @return the block's registry name - */ - fun getRegistryName(): String = Registries.BLOCK.getId(mcValue).toString() - - /** - * Gets the block's translation key. - * Example: block.minecraft.oak_planks - * - * @return the block's translation key - */ - fun getTranslationKey(): String = mcValue.translationKey - - /** - * Gets the block's localized name. - * Example: Wooden Planks - * - * @return the block's localized name - */ - fun getName() = TextComponent(mcValue.name).formattedText - - fun getLightValue(): Int = getDefaultState().luminance - - fun getDefaultState() = mcValue.defaultState - - fun canProvidePower() = getDefaultState().emitsRedstonePower() - - fun isTranslucent() = getDefaultState().hasSidedTransparency() - - override fun toString(): String = "BlockType{${getRegistryName()}}" -} diff --git a/src/main/kotlin/com/chattriggers/ctjs/engine/Console.kt b/src/main/kotlin/com/chattriggers/ctjs/engine/Console.kt index e594e98d..37ed616f 100644 --- a/src/main/kotlin/com/chattriggers/ctjs/engine/Console.kt +++ b/src/main/kotlin/com/chattriggers/ctjs/engine/Console.kt @@ -1,6 +1,5 @@ package com.chattriggers.ctjs.engine -import com.chattriggers.ctjs.api.Config import com.chattriggers.ctjs.internal.console.ConsoleHostProcess import kotlinx.serialization.Serializable import org.mozilla.javascript.WrappedException @@ -12,6 +11,7 @@ object Console { fun clear() = ConsoleHostProcess.clear() fun println(obj: Any, logType: LogType, end: String, customColor: Color?) = ConsoleHostProcess.println(obj, logType, end, customColor) + fun println(obj: Any, logType: LogType, end: String) = ConsoleHostProcess.println(obj, logType, end, null) fun println(obj: Any, logType: LogType) = println(obj, logType, "\n") fun println(obj: Any) = println(obj, LogType.INFO) @@ -19,8 +19,6 @@ object Console { fun printStackTrace(error: Throwable) = ConsoleHostProcess.printStackTrace(error) fun show() = ConsoleHostProcess.show() fun close() = ConsoleHostProcess.close() - fun onConsoleSettingsChanged(settings: Config.ConsoleSettings) = - ConsoleHostProcess.onConsoleSettingsChanged(settings) } @Serializable diff --git a/src/main/kotlin/com/chattriggers/ctjs/engine/MixinCallback.kt b/src/main/kotlin/com/chattriggers/ctjs/engine/MixinCallback.kt deleted file mode 100644 index 8c8ffe87..00000000 --- a/src/main/kotlin/com/chattriggers/ctjs/engine/MixinCallback.kt +++ /dev/null @@ -1,20 +0,0 @@ -package com.chattriggers.ctjs.engine - -import com.chattriggers.ctjs.internal.launch.IInjector -import java.lang.invoke.MethodHandle -import java.lang.invoke.SwitchPoint - -data class MixinCallback(internal val id: Int, internal val injector: IInjector) { - internal var method: Any? = null - internal var handle: MethodHandle? = null - internal var invalidator = SwitchPoint() - - fun attach(method: Any) { - this.method = method - - // The target method of this mixin has changed, so we need to re-initialize the invokedynamic instruction tied - // to this callback - SwitchPoint.invalidateAll(arrayOf(invalidator)) - invalidator = SwitchPoint() - } -} diff --git a/src/main/kotlin/com/chattriggers/ctjs/engine/Register.kt b/src/main/kotlin/com/chattriggers/ctjs/engine/Register.kt index 85f1c517..5765c34f 100644 --- a/src/main/kotlin/com/chattriggers/ctjs/engine/Register.kt +++ b/src/main/kotlin/com/chattriggers/ctjs/engine/Register.kt @@ -4,31 +4,34 @@ import com.chattriggers.ctjs.api.triggers.* @Suppress("unused", "MemberVisibilityCanBePrivate") object Register { - private val methodMap = Register::class.java.methods.filter { - it.name.startsWith("register") && it.name.length > "register".length - }.associateBy { - it.name.lowercase().drop("register".length) + private val methodMap: MutableMap = mutableMapOf() + + init { + TriggerType.entries.forEach { entry -> + methodMap[entry.name.lowercase().replace("_", "")] = entry + } + + RenderContextTriggerType.entries.forEach { entry -> + methodMap["render" + entry.name.lowercase().replace("_", "")] = entry + } } + private val customTriggers = mutableSetOf() internal fun clearCustomTriggers() = customTriggers.clear() /** - * Helper method register a trigger. - * - * Called by taking the original name of the method, i.e. `registerChat`, - * removing the word register, and comparing it case-insensitively with - * the methods below. + * Helper method to register a trigger. * * @param triggerType the type of trigger - * @param method The name of the method or the actual method to callback when the event is fired + * @param method the actual method to callback when the event is fired * @return The trigger for additional modification */ @JvmStatic fun register(triggerType: String, method: Any): Trigger { val type = triggerType.lowercase() - methodMap[type]?.let { return it.invoke(this, method) as Trigger } + methodMap[type]?.let { return RegularTrigger(method, it) } val customType = CustomTriggerType(type) if (customType in customTriggers) @@ -47,712 +50,4 @@ object Register { fun trigger(vararg args: Any?) = customType.triggerAll(*args) } } - - /** - * Registers a new trigger that runs before a chat message is received. - * - * Passes through multiple arguments: - * - Any number of chat criteria variables - * - The chat event, which can be cancelled - * - * Available modifications: - * - [ChatTrigger.triggerIfCanceled] Sets if triggered if event is already cancelled - * - [ChatTrigger.setChatCriteria] Sets the chat criteria - * - [ChatTrigger.setParameter] Sets the chat parameter - * - [Trigger.setPriority] Sets the priority - * - * @param method The method to call when the event is fired - * @return The trigger for additional modification - */ - @JvmStatic - fun registerChat(method: Any): Trigger { - return ChatTrigger(method, TriggerType.CHAT) - } - - /** - * Registers a new trigger that runs before an action bar message is received. - * - * Passes through multiple arguments: - * - Any number of chat criteria variables - * - The chat event, which can be cancelled - * - * Available modifications: - * - [ChatTrigger.triggerIfCanceled] Sets if triggered if event is already cancelled - * - [ChatTrigger.setChatCriteria] Sets the chat criteria - * - [ChatTrigger.setParameter] Sets the chat parameter - * - [Trigger.setPriority] Sets the priority - * - * @param method The method to call when the event is fired - * @return The trigger for additional modification - */ - @JvmStatic - fun registerActionBar(method: Any): Trigger { - return ChatTrigger(method, TriggerType.ACTION_BAR) - } - - /** - * Registers a trigger that runs before the world loads. - * - * Available modifications: - * - [Trigger.setPriority] Sets the priority - * - * @param method The method to call when the event is fired - * @return The trigger for additional modification - */ - @JvmStatic - fun registerWorldLoad(method: Any): Trigger { - return RegularTrigger(method, TriggerType.WORLD_LOAD) - } - - /** - * Registers a new trigger that runs before the world unloads. - * - * Available modifications: - * - [Trigger.setPriority] Sets the priority - * - * @param method The method to call when the event is fired - * @return The trigger for additional modification - */ - @JvmStatic - fun registerWorldUnload(method: Any): Trigger { - return RegularTrigger(method, TriggerType.WORLD_UNLOAD) - } - - /** - * Registers a new trigger that runs before a mouse button is being pressed or released. - * - * Passes through four arguments: - * - The mouse x position - * - The mouse y position - * - The mouse button - * - The mouse button state (true if button is pressed, false otherwise) - * - * Available modifications: - * - [Trigger.setPriority] Sets the priority - * - * @param method The method to call when the event is fired - * @return The trigger for additional modification - */ - @JvmStatic - fun registerClicked(method: Any): Trigger { - return RegularTrigger(method, TriggerType.CLICKED) - } - - /** - * Registers a new trigger that runs before the mouse is scrolled. - * - * Passes through three arguments: - * - The mouse x position - * - The mouse y position - * - The scroll amount - * - * Available modifications: - * - [Trigger.setPriority] Sets the priority - * - * @param method The method to call when the event is fired - * @return The trigger for additional modification - */ - @JvmStatic - fun registerScrolled(method: Any): Trigger { - return RegularTrigger(method, TriggerType.SCROLLED) - } - - /** - * Registers a new trigger that runs while a mouse button is being held down. - * - * Passes through five arguments: - * - The mouse delta x position (relative to last frame) - * - The mouse delta y position (relative to last frame) - * - The mouse x position - * - The mouse y position - * - The mouse button - * - * Available modifications: - * - [Trigger.setPriority] Sets the priority - * - * @param method The method to call when the event is fired - * @return The trigger for additional modification - */ - @JvmStatic - fun registerDragged(method: Any): Trigger { - return RegularTrigger(method, TriggerType.DRAGGED) - } - - /** - * Registers a new trigger that runs before a sound is played. - * - * Passes through six arguments: - * - The sound event's position - * - The sound event's name - * - The sound event's volume - * - The sound event's pitch - * - The sound event's category's name - * - The sound event, which can be cancelled - * - * Available modifications: - * - [SoundPlayTrigger.setCriteria] Sets the sound name criteria - * - [Trigger.setPriority] Sets the priority - * - * @param method The method to call when the event is fired - * @return The trigger for additional modification - */ - @JvmStatic - fun registerSoundPlay(method: Any): Trigger { - return SoundPlayTrigger(method) - } - - /** - * Registers a new trigger that runs before every game tick. - * - * Passes through one argument: - * - Ticks elapsed - * - * Available modifications: - * - [Trigger.setPriority] Sets the priority - * - * @param method The method to call when the event is fired - * @return The trigger for additional modification - */ - @JvmStatic - fun registerTick(method: Any): Trigger { - return RegularTrigger(method, TriggerType.TICK) - } - - /** - * Registers a new trigger that runs in predictable intervals. (60 per second by default) - * - * Passes through one argument: - * - Steps elapsed - * - * Available modifications: - * - [StepTrigger.setFps] Sets the fps, i.e. how many times this trigger will fire - * per second - * - [StepTrigger.setDelay] Sets the delay in seconds, i.e. how many seconds it takes - * to fire. Overrides [StepTrigger.setFps]. - * - [Trigger.setPriority] Sets the priority - * - * @param method The method to call when the event is fired - * @return The trigger for additional modification - */ - @JvmStatic - fun registerStep(method: Any): Trigger { - return StepTrigger(method) - } - - @Deprecated("Use renderPreWorld", ReplaceWith("registerPreRenderWorld")) - @JvmStatic - fun registerRenderWorld(method: Any) = registerPreRenderWorld(method) - - /** - * Registers a new trigger that runs before the world is drawn. - * - * Passes through one argument: - * - Partial ticks elapsed - * - * Available modifications: - * - [Trigger.setPriority] Sets the priority - * - * @param method The method to call when the event is fired - * @return The trigger for additional modification - */ - @JvmStatic - fun registerPreRenderWorld(method: Any): Trigger { - return RegularTrigger(method, TriggerType.PRE_RENDER_WORLD) - } - - /** - * Registers a new trigger that runs after the world is drawn. - * - * Passes through one argument: - * - Partial ticks elapsed - * - * Available modifications: - * - [Trigger.setPriority] Sets the priority - * - * @param method The method to call when the event is fired - * @return The trigger for additional modification - */ - @JvmStatic - fun registerPostRenderWorld(method: Any): Trigger { - return RegularTrigger(method, TriggerType.POST_RENDER_WORLD) - } - - /** - * Registers a new trigger that runs before the overlay is drawn. - * - * Available modifications: - * - [Trigger.setPriority] Sets the priority - * - * @param method The method to call when the event is fired - * @return The trigger for additional modification - */ - @JvmStatic - fun registerRenderOverlay(method: Any): Trigger { - return RegularTrigger(method, TriggerType.RENDER_OVERLAY) - } - - /** - * Registers a new trigger that runs before the player list is being drawn. - * - * Passes through one argument: - * - The render event, which can be cancelled - * - * Available modifications: - * - [EventTrigger.triggerIfCanceled] Sets if triggered if event is already cancelled - * - [Trigger.setPriority] Sets the priority - * - * @param method The method to call when the event is fired - * @return The trigger for additional modification - */ - @JvmStatic - fun registerRenderPlayerList(method: Any): Trigger { - return EventTrigger(method, TriggerType.RENDER_PLAYER_LIST) - } - - /** - * Registers a new trigger that runs before the block highlight box is drawn. - * - * Passes through two arguments: - * - The draw block highlight event's position - * - The draw block highlight event, which can be cancelled - * - * Available modifications: - * - [Trigger.setPriority] Sets the priority - * - * @param method The method to call when the event is fired - * @return The trigger for additional modification - */ - @JvmStatic - fun registerDrawBlockHighlight(method: Any): Trigger { - return EventTrigger(method, TriggerType.BLOCK_HIGHLIGHT) - } - - /** - * Registers a new trigger that runs after the game loads. - * - * This runs after the initial loading of the game directly after scripts are - * loaded and after "/ct load" happens. - * - * Available modifications: - * - [Trigger.setPriority] Sets the priority - * - * @param method The method to call when the event is fired - * @return The trigger for additional modification - */ - @JvmStatic - fun registerGameLoad(method: Any): Trigger { - return RegularTrigger(method, TriggerType.GAME_LOAD) - } - - /** - * Registers a new trigger that runs before the game unloads. - * - * This runs before shutdown of the JVM and before "/ct load" happens. - * - * Available modifications: - * - [Trigger.setPriority] Sets the priority - * - * @param method The method to call when the event is fired - * @return The trigger for additional modification - */ - @JvmStatic - fun registerGameUnload(method: Any): Trigger { - return RegularTrigger(method, TriggerType.GAME_UNLOAD) - } - - /** - * Registers a new command that will run the method provided. - * - * Passes through multiple arguments: - * - The arguments supplied to the command by the user - * - * Available modifications: - * - [CommandTrigger.setCommandName] Sets the command name - * - [Trigger.setPriority] Sets the priority - * - * @param method The method to call when the event is fired - * @return The trigger for additional modification - */ - @JvmStatic - fun registerCommand(method: Any): Trigger { - return CommandTrigger(method) - } - - /** - * Registers a new trigger that runs when a new gui is first opened. - * - * Passes through one argument: - * - The [net.minecraft.client.gui.screen.Screen] that was opened - * - The gui opened event, which can be cancelled - * - * Available modifications: - * - [Trigger.setPriority] Sets the priority - * - * @param method The method to call when the event is fired - * @return The trigger for additional modification - */ - @JvmStatic - fun registerGuiOpened(method: Any): Trigger { - return EventTrigger(method, TriggerType.GUI_OPENED) - } - - /** - * Registers a new trigger that runs when a gui is closed. - * - * Passes through one argument: - * - The gui that was closed - * - * Available modifications: - * - [Trigger.setPriority] Sets the priority - * - * @param method The method to call when the event is fired - * @return The trigger for additional modification - */ - @JvmStatic - fun registerGuiClosed(method: Any): Trigger { - return RegularTrigger(method, TriggerType.GUI_CLOSED) - } - - /** - * Registers a new trigger that runs before an item is dropped. - * - * Passes through two arguments: - * - The [com.chattriggers.ctjs.api.inventory.Item] that was dropped - * - Whether the entire stack (true), or just 1 item (false) will be dropped - * - The event, which can be cancelled - * - * Available modifications: - * - [Trigger.setPriority] Sets the priority - * - * @param method The method to call when the event is fired - * @return The trigger for additional modification - */ - @JvmStatic - fun registerDropItem(method: Any): Trigger { - return EventTrigger(method, TriggerType.DROP_ITEM) - } - - /** - * Registers a new trigger that runs before a message is sent in chat. - * - * Passes through two arguments: - * - The message - * - The message event, which can be cancelled - * - * Available modifications: - * - [Trigger.setPriority] Sets the priority - * - * @param method The method to call when the event is fired - * @return The trigger for additional modification - */ - @JvmStatic - fun registerMessageSent(method: Any): Trigger { - return EventTrigger(method, TriggerType.MESSAGE_SENT) - } - - /** - * Registers a new trigger that runs when a tooltip is being rendered. - * This allows for the user to modify what text is in the tooltip, and even the - * ability to cancel rendering completely. Note that you must call - * [com.chattriggers.ctjs.api.inventory.Item.setLore] with the modified lore for - * the changes to take effect. - * - * Passes through three arguments: - * - A list of [com.chattriggers.ctjs.api.message.TextComponent] objects to modify. - * - The [com.chattriggers.ctjs.api.inventory.Item] that this lore is attached to. - * - The cancellable event. - * - * Available modifications: - * - [Trigger.setPriority] Sets the priority - * - * @param method The method to call when the event is fired - * @return The trigger for additional modification - */ - @JvmStatic - fun registerItemTooltip(method: Any): Trigger { - return EventTrigger(method, TriggerType.ITEM_TOOLTIP) - } - - /** - * Registers a new trigger that runs before the player interacts. - * - * Passes through three arguments: - * - The [com.chattriggers.ctjs.api.entity.PlayerInteraction] - * - The object of interaction, depending on the interaction type. Either a - * [com.chattriggers.ctjs.api.entity.Entity], - * [com.chattriggers.ctjs.api.world.block.Block], or - * [com.chattriggers.ctjs.api.inventory.Item], - * - The event, which can be cancelled if the interaction is not BreakBlock - * - * Available modifications: - * - [Trigger.setPriority] Sets the priority - * - * @param method The method to call when the event is fired - * @return The trigger for additional modification - */ - @JvmStatic - fun registerPlayerInteract(method: Any): Trigger { - return EventTrigger(method, TriggerType.PLAYER_INTERACT) - } - - /** - * Registers a new trigger that runs when an entity is damaged by the player - * - * Passes through one argument: - * - The target Entity that is damaged - * - * @param method The method to call when the event is fired - * @return The trigger for additional modification - */ - @JvmStatic - fun registerEntityDamage(method: Any): Trigger { - return RegularTrigger(method, TriggerType.ENTITY_DAMAGE) - } - - /** - * Registers a new trigger that runs when an entity dies - * - * Passes through one argument: - * - The Entity that died - * - * @param method The method to call when the event is fired - * @return The trigger for additional modification - */ - @JvmStatic - fun registerEntityDeath(method: Any): Trigger { - return RegularTrigger(method, TriggerType.ENTITY_DEATH) - } - - /** - * Registers a new trigger that runs as a gui is rendered - * - * Passes through three arguments: - * - The mouse x position - * - The mouse y position - * - The gui - * - * Available modifications: - * - [Trigger.setPriority] Sets the priority - * - * @param method The method to call when the event is fired - * @return The trigger for additional modification - */ - @JvmStatic - fun registerGuiRender(method: Any): Trigger { - return RegularTrigger(method, TriggerType.GUI_RENDER) - } - - /** - * Registers a new trigger that runs whenever a key is typed with a gui open - * - * Passes through four arguments: - * - The character pressed (e.g. 'd') - * - The key code pressed (e.g. 41) - * - The gui - * - The event, which can be cancelled - * - * Available modifications: - * - [Trigger.setPriority] Sets the priority - * - * @param method The method to call when the event is fired - * @return The trigger for additional modification - */ - @JvmStatic - fun registerGuiKey(method: Any): Trigger { - return EventTrigger(method, TriggerType.GUI_KEY) - } - - /** - * Registers a new trigger that runs whenever the mouse is clicked with a - * gui open - * - * Passes through five arguments: - * - The mouse x position - * - The mouse y position - * - The mouse button - * - The mouse button state (true if button is pressed, false otherwise) - * - The gui - * - The event, which can be cancelled - * - * Available modifications: - * - [Trigger.setPriority] Sets the priority - * - * @param method The method to call when the event is fired - * @return The trigger for additional modification - */ - @JvmStatic - fun registerGuiMouseClick(method: Any): Trigger { - return EventTrigger(method, TriggerType.GUI_MOUSE_CLICK) - } - - /** - * Registers a new trigger that runs whenever a mouse button held and dragged - * with a gui open - * - * Passes through seven arguments: - * - The mouse delta x position (relative to last frame) - * - The mouse delta y position (relative to last frame) - * - The mouse x position - * - The mouse y position - * - The mouse button - * - The gui - * - The event, which can be cancelled - * - * Available modifications: - * - [Trigger.setPriority] Sets the priority - * - * @param method The method to call when the event is fired - * @return The trigger for additional modification - */ - @JvmStatic - fun registerGuiMouseDrag(method: Any): Trigger { - return EventTrigger(method, TriggerType.GUI_MOUSE_DRAG) - } - - /** - * Registers a new trigger that runs whenever a packet is sent from the client to the server - * - * Passes through two arguments: - * - The packet - * - The event, which can be cancelled - * - * Available modifications: - * - [Trigger.setPriority] Sets the priority - * - [ClassFilterTrigger.setFilteredClasses] Sets the packet classes which this trigger - * gets fired for - * - * @param method The method to call when the event is fired - * @return The trigger for additional modification - */ - @JvmStatic - fun registerPacketSent(method: Any): Trigger { - return PacketTrigger(method, TriggerType.PACKET_SENT) - } - - /** - * Registers a new trigger that runs whenever a packet is sent to the client from the server - * - * Passes through two arguments: - * - The packet - * - The event, which can be cancelled - * - * Available modifications: - * - [Trigger.setPriority] Sets the priority - * - [ClassFilterTrigger.setFilteredClasses] Sets the packet classes which this trigger - * gets fired for - * - * @param method The method to call when the event is fired - * @return The trigger for additional modification - */ - @JvmStatic - fun registerPacketReceived(method: Any): Trigger { - return PacketTrigger(method, TriggerType.PACKET_RECEIVED) - } - - /** - * Registers a new trigger that runs whenever the player connects to a server - * - * Available modifications: - * - [Trigger.setPriority] Sets the priority - * - * @param method The method to call when the event is fired - * @return The trigger for additional modification - */ - @JvmStatic - fun registerServerConnect(method: Any): Trigger { - return RegularTrigger(method, TriggerType.SERVER_CONNECT) - } - - /** - * Registers a new trigger that runs whenever the player disconnects from a server - * - * Available modifications: - * - [Trigger.setPriority] Sets the priority - * - * @param method The method to call when the event is fired - * @return The trigger for additional modification - */ - @JvmStatic - fun registerServerDisconnect(method: Any): Trigger { - return RegularTrigger(method, TriggerType.SERVER_DISCONNECT) - } - - /** - * Registers a new trigger that runs whenever an entity is rendered - * - * Passes through three arguments: - * - The [com.chattriggers.ctjs.api.entity.Entity] - * - The partial ticks - * - The event, which can be cancelled - * - * Available modifications: - * - [Trigger.setPriority] Sets the priority - * - [ClassFilterTrigger.setFilteredClasses] Sets the entity classes which this trigger - * gets fired for - * - * @param method The method to call when the event is fired - * @return The trigger for additional modification - */ - @JvmStatic - fun registerRenderEntity(method: Any): Trigger { - return RenderEntityTrigger(method) - } - - /** - * Registers a new trigger that runs whenever a block entity is rendered - * - * Passes through three arguments: - * - The [com.chattriggers.ctjs.api.entity.BlockEntity] - * - The partial ticks - * - The event, which can be cancelled - * - * Available modifications: - * - [Trigger.setPriority] Sets the priority - * - [ClassFilterTrigger.setFilteredClasses] Sets the tile entity classes which this trigger - * gets fired for - * - * @param method The method to call when the event is fired - * @return The trigger for additional modification - */ - @JvmStatic - fun registerRenderBlockEntity(method: Any): Trigger { - return RenderBlockEntityTrigger(method) - } - - /** - * Registers a new trigger that runs after the current screen is rendered - * - * Passes through three arguments: - * - The mouseX - * - The mouseY - * - The GuiScreen - * - * Available modifications: - * - [Trigger.setPriority] Sets the priority - * - * @param method The method to call when the event is fired - * @return The trigger for additional modification - */ - @JvmStatic - fun registerPostGuiRender(method: Any): Trigger { - return RegularTrigger(method, TriggerType.POST_GUI_RENDER) - } - - /** - * Registers a new trigger that runs whenever a particle is spawned - * - * Passes through two arguments: - * - The [com.chattriggers.ctjs.api.entity.Particle] - * - The event, which can be cancelled - * - * Available modifications: - * - [Trigger.setPriority] Sets the priority - * - * @param method The method to call when the event is fired - * @return The trigger for additional modification - */ - @JvmStatic - fun registerSpawnParticle(method: Any): Trigger { - return EventTrigger(method, TriggerType.SPAWN_PARTICLE) - } } diff --git a/src/main/kotlin/com/chattriggers/ctjs/internal/commands/CTCommand.kt b/src/main/kotlin/com/chattriggers/ctjs/internal/commands/CTCommand.kt index 13d7777c..ab718d0f 100644 --- a/src/main/kotlin/com/chattriggers/ctjs/internal/commands/CTCommand.kt +++ b/src/main/kotlin/com/chattriggers/ctjs/internal/commands/CTCommand.kt @@ -1,45 +1,32 @@ package com.chattriggers.ctjs.internal.commands import com.chattriggers.ctjs.CTJS -import com.chattriggers.ctjs.api.Config -import com.chattriggers.ctjs.api.client.Client -import com.chattriggers.ctjs.api.client.FileLib -import com.chattriggers.ctjs.api.message.ChatLib -import com.chattriggers.ctjs.api.message.TextComponent +import com.chattriggers.ctjs.api.FileLib import com.chattriggers.ctjs.engine.Console -import com.chattriggers.ctjs.engine.printTraceToConsole -import com.chattriggers.ctjs.internal.commands.StaticCommand.Companion.onExecute +import com.chattriggers.ctjs.internal.engine.module.ModuleListScreen import com.chattriggers.ctjs.internal.engine.module.ModuleManager -import com.chattriggers.ctjs.internal.engine.module.ModulesGui import com.chattriggers.ctjs.internal.listeners.ClientListener import com.chattriggers.ctjs.internal.utils.Initializer -import com.chattriggers.ctjs.internal.utils.toVersion +import com.chattriggers.ctjs.internal.utils.onExecute import com.mojang.brigadier.CommandDispatcher import com.mojang.brigadier.StringReader import com.mojang.brigadier.arguments.ArgumentType -import com.mojang.brigadier.arguments.IntegerArgumentType import com.mojang.brigadier.arguments.StringArgumentType import com.mojang.brigadier.context.CommandContext -import com.mojang.brigadier.exceptions.CommandSyntaxException import com.mojang.brigadier.exceptions.SimpleCommandExceptionType import com.mojang.brigadier.suggestion.Suggestions import com.mojang.brigadier.suggestion.SuggestionsBuilder -import net.fabricmc.fabric.api.client.command.v2.ClientCommandManager.argument -import net.fabricmc.fabric.api.client.command.v2.ClientCommandManager.literal import net.fabricmc.fabric.api.client.command.v2.ClientCommandRegistrationCallback +import net.fabricmc.fabric.api.client.command.v2.ClientCommands.argument +import net.fabricmc.fabric.api.client.command.v2.ClientCommands.literal import net.fabricmc.fabric.api.client.command.v2.FabricClientCommandSource -import net.minecraft.command.CommandSource -import net.minecraft.text.ClickEvent -import net.minecraft.text.HoverEvent -import net.minecraft.text.Text -import java.io.File -import java.io.IOException +import net.minecraft.client.Minecraft +import net.minecraft.commands.SharedSuggestionProvider +import net.minecraft.network.chat.Component import java.util.concurrent.CompletableFuture -import kotlin.concurrent.thread internal object CTCommand : Initializer { - private const val idFixed = 90123 // ID for dumped chat - private var idFixedOffset = -1 // ID offset (increments) + private val mc = Minecraft.getInstance() override fun init() { ClientCommandRegistrationCallback.EVENT.register { dispatcher, _ -> @@ -49,220 +36,38 @@ internal object CTCommand : Initializer { fun register(dispatcher: CommandDispatcher) { val command = literal("ct") - .then(literal("load").onExecute { CTJS.load(asCommand = true) }) - .then(literal("unload").onExecute { CTJS.unload(asCommand = true) }) - .then(literal("files").onExecute { openFileLocation() }) - .then( - literal("import") - .then(argument("module", StringArgumentType.string()) - .onExecute { import(StringArgumentType.getString(it, "module")) }) - ) + .then(literal("load").onExecute { CTJS.load() }) + .then(literal("unload").onExecute { CTJS.unload() }) + .then(literal("files").onExecute { FileLib.openModulesFolder() }) .then( literal("delete") - .then(argument("module", ModuleArgumentType) - .onExecute { - val module = ModuleArgumentType.getModule(it, "module") - if (ModuleManager.deleteModule(module)) { - ChatLib.chat("&aDeleted $module") - } else ChatLib.chat("&cFailed to delete $module") - }) + .then( + argument("module", ModuleArgumentType) + .onExecute { + val module = ModuleArgumentType.getModule(it, "module") + if (ModuleManager.deleteModule(module)) { + mc.player?.sendSystemMessage(Component.nullToEmpty("&aDeleted $module")) + } else mc.player?.sendSystemMessage(Component.nullToEmpty("&cFailed to delete $module")) + }) ) - .then(literal("modules").onExecute { Client.currentGui.set(ModulesGui) }) .then(literal("console").onExecute { Console.show() }) - .then(literal("config").onExecute { Client.currentGui.set(Config.gui()!!) }) .then( literal("simulate") .then( argument("message", StringArgumentType.greedyString()) - .onExecute { ChatLib.simulateChat(StringArgumentType.getString(it, "message")) } - ) - ) - .then( - literal("dump") - .then( - argument("type", StringArgumentType.word()) - .then( - argument("amount", IntegerArgumentType.integer(0)) - .onExecute { - dump( - DumpType.fromString(StringArgumentType.getString(it, "type")), - IntegerArgumentType.getInteger(it, "amount") - ) - } - ).onExecute { - dump(DumpType.fromString(StringArgumentType.getString(it, "type"))) - } - ) - .onExecute { dump(DumpType.CHAT) } - ) - .then( - literal("migrate") - .then( - argument("input", FileArgumentType(File(CTJS.MODULES_FOLDER))) - .then( - argument("output", FileArgumentType(File(CTJS.MODULES_FOLDER))) - .onExecute { - val input = FileArgumentType.getFile(it, "input") - val output = FileArgumentType.getFile(it, "output") - Migration.migrate(input, output) - } - ) .onExecute { - val input = FileArgumentType.getFile(it, "input") - Migration.migrate(input, input) + val msg = StringArgumentType.getString(it, "message") + mc.chatListener.handleSystemMessage(Component.literal(msg), false) } ) ) - .onExecute { ChatLib.chat(getUsage()) } - - dispatcher.register(command) - } - - private fun import(moduleName: String) { - if (ModuleManager.cachedModules.any { it.name.equals(moduleName, ignoreCase = true) }) { - ChatLib.chat("&cModule $moduleName is already installed!") - } else { - ChatLib.chat("&cImporting $moduleName...") - thread { - val (module, dependencies) = ModuleManager.importModule(moduleName) - if (module == null) { - ChatLib.chat("&cUnable to import module $moduleName") - return@thread + .then(literal("modules").onExecute { + ClientListener.addTask(0) { + mc.setScreen(ModuleListScreen()) } - - val allModules = listOf(module) + dependencies - val modVersion = CTJS.MOD_VERSION.toVersion() - allModules.forEach { - val version = it.targetModVersion ?: return@forEach - if (version.majorVersion < modVersion.majorVersion) - ModuleManager.tryReportOldVersion(it) - } - - ChatLib.chat("&aSuccessfully imported ${module.metadata.name ?: module.name}") - if (Config.moduleImportHelp && module.metadata.helpMessage != null) { - ChatLib.chat(module.metadata.helpMessage.toString().take(383)) - } - } - } - } - - private fun getUsage() = """ - &b&m${ChatLib.getChatBreak()} - &c/ct load &7- &oReloads all of the ChatTriggers modules. - &c/ct import &7- &oImports a module. - &c/ct delete &7- &oDeletes a module. - &c/ct files &7- &oOpens the ChatTriggers folder. - &c/ct modules &7- &oOpens the modules GUI. - &c/ct console [language] &7- &oOpens the ChatTriggers console. - &c/ct simulate &7- &oSimulates a received chat message. - &c/ct dump &7- &oDumps previous chat messages into chat. - &c/ct settings &7- &oOpens the ChatTriggers settings. - &c/ct migrate [output]&7 - &oMigrate a module from version 2.X to 3.X - &c/ct &7- &oDisplays this help dialog. - &b&m${ChatLib.getChatBreak()} - """.trimIndent() - - private fun openFileLocation() { - try { - FileLib.open(ModuleManager.modulesFolder) - } catch (exception: IOException) { - exception.printTraceToConsole() - ChatLib.chat("&cCould not open file location") - } - } - - private fun dump(type: DumpType, lines: Int = 100) { - clearOldDump() - - val messages = type.messageList() - val toDump = lines.coerceAtMost(messages.size) - TextComponent("&6&m${ChatLib.getChatBreak()}").withChatLineId(idFixed).chat() - - for (i in 0 until toDump) { - val msg = ChatLib.replaceFormatting(messages[messages.size - toDump + i].formattedText) - TextComponent(Text.literal(msg).styled { - it.withClickEvent(ClickEvent(ClickEvent.Action.COPY_TO_CLIPBOARD, msg)) - .withHoverEvent( - HoverEvent( - HoverEvent.Action.SHOW_TEXT, - TextComponent("&eClick here to copy this message.") - ) - ) }) - .withChatLineId(idFixed + i + 1) - .chat() - } - - TextComponent("&6&m${ChatLib.getChatBreak()}").withChatLineId(idFixed + lines + 1).chat() - - idFixedOffset = idFixed + lines + 1 - } - - private fun clearOldDump() { - if (idFixedOffset == -1) return - while (idFixedOffset >= idFixed) - ChatLib.deleteChat(idFixedOffset--) - idFixedOffset = -1 - } - - enum class DumpType(val messageList: () -> List) { - CHAT(ClientListener::chatHistory), - ACTION_BAR(ClientListener::actionBarHistory); - - companion object { - fun fromString(str: String) = DumpType.entries.first { it.name.equals(str, ignoreCase = true) } - } - } - - private class FileArgumentType(private val relativeTo: File) : ArgumentType { - override fun parse(reader: StringReader): File { - val isquoted = StringReader.isQuotedStringStart(reader.peek()) - val path = if (isquoted) { - reader.readQuotedString() - } else reader.readStringUntilOrEof(' ') - return File(relativeTo, path) - } - - override fun getExamples(): MutableCollection { - return mutableListOf( - "/foo/bar/baz", - "C:\\foo\\bar\\baz", - "\"/path/with/spaces in the name\"", - ) - } - // Copy and pasted from StringReader, but doesn't throw on EOF - fun StringReader.readStringUntilOrEof(terminator: Char): String { - val result = StringBuilder() - var escaped = false - while (canRead()) { - val c = read() - when { - escaped -> { - escaped = if (c == terminator || c == '\\') { - result.append(c) - false - } else { - cursor -= 1 - throw CommandSyntaxException.BUILT_IN_EXCEPTIONS.readerInvalidEscape() - .createWithContext(this, c.toString()) - } - } - c == '\\' -> escaped = true - c == terminator -> { - cursor -= 1 - return result.toString() - } - else -> result.append(c) - } - } - - return result.toString() - } - - companion object { - fun getFile(ctx: CommandContext<*>, name: String) = ctx.getArgument(name, File::class.java) - } + dispatcher.register(command) } private object ModuleArgumentType : ArgumentType { @@ -272,15 +77,15 @@ internal object CTCommand : Initializer { return modules.find { it.equals(string, ignoreCase = true) - } ?: throw SimpleCommandExceptionType(Text.literal("No modules found with name \"$string\"")) + } ?: throw SimpleCommandExceptionType(Component.literal("No modules found with name \"$string\"")) .createWithContext(reader) } override fun listSuggestions( context: CommandContext?, - builder: SuggestionsBuilder? + builder: SuggestionsBuilder ): CompletableFuture { - return CommandSource.suggestMatching(ModuleManager.cachedModules.map { it.name }, builder) + return SharedSuggestionProvider.suggest(ModuleManager.cachedModules.map { it.name }, builder) } fun getModule(ctx: CommandContext, module: String): String { diff --git a/src/main/kotlin/com/chattriggers/ctjs/internal/commands/Command.kt b/src/main/kotlin/com/chattriggers/ctjs/internal/commands/Command.kt deleted file mode 100644 index 35b89494..00000000 --- a/src/main/kotlin/com/chattriggers/ctjs/internal/commands/Command.kt +++ /dev/null @@ -1,28 +0,0 @@ -package com.chattriggers.ctjs.internal.commands - -import com.chattriggers.ctjs.internal.mixins.commands.CommandNodeAccessor -import com.chattriggers.ctjs.internal.utils.asMixin -import com.mojang.brigadier.CommandDispatcher -import com.mojang.brigadier.arguments.ArgumentType -import com.mojang.brigadier.builder.LiteralArgumentBuilder -import com.mojang.brigadier.builder.RequiredArgumentBuilder -import net.minecraft.command.CommandSource - -interface Command { - val overrideExisting: Boolean - val name: String - - fun registerImpl(dispatcher: CommandDispatcher) - - fun unregisterImpl(dispatcher: CommandDispatcher) { - dispatcher.root.asMixin().apply { - childNodes.remove(name) - literals.remove(name) - } - } -} - -fun literal(name: String) = LiteralArgumentBuilder.literal(name) - -fun argument(name: String, argument: ArgumentType) = - RequiredArgumentBuilder.argument(name, argument) diff --git a/src/main/kotlin/com/chattriggers/ctjs/internal/commands/CommandCollection.kt b/src/main/kotlin/com/chattriggers/ctjs/internal/commands/CommandCollection.kt deleted file mode 100644 index 18ed464c..00000000 --- a/src/main/kotlin/com/chattriggers/ctjs/internal/commands/CommandCollection.kt +++ /dev/null @@ -1,73 +0,0 @@ -package com.chattriggers.ctjs.internal.commands - -import com.chattriggers.ctjs.engine.LogType -import com.chattriggers.ctjs.engine.printToConsole -import com.chattriggers.ctjs.internal.engine.CTEvents -import com.chattriggers.ctjs.internal.utils.Initializer -import com.mojang.brigadier.CommandDispatcher -import com.mojang.brigadier.builder.ArgumentBuilder -import com.mojang.brigadier.context.CommandContext -import net.fabricmc.fabric.api.client.command.v2.ClientCommandRegistrationCallback -import net.fabricmc.fabric.api.client.networking.v1.ClientPlayConnectionEvents -import net.minecraft.command.CommandSource - -abstract class CommandCollection : Initializer { - private val allCommands = mutableSetOf() - - private var clientDispatcher: CommandDispatcher? = null - private var networkDispatcher: CommandDispatcher? = null - - @Suppress("UNCHECKED_CAST") - override fun init() { - ClientCommandRegistrationCallback.EVENT.register { dispatcher, _ -> - clientDispatcher = dispatcher as CommandDispatcher - allCommands.forEach { it.registerImpl(dispatcher) } - } - - CTEvents.NETWORK_COMMAND_DISPATCHER_REGISTER.register { dispatcher -> - networkDispatcher = dispatcher as CommandDispatcher - allCommands.forEach { it.registerImpl(dispatcher) } - } - - ClientPlayConnectionEvents.DISCONNECT.register { _, _ -> - clientDispatcher = null - networkDispatcher = null - } - } - - fun register(command: Command) { - allCommands.add(command) - if (clientDispatcher.hasConflict(command) || networkDispatcher.hasConflict(command)) { - existingCommandWarning(command.name).printToConsole(LogType.WARN) - } else { - clientDispatcher?.let { command.registerImpl(it) } - networkDispatcher?.let { command.registerImpl(it) } - } - } - - fun unregister(command: Command) { - for (dispatcher in listOfNotNull(clientDispatcher, networkDispatcher)) - command.unregisterImpl(dispatcher) - } - - fun unregisterAll() { - allCommands.forEach(::unregister) - allCommands.clear() - } - - fun > ArgumentBuilder.onExecute(block: (CommandContext) -> Unit): T = - executes { - block(it) - 1 - } - - private fun CommandDispatcher<*>?.hasConflict(command: Command) = - !command.overrideExisting && (this?.root?.getChild(command.name) != null) - - private fun existingCommandWarning(name: String) = - """ - Command with name $name already exists! This will not override the - other command with the same name. To override the other command, set the - overrideExisting flag in setName() (the second argument) to true. - """.trimIndent().replace("\n", "") -} diff --git a/src/main/kotlin/com/chattriggers/ctjs/internal/commands/DynamicCommand.kt b/src/main/kotlin/com/chattriggers/ctjs/internal/commands/DynamicCommand.kt deleted file mode 100644 index 52a41072..00000000 --- a/src/main/kotlin/com/chattriggers/ctjs/internal/commands/DynamicCommand.kt +++ /dev/null @@ -1,113 +0,0 @@ -package com.chattriggers.ctjs.internal.commands - -import com.chattriggers.ctjs.api.commands.DynamicCommands -import com.chattriggers.ctjs.api.commands.RootCommand -import com.chattriggers.ctjs.internal.CTClientCommandSource -import com.chattriggers.ctjs.internal.engine.JSLoader -import com.chattriggers.ctjs.internal.mixins.commands.CommandContextAccessor -import com.chattriggers.ctjs.internal.utils.asMixin -import com.mojang.brigadier.CommandDispatcher -import com.mojang.brigadier.arguments.ArgumentType -import com.mojang.brigadier.builder.ArgumentBuilder -import com.mojang.brigadier.builder.LiteralArgumentBuilder -import com.mojang.brigadier.tree.CommandNode -import com.mojang.brigadier.tree.LiteralCommandNode -import net.fabricmc.fabric.api.client.command.v2.ClientCommandManager -import net.minecraft.command.CommandSource -import org.mozilla.javascript.Function -import org.mozilla.javascript.NativeObject -import org.mozilla.javascript.ScriptableObject - -object DynamicCommand { - sealed class Node(val parent: Node?) { - var method: Function? = null - var hasRedirect = false - val children = mutableListOf() - var builder: ArgumentBuilder? = null - - open class Literal(parent: Node?, val name: String) : Node(parent) - - class Root(name: String) : Literal(null, name), RootCommand { - var commandNode: LiteralCommandNode? = null - - override fun register() { - DynamicCommands.register(CommandImpl(this)) - } - } - - class Argument(parent: Node?, val name: String, val type: ArgumentType<*>) : Node(parent) - - class Redirect(parent: Node?, val target: Root) : Node(parent) - - class RedirectToCommandNode(parent: Node?, val target: CommandNode) : Node(parent) - - fun initialize(dispatcher: CommandDispatcher) { - if (this is Redirect) { - check(method == null) - check(children.isEmpty()) - target.initialize(dispatcher) - - parent!!.builder!!.redirect(target.commandNode) { - for ((name, arg) in it.asMixin().arguments) - it.source.asMixin().setContextValue(name, arg.result) - it.source - } - - return - } - - if (this is RedirectToCommandNode) { - check(method == null) - check(children.isEmpty()) - - parent!!.builder!!.redirect(target) { - for ((name, arg) in it.asMixin().arguments) - it.source.asMixin().setContextValue(name, arg.result) - it.source - } - - return - } - - builder = when (this) { - is Literal -> literal(name) - is Argument -> argument(name, type) - else -> throw IllegalStateException("unreachable") - } - - // The call to .then() below builds a node which check the command, so we - // need to call .execute() and child..initialize() before then if necessary - if (method != null) { - builder!!.executes { ctx -> - val obj = NativeObject() - - for ((key, value) in ctx.source.asMixin().contextValues) - ScriptableObject.putProperty(obj, key, value) - for ((key, arg) in ctx.asMixin().arguments) - ScriptableObject.putProperty(obj, key, arg.result) - - ctx.source.asMixin().contextValues.clear() - - JSLoader.invoke(method!!, arrayOf(obj)) - 1 - } - } - - for (child in children) - child.initialize(dispatcher) - - parent?.builder?.then(builder) - } - } - - class CommandImpl(private val node: Node.Root) : Command { - override val overrideExisting = true - override val name = node.name - - override fun registerImpl(dispatcher: CommandDispatcher) { - node.initialize(dispatcher) - val builder = node.builder!! as LiteralArgumentBuilder - node.commandNode = dispatcher.register(builder) - } - } -} diff --git a/src/main/kotlin/com/chattriggers/ctjs/internal/commands/Migration.kt b/src/main/kotlin/com/chattriggers/ctjs/internal/commands/Migration.kt deleted file mode 100644 index 8a731cc0..00000000 --- a/src/main/kotlin/com/chattriggers/ctjs/internal/commands/Migration.kt +++ /dev/null @@ -1,211 +0,0 @@ -package com.chattriggers.ctjs.internal.commands - -import com.chattriggers.ctjs.api.message.ChatLib -import java.io.File -import java.nio.file.Files - -internal object Migration { - private val migrationPatterns = listOf( - """Renderer\.color\(""".toRegex() to "Renderer.getColor(", - """register\((['"`])renderTileEntity['"`]""".toRegex(RegexOption.IGNORE_CASE) to "register($1renderBlockEntity$1", - """\.setPacketClass\(""".toRegex() to ".setFilteredClass(", - """\.setPacketClasses\(""".toRegex() to ".setFilteredClasses(", - """EventLib\.cancel\((.+?)\)""".toRegex() to "cancel($1)", - """EventLib\.getMessage\((.+?)\)""".toRegex() to "$1.message", - """EntityLivingBase""".toRegex() to "LivingEntity", - """\.getItemInSlot\(""".toRegex() to ".getStackInSlot(", - """TileEntity""".toRegex() to "BlockEntity", - """\.isDurationMax\(""".toRegex() to ".isInfinite(", - """\.isDamagable\(""".toRegex() to ".isDamageable(", - """\.getAllTileEntities\(\)""".toRegex() to ".getAllBlockEntities()", - """\.getAllTileEntitiesOfType\(""".toRegex() to ".getAllBlockEntitiesOfType(", - """\.isPowered\(\)""".toRegex() to ".isReceivingPower()", - """\.getRedstoneStrength\(\)""".toRegex() to ".getReceivingPower()", - """\.fromMCEnumFacing\(""".toRegex() to ".fromMC(", - """Scoreboard\.getScoreboardTitle\(\)""".toRegex() to "Scoreboard.getTitle()", - *listOf("Cape", "Jacket", "LeftSleeve", "RightSleeve", "LeftPantsLeg", "RightPantsLeg", "Hat").map { - """Settings\.skin\.get$it\(\)""".toRegex() to "Settings.skin.is${it}Enabled" - }.toTypedArray(), - """GuiHandler\.openGui\((.+?)\)""".toRegex() to "Client.currentGui.set($1)", - *listOf("Control", "Alt", "Shift").map { - """\.is${it}Down\(\)""".toRegex() to ".has${it}Down()" - }.toTypedArray(), - """TabList\.getFooterMessage\(\)""".toRegex() to "TabList.getFooterComponent()", - """TabList\.getHeaderMessage\(\)""".toRegex() to "TabList.getHeaderComponent()", - """Client\.getChatGUI\(\)""".toRegex() to "Client.getChatGui()", - """Config\.modulesFolder""".toRegex() to "ChatTriggers.MODULES_FOLDER", - ) - - private val removedTriggersRegex = let { - val triggers = setOf( - "screenshotTaken", - "pickupItem", - "chatComponentClicked", - "chatComponentHovered", - "renderSlot", - "guiDrawBackground", - "renderBossHealth", - "renderDebug", - "renderCrosshair", - "renderHotbar", - "renderExperience", - "renderArmor", - "renderHealth", - "renderFood", - "renderMountHealth", - "renderAir", - "renderPortal", - "renderJumpBar", - "renderChat", - "renderHelmet", - "renderHand", - "renderScoreboard", - "renderTitle", - "preItemRender", - "renderItemIntoGui", - "noteBlockPlay", - "noteBlockChange", - "renderItemOverlayIntoGui", - "renderSlotHighlight", - "postRenderEntity", - "postRenderTileEntity", - "attackEntity", - "hitBlock", - "blockBreak", - "guiMouseRelease" - ) - - """ - register\(['"`](${triggers.joinToString("|")})['"`] - """.trimIndent().toRegex(RegexOption.IGNORE_CASE) - } - - private val guiMouseClickRegex = """register\(['"`]guiMouseClick['"`]""".toRegex(RegexOption.IGNORE_CASE) - private val guiMouseDragRegex = """register\(['"`]guiMouseDrag['"`]""".toRegex(RegexOption.IGNORE_CASE) - private val guiOpenedRegex = """register\(['"`]guiOpened['"`]""".toRegex(RegexOption.IGNORE_CASE) - private val renderBlockEntityRegex = """register\(['"`]renderBlockEntity['"`]""".toRegex(RegexOption.IGNORE_CASE) - private val serverConnectRegex = - """register\(['"`](serverConnect|serverDisconnect)['"`]""".toRegex(RegexOption.IGNORE_CASE) - private val scrolledRegex = """register\(['"`]scrolled['"`]""".toRegex(RegexOption.IGNORE_CASE) - private val dropItemRegex = """register\(['"`]dropItem['"`]""".toRegex(RegexOption.IGNORE_CASE) - private val renderEntityRegex = """register\(['"`]renderEntity['"`]""".toRegex(RegexOption.IGNORE_CASE) - private val spawnParticleRegex = """register\(['"`]spawnParticle['"`]""".toRegex(RegexOption.IGNORE_CASE) - private val ctCopyRegex = """(ChatLib\.command\(['"`]ct copy|ChatLib\.say\(['"`]/ct copy)""".toRegex() - private val getRiderRegex = """\.getRider\(\)""".toRegex() - private val isAirborneRegex = """\.isAirborne\(\)""".toRegex() - private val getDimensionRegex = """\.getDimension\(\)""".toRegex() - - fun migrate(input: File, output: File) { - require(input.exists()) { "Input file \"$input\" does not exist" } - - if (input != output) { - require(!output.exists()) { "Output file \"$output\" already exists" } - output.parentFile.mkdirs() - } - - input.walk(FileWalkDirection.TOP_DOWN).forEach { - val dest = File(output, it.toRelativeString(input)) - - if (it.isFile) { - if (it.extension == "js") { - migrateFile(it, dest) - } else { - Files.copy(it.toPath(), dest.toPath()) - } - } else { - dest.mkdir() - } - } - } - - private fun migrateFile(input: File, output: File) { - var text = input.readText() - for ((regex, replacement) in migrationPatterns) - text = text.replace(regex, replacement) - checkForErrors(output, text) - output.writeText(text) - } - - private fun checkForErrors(file: File, inputText: String) { - val text = inputText.replace("\r\n", "\n").replace('\r', '\n') - val errors = collectErrors(text) - val nlIndices = text.withIndex().filter { it.value == '\n' }.map { it.index } - - for (error in errors) { - val index = nlIndices.indexOfFirst { it > error.first } - val (line, column) = when (index) { - -1 -> nlIndices.size to error.first - nlIndices.last() + 1 - 0 -> 1 to error.first + 1 - else -> index to error.first - nlIndices[index - 1] + 1 - } - - ChatLib.chat("[${file.parentFile.name}${File.separatorChar}${file.name}:$line:$column] ${error.second}") - } - - ChatLib.chat("&oNote: The migrated files are not guaranteed to work") - } - - private fun collectErrors(text: String): List> { - val errors = mutableListOf>() - - removedTriggersRegex.findAll(text).forEach { - errors.add(it.groups[0]!!.range.first to "&6Warning: trigger \"${it.groups[1]!!.value}\" was removed") - } - - fun Regex.warn(block: (MatchResult) -> String) { - findAll(text).forEach { - errors.add(it.groups[0]!!.range.first to "&6Warning: ${block(it)}") - } - } - - fun Regex.error(block: (MatchResult) -> String) { - findAll(text).forEach { - errors.add(it.groups[0]!!.range.first to "&cError: ${block(it)}") - } - } - - guiMouseClickRegex.warn { - "trigger \"guiMouseClick\" activates for both click and release now, and takes an additional boolean " + - "parameter to distinguish the two" - } - - guiMouseDragRegex.warn { "trigger \"guiMouseDrag\" now takes two extra parameters at the start: dx and dy" } - - guiOpenedRegex.warn { "trigger \"guiOpened\" now takes a Screen as its first argument" } - - renderBlockEntityRegex.warn { - "trigger \"renderBlockEntity\" no longer passes in the entity's position as an argument. Access it by " + - "calling `.getBlockPos()`" - } - - serverConnectRegex.warn { - "trigger \"${it.groups[1]!!.value}\" no longer passes an event as the third parameter" - } - - scrolledRegex.warn { "trigger \"scrolled\" now passes in the total delta, not just 1 or -1" } - - dropItemRegex.warn { - "trigger \"dropItem\" now takes different parameters. Check the migration docs for more info" - } - - renderEntityRegex.warn { - "trigger \"renderEntity\" no longer takes the entity's position as an argument. Use `.getPos()` " + - "instead" - } - - spawnParticleRegex.warn { - "trigger \"spawnParticle\" no longer passes in the particle type. Instead, compare the particle's " + - "Minecraft class (i.e. `.toMC() instanceof ...`)" - } - - ctCopyRegex.error { "`/ct copy` no longer exists. Use Client.copy() instead" } - - getRiderRegex.error { "`Entity.getRider()` no longer exists. Replace with `Entity.getRiders()`" } - - isAirborneRegex.error { "`Entity.isAirborne()` no longer exists" } - - getDimensionRegex.warn { "`Entity.getDimension()` now returns `Entity.DimensionType` instead of a number" } - - return errors - } -} diff --git a/src/main/kotlin/com/chattriggers/ctjs/internal/commands/StaticCommand.kt b/src/main/kotlin/com/chattriggers/ctjs/internal/commands/StaticCommand.kt deleted file mode 100644 index 1e332712..00000000 --- a/src/main/kotlin/com/chattriggers/ctjs/internal/commands/StaticCommand.kt +++ /dev/null @@ -1,70 +0,0 @@ -package com.chattriggers.ctjs.internal.commands - -import com.chattriggers.ctjs.api.triggers.CommandTrigger -import com.chattriggers.ctjs.internal.mixins.commands.CommandNodeAccessor -import com.chattriggers.ctjs.internal.utils.asMixin -import com.mojang.brigadier.CommandDispatcher -import com.mojang.brigadier.arguments.StringArgumentType -import net.minecraft.command.CommandSource - -internal class StaticCommand( - val trigger: CommandTrigger, - override val name: String, - private val aliases: Set, - override val overrideExisting: Boolean, - private val staticSuggestions: List, - private val dynamicSuggestions: ((List) -> List)?, -) : Command { - override fun registerImpl(dispatcher: CommandDispatcher) { - val builder = literal(name) - .then(argument("args", StringArgumentType.greedyString()) - .suggests { ctx, builder -> - val suggestions = if (dynamicSuggestions != null) { - val args = try { - StringArgumentType.getString(ctx, "args").split(" ") - } catch (e: IllegalArgumentException) { - emptyList() - } - - // Kotlin compiler bug: Without this null assert, it complains that the receiver is - // nullable, but with it, it says it's unnecessary. - @Suppress("UNNECESSARY_NOT_NULL_ASSERTION") - dynamicSuggestions!!(args) - } else staticSuggestions - - for (suggestion in suggestions) - builder.suggest(suggestion) - - builder.buildFuture() - } - .onExecute { - trigger.trigger(StringArgumentType.getString(it, "args").split(" ").toTypedArray()) - }) - .onExecute { trigger.trigger(emptyArray()) } - - val node = dispatcher.register(builder) - - // Can't use .redirect() since it doesn't work without arguments - for (alias in aliases) { - val aliasNode = literal(alias) - node.children.forEach { - aliasNode.then(it) - } - aliasNode.executes(node.command) - - dispatcher.register(aliasNode) - } - } - - override fun unregisterImpl(dispatcher: CommandDispatcher) { - super.unregisterImpl(dispatcher) - dispatcher.root.asMixin().apply { - for (alias in aliases) { - childNodes.remove(alias) - literals.remove(alias) - } - } - } - - companion object : CommandCollection() -} diff --git a/src/main/kotlin/com/chattriggers/ctjs/internal/compat/ModMenuEntry.kt b/src/main/kotlin/com/chattriggers/ctjs/internal/compat/ModMenuEntry.kt index 46992b27..35ad4684 100644 --- a/src/main/kotlin/com/chattriggers/ctjs/internal/compat/ModMenuEntry.kt +++ b/src/main/kotlin/com/chattriggers/ctjs/internal/compat/ModMenuEntry.kt @@ -1,13 +1,5 @@ package com.chattriggers.ctjs.internal.compat -import com.chattriggers.ctjs.api.Config -import com.terraformersmc.modmenu.api.ConfigScreenFactory import com.terraformersmc.modmenu.api.ModMenuApi -internal class ModMenuEntry : ModMenuApi { - override fun getModConfigScreenFactory(): ConfigScreenFactory<*> { - return ConfigScreenFactory { - Config.gui() - } - } -} +internal class ModMenuEntry : ModMenuApi \ No newline at end of file diff --git a/src/main/kotlin/com/chattriggers/ctjs/internal/console/ConsoleHostProcess.kt b/src/main/kotlin/com/chattriggers/ctjs/internal/console/ConsoleHostProcess.kt index 1413d534..88363731 100644 --- a/src/main/kotlin/com/chattriggers/ctjs/internal/console/ConsoleHostProcess.kt +++ b/src/main/kotlin/com/chattriggers/ctjs/internal/console/ConsoleHostProcess.kt @@ -1,18 +1,17 @@ package com.chattriggers.ctjs.internal.console import com.chattriggers.ctjs.CTJS -import com.chattriggers.ctjs.api.Config -import com.chattriggers.ctjs.api.client.Client import com.chattriggers.ctjs.engine.LogType -import com.chattriggers.ctjs.internal.engine.CTEvents import com.chattriggers.ctjs.internal.engine.JSLoader +import com.chattriggers.ctjs.internal.listeners.ClientListener import com.chattriggers.ctjs.internal.utils.Initializer -import gg.essential.universal.UDesktop -import kotlinx.serialization.encodeToString +import com.mojang.blaze3d.platform.InputConstants import kotlinx.serialization.json.Json -import net.fabricmc.fabric.api.client.keybinding.v1.KeyBindingHelper -import net.minecraft.client.option.KeyBinding -import net.minecraft.client.util.InputUtil +import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents +import net.fabricmc.fabric.api.client.keymapping.v1.KeyMappingHelper +import net.minecraft.client.KeyMapping +import net.minecraft.resources.Identifier +import net.minecraft.util.Util import org.lwjgl.glfw.GLFW import java.awt.Color import java.io.BufferedReader @@ -26,6 +25,7 @@ import java.nio.charset.Charset import kotlin.concurrent.thread import kotlin.io.path.Path + /** * Responsible for spawning and managing a separate Java console process (which uses AWT) * @@ -59,19 +59,20 @@ object ConsoleHostProcess : Initializer { } override fun init() { - val keybind = KeyBindingHelper.registerKeyBinding( - KeyBinding( + val keybind = KeyMappingHelper.registerKeyMapping( + KeyMapping( "ctjs.key.binding.console", - InputUtil.Type.KEYSYM, + InputConstants.Type.KEYSYM, GLFW.GLFW_KEY_GRAVE_ACCENT, - "ctjs.key.category", + KeyMapping.Category(Identifier.fromNamespaceAndPath("ctjs", "key.category")), ) ) - CTEvents.RENDER_GAME.register { - if (keybind.wasPressed()) + ClientTickEvents.END_CLIENT_TICK.register(ClientTickEvents.EndTick { + while (keybind.consumeClick()) { show() - } + } + }) } private fun hostMain() { @@ -81,7 +82,8 @@ object ConsoleHostProcess : Initializer { val urlObjects = (Thread.currentThread().contextClassLoader.parent as URLClassLoader).urLs val urls = urlObjects.joinToString(File.pathSeparator) { - val str = if (UDesktop.isWindows) it.toString().replace("file:/", "") else it.toString() + val str = if (Util.getPlatform().toString().contains("windows", true)) it.toString() + .replace("file:/", "") else it.toString() URLDecoder.decode(str, Charset.defaultCharset()) } @@ -105,7 +107,7 @@ object ConsoleHostProcess : Initializer { val initMessage = InitMessage( CTJS.MOD_VERSION, - ConfigUpdateMessage.constructFromConfig(Config.ConsoleSettings.make()), + ConfigUpdateMessage.constructFromDefaults(), this::class.java.getResourceAsStream("/assets/ctjs/FiraCode-Regular.otf")?.readAllBytes(), ) @@ -133,12 +135,9 @@ object ConsoleHostProcess : Initializer { trySendMessage(EvalResultMessage(message.id, result)) } is FontSizeMessage -> { - val newValue = Config.consoleFontSize + message.delta - - Config.consoleFontSize = newValue.coerceIn(6..32) - onConsoleSettingsChanged(Config.ConsoleSettings.make()) + onConsoleSettingsChanged() } - ReloadCTMessage -> Client.scheduleTask { CTJS.load() } + ReloadCTMessage -> ClientListener.addTask(0) { CTJS.load() } } } } @@ -172,8 +171,8 @@ object ConsoleHostProcess : Initializer { process.destroy() } - fun onConsoleSettingsChanged(settings: Config.ConsoleSettings) = - trySendMessage(ConfigUpdateMessage.constructFromConfig(settings)) + fun onConsoleSettingsChanged() = + trySendMessage(ConfigUpdateMessage.constructFromDefaults()) private fun trySendMessage(message: H2CMessage) { if (connected) { diff --git a/src/main/kotlin/com/chattriggers/ctjs/internal/console/data.kt b/src/main/kotlin/com/chattriggers/ctjs/internal/console/data.kt index c105adc9..b35c40d5 100644 --- a/src/main/kotlin/com/chattriggers/ctjs/internal/console/data.kt +++ b/src/main/kotlin/com/chattriggers/ctjs/internal/console/data.kt @@ -1,8 +1,8 @@ package com.chattriggers.ctjs.internal.console -import com.chattriggers.ctjs.api.Config import com.chattriggers.ctjs.engine.LogType import kotlinx.serialization.Serializable +import java.awt.Color @Serializable sealed class H2CMessage @@ -20,16 +20,16 @@ class ConfigUpdateMessage( val fontSize: Int, ) : H2CMessage() { companion object { - fun constructFromConfig(settings: Config.ConsoleSettings) = ConfigUpdateMessage( - settings.consoleTextColor.rgb, - settings.consoleBackgroundColor.rgb, - settings.consoleWarningColor.rgb, - settings.consoleErrorColor.rgb, - settings.openConsoleOnError, - settings.customTheme, - settings.consoleTheme, - settings.consoleFiraCodeFont, - settings.consoleFontSize, + fun constructFromDefaults() = ConfigUpdateMessage( + Color(208, 208, 208).rgb, + Color(21, 21, 21).rgb, + Color(248, 191, 84).rgb, + Color(225, 65, 73).rgb, + openConsoleOnError = false, + customTheme = false, + theme = 0, + useFiraCode = true, + fontSize = 12, ) } } diff --git a/src/main/kotlin/com/chattriggers/ctjs/internal/engine/CTEvents.kt b/src/main/kotlin/com/chattriggers/ctjs/internal/engine/CTEvents.kt deleted file mode 100644 index 67924700..00000000 --- a/src/main/kotlin/com/chattriggers/ctjs/internal/engine/CTEvents.kt +++ /dev/null @@ -1,176 +0,0 @@ -package com.chattriggers.ctjs.internal.engine - -import com.chattriggers.ctjs.internal.engine.CTEvents.BreakBlockCallback -import com.chattriggers.ctjs.internal.engine.CTEvents.GuiMouseDragCallback -import com.chattriggers.ctjs.internal.engine.CTEvents.MouseButtonCallback -import com.chattriggers.ctjs.internal.engine.CTEvents.MouseDraggedCallback -import com.chattriggers.ctjs.internal.engine.CTEvents.MouseScrollCallback -import com.chattriggers.ctjs.internal.engine.CTEvents.NetworkCommandDispatcherRegisterCallback -import com.chattriggers.ctjs.internal.engine.CTEvents.PacketReceivedCallback -import com.chattriggers.ctjs.internal.engine.CTEvents.RenderBlockEntityCallback -import com.chattriggers.ctjs.internal.engine.CTEvents.RenderEntityCallback -import com.chattriggers.ctjs.internal.engine.CTEvents.RenderOverlayCallback -import com.chattriggers.ctjs.internal.engine.CTEvents.RenderWorldCallback -import com.chattriggers.ctjs.internal.engine.CTEvents.VoidCallback -import com.chattriggers.ctjs.MCBlockEntity -import com.chattriggers.ctjs.MCBlockPos -import com.chattriggers.ctjs.MCEntity -import com.mojang.brigadier.CommandDispatcher -import net.fabricmc.fabric.api.client.command.v2.FabricClientCommandSource -import net.fabricmc.fabric.api.event.Event -import net.fabricmc.fabric.api.event.EventFactory -import net.minecraft.client.gui.Drawable -import net.minecraft.client.gui.screen.Screen -import net.minecraft.client.util.math.MatrixStack -import net.minecraft.network.packet.Packet -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo - -internal object CTEvents { - fun interface VoidCallback { - fun invoke() - } - - fun interface RenderScreenCallback { - fun render(matrixStack: MatrixStack, mouseX: Int, mouseY: Int, drawable: Drawable, partialTicks: Float) - } - - fun interface RenderWorldCallback { - fun render(matrixStack: MatrixStack, partialTicks: Float) - } - - fun interface RenderEntityCallback { - fun render(matrixStack: MatrixStack, entity: MCEntity, partialTicks: Float, ci: CallbackInfo) - } - - fun interface RenderBlockEntityCallback { - fun render(matrixStack: MatrixStack, entity: MCBlockEntity, partialTicks: Float, ci: CallbackInfo) - } - - fun interface RenderOverlayCallback { - fun render(matrixStack: MatrixStack, partialTicks: Float) - } - - fun interface PacketReceivedCallback { - fun receive(packet: Packet<*>, cb: CallbackInfo) - } - - fun interface MouseButtonCallback { - fun process(mouseX: Double, mouseY: Double, button: Int, pressed: Boolean) - } - - fun interface MouseScrollCallback { - fun process(mouseX: Double, mouseY: Double, delta: Double) - } - - fun interface MouseDraggedCallback { - fun process(dx: Double, dy: Double, mouseX: Double, mouseY: Double, button: Int) - } - - fun interface GuiMouseDragCallback { - fun process(dx: Double, dy: Double, mouseX: Double, mouseY: Double, button: Int, gui: Screen, ci: CallbackInfo) - } - - fun interface BreakBlockCallback { - fun breakBlock(pos: MCBlockPos) - } - - fun interface NetworkCommandDispatcherRegisterCallback { - fun register(dispatcher: CommandDispatcher) - } - - @JvmField - val RENDER_GAME = make { listeners -> - Runnable { listeners.forEach(Runnable::run) } - } - - @JvmField - val RENDER_OVERLAY = make { listeners -> - RenderOverlayCallback { stack, partialTicks -> - listeners.forEach { it.render(stack, partialTicks) } - } - } - - @JvmField - val PRE_RENDER_WORLD = make { listeners -> - RenderWorldCallback { stack, partialTicks -> - listeners.forEach { it.render(stack, partialTicks) } - } - } - - @JvmField - val POST_RENDER_WORLD = make { listeners -> - RenderWorldCallback { stack, partialTicks -> - listeners.forEach { it.render(stack, partialTicks) } - } - } - - @JvmField - val RENDER_ENTITY = make { listeners -> - RenderEntityCallback { stack, entity, partialTicks, ci -> - listeners.forEach { it.render(stack, entity, partialTicks, ci) } - } - } - - @JvmField - val RENDER_BLOCK_ENTITY = make { listeners -> - RenderBlockEntityCallback { stack, blockEntity, partialTicks, ci -> - listeners.forEach { it.render(stack, blockEntity, partialTicks, ci) } - } - } - - @JvmField - val PACKET_RECEIVED = make { listeners -> - PacketReceivedCallback { packet, cb -> listeners.forEach { it.receive(packet, cb) } } - } - - @JvmField - val RENDER_TICK = make { listeners -> - VoidCallback { listeners.forEach(VoidCallback::invoke) } - } - - @JvmField - val MOUSE_CLICKED = make { listeners -> - MouseButtonCallback { mouseX, mouseY, button, pressed -> - listeners.forEach { it.process(mouseX, mouseY, button, pressed) } - } - } - - @JvmField - val MOUSE_SCROLLED = make { listeners -> - MouseScrollCallback { mouseX, mouseY, delta -> - listeners.forEach { it.process(mouseX, mouseY, delta) } - } - } - - @JvmField - val MOUSE_DRAGGED = make { listeners -> - MouseDraggedCallback { dx, dy, mouseX, mouseY, button -> - listeners.forEach { it.process(dx, dy, mouseX, mouseY, button) } - } - } - - @JvmField - val GUI_MOUSE_DRAG = make { listeners -> - GuiMouseDragCallback { dx, dy, mouseX, mouseY, button, screen, ci -> - listeners.forEach { it.process(dx, dy, mouseX, mouseY, button, screen, ci) } - } - } - - @JvmField - val BREAK_BLOCK = make { listeners -> - BreakBlockCallback { pos -> - listeners.forEach { it.breakBlock(pos) } - } - } - - @JvmField - val NETWORK_COMMAND_DISPATCHER_REGISTER = make { listeners -> - NetworkCommandDispatcherRegisterCallback { dispatcher -> - listeners.forEach { it.register(dispatcher) } - } - } - - private inline fun make(noinline reducer: (Array) -> T): Event { - return EventFactory.createArrayBacked(T::class.java, reducer) - } -} diff --git a/src/main/kotlin/com/chattriggers/ctjs/internal/engine/JSContextFactory.kt b/src/main/kotlin/com/chattriggers/ctjs/internal/engine/JSContextFactory.kt index 74cace4d..76565b17 100644 --- a/src/main/kotlin/com/chattriggers/ctjs/internal/engine/JSContextFactory.kt +++ b/src/main/kotlin/com/chattriggers/ctjs/internal/engine/JSContextFactory.kt @@ -1,7 +1,6 @@ package com.chattriggers.ctjs.internal.engine import com.chattriggers.ctjs.CTJS -import com.chattriggers.ctjs.internal.launch.CTJavaObjectMappingProvider import org.mozilla.javascript.Context import org.mozilla.javascript.Context.EMIT_DEBUG_OUTPUT import org.mozilla.javascript.Context.FEATURE_LOCATION_INFORMATION_IN_ERROR @@ -29,9 +28,6 @@ object JSContextFactory : ContextFactory() { cx.wrapFactory = WrapFactory().apply { isJavaPrimitiveWrap = false } - - if (!CTJS.isDevelopment) - cx.javaObjectMappingProvider = CTJavaObjectMappingProvider } override fun hasFeature(cx: Context?, featureIndex: Int): Boolean { @@ -50,7 +46,7 @@ object JSContextFactory : ContextFactory() { (urls - sources).forEach(::addURL) } - public override fun addURL(url: URL) { + override fun addURL(url: URL) { super.addURL(url) sources.add(url) } diff --git a/src/main/kotlin/com/chattriggers/ctjs/internal/engine/JSLoader.kt b/src/main/kotlin/com/chattriggers/ctjs/internal/engine/JSLoader.kt index d5723ddb..0d1d7864 100644 --- a/src/main/kotlin/com/chattriggers/ctjs/internal/engine/JSLoader.kt +++ b/src/main/kotlin/com/chattriggers/ctjs/internal/engine/JSLoader.kt @@ -3,14 +3,10 @@ package com.chattriggers.ctjs.internal.engine import com.chattriggers.ctjs.api.triggers.ITriggerType import com.chattriggers.ctjs.api.triggers.Trigger import com.chattriggers.ctjs.engine.LogType -import com.chattriggers.ctjs.engine.MixinCallback import com.chattriggers.ctjs.engine.printToConsole import com.chattriggers.ctjs.engine.printTraceToConsole import com.chattriggers.ctjs.internal.engine.module.Module import com.chattriggers.ctjs.internal.engine.module.ModuleManager.modulesFolder -import com.chattriggers.ctjs.internal.launch.IInjector -import com.chattriggers.ctjs.internal.launch.Mixin -import com.chattriggers.ctjs.internal.launch.MixinDetails import org.apache.commons.io.FileUtils import org.mozilla.javascript.* import org.mozilla.javascript.commonjs.module.ModuleScriptProvider @@ -18,8 +14,6 @@ import org.mozilla.javascript.commonjs.module.Require import org.mozilla.javascript.commonjs.module.provider.StrongCachingModuleScriptProvider import org.mozilla.javascript.commonjs.module.provider.UrlModuleSourceProvider import java.io.File -import java.lang.invoke.MethodHandles -import java.lang.invoke.MethodType import java.net.URI import java.net.URL import java.nio.charset.Charset @@ -38,25 +32,7 @@ object JSLoader { private lateinit var require: CTRequire private lateinit var moduleProvider: ModuleScriptProvider - private var mixinLibsLoaded = false - private var mixinsFinalized = false - private var nextMixinId = 0 - private val mixinIdMap = mutableMapOf() - private val mixins = mutableMapOf() - - private val INVOKE_MIXIN_CALL = MethodHandles.lookup().findStatic( - JSLoader::class.java, - "invokeMixin", - MethodType.methodType(Any::class.java, Callable::class.java, Array::class.java), - ) - fun setup(jars: List) { - // Ensure all active mixins are invalidated - // TODO: It would be nice to do this, but it's possible to have a @Redirect or similar - // mixin try to call it's handler between when we start loading and when we finish - // loading, which would crash. So we need to be smarter about invalidation on load. - // mixinIdMap.values.forEach(MixinCallback::release) - JSContextFactory.addAllURLs(jars) val cx = JSContextFactory.enterContext() @@ -68,34 +44,9 @@ object JSLoader { require.install(moduleScope) require.install(evalScope) Context.exit() - - mixinLibsLoaded = false - } - - internal fun mixinSetup(modules: List): Map { - loadMixinLibs() - - wrapInContext { - modules.forEach { module -> - try { - val uri = File(module.folder, module.metadata.mixinEntry!!).normalize().toURI() - require.loadCTModule(uri.toString(), uri) - } catch (e: Throwable) { - e.printTraceToConsole() - } - } - } - - mixinsFinalized = true - mixinLibsLoaded = true - - return mixins } fun entrySetup(): Unit = wrapInContext { - if (!mixinLibsLoaded) - loadMixinLibs() - val moduleProvidedLibs = saveResource( "/assets/ctjs/js/moduleProvidedLibs.js", File(modulesFolder.parentFile, "chattriggers-modules-provided-libs.js"), @@ -190,96 +141,6 @@ object JSLoader { } } - private fun loadMixinLibs() { - val mixinProvidedLibs = saveResource( - "/assets/ctjs/js/mixinProvidedLibs.js", - File(modulesFolder.parentFile, "chattriggers-mixin-provided-libs.js"), - ) - - wrapInContext { - try { - it.evaluateString( - moduleScope, - mixinProvidedLibs, - "mixinProvided", - 1, null - ) - } catch (e: Throwable) { - e.printTraceToConsole() - } - } - } - - @JvmStatic - fun mixinIsAttached(id: Int) = mixinIdMap[id]?.method != null - - fun invokeMixinLookup(id: Int): MixinCallback { - val callback = mixinIdMap[id] ?: error("Unknown mixin id $id for loader ${this::class.simpleName}") - - callback.handle = if (callback.method != null) { - try { - require(callback.method is Callable) { - "The value passed to MixinCallback.attach() must be a function" - } - - INVOKE_MIXIN_CALL.bindTo(callback.method) - } catch (e: Throwable) { - // This is a pretty vague error, but the trace should make the issue clear - // since it will include the stack trace from the Mixed-into class - "Error loading mixin callback".printToConsole() - e.printTraceToConsole() - - MethodHandles.dropArguments( - MethodHandles.constant(Any::class.java, null), - 0, - Array::class.java, - ) - } - } else null - - return callback - } - - @JvmStatic - fun invokeMixin(func: Callable, args: Array): Any? { - return wrapInContext { - Context.jsToJava(func.call(it, moduleScope, moduleScope, args), Any::class.java) - } - } - - fun registerInjector(mixin: Mixin, injector: IInjector): MixinCallback? { - return if (mixinsFinalized) { - // We are reprocessing the mixin entry file from a ct reload, so we can - // just return the existing mixin callback. If none exists, then the user - // has added a mixin, which requires a reload - - val existing = mixins[mixin]?.injectors?.find { it.injector == injector } - if (existing != null) { - existing - } else { - ("A new injector mixin was registered at runtime. This will require a restart, and will " + - "have no effect until then!").printToConsole() - null - } - } else { - val id = nextMixinId++ - MixinCallback(id, injector).also { - mixinIdMap[id] = it - mixins.getOrPut(mixin, ::MixinDetails).injectors.add(it) - } - } - } - - fun registerFieldWidener(mixin: Mixin, fieldName: String, isMutable: Boolean) { - if (!mixinsFinalized) - mixins.getOrPut(mixin, ::MixinDetails).fieldWideners[fieldName] = isMutable - } - - fun registerMethodWidener(mixin: Mixin, methodName: String, isMutable: Boolean) { - if (!mixinsFinalized) - mixins.getOrPut(mixin, ::MixinDetails).methodWideners[methodName] = isMutable - } - /** * Save a resource to the OS's filesystem from inside the jar * diff --git a/src/main/kotlin/com/chattriggers/ctjs/internal/engine/module/Module.kt b/src/main/kotlin/com/chattriggers/ctjs/internal/engine/module/Module.kt index ebbbc88c..bcea72e3 100644 --- a/src/main/kotlin/com/chattriggers/ctjs/internal/engine/module/Module.kt +++ b/src/main/kotlin/com/chattriggers/ctjs/internal/engine/module/Module.kt @@ -1,91 +1,9 @@ package com.chattriggers.ctjs.internal.engine.module -import com.chattriggers.ctjs.api.message.ChatLib -import com.chattriggers.ctjs.api.render.Renderer -import com.chattriggers.ctjs.api.render.Text -import com.fasterxml.jackson.core.Version import java.io.File class Module(val name: String, var metadata: ModuleMetadata, val folder: File) { - var targetModVersion: Version? = null var requiredBy = mutableSetOf() - private val gui = object { - var collapsed = true - var x = 0f - var y = 0f - var description = Text(metadata.description ?: "No description provided in the metadata") - } - - fun draw(x: Float, y: Float, width: Float): Float { - gui.x = x - gui.y = y - - Renderer.pushMatrix() - Renderer.drawRect( - 0xaa000000, - x, y, width, 13f - ) - Renderer.drawStringWithShadow( - metadata.name ?: name, - x + 3, y + 3 - ) - - return if (gui.collapsed) { - Renderer.translate(x + width - 5, y + 8) - Renderer.rotate(180f) - Renderer.drawString("^", 0f, 0f) - - Renderer.popMatrix() - 15f - } else { - gui.description.setMaxWidth(width.toInt() - 5) - - Renderer.drawRect(0x50000000, x, y + 13, width, gui.description.getHeight() + 12) - Renderer.drawString("^", x + width - 10, y + 5) - - gui.description.draw(x + 3, y + 15) - - if (metadata.version != null) { - Renderer.drawStringWithShadow( - ChatLib.addColor("&8v${metadata.version}"), - x + width - Renderer.getStringWidth(ChatLib.addColor("&8v${metadata.version}")), - y + gui.description.getHeight() + 15 - ) - } - - Renderer.drawStringWithShadow( - ChatLib.addColor( - if (metadata.isRequired && requiredBy.isNotEmpty()) { - "&8required by $requiredBy" - } else { - "&4[delete]" - } - ), - x + 3, y + gui.description.getHeight() + 15 - ) - - Renderer.popMatrix() - gui.description.getHeight() + 27 - } - } - - fun click(x: Double, y: Double, width: Float) { - if (x > gui.x && x < gui.x + width - && y > gui.y && y < gui.y + 13 - ) { - gui.collapsed = !gui.collapsed - return - } - - if (gui.collapsed || (metadata.isRequired && requiredBy.isNotEmpty())) return - - if (x > gui.x && x < gui.x + 45 - && y > gui.y + gui.description.getHeight() + 15 && y < gui.y + gui.description.getHeight() + 25 - ) { - ModuleManager.deleteModule(name) - } - } - override fun toString() = "Module{name=$name,version=${metadata.version}}" } diff --git a/src/main/kotlin/com/chattriggers/ctjs/internal/engine/module/ModuleListScreen.kt b/src/main/kotlin/com/chattriggers/ctjs/internal/engine/module/ModuleListScreen.kt new file mode 100644 index 00000000..08ccaf10 --- /dev/null +++ b/src/main/kotlin/com/chattriggers/ctjs/internal/engine/module/ModuleListScreen.kt @@ -0,0 +1,157 @@ +package com.chattriggers.ctjs.internal.engine.module + +import com.chattriggers.ctjs.api.FileLib +import net.minecraft.client.Minecraft +import net.minecraft.client.gui.Font +import net.minecraft.client.gui.GuiGraphicsExtractor +import net.minecraft.client.gui.components.Button +import net.minecraft.client.gui.components.ObjectSelectionList +import net.minecraft.client.gui.screens.ConfirmScreen +import net.minecraft.client.gui.screens.Screen +import net.minecraft.client.renderer.RenderPipelines +import net.minecraft.network.chat.CommonComponents +import net.minecraft.network.chat.Component +import net.minecraft.network.chat.FormattedText +import net.minecraft.resources.Identifier +import net.minecraft.util.ARGB + +class ModuleListScreen : Screen(Component.translatable("ctjs.ui.modules")) { + private lateinit var moduleList: ModuleListWidget + private lateinit var openFolderButton: Button + private lateinit var deleteButton: Button + private lateinit var closeButton: Button + + override fun init() { + moduleList = ModuleListWidget(minecraft, width, height - 96, 32, 36) + + openFolderButton = Button.builder(Component.translatable("ctjs.ui.openModulesFolder")) { + FileLib.openModulesFolder() + }.width(200).pos(width / 2 - 100, height - 56).build() + + deleteButton = Button.builder(Component.translatable("ctjs.ui.delete")) { + moduleList.selected?.let { + minecraft.setScreen( + ConfirmScreen( + { confirmed -> + if (confirmed) { + ModuleManager.deleteModule(it.module.name) + onClose() + } else minecraft.setScreen(this) + }, + Component.translatable("ctjs.ui.deleteConfirmation", it.module.name), + Component.translatable("ctjs.ui.noRevert").withColor(ARGB.colorFromFloat(1f, 1f, 0f, 0f)), + CommonComponents.GUI_PROCEED, + CommonComponents.GUI_CANCEL + ) + ) + } + }.width(128).pos(width / 2 + 4, height - 32).build() + + closeButton = Button.builder(CommonComponents.GUI_BACK) { onClose() } + .width(128) + .pos(width / 2 - 132, height - 32).build() + + addRenderableWidget(openFolderButton) + addRenderableWidget(deleteButton) + addRenderableWidget(closeButton) + addRenderableWidget(moduleList) + } + + override fun extractRenderState(context: GuiGraphicsExtractor, mouseX: Int, mouseY: Int, deltaTicks: Float) { + super.extractRenderState(context, mouseX, mouseY, deltaTicks) + context.textWithBackdrop( + font, + this.title, + this.width / 2, + 20, + -1, + -1 + ) + deleteButton.active = moduleList.selected != null + } +} + +class ModuleEntry(val textRenderer: Font, val module: Module) : + ObjectSelectionList.Entry() { + override fun getNarration(): Component { + return Component.literal(module.name) + } + + override fun extractContent( + context: GuiGraphicsExtractor, + mouseX: Int, + mouseY: Int, + hovered: Boolean, + tickProgress: Float + ) { + val stack = context.pose() + + stack.pushMatrix() + stack.scale(1.25f, 1.25f) + context.textWithBackdrop( + textRenderer, + Component.literal(module.name), + (x / 1.25f + 4).toInt(), + (y / 1.25f + 4).toInt(), + -1, + -1 + ) + stack.popMatrix() + + module.metadata.creator?.let { + context.textWithBackdrop( + textRenderer, + Component.translatable("ctjs.ui.byCreator", it), + x + 4, + y + contentHeight - textRenderer.lineHeight / 2 - 2, + ARGB.colorFromFloat(1f, 0.8f, 0.8f, 0.8f), + -1 + ) + } + + module.metadata.description?.let { + context.blitSprite( + RenderPipelines.GUI_TEXTURED, + INFO_TEXTURE, + x + contentWidth - 22, y + 2, + 16, 16, + ) + + // If the info icon is hovered + if (mouseX >= x + contentWidth - 22 && mouseX <= x + contentWidth - 6 && mouseY >= y + 2 && mouseY <= y + 18) { + context.setTooltipForNextFrame( + textRenderer, + textRenderer.split(FormattedText.of(it), contentWidth), + mouseX, mouseY + ) + } + } + + module.metadata.version?.let { + context.text( + textRenderer, + it, + x + contentWidth - textRenderer.width(it) - 4, + y + contentHeight - textRenderer.lineHeight, + ARGB.colorFromFloat(1f, 0.4f, 0.4f, 0.4f) + ) + } + } + + companion object { + val INFO_TEXTURE: Identifier = Identifier.parse("icon/info") + } +} + +class ModuleListWidget(client: Minecraft, width: Int, height: Int, y: Int, itemHeight: Int) : + ObjectSelectionList(client, width, height, y, itemHeight) { + init { + clearEntries() + for (module in ModuleManager.cachedModules) { + addEntry(ModuleEntry(client.font, module)) + } + } + + // Default is 220 + override fun getRowWidth(): Int = 320 +} diff --git a/src/main/kotlin/com/chattriggers/ctjs/internal/engine/module/ModuleManager.kt b/src/main/kotlin/com/chattriggers/ctjs/internal/engine/module/ModuleManager.kt index 029414a4..96a13cf2 100644 --- a/src/main/kotlin/com/chattriggers/ctjs/internal/engine/module/ModuleManager.kt +++ b/src/main/kotlin/com/chattriggers/ctjs/internal/engine/module/ModuleManager.kt @@ -1,8 +1,6 @@ package com.chattriggers.ctjs.internal.engine.module import com.chattriggers.ctjs.CTJS -import com.chattriggers.ctjs.api.message.ChatLib -import com.chattriggers.ctjs.api.world.World import com.chattriggers.ctjs.engine.LogType import com.chattriggers.ctjs.engine.printToConsole import com.chattriggers.ctjs.internal.engine.JSContextFactory @@ -16,7 +14,6 @@ import java.util.* object ModuleManager { val cachedModules = mutableListOf() val modulesFolder = File(CTJS.MODULES_FOLDER) - private val pendingOldModules = mutableListOf() fun setup() { modulesFolder.mkdirs() @@ -26,17 +23,8 @@ object ModuleManager { it.name.lowercase() } - // Check if those modules have updates - installedModules.forEach(ModuleUpdater::updateModule) cachedModules.addAll(installedModules) - - // Import required modules - installedModules.distinct().forEach { module -> - module.metadata.requires?.forEach { ModuleUpdater.importModule(it, module.name) } - } - sortModules() - loadAssetsAndJars(cachedModules) } @@ -47,8 +35,6 @@ object ModuleManager { // Normalize all metadata modules.forEach { it.metadata.entry = it.metadata.entry?.replace('/', File.separatorChar)?.replace('\\', File.separatorChar) - it.metadata.mixinEntry = - it.metadata.mixinEntry?.replace('/', File.separatorChar)?.replace('\\', File.separatorChar) } // Get all jars @@ -103,25 +89,8 @@ object ModuleManager { return Module(directory.name, metadata, directory) } - data class ImportedModule(val module: Module?, val dependencies: List) - - fun importModule(moduleName: String): ImportedModule { - val newModules = ModuleUpdater.importModule(moduleName) - - loadAssetsAndJars(newModules) - - newModules.forEach { - if (it.metadata.mixinEntry != null) - ChatLib.chat("&cModule ${it.name} has dynamic mixins which require a restart to take effect") - } - - entryPass(newModules) - - return ImportedModule(newModules.getOrNull(0), newModules.drop(1)) - } - fun deleteModule(name: String): Boolean { - val module = cachedModules.find { it.name.lowercase() == name.lowercase() } ?: return false + val module = cachedModules.find { it.name.equals(name, ignoreCase = true) } ?: return false val file = File(modulesFolder, module.name) check(file.exists()) { "Expected module to have an existing folder!" } @@ -143,26 +112,6 @@ object ModuleManager { return false } - fun reportOldVersions() { - pendingOldModules.forEach(::reportOldVersion) - pendingOldModules.clear() - } - - fun tryReportOldVersion(module: Module) { - if (World.isLoaded()) { - reportOldVersion(module) - } else { - pendingOldModules.add(module) - } - } - - private fun reportOldVersion(module: Module) { - ChatLib.chat( - "&cWarning: the module \"${module.name}\" was made for an older version of CT, " + - "so it may not work correctly." - ) - } - private fun loadAssets(modules: List) { modules.map { File(it.folder, "assets") diff --git a/src/main/kotlin/com/chattriggers/ctjs/internal/engine/module/ModuleMetadata.kt b/src/main/kotlin/com/chattriggers/ctjs/internal/engine/module/ModuleMetadata.kt index 44c3e50a..824564b6 100644 --- a/src/main/kotlin/com/chattriggers/ctjs/internal/engine/module/ModuleMetadata.kt +++ b/src/main/kotlin/com/chattriggers/ctjs/internal/engine/module/ModuleMetadata.kt @@ -10,7 +10,6 @@ data class ModuleMetadata( val name: String? = null, val version: String? = null, var entry: String? = null, - var mixinEntry: String? = null, val tags: ArrayList? = null, val pictureLink: String? = null, @JsonNames("author") diff --git a/src/main/kotlin/com/chattriggers/ctjs/internal/engine/module/ModuleUpdater.kt b/src/main/kotlin/com/chattriggers/ctjs/internal/engine/module/ModuleUpdater.kt deleted file mode 100644 index 03ec2e1c..00000000 --- a/src/main/kotlin/com/chattriggers/ctjs/internal/engine/module/ModuleUpdater.kt +++ /dev/null @@ -1,154 +0,0 @@ -package com.chattriggers.ctjs.internal.engine.module - -import com.chattriggers.ctjs.CTJS -import com.chattriggers.ctjs.api.Config -import com.chattriggers.ctjs.api.message.ChatLib -import com.chattriggers.ctjs.engine.LogType -import com.chattriggers.ctjs.engine.printToConsole -import com.chattriggers.ctjs.engine.printTraceToConsole -import com.chattriggers.ctjs.internal.engine.CTEvents -import com.chattriggers.ctjs.internal.engine.module.ModuleManager.cachedModules -import com.chattriggers.ctjs.internal.engine.module.ModuleManager.modulesFolder -import com.chattriggers.ctjs.internal.utils.Initializer -import com.chattriggers.ctjs.internal.utils.toVersion -import net.fabricmc.fabric.api.client.networking.v1.ClientPlayConnectionEvents -import org.apache.commons.io.FileUtils -import java.io.File -import java.nio.file.FileSystems -import java.nio.file.Files -import java.nio.file.Paths -import java.nio.file.StandardCopyOption - -object ModuleUpdater : Initializer { - private val changelogs = mutableListOf() - private var shouldReportChangelog = false - - override fun init() { - ClientPlayConnectionEvents.JOIN.register { _, _, _ -> shouldReportChangelog = true } - - CTEvents.RENDER_OVERLAY.register { _, _ -> - if (shouldReportChangelog) { - changelogs.forEach(::reportChangelog) - changelogs.clear() - } - } - } - - private fun tryReportChangelog(module: ModuleMetadata) { - if (shouldReportChangelog) { - reportChangelog(module) - } else { - changelogs.add(module) - } - } - - private fun reportChangelog(module: ModuleMetadata) { - ChatLib.chat("&a[ChatTriggers] ${module.name} has updated to version ${module.version}") - ChatLib.chat("&aChangelog: &r${module.changelog}") - } - - fun updateModule(module: Module) { - if (!Config.autoUpdateModules) return - - val metadata = module.metadata - - try { - if (metadata.name == null) return - - "Checking for update in ${metadata.name}".printToConsole() - - val url = "${CTJS.WEBSITE_ROOT}/api/modules/${metadata.name}/metadata?modVersion=${CTJS.MOD_VERSION}" - val connection = CTJS.makeWebRequest(url) - - val newMetadataText = connection.getInputStream().bufferedReader().readText() - val newMetadata = CTJS.json.decodeFromString(newMetadataText) - - if (newMetadata.version == null) { - ("Remote version of module ${metadata.name} has no version numbers, so it will " + - "not be updated!").printToConsole(LogType.WARN) - return - } else if (metadata.version != null && metadata.version.toVersion() >= newMetadata.version.toVersion()) { - return - } - - downloadModule(metadata.name) - "Updated module ${metadata.name}".printToConsole() - - module.metadata = File(module.folder, "metadata.json").let { - CTJS.json.decodeFromString(it.readText()) - } - - if (Config.moduleChangelog && module.metadata.changelog != null) { - tryReportChangelog(module.metadata) - } - } catch (e: Exception) { - "Can't find page for ${metadata.name}".printToConsole(LogType.WARN) - } - } - - fun importModule(moduleName: String, requiredBy: String? = null): List { - val alreadyImported = cachedModules.any { - if (it.name.equals(moduleName, ignoreCase = true)) { - if (requiredBy != null) { - it.metadata.isRequired = true - it.requiredBy.add(requiredBy) - } - - true - } else false - } - - if (alreadyImported) return emptyList() - - val (realName, modVersion) = downloadModule(moduleName) ?: return emptyList() - - val moduleDir = File(modulesFolder, realName) - val module = ModuleManager.parseModule(moduleDir) - module.targetModVersion = modVersion.toVersion() - - if (requiredBy != null) { - module.metadata.isRequired = true - module.requiredBy.add(requiredBy) - } - - cachedModules.add(module) - return listOf(module) + (module.metadata.requires?.map { - importModule(it, module.name) - }?.flatten() ?: emptyList()) - } - - data class DownloadResult(val name: String, val modVersion: String) - - private fun downloadModule(name: String): DownloadResult? { - val downloadZip = File(modulesFolder, "currDownload.zip") - - try { - val url = "${CTJS.WEBSITE_ROOT}/api/modules/$name/scripts?modVersion=${CTJS.MOD_VERSION}" - val connection = CTJS.makeWebRequest(url) - FileUtils.copyInputStreamToFile(connection.getInputStream(), downloadZip) - FileSystems.newFileSystem(downloadZip.toPath()).use { - val rootFolder = Files.newDirectoryStream(it.rootDirectories.first()).iterator() - if (!rootFolder.hasNext()) throw Exception("Too small") - val moduleFolder = rootFolder.next() - if (rootFolder.hasNext()) throw Exception("Too big") - - val realName = moduleFolder.fileName.toString().trimEnd(File.separatorChar) - File(modulesFolder, realName).apply { mkdir() } - Files.walk(moduleFolder).forEach { path -> - val resolvedPath = Paths.get(CTJS.MODULES_FOLDER, path.toString()) - if (Files.isDirectory(resolvedPath)) { - return@forEach - } - Files.copy(path, resolvedPath, StandardCopyOption.REPLACE_EXISTING) - } - return DownloadResult(realName, connection.getHeaderField("CT-Version")) - } - } catch (exception: Exception) { - exception.printTraceToConsole() - } finally { - downloadZip.delete() - } - - return null - } -} diff --git a/src/main/kotlin/com/chattriggers/ctjs/internal/engine/module/ModulesGui.kt b/src/main/kotlin/com/chattriggers/ctjs/internal/engine/module/ModulesGui.kt deleted file mode 100644 index 72096b52..00000000 --- a/src/main/kotlin/com/chattriggers/ctjs/internal/engine/module/ModulesGui.kt +++ /dev/null @@ -1,84 +0,0 @@ -package com.chattriggers.ctjs.internal.engine.module - -import com.chattriggers.ctjs.api.client.Player -import com.chattriggers.ctjs.api.message.ChatLib -import com.chattriggers.ctjs.api.render.Renderer -import com.chattriggers.ctjs.api.render.Text -import gg.essential.universal.UMatrixStack -import gg.essential.universal.UScreen - -object ModulesGui : UScreen(unlocalizedName = "Modules") { - private val window = object { - val title = Text("Modules").setScale(2f).setShadow(true) - val exit = Text(ChatLib.addColor("&cx")).setScale(2f) - var height = 0f - var scroll = 0f - } - - override fun onDrawScreen(matrixStack: UMatrixStack, mouseX: Int, mouseY: Int, partialTicks: Float) { - super.onDrawScreen(matrixStack, mouseX, mouseY, partialTicks) - - Renderer.pushMatrix() - - val middle = Renderer.screen.getWidth() / 2f - val width = (Renderer.screen.getWidth() - 100f).coerceAtMost(500f) - - Renderer.drawRect( - 0x50000000, - 0f, - 0f, - Renderer.screen.getWidth().toFloat(), - Renderer.screen.getHeight().toFloat() - ) - - if (-window.scroll > window.height - Renderer.screen.getHeight() + 20) - window.scroll = -window.height + Renderer.screen.getHeight() - 20 - if (-window.scroll < 0) window.scroll = 0f - - if (-window.scroll > 0) { - Renderer.drawRect(0xaa000000, Renderer.screen.getWidth() - 20f, Renderer.screen.getHeight() - 20f, 20f, 20f) - Renderer.drawString("^", Renderer.screen.getWidth() - 12f, Renderer.screen.getHeight() - 12f) - } - - Renderer.drawRect(0x50000000, middle - width / 2f, window.scroll + 95f, width, window.height - 90) - - Renderer.drawRect(0xaa000000, middle - width / 2f, window.scroll + 95f, width, 25f) - window.title.draw((middle - width / 2f + 5) / 2f, (window.scroll + 100f) / 2f) - window.exit.draw((middle + width / 2f - 17) / 2f, (window.scroll + 99f) / 2f) - - window.height = 125f - ModuleManager.cachedModules.sortedBy { it.name }.forEach { - window.height += it.draw(middle - width / 2f, window.scroll + window.height, width) - } - - Renderer.popMatrix() - } - - override fun onMouseClicked(mouseX: Double, mouseY: Double, mouseButton: Int) { - super.onMouseClicked(mouseX, mouseY, mouseButton) - - var width = Renderer.screen.getWidth() - 100f - if (width > 500) width = 500f - - if (mouseX > Renderer.screen.getWidth() - 20 && mouseY > Renderer.screen.getHeight() - 20) { - window.scroll = 0f - return - } - - if (mouseX > Renderer.screen.getWidth() / 2f + width / 2f - 25 && mouseX < Renderer.screen.getWidth() / 2f + width / 2f - && mouseY > window.scroll + 95 && mouseY < window.scroll + 120 - ) { - Player.toMC()?.closeScreen() - return - } - - ModuleManager.cachedModules.toList().forEach { - it.click(mouseX, mouseY, width) - } - } - - override fun onMouseScrolled(delta: Double) { - super.onMouseScrolled(delta) - window.scroll += delta.toFloat() - } -} diff --git a/src/main/kotlin/com/chattriggers/ctjs/internal/launch/CTJSPreLaunch.kt b/src/main/kotlin/com/chattriggers/ctjs/internal/launch/CTJSPreLaunch.kt index 27de03c3..2102f348 100644 --- a/src/main/kotlin/com/chattriggers/ctjs/internal/launch/CTJSPreLaunch.kt +++ b/src/main/kotlin/com/chattriggers/ctjs/internal/launch/CTJSPreLaunch.kt @@ -13,11 +13,5 @@ class CTJSPreLaunch : PreLaunchEntrypoint { exception.printTraceToConsole() prevHandler.uncaughtException(thread, exception) } - - try { - DynamicMixinManager.applyMixins() - } catch (e: Throwable) { - IllegalStateException("Error generating dynamic mixins", e).printTraceToConsole() - } } } diff --git a/src/main/kotlin/com/chattriggers/ctjs/internal/launch/CTJavaObjectMappingProvider.kt b/src/main/kotlin/com/chattriggers/ctjs/internal/launch/CTJavaObjectMappingProvider.kt deleted file mode 100644 index d67f3b9e..00000000 --- a/src/main/kotlin/com/chattriggers/ctjs/internal/launch/CTJavaObjectMappingProvider.kt +++ /dev/null @@ -1,104 +0,0 @@ -package com.chattriggers.ctjs.internal.launch - -import com.chattriggers.ctjs.api.Mappings -import org.mozilla.javascript.JavaObjectMappingProvider -import java.lang.reflect.Modifier - -object CTJavaObjectMappingProvider : JavaObjectMappingProvider { - override fun mapClassName(className: String) = Mappings.mapClassName(className)?.replace('/', '.') - - override fun unmapClassName(className: String) = Mappings.unmapClassName(className)?.replace('/', '.') - - override fun findExtraMethods( - clazz: Class<*>, - map: MutableMap, - includeProtected: Boolean, - includePrivate: Boolean - ) { - val queue = ArrayDeque>() - var current: Class<*>? = clazz - - while (current != null) { - findRemappedMethods( - current, - map, - includeProtected, - includePrivate - ) - - val superClass = current.superclass - if (superClass != null) - queue.add(superClass) - - for (itf in current.interfaces) - queue.add(itf) - - current = queue.removeFirstOrNull() - } - } - - override fun findExtraFields( - clazz: Class<*>, - list: MutableList, - includeProtected: Boolean, - includePrivate: Boolean - ) { - var current: Class<*>? = clazz - while (current != null) { - findRemappedFields( - current, - list, - includeProtected, - includePrivate - ) - current = current.superclass - } - } - - private fun findRemappedMethods( - clazz: Class<*>, - map: MutableMap, - includeProtected: Boolean, - includePrivate: Boolean, - ) { - val mappedClass = Mappings.getMappedClass(clazz.name) ?: return - - for ((unmappedMethodName, mappedMethods) in mappedClass.methods) { - for (mappedMethod in mappedMethods) { - val method = clazz.methods.find { - when { - it.name != mappedMethod.name.value -> false - Modifier.isProtected(it.modifiers) && !includeProtected -> false - Modifier.isPrivate(it.modifiers) && !includePrivate -> false - else -> true - } - } ?: continue - - map[JavaObjectMappingProvider.MethodSignature(unmappedMethodName, method.parameterTypes)] = - JavaObjectMappingProvider.RenameableMethod(method, unmappedMethodName) - } - } - } - - private fun findRemappedFields( - clazz: Class<*>, - list: MutableList, - includeProtected: Boolean, - includePrivate: Boolean - ) { - val mappedClass = Mappings.getMappedClass(clazz.name) ?: return - - for ((unmappedFieldName, mappedField) in mappedClass.fields) { - val field = clazz.fields.find { - when { - it.name != mappedField.name.value -> false - Modifier.isProtected(it.modifiers) && !includeProtected -> false - Modifier.isPrivate(it.modifiers) && !includePrivate -> false - else -> true - } - } ?: continue - - list.add(JavaObjectMappingProvider.RenameableField(field, unmappedFieldName)) - } - } -} diff --git a/src/main/kotlin/com/chattriggers/ctjs/internal/launch/CTMixinPlugin.kt b/src/main/kotlin/com/chattriggers/ctjs/internal/launch/CTMixinPlugin.kt index e72f0576..4ea9040f 100644 --- a/src/main/kotlin/com/chattriggers/ctjs/internal/launch/CTMixinPlugin.kt +++ b/src/main/kotlin/com/chattriggers/ctjs/internal/launch/CTMixinPlugin.kt @@ -1,7 +1,5 @@ package com.chattriggers.ctjs.internal.launch -import com.chattriggers.ctjs.api.Mappings -import com.chattriggers.ctjs.engine.printTraceToConsole import com.chattriggers.ctjs.internal.engine.module.ModuleManager import com.llamalad7.mixinextras.MixinExtrasBootstrap import org.objectweb.asm.tree.ClassNode @@ -14,17 +12,8 @@ import java.io.PrintStream class CTMixinPlugin : IMixinConfigPlugin { override fun onLoad(mixinPackage: String?) { redirectIO() - - Mappings.initialize() ModuleManager.setup() MixinExtrasBootstrap.init() - - try { - DynamicMixinManager.initialize() - DynamicMixinManager.applyAccessWideners() - } catch (e: Throwable) { - IllegalStateException("Error generating dynamic mixins", e).printTraceToConsole() - } } override fun getRefMapperConfig(): String? = null diff --git a/src/main/kotlin/com/chattriggers/ctjs/internal/launch/Descriptor.kt b/src/main/kotlin/com/chattriggers/ctjs/internal/launch/Descriptor.kt deleted file mode 100644 index 6f4d64b7..00000000 --- a/src/main/kotlin/com/chattriggers/ctjs/internal/launch/Descriptor.kt +++ /dev/null @@ -1,387 +0,0 @@ -package com.chattriggers.ctjs.internal.launch - -import com.chattriggers.ctjs.api.Mappings -import com.chattriggers.ctjs.internal.launch.generation.Utils -import org.objectweb.asm.Type - -sealed interface Descriptor { - val isType get() = true - - fun originalDescriptor(): String - fun mappedDescriptor(): String - - fun toType(): Type - fun toMappedType(): Type - - enum class Primitive(private val type: Type) : Descriptor { - VOID(Type.VOID_TYPE), - BOOLEAN(Type.BOOLEAN_TYPE), - CHAR(Type.CHAR_TYPE), - BYTE(Type.BYTE_TYPE), - SHORT(Type.SHORT_TYPE), - INT(Type.INT_TYPE), - FLOAT(Type.FLOAT_TYPE), - LONG(Type.LONG_TYPE), - DOUBLE(Type.DOUBLE_TYPE); - - override fun originalDescriptor(): String = type.descriptor - override fun mappedDescriptor() = originalDescriptor() - override fun toType() = type - override fun toMappedType() = type - - override fun toString() = originalDescriptor() - - companion object { - val IDENTIFIERS = entries.map { it.toString() } - } - } - - class Object(private val descriptor: String) : Descriptor { - init { - require(descriptor !in Primitive.IDENTIFIERS) { - "Cannot pass a primitive type to Descriptor.Object" - } - require(!descriptor.startsWith('[')) { - "Cannot pass an array type to Descriptor.Object" - } - require('(' !in descriptor && ')' !in descriptor) { - "Cannot pass a method descriptor to Descriptor.Object" - } - require(':' !in descriptor) { - "Cannot pass a field descriptor to Descriptor.Object" - } - } - - override fun originalDescriptor() = descriptor - - override fun mappedDescriptor(): String { - // Do not map this class if it is not in a mapped package - for (mappedPackage in Mappings.mappedPackages) { - if (descriptor.startsWith(mappedPackage)) { - return Mappings.getMappedClassName(descriptor)?.let { - "L$it;" - } ?: error("Unknown class \"$descriptor\"") - } - } - - return descriptor - } - - override fun toType(): Type = Type.getType(originalDescriptor()) - - override fun toMappedType(): Type = Type.getType(mappedDescriptor()) - - override fun toString() = originalDescriptor() - } - - data class Array(val base: Descriptor, val dimensions: Int) : Descriptor { - init { - require(base.isType) { - "Cannot pass a non-type object base to Descriptor.Array" - } - require(dimensions > 0) { - "Cannot pass a dimensions count less than 1 to Descritor.Array" - } - } - - override fun originalDescriptor() = "[".repeat(dimensions) + base.originalDescriptor() - - override fun mappedDescriptor() = "[".repeat(dimensions) + base.mappedDescriptor() - - override fun toType(): Type = Type.getType(originalDescriptor()) - - override fun toMappedType(): Type = Type.getType(mappedDescriptor()) - - override fun toString() = originalDescriptor() - } - - data class Field(val owner: Object?, val name: String, val type: Descriptor?) : Descriptor { - override val isType get() = false - private val mappedName by lazy { - // Default to 'name' in case this field isn't mapped. If not, the Mixin will just fail to apply - Mappings.getMappedClass(owner!!.originalDescriptor())?.fields?.get(name)?.name?.value ?: name - } - - init { - require(type?.isType != false) { - "Cannot use non-type descriptor $type as the field type" - } - } - - override fun originalDescriptor() = buildString { - if (owner != null) - append(owner.originalDescriptor()) - append(name) - append(':') - if (type != null) - append(type.originalDescriptor()) - } - - override fun mappedDescriptor() = buildString { - require(owner != null) { - "Cannot build mapped field descriptor from incomplete field descriptor" - } - append(owner.mappedDescriptor()) - append(mappedName) - append(':') - if (type != null) - append(type.mappedDescriptor()) - } - - override fun toType() = error("Cannot convert Field descriptor to Type") - - override fun toMappedType() = error("Cannot convert Field descriptor to Type") - - override fun toString() = originalDescriptor() - } - - data class Method( - val owner: Object?, - val name: String, - val parameters: List?, - val returnType: Descriptor?, - ) : Descriptor { - override val isType get() = false - private val mappedName by lazy { - // Default to 'name' in case this field isn't mapped. If not, the Mixin will just fail to apply - Mappings.getMappedClass(owner!!.originalDescriptor()) - ?.let { Utils.findMethod(it, this) }?.first?.name?.value - ?: name - } - - init { - parameters?.forEach { - require(it.isType) { - "Cannot use non-type descriptor $it as a method parameter" - } - } - require(returnType?.isType != false) { - "Cannot use non-type descriptor $returnType as the method return type" - } - - require((parameters == null) == (returnType == null)) { - "Parameters and return type must both be specified or omitted in a method descriptor" - } - } - - override fun originalDescriptor() = buildString { - if (owner != null) - append(owner.originalDescriptor()) - append(name) - if (parameters != null) { - append('(') - parameters.forEach { append(it.originalDescriptor()) } - append(')') - append(returnType!!.originalDescriptor()) - } - } - - override fun mappedDescriptor() = buildString { - require(owner != null) { - "Cannot build mapped method descriptor from incomplete method descriptor" - } - append(owner.mappedDescriptor()) - append(mappedName) - if (parameters != null) { - append('(') - parameters.forEach { append(it.mappedDescriptor()) } - append(')') - append(returnType!!.mappedDescriptor()) - } - } - - override fun toType(): Type = Type.getMethodType(originalDescriptor()) - - override fun toMappedType(): Type = Type.getMethodType(mappedDescriptor()) - - override fun toString() = originalDescriptor() - } - - data class New(val type: Descriptor, val parameters: List?) : Descriptor { - override val isType get() = false - - init { - // TODO: What would `new int[]{...}` look like here? - require(type is Object) { - "New descriptor cannot use non-object descriptor as its return type" - } - parameters?.forEach { - require(it.isType) { - "Cannot use non-type descriptor $it as a new descriptor parameter" - } - } - } - - override fun originalDescriptor() = buildString { - if (parameters != null) { - append('(') - parameters.forEach { append(it.originalDescriptor()) } - append(')') - } - append(type.originalDescriptor()) - } - - override fun mappedDescriptor() = buildString { - if (parameters != null) { - append('(') - parameters.forEach { append(it.mappedDescriptor()) } - append(')') - } - append(type.mappedDescriptor()) - } - - override fun toType() = error("Cannot convert New descriptor to Type") - - override fun toMappedType() = error("Cannot convert New descriptor to Type") - - override fun toString() = originalDescriptor() - } - - class Parser(private val text: String) { - private var cursor = 0 - private val ch get() = text[cursor] - private val done get() = cursor > text.lastIndex - - init { - require(text.isNotEmpty()) { "Invalid descriptor \"$text\"" } - } - - private fun parseJavaIdentifier(): String? { - if (done) - return null - - listOf("", "").forEach { - if (text.substring(cursor).startsWith(it)) { - cursor += it.length - return it - } - } - - if (!ch.isJavaIdentifierStart()) - return null - - val start = cursor - cursor++ - while (!done && ch.isJavaIdentifierPart()) - cursor++ - return text.substring(start, cursor) - } - - fun parseType(full: Boolean = false): Descriptor { - if (full) - check(cursor == 0) - - val descriptor = if (ch == 'L') { - val semicolonIndex = text.indexOf(';', cursor) - if (semicolonIndex == -1) - error("Invalid descriptor \"$text\": expected ';' after position $cursor") - val objectType = text.substring(cursor, semicolonIndex + 1) - cursor += objectType.length - Object(objectType) - } else if (ch in "VZCBSIFJD") { - val primitive = Primitive.entries.first { it.toString() == ch.toString() } - cursor++ - primitive - } else if (ch == '[') { - cursor++ - val base = parseType() - if (base is Array) { - Array(base.base, base.dimensions + 1) - } else Array(base, 1) - } else { - throw IllegalArgumentException("Invalid descriptor \"$text\": unexpected character at position $cursor") - } - - if (full) - require(done) { "Invalid descriptor: \"$text\"" } - - return descriptor - } - - fun parseField(full: Boolean): Field { - check(cursor == 0) - - val owner = try { - val type = parseType() - require(type is Object) { - "Cannot create field descriptor with a non-object owner" - } - type - } catch (e: IllegalArgumentException) { - if (full) - throw e - null - } - - val name = parseJavaIdentifier() - requireNotNull(name) { "Invalid field descriptor: \"$text\"" } - - val type = if (!done && ch == ':') { - cursor++ - parseType() - } else null - - if (full) - requireNotNull(type) { "Invalid field descriptor: \"$text\"" } - - require(done) { "Invalid field descriptor: \"$text\"" } - return Field(owner, name, type) - } - - fun parseMethod(full: Boolean): Method { - check(cursor == 0) - - val owner = try { - val type = parseType() - require(type is Object) { - "Cannot create method descriptor with a non-object owner" - } - type - } catch (e: IllegalArgumentException) { - if (full) - throw e - null - } - - val name = parseJavaIdentifier() - requireNotNull(name) { "Invalid method descriptor: \"$text\"" } - - val parameters = parseParameters() - if (parameters == null && full) - throw IllegalArgumentException("Expected full method descriptor, found \"$text\"") - - val returnType = if (parameters != null) { - parseType() - } else null - - require(done) { "Invalid method descriptor: \"$text\"" } - - return Method(owner, name, parameters, returnType) - } - - fun parseNew(full: Boolean): New { - check(cursor == 0) - - val parameters = parseParameters() - if (parameters == null && full) - throw IllegalArgumentException("Expected full new descriptor, found \"$text\"") - - val type = parseType() - - require(done) { "Invalid new descriptor: \"$text\"" } - return New(type, parameters) - } - - private fun parseParameters(): List? { - return if (!done && ch == '(') { - cursor++ - val parameters = mutableListOf() - while (!done && ch != ')') - parameters.add(parseType()) - require(!done && ch == ')') { "Invalid method descriptor: \"$text\"" } - cursor++ - parameters - } else null - } - } -} diff --git a/src/main/kotlin/com/chattriggers/ctjs/internal/launch/DynamicMixinManager.kt b/src/main/kotlin/com/chattriggers/ctjs/internal/launch/DynamicMixinManager.kt deleted file mode 100644 index 45a9d5a2..00000000 --- a/src/main/kotlin/com/chattriggers/ctjs/internal/launch/DynamicMixinManager.kt +++ /dev/null @@ -1,112 +0,0 @@ -package com.chattriggers.ctjs.internal.launch - -import com.chattriggers.ctjs.CTJS -import com.chattriggers.ctjs.api.Mappings -import com.chattriggers.ctjs.internal.engine.JSLoader -import com.chattriggers.ctjs.internal.engine.module.ModuleManager -import com.chattriggers.ctjs.internal.launch.generation.DynamicMixinGenerator -import com.chattriggers.ctjs.internal.launch.generation.GenerationContext -import com.chattriggers.ctjs.internal.launch.generation.Utils -import kotlinx.serialization.json.* -import org.spongepowered.asm.mixin.Mixins -import org.spongepowered.asm.service.MixinService -import java.io.ByteArrayInputStream -import java.io.File -import java.net.URI -import java.net.URL -import java.net.URLConnection -import java.net.URLStreamHandler - -internal object DynamicMixinManager { - internal const val GENERATED_PROTOCOL = "ct-generated" - internal const val GENERATED_MIXIN = "ct-generated.mixins.json" - internal const val GENERATED_PACKAGE = "com/chattriggers/ctjs/generated_mixins" - - lateinit var mixins: Map - - fun initialize() { - mixins = JSLoader.mixinSetup(ModuleManager.cachedModules.filter { it.metadata.mixinEntry != null }) - } - - fun applyAccessWideners() { - for ((mixin, details) in mixins) { - val mappedClass = Mappings.getMappedClass(mixin.target) ?: run { - if (mixin.remap == false) { - Mappings.getUnmappedClass(mixin.target) - } else { - error("Unknown class name ${mixin.target}") - } - } - - for ((field, isMutable) in details.fieldWideners) - Utils.widenField(mappedClass, field, isMutable) - for ((method, isMutable) in details.methodWideners) - Utils.widenMethod(mappedClass, method, isMutable) - } - } - - fun applyMixins() { - val dynamicMixins = mutableListOf() - - if (CTJS.isDevelopment) deleteOldMixinClasses() - - for ((mixin, details) in mixins) { - val ctx = GenerationContext(mixin) - val generator = DynamicMixinGenerator(ctx, details) - ByteBasedStreamHandler[ctx.generatedClassFullPath + ".class"] = generator.generate() - dynamicMixins += ctx.generatedClassName - } - - ByteBasedStreamHandler[GENERATED_MIXIN] = createDynamicMixinsJson(dynamicMixins) - - injectConfiguration() - } - - private fun createDynamicMixinsJson(mixins: List): ByteArray { - return buildJsonObject { - put("required", JsonPrimitive(true)) - put("minVersion", JsonPrimitive("0.8")) - put("package", JsonPrimitive("com.chattriggers.ctjs.generated_mixins")) - put("compatibilityLevel", JsonPrimitive("JAVA_17")) - putJsonObject("injectors") { - put("defaultRequire", JsonPrimitive(1)) - } - - putJsonArray("client") { mixins.forEach(::add) } - }.toString().toByteArray() - } - - private fun injectConfiguration() { - // Credit to hugeblank and his allium project for this setup - // https://github.com/hugeblank/allium/blob/mixins/src/main/java/dev/hugeblank/allium/AlliumPreLaunch.java - val classLoader = DynamicMixinManager::class.java.classLoader - val addUrlMethod = classLoader::class.java.methods.first { it.name == "addUrlFwd" } - addUrlMethod.isAccessible = true - addUrlMethod.invoke(classLoader, ByteBasedStreamHandler.url) - - Mixins.addConfiguration(GENERATED_MIXIN) - } - - private fun deleteOldMixinClasses() { - val dir = File(CTJS.configLocation, "ChatTriggers/mixin-classes") - dir.listFiles()?.forEach { it.delete() } - } - - private object ByteBasedStreamHandler : URLStreamHandler() { - private val classBytes = mutableMapOf() - - val url = URL.of(URI(GENERATED_PROTOCOL, null, "/", ""), ByteBasedStreamHandler) - - operator fun set(path: String, bytes: ByteArray) { - check(classBytes.put(path, bytes) == null) - } - - override fun openConnection(url: URL): URLConnection? = - classBytes[url.path.drop(1)]?.let { Connection(url, it) } - - private class Connection(url: URL, private val bytes: ByteArray) : URLConnection(url) { - override fun getInputStream() = ByteArrayInputStream(bytes) - override fun connect() = throw UnsupportedOperationException() - } - } -} diff --git a/src/main/kotlin/com/chattriggers/ctjs/internal/launch/InvokeDynamicSupport.kt b/src/main/kotlin/com/chattriggers/ctjs/internal/launch/InvokeDynamicSupport.kt deleted file mode 100644 index 767dba1c..00000000 --- a/src/main/kotlin/com/chattriggers/ctjs/internal/launch/InvokeDynamicSupport.kt +++ /dev/null @@ -1,97 +0,0 @@ -package com.chattriggers.ctjs.internal.launch - -import com.chattriggers.ctjs.internal.engine.JSLoader -import com.chattriggers.ctjs.internal.launch.generation.InjectorGenerator -import org.objectweb.asm.Handle -import org.objectweb.asm.Opcodes -import org.objectweb.asm.Type -import java.lang.invoke.CallSite -import java.lang.invoke.MethodHandles -import java.lang.invoke.MethodType -import java.lang.invoke.MutableCallSite -import kotlin.reflect.jvm.javaMethod - -internal object InvokeDynamicSupport { - internal val BOOTSTRAP_HANDLE = Handle( - Opcodes.H_INVOKESTATIC, - InvokeDynamicSupport::class.qualifiedName!!.replace('.', '/'), - "bootstrapInvokeMixin", - Type.getMethodDescriptor(::bootstrapInvokeMixin.javaMethod), - false, - ) - - @JvmStatic - fun bootstrapInvokeMixin( - lookup: MethodHandles.Lookup, - name: String, - type: MethodType, - mixinId: Int, - ): CallSite { - // This method is called when the invokedynamic instruction generated by InjectorGenerator is first encountered - // (i.e. the first time the mixin handler method is called). This method's job is to return a CallSite object, - // which contains the actual target we want to call in the future (i.e. in future invocations of the mixin - // handler method). - - val callSite = MutableCallSite(type) - - // We link to an intermediary method (initInvokeMixin) that will do the function lookup when the method is first - // called. This intermediary method doesn't meet the required type of (Object[])Object, so we need to meddle - // with it to make sure it fits. It requires the call site and mixinId as parameters, which are all effectively - // constants at this point in time (we have them now and they will not change). We thus create a new - // MethodHandle with these arguments automatically provided, which gives us a handle that only needs that final - // Array argument. - val initHandle = MethodHandles.insertArguments( - lookup.findStatic( - InvokeDynamicSupport::class.java, - "initInvokeMixin", - MethodType.methodType( - Any::class.java, - MutableCallSite::class.java, - String::class.java, - Int::class.java, - Array::class.java, - ) - ), - 0, - callSite, - name, - mixinId, - ) - - // Bind the target to the callSite and return it - callSite.target = initHandle.asType(type) - return callSite - } - - @JvmStatic - fun initInvokeMixin(callSite: MutableCallSite, name: String, mixinId: Int, args: Array): Any? { - // Make an initial lookup to the target function. This is where we want our mixin handler method to point to - val mixinCallback = JSLoader.invokeMixinLookup(mixinId) - - checkNotNull(mixinCallback.handle) - checkNotNull(mixinCallback.method) - - // Until we /ct load, however. When we reload, we need to re-resolve all JS invocation targets since our old - // engine context has been thrown away and recreated. It is also possible that the user has changed their code - // in the handler function. - val initTarget = callSite.target - - // This switch point will be our indicator to know if the user has reloaded. As soon as the user reloads, this - // switch will get flipped, immediately making the call site link back to the fallback MethodHandle. The - // fallback method (initTarget above) is this method, so we will rerun the lookup and get a handle to the new - // method. - // - // Note that the mechanism for flipping these switches is in MixinCallback. When the user calls attach(), the - // invalidator gets invalidated, as the method has changed. This of course happens for all mixins when the user - // /ct loads, since the scripts are re-run. - val guardedTarget = mixinCallback.invalidator.guardWithTest(mixinCallback.handle, initTarget) - - // We now have a target that is very fast to call back into the target method, and can survive reloads or calls - // to attach(), so we want our call site to now point to that target. - callSite.target = guardedTarget - - // This method invocation occurred because we actually tried to call the target method with the supplied mixin - // arguments. So in addition to performing the call site rebinding, we also need to make the actual method call. - return mixinCallback.handle!!.invoke(args) - } -} diff --git a/src/main/kotlin/com/chattriggers/ctjs/internal/launch/MixinDetails.kt b/src/main/kotlin/com/chattriggers/ctjs/internal/launch/MixinDetails.kt deleted file mode 100644 index f3e29033..00000000 --- a/src/main/kotlin/com/chattriggers/ctjs/internal/launch/MixinDetails.kt +++ /dev/null @@ -1,9 +0,0 @@ -package com.chattriggers.ctjs.internal.launch - -import com.chattriggers.ctjs.engine.MixinCallback - -internal data class MixinDetails( - val injectors: MutableList = mutableListOf(), - val fieldWideners: MutableMap = mutableMapOf(), - val methodWideners: MutableMap = mutableMapOf(), -) diff --git a/src/main/kotlin/com/chattriggers/ctjs/internal/launch/annotations.kt b/src/main/kotlin/com/chattriggers/ctjs/internal/launch/annotations.kt deleted file mode 100644 index 10759c54..00000000 --- a/src/main/kotlin/com/chattriggers/ctjs/internal/launch/annotations.kt +++ /dev/null @@ -1,300 +0,0 @@ -package com.chattriggers.ctjs.internal.launch - -import com.chattriggers.ctjs.internal.utils.descriptor -import org.objectweb.asm.Opcodes -import org.spongepowered.asm.mixin.injection.Constant as SPConstant - -/* - * Annotation classes present some difficulties, especially when trying to - * create them from an embedded engine context. They've been more-or-less - * recreated here as normal classes for the loaders to use - */ - -data class Mixin( - val target: String, - val priority: Int?, - val remap: Boolean?, -) - -data class At( - val value: String, - val id: String?, - val slice: String?, - val shift: Shift?, - val by: Int?, - val args: List?, - val target: String?, - val ordinal: Int?, - val opcode: Int?, - val remap: Boolean?, -) { - internal val atTarget: AtTarget<*> by lazy(::getAtTarget) - - internal sealed class AtTarget(val descriptor: T, val targetName: String) - - internal class InvokeTarget(descriptor: Descriptor.Method) : AtTarget(descriptor, "INVOKE") { - override fun toString() = descriptor.originalDescriptor() - } - - internal class NewTarget(descriptor: Descriptor.New) : AtTarget(descriptor, "NEW") { - override fun toString() = descriptor.originalDescriptor() - } - - internal class FieldTarget( - descriptor: Descriptor.Field, val isGet: Boolean?, val isStatic: Boolean?, - ) : AtTarget(descriptor, "FIELD") { - override fun toString() = descriptor.originalDescriptor() - } - - internal class ConstantTarget(val key: String, descriptor: Descriptor) : AtTarget(descriptor, "CONSTANT") { - init { - require(descriptor.isType) - } - - override fun toString() = "$key=$descriptor" - } - - private fun getAtTarget(): AtTarget<*> { - return when (value) { - "INVOKE" -> { - requireNotNull(target) { "At targeting INVOKE expects its target to be a method descriptor" } - InvokeTarget(Descriptor.Parser(target).parseMethod(full = true)) - } - "NEW" -> { - requireNotNull(target) { "At targeting NEW expects its target to be a new invocation descriptor" } - NewTarget(Descriptor.Parser(target).parseNew(full = true)) - } - "FIELD" -> { - requireNotNull(target) { "At targeting FIELD expects its target to be a field descriptor" } - if (opcode != null) { - require( - opcode in setOf( - Opcodes.GETFIELD, - Opcodes.GETSTATIC, - Opcodes.PUTFIELD, - Opcodes.PUTSTATIC - ) - ) { - "At targeting FIELD expects its opcode to be one of: GETFIELD, GETSTATIC, PUTFIELD, PUTSTATIC" - } - val isGet = opcode == Opcodes.GETFIELD || opcode == Opcodes.GETSTATIC - val isStatic = opcode == Opcodes.GETSTATIC || opcode == Opcodes.PUTSTATIC - FieldTarget(Descriptor.Parser(target).parseField(full = true), isGet, isStatic) - } else { - FieldTarget(Descriptor.Parser(target).parseField(full = true), null, null) - } - } - "CONSTANT" -> { - require(args != null) { - "At targeting CONSTANT requires args" - } - args.firstNotNullOfOrNull { - val key = it.substringBefore('=') - val type = when (key) { - "null" -> Any::class.descriptor() // Is this right? - "intValue" -> Descriptor.Primitive.INT - "floatValue" -> Descriptor.Primitive.FLOAT - "longValue" -> Descriptor.Primitive.LONG - "doubleValue" -> Descriptor.Primitive.DOUBLE - "stringValue" -> String::class.descriptor() - "classValue" -> Descriptor.Object("L${it.substringAfter("=")};") - else -> return@firstNotNullOfOrNull null - } - - ConstantTarget(key, type) - } ?: error("At targeting CONSTANT expects a typeValue arg") - } - else -> error("Invalid At.value for Utils.getAtTarget: ${value}") - } - } - - enum class Shift { - NONE, - BEFORE, - AFTER, - BY, - } -} - -data class Slice( - val id: String?, - val from: At?, - val to: At?, -) - -// There are two ways to capture a local: -// - By absolute local index: Local(type = "F", index = 4) -// - By ordinal and type: Local(type = "F", ordinal = 1) -// -// If print is required, then type is not required since the local -// is not actually captured -data class Local( - val print: Boolean?, - val index: Int?, - val ordinal: Int?, - val type: String?, - val mutable: Boolean?, -) - -data class Constant( - val nullValue: Boolean?, - val intValue: Int?, - val floatValue: Float?, - val longValue: Long?, - val doubleValue: Double?, - val stringValue: String?, - val classValue: String?, - val ordinal: Int?, - val slice: String?, - val expandZeroConditions: List?, - val log: Boolean?, -) { - fun getTypeDescriptor() = when { - nullValue != null -> Any::class.descriptor() // Is this right? - intValue != null -> Descriptor.Primitive.INT - floatValue != null -> Descriptor.Primitive.FLOAT - longValue != null -> Descriptor.Primitive.LONG - doubleValue != null -> Descriptor.Primitive.DOUBLE - stringValue != null -> String::class.descriptor() - classValue != null -> Class::class.descriptor() - else -> error("Constant() expects one non-null type field") - } -} - -sealed interface IInjector - -data class Inject( - val method: String, - val id: String?, - val slice: List?, - val at: List?, - val cancellable: Boolean?, - val locals: List?, - val remap: Boolean?, - val require: Int?, - val expect: Int?, - val allow: Int?, - val constraints: String?, -) : IInjector - -data class Redirect( - val method: String, - val slice: Slice?, - val at: At, - val locals: List?, - val remap: Boolean?, - val require: Int?, - val expect: Int?, - val allow: Int?, - val constraints: String?, -) : IInjector - -data class ModifyArg( - val method: String, - val slice: Slice?, - val at: At, - val index: Int, - val captureAllParams: Boolean?, - val locals: List?, - val remap: Boolean?, - val require: Int?, - val expect: Int?, - val allow: Int?, - val constraints: String?, -) : IInjector - -data class ModifyArgs( - val method: String, - val slice: Slice?, - val at: At, - val locals: List?, - val remap: Boolean?, - val require: Int?, - val expect: Int?, - val allow: Int?, - val constraints: String?, -) : IInjector - -data class ModifyConstant( - val method: String, - val slice: List?, - val constant: Constant, - val locals: List?, - val remap: Boolean?, - val require: Int?, - val expect: Int?, - val allow: Int?, - val constraints: String?, -) : IInjector - -data class ModifyExpressionValue( - val method: String, - val at: At, - val slice: List?, - val locals: List?, - val remap: Boolean?, - val require: Int?, - val expect: Int?, - val allow: Int?, -) : IInjector - -data class ModifyReceiver( - val method: String, - val at: At, - val slice: List?, - val locals: List?, - val remap: Boolean?, - val require: Int?, - val expect: Int?, - val allow: Int?, -) : IInjector - -data class ModifyReturnValue( - val method: String, - val at: At, - val slice: List?, - val locals: List?, - val remap: Boolean?, - val require: Int?, - val expect: Int?, - val allow: Int?, -) : IInjector - -data class ModifyVariable( - val method: String, - val at: At, - val slice: Slice?, - val print: Boolean?, - val ordinal: Int?, - val index: Int?, - val type: String?, - val locals: List?, - val remap: Boolean?, - val require: Int?, - val expect: Int?, - val allow: Int?, - val constraints: String?, -) : IInjector - -data class WrapOperation( - val method: String, - val at: At?, - val constant: Constant?, - val slice: List?, - val locals: List?, - val remap: Boolean?, - val require: Int?, - val expect: Int?, - val allow: Int?, -) : IInjector - -data class WrapWithCondition( - val method: String, - val at: At, - val slice: List?, - val locals: List?, - val remap: Boolean?, - val require: Int?, - val expect: Int?, - val allow: Int?, -) : IInjector diff --git a/src/main/kotlin/com/chattriggers/ctjs/internal/launch/generation/DynamicMixinGenerator.kt b/src/main/kotlin/com/chattriggers/ctjs/internal/launch/generation/DynamicMixinGenerator.kt deleted file mode 100644 index 080a8464..00000000 --- a/src/main/kotlin/com/chattriggers/ctjs/internal/launch/generation/DynamicMixinGenerator.kt +++ /dev/null @@ -1,53 +0,0 @@ -package com.chattriggers.ctjs.internal.launch.generation - -import codes.som.koffee.assembleClass -import codes.som.koffee.modifiers.public -import com.chattriggers.ctjs.CTJS -import com.chattriggers.ctjs.internal.launch.* -import org.objectweb.asm.ClassWriter -import org.objectweb.asm.Opcodes -import java.io.File -import org.spongepowered.asm.mixin.Mixin as SPMixin - -internal class DynamicMixinGenerator(private val ctx: GenerationContext, private val details: MixinDetails) { - fun generate(): ByteArray { - val mixinClassNode = assembleClass(public, ctx.generatedClassFullPath, version = Opcodes.V17) { - for ((id, injector) in details.injectors) { - when (injector) { - is Inject -> InjectGenerator(ctx, id, injector).generate() - is Redirect -> RedirectGenerator(ctx, id, injector).generate() - is ModifyArg -> ModifyArgGenerator(ctx, id, injector).generate() - is ModifyArgs -> ModifyArgsGenerator(ctx, id, injector).generate() - is ModifyConstant -> ModifyConstantGenerator(ctx, id, injector).generate() - is ModifyExpressionValue -> ModifyExpressionValueGenerator(ctx, id, injector).generate() - is ModifyReceiver -> ModifyReceiverGenerator(ctx, id, injector).generate() - is ModifyReturnValue -> ModifyReturnValueInjector(ctx, id, injector).generate() - is ModifyVariable -> ModifyVariableGenerator(ctx, id, injector).generate() - is WrapOperation -> WrapOperationGenerator(ctx, id, injector).generate() - is WrapWithCondition -> WrapWithConditionGenerator(ctx, id, injector).generate() - } - } - } - - val mixinAnnotation = mixinClassNode.visitAnnotation(SPMixin::class.java.descriptorString(), false) - val mixin = ctx.mixin - mixinAnnotation.visit("targets", listOf(ctx.mappedClass.name.value)) - if (mixin.priority != null) - mixinAnnotation.visit("priority", mixin.priority) - if (mixin.remap != null) - mixinAnnotation.visit("remap", mixin.remap) - mixinAnnotation.visitEnd() - - val writer = ClassWriter(ClassWriter.COMPUTE_FRAMES) - mixinClassNode.accept(writer) - val bytes = writer.toByteArray() - - if (CTJS.isDevelopment) { - val dir = File(CTJS.configLocation, "ChatTriggers/mixin-classes") - dir.mkdirs() - File(dir, "${ctx.generatedClassName}.class").writeBytes(bytes) - } - - return bytes - } -} diff --git a/src/main/kotlin/com/chattriggers/ctjs/internal/launch/generation/GenerationContext.kt b/src/main/kotlin/com/chattriggers/ctjs/internal/launch/generation/GenerationContext.kt deleted file mode 100644 index 11cdd285..00000000 --- a/src/main/kotlin/com/chattriggers/ctjs/internal/launch/generation/GenerationContext.kt +++ /dev/null @@ -1,28 +0,0 @@ -package com.chattriggers.ctjs.internal.launch.generation - -import com.chattriggers.ctjs.api.Mappings -import com.chattriggers.ctjs.internal.launch.Descriptor -import com.chattriggers.ctjs.internal.launch.DynamicMixinManager -import com.chattriggers.ctjs.internal.launch.Mixin -import org.spongepowered.asm.mixin.transformer.ClassInfo - -internal data class GenerationContext(val mixin: Mixin) { - val mappedClass = Mappings.getMappedClass(mixin.target) ?: run { - if (mixin.remap == false) { - Mappings.getUnmappedClass(mixin.target) - } else { - error("Unknown class name ${mixin.target}") - } - } - val generatedClassName = "CTMixin_\$${mixin.target.replace('.', '_')}\$_${mixinCounter++}" - val generatedClassFullPath = "${DynamicMixinManager.GENERATED_PACKAGE}/$generatedClassName" - - fun findMethod(method: String): Pair { - val descriptor = Descriptor.Parser(method).parseMethod(full = false) - return Utils.findMethod(mappedClass, descriptor) - } - - companion object { - private var mixinCounter = 0 - } -} diff --git a/src/main/kotlin/com/chattriggers/ctjs/internal/launch/generation/InjectGenerator.kt b/src/main/kotlin/com/chattriggers/ctjs/internal/launch/generation/InjectGenerator.kt deleted file mode 100644 index 38969063..00000000 --- a/src/main/kotlin/com/chattriggers/ctjs/internal/launch/generation/InjectGenerator.kt +++ /dev/null @@ -1,74 +0,0 @@ -package com.chattriggers.ctjs.internal.launch.generation - -import codes.som.koffee.MethodAssembly -import codes.som.koffee.insns.jvm.aconst_null -import codes.som.koffee.insns.jvm.areturn -import codes.som.koffee.insns.jvm.ldc -import com.chattriggers.ctjs.internal.launch.Descriptor -import com.chattriggers.ctjs.internal.launch.Inject -import com.chattriggers.ctjs.internal.utils.descriptor -import org.objectweb.asm.tree.MethodNode -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo -import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable -import org.spongepowered.asm.mixin.injection.Inject as SPInject - -internal class InjectGenerator( - ctx: GenerationContext, - id: Int, - private val inject: Inject, -) : InjectorGenerator(ctx, id) { - override val type = "inject" - - override fun getInjectionSignature(): InjectionSignature { - val (mappedMethod, method) = ctx.findMethod(inject.method) - val parameters = mutableListOf() - - if (mappedMethod.returnType.value == "V") { - parameters.add(Parameter(CallbackInfo::class.descriptor())) - } else { - parameters.add(Parameter(CallbackInfoReturnable::class.descriptor())) - } - - inject.locals?.forEach { - parameters.add(Utils.getParameterFromLocal(it)) - } - - return InjectionSignature( - mappedMethod, - parameters, - Descriptor.Primitive.VOID, - method.isStatic, - ) - } - - override fun attachAnnotation(node: MethodNode, signature: InjectionSignature) { - node.visitAnnotation(SPInject::class.java.descriptorString(), true).apply { - if (inject.id != null) - visit("id", inject.id) - visit("method", signature.targetMethod.toFullDescriptor()) - if (inject.slice != null) - visit("slice", inject.slice.map(Utils::createSliceAnnotation)) - if (inject.at != null) - visit("at", inject.at.map(Utils::createAtAnnotation)) - if (inject.cancellable != null) - visit("cancellable", inject.cancellable) - if (inject.remap != null) - visit("remap", inject.remap) - if (inject.require != null) - visit("require", inject.require) - if (inject.expect != null) - visit("expect", inject.expect) - if (inject.allow != null) - visit("allow", inject.allow) - if (inject.constraints != null) - visit("constraints", inject.constraints) - visitEnd() - } - } - - context(MethodAssembly) - override fun generateNotAttachedBehavior() { - // This method is expected to leave something on the stack - aconst_null - } -} diff --git a/src/main/kotlin/com/chattriggers/ctjs/internal/launch/generation/InjectorGenerator.kt b/src/main/kotlin/com/chattriggers/ctjs/internal/launch/generation/InjectorGenerator.kt deleted file mode 100644 index 5b3695cf..00000000 --- a/src/main/kotlin/com/chattriggers/ctjs/internal/launch/generation/InjectorGenerator.kt +++ /dev/null @@ -1,227 +0,0 @@ -package com.chattriggers.ctjs.internal.launch.generation - -import codes.som.koffee.ClassAssembly -import codes.som.koffee.MethodAssembly -import codes.som.koffee.insns.InstructionAssembly -import codes.som.koffee.insns.jvm.* -import codes.som.koffee.insns.sugar.JumpCondition -import codes.som.koffee.insns.sugar.ifStatement -import com.chattriggers.ctjs.CTJS -import com.chattriggers.ctjs.api.Mappings -import com.chattriggers.ctjs.internal.engine.JSLoader -import com.chattriggers.ctjs.internal.launch.Descriptor -import com.chattriggers.ctjs.internal.launch.InvokeDynamicSupport -import com.chattriggers.ctjs.internal.launch.Local -import com.chattriggers.ctjs.internal.utils.descriptor -import com.chattriggers.ctjs.internal.utils.descriptorString -import org.objectweb.asm.tree.MethodNode - -internal abstract class InjectorGenerator(protected val ctx: GenerationContext, val id: Int) { - abstract val type: String - protected val signature by lazy { getInjectionSignature() } - protected val parameterDescriptors by lazy { - signature.parameters.map { - // Check if the type needs to be wrapped in a ref. Also handle the case where - // the user provides an explicitly wrapped type - if (it.local?.mutable == true && !it.descriptor.originalDescriptor() - .startsWith("Lcom/llamalad7/mixinextras/sugar/ref/") - ) { - when (it.descriptor) { - com.chattriggers.ctjs.internal.launch.Descriptor.Primitive.BOOLEAN -> com.llamalad7.mixinextras.sugar.ref.LocalBooleanRef::class.descriptor() - com.chattriggers.ctjs.internal.launch.Descriptor.Primitive.BYTE -> com.llamalad7.mixinextras.sugar.ref.LocalByteRef::class.descriptor() - com.chattriggers.ctjs.internal.launch.Descriptor.Primitive.CHAR -> com.llamalad7.mixinextras.sugar.ref.LocalCharRef::class.descriptor() - com.chattriggers.ctjs.internal.launch.Descriptor.Primitive.DOUBLE -> com.llamalad7.mixinextras.sugar.ref.LocalDoubleRef::class.descriptor() - com.chattriggers.ctjs.internal.launch.Descriptor.Primitive.FLOAT -> com.llamalad7.mixinextras.sugar.ref.LocalFloatRef::class.descriptor() - com.chattriggers.ctjs.internal.launch.Descriptor.Primitive.INT -> com.llamalad7.mixinextras.sugar.ref.LocalIntRef::class.descriptor() - com.chattriggers.ctjs.internal.launch.Descriptor.Primitive.LONG -> com.llamalad7.mixinextras.sugar.ref.LocalLongRef::class.descriptor() - com.chattriggers.ctjs.internal.launch.Descriptor.Primitive.SHORT -> com.llamalad7.mixinextras.sugar.ref.LocalShortRef::class.descriptor() - else -> com.llamalad7.mixinextras.sugar.ref.LocalRef::class.descriptor() - } - } else it.descriptor - } - } - - abstract fun getInjectionSignature(): InjectionSignature - - abstract fun attachAnnotation(node: MethodNode, signature: InjectionSignature) - - context(MethodAssembly) - abstract fun generateNotAttachedBehavior() - - context(ClassAssembly) - fun generate() { - val (targetMethod, parameters, returnType, isStatic) = signature - - var modifiers = private - if (isStatic) - modifiers += static - - val nameForInjection = targetMethod.name.original.replace('<', '$').replace('>', '$') - val methodNode = method( - modifiers, - "${CTJS.MOD_ID}_${type}_${nameForInjection}_${counter++}", - returnType.toMappedType(), - *parameterDescriptors.map { it.toMappedType() }.toTypedArray(), - ) { - // Apply parameter annotations - for (i in parameters.indices) { - val local = parameters[i].local ?: continue - node.visitParameterAnnotation(i, com.llamalad7.mixinextras.sugar.Local::class.descriptorString(), false) - .apply { - local.print?.let { visit("print", it) } - local.index?.let { visit("index", it) } - local.ordinal?.let { visit("ordinal", it) } - } - } - - // Check if we're attached - ldc(id) - invokestatic(JSLoader::class, "mixinIsAttached", Boolean::class, Int::class) - ifStatement(JumpCondition.False) { - generateNotAttachedBehavior() - generateReturn(returnType) - } - - ldc(parameters.size + if (isStatic) 0 else 1) - anewarray(Any::class) - - if (!isStatic) { - dup - ldc(0) - aload_0 - aastore - } - - parameterDescriptors.forEachIndexed { index, descriptor -> - dup - ldc(index + if (isStatic) 0 else 1) - generateParameterLoad(index) - generateBoxIfNecessary(descriptor) - aastore - } - - invokedynamic( - assembleIndyName(nameForInjection, type), - "([Ljava/lang/Object;)Ljava/lang/Object;", - InvokeDynamicSupport.BOOTSTRAP_HANDLE, - arrayOf(id), - ) - - generateUnboxIfNecessary(returnType) - generateReturn(returnType) - } - - attachAnnotation(methodNode, signature) - } - - context(MethodAssembly) - private fun generateBoxIfNecessary(descriptor: Descriptor) { - when (descriptor) { - Descriptor.Primitive.VOID -> throw IllegalStateException("Cannot use Void as a parameter type") - Descriptor.Primitive.BOOLEAN -> - invokestatic(java.lang.Boolean::class, "valueOf", java.lang.Boolean::class, boolean) - Descriptor.Primitive.CHAR -> - invokestatic(java.lang.Character::class, "valueOf", java.lang.Character::class, char) - Descriptor.Primitive.BYTE -> - invokestatic(java.lang.Byte::class, "valueOf", java.lang.Byte::class, byte) - Descriptor.Primitive.SHORT -> - invokestatic(java.lang.Short::class, "valueOf", java.lang.Short::class, short) - Descriptor.Primitive.INT -> - invokestatic(java.lang.Integer::class, "valueOf", java.lang.Integer::class, int) - Descriptor.Primitive.FLOAT -> - invokestatic(java.lang.Float::class, "valueOf", java.lang.Float::class, float) - Descriptor.Primitive.LONG -> - invokestatic(java.lang.Long::class, "valueOf", java.lang.Long::class, long) - Descriptor.Primitive.DOUBLE -> - invokestatic(java.lang.Double::class, "valueOf", java.lang.Double::class, double) - else -> {} - } - } - - context(MethodAssembly) - private fun generateUnboxIfNecessary(descriptor: Descriptor) { - when (descriptor) { - Descriptor.Primitive.VOID -> {} - Descriptor.Primitive.BOOLEAN -> { - checkcast(java.lang.Boolean::class) - invokevirtual(java.lang.Boolean::class, "booleanValue", boolean) - } - is Descriptor.Primitive -> { - checkcast(java.lang.Number::class) - - when (descriptor) { - Descriptor.Primitive.CHAR -> invokevirtual(java.lang.Number::class, "charValue", char) - Descriptor.Primitive.BYTE -> invokevirtual(java.lang.Number::class, "byteValue", byte) - Descriptor.Primitive.SHORT -> invokevirtual(java.lang.Number::class, "shortValue", short) - Descriptor.Primitive.INT -> invokevirtual(java.lang.Number::class, "intValue", int) - Descriptor.Primitive.LONG -> invokevirtual(java.lang.Number::class, "longValue", long) - Descriptor.Primitive.FLOAT -> invokevirtual(java.lang.Number::class, "floatValue", float) - Descriptor.Primitive.DOUBLE -> invokevirtual(java.lang.Number::class, "doubleValue", double) - else -> throw IllegalStateException() - } - } - else -> checkcast(descriptor.toMappedType()) - } - } - - context(MethodAssembly) - private fun generateReturn(returnType: Descriptor) { - when (returnType) { - Descriptor.Primitive.VOID -> { - pop - _return - } - Descriptor.Primitive.BOOLEAN -> ireturn - Descriptor.Primitive.LONG -> lreturn - Descriptor.Primitive.FLOAT -> freturn - Descriptor.Primitive.DOUBLE -> dreturn - is Descriptor.Primitive -> ireturn - else -> areturn - } - } - - protected fun InstructionAssembly.generateParameterLoad(parameterIndex: Int) { - val localIndex = (0 until parameterIndex).sumOf { - val descriptor = parameterDescriptors[it] - if (descriptor == Descriptor.Primitive.LONG || descriptor == Descriptor.Primitive.DOUBLE) { - // Compiler bug - @Suppress("USELESS_CAST") - 2 as Int - } else 1 - } - generateLoad(parameterDescriptors[parameterIndex], localIndex) - } - - protected fun InstructionAssembly.generateLoad(descriptor: Descriptor, index: Int) { - val modifiedIndex = if (signature.isStatic) index else index + 1 - when (descriptor) { - Descriptor.Primitive.BOOLEAN, - Descriptor.Primitive.BYTE, - Descriptor.Primitive.SHORT, - Descriptor.Primitive.INT -> ::iload - Descriptor.Primitive.LONG -> ::lload - Descriptor.Primitive.FLOAT -> ::fload - Descriptor.Primitive.DOUBLE -> ::dload - else -> ::aload - }(modifiedIndex) - } - - data class Parameter( - val descriptor: Descriptor, - val local: Local? = null, - ) - - data class InjectionSignature( - val targetMethod: Mappings.MappedMethod, - val parameters: List, - val returnType: Descriptor, - val isStatic: Boolean, - ) - - companion object { - private var counter = 0 - - fun assembleIndyName(methodName: String, injectionType: String) = - "invokeDynamic_${methodName}_${injectionType}_${counter++}" - } -} diff --git a/src/main/kotlin/com/chattriggers/ctjs/internal/launch/generation/ModifyArgGenerator.kt b/src/main/kotlin/com/chattriggers/ctjs/internal/launch/generation/ModifyArgGenerator.kt deleted file mode 100644 index bafd1297..00000000 --- a/src/main/kotlin/com/chattriggers/ctjs/internal/launch/generation/ModifyArgGenerator.kt +++ /dev/null @@ -1,72 +0,0 @@ -package com.chattriggers.ctjs.internal.launch.generation - -import codes.som.koffee.MethodAssembly -import com.chattriggers.ctjs.internal.launch.At -import com.chattriggers.ctjs.internal.launch.ModifyArg -import com.chattriggers.ctjs.internal.utils.descriptorString -import org.objectweb.asm.tree.MethodNode -import kotlin.math.sign -import org.spongepowered.asm.mixin.injection.ModifyArg as SPModifyArg - -internal class ModifyArgGenerator( - ctx: GenerationContext, - id: Int, - private val modifyArg: ModifyArg, -) : InjectorGenerator(ctx, id) { - override val type = "modifyArg" - - override fun getInjectionSignature(): InjectionSignature { - val (mappedMethod, method) = ctx.findMethod(modifyArg.method) - - // Resolve the target method - val atTarget = modifyArg.at.atTarget - check(atTarget is At.InvokeTarget) { "ModifyArg expects At.target to be INVOKE" } - val targetDescriptor = atTarget.descriptor - requireNotNull(targetDescriptor.parameters) - - if (modifyArg.index !in targetDescriptor.parameters.indices) - error("ModifyArg received an out-of-bounds index ${modifyArg.index}") - - val parameters = if (modifyArg.captureAllParams == true) { - targetDescriptor.parameters.mapTo(mutableListOf(), ::Parameter) - } else mutableListOf(Parameter(targetDescriptor.parameters[modifyArg.index])) - - val returnType = targetDescriptor.parameters[modifyArg.index] - - modifyArg.locals?.forEach { - parameters.add(Utils.getParameterFromLocal(it)) - } - - return InjectionSignature( - mappedMethod, - parameters, - returnType, - method.isStatic, - ) - } - - override fun attachAnnotation(node: MethodNode, signature: InjectionSignature) { - node.visitAnnotation(SPModifyArg::class.descriptorString(), true).apply { - visit("method", listOf(signature.targetMethod.toFullDescriptor())) - if (modifyArg.slice != null) - visit("slice", modifyArg.slice) - visit("at", Utils.createAtAnnotation(modifyArg.at)) - visit("index", modifyArg.index) - if (modifyArg.remap != null) - visit("remap", modifyArg.remap) - if (modifyArg.require != null) - visit("require", modifyArg.require) - if (modifyArg.expect != null) - visit("expect", modifyArg.expect) - if (modifyArg.allow != null) - visit("allow", modifyArg.allow) - if (modifyArg.constraints != null) - visit("constraints", modifyArg.constraints) - } - } - - context(MethodAssembly) - override fun generateNotAttachedBehavior() { - generateParameterLoad(0) - } -} diff --git a/src/main/kotlin/com/chattriggers/ctjs/internal/launch/generation/ModifyArgsGenerator.kt b/src/main/kotlin/com/chattriggers/ctjs/internal/launch/generation/ModifyArgsGenerator.kt deleted file mode 100644 index 156a35e4..00000000 --- a/src/main/kotlin/com/chattriggers/ctjs/internal/launch/generation/ModifyArgsGenerator.kt +++ /dev/null @@ -1,59 +0,0 @@ -package com.chattriggers.ctjs.internal.launch.generation - -import codes.som.koffee.MethodAssembly -import codes.som.koffee.insns.jvm.aconst_null -import com.chattriggers.ctjs.internal.launch.Descriptor -import com.chattriggers.ctjs.internal.launch.ModifyArgs -import com.chattriggers.ctjs.internal.utils.descriptor -import com.chattriggers.ctjs.internal.utils.descriptorString -import org.objectweb.asm.tree.MethodNode -import org.spongepowered.asm.mixin.injection.invoke.arg.Args -import org.spongepowered.asm.mixin.injection.ModifyArgs as SPModifyArgs - -internal class ModifyArgsGenerator( - ctx: GenerationContext, - id: Int, - private val modifyArgs: ModifyArgs, -) : InjectorGenerator(ctx, id) { - override val type = "modifyArgs" - - override fun getInjectionSignature(): InjectionSignature { - val (mappedMethod, method) = ctx.findMethod(modifyArgs.method) - - val parameters = mutableListOf() - parameters.add(Parameter(Args::class.descriptor())) - modifyArgs.locals?.forEach { - parameters.add(Utils.getParameterFromLocal(it)) - } - - return InjectionSignature( - mappedMethod, - parameters, - Descriptor.Primitive.VOID, - method.isStatic, - ) - } - - override fun attachAnnotation(node: MethodNode, signature: InjectionSignature) { - node.visitAnnotation(SPModifyArgs::class.descriptorString(), true).apply { - visit("method", listOf(signature.targetMethod.toFullDescriptor())) - if (modifyArgs.slice != null) - visit("slice", modifyArgs.slice) - visit("at", Utils.createAtAnnotation(modifyArgs.at)) - if (modifyArgs.remap != null) - visit("remap", modifyArgs.remap) - if (modifyArgs.expect != null) - visit("expect", modifyArgs.expect) - if (modifyArgs.allow != null) - visit("allow", modifyArgs.allow) - if (modifyArgs.constraints != null) - visit("constraints", modifyArgs.constraints) - } - } - - context(MethodAssembly) - override fun generateNotAttachedBehavior() { - // This method is expected to leave something on the stack - aconst_null - } -} diff --git a/src/main/kotlin/com/chattriggers/ctjs/internal/launch/generation/ModifyConstantGenerator.kt b/src/main/kotlin/com/chattriggers/ctjs/internal/launch/generation/ModifyConstantGenerator.kt deleted file mode 100644 index ae93f40c..00000000 --- a/src/main/kotlin/com/chattriggers/ctjs/internal/launch/generation/ModifyConstantGenerator.kt +++ /dev/null @@ -1,54 +0,0 @@ -package com.chattriggers.ctjs.internal.launch.generation - -import codes.som.koffee.MethodAssembly -import com.chattriggers.ctjs.internal.launch.ModifyConstant -import com.chattriggers.ctjs.internal.utils.descriptorString -import org.objectweb.asm.tree.MethodNode -import org.spongepowered.asm.mixin.injection.ModifyConstant as SPModifyConstant - -internal class ModifyConstantGenerator( - ctx: GenerationContext, - id: Int, - private val modifyConstant: ModifyConstant, -) : InjectorGenerator(ctx, id) { - override val type = "modifyConstant" - - override fun getInjectionSignature(): InjectionSignature { - val (mappedMethod, method) = ctx.findMethod(modifyConstant.method) - - val type = modifyConstant.constant.getTypeDescriptor() - val parameters = listOf(Parameter(type)) + modifyConstant.locals?.map(Utils::getParameterFromLocal).orEmpty() - - return InjectionSignature( - mappedMethod, - parameters, - type, - method.isStatic, - ) - } - - override fun attachAnnotation(node: MethodNode, signature: InjectionSignature) { - node.visitAnnotation(SPModifyConstant::class.descriptorString(), true).apply { - visit("method", signature.targetMethod.toFullDescriptor()) - if (modifyConstant.slice != null) - visit("slice", modifyConstant.slice.map(Utils::createSliceAnnotation)) - visit("constant", listOf(Utils.createConstantAnnotation(modifyConstant.constant))) - if (modifyConstant.remap != null) - visit("remap", modifyConstant.remap) - if (modifyConstant.require != null) - visit("require", modifyConstant.require) - if (modifyConstant.expect != null) - visit("expect", modifyConstant.expect) - if (modifyConstant.allow != null) - visit("allow", modifyConstant.allow) - if (modifyConstant.constraints != null) - visit("constraints", modifyConstant.constraints) - visitEnd() - } - } - - context(MethodAssembly) - override fun generateNotAttachedBehavior() { - generateParameterLoad(0) - } -} diff --git a/src/main/kotlin/com/chattriggers/ctjs/internal/launch/generation/ModifyExpressionValueGenerator.kt b/src/main/kotlin/com/chattriggers/ctjs/internal/launch/generation/ModifyExpressionValueGenerator.kt deleted file mode 100644 index 80e6b785..00000000 --- a/src/main/kotlin/com/chattriggers/ctjs/internal/launch/generation/ModifyExpressionValueGenerator.kt +++ /dev/null @@ -1,67 +0,0 @@ -package com.chattriggers.ctjs.internal.launch.generation - -import codes.som.koffee.MethodAssembly -import com.chattriggers.ctjs.internal.launch.At -import com.chattriggers.ctjs.internal.launch.Descriptor -import com.chattriggers.ctjs.internal.launch.ModifyExpressionValue -import com.chattriggers.ctjs.internal.utils.descriptorString -import org.objectweb.asm.tree.MethodNode -import com.llamalad7.mixinextras.injector.ModifyExpressionValue as SPModifyExpressionValue - -internal class ModifyExpressionValueGenerator( - ctx: GenerationContext, - id: Int, - private val modifyExpressionValue: ModifyExpressionValue, -) : InjectorGenerator(ctx, id) { - override val type = "modifyExpressionValue" - - override fun getInjectionSignature(): InjectionSignature { - val (mappedMethod, method) = ctx.findMethod(modifyExpressionValue.method) - - val exprDescriptor = when (val atTarget = modifyExpressionValue.at.atTarget) { - is At.InvokeTarget -> atTarget.descriptor.returnType - is At.FieldTarget -> atTarget.descriptor.type - is At.NewTarget -> atTarget.descriptor.type - is At.ConstantTarget -> atTarget.descriptor - } - - check(exprDescriptor != null && exprDescriptor.isType) - check(exprDescriptor != Descriptor.Primitive.VOID) { - "ModifyExpressionValue mixin cannot target a void method" - } - - val parameters = listOf(Parameter(exprDescriptor)) + modifyExpressionValue.locals - ?.map(Utils::getParameterFromLocal) - .orEmpty() - - return InjectionSignature( - mappedMethod, - parameters, - exprDescriptor, - method.isStatic, - ) - } - - override fun attachAnnotation(node: MethodNode, signature: InjectionSignature) { - node.visitAnnotation(SPModifyExpressionValue::class.descriptorString(), true).apply { - visit("method", listOf(signature.targetMethod.toFullDescriptor())) - visit("at", Utils.createAtAnnotation(modifyExpressionValue.at)) - if (modifyExpressionValue.slice != null) - visit("slice", modifyExpressionValue.slice.map(Utils::createSliceAnnotation)) - if (modifyExpressionValue.remap != null) - visit("remap", modifyExpressionValue.remap) - if (modifyExpressionValue.require != null) - visit("require", modifyExpressionValue.require) - if (modifyExpressionValue.expect != null) - visit("expect", modifyExpressionValue.expect) - if (modifyExpressionValue.allow != null) - visit("allow", modifyExpressionValue.allow) - visitEnd() - } - } - - context(MethodAssembly) - override fun generateNotAttachedBehavior() { - generateParameterLoad(0) - } -} diff --git a/src/main/kotlin/com/chattriggers/ctjs/internal/launch/generation/ModifyReceiverGenerator.kt b/src/main/kotlin/com/chattriggers/ctjs/internal/launch/generation/ModifyReceiverGenerator.kt deleted file mode 100644 index 8432e65d..00000000 --- a/src/main/kotlin/com/chattriggers/ctjs/internal/launch/generation/ModifyReceiverGenerator.kt +++ /dev/null @@ -1,71 +0,0 @@ -package com.chattriggers.ctjs.internal.launch.generation - -import codes.som.koffee.MethodAssembly -import codes.som.koffee.insns.jvm.getfield -import codes.som.koffee.insns.jvm.invokevirtual -import codes.som.koffee.insns.jvm.putfield -import com.chattriggers.ctjs.internal.launch.At -import com.chattriggers.ctjs.internal.launch.ModifyReceiver -import com.chattriggers.ctjs.internal.utils.descriptorString -import org.objectweb.asm.tree.MethodNode -import com.llamalad7.mixinextras.injector.ModifyReceiver as SPModifyReceiver - -internal class ModifyReceiverGenerator( - ctx: GenerationContext, - id: Int, - private val modifyReceiver: ModifyReceiver, -) : InjectorGenerator(ctx, id) { - override val type = "modifyReceiver" - - override fun getInjectionSignature(): InjectionSignature { - val (mappedMethod, method) = ctx.findMethod(modifyReceiver.method) - - val (owner, extraParams) = when (val atTarget = modifyReceiver.at.atTarget) { - is At.InvokeTarget -> atTarget.descriptor.owner to atTarget.descriptor.parameters - is At.FieldTarget -> { - check(atTarget.isStatic != null && atTarget.isGet != null) { - "ModifyReceiver targeting FIELD expects an opcode value" - } - check(!atTarget.isStatic) { "ModifyReceiver targeting FIELD expects a non-static field access" } - if (atTarget.isGet) { - atTarget.descriptor.owner to emptyList() - } else atTarget.descriptor.owner to listOf(atTarget.descriptor.type!!) - } - else -> error("Unsupported At.value for ModifyReceiver: ${atTarget.targetName}") - } - - val params = listOf(Parameter(owner!!)) + - extraParams!!.map(::Parameter) + - modifyReceiver.locals?.map(Utils::getParameterFromLocal).orEmpty() - - return InjectionSignature( - mappedMethod, - params, - owner, - method.isStatic, - ) - } - - override fun attachAnnotation(node: MethodNode, signature: InjectionSignature) { - node.visitAnnotation(SPModifyReceiver::class.descriptorString(), true).apply { - visit("method", listOf(signature.targetMethod.toFullDescriptor())) - visit("at", Utils.createAtAnnotation(modifyReceiver.at)) - if (modifyReceiver.slice != null) - visit("slice", listOf(modifyReceiver.slice.map(Utils::createSliceAnnotation))) - if (modifyReceiver.remap != null) - visit("remap", modifyReceiver.remap) - if (modifyReceiver.require != null) - visit("require", modifyReceiver.require) - if (modifyReceiver.expect != null) - visit("expect", modifyReceiver.expect) - if (modifyReceiver.allow != null) - visit("allow", modifyReceiver.allow) - visitEnd() - } - } - - context(MethodAssembly) - override fun generateNotAttachedBehavior() { - generateParameterLoad(0) - } -} diff --git a/src/main/kotlin/com/chattriggers/ctjs/internal/launch/generation/ModifyReturnValueInjector.kt b/src/main/kotlin/com/chattriggers/ctjs/internal/launch/generation/ModifyReturnValueInjector.kt deleted file mode 100644 index f80f4251..00000000 --- a/src/main/kotlin/com/chattriggers/ctjs/internal/launch/generation/ModifyReturnValueInjector.kt +++ /dev/null @@ -1,59 +0,0 @@ -package com.chattriggers.ctjs.internal.launch.generation - -import codes.som.koffee.MethodAssembly -import com.chattriggers.ctjs.internal.launch.Descriptor -import com.chattriggers.ctjs.internal.launch.ModifyReturnValue -import com.chattriggers.ctjs.internal.utils.descriptorString -import org.objectweb.asm.tree.MethodNode -import org.spongepowered.asm.mixin.injection.Desc -import com.llamalad7.mixinextras.injector.ModifyReturnValue as SPModifyReturnValue - -internal class ModifyReturnValueInjector( - ctx: GenerationContext, - id: Int, - private val modifyReturnValue: ModifyReturnValue -) : InjectorGenerator(ctx, id) { - override val type = "modifyReturnValue" - - override fun getInjectionSignature(): InjectionSignature { - val (mappedMethod, method) = ctx.findMethod(modifyReturnValue.method) - val returnType = Descriptor.Parser(mappedMethod.returnType.value).parseType(full = true) - check(returnType != Descriptor.Primitive.VOID) { - "ModifyReturnValue mixin cannot target a void method" - } - - val parameters = listOf(Parameter(returnType)) + modifyReturnValue.locals - ?.map(Utils::getParameterFromLocal) - .orEmpty() - - return InjectionSignature( - mappedMethod, - parameters, - returnType, - method.isStatic, - ) - } - - override fun attachAnnotation(node: MethodNode, signature: InjectionSignature) { - node.visitAnnotation(SPModifyReturnValue::class.descriptorString(), true).apply { - visit("method", listOf(signature.targetMethod.toFullDescriptor())) - visit("at", Utils.createAtAnnotation(modifyReturnValue.at)) - if (modifyReturnValue.slice != null) - visit("slice", listOf(modifyReturnValue.slice.map(Utils::createSliceAnnotation))) - if (modifyReturnValue.remap != null) - visit("remap", modifyReturnValue.remap) - if (modifyReturnValue.require != null) - visit("require", modifyReturnValue.require) - if (modifyReturnValue.expect != null) - visit("expect", modifyReturnValue.expect) - if (modifyReturnValue.allow != null) - visit("allow", modifyReturnValue.allow) - visitEnd() - } - } - - context(MethodAssembly) - override fun generateNotAttachedBehavior() { - generateParameterLoad(0) - } -} diff --git a/src/main/kotlin/com/chattriggers/ctjs/internal/launch/generation/ModifyVariableGenerator.kt b/src/main/kotlin/com/chattriggers/ctjs/internal/launch/generation/ModifyVariableGenerator.kt deleted file mode 100644 index b99755d1..00000000 --- a/src/main/kotlin/com/chattriggers/ctjs/internal/launch/generation/ModifyVariableGenerator.kt +++ /dev/null @@ -1,74 +0,0 @@ -package com.chattriggers.ctjs.internal.launch.generation - -import codes.som.koffee.MethodAssembly -import com.chattriggers.ctjs.internal.launch.Local -import com.chattriggers.ctjs.internal.launch.ModifyVariable -import com.chattriggers.ctjs.internal.utils.descriptorString -import org.objectweb.asm.tree.MethodNode -import org.spongepowered.asm.mixin.injection.ModifyVariable as SPModifyVariable - -internal class ModifyVariableGenerator( - ctx: GenerationContext, - id: Int, - private var modifyVariable: ModifyVariable, -) : InjectorGenerator(ctx, id) { - override val type = "modifyVariable" - - override fun getInjectionSignature(): InjectionSignature { - val (mappedMethod, method) = ctx.findMethod(modifyVariable.method) - - // Construct a temporary local so we can call Utils.getParameterFromLocal - val tempLocal = Local( - modifyVariable.print, - modifyVariable.index, - modifyVariable.ordinal, - modifyVariable.type, - mutable = false, - ) - - val parameter = Utils.getParameterFromLocal(tempLocal, name = "ModifyVariable") - - // Update our ModifyVariable annotation since we may have changed the index - modifyVariable = modifyVariable.copy( - index = parameter.local?.index ?: modifyVariable.index, - ) - - return InjectionSignature( - mappedMethod, - listOf(parameter.copy(local = null)), - parameter.descriptor, - method.isStatic, - ) - } - - override fun attachAnnotation(node: MethodNode, signature: InjectionSignature) { - node.visitAnnotation(SPModifyVariable::class.descriptorString(), true).apply { - visit("method", listOf(signature.targetMethod.toFullDescriptor())) - visit("at", Utils.createAtAnnotation(modifyVariable.at)) - if (modifyVariable.slice != null) - visit("slice", Utils.createSliceAnnotation(modifyVariable.slice!!)) - if (modifyVariable.print != null) - visit("print", modifyVariable.print) - if (modifyVariable.ordinal != null) - visit("ordinal", modifyVariable.ordinal) - if (modifyVariable.index != null) - visit("index", modifyVariable.index) - if (modifyVariable.remap != null) - visit("remap", modifyVariable.remap) - if (modifyVariable.require != null) - visit("require", modifyVariable.require) - if (modifyVariable.expect != null) - visit("expect", modifyVariable.expect) - if (modifyVariable.allow != null) - visit("allow", modifyVariable.allow) - if (modifyVariable.constraints != null) - visit("constraints", modifyVariable.constraints) - visitEnd() - } - } - - context(MethodAssembly) - override fun generateNotAttachedBehavior() { - generateParameterLoad(0) - } -} diff --git a/src/main/kotlin/com/chattriggers/ctjs/internal/launch/generation/RedirectGenerator.kt b/src/main/kotlin/com/chattriggers/ctjs/internal/launch/generation/RedirectGenerator.kt deleted file mode 100644 index a7ca6b78..00000000 --- a/src/main/kotlin/com/chattriggers/ctjs/internal/launch/generation/RedirectGenerator.kt +++ /dev/null @@ -1,150 +0,0 @@ -package com.chattriggers.ctjs.internal.launch.generation - -import codes.som.koffee.MethodAssembly -import codes.som.koffee.insns.jvm.* -import codes.som.koffee.insns.sugar.construct -import com.chattriggers.ctjs.api.Mappings -import com.chattriggers.ctjs.internal.launch.At -import com.chattriggers.ctjs.internal.launch.Descriptor -import com.chattriggers.ctjs.internal.launch.Redirect -import com.chattriggers.ctjs.internal.utils.descriptorString -import org.objectweb.asm.tree.MethodNode -import org.spongepowered.asm.mixin.injection.Redirect as SPRedirect - -internal class RedirectGenerator( - ctx: GenerationContext, - id: Int, - private val redirect: Redirect, -) : InjectorGenerator(ctx, id) { - override val type = "redirect" - - override fun getInjectionSignature(): InjectionSignature { - val (mappedMethod, method) = ctx.findMethod(redirect.method) - - val parameters = mutableListOf() - val returnType: Descriptor - - when (val atTarget = redirect.at.atTarget) { - is At.InvokeTarget -> { - val descriptor = atTarget.descriptor - - val targetClass = Mappings.getMappedClass(descriptor.owner!!.originalDescriptor()) - ?: error("Unknown class ${descriptor.owner}") - val targetMethod = Utils.findMethod(targetClass, descriptor).second - if (!targetMethod.isStatic) - parameters.add(Parameter(descriptor.owner)) - descriptor.parameters!!.forEach { parameters.add(Parameter(it)) } - returnType = descriptor.returnType!! - } - is At.FieldTarget -> { - require(atTarget.isStatic != null && atTarget.isGet != null) { - "Redirect targeting FIELD expects an opcode value" - } - returnType = if (atTarget.isGet) { - atTarget.descriptor.type!! - } else Descriptor.Primitive.VOID - - if (!atTarget.isStatic) - parameters.add(Parameter(atTarget.descriptor.owner!!)) - - if (!atTarget.isGet) - parameters.add(Parameter(atTarget.descriptor.type!!)) - } - is At.NewTarget -> { - atTarget.descriptor.parameters?.forEach { - parameters.add(Parameter(it)) - } - returnType = atTarget.descriptor.type - } - else -> error("Invalid target type ${atTarget.targetName} for Redirect inject") - } - - redirect.locals?.forEach { - parameters.add(Utils.getParameterFromLocal(it)) - } - - return InjectionSignature( - mappedMethod, - parameters, - returnType, - method.isStatic, - ) - } - - override fun attachAnnotation(node: MethodNode, signature: InjectionSignature) { - node.visitAnnotation(SPRedirect::class.descriptorString(), true).apply { - visit("method", signature.targetMethod.toFullDescriptor()) - if (redirect.slice != null) - visit("slice", Utils.createSliceAnnotation(redirect.slice)) - visit("at", Utils.createAtAnnotation(redirect.at)) - if (redirect.remap != null) - visit("remap", redirect.remap) - if (redirect.require != null) - visit("require", redirect.require) - if (redirect.expect != null) - visit("expect", redirect.expect) - if (redirect.allow != null) - visit("allow", redirect.allow) - if (redirect.constraints != null) - visit("constraints", redirect.constraints) - visitEnd() - } - } - - context(MethodAssembly) - override fun generateNotAttachedBehavior() { - val parameters = signature.parameters.filter { it.local == null } - - when (val target = redirect.at.atTarget) { - is At.FieldTarget -> { - parameters.indices.forEach { generateParameterLoad(it) } - - val owner = target.descriptor.owner!!.toType() - val name = target.descriptor.name - val type = target.descriptor.type!!.toType() - - if (target.isGet!!) { - if (target.isStatic!!) { - getstatic(owner, name, type) - } else { - getfield(owner, name, type) - } - } else { - if (target.isStatic!!) { - putstatic(owner, name, type) - } else { - putfield(owner, name, type) - } - - // Must leave something on the stack to pop - aconst_null - } - } - is At.InvokeTarget -> { - parameters.indices.forEach { generateParameterLoad(it) } - - val owner = target.descriptor.owner!!.toType() - val name = target.descriptor.name - val returnType = target.descriptor.returnType!!.toType() - val parameterTypes = parameters.drop(1).map { - it.descriptor.toType() - }.toTypedArray() - - if (signature.isStatic) { - invokestatic(owner, name, returnType, *parameterTypes) - } else { - invokevirtual(owner, name, returnType, *parameterTypes) - } - } - is At.NewTarget -> { - construct( - target.descriptor.type.toType(), - *parameters.map { it.descriptor.toType() }.toTypedArray(), - ) { - parameters.indices.forEach { generateParameterLoad(it) } - } - } - else -> error("unreachable") - } - } -} diff --git a/src/main/kotlin/com/chattriggers/ctjs/internal/launch/generation/Utils.kt b/src/main/kotlin/com/chattriggers/ctjs/internal/launch/generation/Utils.kt deleted file mode 100644 index d706959c..00000000 --- a/src/main/kotlin/com/chattriggers/ctjs/internal/launch/generation/Utils.kt +++ /dev/null @@ -1,204 +0,0 @@ -package com.chattriggers.ctjs.internal.launch.generation - -import com.chattriggers.ctjs.api.Mappings -import com.chattriggers.ctjs.internal.launch.* -import com.chattriggers.ctjs.internal.utils.descriptor -import com.chattriggers.ctjs.internal.utils.descriptorString -import net.fabricmc.loader.impl.FabricLoaderImpl -import net.fabricmc.loader.impl.lib.accesswidener.AccessWidenerReader -import org.objectweb.asm.Opcodes -import org.objectweb.asm.Type -import org.objectweb.asm.tree.AnnotationNode -import org.spongepowered.asm.mixin.transformer.ClassInfo -import org.spongepowered.asm.mixin.injection.At as SPAt -import org.spongepowered.asm.mixin.injection.Constant as SPConstant -import org.spongepowered.asm.mixin.injection.Slice as SPSlice - -internal object Utils { - fun createAtAnnotation(at: At): AnnotationNode { - return AnnotationNode(SPAt::class.descriptorString()).apply { - if (at.id != null) - visit("id", at.id) - visit("value", at.value) - if (at.slice != null) - visit("slice", at.slice) - if (at.shift != null) - visit("shift", arrayOf(SPAt.Shift::class.java.descriptorString(), at.shift.name)) - if (at.by != null) - visit("by", at.by) - if (at.args != null) - visit("args", at.args) - if (at.target != null) - visit("target", at.atTarget.descriptor.mappedDescriptor()) - if (at.ordinal != null) - visit("ordinal", at.ordinal) - if (at.opcode != null) - visit("opcode", at.opcode) - if (at.remap != null) - visit("remap", at.remap) - - visitEnd() - } - } - - fun createSliceAnnotation(slice: Slice): AnnotationNode { - return AnnotationNode(SPSlice::class.descriptorString()).apply { - if (slice.id != null) - visit("id", slice.id) - if (slice.from != null) - visit("from", createAtAnnotation(slice.from)) - if (slice.to != null) - visit("to", createAtAnnotation(slice.to)) - visitEnd() - } - } - - fun createConstantAnnotation(constant: Constant): AnnotationNode { - return AnnotationNode(SPConstant::class.descriptorString()).apply { - if (constant.nullValue != null) - visit("nullValue", constant.nullValue) - if (constant.intValue != null) - visit("intValue", constant.intValue) - if (constant.floatValue != null) - visit("floatValue", constant.floatValue) - if (constant.longValue != null) - visit("longValue", constant.longValue) - if (constant.doubleValue != null) - visit("doubleValue", constant.doubleValue) - if (constant.stringValue != null) - visit("stringValue", constant.stringValue) - if (constant.classValue != null) { - val name = Mappings.getMappedClassName(constant.classValue) - ?: error("Unknown class \"${constant.classValue}\"") - visit("classValue", Type.getObjectType(name)) - } - if (constant.ordinal != null) - visit("ordinal", constant.ordinal) - if (constant.slice != null) - visit("slice", constant.slice) - if (constant.expandZeroConditions != null) - visit("expandZeroConditions", constant.expandZeroConditions) - if (constant.log != null) - visit("log", constant.log) - } - } - - fun widenField(mappedClass: Mappings.MappedClass, fieldName: String, isMutable: Boolean) { - val field = mappedClass.fields[fieldName] - ?: error("Unable to find field $fieldName in class ${mappedClass.name.original}") - - FabricLoaderImpl.INSTANCE.accessWidener.visitField( - mappedClass.name.value, - field.name.value, - field.type.value, - AccessWidenerReader.AccessType.ACCESSIBLE, - false, - ) - - if (isMutable) { - FabricLoaderImpl.INSTANCE.accessWidener.visitField( - mappedClass.name.value, - field.name.value, - field.type.value, - AccessWidenerReader.AccessType.MUTABLE, - false, - ) - } - } - - fun widenMethod( - mappedClass: Mappings.MappedClass, - methodName: String, - isMutable: Boolean, - ) { - val descriptor = Descriptor.Parser(methodName).parseMethod(full = false) - val mappedMethod = findMethod(mappedClass, descriptor).first - - FabricLoaderImpl.INSTANCE.accessWidener.visitMethod( - mappedClass.name.value, - mappedMethod.name.value, - mappedMethod.toDescriptor(), - AccessWidenerReader.AccessType.ACCESSIBLE, - false, - ) - - if (isMutable) { - FabricLoaderImpl.INSTANCE.accessWidener.visitMethod( - mappedClass.name.value, - mappedMethod.name.value, - mappedMethod.toDescriptor(), - AccessWidenerReader.AccessType.MUTABLE, - false, - ) - } - } - - fun findMethod( - mappedClass: Mappings.MappedClass, - descriptor: Descriptor.Method, - ): Pair { - val parameters = descriptor.parameters - - val classInfo = ClassInfo.forName(mappedClass.name.value) - val mappedMethods = mappedClass.findMethods(descriptor.name, classInfo) - ?: error("Cannot find method ${descriptor.name} in class ${mappedClass.name.original}") - - var value: Pair? = null - - for (method in mappedMethods) { - if (parameters != null) { - if (method.parameters.size != parameters.size) - continue - - if (method.parameters.zip(parameters).any { it.first.type.original != it.second.originalDescriptor() }) - continue - } - - val result = classInfo.findMethodInHierarchy( - method.name.value, - method.toDescriptor(), - ClassInfo.SearchType.ALL_CLASSES, - ClassInfo.INCLUDE_ALL or ClassInfo.INCLUDE_INITIALISERS, - ) ?: continue - - if (value != null) - error( - "Multiple methods match name ${descriptor.name} in class ${mappedClass.name.original}, please " + - "provide a method descriptor" - ) - - value = method to result - } - - if (value != null) - return value - - error("Unable to match method $descriptor in class ${mappedClass.name.original}") - } - - fun getParameterFromLocal(local: Local, name: String = "Local"): InjectorGenerator.Parameter { - val descriptor = when { - local.print == true -> { - // The type doesn't matter, it won't actually be applied - Descriptor.Primitive.INT - } - local.type != null -> { - if (local.index != null) { - require(local.ordinal == null) { - "$name that specifies a type and index cannot specify an ordinal" - } - } else { - require(local.ordinal != null) { - "$name that specifies a type must also specify an index or ordinal" - } - } - Descriptor.Parser(local.type).parseType(full = true) - } - else -> error("$name must specify \"print\", or \"type\" and either \"ordinal\" or \"index\"") - } - - require(descriptor.isType) - - return InjectorGenerator.Parameter(descriptor, local) - } -} diff --git a/src/main/kotlin/com/chattriggers/ctjs/internal/launch/generation/WrapOperationGenerator.kt b/src/main/kotlin/com/chattriggers/ctjs/internal/launch/generation/WrapOperationGenerator.kt deleted file mode 100644 index 3026f771..00000000 --- a/src/main/kotlin/com/chattriggers/ctjs/internal/launch/generation/WrapOperationGenerator.kt +++ /dev/null @@ -1,137 +0,0 @@ -package com.chattriggers.ctjs.internal.launch.generation - -import codes.som.koffee.MethodAssembly -import codes.som.koffee.insns.jvm.* -import com.chattriggers.ctjs.api.Mappings -import com.chattriggers.ctjs.internal.launch.At -import com.chattriggers.ctjs.internal.launch.Descriptor -import com.chattriggers.ctjs.internal.launch.WrapOperation -import com.chattriggers.ctjs.internal.utils.descriptor -import com.chattriggers.ctjs.internal.utils.descriptorString -import com.llamalad7.mixinextras.injector.wrapoperation.Operation -import org.objectweb.asm.Type -import org.objectweb.asm.tree.MethodNode -import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation as SPWrapOperation - -internal class WrapOperationGenerator( - ctx: GenerationContext, - id: Int, - private val wrapOperation: WrapOperation, -) : InjectorGenerator(ctx, id) { - override val type = "wrapOperation" - - override fun getInjectionSignature(): InjectionSignature { - val (mappedMethod, method) = ctx.findMethod(wrapOperation.method) - - val parameters = mutableListOf() - val returnType: Descriptor - - if (wrapOperation.at == null) { - require(wrapOperation.constant != null) { - "WrapOperation must specify either 'at' or 'constant'" - } - require(wrapOperation.constant.classValue != null) { - "WrapOperation targeting INSTANCEOF must specify constant.classValue" - } - - parameters.add(Parameter(Any::class.descriptor())) - parameters.add(Parameter(Operation::class.descriptor())) - returnType = Descriptor.Primitive.BOOLEAN - } else { - when (val atTarget = wrapOperation.at.atTarget) { - is At.InvokeTarget -> { - val descriptor = atTarget.descriptor - - val targetClass = Mappings.getMappedClass(descriptor.owner!!.originalDescriptor()) - ?: error("Unknown class ${descriptor.owner}") - val targetMethodIsStatic = Utils.findMethod(targetClass, descriptor).second.isStatic - - if (!targetMethodIsStatic) - parameters.add(Parameter(descriptor.owner)) - - descriptor.parameters!!.forEach { - parameters.add(Parameter(it)) - } - parameters.add(Parameter(Operation::class.descriptor())) - returnType = descriptor.returnType!! - } - is At.FieldTarget -> { - require(atTarget.isStatic != null && atTarget.isGet != null) { - "WrapOperation targeting FIELD expects an opcode value" - } - - val descriptor = atTarget.descriptor - if (!atTarget.isStatic) - parameters.add(Parameter(descriptor.owner!!)) - - if (!atTarget.isGet) - parameters.add(Parameter(descriptor.type!!)) - - parameters.add(Parameter(Operation::class.descriptor())) - - returnType = if (atTarget.isGet) { - descriptor.type!! - } else Descriptor.Primitive.VOID - } - is At.NewTarget -> { - atTarget.descriptor.parameters!!.forEach { - parameters.add(Parameter(it)) - } - parameters.add(Parameter(Operation::class.descriptor())) - returnType = atTarget.descriptor.type - } - else -> error("Unexpected At.target for WrapOperation: ${atTarget.targetName}") - } - } - - return InjectionSignature( - mappedMethod, - parameters, - returnType, - method.isStatic, - ) - } - - override fun attachAnnotation(node: MethodNode, signature: InjectionSignature) { - node.visitAnnotation(SPWrapOperation::class.descriptorString(), true).apply { - visit("method", signature.targetMethod.toFullDescriptor()) - if (wrapOperation.at != null) - visit("at", Utils.createAtAnnotation(wrapOperation.at)) - if (wrapOperation.constant != null) - visit("constant", Utils.createConstantAnnotation(wrapOperation.constant)) - if (wrapOperation.slice != null) - visit("slice", wrapOperation.slice.map(Utils::createSliceAnnotation)) - if (wrapOperation.remap != null) - visit("remap", wrapOperation.remap) - if (wrapOperation.require != null) - visit("require", wrapOperation.require) - if (wrapOperation.expect != null) - visit("expect", wrapOperation.expect) - if (wrapOperation.allow != null) - visit("allow", wrapOperation.allow) - visitEnd() - } - } - - context(MethodAssembly) - override fun generateNotAttachedBehavior() { - val operationType = Type.getType(Operation::class.java) - val operationParameterIndex = signature.parameters.indexOfFirst { - it.descriptor.toType() == operationType - } - check(operationParameterIndex != -1) - - generateParameterLoad(operationParameterIndex) - ldc(operationParameterIndex) - anewarray() - - (0 until operationParameterIndex).map { - dup - ldc(it) - generateParameterLoad(it) - aastore - } - - invokeinterface(Operation::class, "call", Any::class, Array::class) - } -} diff --git a/src/main/kotlin/com/chattriggers/ctjs/internal/launch/generation/WrapWithConditionGenerator.kt b/src/main/kotlin/com/chattriggers/ctjs/internal/launch/generation/WrapWithConditionGenerator.kt deleted file mode 100644 index 5da7902d..00000000 --- a/src/main/kotlin/com/chattriggers/ctjs/internal/launch/generation/WrapWithConditionGenerator.kt +++ /dev/null @@ -1,87 +0,0 @@ -package com.chattriggers.ctjs.internal.launch.generation - -import codes.som.koffee.MethodAssembly -import codes.som.koffee.insns.jvm.ldc -import com.chattriggers.ctjs.api.Mappings -import com.chattriggers.ctjs.internal.launch.At -import com.chattriggers.ctjs.internal.launch.Descriptor -import com.chattriggers.ctjs.internal.launch.WrapWithCondition -import com.chattriggers.ctjs.internal.utils.descriptorString -import org.objectweb.asm.tree.MethodNode -import com.llamalad7.mixinextras.injector.v2.WrapWithCondition as SPWrapWithCondition - -internal class WrapWithConditionGenerator( - ctx: GenerationContext, - id: Int, - private val wrapWithCondition: WrapWithCondition, -) : InjectorGenerator(ctx, id) { - override val type = "wrapWithCondition" - - override fun getInjectionSignature(): InjectionSignature { - val (mappedMethod, method) = ctx.findMethod(wrapWithCondition.method) - - val parameters = mutableListOf() - - when (val atTarget = wrapWithCondition.at.atTarget) { - is At.InvokeTarget -> { - val descriptor = atTarget.descriptor - - val targetClass = Mappings.getMappedClass(descriptor.owner!!.originalDescriptor()) - ?: error("Unknown class ${descriptor.owner}") - val targetMethodIsStatic = Utils.findMethod(targetClass, descriptor).second.isStatic - - if (!targetMethodIsStatic) - parameters.add(Parameter(descriptor.owner)) - - descriptor.parameters!!.forEach { - parameters.add(Parameter(it)) - } - } - is At.FieldTarget -> { - require(atTarget.isStatic != null && atTarget.isGet != null) { - "WrapWithCondition targeting FIELD expects an opcode value" - } - require(!atTarget.isGet) { - "WrapWithCondition targeting FIELD expects opcode to be PUTFIELD or PUTSTATIC" - } - - val descriptor = atTarget.descriptor - if (!atTarget.isStatic) - parameters.add(Parameter(descriptor.owner!!)) - - parameters.add(Parameter(descriptor.type!!)) - } - else -> error("Unexpected At.target for WrapWithCondition: ${atTarget.targetName}") - } - - return InjectionSignature( - mappedMethod, - parameters, - Descriptor.Primitive.BOOLEAN, - method.isStatic, - ) - } - - override fun attachAnnotation(node: MethodNode, signature: InjectionSignature) { - node.visitAnnotation(SPWrapWithCondition::class.descriptorString(), true).apply { - visit("method", signature.targetMethod.toFullDescriptor()) - visit("at", Utils.createAtAnnotation(wrapWithCondition.at)) - if (wrapWithCondition.slice != null) - visit("slice", wrapWithCondition.slice.map(Utils::createSliceAnnotation)) - if (wrapWithCondition.remap != null) - visit("remap", wrapWithCondition.remap) - if (wrapWithCondition.require != null) - visit("require", wrapWithCondition.require) - if (wrapWithCondition.expect != null) - visit("expect", wrapWithCondition.expect) - if (wrapWithCondition.allow != null) - visit("allow", wrapWithCondition.allow) - visitEnd() - } - } - - context(MethodAssembly) - override fun generateNotAttachedBehavior() { - ldc(1) - } -} diff --git a/src/main/kotlin/com/chattriggers/ctjs/internal/listeners/ClientListener.kt b/src/main/kotlin/com/chattriggers/ctjs/internal/listeners/ClientListener.kt index c54fc4d3..1e350f50 100644 --- a/src/main/kotlin/com/chattriggers/ctjs/internal/listeners/ClientListener.kt +++ b/src/main/kotlin/com/chattriggers/ctjs/internal/listeners/ClientListener.kt @@ -1,220 +1,84 @@ package com.chattriggers.ctjs.internal.listeners -import com.chattriggers.ctjs.api.entity.BlockEntity -import com.chattriggers.ctjs.api.entity.Entity -import com.chattriggers.ctjs.api.entity.PlayerInteraction -import com.chattriggers.ctjs.api.inventory.Item -import com.chattriggers.ctjs.api.message.TextComponent -import com.chattriggers.ctjs.api.render.Renderer import com.chattriggers.ctjs.api.triggers.CancellableEvent -import com.chattriggers.ctjs.api.triggers.ChatTrigger +import com.chattriggers.ctjs.api.triggers.RenderContextTriggerType import com.chattriggers.ctjs.api.triggers.TriggerType -import com.chattriggers.ctjs.api.world.Scoreboard -import com.chattriggers.ctjs.api.world.TabList -import com.chattriggers.ctjs.api.world.World -import com.chattriggers.ctjs.api.world.block.BlockFace -import com.chattriggers.ctjs.api.world.block.BlockPos -import com.chattriggers.ctjs.internal.engine.CTEvents -import com.chattriggers.ctjs.internal.engine.JSContextFactory -import com.chattriggers.ctjs.internal.engine.JSLoader import com.chattriggers.ctjs.internal.utils.Initializer -import gg.essential.universal.UMinecraft import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents import net.fabricmc.fabric.api.client.message.v1.ClientReceiveMessageEvents import net.fabricmc.fabric.api.client.message.v1.ClientSendMessageEvents -import net.fabricmc.fabric.api.client.screen.v1.ScreenEvents -import net.fabricmc.fabric.api.client.screen.v1.ScreenKeyboardEvents -import net.fabricmc.fabric.api.event.player.* -import net.minecraft.text.Text -import net.minecraft.util.ActionResult -import net.minecraft.util.TypedActionResult -import org.lwjgl.glfw.GLFW -import org.mozilla.javascript.Context +import net.fabricmc.fabric.api.client.rendering.v1.hud.HudElementRegistry +import net.fabricmc.fabric.api.client.rendering.v1.level.LevelRenderEvents +import net.minecraft.client.Minecraft +import net.minecraft.resources.Identifier object ClientListener : Initializer { - private var ticksPassed: Int = 0 - val chatHistory = mutableListOf() - val actionBarHistory = mutableListOf() private val tasks = mutableListOf() - private lateinit var packetContext: Context class Task(var delay: Int, val callback: () -> Unit) override fun init() { - packetContext = JSContextFactory.enterContext() - Context.exit() - - ClientReceiveMessageEvents.ALLOW_CHAT.register { message, _, _, _, _ -> - handleChatMessage(message, actionBar = false) - } - - ClientReceiveMessageEvents.ALLOW_GAME.register { message, overlay -> - handleChatMessage(message, actionBar = overlay) - } - ClientTickEvents.START_CLIENT_TICK.register { synchronized(tasks) { tasks.removeAll { if (it.delay-- <= 0) { - UMinecraft.getMinecraft().submit(it.callback) + Minecraft.getInstance().submit(it.callback) true } else false } } - if (World.isLoaded() && World.toMC()?.tickManager?.shouldTick() == true) { - TriggerType.TICK.triggerAll(ticksPassed) - ticksPassed++ - - Scoreboard.resetCache() - TabList.resetCache() + if (Minecraft.getInstance().level?.tickRateManager()?.runsNormally() == true) { + TriggerType.TICK.triggerAll() } } - ClientSendMessageEvents.ALLOW_CHAT.register { message -> - val event = CancellableEvent() - TriggerType.MESSAGE_SENT.triggerAll(message, event) - - !event.isCancelled() + HudElementRegistry.addLast( + Identifier.fromNamespaceAndPath( + "chattriggers", + "render_overlay" + ) + ) { ctx, tickCounter -> + TriggerType.RENDER_OVERLAY.triggerAll(ctx, tickCounter) } - ClientSendMessageEvents.ALLOW_COMMAND.register { message -> + ClientReceiveMessageEvents.ALLOW_CHAT.register { message, _, _, _, _ -> val event = CancellableEvent() - TriggerType.MESSAGE_SENT.triggerAll("/$message", event) + TriggerType.CHAT.triggerAll(message, event) !event.isCancelled() } - ScreenEvents.BEFORE_INIT.register { _, screen, _, _ -> - // TODO: Why does Renderer.drawString not work in here? - ScreenEvents.beforeRender(screen).register { _, stack, mouseX, mouseY, partialTicks -> - Renderer.withMatrix(stack.matrices, partialTicks) { - TriggerType.GUI_RENDER.triggerAll(mouseX, mouseY, screen) - } - } - - // TODO: Why does Renderer.drawString not work in here? - ScreenEvents.afterRender(screen).register { _, stack, mouseX, mouseY, partialTicks -> - Renderer.withMatrix(stack.matrices, partialTicks) { - TriggerType.POST_GUI_RENDER.triggerAll(mouseX, mouseY, screen, partialTicks) - } - } - - ScreenKeyboardEvents.allowKeyPress(screen).register { _, key, scancode, _ -> - val event = CancellableEvent() - TriggerType.GUI_KEY.triggerAll(GLFW.glfwGetKeyName(key, scancode), key, screen, event) - !event.isCancelled() - } - } - - ScreenEvents.AFTER_INIT.register { _, screen, _, _ -> - ScreenEvents.remove(screen).register { - TriggerType.GUI_CLOSED.triggerAll(screen) - } - } - - CTEvents.PACKET_RECEIVED.register { packet, ctx -> - JSLoader.wrapInContext(packetContext) { - TriggerType.PACKET_RECEIVED.triggerAll(packet, ctx) - } - } - - CTEvents.RENDER_TICK.register { - TriggerType.STEP.triggerAll() - } - - CTEvents.RENDER_OVERLAY.register { stack, partialTicks -> - Renderer.withMatrix(stack, partialTicks) { - TriggerType.RENDER_OVERLAY.triggerAll() - } - } - - CTEvents.RENDER_ENTITY.register { stack, entity, partialTicks, ci -> - Renderer.withMatrix(stack, partialTicks) { - TriggerType.RENDER_ENTITY.triggerAll(Entity.fromMC(entity), partialTicks, ci) - } - } - - CTEvents.RENDER_BLOCK_ENTITY.register { stack, blockEntity, partialTicks, ci -> - Renderer.withMatrix(stack, partialTicks) { - TriggerType.RENDER_BLOCK_ENTITY.triggerAll(BlockEntity(blockEntity), partialTicks, ci) - } - } - - AttackBlockCallback.EVENT.register { player, _, _, pos, direction -> - if (!player.world.isClient) return@register ActionResult.PASS - val event = CancellableEvent() - - TriggerType.PLAYER_INTERACT.triggerAll( - PlayerInteraction.AttackBlock, - World.getBlockAt(BlockPos(pos)).withFace(BlockFace.fromMC(direction)), - event, - ) - - if (event.isCancelled()) ActionResult.FAIL else ActionResult.PASS - } - - AttackEntityCallback.EVENT.register { player, _, _, entity, _ -> - if (!player.world.isClient) return@register ActionResult.PASS + ClientReceiveMessageEvents.ALLOW_GAME.register { message, overlay -> val event = CancellableEvent() + (if (overlay) TriggerType.ACTION_BAR else TriggerType.CHAT) + .triggerAll(message, event) - TriggerType.PLAYER_INTERACT.triggerAll( - PlayerInteraction.AttackEntity, - Entity.fromMC(entity), - event, - ) - - if (event.isCancelled()) ActionResult.FAIL else ActionResult.PASS + !event.isCancelled() } - CTEvents.BREAK_BLOCK.register { pos -> + ClientSendMessageEvents.ALLOW_CHAT.register { message -> val event = CancellableEvent() - TriggerType.PLAYER_INTERACT.triggerAll(PlayerInteraction.BreakBlock, World.getBlockAt(BlockPos(pos)), event) + TriggerType.MESSAGE_SENT.triggerAll(message, false, event) - check(!event.isCancelled()) { - "PlayerInteraction event of type BreakBlock is not cancellable" - } + !event.isCancelled() } - UseBlockCallback.EVENT.register { player, _, hand, hitResult -> - if (!player.world.isClient) return@register ActionResult.PASS + ClientSendMessageEvents.ALLOW_COMMAND.register { message -> val event = CancellableEvent() + TriggerType.MESSAGE_SENT.triggerAll(message, true, event) - TriggerType.PLAYER_INTERACT.triggerAll( - PlayerInteraction.UseBlock(hand), - World.getBlockAt(BlockPos(hitResult.blockPos)).withFace(BlockFace.fromMC(hitResult.side)), - event, - ) - - if (event.isCancelled()) ActionResult.FAIL else ActionResult.PASS + !event.isCancelled() } - UseEntityCallback.EVENT.register { player, _, hand, entity, _ -> - if (!player.world.isClient) return@register ActionResult.PASS - val event = CancellableEvent() - - TriggerType.PLAYER_INTERACT.triggerAll( - PlayerInteraction.UseEntity(hand), - Entity.fromMC(entity), - event, - ) - - if (event.isCancelled()) ActionResult.FAIL else ActionResult.PASS + LevelRenderEvents.END_EXTRACTION.register { ctx -> + TriggerType.RENDER_LEVEL_EXTRACTION.triggerAll(ctx) } - UseItemCallback.EVENT.register { player, _, hand -> - if (!player.world.isClient) return@register TypedActionResult.pass(null) - val event = CancellableEvent() - - val stack = player.getStackInHand(hand) - - TriggerType.PLAYER_INTERACT.triggerAll( - PlayerInteraction.UseItem(hand), - Item.fromMC(stack), - event, - ) - - if (event.isCancelled()) TypedActionResult.fail(null) else TypedActionResult.pass(null) + RenderContextTriggerType.entries.forEach { entry -> + entry.register { ctx -> + entry.triggerAll(ctx) + } } } @@ -223,26 +87,4 @@ object ClientListener : Initializer { tasks.add(Task(delay, callback)) } } - - private fun handleChatMessage(message: Text, actionBar: Boolean): Boolean { - val textComponent = TextComponent(message) - val event = ChatTrigger.Event(textComponent) - - return if (actionBar) { - actionBarHistory += textComponent - if (actionBarHistory.size > 1000) - actionBarHistory.removeAt(0) - - TriggerType.ACTION_BAR.triggerAll(event) - !event.isCancelled() - } else { - chatHistory += textComponent - if (chatHistory.size > 1000) - chatHistory.removeAt(0) - - TriggerType.CHAT.triggerAll(event) - - !event.isCancelled() - } - } } diff --git a/src/main/kotlin/com/chattriggers/ctjs/internal/listeners/MouseListener.kt b/src/main/kotlin/com/chattriggers/ctjs/internal/listeners/MouseListener.kt deleted file mode 100644 index 7a91fd98..00000000 --- a/src/main/kotlin/com/chattriggers/ctjs/internal/listeners/MouseListener.kt +++ /dev/null @@ -1,97 +0,0 @@ -package com.chattriggers.ctjs.internal.listeners - -import com.chattriggers.ctjs.api.client.Client -import com.chattriggers.ctjs.api.triggers.CancellableEvent -import com.chattriggers.ctjs.api.triggers.TriggerType -import com.chattriggers.ctjs.api.world.World -import com.chattriggers.ctjs.internal.engine.CTEvents -import com.chattriggers.ctjs.internal.utils.Initializer -import net.fabricmc.fabric.api.client.screen.v1.ScreenEvents -import net.fabricmc.fabric.api.client.screen.v1.ScreenMouseEvents -import org.lwjgl.glfw.GLFW - -internal object MouseListener : Initializer { - private val mouseState = mutableMapOf() - private val draggedState = mutableMapOf() - - private class State(val x: Double, val y: Double) - - override fun init() { - CTEvents.RENDER_TICK.register { - if (!World.isLoaded()) - return@register - - for (button in 0..4) { - if (button !in draggedState) - continue - - val x = Client.getMouseX() - val y = Client.getMouseY() - - if (x == draggedState[button]?.x && y == draggedState[button]?.y) - continue - - CTEvents.MOUSE_DRAGGED.invoker().process( - x - (draggedState[button]?.x ?: 0.0), - y - (draggedState[button]?.y ?: 0.0), - x, - y, - button, - ) - - // update dragged - draggedState[button] = State(x, y) - } - } - - CTEvents.MOUSE_CLICKED.register(TriggerType.CLICKED::triggerAll) - CTEvents.MOUSE_SCROLLED.register(TriggerType.SCROLLED::triggerAll) - CTEvents.MOUSE_DRAGGED.register(TriggerType.DRAGGED::triggerAll) - CTEvents.GUI_MOUSE_DRAG.register(TriggerType.GUI_MOUSE_DRAG::triggerAll) - - ScreenEvents.BEFORE_INIT.register { _, screen, _, _ -> - ScreenMouseEvents.allowMouseClick(screen).register { _, mouseX, mouseY, button -> - val event = CancellableEvent() - TriggerType.GUI_MOUSE_CLICK.triggerAll(mouseX, mouseY, button, true, screen, event) - - !event.isCanceled() - } - - ScreenMouseEvents.allowMouseRelease(screen).register { _, mouseX, mouseY, button -> - val event = CancellableEvent() - TriggerType.GUI_MOUSE_CLICK.triggerAll(mouseX, mouseY, button, false, screen, event) - - !event.isCanceled() - } - } - } - - @JvmStatic - fun onRawMouseInput(button: Int, action: Int) { - if (!World.isLoaded()) { - mouseState.clear() - draggedState.clear() - return - } - - if (button == -1 || action == mouseState[button]) - return - - val x = Client.getMouseX() - val y = Client.getMouseY() - - CTEvents.MOUSE_CLICKED.invoker().process(x, y, button, action == GLFW.GLFW_PRESS) - mouseState[button] = action - - if (action == GLFW.GLFW_PRESS) { - draggedState[button] = State(x, y) - } else { - draggedState.remove(button) - } - } - - @JvmStatic - fun onRawMouseScroll(dy: Double) { - CTEvents.MOUSE_SCROLLED.invoker().process(Client.getMouseX(), Client.getMouseY(), dy) - } -} diff --git a/src/main/kotlin/com/chattriggers/ctjs/internal/listeners/WorldListener.kt b/src/main/kotlin/com/chattriggers/ctjs/internal/listeners/WorldListener.kt deleted file mode 100644 index e0a8bbbc..00000000 --- a/src/main/kotlin/com/chattriggers/ctjs/internal/listeners/WorldListener.kt +++ /dev/null @@ -1,32 +0,0 @@ -package com.chattriggers.ctjs.internal.listeners - -import com.chattriggers.ctjs.api.render.Renderer -import com.chattriggers.ctjs.api.triggers.CancellableEvent -import com.chattriggers.ctjs.api.triggers.TriggerType -import com.chattriggers.ctjs.internal.utils.Initializer -import net.fabricmc.fabric.api.client.rendering.v1.WorldRenderEvents -import net.minecraft.util.math.BlockPos - -object WorldListener : Initializer { - override fun init() { - WorldRenderEvents.BLOCK_OUTLINE.register { _, ctx -> - val event = CancellableEvent() - TriggerType.BLOCK_HIGHLIGHT.triggerAll(BlockPos(ctx.blockPos()), event) - !event.isCancelled() - } - - WorldRenderEvents.START.register { ctx -> - val deltaTicks = ctx.tickCounter().getTickDelta(false) - Renderer.withMatrix(ctx.matrixStack(), deltaTicks) { - TriggerType.PRE_RENDER_WORLD.triggerAll(deltaTicks) - } - } - - WorldRenderEvents.LAST.register { ctx -> - val deltaTicks = ctx.tickCounter().getTickDelta(false) - Renderer.withMatrix(ctx.matrixStack(), deltaTicks) { - TriggerType.POST_RENDER_WORLD.triggerAll(deltaTicks) - } - } - } -} diff --git a/src/main/kotlin/com/chattriggers/ctjs/internal/utils/CategorySorting.kt b/src/main/kotlin/com/chattriggers/ctjs/internal/utils/CategorySorting.kt deleted file mode 100644 index 5e826e74..00000000 --- a/src/main/kotlin/com/chattriggers/ctjs/internal/utils/CategorySorting.kt +++ /dev/null @@ -1,18 +0,0 @@ -package com.chattriggers.ctjs.internal.utils - -import gg.essential.vigilance.data.Category -import gg.essential.vigilance.data.SortingBehavior - -internal object CategorySorting : SortingBehavior() { - override fun getCategoryComparator(): Comparator { - return Comparator { o1, o2 -> - val categories = listOf("General", "Console") - - if (o1.name !in categories || o2.name !in categories) { - throw IllegalArgumentException("All categories must be in the list of categories") - } - - categories.indexOf(o1.name) - categories.indexOf(o2.name) - } - } -} diff --git a/src/main/kotlin/com/chattriggers/ctjs/internal/utils/Initializer.kt b/src/main/kotlin/com/chattriggers/ctjs/internal/utils/Initializer.kt index 38ba65c1..f616657b 100644 --- a/src/main/kotlin/com/chattriggers/ctjs/internal/utils/Initializer.kt +++ b/src/main/kotlin/com/chattriggers/ctjs/internal/utils/Initializer.kt @@ -1,15 +1,9 @@ package com.chattriggers.ctjs.internal.utils -import com.chattriggers.ctjs.api.client.CPS -import com.chattriggers.ctjs.api.client.KeyBind -import com.chattriggers.ctjs.api.commands.DynamicCommands +import com.chattriggers.ctjs.api.CustomCommand import com.chattriggers.ctjs.internal.commands.CTCommand -import com.chattriggers.ctjs.internal.commands.StaticCommand import com.chattriggers.ctjs.internal.console.ConsoleHostProcess -import com.chattriggers.ctjs.internal.engine.module.ModuleUpdater import com.chattriggers.ctjs.internal.listeners.ClientListener -import com.chattriggers.ctjs.internal.listeners.MouseListener -import com.chattriggers.ctjs.internal.listeners.WorldListener internal interface Initializer { fun init() @@ -18,14 +12,8 @@ internal interface Initializer { internal val initializers = listOf( ClientListener, ConsoleHostProcess, - CPS, CTCommand, - DynamicCommands, - KeyBind, - ModuleUpdater, - MouseListener, - StaticCommand, - WorldListener, + CustomCommand ) } } diff --git a/src/main/kotlin/com/chattriggers/ctjs/internal/utils/extensions.kt b/src/main/kotlin/com/chattriggers/ctjs/internal/utils/extensions.kt index bb34355f..c1f30055 100644 --- a/src/main/kotlin/com/chattriggers/ctjs/internal/utils/extensions.kt +++ b/src/main/kotlin/com/chattriggers/ctjs/internal/utils/extensions.kt @@ -1,56 +1,15 @@ package com.chattriggers.ctjs.internal.utils -import com.chattriggers.ctjs.internal.launch.Descriptor -import com.fasterxml.jackson.core.Version -import net.minecraft.util.Identifier -import net.minecraft.util.math.MathHelper +import com.mojang.brigadier.builder.ArgumentBuilder +import com.mojang.brigadier.context.CommandContext import org.mozilla.javascript.NativeObject -import org.mozilla.javascript.Scriptable -import java.net.URLEncoder -import java.nio.charset.Charset -import kotlin.reflect.KClass - -fun String.toVersion(): Version { - val (semvar, extra) = if ('-' in this) { - split('-') - } else listOf(this, null) - - val split = semvar!!.split(".").map(String::toInt) - return Version(split.getOrElse(0) { 0 }, split.getOrElse(1) { 0 }, split.getOrElse(2) { 0 }, extra, null, null) -} - -fun String.toIdentifier(): Identifier { - return Identifier.of(if (':' in this) this else "minecraft:$this") -} - -fun String.urlEncode() = URLEncoder.encode(this, Charset.defaultCharset()) - -// A helper function that makes the intent explicit and reduces parens -inline fun Any.asMixin() = this as T inline fun NativeObject?.get(key: String): T? { return this?.get(key) as? T } -fun NativeObject?.getOption(key: String, default: Any): String { - return (this?.get(key) ?: default).toString() -} - -// Note: getOrDefault(...).toInt/Double/Float() should be preferred -// over getOrDefault(...), as the exact numeric type -// of numeric properties depends on Rhino internals -inline fun NativeObject?.getOrDefault(key: String, default: T): T { - return this?.get(key) as? T ?: default -} - -fun NativeObject?.getOrNull(key: String): Any? { - return this?.get(key).takeIf { it != Scriptable.NOT_FOUND } -} - -fun Double.toRadians() = this * MathHelper.RADIANS_PER_DEGREE -fun Float.toRadians() = this * MathHelper.RADIANS_PER_DEGREE -fun Double.toDegrees() = this * MathHelper.DEGREES_PER_RADIAN -fun Float.toDegrees() = this * MathHelper.DEGREES_PER_RADIAN - -fun KClass<*>.descriptorString(): String = java.descriptorString() -fun KClass<*>.descriptor() = Descriptor.Object(descriptorString()) +fun > ArgumentBuilder.onExecute(block: (CommandContext) -> Unit): T = + executes { + block(it) + 1 + } diff --git a/src/main/kotlin/com/chattriggers/ctjs/typealiases.kt b/src/main/kotlin/com/chattriggers/ctjs/typealiases.kt deleted file mode 100644 index 159e8e83..00000000 --- a/src/main/kotlin/com/chattriggers/ctjs/typealiases.kt +++ /dev/null @@ -1,27 +0,0 @@ -package com.chattriggers.ctjs - -typealias MCSound = net.minecraft.client.sound.Sound -typealias MCBlockPos = net.minecraft.util.math.BlockPos -typealias MCBlock = net.minecraft.block.Block -typealias MCChunk = net.minecraft.world.chunk.Chunk -typealias MCEntity = net.minecraft.entity.Entity -typealias MCLivingEntity = net.minecraft.entity.LivingEntity -typealias MCParticle = net.minecraft.client.particle.Particle -typealias MCTeam = net.minecraft.scoreboard.Team -typealias MCInventory = net.minecraft.inventory.Inventory -typealias MCItem = net.minecraft.item.Item -typealias MCNbtBase = net.minecraft.nbt.NbtElement -typealias MCNbtCompound = net.minecraft.nbt.NbtCompound -typealias MCNbtList = net.minecraft.nbt.NbtList -typealias MCBlockEntity = net.minecraft.block.entity.BlockEntity -typealias MCDifficulty = net.minecraft.world.Difficulty -typealias MCGraphicsMode = net.minecraft.client.option.GraphicsMode -typealias MCSlot = net.minecraft.screen.slot.Slot -typealias MCAttenuationType = net.minecraft.client.sound.SoundInstance.AttenuationType -typealias MCBossBarColor = net.minecraft.entity.boss.BossBar.Color -typealias MCBossBarStyle = net.minecraft.entity.boss.BossBar.Style -typealias MCCloudRenderMode = net.minecraft.client.option.CloudRenderMode -typealias MCParticlesMode = net.minecraft.client.option.ParticlesMode -typealias MCDimensionType = net.minecraft.world.dimension.DimensionType -typealias MCVertexFormat = net.minecraft.client.render.VertexFormat -typealias MCChatVisibility = net.minecraft.network.message.ChatVisibility diff --git a/src/main/resources/assets/ctjs/js/mixinProvidedLibs.js b/src/main/resources/assets/ctjs/js/mixinProvidedLibs.js deleted file mode 100644 index 8439ebb3..00000000 --- a/src/main/resources/assets/ctjs/js/mixinProvidedLibs.js +++ /dev/null @@ -1,1142 +0,0 @@ -(function (global) { - // A restricted version of Java.type - global.Java = { - type(arg) { - if (typeof arg !== 'string') - throw new Error('Java.type expects a string as its only object'); - if (arg.startsWith('net.minecraft') || arg.startsWith('com.mojang.blaze3d')) - throw new Error(`Attempt to classload MC class ${arg} during Mixin application`); - return Packages[arg] - } - } - - const JSLoader = Java.type('com.chattriggers.ctjs.internal.engine.JSLoader').INSTANCE; - global.Console = Java.type('com.chattriggers.ctjs.engine.Console').INSTANCE; - - const Condition = Java.type('org.spongepowered.asm.mixin.injection.Constant').Condition; - const MixinObj = Java.type('com.chattriggers.ctjs.internal.launch.Mixin'); - const AtObj = Java.type('com.chattriggers.ctjs.internal.launch.At'); - const SliceObj = Java.type('com.chattriggers.ctjs.internal.launch.Slice'); - const LocalObj = Java.type('com.chattriggers.ctjs.internal.launch.Local'); - const ConstantObj = Java.type('com.chattriggers.ctjs.internal.launch.Constant'); - const InjectObj = Java.type('com.chattriggers.ctjs.internal.launch.Inject'); - const RedirectObj = Java.type('com.chattriggers.ctjs.internal.launch.Redirect'); - const ModifyArgObj = Java.type('com.chattriggers.ctjs.internal.launch.ModifyArg'); - const ModifyArgsObj = Java.type('com.chattriggers.ctjs.internal.launch.ModifyArgs'); - const ModifyConstantObj = Java.type('com.chattriggers.ctjs.internal.launch.ModifyConstant'); - const ModifyExpressionValueObj = Java.type('com.chattriggers.ctjs.internal.launch.ModifyExpressionValue'); - const ModifyReceiverObj = Java.type('com.chattriggers.ctjs.internal.launch.ModifyReceiver'); - const ModifyReturnValueObj = Java.type('com.chattriggers.ctjs.internal.launch.ModifyReturnValue'); - const ModifyVariableObj = Java.type('com.chattriggers.ctjs.internal.launch.ModifyVariable'); - const WrapOperationObj = Java.type('com.chattriggers.ctjs.internal.launch.WrapOperation'); - const WrapWithConditionObj = Java.type('com.chattriggers.ctjs.internal.launch.WrapWithCondition'); - - global.Condition = Condition - global.Opcodes = Java.type('org.objectweb.asm.Opcodes'); - - // Descriptor helpers - global.void_ = 'V'; - global.boolean = 'Z'; - global.char = 'C'; - global.byte = 'B'; - global.short = 'S'; - global.int = 'I'; - global.float = 'F'; - global.long = 'J'; - global.double = 'D'; - - global.desc = function desc(options) { - let str = options.owner ?? ''; - str += options.name ?? ''; - if (options.type) { - str += `:${options.type}`; - } else if (options.args) { - str += '('; - for (let arg of options.args) - str += arg; - str += ')'; - str += options.ret ?? 'V'; - } - return str; - } - - global.J = function(strings, exprs) { - // Transform 'a.b.c' into 'La/b/c;'; - let s = strings[0]; - for (let i = 0; exprs && i < exprs.length; i++) { - s += exprs[i]; - s += strings[i + 1]; - } - return `L${s.replaceAll('.', '/')};`; - } - - // Type assertions - const checkType = (value, expectedType) => { - if (typeof expectedType === 'string') { - if (typeof value !== expectedType) - return false; - } else { - if (!(value instanceof expectedType)) - return false; - } - - return true; - }; - - const assertType = (value, expectedType, obj) => { - if (value !== null && value !== undefined && !checkType(value, expectedType)) - throw new Error(`${obj} must be of type ${expectedType}, found type ${typeof value}`); - }; - - const assertArrayType = (value, expectedType, obj) => { - if (value !== null && value !== undefined && (!Array.isArray(value) || !value.every(v => checkType(v, expectedType)))) - throw new Error(`${obj} must be an array of ${expectedType}`); - }; - - class At { - static Shift = { - NONE: AtObj.Shift.NONE, - BEFORE: AtObj.Shift.BEFORE, - AFTER: AtObj.Shift.AFTER, - BY: AtObj.Shift.BY, - }; - - constructor(obj) { - if (typeof obj === 'string') { - this._initProps({ value: obj }); - } else { - this._initProps(obj); - } - } - - _initProps(obj) { - const value = obj.value ?? throw new Error('At.value must be specified'); - const id = obj.id; - const slice = obj.slice; - const shift = obj.shift; - const by = obj.by; - let args = obj.args; - if (typeof args === 'string') - args = [args]; - const target = obj.target; - const ordinal = obj.ordinal; - const opcode = obj.opcode; - const remap = obj.remap; - - assertType(id, 'string', 'At.id'); - assertType(value, 'string', 'At.value'); - assertType(slice, 'string', 'At.slice'); - assertType(shift, AtObj.Shift, 'At.shift'); - assertType(by, 'number', 'At.by'); - assertArrayType(args, 'string', 'At.args'); - assertType(target, 'string', 'At.target'); - assertType(ordinal, 'number', 'At.ordinal'); - assertType(opcode, 'number', 'At.opcode'); - assertType(remap, 'boolean', 'At.remap'); - - this.atObj = new AtObj( - value, id, slice, shift, by, args, target, ordinal, opcode, remap, - ) - } - } - - class Slice { - constructor(obj) { - if (typeof obj !== 'object') - throw new Error('Slice() expects an object as its first argument'); - this._initProps(obj); - } - - _initProps(obj) { - const id = obj.id; - const from = obj.from; - const to = obj.to; - - assertType(id, 'string', 'Slice.id'); - assertType(from, At, 'Slice.from'); - assertType(to, At, 'Slice.to'); - - this.sliceObj = new SliceObj(id, from?.atObj, to?.atObj); - } - } - - class Local { - constructor(obj) { - this._initProps(obj); - } - - _initProps(obj) { - const print = obj.print; - const index = obj.index; - const ordinal = obj.ordinal; - const type = obj.type; - const mutable = obj.mutable; - - assertType(print, 'boolean', 'Local.print'); - assertType(index, 'number', 'Local.index'); - assertType(ordinal, 'number', 'Local.ordinal'); - assertType(type, 'string', 'Local.type'); - assertType(mutable, 'boolean', 'Local.mutable'); - - this.localObj = new LocalObj(print, index, ordinal, type, mutable); - } - } - - class Constant { - constructor(obj) { - if (typeof obj !== 'object') - throw new Error('Constant() expects an object as its first argument'); - this._initProps(obj); - } - - _initProps(obj) { - const nullValue = obj.nullValue; - const intValue = obj.intValue; - const floatValue = obj.floatValue; - const longValue = obj.longValue; - const doubleValue = obj.doubleValue; - const stringValue = obj.stringValue; - const classValue = obj.classValue; - const ordinal = obj.ordinal; - const slice = obj.slice; - const expandZeroConditions = obj.expandZeroConditions; - const log = obj.log; - - assertType(nullValue, 'boolean', 'Constant.nullValue'); - assertType(intValue, 'number', 'Constant.intValue'); - assertType(floatValue, 'number', 'Constant.floatValue'); - assertType(longValue, 'number', 'Constant.longValue'); - assertType(doubleValue, 'number', 'Constant.doubleValue'); - assertType(stringValue, 'string', 'Constant.stringValue'); - assertType(classValue, 'string', 'Constant.classValue'); - assertType(ordinal, 'number', 'Constant.ordinal'); - assertType(slice, 'string', 'Constant.slice'); - assertType(expandZeroConditions, 'boolean', 'Constant.expandZeroConditions'); - assertType(log, 'boolean', 'Constant.log'); - - this.constantObj = new ConstantObj( - nullValue, intValue, floatValue, longValue, doubleValue, - stringValue, classValue, ordinal, slice, expandZeroConditions, log, - ) - } - } - - class Mixin { - constructor(obj) { - if (typeof obj === 'string') { - this._initProps({ target: obj }); - } else { - this._initProps(obj); - } - } - - _initProps(obj) { - const target = obj.target ?? throw new Error('Mixin.target must be specified'); - const priority = obj.priority; - const remap = obj.remap; - - assertType(target, 'string', 'Mixin.target'); - assertType(priority, 'number', 'Mixin.priority'); - assertType(remap, 'boolean', 'Mixin.remap'); - - this.mixinObj = new MixinObj(target, priority, remap); - } - - inject(obj) { - if (typeof obj !== 'object') - throw new Error('Mixin.inject() expects an object as its first argument'); - return this._createInject(obj); - } - - redirect(obj) { - if (typeof obj != 'object') - throw new Error('Mixin.redirect() expects an object as its first argument'); - return this._createRedirect(obj); - } - - modifyArg(obj) { - if (typeof obj != 'object') - throw new Error('Mixin.modifyArg() expects an object as its first argument'); - return this._createModifyArg(obj); - } - - modifyArgs(obj) { - if (typeof obj != 'object') - throw new Error('Mixin.modifyArgs() expects an object as its first argument'); - return this._createModifyArgs(obj); - } - - modifyConstant(obj) { - if (typeof obj != 'object') - throw new Error('Mixin.modifyConstant() expects an object as its first argument'); - return this._createModifyConstant(obj); - } - - modifyExpressionValue(obj) { - if (typeof obj != 'object') - throw new Error('Mixin.modifyExpressionValue() expects an object as its first argument'); - return this._createModifyExpressionValue(obj); - } - - modifyReceiver(obj) { - if (typeof obj != 'object') - throw new Error('Mixin.modifyReceiver() expects an object as its first argument'); - return this._createModifyReceiver(obj); - } - - modifyReturnValue(obj) { - if (typeof obj != 'object') - throw new Error('Mixin.modifyReturnValue() expects an object as its first argument'); - return this._createModifyReturnValue(obj); - } - - modifyVariable(obj) { - if (typeof obj != 'object') - throw new Error('Mixin.modifyVariable() expects an object as its first argument'); - return this._createModifyVariable(obj); - } - - wrapOperation(obj) { - if (typeof obj != 'object') - throw new Error('Mixin.wrapOperation() expects an object as its first argument'); - return this._createWrapOperation(obj); - } - - wrapWithCondition(obj) { - if (typeof obj != 'object') - throw new Error('Mixin.wrapWithCondition() expects an object as its first argument'); - return this._createWrapWithCondition(obj); - } - - widenField(name, isMutable) { - if (typeof name !== 'string') - throw new Error('Mixin.widenField expects a string'); - isMutable ??= false - if (typeof isMutable !== 'boolean') - throw new Error('The second argument provided to Mixin.widenField must be a boolean or undefined') - - JSLoader.registerFieldWidener(this.mixinObj, name, isMutable); - } - - widenMethod(name, isMutable) { - if (typeof name !== 'string') - throw new Error('Mixin.widenMethod expects a string'); - isMutable ??= false - if (typeof isMutable !== 'boolean') - throw new Error('The second argument provided to Mixin.widenMethod must be a boolean or undefined') - - JSLoader.registerMethodWidener(this.mixinObj, name, isMutable); - } - - _createInject(obj) { - const method = obj.method ?? throw new Error('Inject.method must be specified'); - const id = obj.id; - let slices = obj.slice; - if (slices instanceof Slice) - slices = [slices]; - let at = obj.at; - if (at instanceof At) - at = [at] - const cancellable = obj.cancellable; - let locals = obj.locals; - if (locals instanceof Local) - locals = [locals]; - const remap = obj.remap; - const require = obj.require; - const expect = obj.expect; - const allow = obj.allow; - const constraints = obj.constraints; - - assertType(id, 'string', 'Inject.id'); - assertType(method, 'string', 'Inject.method'); - assertArrayType(slices, Slice, 'Inject.slice'); - assertArrayType(at, At, 'Inject.at'); - assertType(cancellable, 'boolean', 'Inject.cancellable'); - assertArrayType(locals, Local, 'Inject.locals'); - assertType(remap, 'boolean', 'Inject.remap'); - assertType(require, 'number', 'Inject.require'); - assertType(expect, 'number', 'Inject.expect'); - assertType(allow, 'number', 'Inject.allow'); - assertType(constraints, 'string', 'Inject.constraints'); - - const injectObj = new InjectObj( - method, - id, - slices?.map(s => s.sliceObj), - at?.map(a => a.atObj), - cancellable, - locals?.map(l => l.localObj), - remap, - require, - expect, - allow, - constraints, - ); - - return JSLoader.registerInjector(this.mixinObj, injectObj); - } - - _createRedirect(obj) { - const method = obj.method ?? throw new Error('Redirect.method must be specified'); - const slice = obj.slice; - const at = obj.at ?? throw new Error('Redirect.at must be specified'); - let locals = obj.locals; - if (locals instanceof Local) - locals = [locals]; - const remap = obj.remap; - const require = obj.require; - const expect = obj.expect; - const allow = obj.allow; - const constraints = obj.constraints; - - assertType(method, 'string', 'Redirect.method'); - assertType(slice, Slice, 'Redirect.slice'); - assertType(at, At, 'Redirect.at'); - assertArrayType(locals, Local, 'Redirect.locals'); - assertType(remap, 'boolean', 'Redirect.remap'); - assertType(require, 'number', 'Redirect.number'); - assertType(expect, 'number', 'Redirect.expect'); - assertType(allow, 'number', 'Redirect.allow'); - assertType(constraints, 'string', 'Redirect.constraints'); - - const redirectObj = new RedirectObj( - method, - slice?.sliceObj, - at?.atObj, - locals?.map(l => l.localObj), - remap, - require, - expect, - allow, - constraints, - ); - - return JSLoader.registerInjector(this.mixinObj, redirectObj); - } - - _createModifyArg(obj) { - const method = obj.method ?? throw new Error('ModifyArg.method must be specified'); - const slice = obj.slice; - const at = obj.at ?? throw new Error('ModifyArg.at must be specified'); - const index = obj.index ?? throw new Error('ModifyArg.index must be specified'); - const captureAllParams = obj.captureAllParams; - let locals = obj.locals; - if (locals instanceof Local) - locals = [locals]; - const remap = obj.remap; - const require = obj.require; - const expect = obj.expect; - const allow = obj.allow; - const constraints = obj.constraints; - - assertType(method, 'string', 'ModifyArg.method'); - assertType(slice, Slice, 'ModifyArg.slice'); - assertType(at, At, 'ModifyArg.at'); - assertType(index, 'number', 'ModifyArg.index'); - assertType(captureAllParams, 'boolean', 'ModifyArg.captureAllParams'); - assertArrayType(locals, Local, 'ModifyArg.locals'); - assertType(remap, 'boolean', 'ModifyArg.remap'); - assertType(require, 'number', 'ModifyArg.require'); - assertType(expect, 'number', 'ModifyArg.expect'); - assertType(allow, 'number', 'ModifyArg.allow'); - assertType(constraints, 'string', 'ModifyArg.constraints'); - - const modifyArgObj = new ModifyArgObj( - method, - slice?.sliceObj, - at?.atObj, - index, - captureAllParams, - locals?.map(l => l.localObj), - remap, - require, - expect, - allow, - constraints, - ); - - return JSLoader.registerInjector(this.mixinObj, modifyArgObj); - } - - _createModifyArgs(obj) { - const method = obj.method ?? throw new Error('ModifyArgs.method must be specified'); - const slice = obj.slice; - const at = obj.at ?? throw new Error('ModifyArgs.at must be specified'); - let locals = obj.locals; - if (locals instanceof Local) - locals = [locals]; - const require = obj.require; - const remap = obj.remap; - const expect = obj.expect; - const allow = obj.allow; - const constraints = obj.constraints; - - assertType(method, 'string', 'ModifyArgs.method'); - assertType(slice, Slice, 'ModifyArgs.slice'); - assertType(at, At, 'ModifyArgs.at'); - assertArrayType(locals, Local, 'ModifyArgs.locals'); - assertType(require, 'number', 'ModifyArgs.require'); - assertType(remap, 'boolean', 'ModifyArgs.remap'); - assertType(expect, 'number', 'ModifyArgs.expect'); - assertType(allow, 'number', 'ModifyArgs.allow'); - assertType(constraints, 'string', 'ModifyArgs.constraints'); - - const modifyArgsObj = new ModifyArgsObj( - method, - slice?.sliceObj, - at?.atObj, - locals?.map(l => l.localObj), - remap, - require, - expect, - allow, - constraints, - ); - - return JSLoader.registerInjector(this.mixinObj, modifyArgsObj); - } - - _createModifyConstant(obj) { - const method = obj.method ?? throw new Error('ModifyConstant.method must be specified'); - let slice = obj.slice; - if (slice instanceof Slice) - slice = [slice] - const constant = obj.constant; - let locals = obj.locals; - if (locals instanceof Local) - locals = [locals]; - const require = obj.require; - const remap = obj.remap; - const expect = obj.expect; - const allow = obj.allow; - const constraints = obj.constraints; - - assertType(method, 'string', 'ModifyConstant.method'); - assertArrayType(slice, Slice, 'ModifyConstant.slice'); - assertType(constant, Constant, 'ModifyConstant.constant'); - assertArrayType(locals, Local, 'ModifyConstant.locals'); - assertType(require, 'number', 'ModifyConstant.require'); - assertType(remap, 'boolean', 'ModifyConstant.remap'); - assertType(expect, 'number', 'ModifyConstant.expect'); - assertType(allow, 'number', 'ModifyConstant.allow'); - assertType(constraints, 'string', 'ModifyConstant.constraints'); - - const modifyConstantObj = new ModifyConstantObj( - method, - slice?.map(s => s.sliceObj), - constant?.constantObj, - locals?.map(l => l.localObj), - remap, - require, - expect, - allow, - constraints, - ); - - return JSLoader.registerInjector(this.mixinObj, modifyConstantObj); - } - - _createModifyExpressionValue(obj) { - const method = obj.method ?? throw new Error('ModifyExpressionValue.method must be specified'); - const at = obj.at ?? throw new Error('ModifyExpressionValue.at must be specified'); - let slices = obj.slice; - if (slices instanceof Slice) - slices = [slices]; - let locals = obj.locals; - if (locals instanceof Local) - locals = [locals]; - const remap = obj.remap; - const require = obj.require; - const expect = obj.expect; - const allow = obj.allow; - - assertType(method, 'string', 'ModifyExpressionValue.method'); - assertType(at, At, 'ModifyExpressionValue.at'); - assertArrayType(slices, Slice, 'ModifyExpressionValue.slice'); - assertArrayType(locals, Local, 'ModifyExpressionValue.locals'); - assertType(remap, 'boolean', 'ModifyExpressionValue.remap'); - assertType(require, 'number', 'ModifyExpressionValue.require'); - assertType(expect, 'number', 'ModifyExpressionValue.expect'); - assertType(allow, 'number', 'ModifyExpressionValue.allow'); - - const modifyExpressionValueObj = new ModifyExpressionValueObj( - method, - at?.atObj, - slices?.map(s => s.sliceObj), - locals?.map(l => l.localObj), - remap, - require, - expect, - allow, - ); - - return JSLoader.registerInjector(this.mixinObj, modifyExpressionValueObj); - } - - _createModifyReceiver(obj) { - const method = obj.method ?? throw new Error('ModifyReceiver.method must be specified'); - const at = obj.at ?? throw new Error('ModifyReceiver.at must be specified'); - let slices = obj.slice; - if (slices instanceof Slice) - slices = [slices]; - let locals = obj.locals; - if (locals instanceof Local) - locals = [locals]; - const remap = obj.remap; - const require = obj.require; - const expect = obj.expect; - const allow = obj.allow; - - assertType(method, 'string', 'ModifyReceiver.method'); - assertType(at, At, 'ModifyReceiver.at'); - assertArrayType(slices, Slice, 'ModifyReceiver.slice'); - assertType(remap, 'boolean', 'ModifyReceiver.remap'); - assertType(require, 'number', 'ModifyReceiver.require'); - assertType(expect, 'number', 'ModifyReceiver.expect'); - assertType(allow, 'number', 'ModifyReceiver.allow'); - - const modifyReceiverObj = new ModifyReceiverObj( - method, - at?.atObj, - slices?.map(s => s.sliceObj), - locals?.map(l => l.localObj), - remap, - require, - expect, - allow, - ); - - return JSLoader.registerInjector(this.mixinObj, modifyReceiverObj); - } - - _createModifyReturnValue(obj) { - const method = obj.method ?? throw new Error('ModifyReturnValue.method must be specified'); - const at = obj.at ?? throw new Error('ModifyReturnValue.at must be specified'); - let slices = obj.slice; - if (slices instanceof Slice) - slices = [slices]; - let locals = obj.locals; - if (locals instanceof Local) - locals = [locals]; - const remap = obj.remap; - const require = obj.require; - const expect = obj.expect; - const allow = obj.allow; - - assertType(method, 'string', 'ModifyReturnValue.method'); - assertType(at, At, 'ModifyReturnValue.at'); - assertArrayType(slices, Slice, 'ModifyReturnValue.slice'); - assertType(remap, 'boolean', 'ModifyReturnValue.remap'); - assertType(require, 'number', 'ModifyReturnValue.require'); - assertType(expect, 'number', 'ModifyReturnValue.expect'); - assertType(allow, 'number', 'ModifyReturnValue.allow'); - - const modifyReturnValueObj = new ModifyReturnValueObj( - method, - at?.atObj, - slices?.map(s => s.sliceObj), - locals?.map(l => l.localObj), - remap, - require, - expect, - allow, - ); - - return JSLoader.registerInjector(this.mixinObj, modifyReturnValueObj); - } - - _createModifyVariable(obj) { - const method = obj.method ?? throw new Error('ModifyVariable.method must be specified'); - const at = obj.at ?? throw new Error('ModifyVariable.at must be specified'); - const slice = obj.slice; - const print = obj.print; - const ordinal = obj.ordinal; - const index = obj.index; - const type = obj.type; - let locals = obj.locals; - if (locals instanceof Local) - locals = [locals]; - const remap = obj.remap; - const require = obj.require; - const expect = obj.expect; - const allow = obj.allow; - const constraints = obj.constraints; - - assertType(method, 'string', 'ModifyVariable.method'); - assertType(at, At, 'ModifyVariable.at'); - assertType(slice, Slice, 'ModifyVariable.slice'); - assertType(remap, 'boolean', 'ModifyVariable.remap'); - assertType(print, 'boolean', 'ModifyVariable.print'); - assertType(ordinal, 'number', 'ModifyVariable.ordinal'); - assertType(index, 'number', 'ModifyVariable.index'); - assertType(type, 'string', 'ModifyVariable.type'); - assertArrayType(locals, Local, 'ModifyVariable.locals'); - assertType(remap, 'number', 'ModifyVariable.remap'); - assertType(require, 'number', 'ModifyVariable.require'); - assertType(expect, 'number', 'ModifyVariable.expect'); - assertType(allow, 'number', 'ModifyVariable.allow'); - assertType(constraints, 'string', 'ModifyVariable.constraints'); - - const modifyVariableObj = new ModifyVariableObj( - method, - at?.atObj, - slice?.sliceObj, - print, - ordinal, - index, - type, - locals?.map(l => l.localObj), - remap, - require, - expect, - allow, - constraints, - ); - - return JSLoader.registerInjector(this.mixinObj, modifyVariableObj); - } - - _createWrapOperation(obj) { - const method = obj.method ?? throw new Error('WrapOperation.method must be specified'); - const at = obj.at; - let constant = obj.constant; - let slices = obj.slice; - if (slices instanceof Slice) - slices = [slices]; - let locals = obj.locals; - if (locals instanceof Local) - locals = [locals]; - const remap = obj.remap; - const require = obj.require; - const expect = obj.expect; - const allow = obj.allow; - - assertType(method, 'string', 'WrapOperation.method'); - assertType(at, At, 'WrapOperation.at'); - assertType(constant, Constant, 'WrapOperation.constant'); - assertArrayType(locals, Local, 'WrapOperation.locals'); - assertArrayType(slices, Slice, 'WrapOperation.slice'); - assertType(remap, 'boolean', 'WrapOperation.remap'); - assertType(require, 'number', 'WrapOperation.require'); - assertType(expect, 'number', 'WrapOperation.expect'); - assertType(allow, 'number', 'WrapOperation.allow'); - - const wrapOperationObj = new WrapOperationObj( - method, - at?.atObj, - constant?.constantObj, - slices?.map(s => s.sliceObj), - locals?.map(l => l.localObj), - remap, - require, - expect, - allow, - ); - - return JSLoader.registerInjector(this.mixinObj, wrapOperationObj); - } - - _createWrapWithCondition(obj) { - const method = obj.method ?? throw new Error('WrapWithCondition.method must be specified'); - const at = obj.at ?? throw new Error('WrapWithCondition.at must be specified'); - let slices = obj.slice; - if (slices instanceof Slice) - slices = [slices]; - let locals = obj.locals; - if (locals instanceof Local) - locals = [locals]; - const remap = obj.remap; - const require = obj.require; - const expect = obj.expect; - const allow = obj.allow; - - assertType(method, 'string', 'WrapWithCondition.method'); - assertType(at, At, 'WrapWithCondition.at'); - assertArrayType(locals, Local, 'WrapWithCondition.locals'); - assertArrayType(slices, Slice, 'WrapWithCondition.slice'); - assertType(remap, 'boolean', 'WrapWithCondition.remap'); - assertType(require, 'number', 'WrapWithCondition.require'); - assertType(expect, 'number', 'WrapWithCondition.expect'); - assertType(allow, 'number', 'WrapWithCondition.allow'); - - const wrapWithConditionObj = new WrapWithConditionObj( - method, - at?.atObj, - slices?.map(s => s.sliceObj), - locals?.map(l => l.localObj), - remap, - require, - expect, - allow, - ); - - return JSLoader.registerInjector(this.mixinObj, wrapWithConditionObj); - } - } - - global.Mixin = Mixin; - global.Slice = Slice; - global.At = At; - global.Local = Local; - global.Constant = Constant; - - - /** - * @fileoverview console.js - * Implementation of the whatwg/console namespace for the Nashorn script engine. - * Ported to CT/Rhino - * See https://console.spec.whatwg.org - * - * @author https://github.com/fmartin5 - * - * @license AGPL-3.0 - * - * @environment Nashorn on JDK 9 - * - * @globals es5 - * - * @syntax es5 +arrow-functions +const +for-of +let - * - * @members - * config (non-standard) - * assert - * clear - * count - * debug - * dir - * dirxml - * error - * group - * groupCollapsed - * groupEnd - * info - * log - * table - * time - * timeEnd - * trace - * warn - */ - (function (globalObject, factory) { - Object.defineProperty(globalObject, "console", { - "writable": true, - "configurable": true, - "enumerable": false, - "value": factory() - }); - }(global, function factory() { - const console = {}; - - console.config = { - "indent": " | ", - "showMilliseconds": false, - "showMessageType": false, - "showTimeStamp": false, - "useColors": false, - "colorsByLogLevel": { - "error": "", - "log": "", - "info": "", - "warn": "" - } - }; - - // An object holding local data and functions. - const _ = {}; - - // The following line can be commented out in development for debugging purposes. - // console._ = _; - - _.counters = {}; - - _.defaultStringifier = function (anyValue) { - // noinspection FallThroughInSwitchStatementJS - switch (typeof anyValue) { - case "function": - return "[object Function(" + anyValue.length + ")]"; - case "object": { - if (Array.isArray(anyValue)) return "[object Array(" + anyValue.length + ")]"; - } - default: - return String(anyValue); - } - }; - - _.formats = { - "%d": (x) => typeof x === "symbol" ? NaN : parseInt(x), - "%f": (x) => typeof x === "symbol" ? NaN : parseFloat(x), - "%i": (x) => typeof x === "symbol" ? NaN : parseInt(x), - "%s": (x) => String(x), - "%%": (x) => "%", - // @todo Implement less trivial behaviors for the following format specifiers. - "%c": (x) => String(x), - "%o": (x) => String(x), - "%O": (x) => String(x) - }; - - _.indentLevel = 0; - _.lineSep = java.lang.System.getProperty("line.separator"); - _.timers = {}; - - - // Formatter - _.formatArguments = function (args) { - const rv = []; - for (let i = 0; i < args.length; i++) { - const arg = args[i]; - if (typeof arg === "string") { - rv.push(arg.replace(/%[cdfiosO%]/g, (match) => { - if (match === "%%") return "%"; - return ++i in args ? _.formats[match](args[i]) : match; - })); - } else { - rv.push(String(arg)); - } - } - return rv.join(" "); - }; - - _.formatObject = function (object) { - const sep = _.lineSep; - return _.defaultStringifier(object) + (" {" + sep + " ") + Object.keys(object).map(key => - _.defaultStringifier(key) + ": " + _.defaultStringifier(object[key])).join("," + sep + " ") + (sep + "}"); - }; - - _.makeTimeStamp = function () { - if (console.config.showMilliseconds) { - const date = new Date(); - return date.toLocaleTimeString() + "," + date.getMilliseconds(); - } - return new Date().toLocaleTimeString(); - }; - - - // Printer - _.printlnWarn = function (s) { - Console.println(s, LogType.WARN); - }; - - _.printLineToStdErr = function (s) { - Console.println(s, LogType.ERROR); - }; - - _.printLineToStdOut = function (s) { - Console.println(s); - }; - - - _.repeat = (s, n) => new Array(n + 1).join(s); - - - // Logger - _.writeln = function (msgType, msg) { - if (arguments.length < 2) return; - const showMessageType = console.config.showMessageType; - const showTimeStamp = console.config.showTimeStamp; - const msgTypePart = showMessageType ? msgType : ""; - const timeStampPart = showTimeStamp ? _.makeTimeStamp() : ""; - const prefix = (showMessageType || showTimeStamp - ? "[" + msgTypePart + (msgTypePart && timeStampPart ? " - " : "") + timeStampPart + "] " - : ""); - const indent = (_.indentLevel > 0 - ? _.repeat(console.config.indent, _.indentLevel) - : ""); - switch (msgType) { - case "assert": - case "error": { - _.printLineToStdErr(prefix + indent + msg); - break; - } - case "warn": { - _.printlnWarn(prefix + indent + msg); - break; - } - default: { - _.printLineToStdOut(prefix + indent + msg); - } - } - }; - - - /** - * Tests whether the given expression is true. If not, logs a message with the visual "error" representation. - */ - console.assert = function assert(booleanValue, arg) { - if (!!booleanValue) return; - const defaultMessage = "assertion failed"; - if (arguments.length < 2) return _.writeln("assert", defaultMessage); - if (typeof arg !== "string") return _.writeln("assert", _.formatArguments([defaultMessage, arg])); - _.writeln("assert", (defaultMessage + ": " + arg)); - }; - - - /** - * Clears the console. - * Works by invoking `cmd /c cls` on Windows and `clear` on other OSes. - */ - console.clear = function clear() { - try { - Console.clearConsole(); - } catch (_) { - // Pass - } - }; - - - /** - * Prints the number of times that 'console.count()' was called with the same label. - */ - console.count = function count(label = "default") { - label = String(label); - if (!(label in _.counters)) _.counters[label] = 0; - _.counters[label]++; - _.writeln("count", label + ": " + _.counters[label]); - }; - - - /** - * Logs a message, with a visual "debug" representation. - * @todo Optionally include some information for debugging, like the file path or line number where the call occurred from. - */ - console.debug = function debug(...args) { - const s = _.formatArguments(args); - _.writeln("debug", s); - }; - - /** - * Logs a listing of the properties of the given object. - * @todo Use the `options` argument. - */ - console.dir = function dir(arg, options) { - if (Object(arg) === arg) { - _.writeln("dir", _.formatObject(arg)); - return; - } - _.writeln("dir", _.defaultStringifier(arg)); - }; - - - /** - * Logs a space-separated list of formatted representations of the given arguments, - * using DOM tree representation whenever possible. - */ - console.dirxml = function dirxml(...args) { - const list = []; - args.forEach((arg) => { - if (Object(arg) === arg) list.push(_.formatObject(arg)); - else list.push(_.defaultStringifier(arg)); - }); - _.writeln("dirxml", list.join(" ")); - }; - - - /** - * Logs a message with the visual "error" representation. - * @todo Optionally include some information for debugging, like the file path or line number where the call occurred from. - */ - console.error = function error(...args) { - const s = _.formatArguments(args); - _.writeln("error", s); - }; - - - /** - * Logs a message as a label for and opens a nested block to indent future messages sent. - * Call console.groupEnd() to close the block. - * Representation of block is up to the platform, - * it can be an interactive block or just a set of indented sub messages. - */ - console.group = function group(...args) { - if (args.length) { - const s = _.formatArguments(args); - _.writeln("group", s); - } - _.indentLevel++; - }; - - - console.groupCollapsed = function groupCollapsed(...args) { - console.group([]); - }; - - - /** - * Closes the most recently opened block created by a call - * to 'console.group()' or 'console.groupCollapsed()'. - */ - console.groupEnd = function groupEnd() { - if (_.indentLevel < 1) return; - _.indentLevel--; - }; - - - /** - * Logs a message with the visual "info" representation. - */ - console.info = function info(...args) { - const s = _.formatArguments(args); - _.writeln("info", s); - }; - - - /** - * Logs a message with the visual "log" representation. - */ - console.log = function log(...args) { - const s = _.formatArguments(args); - _.writeln("log", s); - }; - - - console.time = function time(label = "default") { - label = String(label); - if (label in _.timers) return; - _.timers[label] = Date.now(); - }; - - - /** - * Stops a timer created by a call to `console.time(label)` and logs the elapsed time. - */ - console.timeEnd = function timeEnd(label = "default") { - label = String(label); - const milliseconds = Date.now() - _.timers[label]; - delete _.timers[label]; - - _.writeln("timeEnd", label + ": " + milliseconds + " ms"); - }; - - - /** - * Logs a stack trace for where the call occurred from, using the given arguments as a label. - */ - console.trace = function trace(...args) { - const label = "Trace" + (args.length > 0 ? ": " + _.formatArguments(args) : ""); - const e = new Error(); - Error.captureStackTrace(e, trace); - // Replaces the first line by our label. - const s = label + "\n" + e.stack; - _.writeln("trace", s); - }; - - - /** - * @todo Logs a tabular representation of the given data. - * Fall back to just logging the argument if it can’t be parsed as tabular. - */ - console.table = function table(tabularData, properties) { - console.log(tabularData); - }; - - - /** - * Logs a message with the visual "warning" representation. - */ - console.warn = function warn(...args) { - const s = _.formatArguments(args); - _.writeln("warn", s); - }; - - return console; - })); -})(this); diff --git a/src/main/resources/assets/ctjs/js/moduleProvidedLibs.js b/src/main/resources/assets/ctjs/js/moduleProvidedLibs.js index 686c6832..b1124785 100644 --- a/src/main/resources/assets/ctjs/js/moduleProvidedLibs.js +++ b/src/main/resources/assets/ctjs/js/moduleProvidedLibs.js @@ -1,10 +1,7 @@ -(function(global) { +(function (global) { global.Mappings = com.chattriggers.ctjs.api.Mappings; function getJavaType(clazz) { - const mappedName = Mappings.mapClassName(clazz); - if (mappedName) - return Packages[mappedName.replaceAll("/", ".")] return Packages[clazz]; } @@ -38,108 +35,20 @@ } // API - - loadClass("java.util.ArrayList"); - loadClass("java.util.HashMap"); - loadClass("gg.essential.universal.UKeyboard", "Keyboard"); - loadClass("net.minecraft.util.Hand"); - - loadClass("com.chattriggers.ctjs.api.client.Client"); - loadClass("com.chattriggers.ctjs.api.client.CPS"); - loadClass("com.chattriggers.ctjs.api.client.FileLib"); - loadClass("com.chattriggers.ctjs.api.client.KeyBind"); - loadClass("com.chattriggers.ctjs.api.client.MathLib"); - loadClass("com.chattriggers.ctjs.api.client.Player"); - loadClass("com.chattriggers.ctjs.api.client.Settings"); - loadClass("com.chattriggers.ctjs.api.client.Sound"); - - loadClass("com.chattriggers.ctjs.api.commands.DynamicCommands", "Commands"); - - loadClass("com.chattriggers.ctjs.api.entity.BlockEntity"); - loadClass("com.chattriggers.ctjs.api.entity.Entity"); - loadClass("com.chattriggers.ctjs.api.entity.LivingEntity"); - loadClass("com.chattriggers.ctjs.api.entity.Particle"); - loadClass("com.chattriggers.ctjs.api.entity.PlayerInteraction"); - loadClass("com.chattriggers.ctjs.api.entity.PlayerMP"); - loadClass("com.chattriggers.ctjs.api.entity.Team"); - - loadClass("com.chattriggers.ctjs.api.inventory.action.Action"); - loadClass("com.chattriggers.ctjs.api.inventory.action.ClickAction"); - loadClass("com.chattriggers.ctjs.api.inventory.action.DragAction"); - loadClass("com.chattriggers.ctjs.api.inventory.action.DropAction"); - loadClass("com.chattriggers.ctjs.api.inventory.action.KeyAction"); - loadClass("com.chattriggers.ctjs.api.inventory.nbt.NBT"); - loadClass("com.chattriggers.ctjs.api.inventory.nbt.NBTBase"); - loadClass("com.chattriggers.ctjs.api.inventory.nbt.NBTTagCompound"); - loadClass("com.chattriggers.ctjs.api.inventory.nbt.NBTTagList"); - loadClass("com.chattriggers.ctjs.api.inventory.Inventory"); - loadClass("com.chattriggers.ctjs.api.inventory.Item"); - loadClass("com.chattriggers.ctjs.api.inventory.ItemType"); - loadClass("com.chattriggers.ctjs.api.inventory.Slot"); - - loadClass("com.chattriggers.ctjs.api.message.ChatLib"); - loadClass("com.chattriggers.ctjs.api.message.TextComponent"); - - loadClass("com.chattriggers.ctjs.api.render.Book"); - loadClass("com.chattriggers.ctjs.api.render.Display"); - loadClass("com.chattriggers.ctjs.api.render.Gui"); - loadClass("com.chattriggers.ctjs.api.render.Image"); - loadClass("com.chattriggers.ctjs.api.render.Rectangle"); - loadClass("com.chattriggers.ctjs.api.render.Renderer"); - loadClass("com.chattriggers.ctjs.api.render.Renderer3d"); - loadClass("com.chattriggers.ctjs.api.render.Shape"); - loadClass("com.chattriggers.ctjs.api.render.Text"); - loadClass("com.chattriggers.ctjs.api.render.Toast"); + loadClass("com.chattriggers.ctjs.api.FileLib"); + loadClass("com.chattriggers.ctjs.api.CustomKeyMapping"); + loadClass("com.chattriggers.ctjs.api.CustomCommand"); // For module authors to use with custom triggers loadClass("com.chattriggers.ctjs.api.triggers.CancellableEvent"); - loadClass("com.chattriggers.ctjs.api.vec.Vec2f"); - loadClass("com.chattriggers.ctjs.api.vec.Vec3f"); - loadClass("com.chattriggers.ctjs.api.vec.Vec3i"); - - loadClass("com.chattriggers.ctjs.api.world.block.Block"); - loadClass("com.chattriggers.ctjs.api.world.block.BlockFace"); - loadClass("com.chattriggers.ctjs.api.world.block.BlockPos"); - loadClass("com.chattriggers.ctjs.api.world.block.BlockType"); - loadClass("com.chattriggers.ctjs.api.world.BossBars"); - loadClass("com.chattriggers.ctjs.api.world.Chunk"); - loadClass("com.chattriggers.ctjs.api.world.PotionEffect"); - loadClass("com.chattriggers.ctjs.api.world.PotionEffectType"); - loadClass("com.chattriggers.ctjs.api.world.Scoreboard"); - loadClass("com.chattriggers.ctjs.api.world.Server"); - loadClass("com.chattriggers.ctjs.api.world.TabList"); - loadClass("com.chattriggers.ctjs.api.world.World"); - - loadClass("com.chattriggers.ctjs.api.Config"); - // Misc - loadClass("com.chattriggers.ctjs.engine.Register", "TriggerRegister"); loadClass("com.chattriggers.ctjs.engine.WrappedThread", "Thread"); + loadClass("com.chattriggers.ctjs.CTJS"); global.Priority = Java.class("com.chattriggers.ctjs.api.triggers.Trigger").Priority; - loadClass("com.chattriggers.ctjs.CTJS", "ChatTriggers"); global.Console = Java.type("com.chattriggers.ctjs.engine.Console").INSTANCE; - // GL - loadClass("org.lwjgl.opengl.GL11"); - loadClass("org.lwjgl.opengl.GL12"); - loadClass("org.lwjgl.opengl.GL13"); - loadClass("org.lwjgl.opengl.GL14"); - loadClass("org.lwjgl.opengl.GL15"); - loadClass("org.lwjgl.opengl.GL20"); - loadClass("org.lwjgl.opengl.GL21"); - loadClass("org.lwjgl.opengl.GL30"); - loadClass("org.lwjgl.opengl.GL31"); - loadClass("org.lwjgl.opengl.GL32"); - loadClass("org.lwjgl.opengl.GL33"); - loadClass("org.lwjgl.opengl.GL40"); - loadClass("org.lwjgl.opengl.GL41"); - loadClass("org.lwjgl.opengl.GL42"); - loadClass("org.lwjgl.opengl.GL43"); - loadClass("org.lwjgl.opengl.GL44"); - loadClass("org.lwjgl.opengl.GL45"); - global.cancel = event => { if (event instanceof CancellableEvent) { event.setCanceled(true); @@ -153,21 +62,6 @@ global.register = (type, method) => TriggerRegister.register(type, method); global.createCustomTrigger = name => TriggerRegister.createCustomTrigger(name); - // String prototypes - String.prototype.addFormatting = function () { - return ChatLib.addColor(this); - }; - - String.prototype.addColor = String.prototype.addFormatting; - - String.prototype.removeFormatting = function () { - return ChatLib.removeFormatting(this); - }; - - String.prototype.replaceFormatting = function () { - return ChatLib.replaceFormatting(this); - }; - // animation global.easeOut = (start, finish, speed, jump = 1) => { if (Math.floor(Math.abs(finish - start) / jump) > 0) @@ -179,17 +73,6 @@ return easeOut(this, to, speed, jump); }; - global.easeColor = (start, finish, speed, jump) => Renderer.getColor( - easeOut((start >> 16) & 0xFF, (finish >> 16) & 0xFF, speed, jump), - easeOut((start >> 8) & 0xFF, (finish >> 8) & 0xFF, speed, jump), - easeOut(start & 0xFF, finish & 0xFF, speed, jump), - easeOut((start >> 24) & 0xFF, (finish >> 24) & 0xFF, speed, jump) - ); - - Number.prototype.easeColor = function (to, speed, jump) { - return easeColor(this, to, speed, jump); - }; - const LogType = com.chattriggers.ctjs.engine.LogType; global.print = function (toPrint, color = null) { diff --git a/src/main/resources/assets/ctjs/lang/en_us.json b/src/main/resources/assets/ctjs/lang/en_us.json index 9fd617bf..aaff35d2 100644 --- a/src/main/resources/assets/ctjs/lang/en_us.json +++ b/src/main/resources/assets/ctjs/lang/en_us.json @@ -1,4 +1,10 @@ { "ctjs.key.binding.console": "Console", - "ctjs.key.category": "ChatTriggers" + "ctjs.key.category": "ChatTriggers", + "ctjs.ui.modules": "Modules", + "ctjs.ui.openModulesFolder": "Open Modules Folder", + "ctjs.ui.delete": "Delete", + "ctjs.ui.deleteConfirmation": "Are you sure you want to delete %s?", + "ctjs.ui.noRevert": "This action cannot be reverted!", + "ctjs.ui.byCreator": "by %s" } diff --git a/src/main/resources/ctjs.accesswidener b/src/main/resources/ctjs.accesswidener deleted file mode 100644 index b32abfff..00000000 --- a/src/main/resources/ctjs.accesswidener +++ /dev/null @@ -1,3 +0,0 @@ -accessWidener v2 named -accessible class net/minecraft/client/world/ClientChunkManager$ClientChunkMap -accessible class net/minecraft/client/option/GameOptions$Visitor \ No newline at end of file diff --git a/src/main/resources/ctjs.mixins.json b/src/main/resources/ctjs.mixins.json index e0e9f916..5e4e9f85 100644 --- a/src/main/resources/ctjs.mixins.json +++ b/src/main/resources/ctjs.mixins.json @@ -2,69 +2,20 @@ "required": true, "minVersion": "0.8", "package": "com.chattriggers.ctjs.internal.mixins", - "compatibilityLevel": "JAVA_21", + "compatibilityLevel": "JAVA_25", "client": [ - "AbstractSoundInstanceAccessor", - "BlockEntityRenderDispatcherMixin", - "BookScreenAccessor", - "BossBarHudAccessor", - "ChatHudAccessor", - "ChatHudMixin", - "ChatScreenAccessor", - "ClickableWidgetAccessor", - "ClientChunkManagerAccessor", - "ClientChunkMapAccessor", - "ClientPlayerEntityMixin", - "ClientPlayerInteractionManagerMixin", - "ClientPlayNetworkHandlerAccessor", - "ClientWorldAccessor", - "CreativeInventoryScreenMixin", - "EntityRenderDispatcherAccessor", - "EntityRenderDispatcherMixin", - "GameOptionsAccessor", - "GameOptionsMixin", - "HandledScreenAccessor", - "HandledScreenMixin", - "InGameHudMixin", - "KeyBindingAccessor", + "ClientPacketListenerMixin", + "KeyBindsListMixin", "MinecraftClientMixin", - "MouseMixin", - "ParticleAccessor", - "ParticleManagerMixin", - "PlayerListEntryAccessor", - "PlayerListHudAccessor", - "PlayerListHudMixin", - "RenderTickCounterMixin", - "commands.ClientCommandSourceMixin", - "commands.ClientPlayNetworkHandlerMixin", - "sound.SoundAccessor", - "sound.SoundManagerAccessor", - "sound.SoundSystemAccessor", - "sound.SoundSystemMixin", - "sound.SourceAccessor" + "OptionsMixin" ], "injectors": { "defaultRequire": 1 }, "plugin": "com.chattriggers.ctjs.internal.launch.CTMixinPlugin", "mixins": [ - "ChunkAccessor", - "ClientConnectionMixin", - "ItemStackMixin", - "LivingEntityMixin", - "MinecraftClientAccessor", - "NbtCompoundAccessor", - "PlayerEntityMixin", - "PlayerScreenHandlerMixin", - "Scoreboard$1Accessor", - "ScoreboardObjectiveMixin", - "ScreenHandlerMixin", + "CommandNodeAccessor", "SystemDetailsMixin", - "commands.CommandContextAccessor", - "commands.CommandDispatcherMixin", - "commands.CommandNodeAccessor", - "commands.EntitySelectorAccessor", - "stdio.BootstrapMixin", "stdio.LoggerPrintStreamMixin" ] } diff --git a/src/main/resources/fabric.mod.json b/src/main/resources/fabric.mod.json index b081c165..7b76c767 100644 --- a/src/main/resources/fabric.mod.json +++ b/src/main/resources/fabric.mod.json @@ -4,38 +4,50 @@ "name": "ChatTriggers", "version": "$version", "description": "A framework for Minecraft that allows for live scripting and client modification using JavaScript", - "authors": ["Ecolsson", "FalseHonesty", "kerbybit"], - "contributors": ["Squagward", "Debuggings", "DJtheRedstoner"], + "authors": [ + "Ecolsson", + "FalseHonesty", + "kerbybit" + ], + "contributors": [ + "Squagward", + "Debuggings", + "DJtheRedstoner" + ], "icon": "assets/ctjs/logo.png", - "license": ["MIT"], + "license": [ + "MIT" + ], "contact": { - "homepage": "https://chattriggers.com", - "sources": "https://github.com/ChatTriggers/ChatTriggers", - "issues": "https://github.com/ChatTriggers/ChatTriggers/issues" + "homepage": "https://github.com/srockw/ctjs", + "sources": "https://github.com/srockw/ctjs", + "issues": "https://github.com/srockw/ctjs/issues" }, "environment": "client", "entrypoints": { "preLaunch": [ "com.chattriggers.ctjs.internal.launch.CTJSPreLaunch" ], - "client": ["com.chattriggers.ctjs.CTJS"], + "client": [ + "com.chattriggers.ctjs.CTJS" + ], "modmenu": [ "com.chattriggers.ctjs.internal.compat.ModMenuEntry" ] }, - "mixins": ["ctjs.mixins.json"], + "mixins": [ + "ctjs.mixins.json" + ], "depends": { "fabricloader": ">=$loader_version", "fabric-api": ">=$fabric_api_version", "fabric-language-kotlin": ">=$fabric_kotlin_version" }, "custom": { - "ctjs:yarn-mappings": "$yarn_mappings", "modmenu": { "links": { "modmenu.discord": "https://discord.gg/chattriggers" } } - }, - "accessWidener": "ctjs.accesswidener" + } } diff --git a/typing-generator/build.gradle.kts b/typing-generator/build.gradle.kts index d2cbcc7c..01cb0fcf 100644 --- a/typing-generator/build.gradle.kts +++ b/typing-generator/build.gradle.kts @@ -14,4 +14,5 @@ repositories { dependencies { implementation(libs.ksp) + implementation("org.jsoup:jsoup:1.15.3") } diff --git a/typing-generator/src/main/kotlin/com/chattriggers/ctjs/typing/Provider.kt b/typing-generator/src/main/kotlin/com/chattriggers/ctjs/typing/Provider.kt index f55e1cc4..762c5014 100644 --- a/typing-generator/src/main/kotlin/com/chattriggers/ctjs/typing/Provider.kt +++ b/typing-generator/src/main/kotlin/com/chattriggers/ctjs/typing/Provider.kt @@ -37,7 +37,7 @@ class Processor(environment: SymbolProcessorEnvironment) : SymbolProcessor { } private fun collectRoots(resolver: Resolver): Set { - val manualRootDeclarations = manualRoots + val manualRootDeclarations = ManualRoots.roots .map(resolver::getKSNameFromString) .mapNotNull(resolver::getClassDeclarationByName) .toSet() @@ -48,14 +48,14 @@ class Processor(environment: SymbolProcessorEnvironment) : SymbolProcessor { it.declarations.filter { decl -> val qualifier = decl.packageName.asString() !qualifier.startsWith("com.chattriggers.ctjs.internal") && - !qualifier.startsWith("com.chattriggers.ctjs.typing") && - decl.isPublic() + !qualifier.startsWith("com.chattriggers.ctjs.typing") && + decl.isPublic() } }.filterIsInstance().toSet() } private fun collectAllReachableClasses(decl: KSDeclaration, classes: MutableSet, depth: Int) { - if (depth > MAX_DEPTH || decl in classes || decl is KSTypeParameter || !decl.isPublic()) + if (depth > MAX_DEPTH || decl in classes || decl is KSTypeParameter) return if (decl is KSTypeAlias) { @@ -152,7 +152,7 @@ class Processor(environment: SymbolProcessorEnvironment) : SymbolProcessor { // Note: We take a name parameter so that we can override the name of clazz. This is done for nested classes val functions = clazz.getDeclaredFunctions().filter { - it.isPublic() + it.isPublicSafe() }.filterNot { it.findOverridee() != null || it.simpleName.asString().let { name -> name in excludedMethods || name in typescriptReservedWords @@ -164,7 +164,7 @@ class Processor(environment: SymbolProcessorEnvironment) : SymbolProcessor { val functionNames = functions.map { it.simpleName.asString() } val properties = clazz.getDeclaredProperties().filter { - it.isPublic() + it.isPublicSafe() }.filterNot { it.simpleName.asString() in functionNames || it.findOverridee() != null }.toList() @@ -173,11 +173,12 @@ class Processor(environment: SymbolProcessorEnvironment) : SymbolProcessor { val (staticProperties, instanceProperties) = properties.partition { it.isStatic() } val isEnum = clazz.classKind == ClassKind.ENUM_CLASS - val nestedClasses = clazz.declarations.filterIsInstance().filter { - it.isPublic() - }.filter { - it.classKind == ClassKind.ENUM_CLASS || it.classKind == ClassKind.CLASS - }.toList() + val nestedClasses = clazz.declarations + .filterIsInstance() + .filter { + it.isPublicSafe() && (it.classKind == ClassKind.ENUM_CLASS || it.classKind == ClassKind.CLASS) + } + .toList() // Output static object first, if necessary if (staticProperties.isNotEmpty() || staticFunctions.isNotEmpty() || nestedClasses.isNotEmpty() || isEnum) { @@ -486,12 +487,20 @@ class Processor(environment: SymbolProcessorEnvironment) : SymbolProcessor { } fun KSPropertyDeclaration.isStatic() = Modifier.JAVA_STATIC in modifiers || - isAnnotationPresent(JvmStatic::class) || - isAnnotationPresent(JvmField::class) + isAnnotationPresent(JvmStatic::class) || + isAnnotationPresent(JvmField::class) fun KSFunctionDeclaration.isStatic() = Modifier.JAVA_STATIC in modifiers || - isAnnotationPresent(JvmStatic::class) || - isConstructor() + isAnnotationPresent(JvmStatic::class) || + isConstructor() + + private fun KSDeclaration.isPublicSafe(): Boolean { + return try { + isPublic() || Modifier.PUBLIC in modifiers + } catch (e: Exception) { + false + } + } private class Package(val parent: Package?, val name: String) { val subpackages = mutableMapOf() diff --git a/typing-generator/src/main/kotlin/com/chattriggers/ctjs/typing/manualRoots.kt b/typing-generator/src/main/kotlin/com/chattriggers/ctjs/typing/manualRoots.kt new file mode 100644 index 00000000..b2bb3bef --- /dev/null +++ b/typing-generator/src/main/kotlin/com/chattriggers/ctjs/typing/manualRoots.kt @@ -0,0 +1,92 @@ +package com.chattriggers.ctjs.typing + +import org.jsoup.Jsoup + +object ManualRoots { + private const val FABRIC_API_URL = "https://maven.fabricmc.net/docs/fabric-api-0.151.0+26.1.2/allclasses-index.html" + + val roots = mutableSetOf( + "java.awt.Color", + "java.util.ArrayList", + "java.util.HashMap", + "org.lwjgl.glfw.GLFW", + "org.spongepowered.asm.mixin.injection.callback.CallbackInfo", + "net.minecraft.client.Minecraft", + "net.minecraft.util.ARGB", + "net.minecraft.client.renderer.ShapeRenderer", + "net.minecraft.client.renderer.rendertype.RenderTypes", + "com.mojang.brigadier.arguments.ArgumentType", + "com.mojang.brigadier.arguments.BoolArgumentType", + "com.mojang.brigadier.arguments.DoubleArgumentType", + "com.mojang.brigadier.arguments.FloatArgumentType", + "com.mojang.brigadier.arguments.IntegerArgumentType", + "com.mojang.brigadier.arguments.LongArgumentType", + "com.mojang.brigadier.arguments.StringArgumentType", "net.minecraft.commands.arguments.item.ItemArgument", + "net.minecraft.commands.arguments.SlotArgument", + "net.minecraft.commands.arguments.TeamArgument", + "net.minecraft.commands.arguments.TimeArgument", + "net.minecraft.commands.arguments.UuidArgument", + "net.minecraft.commands.arguments.coordinates.Vec2Argument", + "net.minecraft.commands.arguments.coordinates.Vec3Argument", + "net.minecraft.commands.arguments.AngleArgument", + "net.minecraft.commands.arguments.RangeArgument", + "net.minecraft.commands.arguments.SlotsArgument", + "net.minecraft.commands.arguments.StyleArgument", + "net.minecraft.commands.arguments.EntityArgument", + "net.minecraft.commands.arguments.NbtTagArgument", + "net.minecraft.commands.arguments.SignedArgument", + "net.minecraft.commands.arguments.MessageArgument", + "net.minecraft.commands.arguments.NbtPathArgument", + "net.minecraft.commands.arguments.coordinates.SwizzleArgument", + "net.minecraft.commands.arguments.coordinates.BlockPosArgument", + "net.minecraft.commands.arguments.item.FunctionArgument", + "net.minecraft.commands.arguments.GameModeArgument", + "net.minecraft.commands.arguments.HexColorArgument", + "net.minecraft.commands.arguments.ParticleArgument", + "net.minecraft.commands.arguments.ResourceArgument", + "net.minecraft.commands.arguments.coordinates.RotationArgument", + "net.minecraft.commands.arguments.WaypointArgument", + "net.minecraft.commands.arguments.coordinates.ColumnPosArgument", + "net.minecraft.commands.arguments.ComponentArgument", + "net.minecraft.commands.arguments.DimensionArgument", + "net.minecraft.commands.arguments.ObjectiveArgument", + "net.minecraft.commands.arguments.OperationArgument", + "net.minecraft.commands.arguments.TeamColorArgument", + "net.minecraft.commands.arguments.blocks.BlockStateArgument", + "net.minecraft.commands.arguments.IdentifierArgument", + "net.minecraft.commands.arguments.CompoundTagArgument", + "net.minecraft.commands.arguments.GameProfileArgument", + "net.minecraft.commands.arguments.ResourceKeyArgument", + "net.minecraft.commands.arguments.ScoreHolderArgument", + "net.minecraft.commands.arguments.EntityAnchorArgument", + "net.minecraft.commands.arguments.ResourceOrIdArgument", + "net.minecraft.commands.arguments.HeightmapTypeArgument", + "net.minecraft.commands.arguments.item.ItemPredicateArgument", + "net.minecraft.commands.arguments.ResourceOrTagArgument", + "net.minecraft.commands.arguments.blocks.BlockPredicateArgument", + "net.minecraft.commands.arguments.ScoreboardSlotArgument", + "net.minecraft.commands.arguments.TemplateMirrorArgument", + "net.minecraft.commands.arguments.ResourceOrTagKeyArgument", + "net.minecraft.commands.arguments.ResourceSelectorArgument", + "net.minecraft.commands.arguments.TemplateRotationArgument", + "net.minecraft.commands.arguments.ObjectiveCriteriaArgument", + "net.minecraft.commands.arguments.StringRepresentableArgument", + ) + + private fun collectClasses(url: String) { + val doc = Jsoup.connect(url).get() + val links = doc.getElementsByClass("col-first") + links.forEach { link -> + val a = link.getElementsByTag("a") + if (a.isEmpty()) return@forEach + val href = a.first()?.attr("href") ?: return@forEach + roots += href.replace("/", ".").replace(".html", "").trim() + } + } + + init { + collectClasses(FABRIC_API_URL) + } +} + + diff --git a/typing-generator/src/main/kotlin/com/chattriggers/ctjs/typing/prologue.kt b/typing-generator/src/main/kotlin/com/chattriggers/ctjs/typing/prologue.kt index ba4a9516..6da724a4 100644 --- a/typing-generator/src/main/kotlin/com/chattriggers/ctjs/typing/prologue.kt +++ b/typing-generator/src/main/kotlin/com/chattriggers/ctjs/typing/prologue.kt @@ -1,123 +1,15 @@ package com.chattriggers.ctjs.typing -val manualRoots = setOf( - "java.awt.Color", - "java.util.ArrayList", - "java.util.HashMap", - "gg.essential.universal.UKeyboard", - "net.minecraft.util.Hand", - "org.lwjgl.opengl.GL11", - "org.lwjgl.opengl.GL12", - "org.lwjgl.opengl.GL13", - "org.lwjgl.opengl.GL14", - "org.lwjgl.opengl.GL15", - "org.lwjgl.opengl.GL20", - "org.lwjgl.opengl.GL21", - "org.lwjgl.opengl.GL30", - "org.lwjgl.opengl.GL31", - "org.lwjgl.opengl.GL32", - "org.lwjgl.opengl.GL33", - "org.lwjgl.opengl.GL40", - "org.lwjgl.opengl.GL41", - "org.lwjgl.opengl.GL42", - "org.lwjgl.opengl.GL43", - "org.lwjgl.opengl.GL44", - "org.lwjgl.opengl.GL45", - "org.spongepowered.asm.mixin.injection.callback.CallbackInfo", -) - private val providedTypes = mutableMapOf( - "Keyboard" to "gg.essential.universal.UKeyboard", - "Hand" to "net.minecraft.util.Hand", - - "Client" to "com.chattriggers.ctjs.api.client.Client", - "CPS" to "com.chattriggers.ctjs.api.client.CPS", - "FileLib" to "com.chattriggers.ctjs.api.client.FileLib", - "KeyBind" to "com.chattriggers.ctjs.api.client.KeyBind", - "MathLib" to "com.chattriggers.ctjs.api.client.MathLib", - "Player" to "com.chattriggers.ctjs.api.client.Player", - "Settings" to "com.chattriggers.ctjs.api.client.Settings", - "Sound" to "com.chattriggers.ctjs.api.client.Sound", - - "Commands" to "com.chattriggers.ctjs.api.commands.DynamicCommands", - - "BlockEntity" to "com.chattriggers.ctjs.api.entity.BlockEntity", - "Entity" to "com.chattriggers.ctjs.api.entity.Entity", - "LivingEntity" to "com.chattriggers.ctjs.api.entity.LivingEntity", - "Particle" to "com.chattriggers.ctjs.api.entity.Particle", - "PlayerMP" to "com.chattriggers.ctjs.api.entity.PlayerMP", - "Team" to "com.chattriggers.ctjs.api.entity.Team", - - "Action" to "com.chattriggers.ctjs.api.inventory.action.Action", - "ClickAction" to "com.chattriggers.ctjs.api.inventory.action.ClickAction", - "DragAction" to "com.chattriggers.ctjs.api.inventory.action.DragAction", - "DropAction" to "com.chattriggers.ctjs.api.inventory.action.DropAction", - "KeyAction" to "com.chattriggers.ctjs.api.inventory.action.KeyAction", - "NBT" to "com.chattriggers.ctjs.api.inventory.nbt.NBT", - "NBTBase" to "com.chattriggers.ctjs.api.inventory.nbt.NBTBase", - "NBTTagCompound" to "com.chattriggers.ctjs.api.inventory.nbt.NBTTagCompound", - "NBTTagList" to "com.chattriggers.ctjs.api.inventory.nbt.NBTTagList", - "Inventory" to "com.chattriggers.ctjs.api.inventory.Inventory", - "Item" to "com.chattriggers.ctjs.api.inventory.Item", - "ItemType" to "com.chattriggers.ctjs.api.inventory.ItemType", - "Slot" to "com.chattriggers.ctjs.api.inventory.Slot", - - "ChatLib" to "com.chattriggers.ctjs.api.message.ChatLib", - "TextComponent" to "com.chattriggers.ctjs.api.message.TextComponent", - - "Book" to "com.chattriggers.ctjs.api.render.Book", - "Display" to "com.chattriggers.ctjs.api.render.Display", - "Gui" to "com.chattriggers.ctjs.api.render.Gui", - "Image" to "com.chattriggers.ctjs.api.render.Image", - "Rectangle" to "com.chattriggers.ctjs.api.render.Rectangle", - "Renderer" to "com.chattriggers.ctjs.api.render.Renderer", - "Renderer3d" to "com.chattriggers.ctjs.api.render.Renderer3d", - "Shape" to "com.chattriggers.ctjs.api.render.Shape", - "Text" to "com.chattriggers.ctjs.api.render.Text", + "FileLib" to "com.chattriggers.ctjs.api.FileLib", + "CustomKeyMapping" to "com.chattriggers.ctjs.api.CustomKeyMapping", + "CustomCommand" to "com.chattriggers.ctjs.api.CustomCommand", "CancellableEvent" to "com.chattriggers.ctjs.api.triggers.CancellableEvent", - - "Vec2f" to "com.chattriggers.ctjs.api.vec.Vec2f", - "Vec3f" to "com.chattriggers.ctjs.api.vec.Vec3f", - "Vec3i" to "com.chattriggers.ctjs.api.vec.Vec3i", - - "Block" to "com.chattriggers.ctjs.api.world.block.Block", - "BlockFace" to "com.chattriggers.ctjs.api.world.block.BlockFace", - "BlockPos" to "com.chattriggers.ctjs.api.world.block.BlockPos", - "BlockType" to "com.chattriggers.ctjs.api.world.block.BlockType", - "BossBars" to "com.chattriggers.ctjs.api.world.BossBars", - "Chunk" to "com.chattriggers.ctjs.api.world.Chunk", - "PotionEffect" to "com.chattriggers.ctjs.api.world.PotionEffect", - "PotionEffectType" to "com.chattriggers.ctjs.api.world.PotionEffectType", - "Scoreboard" to "com.chattriggers.ctjs.api.world.Scoreboard", - "Server" to "com.chattriggers.ctjs.api.world.Server", - "TabList" to "com.chattriggers.ctjs.api.world.TabList", - "World" to "com.chattriggers.ctjs.api.world.World", - - "Config" to "com.chattriggers.ctjs.api.Config", - "TriggerRegister" to "com.chattriggers.ctjs.engine.Register", "Thread" to "com.chattriggers.ctjs.engine.WrappedThread", "Priority" to "com.chattriggers.ctjs.api.triggers.Trigger\$Priority", - "ChatTriggers" to "com.chattriggers.ctjs.CTJS", + "CTJS" to "com.chattriggers.ctjs.CTJS", "Console" to "com.chattriggers.ctjs.engine.Console", - - "GL11" to "org.lwjgl.opengl.GL11", - "GL12" to "org.lwjgl.opengl.GL12", - "GL13" to "org.lwjgl.opengl.GL13", - "GL14" to "org.lwjgl.opengl.GL14", - "GL15" to "org.lwjgl.opengl.GL15", - "GL20" to "org.lwjgl.opengl.GL20", - "GL21" to "org.lwjgl.opengl.GL21", - "GL30" to "org.lwjgl.opengl.GL30", - "GL31" to "org.lwjgl.opengl.GL31", - "GL32" to "org.lwjgl.opengl.GL32", - "GL33" to "org.lwjgl.opengl.GL33", - "GL40" to "org.lwjgl.opengl.GL40", - "GL41" to "org.lwjgl.opengl.GL41", - "GL42" to "org.lwjgl.opengl.GL42", - "GL43" to "org.lwjgl.opengl.GL43", - "GL44" to "org.lwjgl.opengl.GL44", - "GL45" to "org.lwjgl.opengl.GL45", ) val prologue = """ @@ -125,60 +17,26 @@ val prologue = """ /// export {}; - declare interface String { - addFormatting(): string; - addColor(): string; - removeFormatting(): string; - replaceFormatting(): string; - } - declare interface Number { easeOut(to: number, speed: number, jump: number): number; - easeColor(to: number, speed: number, jump: number): java.awt.Color; } - + interface RegisterTypes { - chat(...args: (string | unknown)[]): com.chattriggers.ctjs.api.triggers.ChatTrigger; - actionBar(...args: (string | unknown)[]): com.chattriggers.ctjs.api.triggers.ChatTrigger; - worldLoad(): com.chattriggers.ctjs.api.triggers.Trigger; - worldUnload(): com.chattriggers.ctjs.api.triggers.Trigger; - clicked(mouseX: number, mouseY: number, button: number, isPressed: boolean): com.chattriggers.ctjs.api.triggers.Trigger; - scrolled(mouseX: number, mouseY: number, scrollDelta: number): com.chattriggers.ctjs.api.triggers.Trigger; - dragged(mouseXDelta: number, mouseYDelta: number, mouseX: number, mouseY: number, mouseButton: number): com.chattriggers.ctjs.api.triggers.Trigger; - soundPlay(position: com.chattriggers.ctjs.api.vec.Vec3f, name: string, volume: number, pitch: number, category: net.minecraft.sound.SoundCategory, event: org.spongepowered.asm.mixin.injection.callback.CallbackInfo): com.chattriggers.ctjs.api.triggers.SoundPlayTrigger; - tick(ticksElapsed: number): com.chattriggers.ctjs.api.triggers.Trigger; - step(stepsElapsed: number): com.chattriggers.ctjs.api.triggers.StepTrigger; - renderWorld(partialTicks: number): com.chattriggers.ctjs.api.triggers.Trigger; - preRenderWorld(partialTicks: number): com.chattriggers.ctjs.api.triggers.Trigger; - postRenderWorld(partialTicks: number): com.chattriggers.ctjs.api.triggers.Trigger; - renderOverlay(): com.chattriggers.ctjs.api.triggers.Trigger; - renderPlayerList(event: org.spongepowered.asm.mixin.injection.callback.CallbackInfo): com.chattriggers.ctjs.api.triggers.EventTrigger; - drawBlockHighlight(position: BlockPos, event: CancellableEvent): com.chattriggers.ctjs.api.triggers.EventTrigger; - gameLoad(): com.chattriggers.ctjs.api.triggers.Trigger; - gameUnload(): com.chattriggers.ctjs.api.triggers.Trigger; - command(...args: string[]): com.chattriggers.ctjs.api.triggers.CommandTrigger; - guiOpened(screen: net.minecraft.client.gui.screen.Screen, event: org.spongepowered.asm.mixin.injection.callback.CallbackInfo): com.chattriggers.ctjs.api.triggers.EventTrigger; - guiClosed(screen: net.minecraft.client.gui.screen.Screen): com.chattriggers.ctjs.api.triggers.Trigger; - dropItem(item: Item, entireStack: boolean, event: org.spongepowered.asm.mixin.injection.callback.CallbackInfo): com.chattriggers.ctjs.api.triggers.EventTrigger; - messageSent(message: string, event: CancellableEvent): com.chattriggers.ctjs.api.triggers.EventTrigger; - itemTooltip(lore: TextComponent[], item: Item, event: org.spongepowered.asm.mixin.injection.callback.CallbackInfo): com.chattriggers.ctjs.api.triggers.EventTrigger; - playerInteract(interaction: com.chattriggers.ctjs.api.entity.PlayerInteraction, interactionTarget: Entity | Block | Item, event: CancellableEvent): com.chattriggers.ctjs.api.triggers.EventTrigger; - entityDamage(entity: Entity, attacker: PlayerMP): com.chattriggers.ctjs.api.triggers.Trigger; - entityDeath(entity: Entity): com.chattriggers.ctjs.api.triggers.Trigger; - guiRender(mouseX: number, mouseY: number, screen: net.minecraft.client.gui.screen.Screen): com.chattriggers.ctjs.api.triggers.Trigger; - guiKey(char: String, keyCode: number, screen: net.minecraft.client.gui.screen.Screen, event: CancellableEvent): com.chattriggers.ctjs.api.triggers.EventTrigger; - guiMouseClick(mouseX: number, mouseY: number, mouseButton: number, isPressed: boolean, screen: net.minecraft.client.gui.screen.Screen, event: CancellableEvent): com.chattriggers.ctjs.api.triggers.EventTrigger; - guiMouseDrag(mouseXDelta: number, mouseYDelta: number, mouseX: number, mouseY: number, mouseButton: number, screen: net.minecraft.client.gui.screen.Screen, event: CancellableEvent): com.chattriggers.ctjs.api.triggers.EventTrigger; - packetSent(packet: net.minecraft.network.packet.Packet, event: org.spongepowered.asm.mixin.injection.callback.CallbackInfo): com.chattriggers.ctjs.api.triggers.PacketTrigger; - packetReceived(packet: net.minecraft.network.packet.Packet, event: CancellableEvent): com.chattriggers.ctjs.api.triggers.PacketTrigger; - serverConnect(): com.chattriggers.ctjs.api.triggers.Trigger; - serverDisconnect(): com.chattriggers.ctjs.api.triggers.Trigger; - renderEntity(entity: Entity, partialTicks: number, event: CancellableEvent): com.chattriggers.ctjs.api.triggers.RenderEntityTrigger; - renderBlockEntity(blockEntity: BlockEntity, partialTicks: number, event: CancellableEvent): com.chattriggers.ctjs.api.triggers.RenderBlockEntityTrigger; - postGuiRender(mouseX: number, mouseY: number, screen: net.minecraft.client.gui.screen.Screen): com.chattriggers.ctjs.api.triggers.Trigger; - spawnParticle(particle: Particle, event: org.spongepowered.asm.mixin.injection.callback.CallbackInfo): com.chattriggers.ctjs.api.triggers.EventTrigger; + renderOverlay(ctx: net.minecraft.client.gui.GuiGraphicsExtractor, tickCounter: net.minecraft.client.DeltaTracker); + chat(message: net.minecraft.network.chat.Component, event: CancellableEvent); + actionBar(message: net.minecraft.network.chat.Component, event: CancellableEvent); + messageSent(message: string, isCommand: boolean, event: CancellableEvent); + tick(); + + renderLevelExtraction(ctx: net.fabricmc.fabric.api.client.rendering.v1.level.LevelExtractionContext) + renderEndMain(ctx: net.fabricmc.fabric.api.client.rendering.v1.level.LevelRenderContext); + renderBeforeGizmos(ctx: net.fabricmc.fabric.api.client.rendering.v1.level.LevelRenderContext); + renderAfterTranslucentTerrain(ctx: net.fabricmc.fabric.api.client.rendering.v1.level.LevelRenderContext); + renderAfterSolidFeatures(ctx: net.fabricmc.fabric.api.client.rendering.v1.level.LevelRenderContext); + renderAfterTranslucentFeatures(ctx: net.fabricmc.fabric.api.client.rendering.v1.level.LevelRenderContext); + renderBeforeTranslucentTerrain(ctx: net.fabricmc.fabric.api.client.rendering.v1.level.LevelRenderContext); } - + declare global { const Java: { /** @@ -205,15 +63,12 @@ val prologue = """ * instantiation, use `Client.scheduleTask(delayInTicks, func)`. */ function setTimeout(func: () => void, delayInMs: number): void; - - const ArrayList: typeof java.util.ArrayList; - interface ArrayList extends java.util.ArrayList {} - const HashMap: typeof java.util.HashMap; - interface HashMap extends java.util.HashMap {} -${providedTypes.entries.joinToString("") { (name, type) -> -"const $name: typeof $type;\ninterface $name extends $type {}\n" -}.prependIndent(" ")} +${ + providedTypes.entries.joinToString("") { (name, type) -> + "const $name: typeof $type;\ninterface $name extends $type {}\n" + }.prependIndent(" ") +} /** * Registers a new trigger and returns it. @@ -221,7 +76,7 @@ ${providedTypes.entries.joinToString("") { (name, type) -> function register( name: T, cb: (...args: Parameters) => void, - ): ReturnType; + ): com.chattriggers.ctjs.api.triggers.Trigger; /** * Cancels the given event @@ -236,7 +91,6 @@ ${providedTypes.entries.joinToString("") { (name, type) -> function createCustomTrigger(name: string): { trigger(...args: unknown[]) }; function easeOut(start: number, finish: number, speed: number, jump?: number): number; - function easeColor(start: number, finish: number, speed: number, jump?: number): java.awt.Color; function print(message: string, color?: java.awt.Color): void; function println(message: string, color?: java.awt.Color, end?: string): void;