commit 166d04c3ba7f88b1d3e1b9a7d633129827899e9e Author: core Date: Fri Jul 21 21:58:40 2023 -0400 make tha client diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..cbd0d3a --- /dev/null +++ b/.gitignore @@ -0,0 +1,39 @@ +# gradle +.gradle/ +build/ +out/ +classes/ + +# eclipse + +*.launch + +# idea + +.idea/ +*.iml +*.ipr +*.iws + +# vscode + +.settings/ +.vscode/ +bin/ +.classpath +.project + +# macos + +*.DS_Store + +# fabric + +run/ + +# java + +hs_err_*.log +replay_*.log +*.hprof +*.jfr \ No newline at end of file diff --git a/build.gradle b/build.gradle new file mode 100644 index 0000000..afc04fb --- /dev/null +++ b/build.gradle @@ -0,0 +1,104 @@ +plugins { + id 'fabric-loom' version '1.3-SNAPSHOT' + id 'maven-publish' + id "org.jetbrains.kotlin.jvm" version "1.9.0" + id("com.github.johnrengelman.shadow") version "8.1.1" +} + +version = project.mod_version +group = project.maven_group + +base { + archivesName = project.archives_base_name +} + +repositories { + // Add repositories to retrieve artifacts from in here. + // You should only use this when depending on other mods because + // Loom adds the essential maven repositories to download Minecraft and libraries from automatically. + // See https://docs.gradle.org/current/userguide/declaring_repositories.html + // for more information about repositories. + + maven { + url "https://notnite.github.io/blockbuild/mvn/" + } +} + +dependencies { + // To change the versions see the gradle.properties file + minecraft "com.mojang:minecraft:${project.minecraft_version}" + mappings "net.fabricmc:yarn:${project.yarn_mappings}:v2" + modImplementation "net.fabricmc:fabric-loader:${project.loader_version}" + + // Fabric API. This is technically optional, but you probably want it anyway. + modImplementation "net.fabricmc.fabric-api:fabric-api:${project.fabric_version}" + modImplementation "net.fabricmc:fabric-language-kotlin:${project.fabric_kotlin_version}" + // Uncomment the following line to enable the deprecated Fabric API modules. + // These are included in the Fabric API production distribution and allow you to update your mod to the latest modules at a later more convenient time. + + // modImplementation "net.fabricmc.fabric-api:fabric-api-deprecated:${project.fabric_version}" + implementation(shadow("io.github.spair:imgui-java-binding:${project.imgui_version}")) + implementation(shadow("io.github.spair:imgui-java-lwjgl3:${project.imgui_version}")) + implementation(shadow("io.github.spair:imgui-java-natives-windows:${project.imgui_version}")) + implementation(shadow("io.github.spair:imgui-java-natives-linux:${project.imgui_version}")) + implementation(shadow("io.github.spair:imgui-java-natives-macos:${project.imgui_version}")) +} + +processResources { + inputs.property "version", project.version + + filesMatching("fabric.mod.json") { + expand "version": project.version + } +} + +tasks.withType(JavaCompile).configureEach { + it.options.release = 17 +} + +tasks.withType(org.jetbrains.kotlin.gradle.tasks.KotlinCompile).all { + kotlinOptions { + jvmTarget = 17 + } +} + +java { + // Loom will automatically attach sourcesJar to a RemapSourcesJar task and to the "build" task + // if it is present. + // If you remove this line, sources will not be generated. + withSourcesJar() + + sourceCompatibility = JavaVersion.VERSION_17 + targetCompatibility = JavaVersion.VERSION_17 +} + +jar { + from("LICENSE") { + rename { "${it}_${project.base.archivesName.get()}"} + } +} + +// configure the maven publication +publishing { + publications { + mavenJava(MavenPublication) { + from components.java + } + } + + // See https://docs.gradle.org/current/userguide/publishing_maven.html for information on how to set up publishing. + repositories { + // Add repositories to publish to here. + // Notice: This block does NOT have the same function as the block in the top level. + // The repositories here will be used for publishing your artifact, not for + // retrieving dependencies. + } +} + +loom { + runs { + client { + vmArgs "-Dclient-brand=LiveOverflowMod" + } + } +} \ No newline at end of file diff --git a/gradle.properties b/gradle.properties new file mode 100644 index 0000000..2424139 --- /dev/null +++ b/gradle.properties @@ -0,0 +1,16 @@ +org.gradle.jvmargs=-Xmx1G +org.gradle.parallel=true + +# Fabric Properties +# check these on https://fabricmc.net/develop +minecraft_version=1.20.1 +yarn_mappings=1.20.1+build.10 +loader_version=0.14.21 +fabric_kotlin_version=1.10.8+kotlin.1.9.0 + +mod_version=1.0.0 +maven_group=dev.coredeos +archives_base_name=maple + +fabric_version=0.86.0+1.20.1 +imgui_version=1.86.10 \ No newline at end of file diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 0000000..033e24c Binary files /dev/null and b/gradle/wrapper/gradle-wrapper.jar differ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 0000000..62f495d --- /dev/null +++ b/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,7 @@ +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-8.2-bin.zip +networkTimeout=10000 +validateDistributionUrl=true +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists diff --git a/gradlew b/gradlew new file mode 100755 index 0000000..fcb6fca --- /dev/null +++ b/gradlew @@ -0,0 +1,248 @@ +#!/bin/sh + +# +# Copyright © 2015-2021 the original authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +############################################################################## +# +# Gradle start up script for POSIX generated by Gradle. +# +# Important for running: +# +# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is +# noncompliant, but you have some other compliant shell such as ksh or +# bash, then to run this script, type that shell name before the whole +# command line, like: +# +# ksh Gradle +# +# Busybox and similar reduced shells will NOT work, because this script +# requires all of these POSIX shell features: +# * functions; +# * expansions «$var», «${var}», «${var:-default}», «${var+SET}», +# «${var#prefix}», «${var%suffix}», and «$( cmd )»; +# * compound commands having a testable exit status, especially «case»; +# * various built-in commands including «command», «set», and «ulimit». +# +# Important for patching: +# +# (2) This script targets any POSIX shell, so it avoids extensions provided +# by Bash, Ksh, etc; in particular arrays are avoided. +# +# The "traditional" practice of packing multiple parameters into a +# space-separated string is a well documented source of bugs and security +# problems, so this is (mostly) avoided, by progressively accumulating +# options in "$@", and eventually passing that to Java. +# +# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, +# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; +# see the in-line comments for details. +# +# There are tweaks for specific operating systems such as AIX, CygWin, +# Darwin, MinGW, and NonStop. +# +# (3) This script is generated from the Groovy template +# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# within the Gradle project. +# +# You can find Gradle at https://github.com/gradle/gradle/. +# +############################################################################## + +# Attempt to set APP_HOME + +# Resolve links: $0 may be a link +app_path=$0 + +# Need this for daisy-chained symlinks. +while + APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path + [ -h "$app_path" ] +do + ls=$( ls -ld "$app_path" ) + link=${ls#*' -> '} + case $link in #( + /*) app_path=$link ;; #( + *) app_path=$APP_HOME$link ;; + esac +done + +# This is normally unused +# shellcheck disable=SC2034 +APP_BASE_NAME=${0##*/} +APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD=maximum + +warn () { + echo "$*" +} >&2 + +die () { + echo + echo "$*" + echo + exit 1 +} >&2 + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "$( uname )" in #( + CYGWIN* ) cygwin=true ;; #( + Darwin* ) darwin=true ;; #( + MSYS* | MINGW* ) msys=true ;; #( + NONSTOP* ) nonstop=true ;; +esac + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD=$JAVA_HOME/jre/sh/java + else + JAVACMD=$JAVA_HOME/bin/java + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD=java + if ! command -v java >/dev/null 2>&1 + then + die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +fi + +# Increase the maximum file descriptors if we can. +if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then + case $MAX_FD in #( + max*) + # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC3045 + MAX_FD=$( ulimit -H -n ) || + warn "Could not query maximum file descriptor limit" + esac + case $MAX_FD in #( + '' | soft) :;; #( + *) + # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC3045 + ulimit -n "$MAX_FD" || + warn "Could not set maximum file descriptor limit to $MAX_FD" + esac +fi + +# Collect all arguments for the java command, stacking in reverse order: +# * args from the command line +# * the main class name +# * -classpath +# * -D...appname settings +# * --module-path (only if needed) +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. + +# For Cygwin or MSYS, switch paths to Windows format before running java +if "$cygwin" || "$msys" ; then + APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) + CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) + + JAVACMD=$( cygpath --unix "$JAVACMD" ) + + # Now convert the arguments - kludge to limit ourselves to /bin/sh + for arg do + if + case $arg in #( + -*) false ;; # don't mess with options #( + /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath + [ -e "$t" ] ;; #( + *) false ;; + esac + then + arg=$( cygpath --path --ignore --mixed "$arg" ) + fi + # Roll the args list around exactly as many times as the number of + # args, so each arg winds up back in the position where it started, but + # possibly modified. + # + # NB: a `for` loop captures its iteration list before it begins, so + # changing the positional parameters here affects neither the number of + # iterations, nor the values presented in `arg`. + shift # remove old arg + set -- "$@" "$arg" # push replacement arg + done +fi + + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + +# Collect all arguments for the java command; +# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of +# shell script including quotes and variable substitutions, so put them in +# double quotes to make sure that they get re-expanded; and +# * put everything else in single quotes, so that it's not re-expanded. + +set -- \ + "-Dorg.gradle.appname=$APP_BASE_NAME" \ + -classpath "$CLASSPATH" \ + org.gradle.wrapper.GradleWrapperMain \ + "$@" + +# Stop when "xargs" is not available. +if ! command -v xargs >/dev/null 2>&1 +then + die "xargs is not available" +fi + +# Use "xargs" to parse quoted args. +# +# With -n1 it outputs one arg per line, with the quotes and backslashes removed. +# +# In Bash we could simply go: +# +# readarray ARGS < <( xargs -n1 <<<"$var" ) && +# set -- "${ARGS[@]}" "$@" +# +# but POSIX shell has neither arrays nor command substitution, so instead we +# post-process each arg (as a line of input to sed) to backslash-escape any +# character that might be a shell metacharacter, then use eval to reverse +# that process (while maintaining the separation between arguments), and wrap +# the whole thing up as a single "set" statement. +# +# This will of course break if any of these variables contains a newline or +# an unmatched quote. +# + +eval "set -- $( + printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | + xargs -n1 | + sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | + tr '\n' ' ' + )" '"$@"' + +exec "$JAVACMD" "$@" diff --git a/gradlew.bat b/gradlew.bat new file mode 100644 index 0000000..93e3f59 --- /dev/null +++ b/gradlew.bat @@ -0,0 +1,92 @@ +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem + +@if "%DEBUG%"=="" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%"=="" set DIRNAME=. +@rem This is normally unused +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if %ERRORLEVEL% equ 0 goto execute + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto execute + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* + +:end +@rem End local scope for the variables with windows NT shell +if %ERRORLEVEL% equ 0 goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +set EXIT_CODE=%ERRORLEVEL% +if %EXIT_CODE% equ 0 set EXIT_CODE=1 +if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% +exit /b %EXIT_CODE% + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/run/mods/DevAuth-fabric-1.1.2.jar b/run/mods/DevAuth-fabric-1.1.2.jar new file mode 100644 index 0000000..cb2ec3c Binary files /dev/null and b/run/mods/DevAuth-fabric-1.1.2.jar differ diff --git a/settings.gradle b/settings.gradle new file mode 100644 index 0000000..56266b4 --- /dev/null +++ b/settings.gradle @@ -0,0 +1,10 @@ +pluginManagement { + repositories { + maven { + name = 'Fabric' + url = 'https://maven.fabricmc.net/' + } + mavenCentral() + gradlePluginPortal() + } +} \ No newline at end of file diff --git a/src/main/java/dev/coredoes/maple/mixin/ClientBrandRetrieverMixin.java b/src/main/java/dev/coredoes/maple/mixin/ClientBrandRetrieverMixin.java new file mode 100644 index 0000000..6fba5f7 --- /dev/null +++ b/src/main/java/dev/coredoes/maple/mixin/ClientBrandRetrieverMixin.java @@ -0,0 +1,20 @@ +package dev.coredoes.maple.mixin; + +import dev.coredoes.maple.util.BrandRetriever; +import net.minecraft.client.ClientBrandRetriever; +import net.minecraft.obfuscate.DontObfuscate; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Overwrite; + +@Mixin(ClientBrandRetriever.class) +public class ClientBrandRetrieverMixin { + /** + * @author c0repwn3r + * @reason for brand setting with -Dclient-brand + */ + @DontObfuscate + @Overwrite(remap = false) + public static String getClientModName() { + return BrandRetriever.Companion.retrieveBrand(); + } +} diff --git a/src/main/java/dev/coredoes/maple/mixin/ClientConnectionMixin.java b/src/main/java/dev/coredoes/maple/mixin/ClientConnectionMixin.java new file mode 100644 index 0000000..e0cba69 --- /dev/null +++ b/src/main/java/dev/coredoes/maple/mixin/ClientConnectionMixin.java @@ -0,0 +1,37 @@ +package dev.coredoes.maple.mixin; + +import net.minecraft.network.ClientConnection; +import net.minecraft.network.PacketCallbacks; +import net.minecraft.network.listener.PacketListener; +import net.minecraft.network.packet.Packet; +import net.minecraft.network.packet.c2s.play.CustomPayloadC2SPacket; +import net.minecraft.network.packet.s2c.play.HealthUpdateS2CPacket; +import net.minecraft.util.Identifier; +import org.jetbrains.annotations.Nullable; +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(ClientConnection.class) +public class ClientConnectionMixin { + @Inject(method = "handlePacket", at = @At("HEAD"), cancellable = true) + private static void onHandlePacket(Packet packet, PacketListener listener, CallbackInfo info) { + if (packet instanceof HealthUpdateS2CPacket pkt) { + if (pkt.getHealth() == 0 && pkt.getFood() == 0 && pkt.getSaturation() == 0) { + info.cancel(); + } + } + } + + @Inject(method = "sendImmediately", at = @At("HEAD"), cancellable = true) + private void sendImmediately(Packet packet, @Nullable PacketCallbacks callbacks, CallbackInfo ci) { + if (packet instanceof CustomPayloadC2SPacket pkt) { + if (Objects.equals(pkt.getChannel(), new Identifier("minecraft", "register"))) { + ci.cancel(); + } + } + } +} diff --git a/src/main/java/dev/coredoes/maple/mixin/InputUtilMixin.java b/src/main/java/dev/coredoes/maple/mixin/InputUtilMixin.java new file mode 100644 index 0000000..8b55690 --- /dev/null +++ b/src/main/java/dev/coredoes/maple/mixin/InputUtilMixin.java @@ -0,0 +1,18 @@ +package dev.coredoes.maple.mixin; + +import dev.coredoes.maple.manager.GuiManager; +import net.minecraft.client.util.InputUtil; +import org.lwjgl.glfw.GLFWCharModsCallbackI; +import org.lwjgl.glfw.GLFWKeyCallbackI; +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(InputUtil.class) +public class InputUtilMixin { + @Inject(method = "setKeyboardCallbacks", at = @At("TAIL")) + private static void setKeyboardCallbacks(long handle, GLFWKeyCallbackI keyCallback, GLFWCharModsCallbackI charModsCallback, CallbackInfo ci) { + GuiManager.INSTANCE.windowInit(handle); + } +} diff --git a/src/main/java/dev/coredoes/maple/mixin/KeyboardMixin.java b/src/main/java/dev/coredoes/maple/mixin/KeyboardMixin.java new file mode 100644 index 0000000..ede574e --- /dev/null +++ b/src/main/java/dev/coredoes/maple/mixin/KeyboardMixin.java @@ -0,0 +1,23 @@ +package dev.coredoes.maple.mixin; + +import dev.coredoes.maple.gui.MapleScreen; +import net.minecraft.client.Keyboard; +import net.minecraft.client.MinecraftClient; +import org.lwjgl.glfw.GLFW; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +@Mixin(Keyboard.class) +public class KeyboardMixin { + @Inject(method = "onKey(JIIII)V", at = @At("HEAD")) + public void onKey(long window, int key, int scancode, int action, int modifiers, CallbackInfo ci) { + var menuKey = GLFW.GLFW_KEY_RIGHT_SHIFT; + + if (key == menuKey) { + var mc = MinecraftClient.getInstance(); + if (mc.currentScreen == null) mc.setScreen(MapleScreen.INSTANCE); + } + } +} diff --git a/src/main/java/dev/coredoes/maple/mixin/PlayerMoveC2SPacketMixin.java b/src/main/java/dev/coredoes/maple/mixin/PlayerMoveC2SPacketMixin.java new file mode 100644 index 0000000..141e0db --- /dev/null +++ b/src/main/java/dev/coredoes/maple/mixin/PlayerMoveC2SPacketMixin.java @@ -0,0 +1,33 @@ +package dev.coredoes.maple.mixin; + +import dev.coredoes.maple.module.BotMovement; +import net.minecraft.network.packet.c2s.play.PlayerMoveC2SPacket; +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Mutable; +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(PlayerMoveC2SPacket.class) +public class PlayerMoveC2SPacketMixin { + @Final + @Shadow + @Mutable + protected double x; + @Final + @Mutable + @Shadow + protected double z; + + @Inject(method = "", at = @At("TAIL")) + public void constructor(double x, double y, double z, float yaw, float pitch, boolean onGround, boolean changePosition, boolean changeLook, CallbackInfo ci) { + if (BotMovement.INSTANCE.isEnabled()) { + double newX = Math.round(x * 100) / 100d; + double newZ = Math.round(z * 100) / 100d; + this.x = Math.nextAfter(newX, newX + Math.signum(newX)); // Round x + this.z = Math.nextAfter(newZ, newZ + Math.signum(newZ)); // Round z + } + } +} diff --git a/src/main/java/dev/coredoes/maple/mixin/RenderSystemMixin.java b/src/main/java/dev/coredoes/maple/mixin/RenderSystemMixin.java new file mode 100644 index 0000000..68ae714 --- /dev/null +++ b/src/main/java/dev/coredoes/maple/mixin/RenderSystemMixin.java @@ -0,0 +1,16 @@ +package dev.coredoes.maple.mixin; + +import com.mojang.blaze3d.systems.RenderSystem; +import dev.coredoes.maple.manager.GuiManager; +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(RenderSystem.class) +public class RenderSystemMixin { + @Inject(at = @At("HEAD"), method = "flipFrame") + private static void flipFrame(long window, CallbackInfo ci) { + GuiManager.INSTANCE.onFrame(); + } +} diff --git a/src/main/kotlin/dev/coredoes/maple/Manager.kt b/src/main/kotlin/dev/coredoes/maple/Manager.kt new file mode 100644 index 0000000..815d6ca --- /dev/null +++ b/src/main/kotlin/dev/coredoes/maple/Manager.kt @@ -0,0 +1,6 @@ +package dev.coredoes.maple + +interface Manager { + fun init() + fun stringName(): String +} \ No newline at end of file diff --git a/src/main/kotlin/dev/coredoes/maple/Maple.kt b/src/main/kotlin/dev/coredoes/maple/Maple.kt new file mode 100644 index 0000000..8428f21 --- /dev/null +++ b/src/main/kotlin/dev/coredoes/maple/Maple.kt @@ -0,0 +1,29 @@ +package dev.coredoes.maple + +import dev.coredoes.maple.event.EventManager +import dev.coredoes.maple.manager.GuiManager +import dev.coredoes.maple.manager.LOJoinChallengeManager +import dev.coredoes.maple.manager.ModuleManager +import net.fabricmc.api.ClientModInitializer +import org.slf4j.LoggerFactory + +object Maple : ClientModInitializer { + val logger = LoggerFactory.getLogger("maple") + val eventManager = EventManager() + + override fun onInitializeClient() { + logger.info("Hello, world!") + + val managers = arrayOf( + LOJoinChallengeManager, + ModuleManager, + GuiManager, + dev.coredoes.maple.manager.EventManager + ) + + for (i in managers.indices) { + logger.info("Initializing Maple... [Stage ${i+1}/${managers.size}: ${managers[i].stringName()}Init]") + managers[i].init() + } + } +} \ No newline at end of file diff --git a/src/main/kotlin/dev/coredoes/maple/event/EventHandler.kt b/src/main/kotlin/dev/coredoes/maple/event/EventHandler.kt new file mode 100644 index 0000000..1c78b8e --- /dev/null +++ b/src/main/kotlin/dev/coredoes/maple/event/EventHandler.kt @@ -0,0 +1,8 @@ +package dev.coredoes.maple.event + +/** + * Marks a function as an event handler. + * The function must have a single parameter of the event type. + */ +@Target(AnnotationTarget.FUNCTION) +annotation class EventHandler \ No newline at end of file diff --git a/src/main/kotlin/dev/coredoes/maple/event/EventManager.kt b/src/main/kotlin/dev/coredoes/maple/event/EventManager.kt new file mode 100644 index 0000000..295bd24 --- /dev/null +++ b/src/main/kotlin/dev/coredoes/maple/event/EventManager.kt @@ -0,0 +1,209 @@ +package dev.coredoes.maple.event + +import kotlinx.coroutines.sync.Mutex +import java.lang.reflect.Method +import kotlin.reflect.KClass +import kotlin.reflect.full.declaredFunctions +import kotlin.reflect.jvm.javaMethod +import kotlin.reflect.jvm.javaType + +typealias UnregisterFunc = () -> Unit +typealias EventHandlerFunc = (obj: T, unregister: UnregisterFunc) -> Any? +typealias EventTarget = Pair + +/** + * A simple event bus, similar to Bukkit and Orbit. + * + * There are two ways to receive events: + * - Register instances of classes with [registerClass], adding functions annotated with [EventHandler]. + * - Register functions directly with [registerFunc]. + * + * Define custom events in your own enum-like class, or use existing types (e.g. packet classes). + * + * ``` + * sealed class MyEvents { + * object SomethingHappened : MyEvents() + * class SomethingElseHappened(val data: String) : MyEvents() + * } + * ``` + */ +@Suppress("UNCHECKED_CAST") +class EventManager { + private val handlers: MutableMap, MutableList> = mutableMapOf() + private val functions: MutableMap, MutableList>> = mutableMapOf() + + private fun registerClassInternal(clazz: KClass<*>, obj: Any, register: Boolean) { + val methods = clazz.declaredFunctions.filter { func -> func.annotations.any { it is EventHandler } } + + for (method in methods) { + val paramType = method.parameters[1].type.javaType as Class<*> + val list = handlers.getOrPut(paramType) { mutableListOf() } + + if (register) { + list.add( + EventTarget( + obj, + method.javaMethod!! + ) + ) + } else { + list.removeIf { it.first == obj && it.second == method.javaMethod!! } + } + } + } + + private fun dispatchClassInternal(event: T): List { + val targetHandlers = handlers[event.javaClass] ?: listOf() + val ret = mutableListOf() + + for (target in targetHandlers) { + val response = target.second.invoke(target.first, event) + ret.add(response) + } + + return ret + } + + private fun dispatchFuncInternal(event: T): List { + val targetFunctions = functions[event.javaClass] ?: listOf() + val ret = mutableListOf() + + // Clone it so we don't ConcurrentModificationException + for (func in targetFunctions.toMutableList()) { + val funcCasted = func as EventHandlerFunc + var shouldUnregister = false + val response = funcCasted(event) { shouldUnregister = true } + ret.add(response) + + if (shouldUnregister) { + // Could call the internal function to remove it, but eh + functions[event.javaClass]?.remove(func) + } + } + + return ret + } + + /** + * Do not call this function directly. Use [registerFunc] and [unregisterFunc] instead. + * It is public because of inlined functions. + */ + fun > registerFuncInternal( + type: C, + func: EventHandlerFunc, + register: Boolean + ): EventHandlerFunc { + val list = functions.getOrPut(type.java) { mutableListOf() } + + if (register) { + list.add(func) + } else { + list.remove(func) + } + + return func + } + + /** + * Registers all functions with the [EventHandler] annotation in the specified class. + * + * ``` + * class MyClass { + * @EventHandler + * fun exampleFunction(event: String) { + * // Do something + * } + * } + * + * val clazz = MyClass() + * val eventHandler = EventManager() + * + * eventHandler.registerClass(clazz) + * eventHandler.dispatch("Hello, world!") + * ``` + * + * @param obj The class to register functions in. + */ + fun registerClass(obj: Any) = registerClassInternal(obj::class, obj, true) + + /** + * Unregisters all functions with the [EventHandler] annotation in the specified class. + * + * @param obj The class to unregister functions in. + */ + fun unregisterClass(obj: Any) = registerClassInternal(obj::class, obj, false) + + /** + * Registers a function to receive events of the specified type. + * + * The function will receive the event along with an unregister function. This can be called in your event handler + * logic to stop receiving events (e.g. one-time event handlers). + * + * ``` + * val eventManager = EventManager() + * + * eventManager.registerFunc(String::class) { str, _ -> + * println("String received (func one): $str") + * } + * + * eventManager.registerFunc(String::class) { str, unregister -> + * println("String received (func two): $str") + * unregister() // This function will no longer be called after this event + * } + * + * eventManager.dispatch("Hello, world!") + * eventManager.dispatch("Hello again, world!") + * ``` + * + * @param clazz The class of the event to receive. + * @param func The function to call when an event is dispatched. + */ + inline fun > registerFunc(clazz: C, noinline func: EventHandlerFunc) = + registerFuncInternal(clazz, func, true) + + /** + * Unregisters a function receiving events of the specified type. This is effectively the same as calling the + * unregister function inside the event handler. + * + * @param clazz The class of the event to stop receiving. + * @param func The associated event handler function. + */ + inline fun > unregisterFunc(clazz: C, noinline func: EventHandlerFunc) = + registerFuncInternal(clazz, func, false) + + /** + * Dispatches an event to all registered handlers, returning a list of all return values from each handler. + * Use the [filterIsInstance] function to filter to a specific type. + * + * @param event The event to dispatch. + * @return A list of all return values from each handler. + */ + fun dispatch(event: T): List { + val ret = mutableListOf() + ret.addAll(dispatchClassInternal(event)) + ret.addAll(dispatchFuncInternal(event)) + return ret + } + + /** + * Waits for an event of the specified type and returns it. + * + * @param obj The class of the event to wait for. + */ + suspend inline fun > waitForEvent(obj: C): T { + var value: T? = null + // This is a very fun way to solve this, I think + val receivedSignal = Mutex(true) + + val func = { e: T, unregister: UnregisterFunc -> + value = e + receivedSignal.unlock() + unregister() + } + + registerFunc(obj, func) + receivedSignal.lock() + + return value!! + } +} \ No newline at end of file diff --git a/src/main/kotlin/dev/coredoes/maple/event/MapleEvent.kt b/src/main/kotlin/dev/coredoes/maple/event/MapleEvent.kt new file mode 100644 index 0000000..5ad8f6d --- /dev/null +++ b/src/main/kotlin/dev/coredoes/maple/event/MapleEvent.kt @@ -0,0 +1,13 @@ +package dev.coredoes.maple.event + +import net.minecraft.network.packet.Packet + +sealed class MapleEvent { + data object PreTick : MapleEvent() + data object PostTick : MapleEvent() + + data class SendPacket(val packet: Packet<*>) : MapleEvent() + data class RecievePacket(val packet: Packet<*>) : MapleEvent() + + data object Draw : MapleEvent() +} \ No newline at end of file diff --git a/src/main/kotlin/dev/coredoes/maple/event/README b/src/main/kotlin/dev/coredoes/maple/event/README new file mode 100644 index 0000000..3fead80 --- /dev/null +++ b/src/main/kotlin/dev/coredoes/maple/event/README @@ -0,0 +1 @@ +stolen from hajlib \ No newline at end of file diff --git a/src/main/kotlin/dev/coredoes/maple/gui/MapleScreen.kt b/src/main/kotlin/dev/coredoes/maple/gui/MapleScreen.kt new file mode 100644 index 0000000..3e86796 --- /dev/null +++ b/src/main/kotlin/dev/coredoes/maple/gui/MapleScreen.kt @@ -0,0 +1,16 @@ +package dev.coredoes.maple.gui + +import dev.coredoes.maple.gui.panel.PanelManager +import net.minecraft.text.Text + +object MapleScreen : Screen(Text.of("Maple")) { + override fun shouldPause() = false + + override fun draw() { + PanelManager.draw() + } + + override fun close() { + super.close() + } +} \ No newline at end of file diff --git a/src/main/kotlin/dev/coredoes/maple/gui/ModMenu.kt b/src/main/kotlin/dev/coredoes/maple/gui/ModMenu.kt new file mode 100644 index 0000000..1e32b33 --- /dev/null +++ b/src/main/kotlin/dev/coredoes/maple/gui/ModMenu.kt @@ -0,0 +1,6 @@ +package dev.coredoes.maple.gui + + + +object ModMenu { +} \ No newline at end of file diff --git a/src/main/kotlin/dev/coredoes/maple/gui/Screen.kt b/src/main/kotlin/dev/coredoes/maple/gui/Screen.kt new file mode 100644 index 0000000..1b24ed0 --- /dev/null +++ b/src/main/kotlin/dev/coredoes/maple/gui/Screen.kt @@ -0,0 +1,45 @@ +package dev.coredoes.maple.gui + +import dev.coredoes.maple.Maple +import dev.coredoes.maple.event.MapleEvent +import dev.coredoes.maple.event.UnregisterFunc +import imgui.ImGui +import net.minecraft.client.gui.screen.Screen +import net.minecraft.text.Text + +open class Screen(title: Text) : Screen(title) { + var initialized: Boolean = false + + private val drawFun = { _: MapleEvent.Draw, _: UnregisterFunc -> this.draw() } + + open fun draw() {} + + override fun init() { + if (!initialized) { + Maple.eventManager.registerFunc(MapleEvent.Draw::class, drawFun) + + val io = ImGui.getIO() + + io.wantCaptureKeyboard = true + io.wantCaptureMouse = true + io.wantTextInput = true + + initialized = true + } + } + + override fun removed() { + if (initialized) { + Maple.eventManager.unregisterFunc(MapleEvent.Draw::class, drawFun) + + val io = ImGui.getIO() + io.wantCaptureKeyboard = false + io.wantCaptureMouse = false + io.wantTextInput = false + + initialized = false + } + + super.removed() + } +} \ No newline at end of file diff --git a/src/main/kotlin/dev/coredoes/maple/gui/panel/AboutPanel.kt b/src/main/kotlin/dev/coredoes/maple/gui/panel/AboutPanel.kt new file mode 100644 index 0000000..cd62554 --- /dev/null +++ b/src/main/kotlin/dev/coredoes/maple/gui/panel/AboutPanel.kt @@ -0,0 +1,28 @@ +package dev.coredoes.maple.gui.panel + +import imgui.ImGui +import imgui.extension.implot.ImPlot +import imgui.type.ImBoolean + +object AboutPanel : Panel { + private var showDemo = ImBoolean(false) + private var showPlotDemo = ImBoolean(false) + + override fun draw() { + ImGui.text("Maple is a really terrible Minecraft utility mod made by c0repwn3r.") + + ImGui.checkbox("Show ImGui demo window", showDemo) + ImGui.checkbox("Show ImPlot demo window", showPlotDemo) + + if (showDemo.get()) { + ImGui.showDemoWindow(showDemo) + } + if (showPlotDemo.get()) { + ImPlot.showDemoWindow(showPlotDemo) + } + } + + override fun getTitle(): String { + return "About" + } +} \ No newline at end of file diff --git a/src/main/kotlin/dev/coredoes/maple/gui/panel/Panel.kt b/src/main/kotlin/dev/coredoes/maple/gui/panel/Panel.kt new file mode 100644 index 0000000..4ea8447 --- /dev/null +++ b/src/main/kotlin/dev/coredoes/maple/gui/panel/Panel.kt @@ -0,0 +1,7 @@ +package dev.coredoes.maple.gui.panel + +interface Panel { + fun draw() + fun getTitle(): String + fun postDraw() {} +} \ No newline at end of file diff --git a/src/main/kotlin/dev/coredoes/maple/gui/panel/PanelManager.kt b/src/main/kotlin/dev/coredoes/maple/gui/panel/PanelManager.kt new file mode 100644 index 0000000..a172d6b --- /dev/null +++ b/src/main/kotlin/dev/coredoes/maple/gui/panel/PanelManager.kt @@ -0,0 +1,23 @@ +package dev.coredoes.maple.gui.panel + +import imgui.ImGui + +object PanelManager { + private var panels: Array = emptyArray() + + fun registerPanel(panel: Panel) { + panels = panels.plus(panel) + } + + fun draw() { + for (panel in panels) { + ImGui.begin(panel.getTitle()) + + panel.draw() + + ImGui.end() + + panel.postDraw() + } + } +} \ No newline at end of file diff --git a/src/main/kotlin/dev/coredoes/maple/manager/EventManager.kt b/src/main/kotlin/dev/coredoes/maple/manager/EventManager.kt new file mode 100644 index 0000000..3051369 --- /dev/null +++ b/src/main/kotlin/dev/coredoes/maple/manager/EventManager.kt @@ -0,0 +1,21 @@ +package dev.coredoes.maple.manager + +import dev.coredoes.maple.Manager +import dev.coredoes.maple.Maple +import dev.coredoes.maple.event.MapleEvent +import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents + +object EventManager : Manager { + override fun init() { + ClientTickEvents.START_CLIENT_TICK.register { + Maple.eventManager.dispatch(MapleEvent.PreTick) + } + ClientTickEvents.END_CLIENT_TICK.register { + Maple.eventManager.dispatch(MapleEvent.PostTick) + } + } + + override fun stringName(): String { + return "EventManager" + } +} \ No newline at end of file diff --git a/src/main/kotlin/dev/coredoes/maple/manager/GuiManager.kt b/src/main/kotlin/dev/coredoes/maple/manager/GuiManager.kt new file mode 100644 index 0000000..5e13b23 --- /dev/null +++ b/src/main/kotlin/dev/coredoes/maple/manager/GuiManager.kt @@ -0,0 +1,75 @@ +package dev.coredoes.maple.manager + +import dev.coredoes.maple.Manager +import dev.coredoes.maple.Maple +import dev.coredoes.maple.event.MapleEvent +import dev.coredoes.maple.gui.panel.AboutPanel +import dev.coredoes.maple.gui.panel.PanelManager +import imgui.ImFontConfig +import imgui.ImGui +import imgui.extension.implot.ImPlot +import imgui.flag.ImGuiConfigFlags +import imgui.gl3.ImGuiImplGl3 +import imgui.glfw.ImGuiImplGlfw +import net.fabricmc.loader.api.FabricLoader +import org.lwjgl.glfw.GLFW +import kotlin.properties.Delegates + +object GuiManager : Manager { + private val imguiGlfw = ImGuiImplGlfw() + private val imguiGl3 = ImGuiImplGl3() + private var windowHandle by Delegates.notNull() + + fun windowInit(handle: Long) { + ImGui.createContext() + + val io = ImGui.getIO() + + io.iniFilename = FabricLoader.getInstance().configDir.resolve("imgui.ini").toString() + io.addConfigFlags(ImGuiConfigFlags.NavEnableKeyboard or ImGuiConfigFlags.DockingEnable) + + val fontAtlas = io.fonts + val fontConfig = ImFontConfig() + + fontAtlas.addFontDefault() + + fontConfig.mergeMode = true + fontConfig.pixelSnapH = true + + fontConfig.destroy() + + imguiGl3.init("#version 130") + imguiGlfw.init(handle, true) + + windowHandle = handle + + ImPlot.createContext() + } + + fun onFrame() { + imguiGlfw.newFrame() + + ImGui.newFrame() + + Maple.eventManager.dispatch(MapleEvent.Draw) + + ImGui.render() + + imguiGl3.renderDrawData(ImGui.getDrawData()) + + val backupWindowPtr = GLFW.glfwGetCurrentContext() + + ImGui.updatePlatformWindows() + ImGui.renderPlatformWindowsDefault() + + GLFW.glfwMakeContextCurrent(backupWindowPtr) + } + + override fun init() { + PanelManager.registerPanel(AboutPanel) + } + + override fun stringName(): String { + return "Gui" + } +} \ No newline at end of file diff --git a/src/main/kotlin/dev/coredoes/maple/manager/LOJoinChallengeManager.kt b/src/main/kotlin/dev/coredoes/maple/manager/LOJoinChallengeManager.kt new file mode 100644 index 0000000..75403b8 --- /dev/null +++ b/src/main/kotlin/dev/coredoes/maple/manager/LOJoinChallengeManager.kt @@ -0,0 +1,23 @@ +package dev.coredoes.maple.manager + +import dev.coredoes.maple.Manager +import net.fabricmc.fabric.api.client.networking.v1.ClientLoginNetworking +import net.fabricmc.fabric.api.networking.v1.PacketByteBufs +import net.minecraft.util.Identifier +import java.util.concurrent.CompletableFuture + +object LOJoinChallengeManager : Manager { + override fun init() { + ClientLoginNetworking.registerGlobalReceiver(Identifier("liveoverflowmod:join")) { _, _, buf, _ -> + buf.readString() + val buf2 = PacketByteBufs.create() + buf2.writeInt(buf.readInt() + buf.readInt()) + val future = CompletableFuture.completedFuture(buf2) + future + } + } + + override fun stringName(): String { + return "LOJoinChallengeManager" + } +} \ No newline at end of file diff --git a/src/main/kotlin/dev/coredoes/maple/manager/ModuleManager.kt b/src/main/kotlin/dev/coredoes/maple/manager/ModuleManager.kt new file mode 100644 index 0000000..d118554 --- /dev/null +++ b/src/main/kotlin/dev/coredoes/maple/manager/ModuleManager.kt @@ -0,0 +1,30 @@ +package dev.coredoes.maple.manager + +import dev.coredoes.maple.Manager +import dev.coredoes.maple.module.BotMovement +import dev.coredoes.maple.module.Module + +object ModuleManager : Manager { + private val modules: MutableMap = mutableMapOf() + + override fun init() { + registerModule("botmovement", BotMovement) + } + + override fun stringName(): String { + return "ModuleManager" + } + + fun registerModule(id: String, module: Module) { + modules[id] = module + } + fun unregisterModule(id: String) { + modules.remove(id) + } + fun enableModule(id: String) { + modules[id]?.setEnabled(true) + } + fun disableModule(id: String) { + modules[id]?.setEnabled(false) + } +} \ No newline at end of file diff --git a/src/main/kotlin/dev/coredoes/maple/module/BotMovement.kt b/src/main/kotlin/dev/coredoes/maple/module/BotMovement.kt new file mode 100644 index 0000000..b92f013 --- /dev/null +++ b/src/main/kotlin/dev/coredoes/maple/module/BotMovement.kt @@ -0,0 +1,10 @@ +package dev.coredoes.maple.module + +object BotMovement : Module { + private var enabled = true + + override fun isEnabled(): Boolean { return enabled } + override fun setEnabled(enabled: Boolean) { + this.enabled = enabled + } +} \ No newline at end of file diff --git a/src/main/kotlin/dev/coredoes/maple/module/Module.kt b/src/main/kotlin/dev/coredoes/maple/module/Module.kt new file mode 100644 index 0000000..cb087e4 --- /dev/null +++ b/src/main/kotlin/dev/coredoes/maple/module/Module.kt @@ -0,0 +1,14 @@ +package dev.coredoes.maple.module + +import dev.coredoes.maple.manager.ModuleManager + +interface Module { + fun onRegister(manager: ModuleManager) {} + fun onUnregister(manager: ModuleManager) {} + + fun onEnable(manager: ModuleManager) {} + fun onDisable(manager: ModuleManager) {} + + fun isEnabled(): Boolean { return false } + fun setEnabled(enabled: Boolean) {} +} \ No newline at end of file diff --git a/src/main/kotlin/dev/coredoes/maple/util/BrandRetriever.kt b/src/main/kotlin/dev/coredoes/maple/util/BrandRetriever.kt new file mode 100644 index 0000000..84872d9 --- /dev/null +++ b/src/main/kotlin/dev/coredoes/maple/util/BrandRetriever.kt @@ -0,0 +1,9 @@ +package dev.coredoes.maple.util + +class BrandRetriever { + companion object { + fun retrieveBrand(): String { + return System.getProperty("client-brand") ?: "vanilla" + } + } +} \ No newline at end of file diff --git a/src/main/resources/fabric.mod.json b/src/main/resources/fabric.mod.json new file mode 100644 index 0000000..af608dd --- /dev/null +++ b/src/main/resources/fabric.mod.json @@ -0,0 +1,35 @@ +{ + "schemaVersion": 1, + "id": "maple", + "version": "${version}", + "name": "maple", + "description": "minecraft utility mod", + "authors": [ + "c0repwn3r" + ], + "contact": { + "homepage": "https://coredoes.dev", + "sources": "https://git.e3t.cc/~core/maple" + }, + "license": "All rights reserved", + "icon": "assets/maple/icon.png", + "environment": "client", + "entrypoints": { + "client": [ + { + "value": "dev.coredoes.maple.Maple", + "adapter": "kotlin" + } + ] + }, + "mixins": [ + "maple.mixins.json" + ], + "depends": { + "fabricloader": ">=0.14.21", + "minecraft": "~1.20.1", + "java": ">=17", + "fabric-api": "*", + "fabric-language-kotlin": ">=1.9.0" + } +} \ No newline at end of file diff --git a/src/main/resources/maple.mixins.json b/src/main/resources/maple.mixins.json new file mode 100644 index 0000000..26ba4ce --- /dev/null +++ b/src/main/resources/maple.mixins.json @@ -0,0 +1,18 @@ +{ + "required": true, + "package": "dev.coredoes.maple.mixin", + "compatibilityLevel": "JAVA_17", + "mixins": [ + "ClientConnectionMixin", + "PlayerMoveC2SPacketMixin" + ], + "injectors": { + "defaultRequire": 1 + }, + "client": [ + "ClientBrandRetrieverMixin", + "InputUtilMixin", + "KeyboardMixin", + "RenderSystemMixin" + ] +} \ No newline at end of file