No Fog, 'Hard' mode for Flight, failsafe for ImGui

This commit is contained in:
Charlotte Som 2022-03-08 02:50:08 +00:00
parent ea9d543d32
commit e75052edea
19 changed files with 186 additions and 65 deletions

View file

@ -0,0 +1,26 @@
package codes.som.hibiscus.mixins;
import codes.som.hibiscus.Hibiscus;
import codes.som.hibiscus.events.RenderFogEvent;
import com.mojang.blaze3d.systems.RenderSystem;
import net.minecraft.client.render.BackgroundRenderer;
import net.minecraft.client.render.Camera;
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(BackgroundRenderer.class)
public abstract class MixinBackgroundRenderer {
@Inject(method = "applyFog", at = @At("HEAD"), cancellable = true)
private static void onApplyFog(Camera camera, BackgroundRenderer.FogType fogType, float viewDistance, boolean thickFog, CallbackInfo ci) {
var event = new RenderFogEvent();
Hibiscus.bus().fire(event);
if (event.isCancelled()) {
RenderSystem.setShaderFogStart(1000.0f);
RenderSystem.setShaderFogEnd(8000.0f);
ci.cancel();
}
}
}

View file

@ -1,10 +1,7 @@
package codes.som.hibiscus.mixins; package codes.som.hibiscus.mixins;
import codes.som.hibiscus.Hibiscus; import codes.som.hibiscus.Hibiscus;
import codes.som.hibiscus.events.MovePlayerEvent; import codes.som.hibiscus.events.*;
import codes.som.hibiscus.events.PlayerPreTickEvent;
import codes.som.hibiscus.events.PlayerTickEvent;
import codes.som.hibiscus.events.SendChatEvent;
import net.minecraft.client.network.ClientPlayerEntity; import net.minecraft.client.network.ClientPlayerEntity;
import net.minecraft.entity.MovementType; import net.minecraft.entity.MovementType;
import net.minecraft.util.math.Vec3d; import net.minecraft.util.math.Vec3d;
@ -49,4 +46,9 @@ public abstract class MixinClientPlayerEntity {
Hibiscus.bus().fire(event); Hibiscus.bus().fire(event);
return new Vec3d(event.getX(), event.getY(), event.getZ()); return new Vec3d(event.getX(), event.getY(), event.getZ());
} }
@Inject(method = "tickMovement", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/input/Input;tick(Z)V", shift = At.Shift.AFTER))
private void onInputTick(CallbackInfo ci) {
Hibiscus.bus().fire(PlayerInputTickEvent.INSTANCE);
}
} }

View file

@ -43,7 +43,9 @@ public abstract class MixinMinecraftClient {
@Inject(method = "render", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gl/Framebuffer;endWrite()V", shift = At.Shift.BEFORE)) @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) { private void onPostRenderEverything(boolean tick, CallbackInfo ci) {
float delta = this.paused ? this.pausedTickDelta : this.renderTickCounter.tickDelta; float delta = this.paused ? this.pausedTickDelta : this.renderTickCounter.tickDelta;
Hibiscus.bus().fire(new PostRenderAllEvent(delta)); if (!ImGuiRenderer.INSTANCE.getStalled())
Hibiscus.bus().fire(new PostRenderAllEvent(delta));
ImGuiRenderer.INSTANCE.finishFrame(delta); ImGuiRenderer.INSTANCE.finishFrame(delta);
} }

View file

@ -9,23 +9,36 @@ import net.minecraft.util.math.BlockPos;
import net.minecraft.world.BlockRenderView; import net.minecraft.world.BlockRenderView;
import net.minecraft.world.BlockView; import net.minecraft.world.BlockView;
import org.spongepowered.asm.mixin.Mixin; 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.At;
import org.spongepowered.asm.mixin.injection.Redirect; import org.spongepowered.asm.mixin.injection.Redirect;
@Mixin(LightDataAccess.class) @Mixin(LightDataAccess.class)
public abstract class MixinLightDataAccess { public abstract class MixinLightDataAccess {
@Shadow
public static long packLM(int lm) {
return 0;
}
@Redirect(method = "compute", at = @At(value = "INVOKE", target = "Lnet/minecraft/block/BlockState;getAmbientOcclusionLightLevel(Lnet/minecraft/world/BlockView;Lnet/minecraft/util/math/BlockPos;)F")) @Redirect(method = "compute", at = @At(value = "INVOKE", target = "Lnet/minecraft/block/BlockState;getAmbientOcclusionLightLevel(Lnet/minecraft/world/BlockView;Lnet/minecraft/util/math/BlockPos;)F"))
private float getAOLevel(BlockState instance, BlockView blockView, BlockPos blockPos) { private float getAOLevel(BlockState instance, BlockView blockView, BlockPos blockPos) {
if (XraySystem.shouldRenderXray() || FullbrightSystem.shouldRenderFullbright()) if (XraySystem.shouldRenderXray())
return 1f; return 1f;
return instance.getAmbientOcclusionLightLevel(blockView, blockPos); return instance.getAmbientOcclusionLightLevel(blockView, blockPos);
} }
@Redirect(method = "compute", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/render/WorldRenderer;getLightmapCoordinates(Lnet/minecraft/world/BlockRenderView;Lnet/minecraft/block/BlockState;Lnet/minecraft/util/math/BlockPos;)I")) @Redirect(method = "compute", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/render/WorldRenderer;getLightmapCoordinates(Lnet/minecraft/world/BlockRenderView;Lnet/minecraft/block/BlockState;Lnet/minecraft/util/math/BlockPos;)I"))
private int getLMCoords(BlockRenderView world, BlockState state, BlockPos pos) { private int getLMCoords1(BlockRenderView world, BlockState state, BlockPos pos) {
if (XraySystem.shouldRenderXray() || FullbrightSystem.shouldRenderFullbright()) if (FullbrightSystem.shouldRenderFullbright())
return 15728832; return 15728832;
return WorldRenderer.getLightmapCoordinates(world, state, pos); return WorldRenderer.getLightmapCoordinates(world, state, pos);
} }
@Redirect(method = "compute", at = @At(value = "INVOKE", target = "Lme/jellysquid/mods/sodium/client/model/light/data/LightDataAccess;packLM(I)J"), remap = false)
private long getLMCoords2(int lm) {
if (XraySystem.shouldRenderXray())
return packLM(15728832);
return packLM(lm);
}
} }

View file

@ -2,12 +2,15 @@
package codes.som.hibiscus.api.event package codes.som.hibiscus.api.event
abstract class TypedListener<T : Event>(val eventType: Class<T>) : Listener<T> abstract class TypedListener<T : Event>(
val eventType: Class<T>,
val phase: EventPhase = EventPhase.NORMAL
) : Listener<T>
inline fun <T : Event> EventBus.registerTyped(typedListener: TypedListener<T>) { inline fun <T : Event> EventBus.registerTyped(typedListener: TypedListener<T>) {
register(typedListener.eventType, typedListener) register(typedListener.eventType, typedListener, typedListener.phase)
} }
inline fun <T : Event> EventBus.unregisterTyped(typedListener: TypedListener<T>) { inline fun <T : Event> EventBus.unregisterTyped(typedListener: TypedListener<T>) {
unregister(typedListener.eventType, typedListener) unregister(typedListener.eventType, typedListener, typedListener.phase)
} }

View file

@ -8,8 +8,16 @@ import codes.som.hibiscus.api.feature.values.ValueRegistry
abstract class Feature(val name: String, val category: FeatureCategory) { abstract class Feature(val name: String, val category: FeatureCategory) {
private val listeners = mutableListOf<TypedListener<*>>() private val listeners = mutableListOf<TypedListener<*>>()
protected inline fun <reified T : Event> on(listener: Listener<T>) = protected inline fun <reified T : Event> on(
on(object : TypedListener<T>(T::class.java), Listener<T> by listener {}) crossinline cond: () -> Boolean = { true },
phase: EventPhase = EventPhase.NORMAL,
listener: Listener<T>
) =
on(object : TypedListener<T>(T::class.java, phase) {
override fun on(event: T) {
if (cond()) listener.on(event)
}
})
protected fun <T : Event> on(listener: TypedListener<T>) = protected fun <T : Event> on(listener: TypedListener<T>) =
listeners.add(listener) listeners.add(listener)

View file

@ -28,10 +28,10 @@ class ValueRegistry {
FloatValue(name, default, min, max).also(this::register) FloatValue(name, default, min, max).also(this::register)
fun <E : Enum<E>> enum(name: String, default: E) = fun <E : Enum<E>> enum(name: String, default: E) =
EnumValue(name, default) EnumValue(name, default).also(this::register)
fun <E : Enum<E>> optionalEnum(name: String, type: Class<E>, default: E?) = fun <E : Enum<E>> optionalEnum(name: String, type: Class<E>, default: E?) =
OptionalEnumValue(name, type, default) OptionalEnumValue(name, type, default).also(this::register)
inline fun <reified E : Enum<E>> optionalEnum(name: String, default: E?) = inline fun <reified E : Enum<E>> optionalEnum(name: String, default: E?) =
optionalEnum(name, E::class.java, default) optionalEnum(name, E::class.java, default)

View file

@ -8,3 +8,4 @@ object PlayerPreTickEvent : Event
object PlayerTickEvent : Event object PlayerTickEvent : Event
class SendChatEvent(val message: String) : Cancellable(), Event class SendChatEvent(val message: String) : Cancellable(), Event
data class MovePlayerEvent(var x: Double, var y: Double, var z: Double, val movementType: MovementType) : Event data class MovePlayerEvent(var x: Double, var y: Double, var z: Double, val movementType: MovementType) : Event
object PlayerInputTickEvent : Event

View file

@ -19,3 +19,5 @@ class PostRenderEntitiesEvent(val delta: Float) : Event
class PostRenderWorldEvent(val delta: Float, val camera: Camera, val matrices: MatrixStack) : Event class PostRenderWorldEvent(val delta: Float, val camera: Camera, val matrices: MatrixStack) : Event
class RenderHandEvent(val delta: Float) : Cancellable(), Event class RenderHandEvent(val delta: Float) : Cancellable(), Event
class RenderFogEvent() : Cancellable(), Event

View file

@ -12,6 +12,7 @@ import codes.som.hibiscus.features.player.NoSprintingPacket
import codes.som.hibiscus.features.player.Nuker import codes.som.hibiscus.features.player.Nuker
import codes.som.hibiscus.features.visual.Freecam import codes.som.hibiscus.features.visual.Freecam
import codes.som.hibiscus.features.visual.Fullbright import codes.som.hibiscus.features.visual.Fullbright
import codes.som.hibiscus.features.visual.NoFog
import codes.som.hibiscus.features.visual.Xray import codes.som.hibiscus.features.visual.Xray
import codes.som.hibiscus.util.Resettable import codes.som.hibiscus.util.Resettable
@ -29,6 +30,7 @@ fun FEATURE_CONSTRUCTORS(): Array<() -> Feature> = arrayOf(
::Xray, ::Xray,
::Nuker, ::Nuker,
::Fullbright, ::Fullbright,
::NoFog,
) )
class FeaturesRegistry : Resettable { class FeaturesRegistry : Resettable {
@ -47,7 +49,7 @@ class FeaturesRegistry : Resettable {
getAllFeatures().first { it.javaClass == type } as T getAllFeatures().first { it.javaClass == type } as T
private fun registerFeatures() { private fun registerFeatures() {
features.addAll(FEATURE_CONSTRUCTORS().map { it() }) features.addAll(FEATURE_CONSTRUCTORS().map { it() }.sortedBy { it.name })
} }
override fun reset() { override fun reset() {

View file

@ -2,14 +2,14 @@ package codes.som.hibiscus.features.movement
import codes.som.hibiscus.api.feature.Feature import codes.som.hibiscus.api.feature.Feature
import codes.som.hibiscus.api.feature.FeatureCategory import codes.som.hibiscus.api.feature.FeatureCategory
import codes.som.hibiscus.events.NetworkMovingEvent import codes.som.hibiscus.events.*
import codes.som.hibiscus.events.PlayerTickEvent
import codes.som.hibiscus.events.SendPacketEvent
import codes.som.hibiscus.mc import codes.som.hibiscus.mc
import codes.som.hibiscus.mixins.MixinExtUpdatePlayerAbilitiesC2SPacket import codes.som.hibiscus.mixins.MixinExtUpdatePlayerAbilitiesC2SPacket
import codes.som.hibiscus.player import codes.som.hibiscus.player
import codes.som.hibiscus.util.ext.requireExtension import codes.som.hibiscus.util.ext.requireExtension
import codes.som.hibiscus.util.math.constructMovementVectorFromKeyboard
import codes.som.hibiscus.world import codes.som.hibiscus.world
import net.minecraft.entity.MovementType
import net.minecraft.network.packet.c2s.play.ClientCommandC2SPacket import net.minecraft.network.packet.c2s.play.ClientCommandC2SPacket
import net.minecraft.network.packet.c2s.play.UpdatePlayerAbilitiesC2SPacket import net.minecraft.network.packet.c2s.play.UpdatePlayerAbilitiesC2SPacket
import net.minecraft.util.shape.VoxelShape import net.minecraft.util.shape.VoxelShape
@ -18,20 +18,38 @@ class Flight : Feature("Flight", FeatureCategory.MOVEMENT) {
private var flyKickCounter = 0 private var flyKickCounter = 0
private var lockY = 0.0 private var lockY = 0.0
private val spoofAbilityPackets by values.bool("Spoof Outgoing Ability Packets", true)
private val vanillaKickBypass by values.bool("Vanilla Kick Bypass", true)
private val mode by values.enum("Mode", FlightMode.HARD)
init { init {
on { _: PlayerTickEvent -> on(cond = { mode == FlightMode.VANILLA }) { _: PlayerTickEvent ->
player.abilities.flying = true player.abilities.flying = true
} }
val spoofAbilityPackets by values.bool("Spoof Outgoing Ability Packets", true) on(cond = { mode == FlightMode.HARD }) { event: MovePlayerEvent ->
val vanillaKickBypass by values.bool("Vanilla Kick Bypass", true) if (event.movementType != MovementType.SELF)
on { event: SendPacketEvent ->
val (packet) = event
if (!spoofAbilityPackets)
return@on return@on
val movement =
constructMovementVectorFromKeyboard(player.yaw)
.multiply(if (player.isSprinting) 1.5 else 0.75)
.multiply(1.0, 0.75, 1.0)
event.x = movement.x
event.y = movement.y
event.z = movement.z
player.velocity = movement.multiply(0.25, 0.25, 0.25)
}
on(cond = { mode == FlightMode.HARD }) { _: PlayerInputTickEvent ->
player.input.sneaking = false
}
on(cond = { spoofAbilityPackets }) { event: SendPacketEvent ->
val (packet) = event
if (packet is UpdatePlayerAbilitiesC2SPacket) { if (packet is UpdatePlayerAbilitiesC2SPacket) {
requireExtension<MixinExtUpdatePlayerAbilitiesC2SPacket>(packet) requireExtension<MixinExtUpdatePlayerAbilitiesC2SPacket>(packet)
packet.setFlying(player.abilities.allowFlying) packet.setFlying(player.abilities.allowFlying)
@ -44,10 +62,7 @@ class Flight : Feature("Flight", FeatureCategory.MOVEMENT) {
} }
} }
on { event: NetworkMovingEvent -> on(cond = { vanillaKickBypass }) { event: NetworkMovingEvent ->
if (!vanillaKickBypass)
return@on
flyKickCounter++ flyKickCounter++
if (flyKickCounter >= 16) { if (flyKickCounter >= 16) {
@ -83,4 +98,12 @@ class Flight : Feature("Flight", FeatureCategory.MOVEMENT) {
super.createFeatureCommand().apply { super.createFeatureCommand().apply {
alias("fly") alias("fly")
} }
enum class FlightMode {
VANILLA, HARD;
override fun toString(): String {
return name[0] + name.substring(1).lowercase()
}
}
} }

View file

@ -1,5 +1,6 @@
package codes.som.hibiscus.features.movement package codes.som.hibiscus.features.movement
import codes.som.hibiscus.api.event.EventPhase
import codes.som.hibiscus.api.feature.Feature import codes.som.hibiscus.api.feature.Feature
import codes.som.hibiscus.api.feature.FeatureCategory import codes.som.hibiscus.api.feature.FeatureCategory
import codes.som.hibiscus.events.MovePlayerEvent import codes.som.hibiscus.events.MovePlayerEvent
@ -9,7 +10,7 @@ class Speed : Feature("Speed", FeatureCategory.MOVEMENT) {
init { init {
val speed by values.float("Speed", 2f, 0.05f, 10f) val speed by values.float("Speed", 2f, 0.05f, 10f)
on { event: MovePlayerEvent -> on(phase = EventPhase.AFTER) { event: MovePlayerEvent ->
if (event.movementType == MovementType.SELF) { if (event.movementType == MovementType.SELF) {
event.x *= speed event.x *= speed
event.z *= speed event.z *= speed

View file

@ -9,6 +9,7 @@ import codes.som.hibiscus.mixins.MixinExtPlayerInteractEntityC2SPacket
import codes.som.hibiscus.player import codes.som.hibiscus.player
import codes.som.hibiscus.util.ext.requireExtension import codes.som.hibiscus.util.ext.requireExtension
import codes.som.hibiscus.util.graphics.MinecraftRenderPipelineProgress import codes.som.hibiscus.util.graphics.MinecraftRenderPipelineProgress
import codes.som.hibiscus.util.math.constructMovementVectorFromKeyboard
import codes.som.hibiscus.world import codes.som.hibiscus.world
import net.minecraft.client.input.Input import net.minecraft.client.input.Input
import net.minecraft.client.network.ClientPlayerEntity import net.minecraft.client.network.ClientPlayerEntity
@ -18,8 +19,6 @@ import net.minecraft.entity.EntityType
import net.minecraft.entity.MovementType import net.minecraft.entity.MovementType
import net.minecraft.nbt.NbtCompound import net.minecraft.nbt.NbtCompound
import net.minecraft.network.packet.c2s.play.PlayerInteractEntityC2SPacket import net.minecraft.network.packet.c2s.play.PlayerInteractEntityC2SPacket
import net.minecraft.util.math.MathHelper
import net.minecraft.util.math.Vec3d
import net.minecraft.world.World import net.minecraft.world.World
import org.lwjgl.glfw.GLFW.GLFW_KEY_TAB import org.lwjgl.glfw.GLFW.GLFW_KEY_TAB
import org.lwjgl.glfw.GLFW.GLFW_PRESS import org.lwjgl.glfw.GLFW.GLFW_PRESS
@ -78,30 +77,10 @@ class Freecam : Feature("Freecam", FeatureCategory.VISUAL) {
} }
if (!isControllingPlayer) { if (!isControllingPlayer) {
val yaw = MathHelper.RADIANS_PER_DEGREE * view.yaw val movement = constructMovementVectorFromKeyboard(view.yaw)
val lookVec = Vec3d(-MathHelper.sin(yaw).toDouble(), 0.0, MathHelper.cos(yaw).toDouble())
var movement = Vec3d.ZERO
if (mc.options.forwardKey.isPressed)
movement = movement.add(0.0, 0.0, 1.0)
if (mc.options.backKey.isPressed)
movement = movement.add(0.0, 0.0, -1.0)
if (mc.options.rightKey.isPressed)
movement = movement.add(1.0, 0.0, 0.0)
if (mc.options.leftKey.isPressed)
movement = movement.add(-1.0, 0.0, 0.0)
if (mc.options.jumpKey.isPressed)
movement = movement.add(0.0, 1.0, 0.0)
if (mc.options.sneakKey.isPressed)
movement = movement.add(0.0, -1.0, 0.0)
// one day i will learn the matrix math for this
movement = lookVec
.multiply(movement.z)
.add(lookVec.rotateY(-MathHelper.HALF_PI).multiply(movement.x))
.add(0.0, movement.y, 0.0)
.multiply(speed.toDouble()) .multiply(speed.toDouble())
// Update entity positional state properly by calling move()
view.move(MovementType.SELF, movement) // Update entity positional state properly by calling move() view.move(MovementType.SELF, movement)
} }
} }

View file

@ -0,0 +1,15 @@
package codes.som.hibiscus.features.visual
import codes.som.hibiscus.api.feature.Feature
import codes.som.hibiscus.api.feature.FeatureCategory
import codes.som.hibiscus.events.RenderFogEvent
class NoFog : Feature("No Fog", FeatureCategory.VISUAL) {
init {
on { event: RenderFogEvent ->
event.cancel()
}
enabled = true
}
}

View file

@ -11,6 +11,9 @@ object ImGuiRenderer {
private val imGuiGlfw = ImGuiImplGlfw() private val imGuiGlfw = ImGuiImplGlfw()
private val imGuiGl3 = ImGuiImplGl3() private val imGuiGl3 = ImGuiImplGl3()
private var didRender = true
var stalled = false
fun setup() { fun setup() {
ImGui.createContext() ImGui.createContext()
@ -29,8 +32,15 @@ object ImGuiRenderer {
} }
fun beginFrame(delta: Float) { fun beginFrame(delta: Float) {
imGuiGlfw.newFrame() if (didRender) {
ImGui.newFrame() imGuiGlfw.newFrame()
ImGui.newFrame()
didRender = false
} else {
// If we run into an exception while the game is running (causing finishFrame() to not get hit),
// stall ImGui so that we have time to spit out a stack trace instead of crashing on an ImGui assert
stalled = true
}
} }
fun finishFrame(delta: Float) { fun finishFrame(delta: Float) {
@ -43,5 +53,6 @@ object ImGuiRenderer {
ImGui.renderPlatformWindowsDefault() ImGui.renderPlatformWindowsDefault()
GLFW.glfwMakeContextCurrent(backupWindowPtr) GLFW.glfwMakeContextCurrent(backupWindowPtr)
} }
didRender = true
} }
} }

View file

@ -0,0 +1,32 @@
package codes.som.hibiscus.util.math
import codes.som.hibiscus.mc
import net.minecraft.util.math.MathHelper
import net.minecraft.util.math.Vec3d
fun constructMovementVectorFromKeyboard(yawDeg: Float): Vec3d {
val yaw = MathHelper.RADIANS_PER_DEGREE * yawDeg
val lookVec = Vec3d(-MathHelper.sin(yaw).toDouble(), 0.0, MathHelper.cos(yaw).toDouble())
var movement = Vec3d.ZERO
if (mc.options.forwardKey.isPressed)
movement = movement.add(0.0, 0.0, 1.0)
if (mc.options.backKey.isPressed)
movement = movement.add(0.0, 0.0, -1.0)
if (mc.options.rightKey.isPressed)
movement = movement.add(1.0, 0.0, 0.0)
if (mc.options.leftKey.isPressed)
movement = movement.add(-1.0, 0.0, 0.0)
if (mc.options.jumpKey.isPressed)
movement = movement.add(0.0, 1.0, 0.0)
if (mc.options.sneakKey.isPressed)
movement = movement.add(0.0, -1.0, 0.0)
movement = lookVec
.multiply(movement.z)
.add(lookVec.rotateY(-MathHelper.HALF_PI).multiply(movement.x))
.add(0.0, movement.y, 0.0)
return movement
}

View file

@ -6,6 +6,7 @@
"defaultRequire": 1 "defaultRequire": 1
}, },
"mixins": [ "mixins": [
"MixinBackgroundRenderer",
"MixinClientConnection", "MixinClientConnection",
"MixinClientPlayerEntity", "MixinClientPlayerEntity",
"MixinClientPlayNetworkHandler", "MixinClientPlayNetworkHandler",