Create features system with Flight, No Fall Damage
parent
ab0e18e2c8
commit
ceac1fda7a
|
@ -1,7 +1,11 @@
|
||||||
|
import org.gradle.kotlin.dsl.accessors.runtime.extensionOf
|
||||||
|
import org.quiltmc.quiltmappings.loom.QuiltMappingsOnLoomPlugin
|
||||||
|
|
||||||
plugins {
|
plugins {
|
||||||
id("fabric-loom")
|
id("fabric-loom")
|
||||||
val kotlinVersion: String by System.getProperties()
|
val kotlinVersion: String by System.getProperties()
|
||||||
kotlin("jvm").version(kotlinVersion)
|
kotlin("jvm").version(kotlinVersion)
|
||||||
|
id("org.quiltmc.quilt-mappings-on-loom").version("3.1.1")
|
||||||
}
|
}
|
||||||
|
|
||||||
base {
|
base {
|
||||||
|
@ -21,8 +25,25 @@ repositories {}
|
||||||
dependencies {
|
dependencies {
|
||||||
val minecraftVersion: String by project
|
val minecraftVersion: String by project
|
||||||
minecraft("com.mojang:minecraft:$minecraftVersion")
|
minecraft("com.mojang:minecraft:$minecraftVersion")
|
||||||
|
|
||||||
|
val USE_QUILT_MAPPINGS = false
|
||||||
|
if (USE_QUILT_MAPPINGS) {
|
||||||
|
// Seems to crash on startup right now
|
||||||
|
|
||||||
|
val quiltMappings: String by project
|
||||||
|
mappings(loom.layered {
|
||||||
|
officialMojangMappings {
|
||||||
|
nameSyntheticMembers = false
|
||||||
|
}
|
||||||
|
|
||||||
|
val qm = extensionOf(project, "quiltMappings") as QuiltMappingsOnLoomPlugin.QuiltMappingsOnLoomExtension
|
||||||
|
addLayer(qm.mappings("org.quiltmc:quilt-mappings:${quiltMappings}:v2"))
|
||||||
|
})
|
||||||
|
} else {
|
||||||
val yarnMappings: String by project
|
val yarnMappings: String by project
|
||||||
mappings("net.fabricmc:yarn:$yarnMappings:v2")
|
mappings("net.fabricmc:yarn:$yarnMappings:v2")
|
||||||
|
}
|
||||||
|
|
||||||
val loaderVersion: String by project
|
val loaderVersion: String by project
|
||||||
modImplementation("net.fabricmc:fabric-loader:$loaderVersion")
|
modImplementation("net.fabricmc:fabric-loader:$loaderVersion")
|
||||||
val fabricVersion: String by project
|
val fabricVersion: String by project
|
||||||
|
@ -49,7 +70,11 @@ tasks {
|
||||||
}
|
}
|
||||||
|
|
||||||
withType<org.jetbrains.kotlin.gradle.tasks.KotlinCompile> {
|
withType<org.jetbrains.kotlin.gradle.tasks.KotlinCompile> {
|
||||||
kotlinOptions { jvmTarget = javaVersion.toString() }
|
kotlinOptions {
|
||||||
|
jvmTarget = javaVersion.toString()
|
||||||
|
freeCompilerArgs = freeCompilerArgs + listOf("-Xopt-in=kotlin.RequiresOptIn")
|
||||||
|
}
|
||||||
|
|
||||||
sourceCompatibility = javaVersion.toString()
|
sourceCompatibility = javaVersion.toString()
|
||||||
targetCompatibility = javaVersion.toString()
|
targetCompatibility = javaVersion.toString()
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,7 @@ org.gradle.warning.mode=all
|
||||||
# Check these on https://fabricmc.net/develop/
|
# Check these on https://fabricmc.net/develop/
|
||||||
minecraftVersion=1.18.1
|
minecraftVersion=1.18.1
|
||||||
yarnMappings=1.18.1+build.22
|
yarnMappings=1.18.1+build.22
|
||||||
|
quiltMappings=1.18.1+build.6
|
||||||
loaderVersion=0.12.12
|
loaderVersion=0.12.12
|
||||||
# Fabric API
|
# Fabric API
|
||||||
fabricVersion=0.46.1+1.18
|
fabricVersion=0.46.1+1.18
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
pluginManagement {
|
pluginManagement {
|
||||||
repositories {
|
repositories {
|
||||||
maven("https://maven.fabricmc.net") { name = "Fabric" }
|
maven("https://maven.fabricmc.net") { name = "Fabric" }
|
||||||
|
maven("https://maven.quiltmc.org/repository/release") { name = "Quilt" }
|
||||||
mavenCentral()
|
mavenCentral()
|
||||||
gradlePluginPortal()
|
gradlePluginPortal()
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,22 @@
|
||||||
|
package codes.som.hibiscus.mixins;
|
||||||
|
|
||||||
|
import codes.som.hibiscus.HibiscusMod;
|
||||||
|
import codes.som.hibiscus.events.SendPacketEvent;
|
||||||
|
import net.minecraft.client.network.ClientPlayNetworkHandler;
|
||||||
|
import net.minecraft.network.ClientConnection;
|
||||||
|
import net.minecraft.network.Packet;
|
||||||
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
|
import org.spongepowered.asm.mixin.injection.At;
|
||||||
|
import org.spongepowered.asm.mixin.injection.Redirect;
|
||||||
|
|
||||||
|
@Mixin(ClientPlayNetworkHandler.class)
|
||||||
|
public abstract class MixinClientPlayNetworkHandler {
|
||||||
|
@Redirect(method = "sendPacket", at = @At(value = "INVOKE", target = "Lnet/minecraft/network/ClientConnection;send(Lnet/minecraft/network/Packet;)V"))
|
||||||
|
public void onSendPacket(ClientConnection clientConnection, Packet<?> packet) {
|
||||||
|
var event = new SendPacketEvent(packet);
|
||||||
|
HibiscusMod.bus().fire(event);
|
||||||
|
if (!event.isCancelled()) {
|
||||||
|
clientConnection.send(event.getPacket());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,38 @@
|
||||||
|
package codes.som.hibiscus.mixins;
|
||||||
|
|
||||||
|
import net.minecraft.client.network.ClientPlayerEntity;
|
||||||
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
|
import org.spongepowered.asm.mixin.gen.Accessor;
|
||||||
|
|
||||||
|
@Mixin(ClientPlayerEntity.class)
|
||||||
|
public interface MixinExtClientPlayerEntity {
|
||||||
|
@Accessor
|
||||||
|
double getLastX();
|
||||||
|
|
||||||
|
@Accessor
|
||||||
|
void setLastX(double lastX);
|
||||||
|
|
||||||
|
@Accessor
|
||||||
|
double getLastBaseY();
|
||||||
|
|
||||||
|
@Accessor
|
||||||
|
void setLastBaseY(double lastBaseY);
|
||||||
|
|
||||||
|
@Accessor
|
||||||
|
double getLastZ();
|
||||||
|
|
||||||
|
@Accessor
|
||||||
|
void setLastZ(double lastZ);
|
||||||
|
|
||||||
|
@Accessor
|
||||||
|
float getLastYaw();
|
||||||
|
|
||||||
|
@Accessor
|
||||||
|
void setLastYaw(float lastYaw);
|
||||||
|
|
||||||
|
@Accessor
|
||||||
|
float getLastPitch();
|
||||||
|
|
||||||
|
@Accessor
|
||||||
|
void setLastPitch(float lastPitch);
|
||||||
|
}
|
|
@ -0,0 +1,13 @@
|
||||||
|
package codes.som.hibiscus.mixins;
|
||||||
|
|
||||||
|
import net.minecraft.network.packet.c2s.play.PlayerMoveC2SPacket;
|
||||||
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
|
import org.spongepowered.asm.mixin.Mutable;
|
||||||
|
import org.spongepowered.asm.mixin.gen.Accessor;
|
||||||
|
|
||||||
|
@Mixin(PlayerMoveC2SPacket.class)
|
||||||
|
public interface MixinExtPlayerMoveC2SPacket {
|
||||||
|
@Accessor
|
||||||
|
@Mutable
|
||||||
|
void setOnGround(boolean onGround);
|
||||||
|
}
|
|
@ -0,0 +1,13 @@
|
||||||
|
package codes.som.hibiscus.mixins;
|
||||||
|
|
||||||
|
import net.minecraft.network.packet.c2s.play.UpdatePlayerAbilitiesC2SPacket;
|
||||||
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
|
import org.spongepowered.asm.mixin.Mutable;
|
||||||
|
import org.spongepowered.asm.mixin.gen.Accessor;
|
||||||
|
|
||||||
|
@Mixin(UpdatePlayerAbilitiesC2SPacket.class)
|
||||||
|
public interface MixinExtUpdatePlayerAbilitiesC2SPacket {
|
||||||
|
@Accessor
|
||||||
|
@Mutable
|
||||||
|
void setFlying(boolean flying);
|
||||||
|
}
|
|
@ -0,0 +1,45 @@
|
||||||
|
package codes.som.hibiscus.mixins;
|
||||||
|
|
||||||
|
import codes.som.hibiscus.HibiscusMod;
|
||||||
|
import codes.som.hibiscus.events.RenderOverlayEvent;
|
||||||
|
import codes.som.hibiscus.gui.ImGuiRenderer;
|
||||||
|
import net.minecraft.client.MinecraftClient;
|
||||||
|
import net.minecraft.client.RunArgs;
|
||||||
|
import net.minecraft.client.render.RenderTickCounter;
|
||||||
|
import org.spongepowered.asm.mixin.Final;
|
||||||
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
|
import org.spongepowered.asm.mixin.Shadow;
|
||||||
|
import org.spongepowered.asm.mixin.injection.At;
|
||||||
|
import org.spongepowered.asm.mixin.injection.Inject;
|
||||||
|
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||||
|
|
||||||
|
@Mixin(MinecraftClient.class)
|
||||||
|
public abstract class MixinMinecraftClient {
|
||||||
|
@Shadow
|
||||||
|
private volatile boolean paused;
|
||||||
|
|
||||||
|
@Shadow
|
||||||
|
private float pausedTickDelta;
|
||||||
|
|
||||||
|
@Shadow
|
||||||
|
@Final
|
||||||
|
private RenderTickCounter renderTickCounter;
|
||||||
|
|
||||||
|
@Inject(method = "<init>", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/screen/SplashOverlay;init(Lnet/minecraft/client/MinecraftClient;)V", shift = At.Shift.BEFORE))
|
||||||
|
private void onFinishingStartup(RunArgs args, CallbackInfo ci) {
|
||||||
|
ImGuiRenderer.INSTANCE.setup();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Inject(method = "render", at = @At(value = "FIELD", target = "Lnet/minecraft/client/MinecraftClient;skipGameRender:Z", shift = At.Shift.BEFORE))
|
||||||
|
private void onPreRenderEverything(boolean tick, CallbackInfo ci) {
|
||||||
|
float delta = this.paused ? this.pausedTickDelta : this.renderTickCounter.tickDelta;
|
||||||
|
ImGuiRenderer.INSTANCE.beginFrame(delta);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Inject(method = "render", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gl/Framebuffer;endWrite()V", shift = At.Shift.BEFORE))
|
||||||
|
private void onPostRenderEverything(boolean tick, CallbackInfo ci) {
|
||||||
|
float delta = this.paused ? this.pausedTickDelta : this.renderTickCounter.tickDelta;
|
||||||
|
HibiscusMod.bus().fire(new RenderOverlayEvent(delta));
|
||||||
|
ImGuiRenderer.INSTANCE.finishFrame(delta);
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,19 +1,26 @@
|
||||||
package site.hackery.unknit;
|
package site.hackery.unknit;
|
||||||
|
|
||||||
|
|
||||||
import com.mojang.authlib.*;
|
import com.mojang.authlib.Agent;
|
||||||
import com.mojang.authlib.exceptions.*;
|
import com.mojang.authlib.GameProfile;
|
||||||
import com.mojang.authlib.yggdrasil.*;
|
import com.mojang.authlib.exceptions.AuthenticationException;
|
||||||
import com.mojang.util.*;
|
import com.mojang.authlib.yggdrasil.YggdrasilAuthenticationService;
|
||||||
import net.minecraft.client.main.*;
|
import com.mojang.authlib.yggdrasil.YggdrasilUserAuthentication;
|
||||||
import net.minecraft.client.util.*;
|
import com.mojang.util.UUIDTypeAdapter;
|
||||||
import org.spongepowered.asm.mixin.*;
|
import net.minecraft.client.main.Main;
|
||||||
import org.spongepowered.asm.mixin.injection.*;
|
import net.minecraft.client.util.Session;
|
||||||
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
|
import org.spongepowered.asm.mixin.injection.At;
|
||||||
|
import org.spongepowered.asm.mixin.injection.ModifyVariable;
|
||||||
|
|
||||||
import java.io.*;
|
import java.io.IOException;
|
||||||
import java.net.*;
|
import java.net.Proxy;
|
||||||
import java.nio.file.*;
|
import java.nio.file.Files;
|
||||||
import java.util.*;
|
import java.nio.file.Paths;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
@Mixin(Main.class)
|
@Mixin(Main.class)
|
||||||
public abstract class MixinMinecraftMain {
|
public abstract class MixinMinecraftMain {
|
||||||
|
@ -24,7 +31,7 @@ public abstract class MixinMinecraftMain {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ModifyVariable(method = "main", at = @At("HEAD"), argsOnly = true)
|
@ModifyVariable(method = "main", at = @At("HEAD"), argsOnly = true, remap = false)
|
||||||
private static String[] setArgs(String[] args) {
|
private static String[] setArgs(String[] args) {
|
||||||
List<String> arguments = new ArrayList<>(Arrays.asList(args));
|
List<String> arguments = new ArrayList<>(Arrays.asList(args));
|
||||||
replace(arguments, "--version", "1.18.1");
|
replace(arguments, "--version", "1.18.1");
|
||||||
|
|
|
@ -2,7 +2,9 @@ package codes.som.hibiscus
|
||||||
|
|
||||||
import codes.som.hibiscus.api.event.EventBus
|
import codes.som.hibiscus.api.event.EventBus
|
||||||
import codes.som.hibiscus.events.KeyEvent
|
import codes.som.hibiscus.events.KeyEvent
|
||||||
|
import codes.som.hibiscus.features.FeaturesRegistry
|
||||||
import codes.som.hibiscus.gui.ImGuiScreen
|
import codes.som.hibiscus.gui.ImGuiScreen
|
||||||
|
import codes.som.hibiscus.util.netmoving.NetworkMovingDispatcher
|
||||||
import net.fabricmc.api.ModInitializer
|
import net.fabricmc.api.ModInitializer
|
||||||
import org.lwjgl.glfw.GLFW
|
import org.lwjgl.glfw.GLFW
|
||||||
import org.lwjgl.glfw.GLFW.GLFW_KEY_RIGHT_SHIFT
|
import org.lwjgl.glfw.GLFW.GLFW_KEY_RIGHT_SHIFT
|
||||||
|
@ -15,9 +17,15 @@ object HibiscusMod : ModInitializer {
|
||||||
@get:JvmName("bus")
|
@get:JvmName("bus")
|
||||||
val bus = EventBus()
|
val bus = EventBus()
|
||||||
|
|
||||||
|
val features = FeaturesRegistry()
|
||||||
|
|
||||||
override fun onInitialize() {
|
override fun onInitialize() {
|
||||||
bus.register { key: KeyEvent ->
|
bus.register(NetworkMovingDispatcher())
|
||||||
if (key.key != GLFW_KEY_RIGHT_SHIFT || key.action != GLFW.GLFW_PRESS)
|
bus.register { event: KeyEvent ->
|
||||||
|
if (event.key != GLFW_KEY_RIGHT_SHIFT || event.action != GLFW.GLFW_PRESS)
|
||||||
|
return@register
|
||||||
|
|
||||||
|
if (mc.currentScreen != null)
|
||||||
return@register
|
return@register
|
||||||
|
|
||||||
mc.setScreen(ImGuiScreen)
|
mc.setScreen(ImGuiScreen)
|
||||||
|
|
|
@ -1,5 +1,9 @@
|
||||||
package codes.som.hibiscus
|
package codes.som.hibiscus
|
||||||
|
|
||||||
import net.minecraft.client.MinecraftClient
|
import net.minecraft.client.MinecraftClient
|
||||||
|
import net.minecraft.client.network.ClientPlayerEntity
|
||||||
|
import net.minecraft.client.world.ClientWorld
|
||||||
|
|
||||||
val mc: MinecraftClient inline get() = MinecraftClient.getInstance()
|
val mc: MinecraftClient inline get() = MinecraftClient.getInstance()
|
||||||
|
val player: ClientPlayerEntity inline get() = mc.player!!
|
||||||
|
val world: ClientWorld inline get() = mc.world!!
|
||||||
|
|
|
@ -0,0 +1,10 @@
|
||||||
|
package codes.som.hibiscus.api.event
|
||||||
|
|
||||||
|
abstract class Cancellable {
|
||||||
|
@get:JvmName("isCancelled")
|
||||||
|
var cancelled: Boolean = false
|
||||||
|
|
||||||
|
fun cancel() {
|
||||||
|
cancelled = true
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,13 @@
|
||||||
|
@file:Suppress("NOTHING_TO_INLINE")
|
||||||
|
|
||||||
|
package codes.som.hibiscus.api.event
|
||||||
|
|
||||||
|
abstract class TypedListener<T : Event>(val eventType: Class<T>) : Listener<T>
|
||||||
|
|
||||||
|
inline fun <T : Event> EventBus.registerTyped(typedListener: TypedListener<T>) {
|
||||||
|
register(typedListener.eventType, typedListener)
|
||||||
|
}
|
||||||
|
|
||||||
|
inline fun <T : Event> EventBus.unregisterTyped(typedListener: TypedListener<T>) {
|
||||||
|
unregister(typedListener.eventType, typedListener)
|
||||||
|
}
|
|
@ -0,0 +1,37 @@
|
||||||
|
package codes.som.hibiscus.api.feature
|
||||||
|
|
||||||
|
import codes.som.hibiscus.HibiscusMod
|
||||||
|
import codes.som.hibiscus.api.event.*
|
||||||
|
import codes.som.hibiscus.api.feature.values.ValueRegistry
|
||||||
|
|
||||||
|
abstract class Feature(val name: String, val category: FeatureCategory) {
|
||||||
|
private val listeners = mutableListOf<TypedListener<*>>()
|
||||||
|
|
||||||
|
protected inline fun <reified T : Event> on(listener: Listener<T>) =
|
||||||
|
on(object : TypedListener<T>(T::class.java), Listener<T> by listener {})
|
||||||
|
|
||||||
|
protected fun <T : Event> on(listener: TypedListener<T>) =
|
||||||
|
listeners.add(listener)
|
||||||
|
|
||||||
|
val values = ValueRegistry()
|
||||||
|
|
||||||
|
var enabled: Boolean = false
|
||||||
|
set(value) {
|
||||||
|
val hasChanged = value != field
|
||||||
|
if (hasChanged) {
|
||||||
|
field = value
|
||||||
|
if (value) {
|
||||||
|
onEnable()
|
||||||
|
listeners.forEach { HibiscusMod.bus.registerTyped(it) }
|
||||||
|
} else {
|
||||||
|
listeners.forEach { HibiscusMod.bus.unregisterTyped(it) }
|
||||||
|
onDisable()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
open fun onEnable() {}
|
||||||
|
open fun onDisable() {}
|
||||||
|
|
||||||
|
// TODO: Module commands
|
||||||
|
}
|
|
@ -0,0 +1,6 @@
|
||||||
|
package codes.som.hibiscus.api.feature
|
||||||
|
|
||||||
|
enum class FeatureCategory(val humanName: String) {
|
||||||
|
PLAYER("Player"),
|
||||||
|
MOVEMENT("Movement"),
|
||||||
|
}
|
|
@ -0,0 +1,11 @@
|
||||||
|
package codes.som.hibiscus.api.feature.values
|
||||||
|
|
||||||
|
import codes.som.hibiscus.gui.ImGuiKt
|
||||||
|
|
||||||
|
class BooleanValue(name: String, value: Boolean) : RegisteredValue<Boolean>(name, value) {
|
||||||
|
override fun convertValueFromString(representation: String) = representation.toBoolean()
|
||||||
|
|
||||||
|
override fun drawUIControl() {
|
||||||
|
ImGuiKt.checkbox(name, ::value)
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,23 @@
|
||||||
|
package codes.som.hibiscus.api.feature.values
|
||||||
|
|
||||||
|
import codes.som.hibiscus.gui.ImGuiKt
|
||||||
|
|
||||||
|
class FloatValue(
|
||||||
|
name: String, value: Float,
|
||||||
|
val min: Float = Float.MIN_VALUE, val max: Float = Float.MAX_VALUE
|
||||||
|
) : RegisteredValue<Float>(name, value) {
|
||||||
|
override fun valueChangeHook(orig: Float, new: Float) =
|
||||||
|
new.coerceIn(min, max)
|
||||||
|
|
||||||
|
override fun convertValueFromString(representation: String): Float {
|
||||||
|
return representation.toFloat()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun drawUIControl() {
|
||||||
|
if (min == Float.MIN_VALUE || max == Float.MAX_VALUE) {
|
||||||
|
ImGuiKt.dragFloat(name, ::value, 1f, min, max)
|
||||||
|
} else {
|
||||||
|
ImGuiKt.sliderFloat(name, ::value, min, max)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,23 @@
|
||||||
|
package codes.som.hibiscus.api.feature.values
|
||||||
|
|
||||||
|
import codes.som.hibiscus.gui.ImGuiKt
|
||||||
|
|
||||||
|
class IntegerValue(
|
||||||
|
name: String, value: Int,
|
||||||
|
val min: Int = Int.MIN_VALUE, val max: Int = Int.MAX_VALUE
|
||||||
|
) : RegisteredValue<Int>(name, value) {
|
||||||
|
override fun valueChangeHook(orig: Int, new: Int) =
|
||||||
|
new.coerceIn(min, max)
|
||||||
|
|
||||||
|
override fun convertValueFromString(representation: String): Int {
|
||||||
|
return representation.toInt()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun drawUIControl() {
|
||||||
|
if (min == Int.MIN_VALUE || max == Int.MAX_VALUE) {
|
||||||
|
ImGuiKt.dragInt(name, ::value, 1f, min.toFloat(), max.toFloat())
|
||||||
|
} else {
|
||||||
|
ImGuiKt.sliderInt(name, ::value, min, max)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,18 @@
|
||||||
|
package codes.som.hibiscus.api.feature.values
|
||||||
|
|
||||||
|
import codes.som.hibiscus.util.input.Keys
|
||||||
|
import org.lwjgl.glfw.GLFW
|
||||||
|
|
||||||
|
class KeyboardValue(name: String, value: Int = GLFW.GLFW_KEY_UNKNOWN) : RegisteredValue<Int>(name, value) {
|
||||||
|
override fun convertValueFromString(representation: String): Int {
|
||||||
|
return Keys.KEY_MAP[representation.toUpperCase()] ?: -1
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getValueAsString(): String {
|
||||||
|
return Keys.KEY_MAP.inverse()[value] ?: "UNKNOWN"
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun drawUIControl() {
|
||||||
|
// TODO
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,25 @@
|
||||||
|
package codes.som.hibiscus.api.feature.values
|
||||||
|
|
||||||
|
import kotlin.reflect.KProperty
|
||||||
|
|
||||||
|
abstract class RegisteredValue<T>(val name: String, value: T) {
|
||||||
|
var value: T = value
|
||||||
|
set(value) {
|
||||||
|
field = valueChangeHook(field, value)
|
||||||
|
}
|
||||||
|
|
||||||
|
open fun valueChangeHook(orig: T, new: T): T = new
|
||||||
|
|
||||||
|
open fun getValueAsString(): String = value.toString()
|
||||||
|
abstract fun convertValueFromString(representation: String): T
|
||||||
|
fun setValueFromString(representation: String) {
|
||||||
|
value = convertValueFromString(representation)
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract fun drawUIControl()
|
||||||
|
|
||||||
|
operator fun getValue(thisRef: Any?, property: KProperty<*>): T = value
|
||||||
|
operator fun setValue(thisRef: Any?, property: KProperty<*>, value: T) {
|
||||||
|
this.value = value
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,21 @@
|
||||||
|
package codes.som.hibiscus.api.feature.values
|
||||||
|
|
||||||
|
import imgui.ImGui
|
||||||
|
import imgui.type.ImString
|
||||||
|
|
||||||
|
class StringValue(name: String, value: String) : RegisteredValue<String>(name, value) {
|
||||||
|
override fun convertValueFromString(representation: String) = representation
|
||||||
|
|
||||||
|
private val uiState = ImString(256)
|
||||||
|
private var lastValue = value
|
||||||
|
|
||||||
|
override fun drawUIControl() {
|
||||||
|
if (value != lastValue) {
|
||||||
|
uiState.set(value)
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui.inputText(name, uiState)
|
||||||
|
value = uiState.get()
|
||||||
|
lastValue = value
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,29 @@
|
||||||
|
package codes.som.hibiscus.api.feature.values
|
||||||
|
|
||||||
|
import org.lwjgl.glfw.GLFW
|
||||||
|
|
||||||
|
class ValueRegistry {
|
||||||
|
private val registeredValues = mutableListOf<RegisteredValue<*>>()
|
||||||
|
|
||||||
|
fun register(value: RegisteredValue<*>) {
|
||||||
|
registeredValues.add(value)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun exist() = registeredValues.isNotEmpty()
|
||||||
|
operator fun iterator() = registeredValues.iterator()
|
||||||
|
|
||||||
|
fun string(name: String, default: String) =
|
||||||
|
StringValue(name, default).also(this::register)
|
||||||
|
|
||||||
|
fun bool(name: String, default: Boolean) =
|
||||||
|
BooleanValue(name, default).also(this::register)
|
||||||
|
|
||||||
|
fun int(name: String, default: Int, min: Int = Int.MIN_VALUE, max: Int = Int.MAX_VALUE) =
|
||||||
|
IntegerValue(name, default, min, max).also(this::register)
|
||||||
|
|
||||||
|
fun key(name: String, default: Int = GLFW.GLFW_KEY_UNKNOWN) =
|
||||||
|
KeyboardValue(name, default).also(this::register)
|
||||||
|
|
||||||
|
fun float(name: String, default: Float, min: Float = Float.MIN_VALUE, max: Float = Float.MAX_VALUE) =
|
||||||
|
FloatValue(name, default, min, max).also(this::register)
|
||||||
|
}
|
|
@ -0,0 +1,15 @@
|
||||||
|
package codes.som.hibiscus.events
|
||||||
|
|
||||||
|
import codes.som.hibiscus.api.event.Cancellable
|
||||||
|
import codes.som.hibiscus.api.event.Event
|
||||||
|
import net.minecraft.network.Packet
|
||||||
|
|
||||||
|
data class SendPacketEvent(var packet: Packet<*>) : Cancellable(), Event
|
||||||
|
class NetworkMovingEvent(
|
||||||
|
var x: Double,
|
||||||
|
var y: Double,
|
||||||
|
var z: Double,
|
||||||
|
var yaw: Float,
|
||||||
|
var pitch: Float,
|
||||||
|
var onGround: Boolean
|
||||||
|
) : Cancellable(), Event
|
|
@ -0,0 +1,5 @@
|
||||||
|
package codes.som.hibiscus.events
|
||||||
|
|
||||||
|
import codes.som.hibiscus.api.event.Event
|
||||||
|
|
||||||
|
class RenderOverlayEvent(val delta: Float) : Event
|
|
@ -0,0 +1,10 @@
|
||||||
|
package codes.som.hibiscus.features
|
||||||
|
|
||||||
|
import codes.som.hibiscus.api.feature.Feature
|
||||||
|
import codes.som.hibiscus.features.movement.Flight
|
||||||
|
import codes.som.hibiscus.features.player.NoFallDamage
|
||||||
|
|
||||||
|
val ALL_FEATURES: Array<() -> Feature> = arrayOf(
|
||||||
|
::NoFallDamage,
|
||||||
|
::Flight,
|
||||||
|
)
|
|
@ -0,0 +1,7 @@
|
||||||
|
package codes.som.hibiscus.features
|
||||||
|
|
||||||
|
class FeaturesRegistry {
|
||||||
|
private val features = ALL_FEATURES.map { it() }
|
||||||
|
|
||||||
|
fun getAllFeatures() = features.asSequence()
|
||||||
|
}
|
|
@ -0,0 +1,79 @@
|
||||||
|
package codes.som.hibiscus.features.movement
|
||||||
|
|
||||||
|
import codes.som.hibiscus.api.feature.Feature
|
||||||
|
import codes.som.hibiscus.api.feature.FeatureCategory
|
||||||
|
import codes.som.hibiscus.events.NetworkMovingEvent
|
||||||
|
import codes.som.hibiscus.events.PlayerTickEvent
|
||||||
|
import codes.som.hibiscus.events.SendPacketEvent
|
||||||
|
import codes.som.hibiscus.mc
|
||||||
|
import codes.som.hibiscus.mixins.MixinExtUpdatePlayerAbilitiesC2SPacket
|
||||||
|
import codes.som.hibiscus.player
|
||||||
|
import codes.som.hibiscus.util.ext.requireExtension
|
||||||
|
import codes.som.hibiscus.world
|
||||||
|
import net.minecraft.network.packet.c2s.play.ClientCommandC2SPacket
|
||||||
|
import net.minecraft.network.packet.c2s.play.UpdatePlayerAbilitiesC2SPacket
|
||||||
|
import net.minecraft.util.shape.VoxelShape
|
||||||
|
|
||||||
|
class Flight : Feature("Flight", FeatureCategory.MOVEMENT) {
|
||||||
|
private var flyKickCounter = 0
|
||||||
|
private var lockY = 0.0
|
||||||
|
|
||||||
|
init {
|
||||||
|
on { _: PlayerTickEvent ->
|
||||||
|
player.abilities.flying = true
|
||||||
|
}
|
||||||
|
|
||||||
|
val interceptServerboundAbilityPackets by values.bool("Intercept Serverbound Ability Packets", true)
|
||||||
|
val vanillaKickBypass by values.bool("Vanilla Kick Bypass", false)
|
||||||
|
|
||||||
|
on { event: SendPacketEvent ->
|
||||||
|
val (packet) = event
|
||||||
|
|
||||||
|
if (!interceptServerboundAbilityPackets)
|
||||||
|
return@on
|
||||||
|
|
||||||
|
if (packet is UpdatePlayerAbilitiesC2SPacket) {
|
||||||
|
requireExtension<MixinExtUpdatePlayerAbilitiesC2SPacket>(packet)
|
||||||
|
packet.setFlying(player.abilities.allowFlying)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (packet is ClientCommandC2SPacket) {
|
||||||
|
if (packet.mode == ClientCommandC2SPacket.Mode.PRESS_SHIFT_KEY) {
|
||||||
|
event.cancel()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
on { event: NetworkMovingEvent ->
|
||||||
|
if (!vanillaKickBypass)
|
||||||
|
return@on
|
||||||
|
|
||||||
|
flyKickCounter++
|
||||||
|
|
||||||
|
if (flyKickCounter >= 16) {
|
||||||
|
if (flyKickCounter == 16)
|
||||||
|
lockY = event.y - 0.03126
|
||||||
|
|
||||||
|
if (world.getBlockCollisions(
|
||||||
|
null,
|
||||||
|
player.boundingBox.offset(0.0, lockY - player.y, 0.0).expand(0.0625).stretch(0.0, -0.55, 0.0)
|
||||||
|
).all(VoxelShape::isEmpty)
|
||||||
|
) {
|
||||||
|
event.y = lockY
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (flyKickCounter >= 24)
|
||||||
|
flyKickCounter = 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onEnable() {
|
||||||
|
if (mc.player != null)
|
||||||
|
lockY = player.y - 0.03126
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onDisable() {
|
||||||
|
player.abilities.flying = false
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,19 @@
|
||||||
|
package codes.som.hibiscus.features.player
|
||||||
|
|
||||||
|
import codes.som.hibiscus.api.feature.Feature
|
||||||
|
import codes.som.hibiscus.api.feature.FeatureCategory
|
||||||
|
import codes.som.hibiscus.events.SendPacketEvent
|
||||||
|
import codes.som.hibiscus.mixins.MixinExtPlayerMoveC2SPacket
|
||||||
|
import codes.som.hibiscus.util.ext.requireExtension
|
||||||
|
import net.minecraft.network.packet.c2s.play.PlayerMoveC2SPacket
|
||||||
|
|
||||||
|
class NoFallDamage : Feature("No Fall Damage", FeatureCategory.PLAYER) {
|
||||||
|
init {
|
||||||
|
on { (packet): SendPacketEvent ->
|
||||||
|
if (packet is PlayerMoveC2SPacket) {
|
||||||
|
requireExtension<MixinExtPlayerMoveC2SPacket>(packet)
|
||||||
|
packet.setOnGround(true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,37 @@
|
||||||
|
package codes.som.hibiscus.gui
|
||||||
|
|
||||||
|
import imgui.ImGui
|
||||||
|
import imgui.type.ImBoolean
|
||||||
|
import kotlin.reflect.KMutableProperty
|
||||||
|
|
||||||
|
object ImGuiKt {
|
||||||
|
fun checkbox(label: String, prop: KMutableProperty<Boolean>) {
|
||||||
|
val imB = ImBoolean(prop.call())
|
||||||
|
ImGui.checkbox(label, imB)
|
||||||
|
prop.setter.call(imB.get())
|
||||||
|
}
|
||||||
|
|
||||||
|
fun dragFloat(label: String, prop: KMutableProperty<Float>, speed: Float, min: Float, max: Float) {
|
||||||
|
val arr = floatArrayOf(prop.call())
|
||||||
|
ImGui.dragFloat(label, arr, speed, min, max)
|
||||||
|
prop.setter.call(arr[0])
|
||||||
|
}
|
||||||
|
|
||||||
|
fun sliderFloat(label: String, prop: KMutableProperty<Float>, min: Float, max: Float) {
|
||||||
|
val arr = floatArrayOf(prop.call())
|
||||||
|
ImGui.sliderFloat(label, arr, min, max)
|
||||||
|
prop.setter.call(arr[0])
|
||||||
|
}
|
||||||
|
|
||||||
|
fun dragInt(label: String, prop: KMutableProperty<Int>, speed: Float, min: Float, max: Float) {
|
||||||
|
val arr = intArrayOf(prop.call())
|
||||||
|
ImGui.dragInt(label, arr, speed, min, max)
|
||||||
|
prop.setter.call(arr[0])
|
||||||
|
}
|
||||||
|
|
||||||
|
fun sliderInt(label: String, prop: KMutableProperty<Int>, min: Int, max: Int) {
|
||||||
|
val arr = intArrayOf(prop.call())
|
||||||
|
ImGui.sliderInt(label, arr, min, max)
|
||||||
|
prop.setter.call(arr[0])
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,47 @@
|
||||||
|
package codes.som.hibiscus.gui
|
||||||
|
|
||||||
|
import codes.som.hibiscus.mc
|
||||||
|
import imgui.ImGui
|
||||||
|
import imgui.flag.ImGuiConfigFlags
|
||||||
|
import imgui.gl3.ImGuiImplGl3
|
||||||
|
import imgui.glfw.ImGuiImplGlfw
|
||||||
|
import org.lwjgl.glfw.GLFW
|
||||||
|
|
||||||
|
object ImGuiRenderer {
|
||||||
|
private val imGuiGlfw = ImGuiImplGlfw()
|
||||||
|
private val imGuiGl3 = ImGuiImplGl3()
|
||||||
|
|
||||||
|
fun setup() {
|
||||||
|
ImGui.createContext()
|
||||||
|
|
||||||
|
with(ImGui.getIO()) {
|
||||||
|
iniFilename = null // We don't want to save .ini file
|
||||||
|
addConfigFlags(ImGuiConfigFlags.NavEnableKeyboard) // Enable Keyboard Controls
|
||||||
|
addConfigFlags(ImGuiConfigFlags.DockingEnable) // Enable Docking
|
||||||
|
addConfigFlags(ImGuiConfigFlags.ViewportsEnable) // Enable Multi-Viewport / Platform Windows
|
||||||
|
configViewportsNoTaskBarIcon = true
|
||||||
|
}
|
||||||
|
|
||||||
|
applyHibiscusImGuiTheme()
|
||||||
|
|
||||||
|
imGuiGlfw.init(mc.window.handle, true)
|
||||||
|
imGuiGl3.init()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun beginFrame(delta: Float) {
|
||||||
|
imGuiGlfw.newFrame()
|
||||||
|
ImGui.newFrame()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun finishFrame(delta: Float) {
|
||||||
|
ImGui.render()
|
||||||
|
imGuiGl3.renderDrawData(ImGui.getDrawData())
|
||||||
|
|
||||||
|
if (ImGui.getIO().hasConfigFlags(ImGuiConfigFlags.ViewportsEnable)) {
|
||||||
|
val backupWindowPtr = GLFW.glfwGetCurrentContext()
|
||||||
|
ImGui.updatePlatformWindows()
|
||||||
|
ImGui.renderPlatformWindowsDefault()
|
||||||
|
GLFW.glfwMakeContextCurrent(backupWindowPtr)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,47 +1,14 @@
|
||||||
package codes.som.hibiscus.gui
|
package codes.som.hibiscus.gui
|
||||||
|
|
||||||
import codes.som.hibiscus.mc
|
|
||||||
import imgui.ImGui
|
|
||||||
import imgui.flag.ImGuiConfigFlags
|
|
||||||
import imgui.gl3.ImGuiImplGl3
|
|
||||||
import imgui.glfw.ImGuiImplGlfw
|
|
||||||
import net.minecraft.client.gui.screen.Screen
|
import net.minecraft.client.gui.screen.Screen
|
||||||
import net.minecraft.client.util.math.MatrixStack
|
import net.minecraft.client.util.math.MatrixStack
|
||||||
import net.minecraft.text.Text
|
import net.minecraft.text.Text
|
||||||
import org.lwjgl.glfw.GLFW
|
|
||||||
|
|
||||||
|
|
||||||
object ImGuiScreen : Screen(Text.of("hacker_menu")) {
|
|
||||||
private val imGuiGlfw = ImGuiImplGlfw()
|
|
||||||
private val imGuiGl3 = ImGuiImplGl3()
|
|
||||||
|
|
||||||
init {
|
|
||||||
ImGui.createContext()
|
|
||||||
applyHibiscusImGuiTheme()
|
|
||||||
|
|
||||||
imGuiGlfw.init(mc.window.handle, true)
|
|
||||||
imGuiGl3.init()
|
|
||||||
}
|
|
||||||
|
|
||||||
|
object ImGuiScreen : Screen(Text.of("hacker menu")) {
|
||||||
override fun render(matrices: MatrixStack?, mouseX: Int, mouseY: Int, delta: Float) {
|
override fun render(matrices: MatrixStack?, mouseX: Int, mouseY: Int, delta: Float) {
|
||||||
super.render(matrices, mouseX, mouseY, delta)
|
super.render(matrices, mouseX, mouseY, delta)
|
||||||
|
|
||||||
imGuiGlfw.newFrame()
|
ModuleControlsUI.render(delta)
|
||||||
ImGui.newFrame()
|
|
||||||
|
|
||||||
ImGui.begin("hello")
|
|
||||||
ImGui.text("you just got hacked by didi @ digitalgangster")
|
|
||||||
ImGui.end()
|
|
||||||
|
|
||||||
ImGui.render()
|
|
||||||
imGuiGl3.renderDrawData(ImGui.getDrawData())
|
|
||||||
|
|
||||||
if (ImGui.getIO().hasConfigFlags(ImGuiConfigFlags.ViewportsEnable)) {
|
|
||||||
val backupWindowPtr = GLFW.glfwGetCurrentContext()
|
|
||||||
ImGui.updatePlatformWindows()
|
|
||||||
ImGui.renderPlatformWindowsDefault()
|
|
||||||
GLFW.glfwMakeContextCurrent(backupWindowPtr)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun shouldPause() = false
|
override fun shouldPause() = false
|
||||||
|
|
|
@ -0,0 +1,58 @@
|
||||||
|
package codes.som.hibiscus.gui
|
||||||
|
|
||||||
|
import codes.som.hibiscus.HibiscusMod
|
||||||
|
import codes.som.hibiscus.api.feature.Feature
|
||||||
|
import codes.som.hibiscus.api.feature.FeatureCategory
|
||||||
|
import imgui.ImGui
|
||||||
|
import imgui.flag.ImGuiCond.FirstUseEver
|
||||||
|
import imgui.flag.ImGuiWindowFlags
|
||||||
|
import imgui.flag.ImGuiWindowFlags.AlwaysVerticalScrollbar
|
||||||
|
|
||||||
|
object ModuleControlsUI {
|
||||||
|
private val moduleValueWindows = mutableMapOf<Feature, BooleanArray>()
|
||||||
|
|
||||||
|
private fun categoryPanel(category: FeatureCategory, initialX: Float, initialY: Float) {
|
||||||
|
ImGui.setNextWindowPos(initialX, initialY, FirstUseEver)
|
||||||
|
ImGui.setNextWindowCollapsed(true, FirstUseEver)
|
||||||
|
|
||||||
|
ImGui.begin(category.humanName, AlwaysVerticalScrollbar)
|
||||||
|
|
||||||
|
for (feature in HibiscusMod.features.getAllFeatures().filter { it.category == category }) {
|
||||||
|
featureControls(feature)
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui.end()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun featureControls(feature: Feature) {
|
||||||
|
ImGuiKt.checkbox(feature.name, feature::enabled)
|
||||||
|
|
||||||
|
if (feature.values.exist()) {
|
||||||
|
val showValueWindow = moduleValueWindows.getOrPut(feature) { booleanArrayOf(false) }
|
||||||
|
|
||||||
|
ImGui.sameLine(ImGui.getWindowContentRegionMaxX() - ImGui.getWindowContentRegionMinX() - 10)
|
||||||
|
if (ImGui.radioButton("##${feature.name} values", showValueWindow[0])) {
|
||||||
|
showValueWindow[0] = !showValueWindow[0]
|
||||||
|
}
|
||||||
|
|
||||||
|
if (showValueWindow[0]) {
|
||||||
|
if (ImGui.begin("${feature.name}##Feature Controls", ImGuiWindowFlags.NoCollapse)) {
|
||||||
|
for (value in feature.values)
|
||||||
|
value.drawUIControl()
|
||||||
|
}
|
||||||
|
ImGui.end()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fun render(delta: Float) {
|
||||||
|
for ((index, category) in FeatureCategory.values().withIndex()) {
|
||||||
|
categoryPanel(
|
||||||
|
category,
|
||||||
|
ImGui.getMainViewport().posX + 10f,
|
||||||
|
ImGui.getMainViewport().posY + 10f + index * 20f
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,14 @@
|
||||||
|
package codes.som.hibiscus.util.ext
|
||||||
|
|
||||||
|
import kotlin.contracts.ExperimentalContracts
|
||||||
|
import kotlin.contracts.contract
|
||||||
|
|
||||||
|
@OptIn(ExperimentalContracts::class)
|
||||||
|
inline fun <reified T : Any> requireExtension(obj: Any) {
|
||||||
|
contract {
|
||||||
|
returns() implies (obj is T)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (obj !is T)
|
||||||
|
error("Missing mixin extension ${T::class.java.name} for ${obj.javaClass.name}")
|
||||||
|
}
|
|
@ -0,0 +1,155 @@
|
||||||
|
package codes.som.hibiscus.util.input
|
||||||
|
|
||||||
|
|
||||||
|
import codes.som.hibiscus.mc
|
||||||
|
import com.google.common.collect.BiMap
|
||||||
|
import com.google.common.collect.ImmutableBiMap
|
||||||
|
import com.google.common.collect.ImmutableSortedSet
|
||||||
|
import net.minecraft.client.util.InputUtil
|
||||||
|
import org.lwjgl.glfw.GLFW
|
||||||
|
|
||||||
|
object Keys {
|
||||||
|
val KEY_MAP: BiMap<String, Int> = ImmutableBiMap.builder<String, Int>()
|
||||||
|
.put("SPACE", GLFW.GLFW_KEY_SPACE)
|
||||||
|
.put("APOSTROPHE", GLFW.GLFW_KEY_APOSTROPHE)
|
||||||
|
.put("COMMA", GLFW.GLFW_KEY_COMMA)
|
||||||
|
.put("MINUS", GLFW.GLFW_KEY_MINUS)
|
||||||
|
.put("PERIOD", GLFW.GLFW_KEY_PERIOD)
|
||||||
|
.put("SLASH", GLFW.GLFW_KEY_SLASH)
|
||||||
|
.put("0", GLFW.GLFW_KEY_0)
|
||||||
|
.put("1", GLFW.GLFW_KEY_1)
|
||||||
|
.put("2", GLFW.GLFW_KEY_2)
|
||||||
|
.put("3", GLFW.GLFW_KEY_3)
|
||||||
|
.put("4", GLFW.GLFW_KEY_4)
|
||||||
|
.put("5", GLFW.GLFW_KEY_5)
|
||||||
|
.put("6", GLFW.GLFW_KEY_6)
|
||||||
|
.put("7", GLFW.GLFW_KEY_7)
|
||||||
|
.put("8", GLFW.GLFW_KEY_8)
|
||||||
|
.put("9", GLFW.GLFW_KEY_9)
|
||||||
|
.put("SEMICOLON", GLFW.GLFW_KEY_SEMICOLON)
|
||||||
|
.put("EQUAL", GLFW.GLFW_KEY_EQUAL)
|
||||||
|
.put("A", GLFW.GLFW_KEY_A)
|
||||||
|
.put("B", GLFW.GLFW_KEY_B)
|
||||||
|
.put("C", GLFW.GLFW_KEY_C)
|
||||||
|
.put("D", GLFW.GLFW_KEY_D)
|
||||||
|
.put("E", GLFW.GLFW_KEY_E)
|
||||||
|
.put("F", GLFW.GLFW_KEY_F)
|
||||||
|
.put("G", GLFW.GLFW_KEY_G)
|
||||||
|
.put("H", GLFW.GLFW_KEY_H)
|
||||||
|
.put("I", GLFW.GLFW_KEY_I)
|
||||||
|
.put("J", GLFW.GLFW_KEY_J)
|
||||||
|
.put("K", GLFW.GLFW_KEY_K)
|
||||||
|
.put("L", GLFW.GLFW_KEY_L)
|
||||||
|
.put("M", GLFW.GLFW_KEY_M)
|
||||||
|
.put("N", GLFW.GLFW_KEY_N)
|
||||||
|
.put("O", GLFW.GLFW_KEY_O)
|
||||||
|
.put("P", GLFW.GLFW_KEY_P)
|
||||||
|
.put("Q", GLFW.GLFW_KEY_Q)
|
||||||
|
.put("R", GLFW.GLFW_KEY_R)
|
||||||
|
.put("S", GLFW.GLFW_KEY_S)
|
||||||
|
.put("T", GLFW.GLFW_KEY_T)
|
||||||
|
.put("U", GLFW.GLFW_KEY_U)
|
||||||
|
.put("V", GLFW.GLFW_KEY_V)
|
||||||
|
.put("W", GLFW.GLFW_KEY_W)
|
||||||
|
.put("X", GLFW.GLFW_KEY_X)
|
||||||
|
.put("Y", GLFW.GLFW_KEY_Y)
|
||||||
|
.put("Z", GLFW.GLFW_KEY_Z)
|
||||||
|
.put("LEFT_BRACKET", GLFW.GLFW_KEY_LEFT_BRACKET)
|
||||||
|
.put("BACKSLASH", GLFW.GLFW_KEY_BACKSLASH)
|
||||||
|
.put("RIGHT_BRACKET", GLFW.GLFW_KEY_RIGHT_BRACKET)
|
||||||
|
.put("GRAVE_ACCENT", GLFW.GLFW_KEY_GRAVE_ACCENT)
|
||||||
|
.put("WORLD_1", GLFW.GLFW_KEY_WORLD_1)
|
||||||
|
.put("WORLD_2", GLFW.GLFW_KEY_WORLD_2)
|
||||||
|
.put("ESCAPE", GLFW.GLFW_KEY_ESCAPE)
|
||||||
|
.put("ENTER", GLFW.GLFW_KEY_ENTER)
|
||||||
|
.put("TAB", GLFW.GLFW_KEY_TAB)
|
||||||
|
.put("BACKSPACE", GLFW.GLFW_KEY_BACKSPACE)
|
||||||
|
.put("INSERT", GLFW.GLFW_KEY_INSERT)
|
||||||
|
.put("DELETE", GLFW.GLFW_KEY_DELETE)
|
||||||
|
.put("RIGHT", GLFW.GLFW_KEY_RIGHT)
|
||||||
|
.put("LEFT", GLFW.GLFW_KEY_LEFT)
|
||||||
|
.put("DOWN", GLFW.GLFW_KEY_DOWN)
|
||||||
|
.put("UP", GLFW.GLFW_KEY_UP)
|
||||||
|
.put("PAGE_UP", GLFW.GLFW_KEY_PAGE_UP)
|
||||||
|
.put("PAGE_DOWN", GLFW.GLFW_KEY_PAGE_DOWN)
|
||||||
|
.put("HOME", GLFW.GLFW_KEY_HOME)
|
||||||
|
.put("END", GLFW.GLFW_KEY_END)
|
||||||
|
.put("CAPS_LOCK", GLFW.GLFW_KEY_CAPS_LOCK)
|
||||||
|
.put("SCROLL_LOCK", GLFW.GLFW_KEY_SCROLL_LOCK)
|
||||||
|
.put("NUM_LOCK", GLFW.GLFW_KEY_NUM_LOCK)
|
||||||
|
.put("PRINT_SCREEN", GLFW.GLFW_KEY_PRINT_SCREEN)
|
||||||
|
.put("PAUSE", GLFW.GLFW_KEY_PAUSE)
|
||||||
|
.put("F1", GLFW.GLFW_KEY_F1)
|
||||||
|
.put("F2", GLFW.GLFW_KEY_F2)
|
||||||
|
.put("F3", GLFW.GLFW_KEY_F3)
|
||||||
|
.put("F4", GLFW.GLFW_KEY_F4)
|
||||||
|
.put("F5", GLFW.GLFW_KEY_F5)
|
||||||
|
.put("F6", GLFW.GLFW_KEY_F6)
|
||||||
|
.put("F7", GLFW.GLFW_KEY_F7)
|
||||||
|
.put("F8", GLFW.GLFW_KEY_F8)
|
||||||
|
.put("F9", GLFW.GLFW_KEY_F9)
|
||||||
|
.put("F10", GLFW.GLFW_KEY_F10)
|
||||||
|
.put("F11", GLFW.GLFW_KEY_F11)
|
||||||
|
.put("F12", GLFW.GLFW_KEY_F12)
|
||||||
|
.put("F13", GLFW.GLFW_KEY_F13)
|
||||||
|
.put("F14", GLFW.GLFW_KEY_F14)
|
||||||
|
.put("F15", GLFW.GLFW_KEY_F15)
|
||||||
|
.put("F16", GLFW.GLFW_KEY_F16)
|
||||||
|
.put("F17", GLFW.GLFW_KEY_F17)
|
||||||
|
.put("F18", GLFW.GLFW_KEY_F18)
|
||||||
|
.put("F19", GLFW.GLFW_KEY_F19)
|
||||||
|
.put("F20", GLFW.GLFW_KEY_F20)
|
||||||
|
.put("F21", GLFW.GLFW_KEY_F21)
|
||||||
|
.put("F22", GLFW.GLFW_KEY_F22)
|
||||||
|
.put("F23", GLFW.GLFW_KEY_F23)
|
||||||
|
.put("F24", GLFW.GLFW_KEY_F24)
|
||||||
|
.put("F25", GLFW.GLFW_KEY_F25)
|
||||||
|
.put("KP_0", GLFW.GLFW_KEY_KP_0)
|
||||||
|
.put("KP_1", GLFW.GLFW_KEY_KP_1)
|
||||||
|
.put("KP_2", GLFW.GLFW_KEY_KP_2)
|
||||||
|
.put("KP_3", GLFW.GLFW_KEY_KP_3)
|
||||||
|
.put("KP_4", GLFW.GLFW_KEY_KP_4)
|
||||||
|
.put("KP_5", GLFW.GLFW_KEY_KP_5)
|
||||||
|
.put("KP_6", GLFW.GLFW_KEY_KP_6)
|
||||||
|
.put("KP_7", GLFW.GLFW_KEY_KP_7)
|
||||||
|
.put("KP_8", GLFW.GLFW_KEY_KP_8)
|
||||||
|
.put("KP_9", GLFW.GLFW_KEY_KP_9)
|
||||||
|
.put("KP_DECIMAL", GLFW.GLFW_KEY_KP_DECIMAL)
|
||||||
|
.put("KP_DIVIDE", GLFW.GLFW_KEY_KP_DIVIDE)
|
||||||
|
.put("KP_MULTIPLY", GLFW.GLFW_KEY_KP_MULTIPLY)
|
||||||
|
.put("KP_SUBTRACT", GLFW.GLFW_KEY_KP_SUBTRACT)
|
||||||
|
.put("KP_ADD", GLFW.GLFW_KEY_KP_ADD)
|
||||||
|
.put("KP_ENTER", GLFW.GLFW_KEY_KP_ENTER)
|
||||||
|
.put("KP_EQUAL", GLFW.GLFW_KEY_KP_EQUAL)
|
||||||
|
.put("LEFT_SHIFT", GLFW.GLFW_KEY_LEFT_SHIFT)
|
||||||
|
.put("LEFT_CONTROL", GLFW.GLFW_KEY_LEFT_CONTROL)
|
||||||
|
.put("LEFT_ALT", GLFW.GLFW_KEY_LEFT_ALT)
|
||||||
|
.put("LEFT_SUPER", GLFW.GLFW_KEY_LEFT_SUPER)
|
||||||
|
.put("RIGHT_SHIFT", GLFW.GLFW_KEY_RIGHT_SHIFT)
|
||||||
|
.put("RIGHT_CONTROL", GLFW.GLFW_KEY_RIGHT_CONTROL)
|
||||||
|
.put("RIGHT_ALT", GLFW.GLFW_KEY_RIGHT_ALT)
|
||||||
|
.put("RIGHT_SUPER", GLFW.GLFW_KEY_RIGHT_SUPER)
|
||||||
|
.put("MENU", GLFW.GLFW_KEY_MENU)
|
||||||
|
.put("NONE", GLFW.GLFW_KEY_UNKNOWN)
|
||||||
|
.build()
|
||||||
|
|
||||||
|
val KEY_PAD: Set<Int> = ImmutableSortedSet.of(
|
||||||
|
GLFW.GLFW_KEY_KP_0,
|
||||||
|
GLFW.GLFW_KEY_KP_1,
|
||||||
|
GLFW.GLFW_KEY_KP_2,
|
||||||
|
GLFW.GLFW_KEY_KP_3,
|
||||||
|
GLFW.GLFW_KEY_KP_4,
|
||||||
|
GLFW.GLFW_KEY_KP_5,
|
||||||
|
GLFW.GLFW_KEY_KP_6,
|
||||||
|
GLFW.GLFW_KEY_KP_7,
|
||||||
|
GLFW.GLFW_KEY_KP_8,
|
||||||
|
GLFW.GLFW_KEY_KP_9
|
||||||
|
)
|
||||||
|
|
||||||
|
fun pressed(key: Int): Boolean {
|
||||||
|
if (key == GLFW.GLFW_KEY_UNKNOWN)
|
||||||
|
return false
|
||||||
|
|
||||||
|
return InputUtil.isKeyPressed(mc.window.handle, key)
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,64 @@
|
||||||
|
package codes.som.hibiscus.util.netmoving
|
||||||
|
|
||||||
|
import codes.som.hibiscus.HibiscusMod
|
||||||
|
import codes.som.hibiscus.api.event.TypedListener
|
||||||
|
import codes.som.hibiscus.events.NetworkMovingEvent
|
||||||
|
import codes.som.hibiscus.events.SendPacketEvent
|
||||||
|
import codes.som.hibiscus.mc
|
||||||
|
import codes.som.hibiscus.mixins.MixinExtClientPlayerEntity
|
||||||
|
import codes.som.hibiscus.util.ext.requireExtension
|
||||||
|
import net.minecraft.network.packet.c2s.play.PlayerMoveC2SPacket
|
||||||
|
|
||||||
|
class NetworkMovingDispatcher : TypedListener<SendPacketEvent>(SendPacketEvent::class.java) {
|
||||||
|
override fun on(event: SendPacketEvent) {
|
||||||
|
val packet = event.packet
|
||||||
|
if (packet is PlayerMoveC2SPacket) {
|
||||||
|
val player = mc.player!!
|
||||||
|
requireExtension<MixinExtClientPlayerEntity>(player)
|
||||||
|
|
||||||
|
val movingEvent = NetworkMovingEvent(
|
||||||
|
packet.getX(player.x), packet.getY(player.y), packet.getZ(player.z),
|
||||||
|
packet.getYaw(player.yaw), packet.getPitch(player.pitch), packet.isOnGround
|
||||||
|
)
|
||||||
|
|
||||||
|
HibiscusMod.bus.fire(movingEvent)
|
||||||
|
|
||||||
|
if (movingEvent.cancelled)
|
||||||
|
event.cancel()
|
||||||
|
|
||||||
|
val moving =
|
||||||
|
movingEvent.x != player.lastX || movingEvent.y != player.lastBaseY || movingEvent.z != player.lastZ
|
||||||
|
val rotating = movingEvent.yaw != player.lastYaw || movingEvent.pitch != player.lastPitch
|
||||||
|
|
||||||
|
player.lastX = movingEvent.x
|
||||||
|
player.lastBaseY = movingEvent.y
|
||||||
|
player.lastZ = movingEvent.z
|
||||||
|
|
||||||
|
player.lastYaw = movingEvent.yaw
|
||||||
|
player.lastPitch = movingEvent.pitch
|
||||||
|
|
||||||
|
event.packet = when {
|
||||||
|
moving && rotating -> PlayerMoveC2SPacket.Full(
|
||||||
|
movingEvent.x,
|
||||||
|
movingEvent.y,
|
||||||
|
movingEvent.z,
|
||||||
|
movingEvent.yaw,
|
||||||
|
movingEvent.pitch,
|
||||||
|
movingEvent.onGround
|
||||||
|
)
|
||||||
|
moving -> PlayerMoveC2SPacket.PositionAndOnGround(
|
||||||
|
movingEvent.x,
|
||||||
|
movingEvent.y,
|
||||||
|
movingEvent.z,
|
||||||
|
movingEvent.onGround
|
||||||
|
)
|
||||||
|
rotating -> PlayerMoveC2SPacket.LookAndOnGround(
|
||||||
|
movingEvent.yaw,
|
||||||
|
movingEvent.pitch,
|
||||||
|
movingEvent.onGround
|
||||||
|
)
|
||||||
|
else -> PlayerMoveC2SPacket.OnGroundOnly(movingEvent.onGround)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -6,9 +6,12 @@
|
||||||
"defaultRequire": 1
|
"defaultRequire": 1
|
||||||
},
|
},
|
||||||
"mixins": [
|
"mixins": [
|
||||||
],
|
|
||||||
"client": [
|
|
||||||
"MixinClientPlayerEntity",
|
"MixinClientPlayerEntity",
|
||||||
"MixinKeyboard"
|
"MixinClientPlayNetworkHandler",
|
||||||
|
"MixinExtClientPlayerEntity",
|
||||||
|
"MixinExtPlayerMoveC2SPacket",
|
||||||
|
"MixinExtUpdatePlayerAbilitiesC2SPacket",
|
||||||
|
"MixinKeyboard",
|
||||||
|
"MixinMinecraftClient"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue