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;
import codes.som.hibiscus.Hibiscus;
import codes.som.hibiscus.events.MovePlayerEvent;
import codes.som.hibiscus.events.PlayerPreTickEvent;
import codes.som.hibiscus.events.PlayerTickEvent;
import codes.som.hibiscus.events.SendChatEvent;
import codes.som.hibiscus.events.*;
import net.minecraft.client.network.ClientPlayerEntity;
import net.minecraft.entity.MovementType;
import net.minecraft.util.math.Vec3d;
@ -49,4 +46,9 @@ public abstract class MixinClientPlayerEntity {
Hibiscus.bus().fire(event);
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))
private void onPostRenderEverything(boolean tick, CallbackInfo ci) {
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);
}

View file

@ -9,23 +9,36 @@ import net.minecraft.util.math.BlockPos;
import net.minecraft.world.BlockRenderView;
import net.minecraft.world.BlockView;
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.Redirect;
@Mixin(LightDataAccess.class)
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"))
private float getAOLevel(BlockState instance, BlockView blockView, BlockPos blockPos) {
if (XraySystem.shouldRenderXray() || FullbrightSystem.shouldRenderFullbright())
if (XraySystem.shouldRenderXray())
return 1f;
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"))
private int getLMCoords(BlockRenderView world, BlockState state, BlockPos pos) {
if (XraySystem.shouldRenderXray() || FullbrightSystem.shouldRenderFullbright())
private int getLMCoords1(BlockRenderView world, BlockState state, BlockPos pos) {
if (FullbrightSystem.shouldRenderFullbright())
return 15728832;
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
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>) {
register(typedListener.eventType, typedListener)
register(typedListener.eventType, typedListener, typedListener.phase)
}
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) {
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 inline fun <reified T : Event> on(
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>) =
listeners.add(listener)

View file

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

View file

@ -8,3 +8,4 @@ object PlayerPreTickEvent : Event
object PlayerTickEvent : Event
class SendChatEvent(val message: String) : Cancellable(), 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 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.visual.Freecam
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.util.Resettable
@ -29,6 +30,7 @@ fun FEATURE_CONSTRUCTORS(): Array<() -> Feature> = arrayOf(
::Xray,
::Nuker,
::Fullbright,
::NoFog,
)
class FeaturesRegistry : Resettable {
@ -47,7 +49,7 @@ class FeaturesRegistry : Resettable {
getAllFeatures().first { it.javaClass == type } as T
private fun registerFeatures() {
features.addAll(FEATURE_CONSTRUCTORS().map { it() })
features.addAll(FEATURE_CONSTRUCTORS().map { it() }.sortedBy { it.name })
}
override fun reset() {

View file

@ -17,10 +17,10 @@ class AntiGhost : Feature("Anti Ghost", FeatureCategory.EXPLOITS) {
if (player.health <= 0) {
player.deathTime = -1
requireExtension<MixinExtEntity>(player)
player.setRemovalReason(null)
player.hurtTime = Int.MAX_VALUE
player.prevHeadYaw = player.prevYaw

View file

@ -14,7 +14,7 @@ import net.minecraft.network.packet.s2c.play.PlayerRespawnS2CPacket
class Ghost : Feature("Ghost", FeatureCategory.EXPLOITS) {
var dead = false
init {
on { _: PlayerTickEvent ->
if (player.health <= 0) {
@ -35,10 +35,10 @@ class Ghost : Feature("Ghost", FeatureCategory.EXPLOITS) {
mc.setScreen(null)
}
}
on { event: ReceivePacketEvent ->
val (packet) = event
if (packet is HealthUpdateS2CPacket) {
if (packet.health <= 0) {
event.cancel()
@ -53,7 +53,7 @@ class Ghost : Feature("Ghost", FeatureCategory.EXPLOITS) {
// TODO: Render 0 health on the status bar when dead
}
override fun createFeatureCommand() = super.createFeatureCommand().apply {
override fun createFeatureCommand() = super.createFeatureCommand().apply {
branch("respawn") {
player.requestRespawn()
}

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.FeatureCategory
import codes.som.hibiscus.events.NetworkMovingEvent
import codes.som.hibiscus.events.PlayerTickEvent
import codes.som.hibiscus.events.SendPacketEvent
import codes.som.hibiscus.events.*
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.util.math.constructMovementVectorFromKeyboard
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.UpdatePlayerAbilitiesC2SPacket
import net.minecraft.util.shape.VoxelShape
@ -18,20 +18,38 @@ class Flight : Feature("Flight", FeatureCategory.MOVEMENT) {
private var flyKickCounter = 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 {
on { _: PlayerTickEvent ->
on(cond = { mode == FlightMode.VANILLA }) { _: PlayerTickEvent ->
player.abilities.flying = true
}
val spoofAbilityPackets by values.bool("Spoof Outgoing Ability Packets", true)
val vanillaKickBypass by values.bool("Vanilla Kick Bypass", true)
on { event: SendPacketEvent ->
val (packet) = event
if (!spoofAbilityPackets)
on(cond = { mode == FlightMode.HARD }) { event: MovePlayerEvent ->
if (event.movementType != MovementType.SELF)
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) {
requireExtension<MixinExtUpdatePlayerAbilitiesC2SPacket>(packet)
packet.setFlying(player.abilities.allowFlying)
@ -44,10 +62,7 @@ class Flight : Feature("Flight", FeatureCategory.MOVEMENT) {
}
}
on { event: NetworkMovingEvent ->
if (!vanillaKickBypass)
return@on
on(cond = { vanillaKickBypass }) { event: NetworkMovingEvent ->
flyKickCounter++
if (flyKickCounter >= 16) {
@ -83,4 +98,12 @@ class Flight : Feature("Flight", FeatureCategory.MOVEMENT) {
super.createFeatureCommand().apply {
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
import codes.som.hibiscus.api.event.EventPhase
import codes.som.hibiscus.api.feature.Feature
import codes.som.hibiscus.api.feature.FeatureCategory
import codes.som.hibiscus.events.MovePlayerEvent
@ -9,7 +10,7 @@ class Speed : Feature("Speed", FeatureCategory.MOVEMENT) {
init {
val speed by values.float("Speed", 2f, 0.05f, 10f)
on { event: MovePlayerEvent ->
on(phase = EventPhase.AFTER) { event: MovePlayerEvent ->
if (event.movementType == MovementType.SELF) {
event.x *= 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.util.ext.requireExtension
import codes.som.hibiscus.util.graphics.MinecraftRenderPipelineProgress
import codes.som.hibiscus.util.math.constructMovementVectorFromKeyboard
import codes.som.hibiscus.world
import net.minecraft.client.input.Input
import net.minecraft.client.network.ClientPlayerEntity
@ -18,8 +19,6 @@ import net.minecraft.entity.EntityType
import net.minecraft.entity.MovementType
import net.minecraft.nbt.NbtCompound
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 org.lwjgl.glfw.GLFW.GLFW_KEY_TAB
import org.lwjgl.glfw.GLFW.GLFW_PRESS
@ -78,30 +77,10 @@ class Freecam : Feature("Freecam", FeatureCategory.VISUAL) {
}
if (!isControllingPlayer) {
val yaw = MathHelper.RADIANS_PER_DEGREE * 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)
val movement = constructMovementVectorFromKeyboard(view.yaw)
.multiply(speed.toDouble())
view.move(MovementType.SELF, movement) // Update entity positional state properly by calling move()
// 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 imGuiGl3 = ImGuiImplGl3()
private var didRender = true
var stalled = false
fun setup() {
ImGui.createContext()
@ -29,8 +32,15 @@ object ImGuiRenderer {
}
fun beginFrame(delta: Float) {
imGuiGlfw.newFrame()
ImGui.newFrame()
if (didRender) {
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) {
@ -43,5 +53,6 @@ object ImGuiRenderer {
ImGui.renderPlatformWindowsDefault()
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
},
"mixins": [
"MixinBackgroundRenderer",
"MixinClientConnection",
"MixinClientPlayerEntity",
"MixinClientPlayNetworkHandler",