Add the 'Freecam' feature
parent
f3f3b21848
commit
f64139b600
|
@ -54,8 +54,10 @@ dependencies {
|
||||||
|
|
||||||
runtimeOnly("org.joml:joml:1.10.2")
|
runtimeOnly("org.joml:joml:1.10.2")
|
||||||
runtimeOnly("org.anarres:jcpp:1.4.14")
|
runtimeOnly("org.anarres:jcpp:1.4.14")
|
||||||
|
|
||||||
modRuntimeOnly(files("vendor/mods/iris-mc1.18.1-1.2.0-pre.jar"))
|
modRuntimeOnly(files("vendor/mods/iris-mc1.18.1-1.2.0-pre.jar"))
|
||||||
modRuntimeOnly(files("vendor/mods/sodium-fabric-mc1.18.1-0.4.0-alpha6+build.14.jar"))
|
modRuntimeOnly(files("vendor/mods/sodium-fabric-mc1.18.1-0.4.0-alpha6+build.14.jar"))
|
||||||
|
modRuntimeOnly(files("vendor/mods/lazydfu-0.1.2.jar"))
|
||||||
}
|
}
|
||||||
|
|
||||||
loom {
|
loom {
|
||||||
|
|
|
@ -2,6 +2,7 @@ package codes.som.hibiscus.mixins;
|
||||||
|
|
||||||
import codes.som.hibiscus.HibiscusMod;
|
import codes.som.hibiscus.HibiscusMod;
|
||||||
import codes.som.hibiscus.events.MovePlayerEvent;
|
import codes.som.hibiscus.events.MovePlayerEvent;
|
||||||
|
import codes.som.hibiscus.events.PlayerPreTickEvent;
|
||||||
import codes.som.hibiscus.events.PlayerTickEvent;
|
import codes.som.hibiscus.events.PlayerTickEvent;
|
||||||
import codes.som.hibiscus.events.SendChatEvent;
|
import codes.som.hibiscus.events.SendChatEvent;
|
||||||
import net.minecraft.client.network.ClientPlayerEntity;
|
import net.minecraft.client.network.ClientPlayerEntity;
|
||||||
|
@ -16,6 +17,11 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||||
|
|
||||||
@Mixin(ClientPlayerEntity.class)
|
@Mixin(ClientPlayerEntity.class)
|
||||||
public abstract class MixinClientPlayerEntity {
|
public abstract class MixinClientPlayerEntity {
|
||||||
|
@Inject(method = "tick", at = @At("HEAD"))
|
||||||
|
private void onPreTick(CallbackInfo ci) {
|
||||||
|
HibiscusMod.bus().fire(PlayerPreTickEvent.INSTANCE);
|
||||||
|
}
|
||||||
|
|
||||||
@Inject(method = "tick", at = @At("RETURN"))
|
@Inject(method = "tick", at = @At("RETURN"))
|
||||||
private void onPostTick(CallbackInfo ci) {
|
private void onPostTick(CallbackInfo ci) {
|
||||||
HibiscusMod.bus().fire(PlayerTickEvent.INSTANCE);
|
HibiscusMod.bus().fire(PlayerTickEvent.INSTANCE);
|
||||||
|
|
|
@ -8,4 +8,7 @@ import org.spongepowered.asm.mixin.gen.Accessor;
|
||||||
public interface MixinExtPlayerInteractEntityC2SPacket {
|
public interface MixinExtPlayerInteractEntityC2SPacket {
|
||||||
@Accessor("type")
|
@Accessor("type")
|
||||||
PlayerInteractEntityC2SPacket.InteractTypeHandler getTypeHandler();
|
PlayerInteractEntityC2SPacket.InteractTypeHandler getTypeHandler();
|
||||||
|
|
||||||
|
@Accessor("entityId")
|
||||||
|
int getEntityId();
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,10 +1,13 @@
|
||||||
package codes.som.hibiscus.mixins;
|
package codes.som.hibiscus.mixins;
|
||||||
|
|
||||||
import codes.som.hibiscus.HibiscusMod;
|
import codes.som.hibiscus.HibiscusMod;
|
||||||
import codes.som.hibiscus.events.RenderWorldEvent;
|
import codes.som.hibiscus.events.Render3DEvent;
|
||||||
|
import codes.som.hibiscus.events.RenderHandEvent;
|
||||||
|
import codes.som.hibiscus.util.graphics.MinecraftRenderPipelineProgress;
|
||||||
import codes.som.hibiscus.util.graphics.WorldToScreenProjection;
|
import codes.som.hibiscus.util.graphics.WorldToScreenProjection;
|
||||||
import com.mojang.blaze3d.systems.RenderSystem;
|
import com.mojang.blaze3d.systems.RenderSystem;
|
||||||
import net.minecraft.client.MinecraftClient;
|
import net.minecraft.client.MinecraftClient;
|
||||||
|
import net.minecraft.client.gui.hud.InGameHud;
|
||||||
import net.minecraft.client.render.Camera;
|
import net.minecraft.client.render.Camera;
|
||||||
import net.minecraft.client.render.GameRenderer;
|
import net.minecraft.client.render.GameRenderer;
|
||||||
import net.minecraft.client.util.math.MatrixStack;
|
import net.minecraft.client.util.math.MatrixStack;
|
||||||
|
@ -14,6 +17,7 @@ import org.spongepowered.asm.mixin.Mixin;
|
||||||
import org.spongepowered.asm.mixin.Shadow;
|
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.Inject;
|
import org.spongepowered.asm.mixin.injection.Inject;
|
||||||
|
import org.spongepowered.asm.mixin.injection.Redirect;
|
||||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||||
|
|
||||||
@Mixin(GameRenderer.class)
|
@Mixin(GameRenderer.class)
|
||||||
|
@ -40,7 +44,32 @@ public abstract class MixinGameRenderer {
|
||||||
|
|
||||||
matrices.push();
|
matrices.push();
|
||||||
RenderSystem.applyModelViewMatrix();
|
RenderSystem.applyModelViewMatrix();
|
||||||
HibiscusMod.bus().fire(new RenderWorldEvent(tickDelta, this.camera, matrices));
|
HibiscusMod.bus().fire(new Render3DEvent(tickDelta, this.camera, matrices));
|
||||||
matrices.pop();
|
matrices.pop();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Redirect(method = "render", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/hud/InGameHud;render(Lnet/minecraft/client/util/math/MatrixStack;F)V"))
|
||||||
|
private void callRenderOverlay(InGameHud inGameHud, MatrixStack matrices, float tickDelta) {
|
||||||
|
MinecraftRenderPipelineProgress.INSTANCE.setDrawingUI(true);
|
||||||
|
inGameHud.render(matrices, tickDelta);
|
||||||
|
MinecraftRenderPipelineProgress.INSTANCE.setDrawingUI(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Inject(method = "updateTargetedEntity", at = @At("HEAD"))
|
||||||
|
public void onPreUpdateTargetedEntity(float tickDelta, CallbackInfo ci) {
|
||||||
|
MinecraftRenderPipelineProgress.INSTANCE.setProcessingInput(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Inject(method = "updateTargetedEntity", at = @At("RETURN"))
|
||||||
|
public void onPostUpdateTargetedEntity(float tickDelta, CallbackInfo ci) {
|
||||||
|
MinecraftRenderPipelineProgress.INSTANCE.setProcessingInput(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Inject(method = "renderHand", at = @At("HEAD"), cancellable = true)
|
||||||
|
private void onRenderHand(MatrixStack matrices, Camera camera, float tickDelta, CallbackInfo ci) {
|
||||||
|
var event = new RenderHandEvent(tickDelta);
|
||||||
|
HibiscusMod.bus().fire(event);
|
||||||
|
if (event.isCancelled())
|
||||||
|
ci.cancel();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,17 +1,21 @@
|
||||||
package codes.som.hibiscus.mixins;
|
package codes.som.hibiscus.mixins;
|
||||||
|
|
||||||
import codes.som.hibiscus.HibiscusMod;
|
import codes.som.hibiscus.HibiscusMod;
|
||||||
|
import codes.som.hibiscus.events.GetRenderViewEntityEvent;
|
||||||
import codes.som.hibiscus.events.PostRenderAllEvent;
|
import codes.som.hibiscus.events.PostRenderAllEvent;
|
||||||
import codes.som.hibiscus.gui.ImGuiRenderer;
|
import codes.som.hibiscus.gui.ImGuiRenderer;
|
||||||
|
import codes.som.hibiscus.util.graphics.MinecraftRenderPipelineProgress;
|
||||||
import net.minecraft.client.MinecraftClient;
|
import net.minecraft.client.MinecraftClient;
|
||||||
import net.minecraft.client.RunArgs;
|
import net.minecraft.client.RunArgs;
|
||||||
import net.minecraft.client.render.RenderTickCounter;
|
import net.minecraft.client.render.RenderTickCounter;
|
||||||
|
import net.minecraft.entity.Entity;
|
||||||
import org.spongepowered.asm.mixin.Final;
|
import org.spongepowered.asm.mixin.Final;
|
||||||
import org.spongepowered.asm.mixin.Mixin;
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
import org.spongepowered.asm.mixin.Shadow;
|
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.Inject;
|
import org.spongepowered.asm.mixin.injection.Inject;
|
||||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||||
|
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||||
|
|
||||||
@Mixin(MinecraftClient.class)
|
@Mixin(MinecraftClient.class)
|
||||||
public abstract class MixinMinecraftClient {
|
public abstract class MixinMinecraftClient {
|
||||||
|
@ -42,4 +46,25 @@ public abstract class MixinMinecraftClient {
|
||||||
HibiscusMod.bus().fire(new PostRenderAllEvent(delta));
|
HibiscusMod.bus().fire(new PostRenderAllEvent(delta));
|
||||||
ImGuiRenderer.INSTANCE.finishFrame(delta);
|
ImGuiRenderer.INSTANCE.finishFrame(delta);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Inject(method = "getCameraEntity", at = @At("RETURN"), cancellable = true)
|
||||||
|
private void onGetCameraEntity(CallbackInfoReturnable<Entity> cir) {
|
||||||
|
Entity view = cir.getReturnValue();
|
||||||
|
|
||||||
|
if (view != null) {
|
||||||
|
var event = new GetRenderViewEntityEvent(view);
|
||||||
|
HibiscusMod.bus().fire(event);
|
||||||
|
cir.setReturnValue(event.getViewEntity());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Inject(method = "handleInputEvents", at = @At("HEAD"))
|
||||||
|
private void onPreHandleInputEvents(CallbackInfo ci) {
|
||||||
|
MinecraftRenderPipelineProgress.INSTANCE.setProcessingInput(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Inject(method = "handleInputEvents", at = @At("RETURN"))
|
||||||
|
private void onPostHandleInputEvents(CallbackInfo ci) {
|
||||||
|
MinecraftRenderPipelineProgress.INSTANCE.setProcessingInput(false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,49 @@
|
||||||
|
package codes.som.hibiscus.mixins;
|
||||||
|
|
||||||
|
import codes.som.hibiscus.HibiscusMod;
|
||||||
|
import codes.som.hibiscus.events.*;
|
||||||
|
import codes.som.hibiscus.util.graphics.MinecraftRenderPipelineProgress;
|
||||||
|
import net.minecraft.client.network.ClientPlayerEntity;
|
||||||
|
import net.minecraft.client.render.Camera;
|
||||||
|
import net.minecraft.client.render.GameRenderer;
|
||||||
|
import net.minecraft.client.render.LightmapTextureManager;
|
||||||
|
import net.minecraft.client.render.WorldRenderer;
|
||||||
|
import net.minecraft.client.util.math.MatrixStack;
|
||||||
|
import net.minecraft.util.math.Matrix4f;
|
||||||
|
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.Redirect;
|
||||||
|
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||||
|
|
||||||
|
@Mixin(WorldRenderer.class)
|
||||||
|
public abstract class MixinWorldRenderer {
|
||||||
|
@Inject(method = "render", at = @At("HEAD"))
|
||||||
|
private void onPreRenderWorld(MatrixStack matrices, float tickDelta, long limitTime, boolean renderBlockOutline, Camera camera, GameRenderer gameRenderer, LightmapTextureManager lightmapTextureManager, Matrix4f matrix4f, CallbackInfo ci) {
|
||||||
|
HibiscusMod.bus().fire(new PreRenderWorldEvent(tickDelta, camera, matrices));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Inject(method = "render", at = @At("HEAD"))
|
||||||
|
private void onPostRenderWorld(MatrixStack matrices, float tickDelta, long limitTime, boolean renderBlockOutline, Camera camera, GameRenderer gameRenderer, LightmapTextureManager lightmapTextureManager, Matrix4f matrix4f, CallbackInfo ci) {
|
||||||
|
HibiscusMod.bus().fire(new PostRenderWorldEvent(tickDelta, camera, matrices));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Redirect(method = "render", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/network/ClientPlayerEntity;isSpectator()Z"))
|
||||||
|
public boolean cancelCulling(ClientPlayerEntity instance) {
|
||||||
|
var event = new WorldCullingEvent();
|
||||||
|
HibiscusMod.bus().fire(event);
|
||||||
|
return instance.isSpectator() || event.isCancelled();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Inject(method = "render", at = @At(value = "INVOKE_STRING", target = "Lnet/minecraft/util/profiler/Profiler;swap(Ljava/lang/String;)V", args = "ldc=entities"))
|
||||||
|
private void startRenderEntities(MatrixStack matrices, float tickDelta, long limitTime, boolean renderBlockOutline, Camera camera, GameRenderer gameRenderer, LightmapTextureManager lightmapTextureManager, Matrix4f matrix4f, CallbackInfo ci) {
|
||||||
|
MinecraftRenderPipelineProgress.INSTANCE.setRenderingEntities(true);
|
||||||
|
HibiscusMod.bus().fire(new PreRenderEntitiesEvent(tickDelta));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Inject(method = "render", at = @At(value = "INVOKE_STRING", target = "Lnet/minecraft/util/profiler/Profiler;swap(Ljava/lang/String;)V", args = "ldc=blockentities"))
|
||||||
|
private void startRenderBlockEntities(MatrixStack matrices, float tickDelta, long limitTime, boolean renderBlockOutline, Camera camera, GameRenderer gameRenderer, LightmapTextureManager lightmapTextureManager, Matrix4f matrix4f, CallbackInfo ci) {
|
||||||
|
MinecraftRenderPipelineProgress.INSTANCE.setRenderingEntities(false);
|
||||||
|
HibiscusMod.bus().fire(new PostRenderEntitiesEvent(tickDelta));
|
||||||
|
}
|
||||||
|
}
|
|
@ -6,13 +6,16 @@ import codes.som.hibiscus.api.keybinds.KeybindRegistry
|
||||||
import codes.som.hibiscus.commands.CommandRegistry
|
import codes.som.hibiscus.commands.CommandRegistry
|
||||||
import codes.som.hibiscus.events.KeyEvent
|
import codes.som.hibiscus.events.KeyEvent
|
||||||
import codes.som.hibiscus.features.FeaturesRegistry
|
import codes.som.hibiscus.features.FeaturesRegistry
|
||||||
|
import codes.som.hibiscus.features.combat.Criticals
|
||||||
|
import codes.som.hibiscus.features.exploits.AntiGhost
|
||||||
|
import codes.som.hibiscus.features.player.NoFallDamage
|
||||||
import codes.som.hibiscus.gui.ImGuiScreen
|
import codes.som.hibiscus.gui.ImGuiScreen
|
||||||
import codes.som.hibiscus.util.command.ChatCommandListener
|
import codes.som.hibiscus.util.command.ChatCommandListener
|
||||||
import codes.som.hibiscus.util.input.KeybindDispatcher
|
import codes.som.hibiscus.util.input.KeybindDispatcher
|
||||||
import codes.som.hibiscus.util.netmoving.NetworkMovingDispatcher
|
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.*
|
||||||
|
|
||||||
@Suppress("UNUSED")
|
@Suppress("UNUSED")
|
||||||
object HibiscusMod : ModInitializer {
|
object HibiscusMod : ModInitializer {
|
||||||
|
@ -45,6 +48,7 @@ object HibiscusMod : ModInitializer {
|
||||||
bus.register(ChatCommandListener())
|
bus.register(ChatCommandListener())
|
||||||
bus.register(KeybindDispatcher())
|
bus.register(KeybindDispatcher())
|
||||||
|
|
||||||
|
defaultConfig()
|
||||||
// TODO: Load files
|
// TODO: Load files
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -55,4 +59,15 @@ object HibiscusMod : ModInitializer {
|
||||||
system.reset()
|
system.reset()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun defaultConfig() {
|
||||||
|
keybinds.register(GLFW_KEY_R, "fly")
|
||||||
|
keybinds.register(GLFW_KEY_O, "nofall")
|
||||||
|
keybinds.register(GLFW_KEY_G, "speed")
|
||||||
|
keybinds.register(GLFW_KEY_B, "freecam")
|
||||||
|
|
||||||
|
features.getFeature<AntiGhost>().enabled = true
|
||||||
|
features.getFeature<NoFallDamage>().enabled = true
|
||||||
|
features.getFeature<Criticals>().enabled = true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,6 +31,8 @@ abstract class Feature(val name: String, val category: FeatureCategory) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var hiddenInOverlay = false
|
||||||
|
|
||||||
open fun onEnable() {}
|
open fun onEnable() {}
|
||||||
open fun onDisable() {}
|
open fun onDisable() {}
|
||||||
|
|
||||||
|
|
|
@ -6,4 +6,5 @@ enum class FeatureCategory(val humanName: String) {
|
||||||
PLAYER("Player"),
|
PLAYER("Player"),
|
||||||
MOVEMENT("Movement"),
|
MOVEMENT("Movement"),
|
||||||
OVERLAY("Overlay"),
|
OVERLAY("Overlay"),
|
||||||
|
VISUAL("Visual"),
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,7 @@ import codes.som.hibiscus.api.event.Cancellable
|
||||||
import codes.som.hibiscus.api.event.Event
|
import codes.som.hibiscus.api.event.Event
|
||||||
import net.minecraft.entity.MovementType
|
import net.minecraft.entity.MovementType
|
||||||
|
|
||||||
|
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
|
||||||
|
|
|
@ -1,8 +1,21 @@
|
||||||
package codes.som.hibiscus.events
|
package codes.som.hibiscus.events
|
||||||
|
|
||||||
|
import codes.som.hibiscus.api.event.Cancellable
|
||||||
import codes.som.hibiscus.api.event.Event
|
import codes.som.hibiscus.api.event.Event
|
||||||
import net.minecraft.client.render.Camera
|
import net.minecraft.client.render.Camera
|
||||||
import net.minecraft.client.util.math.MatrixStack
|
import net.minecraft.client.util.math.MatrixStack
|
||||||
|
import net.minecraft.entity.Entity
|
||||||
|
|
||||||
class PostRenderAllEvent(val delta: Float) : Event
|
class PostRenderAllEvent(val delta: Float) : Event
|
||||||
class RenderWorldEvent(val delta: Float, val camera: Camera, val matrices: MatrixStack) : Event
|
class Render3DEvent(val delta: Float, val camera: Camera, val matrices: MatrixStack) : Event
|
||||||
|
|
||||||
|
class WorldCullingEvent : Cancellable(), Event
|
||||||
|
|
||||||
|
class GetRenderViewEntityEvent(var viewEntity: Entity) : Event
|
||||||
|
|
||||||
|
class PreRenderWorldEvent(val delta: Float, val camera: Camera, val matrices: MatrixStack) : Event
|
||||||
|
class PreRenderEntitiesEvent(val delta: Float) : Event
|
||||||
|
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
|
||||||
|
|
|
@ -8,6 +8,7 @@ import codes.som.hibiscus.features.movement.Flight
|
||||||
import codes.som.hibiscus.features.movement.Speed
|
import codes.som.hibiscus.features.movement.Speed
|
||||||
import codes.som.hibiscus.features.overlay.Overlay
|
import codes.som.hibiscus.features.overlay.Overlay
|
||||||
import codes.som.hibiscus.features.player.NoFallDamage
|
import codes.som.hibiscus.features.player.NoFallDamage
|
||||||
|
import codes.som.hibiscus.features.visual.Freecam
|
||||||
import codes.som.hibiscus.util.Resettable
|
import codes.som.hibiscus.util.Resettable
|
||||||
|
|
||||||
fun allFeatureClasses(): Array<() -> Feature> = arrayOf(
|
fun allFeatureClasses(): Array<() -> Feature> = arrayOf(
|
||||||
|
@ -18,6 +19,7 @@ fun allFeatureClasses(): Array<() -> Feature> = arrayOf(
|
||||||
::Criticals,
|
::Criticals,
|
||||||
::Ghost,
|
::Ghost,
|
||||||
::AntiGhost,
|
::AntiGhost,
|
||||||
|
::Freecam,
|
||||||
)
|
)
|
||||||
|
|
||||||
class FeaturesRegistry : Resettable {
|
class FeaturesRegistry : Resettable {
|
||||||
|
|
|
@ -7,13 +7,12 @@ import codes.som.hibiscus.events.PostRenderAllEvent
|
||||||
import codes.som.hibiscus.mc
|
import codes.som.hibiscus.mc
|
||||||
import imgui.ImGui
|
import imgui.ImGui
|
||||||
import imgui.flag.ImGuiCol
|
import imgui.flag.ImGuiCol
|
||||||
import imgui.flag.ImGuiStyleVar
|
|
||||||
import imgui.flag.ImGuiWindowFlags
|
import imgui.flag.ImGuiWindowFlags
|
||||||
|
|
||||||
class Overlay : Feature("Overlay", FeatureCategory.OVERLAY) {
|
class Overlay : Feature("Overlay", FeatureCategory.OVERLAY) {
|
||||||
init {
|
init {
|
||||||
val enabledFeatures by values.bool("Enabled Features", true)
|
val enabledFeatures by values.bool("Enabled Features", true)
|
||||||
|
|
||||||
on { _: PostRenderAllEvent ->
|
on { _: PostRenderAllEvent ->
|
||||||
if (mc.world == null || mc.options.debugEnabled)
|
if (mc.world == null || mc.options.debugEnabled)
|
||||||
return@on
|
return@on
|
||||||
|
@ -24,10 +23,10 @@ class Overlay : Feature("Overlay", FeatureCategory.OVERLAY) {
|
||||||
|
|
||||||
ImGui.pushStyleColor(ImGuiCol.WindowBg, 0, 0, 0, 0)
|
ImGui.pushStyleColor(ImGuiCol.WindowBg, 0, 0, 0, 0)
|
||||||
ImGui.begin(
|
ImGui.begin(
|
||||||
"Overlay##Overlay",
|
"Overlay##Overlay",
|
||||||
ImGuiWindowFlags.NoMove + ImGuiWindowFlags.NoInputs + ImGuiWindowFlags.NoDecoration
|
ImGuiWindowFlags.NoMove + ImGuiWindowFlags.NoInputs + ImGuiWindowFlags.NoDecoration
|
||||||
)
|
)
|
||||||
|
|
||||||
if (enabledFeatures)
|
if (enabledFeatures)
|
||||||
drawEnabledFeatures()
|
drawEnabledFeatures()
|
||||||
|
|
||||||
|
@ -37,35 +36,35 @@ class Overlay : Feature("Overlay", FeatureCategory.OVERLAY) {
|
||||||
|
|
||||||
enabled = true
|
enabled = true
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun drawEnabledFeatures() {
|
private fun drawEnabledFeatures() {
|
||||||
val enabledFeatures =
|
val displayedFeatures =
|
||||||
HibiscusMod.features.getAllFeatures()
|
HibiscusMod.features.getAllFeatures()
|
||||||
.filter { it.category != FeatureCategory.OVERLAY }
|
.filter { !it.hiddenInOverlay }
|
||||||
.filter { it.enabled }.toList()
|
.filter { it.enabled }.toList()
|
||||||
|
|
||||||
if (enabledFeatures.isEmpty())
|
if (displayedFeatures.isEmpty())
|
||||||
return
|
return
|
||||||
|
|
||||||
val padX = 8f
|
val padX = 8f
|
||||||
val padY = 8f
|
val padY = 8f
|
||||||
|
|
||||||
val pos = ImGui.getCursorScreenPos()
|
val pos = ImGui.getCursorScreenPos()
|
||||||
ImGui.setCursorScreenPos(pos.x + padX, pos.y + padY)
|
ImGui.setCursorScreenPos(pos.x + padX, pos.y + padY)
|
||||||
|
|
||||||
ImGui.beginGroup()
|
ImGui.beginGroup()
|
||||||
|
|
||||||
ImGui.pushStyleColor(ImGuiCol.Text, 244, 161, 255, 255)
|
ImGui.pushStyleColor(ImGuiCol.Text, 244, 161, 255, 255)
|
||||||
for (feature in enabledFeatures)
|
for (feature in displayedFeatures)
|
||||||
ImGui.text(feature.name)
|
ImGui.text(feature.name)
|
||||||
ImGui.popStyleColor()
|
ImGui.popStyleColor()
|
||||||
|
|
||||||
ImGui.endGroup()
|
ImGui.endGroup()
|
||||||
val min = ImGui.getItemRectMin()
|
val min = ImGui.getItemRectMin()
|
||||||
val max = ImGui.getItemRectMax()
|
val max = ImGui.getItemRectMax()
|
||||||
ImGui.getBackgroundDrawList().addRectFilled(
|
ImGui.getBackgroundDrawList().addRectFilled(
|
||||||
min.x - padX, min.y - padY, max.x + padX,
|
min.x - padX, min.y - padY, max.x + padX,
|
||||||
max.y + padY,
|
max.y + padY,
|
||||||
0xAA0A0A0AL.toInt(),
|
0xAA0A0A0AL.toInt(),
|
||||||
0F
|
0F
|
||||||
)
|
)
|
||||||
|
|
|
@ -0,0 +1,267 @@
|
||||||
|
package codes.som.hibiscus.features.visual
|
||||||
|
|
||||||
|
import codes.som.hibiscus.HibiscusMod
|
||||||
|
import codes.som.hibiscus.api.feature.Feature
|
||||||
|
import codes.som.hibiscus.api.feature.FeatureCategory
|
||||||
|
import codes.som.hibiscus.events.*
|
||||||
|
import codes.som.hibiscus.mc
|
||||||
|
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.world
|
||||||
|
import net.minecraft.client.input.Input
|
||||||
|
import net.minecraft.client.network.ClientPlayerEntity
|
||||||
|
import net.minecraft.client.option.Perspective
|
||||||
|
import net.minecraft.entity.Entity
|
||||||
|
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
|
||||||
|
|
||||||
|
class Freecam : Feature("Freecam", FeatureCategory.VISUAL) {
|
||||||
|
private var camEntity: Entity? = null
|
||||||
|
private var playerInput: Input? = null
|
||||||
|
private var isControllingPlayer: Boolean = false
|
||||||
|
|
||||||
|
private var origYaw = 0F
|
||||||
|
private var origPitch = 0F
|
||||||
|
|
||||||
|
private val toggleKey by values.key("Toggle Key", GLFW_KEY_TAB)
|
||||||
|
|
||||||
|
init {
|
||||||
|
var isPlayerTicking = false
|
||||||
|
on { _: PlayerPreTickEvent -> isPlayerTicking = true }
|
||||||
|
on { _: PlayerTickEvent -> isPlayerTicking = false }
|
||||||
|
|
||||||
|
on { event: WorldCullingEvent -> event.cancel() }
|
||||||
|
|
||||||
|
on { event: GetRenderViewEntityEvent ->
|
||||||
|
val view = camEntity ?: return@on
|
||||||
|
|
||||||
|
if (isPlayerTicking)
|
||||||
|
return@on
|
||||||
|
|
||||||
|
if (MinecraftRenderPipelineProgress.isRenderingEntities || MinecraftRenderPipelineProgress.isDrawingUI)
|
||||||
|
return@on
|
||||||
|
|
||||||
|
if (isControllingPlayer && MinecraftRenderPipelineProgress.isProcessingInput)
|
||||||
|
return@on
|
||||||
|
|
||||||
|
event.viewEntity = view
|
||||||
|
}
|
||||||
|
|
||||||
|
on { _: PlayerPreTickEvent ->
|
||||||
|
val view = camEntity ?: return@on
|
||||||
|
|
||||||
|
if (isControllingPlayer) {
|
||||||
|
origYaw = player.yaw
|
||||||
|
origPitch = player.pitch
|
||||||
|
}
|
||||||
|
|
||||||
|
player.yaw = origYaw
|
||||||
|
player.pitch = origPitch
|
||||||
|
|
||||||
|
with(view) {
|
||||||
|
prevHorizontalSpeed = horizontalSpeed
|
||||||
|
prevX = x
|
||||||
|
prevY = y
|
||||||
|
prevZ = z
|
||||||
|
prevPitch = pitch
|
||||||
|
prevYaw = yaw
|
||||||
|
}
|
||||||
|
|
||||||
|
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)
|
||||||
|
|
||||||
|
view.move(MovementType.SELF, movement) // Update entity positional state properly by calling move()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
on { event: KeyEvent ->
|
||||||
|
if (event.action == GLFW_PRESS && event.key == toggleKey) {
|
||||||
|
isControllingPlayer = !isControllingPlayer
|
||||||
|
updatePlayerControl()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var yawPreRender = 0F
|
||||||
|
var pitchPreRender = 0F
|
||||||
|
var prevPitchPreRender = 0F
|
||||||
|
on { _: PreRenderWorldEvent ->
|
||||||
|
yawPreRender = player.yaw
|
||||||
|
pitchPreRender = player.pitch
|
||||||
|
prevPitchPreRender = player.prevPitch
|
||||||
|
|
||||||
|
camEntity?.let { view ->
|
||||||
|
player.yaw = view.yaw
|
||||||
|
player.pitch = view.pitch
|
||||||
|
player.prevPitch = view.prevPitch
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var lastMouseX = 0.0
|
||||||
|
var lastMouseY = 0.0
|
||||||
|
var mouseDeltaX = 0.0
|
||||||
|
var mouseDeltaY = 0.0
|
||||||
|
HibiscusMod.bus.register { _: PostRenderWorldEvent ->
|
||||||
|
mouseDeltaX = mc.mouse.x - lastMouseX
|
||||||
|
mouseDeltaY = mc.mouse.y - lastMouseY
|
||||||
|
lastMouseX = mc.mouse.x
|
||||||
|
lastMouseY = mc.mouse.y
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: On post render world, update the camEntity's view angles based on mouse delta
|
||||||
|
on { _: PostRenderWorldEvent ->
|
||||||
|
val view = camEntity ?: return@on
|
||||||
|
|
||||||
|
if (isControllingPlayer)
|
||||||
|
return@on
|
||||||
|
|
||||||
|
if (mc.isWindowFocused && mc.currentScreen == null) {
|
||||||
|
val mouseSensAdj = mc.options.mouseSensitivity * 0.6 + 0.2
|
||||||
|
val mouseSensAngleCoeff = mouseSensAdj * mouseSensAdj * mouseSensAdj * 8.0
|
||||||
|
val invertYCoeff = if (mc.options.invertYMouse) -1 else 1
|
||||||
|
view.changeLookDirection(
|
||||||
|
mouseDeltaX * mouseSensAngleCoeff,
|
||||||
|
mouseDeltaY * mouseSensAngleCoeff * invertYCoeff
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// TODO: Push / pop origYaw so that the player matches their server-side look angles
|
||||||
|
var perspectivePreRender: Perspective? = null
|
||||||
|
on { event: PreRenderEntitiesEvent ->
|
||||||
|
player.yaw = yawPreRender
|
||||||
|
player.pitch = pitchPreRender
|
||||||
|
player.prevPitch = prevPitchPreRender
|
||||||
|
|
||||||
|
if (!isControllingPlayer) {
|
||||||
|
player.yaw = origYaw
|
||||||
|
player.pitch = origPitch
|
||||||
|
}
|
||||||
|
|
||||||
|
perspectivePreRender = mc.options.perspective
|
||||||
|
mc.options.perspective = Perspective.THIRD_PERSON_BACK
|
||||||
|
mc.gameRenderer.camera.update(mc.world, mc.player, true, false, event.delta)
|
||||||
|
}
|
||||||
|
|
||||||
|
on { event: PostRenderEntitiesEvent ->
|
||||||
|
mc.options.perspective = perspectivePreRender!!
|
||||||
|
|
||||||
|
player.yaw = yawPreRender
|
||||||
|
player.pitch = pitchPreRender
|
||||||
|
player.prevPitch = prevPitchPreRender
|
||||||
|
|
||||||
|
mc.gameRenderer.camera.update(
|
||||||
|
mc.world,
|
||||||
|
mc.getCameraEntity() ?: mc.player,
|
||||||
|
!mc.options.perspective.isFirstPerson,
|
||||||
|
mc.options.perspective.isFrontView,
|
||||||
|
event.delta
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
on { event: SendPacketEvent ->
|
||||||
|
val (packet) = event
|
||||||
|
if (packet is PlayerInteractEntityC2SPacket) {
|
||||||
|
requireExtension<MixinExtPlayerInteractEntityC2SPacket>(packet)
|
||||||
|
if (packet.typeHandler.type == PlayerInteractEntityC2SPacket.InteractType.ATTACK && packet.entityId == player.id) {
|
||||||
|
event.cancel()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
on { event: RenderHandEvent ->
|
||||||
|
if (!isControllingPlayer)
|
||||||
|
event.cancel()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun updatePlayerControl() {
|
||||||
|
if (isControllingPlayer) {
|
||||||
|
if (playerInput != null)
|
||||||
|
player.input = playerInput
|
||||||
|
} else {
|
||||||
|
playerInput = player.input
|
||||||
|
player.input = Input()
|
||||||
|
player.input.sneaking = playerInput!!.sneaking
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun setupCamera() {
|
||||||
|
isControllingPlayer = false
|
||||||
|
camEntity = FreecamControllerEntity(player, world)
|
||||||
|
|
||||||
|
updatePlayerControl()
|
||||||
|
origYaw = player.yaw
|
||||||
|
origPitch = player.pitch
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onEnable() {
|
||||||
|
if (mc.world == null)
|
||||||
|
return
|
||||||
|
|
||||||
|
setupCamera()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onDisable() {
|
||||||
|
if (mc.world == null)
|
||||||
|
return
|
||||||
|
|
||||||
|
isControllingPlayer = true
|
||||||
|
updatePlayerControl()
|
||||||
|
|
||||||
|
camEntity = null
|
||||||
|
playerInput = null
|
||||||
|
}
|
||||||
|
|
||||||
|
class FreecamControllerEntity(localPlayer: ClientPlayerEntity, world: World) : Entity(EntityType.PLAYER, world) {
|
||||||
|
init {
|
||||||
|
updatePositionAndAngles(
|
||||||
|
localPlayer.x, localPlayer.y, localPlayer.z,
|
||||||
|
localPlayer.yaw, localPlayer.pitch
|
||||||
|
)
|
||||||
|
setRotation(localPlayer.yaw, localPlayer.pitch)
|
||||||
|
noClip = true
|
||||||
|
setNoGravity(true)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun initDataTracker() {
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun readCustomDataFromNbt(nbt: NbtCompound?) {
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun writeCustomDataToNbt(nbt: NbtCompound?) {
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun createSpawnPacket() = null
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,7 @@
|
||||||
|
package codes.som.hibiscus.util.graphics
|
||||||
|
|
||||||
|
object MinecraftRenderPipelineProgress {
|
||||||
|
var isRenderingEntities: Boolean = false
|
||||||
|
var isDrawingUI: Boolean = false
|
||||||
|
var isProcessingInput: Boolean = false
|
||||||
|
}
|
|
@ -16,6 +16,7 @@
|
||||||
"MixinExtUpdatePlayerAbilitiesC2SPacket",
|
"MixinExtUpdatePlayerAbilitiesC2SPacket",
|
||||||
"MixinGameRenderer",
|
"MixinGameRenderer",
|
||||||
"MixinKeyboard",
|
"MixinKeyboard",
|
||||||
"MixinMinecraftClient"
|
"MixinMinecraftClient",
|
||||||
|
"MixinWorldRenderer"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue