Create features system with Flight, No Fall Damage
This commit is contained in:
parent
ab0e18e2c8
commit
ceac1fda7a
37 changed files with 930 additions and 57 deletions
|
@ -1,7 +1,11 @@
|
|||
import org.gradle.kotlin.dsl.accessors.runtime.extensionOf
|
||||
import org.quiltmc.quiltmappings.loom.QuiltMappingsOnLoomPlugin
|
||||
|
||||
plugins {
|
||||
id("fabric-loom")
|
||||
val kotlinVersion: String by System.getProperties()
|
||||
kotlin("jvm").version(kotlinVersion)
|
||||
id("org.quiltmc.quilt-mappings-on-loom").version("3.1.1")
|
||||
}
|
||||
|
||||
base {
|
||||
|
@ -21,8 +25,25 @@ repositories {}
|
|||
dependencies {
|
||||
val minecraftVersion: String by project
|
||||
minecraft("com.mojang:minecraft:$minecraftVersion")
|
||||
val yarnMappings: String by project
|
||||
mappings("net.fabricmc:yarn:$yarnMappings:v2")
|
||||
|
||||
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
|
||||
mappings("net.fabricmc:yarn:$yarnMappings:v2")
|
||||
}
|
||||
|
||||
val loaderVersion: String by project
|
||||
modImplementation("net.fabricmc:fabric-loader:$loaderVersion")
|
||||
val fabricVersion: String by project
|
||||
|
@ -49,7 +70,11 @@ tasks {
|
|||
}
|
||||
|
||||
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()
|
||||
targetCompatibility = javaVersion.toString()
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@ org.gradle.warning.mode=all
|
|||
# Check these on https://fabricmc.net/develop/
|
||||
minecraftVersion=1.18.1
|
||||
yarnMappings=1.18.1+build.22
|
||||
quiltMappings=1.18.1+build.6
|
||||
loaderVersion=0.12.12
|
||||
# Fabric API
|
||||
fabricVersion=0.46.1+1.18
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
pluginManagement {
|
||||
repositories {
|
||||
maven("https://maven.fabricmc.net") { name = "Fabric" }
|
||||
maven("https://maven.quiltmc.org/repository/release") { name = "Quilt" }
|
||||
mavenCentral()
|
||||
gradlePluginPortal()
|
||||
}
|
||||
|
@ -10,4 +11,4 @@ pluginManagement {
|
|||
val kotlinVersion: String by System.getProperties()
|
||||
kotlin("jvm").version(kotlinVersion)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
||||
import com.mojang.authlib.*;
|
||||
import com.mojang.authlib.exceptions.*;
|
||||
import com.mojang.authlib.yggdrasil.*;
|
||||
import com.mojang.util.*;
|
||||
import net.minecraft.client.main.*;
|
||||
import net.minecraft.client.util.*;
|
||||
import org.spongepowered.asm.mixin.*;
|
||||
import org.spongepowered.asm.mixin.injection.*;
|
||||
import com.mojang.authlib.Agent;
|
||||
import com.mojang.authlib.GameProfile;
|
||||
import com.mojang.authlib.exceptions.AuthenticationException;
|
||||
import com.mojang.authlib.yggdrasil.YggdrasilAuthenticationService;
|
||||
import com.mojang.authlib.yggdrasil.YggdrasilUserAuthentication;
|
||||
import com.mojang.util.UUIDTypeAdapter;
|
||||
import net.minecraft.client.main.Main;
|
||||
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.net.*;
|
||||
import java.nio.file.*;
|
||||
import java.util.*;
|
||||
import java.io.IOException;
|
||||
import java.net.Proxy;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
@Mixin(Main.class)
|
||||
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) {
|
||||
List<String> arguments = new ArrayList<>(Arrays.asList(args));
|
||||
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.events.KeyEvent
|
||||
import codes.som.hibiscus.features.FeaturesRegistry
|
||||
import codes.som.hibiscus.gui.ImGuiScreen
|
||||
import codes.som.hibiscus.util.netmoving.NetworkMovingDispatcher
|
||||
import net.fabricmc.api.ModInitializer
|
||||
import org.lwjgl.glfw.GLFW
|
||||
import org.lwjgl.glfw.GLFW.GLFW_KEY_RIGHT_SHIFT
|
||||
|
@ -15,9 +17,15 @@ object HibiscusMod : ModInitializer {
|
|||
@get:JvmName("bus")
|
||||
val bus = EventBus()
|
||||
|
||||
val features = FeaturesRegistry()
|
||||
|
||||
override fun onInitialize() {
|
||||
bus.register { key: KeyEvent ->
|
||||
if (key.key != GLFW_KEY_RIGHT_SHIFT || key.action != GLFW.GLFW_PRESS)
|
||||
bus.register(NetworkMovingDispatcher())
|
||||
bus.register { event: KeyEvent ->
|
||||
if (event.key != GLFW_KEY_RIGHT_SHIFT || event.action != GLFW.GLFW_PRESS)
|
||||
return@register
|
||||
|
||||
if (mc.currentScreen != null)
|
||||
return@register
|
||||
|
||||
mc.setScreen(ImGuiScreen)
|
||||
|
|
|
@ -1,5 +1,9 @@
|
|||
package codes.som.hibiscus
|
||||
|
||||
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 player: ClientPlayerEntity inline get() = mc.player!!
|
||||
val world: ClientWorld inline get() = mc.world!!
|
||||
|
|
10
src/main/kotlin/codes/som/hibiscus/api/event/Cancellable.kt
Normal file
10
src/main/kotlin/codes/som/hibiscus/api/event/Cancellable.kt
Normal file
|
@ -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)
|
||||
}
|
37
src/main/kotlin/codes/som/hibiscus/api/feature/Feature.kt
Normal file
37
src/main/kotlin/codes/som/hibiscus/api/feature/Feature.kt
Normal file
|
@ -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)
|
||||
}
|
15
src/main/kotlin/codes/som/hibiscus/events/NetworkEvents.kt
Normal file
15
src/main/kotlin/codes/som/hibiscus/events/NetworkEvents.kt
Normal file
|
@ -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
|
10
src/main/kotlin/codes/som/hibiscus/features/FeatureList.kt
Normal file
10
src/main/kotlin/codes/som/hibiscus/features/FeatureList.kt
Normal file
|
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
37
src/main/kotlin/codes/som/hibiscus/gui/ImGuiKt.kt
Normal file
37
src/main/kotlin/codes/som/hibiscus/gui/ImGuiKt.kt
Normal file
|
@ -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])
|
||||
}
|
||||
}
|
47
src/main/kotlin/codes/som/hibiscus/gui/ImGuiRenderer.kt
Normal file
47
src/main/kotlin/codes/som/hibiscus/gui/ImGuiRenderer.kt
Normal file
|
@ -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
|
||||
|
||||
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.util.math.MatrixStack
|
||||
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) {
|
||||
super.render(matrices, mouseX, mouseY, delta)
|
||||
|
||||
imGuiGlfw.newFrame()
|
||||
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)
|
||||
}
|
||||
ModuleControlsUI.render(delta)
|
||||
}
|
||||
|
||||
override fun shouldPause() = false
|
||||
|
|
58
src/main/kotlin/codes/som/hibiscus/gui/ModuleControlsUI.kt
Normal file
58
src/main/kotlin/codes/som/hibiscus/gui/ModuleControlsUI.kt
Normal file
|
@ -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}")
|
||||
}
|
155
src/main/kotlin/codes/som/hibiscus/util/input/Keys.kt
Normal file
155
src/main/kotlin/codes/som/hibiscus/util/input/Keys.kt
Normal file
|
@ -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
|
||||
},
|
||||
"mixins": [
|
||||
],
|
||||
"client": [
|
||||
"MixinClientPlayerEntity",
|
||||
"MixinKeyboard"
|
||||
"MixinClientPlayNetworkHandler",
|
||||
"MixinExtClientPlayerEntity",
|
||||
"MixinExtPlayerMoveC2SPacket",
|
||||
"MixinExtUpdatePlayerAbilitiesC2SPacket",
|
||||
"MixinKeyboard",
|
||||
"MixinMinecraftClient"
|
||||
]
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue