Merge remote-tracking branch 'upstream/master' into enhancement/Utils

This commit is contained in:
Xiaro 2021-03-08 19:07:07 -05:00
commit 73aa624402
No known key found for this signature in database
GPG Key ID: 996D265D6E155377
41 changed files with 1173 additions and 870 deletions

@ -1 +1 @@
Subproject commit 1daa452960100da342d09903f46c1ffc02d72963
Subproject commit d7d5e820e08ba859188c3bb33671544883afa513

@ -1 +1 @@
Subproject commit 0ad2b06b687679a658995f20e0d79bf8c12c7af1
Subproject commit 9ed896374539caff7a09e1eb403ffc3f8abc7ec5

@ -1 +1 @@
Subproject commit 46b7f83e9efd03e526db36ffd44b4e5e3c5baa69
Subproject commit 6c1f2700355308942c8851e9103d8122e08be5da

View File

@ -22,6 +22,6 @@ public class MixinStateImplementation {
@Inject(method = "addCollisionBoxToList", at = @At("HEAD"), cancellable = true)
public void addCollisionBoxToList(World worldIn, BlockPos pos, AxisAlignedBB entityBox, List<AxisAlignedBB> collidingBoxes, Entity entityIn, boolean isActualState, CallbackInfo ci) {
Jesus.handleAddCollisionBoxToList(pos, block, entityIn, entityBox, collidingBoxes);
Jesus.handleAddCollisionBoxToList(pos, block, entityIn, collidingBoxes);
}
}

View File

@ -1,28 +0,0 @@
package org.kamiblue.client.mixin.client.render;
import net.minecraft.client.renderer.GlStateManager;
import org.kamiblue.client.util.graphics.GlStateUtils;
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(GlStateManager.class)
public class MixinGlStateManager {
@Inject(method = "color(FFF)V", at = @At("HEAD"), cancellable = true)
private static void color3f(float colorRed, float colorGreen, float colorBlue, CallbackInfo ci) {
if (GlStateUtils.getColorLock()) ci.cancel();
}
@Inject(method = "color(FFFF)V", at = @At("HEAD"), cancellable = true)
private static void color4f(float colorRed, float colorGreen, float colorBlue, float colorAlpha, CallbackInfo ci) {
if (GlStateUtils.getColorLock()) ci.cancel();
}
@Inject(method = "loadIdentity", at = @At("HEAD"))
private static void loadIdentity(CallbackInfo ci) {
GlStateUtils.colorLock(false);
}
}

View File

@ -1,56 +1,20 @@
package org.kamiblue.client.mixin.client.render;
import net.minecraft.client.renderer.GLAllocation;
import net.minecraft.client.renderer.GlStateManager;
import net.minecraft.client.renderer.entity.layers.LayerArmorBase;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.inventory.EntityEquipmentSlot;
import org.kamiblue.client.module.modules.render.ArmorHide;
import org.kamiblue.client.util.graphics.GlStateUtils;
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;
import java.nio.FloatBuffer;
import static org.lwjgl.opengl.GL11.*;
@Mixin(LayerArmorBase.class)
public abstract class MixinLayerArmorBase {
private static final FloatBuffer color = GLAllocation.createDirectFloatBuffer(16);
private static boolean texture2d = false;
private static boolean colorLock = false;
@Inject(method = "renderArmorLayer", at = @At("HEAD"), cancellable = true)
public void renderArmorLayerPre(EntityLivingBase entityLivingBaseIn, float limbSwing, float limbSwingAmount, float partialTicks, float ageInTicks, float netHeadYaw, float headPitch, float scale, EntityEquipmentSlot slotIn, CallbackInfo ci) {
if (ArmorHide.INSTANCE.isEnabled() && ArmorHide.shouldHide(slotIn, entityLivingBaseIn)) {
ci.cancel();
}
if (!ci.isCancelled()) {
colorLock = GlStateUtils.getColorLock();
texture2d = glGetBoolean(GL_TEXTURE_2D);
if (colorLock) {
glGetFloat(GL_CURRENT_COLOR, color);
GlStateUtils.colorLock(false);
}
if (!texture2d) {
GlStateManager.enableTexture2D();
}
}
}
@Inject(method = "renderArmorLayer", at = @At("RETURN"))
public void renderArmorLayerPost(EntityLivingBase entityLivingBaseIn, float limbSwing, float limbSwingAmount, float partialTicks, float ageInTicks, float netHeadYaw, float headPitch, float scale, EntityEquipmentSlot slotIn, CallbackInfo ci) {
if (colorLock) {
GlStateManager.color(color.get(0), color.get(1), color.get(2), color.get(3));
GlStateUtils.colorLock(true);
}
if (!texture2d) {
GlStateManager.disableTexture2D();
}
}
}

View File

@ -1,51 +0,0 @@
package org.kamiblue.client.mixin.client.render;
import net.minecraft.client.renderer.GLAllocation;
import net.minecraft.client.renderer.GlStateManager;
import net.minecraft.client.renderer.block.model.ItemCameraTransforms;
import net.minecraft.client.renderer.entity.layers.LayerHeldItem;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.item.ItemStack;
import net.minecraft.util.EnumHandSide;
import org.kamiblue.client.util.graphics.GlStateUtils;
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;
import java.nio.FloatBuffer;
import static org.lwjgl.opengl.GL11.*;
@Mixin(LayerHeldItem.class)
public abstract class MixinLayerHeldItem {
private static final FloatBuffer color = GLAllocation.createDirectFloatBuffer(16);
private static boolean texture2d = false;
private static boolean colorLock = false;
@Inject(method = "renderHeldItem", at = @At("HEAD"))
public void renderHeldItemPre(EntityLivingBase entity, ItemStack itemStack, ItemCameraTransforms.TransformType transformType, EnumHandSide handSide, CallbackInfo ci) {
colorLock = GlStateUtils.getColorLock();
texture2d = glGetBoolean(GL_TEXTURE_2D);
if (colorLock) {
glGetFloat(GL_CURRENT_COLOR, color);
GlStateUtils.colorLock(false);
}
if (!texture2d) {
GlStateManager.enableTexture2D();
}
}
@Inject(method = "renderHeldItem", at = @At("RETURN"))
public void renderHeldItemPost(EntityLivingBase entity, ItemStack itemStack, ItemCameraTransforms.TransformType transformType, EnumHandSide handSide, CallbackInfo ci) {
if (colorLock) {
GlStateManager.color(color.get(0), color.get(1), color.get(2), color.get(3));
GlStateUtils.colorLock(true);
}
if (!texture2d) {
GlStateManager.disableTexture2D();
}
}
}

View File

@ -1,66 +1,19 @@
package org.kamiblue.client.mixin.client.render;
import net.minecraft.client.renderer.GLAllocation;
import net.minecraft.client.renderer.GlStateManager;
import net.minecraft.client.renderer.entity.Render;
import net.minecraft.entity.Entity;
import org.kamiblue.client.module.modules.render.ESP;
import org.kamiblue.client.module.modules.render.Nametags;
import org.kamiblue.client.util.Wrapper;
import org.kamiblue.client.util.graphics.GlStateUtils;
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;
import java.nio.FloatBuffer;
import static org.lwjgl.opengl.GL11.*;
@Mixin(Render.class)
abstract class MixinRender<T extends Entity> {
private static final FloatBuffer color = GLAllocation.createDirectFloatBuffer(16);
private static boolean texture2d = false;
private static boolean colorLock = false;
@Inject(method = "renderLivingLabel", at = @At("HEAD"), cancellable = true)
protected void renderNamePre(T entityIn, String str, double x, double y, double z, int maxDistance, CallbackInfo ci) {
if (Nametags.INSTANCE.isEnabled() && Nametags.INSTANCE.checkEntityType(entityIn)) {
ci.cancel();
} else if (ESP.INSTANCE.isEnabled() && ESP.INSTANCE.getDrawingOutline()) {
if (ESP.INSTANCE.getDrawNametag()) {
Wrapper.getMinecraft().getFramebuffer().bindFramebuffer(false);
} else {
ci.cancel();
}
}
if (!ci.isCancelled()) {
colorLock = GlStateUtils.getColorLock();
texture2d = glGetBoolean(GL_TEXTURE_2D);
if (colorLock) {
glGetFloat(GL_CURRENT_COLOR, color);
GlStateUtils.colorLock(false);
}
if (!texture2d) {
GlStateManager.enableTexture2D();
}
}
}
@Inject(method = "renderLivingLabel", at = @At("RETURN"))
protected void renderNamePost(T entityIn, String str, double x, double y, double z, int maxDistance, CallbackInfo ci) {
if (ESP.INSTANCE.isEnabled() && ESP.INSTANCE.getDrawingOutline() && ESP.INSTANCE.getFrameBuffer() != null) {
ESP.INSTANCE.getFrameBuffer().bindFramebuffer(false);
}
if (colorLock) {
GlStateManager.color(color.get(0), color.get(1), color.get(2), color.get(3));
GlStateUtils.colorLock(true);
}
if (!texture2d) {
GlStateManager.disableTexture2D();
}
}
}

View File

@ -1,36 +1,24 @@
package org.kamiblue.client.mixin.client.render;
import net.minecraft.client.Minecraft;
import net.minecraft.client.entity.EntityPlayerSP;
import net.minecraft.client.renderer.RenderGlobal;
import net.minecraft.client.renderer.ViewFrustum;
import net.minecraft.client.renderer.chunk.RenderChunk;
import net.minecraft.client.renderer.culling.ICamera;
import net.minecraft.entity.Entity;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.MathHelper;
import net.minecraft.util.math.RayTraceResult;
import org.kamiblue.client.event.KamiEventBus;
import org.kamiblue.client.event.events.BlockBreakEvent;
import org.kamiblue.client.mixin.client.accessor.render.AccessorViewFrustum;
import org.kamiblue.client.event.events.RenderEntityEvent;
import org.kamiblue.client.module.modules.player.Freecam;
import org.kamiblue.client.module.modules.render.SelectionHighlight;
import org.kamiblue.client.util.Wrapper;
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.Redirect;
import org.spongepowered.asm.mixin.injection.ModifyVariable;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
@Mixin(RenderGlobal.class)
public abstract class MixinRenderGlobal {
@Shadow private int renderDistanceChunks;
@Shadow private ViewFrustum viewFrustum;
private final Minecraft mc = Minecraft.getMinecraft();
@Inject(method = "drawSelectionBox", at = @At("HEAD"), cancellable = true)
public void drawSelectionBox(EntityPlayer player, RayTraceResult movingObjectPositionIn, int execute, float partialTicks, CallbackInfo ci) {
if (SelectionHighlight.INSTANCE.isEnabled() && SelectionHighlight.INSTANCE.getBlock().getValue()) {
@ -44,38 +32,22 @@ public abstract class MixinRenderGlobal {
KamiEventBus.INSTANCE.post(event);
}
// Can't use @ModifyVariable here because it crashes outside of a dev env with Optifine
@Redirect(method = "setupTerrain", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/RenderGlobal;getRenderChunkOffset(Lnet/minecraft/util/math/BlockPos;Lnet/minecraft/client/renderer/chunk/RenderChunk;Lnet/minecraft/util/EnumFacing;)Lnet/minecraft/client/renderer/chunk/RenderChunk;"))
public RenderChunk renderChunkOffset(RenderGlobal renderGlobal, BlockPos playerPos, RenderChunk renderChunkBase, EnumFacing facing) {
@Inject(method = "renderEntities", at = @At("HEAD"))
public void renderEntitiesHead(Entity renderViewEntity, ICamera camera, float partialTicks, CallbackInfo ci) {
RenderEntityEvent.setRenderingEntities(true);
}
@Inject(method = "renderEntities", at = @At("RETURN"))
public void renderEntitiesReturn(Entity renderViewEntity, ICamera camera, float partialTicks, CallbackInfo ci) {
RenderEntityEvent.setRenderingEntities(false);
}
@ModifyVariable(method = "setupTerrain", at = @At(value = "STORE", ordinal = 0), ordinal = 1)
public BlockPos setupTerrainStoreFlooredChunkPosition(BlockPos playerPos) {
if (Freecam.INSTANCE.isEnabled()) {
playerPos = Freecam.getRenderChunkOffset(playerPos);
}
// Can't use a @Shadow of getRenderChunkOffset because it crashes outside of a dev env with Optifine
BlockPos blockpos = renderChunkBase.getBlockPosOffset16(facing);
if (MathHelper.abs(playerPos.getX() - blockpos.getX()) > this.renderDistanceChunks * 16) {
return null;
} else if (blockpos.getY() >= 0 && blockpos.getY() < 256) {
return MathHelper.abs(playerPos.getZ() - blockpos.getZ()) > this.renderDistanceChunks * 16 ? null : ((AccessorViewFrustum) this.viewFrustum).invokeGetRenderChunk(blockpos);
} else {
return null;
}
}
/*
* updateChunkPositions loadRenderers as well, but as long as you don't change your renderDistance in Freecam loadRenderers won't be called
* One could add the same redirect for loadRenderers if needed
*/
@Redirect(method = "setupTerrain", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/ViewFrustum;updateChunkPositions(DD)V"))
public void updateSetupTerrain(ViewFrustum viewFrustum, double viewEntityX, double viewEntityZ) {
EntityPlayerSP player = Wrapper.getPlayer();
if (Freecam.INSTANCE.isEnabled() && player != null) {
viewEntityX = player.posX;
viewEntityZ = player.posZ;
}
viewFrustum.updateChunkPositions(viewEntityX, viewEntityZ);
return playerPos;
}
}

View File

@ -0,0 +1,30 @@
package org.kamiblue.client.mixin.client.render;
import net.minecraft.client.renderer.entity.RenderLivingBase;
import net.minecraft.entity.EntityLivingBase;
import org.kamiblue.client.event.KamiEventBus;
import org.kamiblue.client.event.Phase;
import org.kamiblue.client.event.events.RenderEntityEvent;
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(value = RenderLivingBase.class, priority = 114514)
public class MixinRenderLivingBase<T extends EntityLivingBase> {
@Inject(method = "renderModel", at = @At("HEAD"), cancellable = true)
public void renderModelHead(T entity, float limbSwing, float limbSwingAmount, float ageInTicks, float netHeadYaw, float headPitch, float scaleFactor, CallbackInfo ci) {
if (entity == null || !RenderEntityEvent.getRenderingEntities()) return;
RenderEntityEvent eventModel = new RenderEntityEvent.Model(entity, Phase.PRE);
KamiEventBus.INSTANCE.post(eventModel);
}
@Inject(method = "renderModel", at = @At("RETURN"), cancellable = true)
public void renderEntityReturn(T entity, float limbSwing, float limbSwingAmount, float ageInTicks, float netHeadYaw, float headPitch, float scaleFactor, CallbackInfo ci) {
if (entity == null || !RenderEntityEvent.getRenderingEntities()) return;
RenderEntityEvent eventModel = new RenderEntityEvent.Model(entity, Phase.POST);
KamiEventBus.INSTANCE.post(eventModel);
}
}

View File

@ -2,6 +2,7 @@ package org.kamiblue.client.mixin.client.render;
import net.minecraft.client.renderer.entity.RenderManager;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityLivingBase;
import org.kamiblue.client.event.KamiEventBus;
import org.kamiblue.client.event.Phase;
import org.kamiblue.client.event.events.RenderEntityEvent;
@ -14,27 +15,36 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
public class MixinRenderManager {
@Inject(method = "renderEntity", at = @At("HEAD"), cancellable = true)
public void renderEntityPre(Entity entity, double x, double y, double z, float yaw, float partialTicks, boolean debug, CallbackInfo ci) {
if (entity == null) return;
if (entity == null || !RenderEntityEvent.getRenderingEntities()) return;
RenderEntityEvent event = new RenderEntityEvent(entity, x, y, z, yaw, partialTicks, Phase.PRE);
KamiEventBus.INSTANCE.post(event);
RenderEntityEvent eventAll = new RenderEntityEvent.All(entity, Phase.PRE);
KamiEventBus.INSTANCE.post(eventAll);
if (eventAll.getCancelled()) ci.cancel();
if (event.getCancelled()) ci.cancel();
if (!(entity instanceof EntityLivingBase)) {
RenderEntityEvent eventModel = new RenderEntityEvent.Model(entity, Phase.PRE);
KamiEventBus.INSTANCE.post(eventModel);
}
}
@Inject(method = "renderEntity", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/entity/Render;doRender(Lnet/minecraft/entity/Entity;DDDFF)V", shift = At.Shift.AFTER))
public void renderEntityPeri(Entity entity, double x, double y, double z, float yaw, float partialTicks, boolean debug, CallbackInfo ci) {
if (entity == null) return;
if (entity == null || !RenderEntityEvent.getRenderingEntities()) return;
RenderEntityEvent event = new RenderEntityEvent(entity, x, y, z, yaw, partialTicks, Phase.PERI);
RenderEntityEvent event = new RenderEntityEvent.All(entity, Phase.PERI);
KamiEventBus.INSTANCE.post(event);
if (!(entity instanceof EntityLivingBase)) {
RenderEntityEvent eventModel = new RenderEntityEvent.Model(entity, Phase.POST);
KamiEventBus.INSTANCE.post(eventModel);
}
}
@Inject(method = "renderEntity", at = @At("RETURN"))
public void renderEntityPost(Entity entity, double x, double y, double z, float yaw, float partialTicks, boolean debug, CallbackInfo ci) {
if (entity == null) return;
if (entity == null || !RenderEntityEvent.getRenderingEntities()) return;
RenderEntityEvent event = new RenderEntityEvent(entity, x, y, z, yaw, partialTicks, Phase.POST);
RenderEntityEvent event = new RenderEntityEvent.All(entity, Phase.POST);
KamiEventBus.INSTANCE.post(event);
}
}

View File

@ -1,25 +1,29 @@
package org.kamiblue.client.mixin.client.render;
import net.minecraft.client.entity.AbstractClientPlayer;
import net.minecraft.client.model.ModelBase;
import net.minecraft.client.renderer.GlStateManager;
import net.minecraft.client.renderer.entity.RenderLivingBase;
import net.minecraft.client.renderer.entity.RenderManager;
import net.minecraft.client.renderer.entity.RenderPlayer;
import net.minecraft.entity.Entity;
import net.minecraft.util.math.Vec3d;
import org.kamiblue.client.module.modules.movement.ElytraFlight;
import org.kamiblue.client.module.modules.player.Freecam;
import org.kamiblue.client.util.Wrapper;
import org.objectweb.asm.Opcodes;
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.Redirect;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
/**
* Created by 086 on 19/12/2017.
*/
@Mixin(RenderPlayer.class)
public class MixinRenderPlayer {
public abstract class MixinRenderPlayer extends RenderLivingBase<AbstractClientPlayer> {
public MixinRenderPlayer(RenderManager renderManagerIn, ModelBase modelBaseIn, float shadowSizeIn) {
super(renderManagerIn, modelBaseIn, shadowSizeIn);
}
@Shadow protected abstract void setModelVisibilities(AbstractClientPlayer clientPlayer);
@Inject(method = "applyRotations", at = @At("RETURN"))
protected void applyRotations(AbstractClientPlayer entityLiving, float ageInTicks, float rotationYaw, float partialTicks, CallbackInfo ci) {
@ -36,9 +40,20 @@ public class MixinRenderPlayer {
}
}
// Redirect it to the original player so the original player can be renderer correctly
@Redirect(method = "doRender", at = @At(value = "FIELD", target = "Lnet/minecraft/client/renderer/entity/RenderManager;renderViewEntity:Lnet/minecraft/entity/Entity;", opcode = Opcodes.GETFIELD))
public Entity getRenderViewEntity(RenderManager renderManager) {
return Wrapper.getPlayer();
// Force it to render the original player in Freecam
@Inject(method = "doRender", at = @At(value = "FIELD", target = "Lnet/minecraft/client/renderer/entity/RenderManager;renderViewEntity:Lnet/minecraft/entity/Entity;"))
public void doRenderGetRenderViewEntity(AbstractClientPlayer entity, double x, double y, double z, float entityYaw, float partialTicks, CallbackInfo ci) {
if (Freecam.INSTANCE.isEnabled() && Wrapper.getMinecraft().getRenderViewEntity() != entity) {
double renderY = y;
if (entity.isSneaking()) {
renderY = y - 0.125D;
}
this.setModelVisibilities(entity);
GlStateManager.enableBlendProfile(GlStateManager.Profile.PLAYER_SKIN);
super.doRender(entity, x, renderY, z, entityYaw, partialTicks);
GlStateManager.disableBlendProfile(GlStateManager.Profile.PLAYER_SKIN);
}
}
}

View File

@ -0,0 +1,53 @@
package org.kamiblue.client.mixin.client.render;
import net.minecraft.client.entity.EntityPlayerSP;
import net.minecraft.client.renderer.ViewFrustum;
import net.minecraft.client.renderer.chunk.RenderChunk;
import net.minecraft.util.math.MathHelper;
import org.kamiblue.client.module.modules.player.Freecam;
import org.kamiblue.client.util.Wrapper;
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;
// TODO: Find a working fix of this for optifine
@Mixin(ViewFrustum.class)
public abstract class MixinViewFrustum {
@Shadow public RenderChunk[] renderChunks;
@Shadow protected int countChunksX;
@Shadow protected int countChunksY;
@Shadow protected int countChunksZ;
@Shadow protected abstract int getBaseCoordinate(int p_178157_1_, int p_178157_2_, int p_178157_3_);
@Inject(method = "updateChunkPositions", at = @At("HEAD"), cancellable = true)
public void updateChunkPositionsHead(double viewEntityX, double viewEntityZ, CallbackInfo ci) {
if (Freecam.INSTANCE.isDisabled()) return;
EntityPlayerSP player = Wrapper.getPlayer();
if (player == null) return;
int centerX = MathHelper.floor(player.posX) - 8;
int centerZ = MathHelper.floor(player.posZ) - 8;
int multipliedCountX = this.countChunksX * 16;
for (int x = 0; x < this.countChunksX; ++x) {
int posX = this.getBaseCoordinate(centerX, multipliedCountX, x);
for (int z = 0; z < this.countChunksZ; ++z) {
int poxZ = this.getBaseCoordinate(centerZ, multipliedCountX, z);
for (int y = 0; y < this.countChunksY; ++y) {
int poxY = y * 16;
RenderChunk renderchunk = this.renderChunks[(z * this.countChunksY + y) * this.countChunksX + x];
renderchunk.setPosition(posX, poxY, poxZ);
}
}
}
ci.cancel();
}
}

View File

@ -44,6 +44,7 @@ class KamiMod {
var ready: Boolean = false; private set
}
@Suppress("UNUSED_PARAMETER")
@Mod.EventHandler
fun preInit(event: FMLPreInitializationEvent) {
val directory = File(DIRECTORY)
@ -53,6 +54,7 @@ class KamiMod {
LoaderWrapper.preLoadAll()
}
@Suppress("UNUSED_PARAMETER")
@Mod.EventHandler
fun init(event: FMLInitializationEvent) {
LOG.info("Initializing $NAME $VERSION")
@ -69,6 +71,7 @@ class KamiMod {
LOG.info("$NAME initialized!")
}
@Suppress("UNUSED_PARAMETER")
@Mod.EventHandler
fun postInit(event: FMLPostInitializationEvent) {
ready = true

View File

@ -28,7 +28,7 @@ abstract class ClientCommand(
val prefixName get() = "$prefix$name"
@CommandBuilder
protected fun AbstractArg<*>.module(
protected inline fun AbstractArg<*>.module(
name: String,
block: BuilderBlock<AbstractModule>
) {
@ -36,7 +36,7 @@ abstract class ClientCommand(
}
@CommandBuilder
protected fun AbstractArg<*>.hudElement(
protected inline fun AbstractArg<*>.hudElement(
name: String,
block: BuilderBlock<HudElement>
) {
@ -44,7 +44,7 @@ abstract class ClientCommand(
}
@CommandBuilder
protected fun AbstractArg<*>.block(
protected inline fun AbstractArg<*>.block(
name: String,
block: BuilderBlock<Block>
) {
@ -52,7 +52,7 @@ abstract class ClientCommand(
}
@CommandBuilder
protected fun AbstractArg<*>.item(
protected inline fun AbstractArg<*>.item(
name: String,
block: BuilderBlock<Item>
) {
@ -60,7 +60,7 @@ abstract class ClientCommand(
}
@CommandBuilder
protected fun AbstractArg<*>.player(
protected inline fun AbstractArg<*>.player(
name: String,
block: BuilderBlock<PlayerProfile>
) {
@ -68,7 +68,7 @@ abstract class ClientCommand(
}
@CommandBuilder
protected fun AbstractArg<*>.blockPos(
protected inline fun AbstractArg<*>.blockPos(
name: String,
block: BuilderBlock<BlockPos>
) {
@ -76,7 +76,7 @@ abstract class ClientCommand(
}
@CommandBuilder
protected fun AbstractArg<*>.baritoneBlock(
protected inline fun AbstractArg<*>.baritoneBlock(
name: String,
block: BuilderBlock<Block>
) {
@ -84,7 +84,7 @@ abstract class ClientCommand(
}
@CommandBuilder
protected fun AbstractArg<*>.schematic(
protected inline fun AbstractArg<*>.schematic(
name: String,
file: BuilderBlock<File>
) {

View File

@ -76,7 +76,9 @@ object CommandManager : AbstractCommandManager<ClientExecuteEvent>(), AsyncLoade
?: throw SubCommandNotFoundException(event.args, command)
onMainThread {
finalArg.invoke(event)
runBlocking {
finalArg.invoke(event)
}
}
}

View File

@ -3,13 +3,8 @@ package org.kamiblue.client.event.events
import net.minecraft.entity.Entity
import org.kamiblue.client.event.*
class RenderEntityEvent(
sealed class RenderEntityEvent(
val entity: Entity,
val x: Double,
val y: Double,
val z: Double,
val yaw: Float,
val partialTicks: Float,
override val phase: Phase
) : Event, ICancellable by Cancellable(), IMultiPhase<RenderEntityEvent>, ProfilerEvent {
@ -18,4 +13,13 @@ class RenderEntityEvent(
override fun nextPhase(): RenderEntityEvent {
throw UnsupportedOperationException()
}
class All(entity: Entity, phase: Phase) : RenderEntityEvent(entity, phase)
class Model(entity: Entity, phase: Phase) : RenderEntityEvent(entity, phase)
companion object {
@JvmStatic
var renderingEntities = false
}
}

View File

@ -85,7 +85,7 @@ object PlayerPacketManager : Manager {
prevServerSideRotation = serverSideRotation
}
listener<RenderEntityEvent> {
listener<RenderEntityEvent.All> {
if (it.entity != Wrapper.player || it.entity.isRiding) return@listener
if (it.phase == Phase.PRE) {

View File

@ -1,7 +1,10 @@
package org.kamiblue.client.module.modules.chat
import net.minecraft.init.Items
import net.minecraft.network.play.server.SPacketUpdateHealth
import net.minecraft.util.EnumHand
import org.kamiblue.client.KamiMod
import org.kamiblue.client.event.SafeClientEvent
import org.kamiblue.client.event.events.PacketEvent
import org.kamiblue.client.module.Category
import org.kamiblue.client.module.Module
@ -66,7 +69,7 @@ internal object AutoExcuse : Module(
init {
safeListener<PacketEvent.Receive> {
if (loadedExcuses.isEmpty() || it.packet !is SPacketUpdateHealth) return@safeListener
if (it.packet.health <= 0f && timer.tick(3L)) {
if (it.packet.health <= 0.0f && !isHoldingTotem && timer.tick(3L)) {
sendServerMessage(getExcuse())
}
}
@ -94,5 +97,8 @@ internal object AutoExcuse : Module(
}
}
private val SafeClientEvent.isHoldingTotem: Boolean
get() = EnumHand.values().any { player.getHeldItem(it).item == Items.TOTEM_OF_UNDYING }
private fun getExcuse() = loadedExcuses.random().replace(CLIENT_NAME, clients.random())
}

View File

@ -34,7 +34,7 @@ internal object KamiMoji : Module(
if (index == -1) continue
val x = mc.fontRenderer.getStringWidth(text.substring(0, index)) + fontHeight / 4
drawEmoji(texture, (posX + x).toDouble(), posY.toDouble(), fontHeight.toFloat(), alpha)
drawEmoji(texture, (posX + x).toDouble(), posY.toDouble(), fontHeight.toFloat())
}
text = text.replaceFirst(emojiText, getReplacement(fontHeight))
@ -70,7 +70,7 @@ internal object KamiMoji : Module(
}
/* This is created because vanilla one doesn't take double position input */
private fun drawEmoji(texture: MipmapTexture, x: Double, y: Double, size: Float, alpha: Float) {
private fun drawEmoji(texture: MipmapTexture, x: Double, y: Double, size: Float) {
val tessellator = Tessellator.getInstance()
val bufBuilder = tessellator.buffer

View File

@ -3,6 +3,7 @@ package org.kamiblue.client.module.modules.combat
import net.minecraft.entity.player.EntityPlayer
import net.minecraftforge.client.event.ClientChatReceivedEvent
import net.minecraftforge.fml.common.gameevent.TickEvent
import org.kamiblue.client.event.SafeClientEvent
import org.kamiblue.client.event.events.ConnectionEvent
import org.kamiblue.client.module.Category
import org.kamiblue.client.module.Module
@ -10,6 +11,7 @@ import org.kamiblue.client.util.TickTimer
import org.kamiblue.client.util.TimeUnit
import org.kamiblue.client.util.text.MessageSendHelper
import org.kamiblue.client.util.text.MessageSendHelper.sendServerMessage
import org.kamiblue.client.util.text.formatValue
import org.kamiblue.client.util.threads.safeListener
import org.kamiblue.commons.extension.synchronized
import org.kamiblue.event.listener.listener
@ -21,24 +23,29 @@ internal object AutoEZ : Module(
category = Category.COMBAT,
description = "Sends an insult in chat after killing someone"
) {
private val detectMode = setting("Detect Mode", DetectMode.HEALTH)
private val messageMode = setting("Message Mode", MessageMode.ONTOP)
private val customText = setting("Custom Text", "unchanged")
private const val UNCHANGED = "Unchanged"
private const val NAME = "\$NAME"
private const val HYPIXEL_MESSAGE = "\$HYPIXEL_MESSAGE"
private val detectMode by setting("Detect Mode", DetectMode.HEALTH)
private val messageMode by setting("Message Mode", MessageMode.ONTOP)
private val customText by setting("Custom Text", UNCHANGED, { messageMode == MessageMode.CUSTOM })
private enum class DetectMode {
BROADCAST, HEALTH
}
@Suppress("UNUSED")
enum class MessageMode(val text: String) {
GG("gg, \$NAME"),
ONTOP("KAMI BLUE on top! ez \$NAME"),
EZD("You just got ez'd \$NAME"),
EZ_HYPIXEL("\$HYPIXEL_MESSAGE \$NAME"),
NAENAE("You just got naenae'd by kami blue plus, \$NAME"),
private enum class MessageMode(val text: String) {
GG("gg, $NAME"),
ONTOP("KAMI BLUE on top! ez $NAME"),
EZD("You just got ez'd $NAME"),
EZ_HYPIXEL("$HYPIXEL_MESSAGE $NAME"),
NAENAE("You just got naenae'd by kami blue plus, $NAME"),
CUSTOM("");
}
// Got these from the forums, kinda based -humboldt123
private val hypixelCensorMessages = arrayOf(
"Hey Helper, how play game?",
"Hello everyone! I am an innocent player who loves everything Hypixel.",
@ -85,73 +92,97 @@ internal object AutoEZ : Module(
"I need help, teach me how to play!",
"What happens if I add chocolate milk to macaroni and cheese?",
"Can you paint with all the colors of the wind"
) // Got these from the forums, kinda based -humboldt123
)
private val timer = TickTimer(TimeUnit.SECONDS)
private val attackedPlayers = LinkedHashMap<EntityPlayer, Int>().synchronized() // <Player, Last Attack Time>
private val confirmedKills = Collections.newSetFromMap(WeakHashMap<EntityPlayer, Boolean>()).synchronized()
init {
safeListener<ClientChatReceivedEvent> {
if (detectMode.value != DetectMode.BROADCAST || player.isDead || player.health <= 0.0f) return@safeListener
onDisable {
reset()
}
val message = it.message.unformattedText
if (!message.contains(player.name, true)) return@safeListener
// Clear the map on disconnect
listener<ConnectionEvent.Disconnect> {
reset()
}
for (player in attackedPlayers.keys) {
if (!message.contains(player.name, true)) continue
sendEzMessage(player)
break // Break right after removing so we don't get exception
safeListener<ClientChatReceivedEvent> { event ->
if (detectMode != DetectMode.BROADCAST || !player.isEntityAlive) return@safeListener
val message = event.message.unformattedText
if (!message.contains(player.name)) return@safeListener
attackedPlayers.keys.find {
message.contains(it.name)
}?.let {
confirmedKills.add(it)
}
}
safeListener<TickEvent.ClientTickEvent> { event ->
if (event.phase != TickEvent.Phase.END) return@safeListener
if (player.isDead || player.health <= 0.0f) {
attackedPlayers.clear()
if (!player.isEntityAlive) {
reset()
return@safeListener
}
// Update attacked Entity
val attacked = player.lastAttackedEntity
if (attacked is EntityPlayer && !attacked.isDead && attacked.health > 0.0f) {
attackedPlayers[attacked] = player.lastAttackedEntityTime
}
// Remove players if they are out of world or we haven't attack them again in 100 ticks (5 seconds)
attackedPlayers.entries.removeIf { !it.key.isAddedToWorld || player.ticksExisted - it.value > 100 }
// Check death
if (detectMode.value == DetectMode.HEALTH) {
for (player in attackedPlayers.keys) {
if (!player.isDead && player.health > 0.0f) continue
sendEzMessage(player)
break // Break right after removing so we don't get exception
}
}
// Send custom message type help message
updateAttackedPlayer()
removeInvalidPlayers()
sendEzMessage()
sendHelpMessage()
}
}
// Clear the map on disconnect
listener<ConnectionEvent.Disconnect> {
attackedPlayers.clear()
private fun SafeClientEvent.updateAttackedPlayer() {
val attacked = player.lastAttackedEntity
if (attacked is EntityPlayer && attacked.isEntityAlive) {
attackedPlayers[attacked] = player.lastAttackedEntityTime
}
}
private fun SafeClientEvent.removeInvalidPlayers() {
val removeTime = player.ticksExisted - 100L
// Remove players if they are offline or we haven't attack them again in 100 ticks (5 seconds)
attackedPlayers.entries.removeIf {
@Suppress("SENSELESS_COMPARISON")
it.value < removeTime || connection.getPlayerInfo(it.key.uniqueID) == null
}
}
private fun sendEzMessage() {
// Check death and confirmation
attackedPlayers.keys.find {
!it.isEntityAlive && (detectMode == DetectMode.HEALTH || confirmedKills.contains(it))
}?.let {
attackedPlayers.remove(it)
confirmedKills.remove(it)
val originalText = if (messageMode == MessageMode.CUSTOM) customText else messageMode.text
var replaced = originalText.replace(NAME, it.name)
if (messageMode == MessageMode.EZ_HYPIXEL) {
replaced = replaced.replace(HYPIXEL_MESSAGE, hypixelCensorMessages.random())
}
sendServerMessage(replaced)
}
}
private fun sendHelpMessage() {
if (messageMode.value == MessageMode.CUSTOM && customText.value == "unchanged" && timer.tick(5L)) { // 5 seconds delay
MessageSendHelper.sendChatMessage("$chatName In order to use the custom $name, " +
"please change the CustomText setting in ClickGUI, " +
"with '&7\$NAME&f' being the username of the killed player")
if (messageMode == MessageMode.CUSTOM && customText == UNCHANGED && timer.tick(5L)) { // 5 seconds delay
MessageSendHelper.sendChatMessage(
"$chatName In order to use the custom $name, " +
"please change the CustomText setting in ClickGUI, " +
"with ${formatValue(NAME)} being the username of the killed player"
)
}
}
private fun sendEzMessage(player: EntityPlayer) {
val text = (if (messageMode.value == MessageMode.CUSTOM) customText.value else messageMode.value.text)
.replace("\$NAME", player.name).replace("\$HYPIXEL_MESSAGE", hypixelCensorMessages.random())
sendServerMessage(text)
attackedPlayers.remove(player)
private fun reset() {
attackedPlayers.clear()
confirmedKills.clear()
}
}

View File

@ -1,25 +1,36 @@
package org.kamiblue.client.module.modules.combat
import net.minecraft.network.play.server.SPacketPlayerPosLook
import net.minecraft.util.MovementInputFromOptions
import net.minecraft.util.math.BlockPos
import net.minecraft.util.math.Vec3d
import net.minecraftforge.client.event.InputUpdateEvent
import org.kamiblue.client.event.SafeClientEvent
import org.kamiblue.client.event.events.PacketEvent
import org.kamiblue.client.event.events.PlayerMoveEvent
import org.kamiblue.client.event.events.PlayerTravelEvent
import org.kamiblue.client.event.events.RenderWorldEvent
import org.kamiblue.client.module.Category
import org.kamiblue.client.module.Module
import org.kamiblue.client.module.modules.movement.Strafe
import org.kamiblue.client.util.EntityUtils
import org.kamiblue.client.util.EntityUtils.flooredPosition
import org.kamiblue.client.util.MovementUtils.isCentered
import org.kamiblue.client.util.MovementUtils.resetMove
import org.kamiblue.client.util.MovementUtils.speed
import org.kamiblue.client.util.combat.SurroundUtils
import org.kamiblue.client.util.combat.SurroundUtils.checkHole
import org.kamiblue.client.util.graphics.KamiTessellator
import org.kamiblue.client.util.math.RotationUtils
import org.kamiblue.client.util.math.VectorUtils
import org.kamiblue.client.util.math.VectorUtils.distanceTo
import org.kamiblue.client.util.math.VectorUtils.toBlockPos
import org.kamiblue.client.util.math.VectorUtils.toVec3d
import org.kamiblue.client.util.threads.safeAsyncListener
import org.kamiblue.client.util.threads.safeListener
import org.kamiblue.commons.extension.ceilToInt
import org.kamiblue.commons.extension.toRadian
import org.kamiblue.event.listener.listener
import org.lwjgl.opengl.GL11.*
import kotlin.math.*
internal object HoleSnap : Module(
@ -27,40 +38,92 @@ internal object HoleSnap : Module(
description = "Move you into the hole nearby",
category = Category.COMBAT
) {
private val airStrafe by setting("Air Strafe", true)
private val disableStrafe by setting("Disable Strafe", true)
private val range by setting("Range", 2.5f, 0.5f..4.0f, 0.25f)
private var holePos: BlockPos? = null
private var stuckTicks = 0
init {
onDisable {
holePos = null
stuckTicks = 0
}
safeListener<RenderWorldEvent>(1) {
holePos?.let {
if (player.flooredPosition == it) return@safeListener
val posFrom = EntityUtils.getInterpolatedPos(player, KamiTessellator.pTicks())
val posTo = it.toVec3d(0.5, 0.0, 0.5)
val buffer = KamiTessellator.buffer
glLineWidth(3.0f)
glDisable(GL_DEPTH_TEST)
KamiTessellator.begin(GL_LINES)
buffer.pos(posFrom.x, posFrom.y, posFrom.z).color(32, 255, 32, 255).endVertex()
buffer.pos(posTo.x, posTo.y, posTo.z).color(32, 255, 32, 255).endVertex()
KamiTessellator.render()
glLineWidth(1.0f)
glEnable(GL_DEPTH_TEST)
}
}
listener<PacketEvent.Receive> {
if (it.packet is SPacketPlayerPosLook) disable()
}
listener<InputUpdateEvent>(-69) {
if (it.movementInput is MovementInputFromOptions && holePos != null) {
it.movementInput.resetMove()
}
}
safeAsyncListener<PlayerMoveEvent> {
if (checkHole(player) != SurroundUtils.HoleType.NONE) {
if (!player.isEntityAlive) return@safeAsyncListener
val currentSpeed = player.speed
if (shouldDisable(currentSpeed)) {
disable()
return@safeAsyncListener
}
findHole()?.let {
getHole()?.let {
if (disableStrafe) Strafe.disable()
if (player.onGround && !isAboveHole(it)) {
if ((airStrafe || player.onGround) && !player.isCentered(it)) {
val playerPos = player.positionVector
val targetPos = Vec3d(it.x + 0.5, player.posY, it.z + 0.5)
val yawRad = RotationUtils.getRotationTo(playerPos, targetPos).x.toRadian()
val dist = playerPos.distanceTo(targetPos)
val speed = min(0.2805, dist / 2.0)
val speed = if (player.onGround) min(0.2805, dist / 2.0) else currentSpeed + 0.02
player.motionX = -sin(yawRad) * speed
player.motionZ = cos(yawRad) * speed
if (player.collidedHorizontally) stuckTicks++
else stuckTicks = 0
}
}
}
}
private fun SafeClientEvent.shouldDisable(currentSpeed: Double) =
holePos?.let { player.posY < it.y } ?: false
|| stuckTicks > 5 && currentSpeed < 0.1
|| currentSpeed < 0.01 && checkHole(player) != SurroundUtils.HoleType.NONE
private fun SafeClientEvent.getHole() =
if (player.ticksExisted % 10 == 0 && player.flooredPosition != holePos) findHole()
else holePos ?: findHole()
private fun SafeClientEvent.findHole(): BlockPos? {
var closestHole = Pair(69.69, BlockPos.ORIGIN)
val playerPos = player.positionVector.toBlockPos()
val playerPos = player.flooredPosition
val ceilRange = range.ceilToInt()
val posList = VectorUtils.getBlockPositionsInArea(playerPos.add(ceilRange, -1, ceilRange), playerPos.add(-ceilRange, -1, -ceilRange))
@ -76,11 +139,7 @@ internal object HoleSnap : Module(
}
}
return if (closestHole.second != BlockPos.ORIGIN) closestHole.second else null
}
private fun SafeClientEvent.isAboveHole(holePos: BlockPos): Boolean {
return player.posX in holePos.x + 0.31..holePos.x + 0.69
&& player.posZ in holePos.z + 0.31..holePos.z + 0.69
return if (closestHole.second != BlockPos.ORIGIN) closestHole.second.also { holePos = it }
else null
}
}

View File

@ -12,6 +12,7 @@ import org.kamiblue.client.module.Category
import org.kamiblue.client.module.Module
import org.kamiblue.client.module.modules.movement.Strafe
import org.kamiblue.client.util.*
import org.kamiblue.client.util.MovementUtils.centerPlayer
import org.kamiblue.client.util.MovementUtils.speed
import org.kamiblue.client.util.WorldUtils.buildStructure
import org.kamiblue.client.util.WorldUtils.getPlaceInfo
@ -33,24 +34,21 @@ internal object Surround : Module(
description = "Surrounds you with obsidian to take less damage",
modulePriority = 200
) {
private val autoCenter = setting("Auto Center", AutoCenterMode.MOTION)
private val placeSpeed = setting("Places Per Tick", 4f, 0.25f..5f, 0.25f)
private val autoDisable = setting("Auto Disable", AutoDisableMode.OUT_OF_HOLE)
private val outOfHoleTimeout = setting("Out Of Hole Timeout", 10, 1..50, 5, { autoDisable.value == AutoDisableMode.OUT_OF_HOLE }, description = "Delay before disabling Surround when you are out of hole, in ticks")
private val placeSpeed by setting("Places Per Tick", 4f, 0.25f..5f, 0.25f)
private val disableStrafe by setting("Disable Strafe", true)
private val autoDisable by setting("Auto Disable", AutoDisableMode.OUT_OF_HOLE)
private val outOfHoleTimeout by setting("Out Of Hole Timeout", 10, 1..50, 5, { autoDisable == AutoDisableMode.OUT_OF_HOLE }, description = "Delay before disabling Surround when you are out of hole, in ticks")
private val enableInHole = setting("Enable In Hole", false)
private val inHoleTimeout = setting("In Hole Timeout", 50, 1..100, 5, { enableInHole.value }, description = "Delay before enabling Surround when you are in hole, in ticks")
private val disableStrafe = setting("Disable Strafe", true)
private val inHoleTimeout by setting("In Hole Timeout", 50, 1..100, 5, { enableInHole.value }, description = "Delay before enabling Surround when you are in hole, in ticks")
private val toggleMessage by setting("Toggle Message", true)
enum class AutoCenterMode {
OFF, TP, MOTION
}
enum class AutoDisableMode {
private enum class AutoDisableMode {
ONE_TIME, OUT_OF_HOLE
}
private val toggleTimer = StopTimer(TimeUnit.TICKS)
private var holePos: BlockPos? = null
private var toggleTimer = StopTimer(TimeUnit.TICKS)
private var job: Job? = null
override fun isActive(): Boolean {
@ -58,26 +56,24 @@ internal object Surround : Module(
}
init {
onEnable {
toggleTimer.reset()
}
onDisable {
PlayerPacketManager.resetHotbar()
toggleTimer.reset()
holePos = null
}
onToggle {
toggleTimer.reset()
}
safeListener<TickEvent.ClientTickEvent> {
if (getObby() == null) return@safeListener
if (isDisabled) {
enableInHoleCheck()
return@safeListener
}
// Following codes will not run if disabled
// Update hole pos
if (holePos == null || inHoleCheck()) {
holePos = player.positionVector.toBlockPos()
@ -91,12 +87,19 @@ internal object Surround : Module(
toggleTimer.reset()
}
// Placeable & Centered check
if (!canRun() || !centerPlayer()) {
if (autoDisable.value == AutoDisableMode.ONE_TIME) disable()
// Placeable
if (!canRun()) {
if (autoDisable == AutoDisableMode.ONE_TIME) disable()
return@safeListener
}
// Centered check
if (!player.centerPlayer()) return@safeListener
if (disableStrafe) {
Strafe.disable()
}
// The actual job
if (!job.isActiveOrFalse) {
job = runSurround()
@ -111,8 +114,8 @@ internal object Surround : Module(
private fun SafeClientEvent.enableInHoleCheck() {
if (enableInHole.value && inHoleCheck()) {
if (toggleTimer.stop() > inHoleTimeout.value) {
MessageSendHelper.sendChatMessage("$chatName You are in hole for longer than ${inHoleTimeout.value} ticks, enabling")
if (toggleTimer.stop() > inHoleTimeout) {
if (toggleMessage) MessageSendHelper.sendChatMessage("$chatName You are in hole for longer than $inHoleTimeout ticks, enabling")
enable()
}
} else {
@ -123,9 +126,9 @@ internal object Surround : Module(
private fun SafeClientEvent.inHoleCheck() = player.onGround && player.speed < 0.15 && checkHole(player) == SurroundUtils.HoleType.OBBY
private fun outOfHoleCheck() {
if (autoDisable.value == AutoDisableMode.OUT_OF_HOLE) {
if (toggleTimer.stop() > outOfHoleTimeout.value) {
MessageSendHelper.sendChatMessage("$chatName You are out of hole for longer than ${outOfHoleTimeout.value} ticks, disabling")
if (autoDisable == AutoDisableMode.OUT_OF_HOLE) {
if (toggleTimer.stop() > outOfHoleTimeout) {
if (toggleMessage) MessageSendHelper.sendChatMessage("$chatName You are out of hole for longer than $outOfHoleTimeout ticks, disabling")
disable()
}
}
@ -140,7 +143,7 @@ internal object Surround : Module(
if (slots == null) { // Obsidian check
if (isEnabled) {
MessageSendHelper.sendChatMessage("$chatName No obsidian in hotbar, disabling!")
if (toggleMessage) MessageSendHelper.sendChatMessage("$chatName No obsidian in hotbar, disabling!")
disable()
}
return null
@ -151,26 +154,15 @@ internal object Surround : Module(
private fun SafeClientEvent.canRun(): Boolean {
val playerPos = player.positionVector.toBlockPos()
for (offset in SurroundUtils.surroundOffset) {
val pos = playerPos.add(offset)
if (isPlaceable(pos, true)) return true
}
return false
}
private fun centerPlayer(): Boolean {
return if (autoCenter.value == AutoCenterMode.OFF) {
true
} else {
if (disableStrafe.value) Strafe.disable()
SurroundUtils.centerPlayer(autoCenter.value == AutoCenterMode.TP)
return SurroundUtils.surroundOffset.any {
isPlaceable(playerPos.add(it), true)
}
}
private fun SafeClientEvent.runSurround() = defaultScope.launch {
spoofHotbar()
buildStructure(placeSpeed.value) {
buildStructure(placeSpeed) {
if (isEnabled && CombatManager.isOnTopPriority(this@Surround)) {
getPlaceInfo(player.positionVector.toBlockPos(), SurroundUtils.surroundOffset, it, 2)
} else {

View File

@ -13,107 +13,112 @@ import org.kamiblue.client.module.Module
import org.kamiblue.client.util.color.EnumTextColor
import org.kamiblue.client.util.text.MessageSendHelper
import org.kamiblue.client.util.text.MessageSendHelper.sendServerMessage
import org.kamiblue.client.util.text.format
import org.kamiblue.client.util.threads.safeListener
import org.kamiblue.commons.extension.synchronized
import org.kamiblue.event.listener.listener
import java.util.*
import kotlin.collections.ArrayList
import kotlin.collections.LinkedHashMap
internal object TotemPopCounter : Module(
name = "TotemPopCounter",
description = "Counts how many times players pop",
category = Category.COMBAT
) {
private val countFriends = setting("Count Friends", true)
private val countSelf = setting("Count Self", false)
private val resetOnDeath = setting("Reset On Death", true)
private val announceSetting = setting("Announce", Announce.CLIENT)
private val thanksTo = setting("Thanks To", false)
private val colorName = setting("Color Name", EnumTextColor.DARK_PURPLE)
private val colorNumber = setting("Color Number", EnumTextColor.LIGHT_PURPLE)
private val countFriends by setting("Count Friends", true)
private val countSelf by setting("Count Self", true)
private val announceSetting by setting("Announce", Announce.CLIENT)
private val thanksTo by setting("Thanks To", false)
private val colorName by setting("Color Name", EnumTextColor.DARK_PURPLE)
private val colorNumber by setting("Color Number", EnumTextColor.LIGHT_PURPLE)
private enum class Announce {
CLIENT, EVERYONE
}
private val playerList = HashMap<EntityPlayer, Int>().synchronized()
private var wasDead = false
private val popCountMap = WeakHashMap<EntityPlayer, Int>().synchronized()
private var wasSent = false
init {
onDisable {
playerList.clear()
popCountMap.clear()
wasSent = true
}
safeListener<PacketEvent.Receive> {
if (it.packet !is SPacketEntityStatus || it.packet.opCode.toInt() != 35 || player.isDead) return@safeListener
if (it.packet !is SPacketEntityStatus || it.packet.opCode.toInt() != 35 || !player.isEntityAlive) return@safeListener
val player = (it.packet.getEntity(world) as? EntityPlayer) ?: return@safeListener
if (friendCheck(player) || selfCheck(player)) {
val count = playerList.getOrDefault(player, 0) + 1
playerList[player] = count
sendMessage("${formatName(player)} popped ${formatNumber(count)} ${plural(count)}${ending()}")
if (friendCheck(player) && selfCheck(player)) {
val count = popCountMap.getOrDefault(player, 0) + 1
popCountMap[player] = count
val isSelf = player == this.player
val message = "${formatName(player)} popped ${formatNumber(count)} ${plural(count)}${ending(isSelf)}"
sendMessage(message, !isSelf && isPublic)
}
}
listener<ConnectionEvent.Disconnect> {
playerList.clear()
popCountMap.clear()
}
safeListener<TickEvent.ClientTickEvent> {
if (it.phase != TickEvent.Phase.END) return@safeListener
if (wasDead && !player.isDead && resetOnDeath.value) {
sendMessage("${formatName(player)} died and ${grammar(player)} pop list was reset!")
playerList.clear()
wasDead = false
if (!player.isEntityAlive) {
if (!wasSent) {
popCountMap.clear()
wasSent = true
}
return@safeListener
}
val toRemove = ArrayList<EntityPlayer>()
for ((poppedPlayer, count) in playerList) {
if (!poppedPlayer.isDead) continue
if (poppedPlayer == player) continue
sendMessage("${formatName(poppedPlayer)} died after popping ${formatNumber(count)} ${plural(count)}${ending()}")
toRemove.add(poppedPlayer)
wasSent = false
popCountMap.entries.removeIf { (player, count) ->
if (player == this.player || player.isEntityAlive) {
false
} else {
val message = "${formatName(player)} died after popping ${formatNumber(count)} ${plural(count)}${ending(false)}"
sendMessage(message, isPublic)
true
}
}
playerList.keys.removeAll(toRemove)
wasDead = player.isDead
}
}
private fun friendCheck(player: EntityPlayer) = FriendManager.isFriend(player.name) && countFriends.value
private fun friendCheck(player: EntityPlayer) = countFriends || !FriendManager.isFriend(player.name)
private fun selfCheck(player: EntityPlayer) = player == mc.player && countSelf.value
private fun selfCheck(player: EntityPlayer) = countSelf || player != mc.player
private fun formatName(player: EntityPlayer): String {
val name = when {
player == mc.player -> "I"
FriendManager.isFriend(player.name) -> if (isPublic) "My friend, " else "Your friend, "
else -> player.name
private fun formatName(player: EntityPlayer) =
colorName.textFormatting format when {
player == mc.player -> {
"I"
}
FriendManager.isFriend(player.name) -> {
if (isPublic) "My friend ${player.name}, " else "Your friend ${player.name}, "
}
else -> {
player.name
}
}
return colorName.value.textFormatting.toString() + name + TextFormatting.RESET
}
private val isPublic: Boolean
get() = announceSetting.value == Announce.EVERYONE
get() = announceSetting == Announce.EVERYONE
private fun formatNumber(message: Int) = colorNumber.textFormatting format message
private fun plural(count: Int) = if (count == 1) "totem" else "totems"
private fun grammar(player: EntityPlayer) = if (player == mc.player) "my" else "their"
private fun ending(self: Boolean): String = if (!self && thanksTo) " thanks to ${KamiMod.NAME} !" else "!"
private fun ending(): String = if (thanksTo.value) " thanks to ${KamiMod.NAME} !" else "!"
private fun formatNumber(message: Int) = colorNumber.value.textFormatting.toString() + message + TextFormatting.RESET
private fun sendMessage(message: String) {
when (announceSetting.value) {
Announce.CLIENT -> {
MessageSendHelper.sendChatMessage("$chatName $message")
}
Announce.EVERYONE -> {
sendServerMessage(TextFormatting.getTextWithoutFormattingCodes(message))
}
private fun sendMessage(message: String, public: Boolean) {
if (public) {
sendServerMessage(TextFormatting.getTextWithoutFormattingCodes(message))
} else {
MessageSendHelper.sendChatMessage("$chatName $message")
}
}
}

View File

@ -0,0 +1,94 @@
package org.kamiblue.client.module.modules.movement
import net.minecraft.util.math.BlockPos
import org.kamiblue.client.event.SafeClientEvent
import org.kamiblue.client.event.events.PlayerMoveEvent
import org.kamiblue.client.module.Category
import org.kamiblue.client.module.Module
import org.kamiblue.client.util.EntityUtils.flooredPosition
import org.kamiblue.client.util.MovementUtils.centerPlayer
import org.kamiblue.client.util.MovementUtils.isCentered
import org.kamiblue.client.util.combat.SurroundUtils
import org.kamiblue.client.util.combat.SurroundUtils.checkHole
import org.kamiblue.client.util.threads.safeListener
internal object Anchor : Module(
name = "Anchor",
description = "Stops your motion when you are above hole",
category = Category.MOVEMENT
) {
private val mode by setting("Mode", Mode.BOTH)
private val autoCenter by setting("Auto Center", true)
private val stopYMotion by setting("Stop Y Motion", false)
private val disableInHole by setting("Disable In Hole", false)
private val pitchTrigger by setting("Pitch Trigger", true)
private val pitch by setting("Pitch", 75, 0..80, 1, { pitchTrigger })
private val verticalRange by setting("Vertical Range", 3, 1..5, 1)
private enum class Mode {
BOTH, BEDROCK
}
private var wasInHole = false
init {
onDisable {
wasInHole = false
}
safeListener<PlayerMoveEvent> {
val isInHole = player.onGround && isHole(player.flooredPosition)
val validPitch = !pitchTrigger || player.rotationPitch > pitch
// Disable after in hole for 2 ticks
if (wasInHole && isInHole && disableInHole) {
disable()
return@safeListener
}
if (validPitch) {
// Stops XZ motion
if (isInHole || isAboveHole()) {
if (player.isCentered(player.flooredPosition)) {
player.motionX = 0.0
player.motionZ = 0.0
} else if (autoCenter) {
player.centerPlayer()
}
}
// Stops Y motion
if (stopYMotion && isInHole) {
player.motionY = -0.08 // Minecraft needs this for on ground check
}
}
wasInHole = isInHole
}
}
/**
* Checks whether the player is above hole
*/
private fun SafeClientEvent.isAboveHole(): Boolean {
val flooredPos = player.flooredPosition
for (yOffset in 1..verticalRange) {
val pos = flooredPos.down(yOffset)
if (!world.isAirBlock(pos)) return false
if (isHole(pos)) return true
}
return false
}
/**
* Checks whether the specified block position is a valid type of hole
*/
private fun SafeClientEvent.isHole(pos: BlockPos): Boolean {
val type = checkHole(pos)
return mode == Mode.BOTH && type != SurroundUtils.HoleType.NONE
|| mode == Mode.BEDROCK && type == SurroundUtils.HoleType.BEDROCK
}
}

View File

@ -64,7 +64,7 @@ internal object Jesus : Module(
}
@JvmStatic
fun handleAddCollisionBoxToList(pos: BlockPos, block: Block, entity: Entity?, entityBox: AxisAlignedBB, collidingBoxes: MutableList<AxisAlignedBB>) {
fun handleAddCollisionBoxToList(pos: BlockPos, block: Block, entity: Entity?, collidingBoxes: MutableList<AxisAlignedBB>) {
if (isDisabled || mode == Mode.DOLPHIN) return
if (mc.gameSettings.keyBindSneak.isKeyDown) return
if (block !is BlockLiquid) return

View File

@ -56,7 +56,6 @@ internal object Strafe : Module(
private var jumpTicks = 0
private val strafeTimer = TickTimer(TimeUnit.TICKS)
/* If you skid this you omega gay */
init {
onDisable {
reset()

View File

@ -25,9 +25,10 @@ import org.kamiblue.client.module.Category
import org.kamiblue.client.module.Module
import org.kamiblue.client.util.*
import org.kamiblue.client.util.MovementUtils.calcMoveYaw
import org.kamiblue.client.util.MovementUtils.resetJumpSneak
import org.kamiblue.client.util.MovementUtils.resetMove
import org.kamiblue.client.util.math.RotationUtils
import org.kamiblue.client.util.math.RotationUtils.getRotationTo
import org.kamiblue.client.util.math.VectorUtils.toBlockPos
import org.kamiblue.client.util.threads.onMainThreadSafe
import org.kamiblue.client.util.threads.runSafeR
import org.kamiblue.client.util.threads.safeListener
@ -45,13 +46,14 @@ internal object Freecam : Module(
category = Category.PLAYER,
description = "Leave your body and transcend into the realm of the gods"
) {
private val directionMode = setting("Flight Mode", FlightMode.CREATIVE)
private val horizontalSpeed = setting("Horizontal Speed", 20f, 1f..50f, 1f)
private val verticalSpeed = setting("Vertical Speed", 20f, 1f..50f, 1f)
private val autoRotate = setting("Auto Rotate", true)
private val arrowKeyMove = setting("Arrow Key Move", true)
private val disableOnDisconnect = setting("Disconnect Disable", true)
private val leftClickCome = setting("Left Click Come", true)
private val directionMode by setting("Flight Mode", FlightMode.CREATIVE)
private val horizontalSpeed by setting("Horizontal Speed", 20.0f, 1.0f..50.0f, 1f)
private val verticalSpeed by setting("Vertical Speed", 20.0f, 1.0f..50.0f, 1f, { directionMode == FlightMode.CREATIVE })
private val autoRotate by setting("Auto Rotate", true)
private val arrowKeyMove by setting("Arrow Key Move", true)
private val disableOnDisconnect by setting("Disconnect Disable", true)
private val leftClickCome by setting("Left Click Come", false)
private val relative by setting("Relative", false)
private enum class FlightMode(override val displayName: String) : DisplayEnum {
CREATIVE("Creative"),
@ -112,7 +114,7 @@ internal object Freecam : Module(
listener<ConnectionEvent.Disconnect> {
prevThirdPersonViewSetting = -1
if (disableOnDisconnect.value) disable()
if (disableOnDisconnect) disable()
else cameraGuy = null
}
@ -149,35 +151,26 @@ internal object Freecam : Module(
if (BaritoneUtils.isActive) return@safeListener
if (autoRotate.value) updatePlayerRotation()
if (arrowKeyMove.value) updatePlayerMovement()
if (autoRotate) updatePlayerRotation()
if (arrowKeyMove) updatePlayerMovement()
}
listener<InputEvent.MouseInputEvent> {
if (leftClickCome.value && Mouse.getEventButton() == 0 && clickTimer.tick(1L)) {
if (leftClickCome && Mouse.getEventButton() == 0 && clickTimer.tick(1L)) {
val result = mc.objectMouseOver ?: return@listener
if (result.typeOfHit != RayTraceResult.Type.BLOCK) {
return@listener
if (result.typeOfHit == RayTraceResult.Type.BLOCK) {
BaritoneUtils.cancelEverything()
BaritoneUtils.primary?.customGoalProcess?.setGoalAndPath(GoalTwoBlocks(result.blockPos))
}
BaritoneUtils.cancelEverything()
BaritoneUtils.primary?.customGoalProcess?.setGoalAndPath(GoalTwoBlocks(result.hitVec.toBlockPos()))
}
}
}
private fun resetMovementInput(movementInput: MovementInput?) {
if (movementInput !is MovementInputFromOptions) return
movementInput.apply {
moveForward = 0f
moveStrafe = 0f
forwardKeyDown = false
backKeyDown = false
leftKeyDown = false
rightKeyDown = false
jump = false
sneak = false
if (movementInput is MovementInputFromOptions) {
movementInput.resetMove()
movementInput.resetJumpSneak()
}
}
@ -219,16 +212,16 @@ internal object Freecam : Module(
val yawDiff = player.rotationYaw - it.rotationYaw
val yawRad = calcMoveYaw(yawDiff, movementInput.first, movementInput.second).toFloat()
val inputTotal = min(abs(movementInput.first) + abs(movementInput.second), 1f)
val inputTotal = min(abs(movementInput.first) + abs(movementInput.second), 1.0f)
player.movementInput?.apply {
moveForward = cos(yawRad) * inputTotal
moveStrafe = sin(yawRad) * inputTotal
forwardKeyDown = moveForward > 0f
backKeyDown = moveForward < 0f
leftKeyDown = moveStrafe < 0f
rightKeyDown = moveStrafe > 0f
forwardKeyDown = moveForward > 0.0f
backKeyDown = moveForward < 0.0f
leftKeyDown = moveStrafe < 0.0f
rightKeyDown = moveStrafe > 0.0f
jump = Keyboard.isKeyDown(Keyboard.KEY_RCONTROL)
}
@ -273,17 +266,18 @@ internal object Freecam : Module(
// Update sprinting
isSprinting = mc.gameSettings.keyBindSprint.isKeyDown
val yawRad = (rotationYaw - RotationUtils.getRotationFromVec(Vec3d(moveStrafing.toDouble(), 0.0, moveForward.toDouble())).x).toDouble().toRadian()
val speed = (horizontalSpeed.value / 20f) * min(abs(moveForward) + abs(moveStrafing), 1f)
val absYaw = RotationUtils.getRotationFromVec(Vec3d(moveStrafing.toDouble(), 0.0, moveForward.toDouble())).x
val yawRad = (rotationYaw - absYaw).toDouble().toRadian()
val speed = (horizontalSpeed / 20.0f) * min(abs(moveForward) + abs(moveStrafing), 1.0f)
if (directionMode.value == FlightMode.THREE_DEE) {
val pitchRad = Math.toRadians(rotationPitch.toDouble()) * moveForward
if (directionMode == FlightMode.THREE_DEE) {
val pitchRad = rotationPitch.toDouble().toRadian() * moveForward
motionX = -sin(yawRad) * cos(pitchRad) * speed
motionY = -sin(pitchRad) * speed
motionZ = cos(yawRad) * cos(pitchRad) * speed
} else {
motionX = -sin(yawRad) * speed
motionY = moveVertical.toDouble() * (verticalSpeed.value / 20f)
motionY = moveVertical.toDouble() * (verticalSpeed / 20.0f)
motionZ = cos(yawRad) * speed
}
@ -293,13 +287,19 @@ internal object Freecam : Module(
motionZ *= 1.5
}
noClip = true
if (relative) {
motionX += player.posX - player.prevPosX
motionY += player.posY - player.prevPosY
motionZ += player.posZ - player.prevPosZ
}
move(MoverType.SELF, motionX, motionY, motionZ)
}
override fun getEyeHeight() = 1.65f
override fun isSpectator() = true
override fun isInvisible() = true
override fun isInvisibleToPlayer(player: EntityPlayer) = true
@ -315,23 +315,23 @@ internal object Freecam : Module(
private fun calcMovementInput(forward: Pair<Boolean, Boolean>, strafe: Pair<Boolean, Boolean>, vertical: Pair<Boolean, Boolean>): Triple<Float, Float, Float> {
// Forward movement input
val moveForward = if (forward.first xor forward.second) {
if (forward.first) 1f else -1f
if (forward.first) 1.0f else -1.0f
} else {
0f
0.0f
}
// Strafe movement input
val moveStrafing = if (strafe.first xor strafe.second) {
if (strafe.second) 1f else -1f
if (strafe.second) 1.0f else -1.0f
} else {
0f
0.0f
}
// Vertical movement input
val moveVertical = if (vertical.first xor vertical.second) {
if (vertical.first) 1f else -1f
if (vertical.first) 1.0f else -1.0f
} else {
0f
0.0f
}
return Triple(moveForward, moveStrafing, moveVertical)

View File

@ -18,6 +18,7 @@ import org.kamiblue.client.util.text.MessageSendHelper
import org.kamiblue.client.util.threads.defaultScope
import org.kamiblue.client.util.threads.safeListener
import org.kamiblue.commons.interfaces.DisplayEnum
import org.kamiblue.event.listener.listener
import java.io.*
import java.time.LocalTime
import java.time.format.DateTimeFormatter
@ -39,10 +40,10 @@ internal object PacketLogger : Module(
private val ignoreCancelled by setting("Ignore Cancelled", true, description = "Ignore cancelled packets.")
private val fileTimeFormatter = DateTimeFormatter.ofPattern("HH-mm-ss_SSS")
private val logTimeFormatter = DateTimeFormatter.ofPattern("HH:mm:ss.SSS")
private var start = 0L
private var last = 0L
private var lastTick = 0L
private val timer = TickTimer(TimeUnit.SECONDS)
private const val directory = "${KamiMod.DIRECTORY}packetLogs"
@ -73,8 +74,10 @@ internal object PacketLogger : Module(
if (it.phase != TickEvent.Phase.START) return@safeListener
if (showClientTicks) {
synchronized(this) {
lines.add("Tick Pulse - Realtime: ${logTimeFormatter.format(LocalTime.now())} - Runtime: ${System.currentTimeMillis() - start}ms\n")
synchronized(this@PacketLogger) {
val current = System.currentTimeMillis()
lines.add("Tick Pulse,,${current - start},${current - lastTick}\n")
lastTick = current
}
}
@ -88,215 +91,305 @@ internal object PacketLogger : Module(
disable()
}
safeListener<PacketEvent.Receive>(Int.MIN_VALUE) {
if (ignoreCancelled && it.cancelled) return@safeListener
listener<PacketEvent.PostReceive>(Int.MIN_VALUE) {
if (ignoreCancelled && it.cancelled) return@listener
if (packetSide == PacketSide.SERVER || packetSide == PacketSide.BOTH) {
when (it.packet) {
is SPacketEntityTeleport -> {
add(PacketSide.SERVER, it.packet,
"x: ${it.packet.x} " +
"y: ${it.packet.y} " +
"z: ${it.packet.z} " +
"pitch: ${it.packet.pitch} " +
"yaw: ${it.packet.yaw} " +
"entityID: ${it.packet.entityId}")
}
is SPacketEntityMetadata -> {
val dataEntry = StringBuilder().run {
append("dataEntries: ")
for (entry in it.packet.dataManagerEntries) {
append("> isDirty: ${entry.isDirty} key: ${entry.key} value: ${entry.value} ")
}
toString()
}
add(PacketSide.SERVER, it.packet, dataEntry)
}
is SPacketUnloadChunk -> {
if (!ignoreChunkLoading) {
add(PacketSide.SERVER, it.packet,
"x: ${it.packet.x} " +
"z: ${it.packet.z}")
}
}
is SPacketDestroyEntities -> {
val entities = StringBuilder().run {
append("entityIDs: ")
for (entry in it.packet.entityIDs) {
append("> $entry ")
}
toString()
}
add(PacketSide.SERVER, it.packet, entities)
}
is SPacketPlayerPosLook -> {
val flags = StringBuilder().run {
append("flags: ")
for (entry in it.packet.flags) {
append("> ${entry.name} ")
}
toString()
}
add(PacketSide.SERVER, it.packet,
"x: ${it.packet.x} " +
"y: ${it.packet.y} " +
"z: ${it.packet.z} " +
"pitch: ${it.packet.pitch} " +
"yaw: ${it.packet.yaw} " +
"teleportID: ${it.packet.teleportId}" +
flags)
}
is SPacketBlockChange -> {
add(PacketSide.SERVER, it.packet,
"x: ${it.packet.blockPosition.x} " +
"y: ${it.packet.blockPosition.y} " +
"z: ${it.packet.blockPosition.z}")
}
is SPacketMultiBlockChange -> {
val changedBlock = StringBuilder().run {
append("changedBlocks: ")
for (changedBlock in it.packet.changedBlocks) {
append("> x: ${changedBlock.pos.x} y: ${changedBlock.pos.y} z: ${changedBlock.pos.z} ")
}
toString()
log(it) {
"x" to it.packet.blockPosition.x
"y" to it.packet.blockPosition.y
"z" to it.packet.blockPosition.z
}
add(PacketSide.SERVER, it.packet, changedBlock)
}
is SPacketTimeUpdate -> {
add(PacketSide.SERVER, it.packet,
"totalWorldTime: ${it.packet.totalWorldTime} " +
"worldTime: ${it.packet.worldTime}")
}
is SPacketChat -> {
if (!ignoreChat) {
add(PacketSide.SERVER, it.packet,
"unformattedText: ${it.packet.chatComponent.unformattedText} " +
"type: ${it.packet.type} " +
"isSystem: ${it.packet.isSystem}")
log(it) {
"unformattedText" to it.packet.chatComponent.unformattedText
"type" to it.packet.type
"itSystem" to it.packet.isSystem
}
}
}
is SPacketTeams -> {
add(PacketSide.SERVER, it.packet,
"action: ${it.packet.action} " +
"displayName: ${it.packet.displayName} " +
"color: ${it.packet.color}")
}
is SPacketChunkData -> {
add(PacketSide.SERVER, it.packet,
"chunkX: ${it.packet.chunkX} " +
"chunkZ: ${it.packet.chunkZ} " +
"extractedSize: ${it.packet.extractedSize}")
log(it) {
"chunkX" to it.packet.chunkX
"chunkZ" to it.packet.chunkZ
"extractedSize" to it.packet.extractedSize
}
}
is SPacketConfirmTransaction -> {
log(it) {
"windowId" to it.packet.windowId
"transactionID" to it.packet.actionNumber
"accepted" to it.packet.wasAccepted()
}
}
is SPacketDestroyEntities -> {
log(it) {
"entityIDs" to buildString {
for (entry in it.packet.entityIDs) {
append("> ")
append(entry)
append(' ')
}
}
}
}
is SPacketEntityMetadata -> {
log(it) {
"dataEntries" to buildString {
for (entry in it.packet.dataManagerEntries) {
append("> isDirty: ")
append(entry.isDirty)
append(" key: ")
append(entry.key)
append(" value: ")
append(entry.value)
append(' ')
}
}
}
}
is SPacketEntityProperties -> {
add(PacketSide.SERVER, it.packet,
"entityID: ${it.packet.entityId}")
log(it) {
"entityID" to it.packet.entityId
}
}
is SPacketUpdateTileEntity -> {
add(PacketSide.SERVER, it.packet,
"posX: ${it.packet.pos.x} " +
"posY: ${it.packet.pos.y} " +
"posZ: ${it.packet.pos.z}")
}
is SPacketSpawnObject -> {
add(PacketSide.SERVER, it.packet,
"entityID: ${it.packet.entityID} " +
"data: ${it.packet.data}")
is SPacketEntityTeleport -> {
log(it) {
"x" to it.packet.x
"y" to it.packet.y
"z" to it.packet.z
"yaw" to it.packet.yaw
"pitch" to it.packet.pitch
"entityID" to it.packet.entityId
}
}
is SPacketKeepAlive -> {
if (!ignoreKeepAlive) {
add(PacketSide.SERVER, it.packet,
"id: ${it.packet.id}")
log(it) {
"id" to it.packet.id
}
}
}
is SPacketMultiBlockChange -> {
log(it) {
"changedBlocks" to buildString {
for (changedBlock in it.packet.changedBlocks) {
append("> x: ")
append(changedBlock.pos.x)
append("y: ")
append(changedBlock.pos.y)
append("z: ")
append(changedBlock.pos.z)
append(' ')
}
}
}
}
is SPacketPlayerPosLook -> {
log(it) {
"x" to it.packet.x
"y" to it.packet.y
"z" to it.packet.z
"yaw" to it.packet.yaw
"pitch" to it.packet.pitch
"teleportID" to it.packet.teleportId
"flags" to buildString {
for (entry in it.packet.flags) {
append("> ")
append(entry.name)
append(' ')
}
}
}
}
is SPacketSoundEffect -> {
log(it) {
"sound" to it.packet.sound.soundName
"category" to it.packet.category
"posX" to it.packet.x
"posY" to it.packet.y
"posZ" to it.packet.z
"volume" to it.packet.volume
"pitch" to it.packet.pitch
}
}
is SPacketSpawnObject -> {
log(it) {
"entityID" to it.packet.entityID
"data" to it.packet.data
}
}
is SPacketTeams -> {
log(it) {
"action" to it.packet.action
"type" to it.packet.displayName
"itSystem" to it.packet.color
}
}
is SPacketTimeUpdate -> {
log(it) {
"totalWorldTime" to it.packet.totalWorldTime
"worldTime" to it.packet.worldTime
}
}
is SPacketUnloadChunk -> {
if (!ignoreChunkLoading) {
log(it) {
"x" to it.packet.x
"z" to it.packet.z
}
}
}
is SPacketUpdateTileEntity -> {
log(it) {
"x" to it.packet.pos.x
"y" to it.packet.pos.y
"z" to it.packet.pos.z
}
}
else -> {
if (!ignoreUnknown) {
add(PacketSide.SERVER, it.packet, "Not Registered in PacketLogger.kt")
log(it) {
+ "Not Registered in PacketLogger"
}
}
}
}
}
}
safeListener<PacketEvent.Send>(Int.MIN_VALUE) {
if (ignoreCancelled && it.cancelled) return@safeListener
listener<PacketEvent.PostSend>(Int.MIN_VALUE) {
if (ignoreCancelled && it.cancelled) return@listener
if (packetSide == PacketSide.CLIENT || packetSide == PacketSide.BOTH) {
when (it.packet) {
is CPacketAnimation -> {
add(PacketSide.CLIENT, it.packet,
"hand: ${it.packet.hand}")
}
is CPacketPlayer.Rotation -> {
add(PacketSide.CLIENT, it.packet,
"pitch: ${it.packet.pitch} " +
"yaw: ${it.packet.yaw} " +
"onGround: ${it.packet.isOnGround}")
}
is CPacketPlayer.Position -> {
add(PacketSide.CLIENT, it.packet,
"x: ${it.packet.x} " +
"y: ${it.packet.y} " +
"z: ${it.packet.z} " +
"onGround: ${it.packet.isOnGround}")
}
is CPacketPlayer.PositionRotation -> {
add(PacketSide.CLIENT, it.packet,
"x: ${it.packet.x} " +
"y: ${it.packet.y} " +
"z: ${it.packet.z} " +
"pitch: ${it.packet.pitch} " +
"yaw: ${it.packet.yaw} " +
"onGround: ${it.packet.isOnGround}")
}
is CPacketPlayerDigging -> {
add(PacketSide.CLIENT, it.packet,
"positionX: ${it.packet.position.x} " +
"positionY: ${it.packet.position.y} " +
"positionZ: ${it.packet.position.z} " +
"facing: ${it.packet.facing} " +
"action: ${it.packet.action} ")
}
is CPacketEntityAction -> {
add(PacketSide.CLIENT, it.packet,
"action: ${it.packet.action} " +
"auxData: ${it.packet.auxData}")
}
is CPacketUseEntity -> {
add(PacketSide.CLIENT, it.packet,
"action: ${it.packet.action} " +
"hand: ${it.packet.hand} " +
"hitVecX: ${it.packet.hitVec.x} " +
"hitVecY: ${it.packet.hitVec.y} " +
"hitVecZ: ${it.packet.hitVec.z}")
}
is CPacketPlayerTryUseItem -> {
add(PacketSide.CLIENT, it.packet,
"hand: ${it.packet.hand}")
}
is CPacketConfirmTeleport -> {
add(PacketSide.CLIENT, it.packet,
"teleportID: ${it.packet.teleportId}")
log(it) {
"hand" to it.packet.hand
}
}
is CPacketChatMessage -> {
if (!ignoreChat) {
add(PacketSide.SERVER, it.packet,
"message: ${it.packet.message}")
log(it) {
"message" to it.packet.message
}
}
}
is CPacketClickWindow -> {
if (!ignoreChat) {
log(it) {
"windowId" to it.packet.windowId
"slotID" to it.packet.slotId
"mouseButton" to it.packet.usedButton
"clickType" to it.packet.clickType
"transactionID" to it.packet.actionNumber
"clickedItem" to it.packet.clickedItem
}
}
}
is CPacketConfirmTeleport -> {
log(it) {
"teleportID" to it.packet.teleportId
}
}
is CPacketEntityAction -> {
log(it) {
"action" to it.packet.action.name
"auxData" to it.packet.auxData
}
}
is CPacketHeldItemChange -> {
log(it) {
"slotID" to it.packet.slotId
}
}
is CPacketKeepAlive -> {
if (!ignoreKeepAlive) {
add(PacketSide.CLIENT, it.packet,
"key: ${it.packet.key}")
log(it) {
"ket" to it.packet.key
}
}
}
is CPacketPlayer.Rotation -> {
log(it) {
"yaw" to it.packet.yaw
"pitch" to it.packet.pitch
"onGround" to it.packet.isOnGround
}
}
is CPacketPlayer.Position -> {
log(it) {
"x" to it.packet.x
"y" to it.packet.y
"z" to it.packet.z
"onGround" to it.packet.isOnGround
}
}
is CPacketPlayer.PositionRotation -> {
log(it) {
"x" to it.packet.x
"y" to it.packet.y
"z" to it.packet.z
"yaw" to it.packet.yaw
"pitch" to it.packet.pitch
"onGround" to it.packet.isOnGround
}
}
is CPacketPlayer -> {
log(it) {
"onGround" to it.packet.isOnGround
}
}
is CPacketPlayerDigging -> {
log(it) {
"x" to it.packet.position.x
"y" to it.packet.position.y
"z" to it.packet.position.z
"facing" to it.packet.facing
"action" to it.packet.action
}
}
is CPacketPlayerTryUseItem -> {
log(it) {
"hand" to it.packet.hand
}
}
is CPacketPlayerTryUseItemOnBlock -> {
log(it) {
"x" to it.packet.pos.x
"y" to it.packet.pos.y
"z" to it.packet.pos.z
"side" to it.packet.direction
"hitVecX" to it.packet.facingX
"hitVecY" to it.packet.facingY
"hitVecZ" to it.packet.facingZ
}
}
is CPacketUseEntity -> {
@Suppress("UNNECESSARY_SAFE_CALL")
log(it) {
"action" to it.packet.action
"action" to it.packet.hand
"hitVecX" to it.packet.hitVec?.x
"hitVecX" to it.packet.hitVec?.y
"hitVecX" to it.packet.hitVec?.z
}
}
else -> {
if (!ignoreUnknown) {
add(PacketSide.CLIENT, it.packet, "Not Registered in PacketLogger.kt")
log(it) {
+ "Not Registered in PacketLogger"
}
}
}
}
@ -326,24 +419,72 @@ internal object PacketLogger : Module(
}
}
/**
* Writes a line to the csv following the format:
* from (client or server), packet name, time since start, time since last packet, packet data
*
* @param side The [PacketSide] where this packet is from
* @param packet Packet to add
* @param data Data of the [packet] in [String]
*/
private fun add(side: PacketSide, packet: Packet<*>, data: String) {
val string = "${side.displayName},${packet.javaClass.simpleName},${System.currentTimeMillis() - start},${System.currentTimeMillis() - last},${data}\n"
private inline fun log(event: PacketEvent.PostSend, block: PacketLogBuilder.() -> Unit) {
PacketLogBuilder(PacketSide.CLIENT, event.packet).apply(block).build()
}
synchronized(this) {
lines.add(string)
last = System.currentTimeMillis()
private inline fun log(event: PacketEvent.PostReceive, block: PacketLogBuilder.() -> Unit) {
PacketLogBuilder(PacketSide.SERVER, event.packet).apply(block).build()
}
private class PacketLogBuilder(val side: PacketSide, val packet: Packet<*>) {
private val stringBuilder = StringBuilder()
init {
stringBuilder.apply {
append(side.displayName)
append(',')
append(packet.javaClass.simpleName)
append(',')
append(System.currentTimeMillis() - start)
append(',')
append(System.currentTimeMillis() - last)
append(',')
}
}
if (logInChat) {
MessageSendHelper.sendChatMessage(string)
operator fun String.unaryPlus() {
stringBuilder.append(this)
}
infix fun String.to(value: Any?) {
if (value != null) {
add(this, value.toString())
}
}
infix fun String.to(value: String?) {
if (value != null) {
add(this, value)
}
}
fun add(key: String, value: String) {
stringBuilder.apply {
append(key)
append(": ")
append(value)
append(' ')
}
}
fun build() {
val string = stringBuilder.run {
append('\n')
toString()
}
synchronized(PacketLogger) {
lines.add(string)
last = System.currentTimeMillis()
}
if (logInChat) {
MessageSendHelper.sendChatMessage(string)
}
}
}
}

View File

@ -26,34 +26,34 @@ internal object Chams : Module(
category = Category.RENDER,
description = "Modify entity rendering"
) {
private val page = setting("Page", Page.ENTITY_TYPE)
private val page by setting("Page", Page.ENTITY_TYPE)
/* Entity type settings */
private val self = setting("Self", false, { page.value == Page.ENTITY_TYPE })
private val all = setting("All Entities", false, { page.value == Page.ENTITY_TYPE })
private val experience = setting("Experience", false, { page.value == Page.ENTITY_TYPE && !all.value })
private val arrows = setting("Arrows", false, { page.value == Page.ENTITY_TYPE && !all.value })
private val throwable = setting("Throwable", false, { page.value == Page.ENTITY_TYPE && !all.value })
private val items = setting("Items", false, { page.value == Page.ENTITY_TYPE && !all.value })
private val crystals = setting("Crystals", false, { page.value == Page.ENTITY_TYPE && !all.value })
private val players = setting("Players", true, { page.value == Page.ENTITY_TYPE && !all.value })
private val friends = setting("Friends", false, { page.value == Page.ENTITY_TYPE && !all.value && players.value })
private val sleeping = setting("Sleeping", false, { page.value == Page.ENTITY_TYPE && !all.value && players.value })
private val mobs = setting("Mobs", true, { page.value == Page.ENTITY_TYPE && !all.value })
private val passive = setting("Passive Mobs", false, { page.value == Page.ENTITY_TYPE && !all.value && mobs.value })
private val neutral = setting("Neutral Mobs", true, { page.value == Page.ENTITY_TYPE && !all.value && mobs.value })
private val hostile = setting("Hostile Mobs", true, { page.value == Page.ENTITY_TYPE && !all.value && mobs.value })
private val self by setting("Self", false, { page == Page.ENTITY_TYPE })
private val all by setting("All Entities", false, { page == Page.ENTITY_TYPE })
private val experience by setting("Experience", false, { page == Page.ENTITY_TYPE && !all })
private val arrows by setting("Arrows", false, { page == Page.ENTITY_TYPE && !all })
private val throwable by setting("Throwable", false, { page == Page.ENTITY_TYPE && !all })
private val items by setting("Items", false, { page == Page.ENTITY_TYPE && !all })
private val crystals by setting("Crystals", false, { page == Page.ENTITY_TYPE && !all })
private val players by setting("Players", true, { page == Page.ENTITY_TYPE && !all })
private val friends by setting("Friends", false, { page == Page.ENTITY_TYPE && !all && players })
private val sleeping by setting("Sleeping", false, { page == Page.ENTITY_TYPE && !all && players })
private val mobs by setting("Mobs", true, { page == Page.ENTITY_TYPE && !all })
private val passive by setting("Passive Mobs", false, { page == Page.ENTITY_TYPE && !all && mobs })
private val neutral by setting("Neutral Mobs", true, { page == Page.ENTITY_TYPE && !all && mobs })
private val hostile by setting("Hostile Mobs", true, { page == Page.ENTITY_TYPE && !all && mobs })
/* Rendering settings */
private val throughWall = setting("Through Wall", true, { page.value == Page.RENDERING })
private val texture = setting("Texture", false, { page.value == Page.RENDERING })
private val lightning = setting("Lightning", false, { page.value == Page.RENDERING })
private val customColor = setting("Custom Color", false, { page.value == Page.RENDERING })
private val rainbow = setting("Rainbow", false, { page.value == Page.RENDERING && customColor.value })
private val r = setting("Red", 255, 0..255, 1, { page.value == Page.RENDERING && customColor.value && !rainbow.value })
private val g = setting("Green", 255, 0..255, 1, { page.value == Page.RENDERING && customColor.value && !rainbow.value })
private val b = setting("Blue", 255, 0..255, 1, { page.value == Page.RENDERING && customColor.value && !rainbow.value })
private val a = setting("Alpha", 255, 0..255, 1, { page.value == Page.RENDERING && customColor.value })
private val throughWall by setting("Through Wall", true, { page == Page.RENDERING })
private val texture by setting("Texture", false, { page == Page.RENDERING })
private val lightning by setting("Lightning", false, { page == Page.RENDERING })
private val customColor by setting("Custom Color", false, { page == Page.RENDERING })
private val rainbow by setting("Rainbow", false, { page == Page.RENDERING && customColor })
private val r by setting("Red", 255, 0..255, 1, { page == Page.RENDERING && customColor && !rainbow })
private val g by setting("Green", 255, 0..255, 1, { page == Page.RENDERING && customColor && !rainbow })
private val b by setting("Blue", 255, 0..255, 1, { page == Page.RENDERING && customColor && !rainbow })
private val a by setting("Alpha", 160, 0..255, 1, { page == Page.RENDERING && customColor })
private enum class Page {
ENTITY_TYPE, RENDERING
@ -62,34 +62,47 @@ internal object Chams : Module(
private var cycler = HueCycler(600)
init {
listener<RenderEntityEvent>(2000) {
listener<RenderEntityEvent.All>(2000) {
if (!checkEntityType(it.entity)) return@listener
if (it.phase == Phase.PRE) {
if (!texture.value) glDisable(GL_TEXTURE_2D)
if (!lightning.value) glDisable(GL_LIGHTING)
if (customColor.value) {
if (rainbow.value) cycler.currentRgba(a.value).setGLColor()
else glColor4f(r.value / 255.0f, g.value / 255.0f, b.value / 255.0f, a.value / 255.0f)
GlStateUtils.colorLock(true)
GlStateUtils.blend(true)
GlStateManager.tryBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ZERO)
when (it.phase) {
Phase.PRE -> {
if (throughWall) glDepthRange(0.0, 0.01)
}
if (throughWall.value) {
glDepthRange(0.0, 0.01)
Phase.PERI -> {
if (throughWall) glDepthRange(0.0, 1.0)
}
else -> {
// Doesn't need to do anything on post phase
}
}
}
if (it.phase == Phase.PERI) {
if (!texture.value) glEnable(GL_TEXTURE_2D)
if (!lightning.value) glEnable(GL_LIGHTING)
if (customColor.value) {
GlStateUtils.blend(false)
GlStateUtils.colorLock(false)
glColor4f(1f, 1f, 1f, 1f)
listener<RenderEntityEvent.Model> {
if (!checkEntityType(it.entity)) return@listener
when (it.phase) {
Phase.PRE -> {
if (!texture) glDisable(GL_TEXTURE_2D)
if (!lightning) glDisable(GL_LIGHTING)
if (customColor) {
if (rainbow) cycler.currentRgba(a).setGLColor()
else glColor4f(r / 255.0f, g / 255.0f, b / 255.0f, a / 255.0f)
GlStateUtils.blend(true)
GlStateManager.tryBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ZERO)
}
}
if (throughWall.value) {
glDepthRange(0.0, 1.0)
Phase.POST -> {
if (!texture) glEnable(GL_TEXTURE_2D)
if (!lightning) glEnable(GL_LIGHTING)
if (customColor) {
GlStateUtils.blend(false)
glColor4f(1f, 1f, 1f, 1f)
}
}
else -> {
// RenderEntityEvent.Model doesn't have peri phase
}
}
}
@ -99,14 +112,15 @@ internal object Chams : Module(
}
}
private fun checkEntityType(entity: Entity): Boolean {
return (self.value || entity != mc.player) && (all.value
|| experience.value && entity is EntityXPOrb
|| arrows.value && entity is EntityArrow
|| throwable.value && entity is EntityThrowable
|| items.value && entity is EntityItem
|| crystals.value && entity is EntityEnderCrystal
|| players.value && entity is EntityPlayer && EntityUtils.playerTypeCheck(entity, friends.value, sleeping.value)
|| mobTypeSettings(entity, mobs.value, passive.value, neutral.value, hostile.value))
}
private fun checkEntityType(entity: Entity) =
(self || entity != mc.player) && (
all
|| experience && entity is EntityXPOrb
|| arrows && entity is EntityArrow
|| throwable && entity is EntityThrowable
|| items && entity is EntityItem
|| crystals && entity is EntityEnderCrystal
|| players && entity is EntityPlayer && EntityUtils.playerTypeCheck(entity, friends, sleeping)
|| mobTypeSettings(entity, mobs, passive, neutral, hostile)
)
}

View File

@ -14,21 +14,21 @@ import org.kamiblue.client.event.Phase
import org.kamiblue.client.event.SafeClientEvent
import org.kamiblue.client.event.events.RenderEntityEvent
import org.kamiblue.client.event.events.RenderWorldEvent
import org.kamiblue.client.mixin.extension.entityOutlineShader
import org.kamiblue.client.mixin.extension.listFrameBuffers
import org.kamiblue.client.mixin.extension.listShaders
import org.kamiblue.client.mixin.extension.renderOutlines
import org.kamiblue.client.mixin.extension.*
import org.kamiblue.client.module.Category
import org.kamiblue.client.module.Module
import org.kamiblue.client.util.EntityUtils
import org.kamiblue.client.util.EntityUtils.getTargetList
import org.kamiblue.client.util.color.ColorHolder
import org.kamiblue.client.util.graphics.ESPRenderer
import org.kamiblue.client.util.graphics.GlStateUtils
import org.kamiblue.client.util.graphics.KamiTessellator
import org.kamiblue.client.util.graphics.ShaderHelper
import org.kamiblue.client.util.threads.runSafe
import org.kamiblue.client.util.threads.safeListener
import org.kamiblue.event.listener.listener
import org.lwjgl.opengl.GL11.*
import org.lwjgl.opengl.GL11.GL_MODELVIEW
import org.lwjgl.opengl.GL11.GL_PROJECTION
internal object ESP : Module(
name = "ESP",
@ -74,87 +74,29 @@ internal object ESP : Module(
BOX, GLOW, SHADER
}
private val entityList = HashSet<Entity>()
private val entityList = LinkedHashSet<Entity>()
var drawingOutline = false; private set
var drawNametag = false; private set
private val shaderHelper = ShaderHelper(ResourceLocation("shaders/post/esp_outline.json"), "final")
val frameBuffer = shaderHelper.getFrameBuffer("final")
private val frameBuffer = shaderHelper.getFrameBuffer("final")
init {
listener<RenderEntityEvent> {
if (mode.value != ESPMode.SHADER || mc.renderManager.renderOutlines || !entityList.contains(it.entity)) return@listener
if (it.phase == Phase.PRE && hideOriginal) {
// Steal it from Minecraft rendering kek
prepareFrameBuffer()
drawNametag = true
}
if (it.phase == Phase.PERI) {
if (!hideOriginal) {
prepareFrameBuffer()
mc.renderManager.getEntityRenderObject<Entity>(it.entity)?.doRender(it.entity, it.x, it.y, it.z, it.yaw, it.partialTicks)
}
mc.framebuffer.bindFramebuffer(false)
GlStateManager.disableOutlineMode()
drawingOutline = false
drawNametag = false
listener<RenderEntityEvent.All> {
if (it.phase == Phase.PRE
&& mode.value == ESPMode.SHADER
&& !mc.renderManager.renderOutlines
&& hideOriginal
&& entityList.contains(it.entity)) {
it.cancel()
}
}
listener<RenderWorldEvent>(69420) {
if (mode.value != ESPMode.SHADER) return@listener
GlStateManager.matrixMode(GL_PROJECTION)
glPushMatrix()
GlStateManager.matrixMode(GL_MODELVIEW)
glPushMatrix()
shaderHelper.shader?.render(KamiTessellator.pTicks())
// Re-enable blend because shader rendering will disable it at the end
GlStateManager.enableBlend()
GlStateManager.disableDepth()
// Draw it on the main frame buffer
mc.framebuffer.bindFramebuffer(false)
frameBuffer?.framebufferRenderExt(mc.displayWidth, mc.displayHeight, false)
// Clean up the frame buffer
frameBuffer?.framebufferClear()
mc.framebuffer.bindFramebuffer(false)
GlStateManager.disableCull()
GlStateManager.enableBlend()
GlStateManager.enableDepth()
GlStateManager.disableTexture2D()
GlStateManager.depthMask(false)
GlStateManager.matrixMode(GL_PROJECTION)
glPopMatrix()
GlStateManager.matrixMode(GL_MODELVIEW)
glPopMatrix()
}
}
private fun prepareFrameBuffer() {
drawingOutline = true
GlStateManager.enableOutlineMode(0xFFFFFF)
frameBuffer?.bindFramebuffer(false)
}
init {
safeListener<EntityViewRenderEvent.FogColors> { event ->
shaderHelper.shader?.listFrameBuffers?.forEach {
it.setFramebufferColor(event.red, event.green, event.blue, 0.0f)
}
}
safeListener<RenderWorldEvent> {
if (mc.renderManager.options == null) return@safeListener
safeListener<RenderWorldEvent>(69420) {
when (mode.value) {
ESPMode.BOX -> {
val color = ColorHolder(r, g, b)
@ -167,35 +109,104 @@ internal object ESP : Module(
}
renderer.render(true)
}
ESPMode.SHADER -> {
drawEntities()
drawShader()
}
else -> {
// Glow and Shader mode
// Glow Mode
}
}
}
}
private fun drawEntities() {
// Clean up the frame buffer and bind it
frameBuffer?.framebufferClear()
frameBuffer?.bindFramebuffer(false)
val prevRenderOutlines = mc.renderManager.renderOutlines
GlStateUtils.texture2d(true)
GlStateUtils.cull(true)
// Draw the entities into the framebuffer
for (entity in entityList) {
val renderer = mc.renderManager.getEntityRenderObject<Entity>(entity) ?: continue
val partialTicks = KamiTessellator.pTicks()
val yaw = entity.prevRotationYaw + (entity.rotationYaw - entity.prevRotationYaw) * partialTicks
val pos = EntityUtils.getInterpolatedPos(entity, partialTicks)
.subtract(mc.renderManager.renderPosX, mc.renderManager.renderPosY, mc.renderManager.renderPosZ)
renderer.setRenderOutlines(true)
renderer.doRender(entity, pos.x, pos.y, pos.z, yaw, partialTicks)
renderer.setRenderOutlines(prevRenderOutlines)
}
GlStateUtils.texture2d(false)
}
private fun drawShader() {
// Push matrix
GlStateManager.matrixMode(GL_PROJECTION)
GlStateManager.pushMatrix()
GlStateManager.matrixMode(GL_MODELVIEW)
GlStateManager.pushMatrix()
shaderHelper.shader?.render(KamiTessellator.pTicks())
// Re-enable blend because shader rendering will disable it at the end
GlStateUtils.blend(true)
GlStateUtils.depth(false)
// Draw it on the main frame buffer
mc.framebuffer.bindFramebuffer(false)
frameBuffer?.framebufferRenderExt(mc.displayWidth, mc.displayHeight, false)
// Revert states
GlStateUtils.blend(true)
GlStateUtils.depth(true)
GlStateUtils.texture2d(false)
GlStateManager.depthMask(false)
GlStateUtils.cull(false)
// Revert matrix
GlStateManager.matrixMode(GL_PROJECTION)
GlStateManager.popMatrix()
GlStateManager.matrixMode(GL_MODELVIEW)
GlStateManager.popMatrix()
}
init {
safeListener<TickEvent.ClientTickEvent> {
entityList.clear()
entityList.addAll(getEntityList())
if (mode.value == ESPMode.GLOW) {
if (entityList.isNotEmpty()) {
for (shader in mc.renderGlobal.entityOutlineShader.listShaders) {
shader.shaderManager.getShaderUniform("Radius")?.set(width)
}
when (mode.value) {
ESPMode.GLOW -> {
if (entityList.isNotEmpty()) {
for (shader in mc.renderGlobal.entityOutlineShader.listShaders) {
shader.shaderManager.getShaderUniform("Radius")?.set(width)
}
for (entity in world.loadedEntityList) { // Set glow for entities in the list. Remove glow for entities not in the list
entity.isGlowing = entityList.contains(entity)
for (entity in world.loadedEntityList) { // Set glow for entities in the list. Remove glow for entities not in the list
entity.isGlowing = entityList.contains(entity)
}
} else {
resetGlow()
}
} else {
resetGlow()
}
} else if (mode.value == ESPMode.SHADER) {
shaderHelper.shader?.let {
for (shader in it.listShaders) {
setShaderSettings(shader)
ESPMode.SHADER -> {
shaderHelper.shader?.let {
for (shader in it.listShaders) {
setShaderSettings(shader)
}
}
}
else -> {
// Box Mode
}
}
}
}
@ -240,8 +251,6 @@ internal object ESP : Module(
}
mode.listeners.add {
drawingOutline = false
drawNametag = false
resetGlow()
}
}

View File

@ -24,6 +24,8 @@ import org.kamiblue.client.util.graphics.font.*
import org.kamiblue.client.util.items.originalName
import org.kamiblue.client.util.math.Vec2d
import org.kamiblue.client.util.threads.safeListener
import org.kamiblue.commons.extension.ceilToInt
import org.kamiblue.commons.extension.floorToInt
import org.kamiblue.commons.utils.MathUtils
import org.kamiblue.event.listener.listener
import org.lwjgl.opengl.GL11.*
@ -98,7 +100,6 @@ internal object Nametags : Module(
private val bText = setting("Text Blue", 255, 0..255, 1, { page.value == Page.RENDERING })
private val aText = setting("Text Alpha", 255, 0..255, 1, { page.value == Page.RENDERING })
private val customFont = setting("Custom Font", true, { page.value == Page.RENDERING })
private val textShadow = setting("Text Shadow", true, { page.value == Page.RENDERING })
private val yOffset = setting("Y Offset", 0.5f, -2.5f..2.5f, 0.05f, { page.value == Page.RENDERING })
private val scale = setting("Scale", 1f, 0.25f..5f, 0.25f, { page.value == Page.RENDERING })
private val distScaleFactor = setting("Distance Scale Factor", 0.0f, 0.0f..1.0f, 0.05f, { page.value == Page.RENDERING })
@ -137,36 +138,56 @@ internal object Nametags : Module(
listener<RenderOverlayEvent> {
if (entityMap.isEmpty() && itemMap.isEmpty()) return@listener
GlStateUtils.rescaleActual()
val camPos = KamiTessellator.camPos
val vertexHelper = VertexHelper(GlStateUtils.useVbo())
val xRange = 0..mc.displayWidth
val yRange = 0..mc.displayHeight
for ((entity, textComponent) in entityMap) {
val pos = EntityUtils.getInterpolatedPos(entity, KamiTessellator.pTicks()).add(0.0, (entity.height + yOffset.value).toDouble(), 0.0)
val screenPos = ProjectionUtils.toScreenPos(pos)
val dist = camPos.distanceTo(pos).toFloat() * 0.2f
val distFactor = if (distScaleFactor.value == 0f) 1f else max(1f / (dist * distScaleFactor.value + 1f), minDistScale.value)
drawNametag(screenPos, (scale.value * 2f) * distFactor, vertexHelper, nameFrame.value, textComponent)
drawItems(screenPos, (scale.value * 2f) * distFactor, vertexHelper, entity, textComponent)
if (drawNametag(screenPos, (scale.value * 2f) * distFactor, xRange, yRange, vertexHelper, nameFrame.value, textComponent)) {
drawItems(screenPos, (scale.value * 2f) * distFactor, vertexHelper, entity, textComponent)
}
}
for (itemGroup in itemMap) {
val pos = itemGroup.getCenter(KamiTessellator.pTicks()).add(0.0, yOffset.value.toDouble(), 0.0)
val screenPos = ProjectionUtils.toScreenPos(pos)
val dist = camPos.distanceTo(pos).toFloat() * 0.2f
val distFactor = if (distScaleFactor.value == 0f) 1f else max(1f / (dist * distScaleFactor.value + 1f), minDistScale.value)
drawNametag(screenPos, (scale.value * 2f) * distFactor, vertexHelper, dropItemFrame.value, itemGroup.textComponent)
drawNametag(screenPos, (scale.value * 2f) * distFactor, xRange, yRange, vertexHelper, dropItemFrame.value, itemGroup.textComponent)
}
GlStateUtils.rescaleMc()
}
}
private fun drawNametag(screenPos: Vec3d, scale: Float, vertexHelper: VertexHelper, drawFrame: Boolean, textComponent: TextComponent) {
private fun drawNametag(screenPos: Vec3d, scale: Float, xRange: IntRange, yRange: IntRange, vertexHelper: VertexHelper, drawFrame: Boolean, textComponent: TextComponent): Boolean {
val halfWidth = textComponent.getWidth(customFont.value) / 2.0 + margins.value + 2.0
val halfHeight = textComponent.getHeight(2, true, customFont.value) / 2.0 + margins.value + 2.0
val scaledHalfWidth = halfWidth * scale
val scaledHalfHeight = halfHeight * scale
if ((screenPos.x - scaledHalfWidth).floorToInt() !in xRange
&& (screenPos.x + scaledHalfWidth).ceilToInt() !in xRange
|| (screenPos.y - scaledHalfHeight).floorToInt() !in yRange
&& (screenPos.y + scaledHalfHeight).ceilToInt() !in yRange) return false
glPushMatrix()
glTranslatef(screenPos.x.toFloat(), screenPos.y.toFloat(), 0f)
glScalef(scale, scale, 1f)
val halfWidth = textComponent.getWidth(customFont.value) / 2.0 + margins.value + 2.0
val halfHeight = textComponent.getHeight(2, true, customFont.value) / 2.0 + margins.value + 2.0
if (drawFrame) drawFrame(vertexHelper, Vec2d(-halfWidth, -halfHeight), Vec2d(halfWidth, halfHeight))
textComponent.draw(drawShadow = textShadow.value, skipEmptyLine = true, horizontalAlign = HAlign.CENTER, verticalAlign = VAlign.CENTER, customFont = customFont.value)
textComponent.draw(skipEmptyLine = true, horizontalAlign = HAlign.CENTER, verticalAlign = VAlign.CENTER, customFont = customFont.value)
glPopMatrix()
return true
}
private fun drawItems(screenPos: Vec3d, nameTagScale: Float, vertexHelper: VertexHelper, entity: Entity, textComponent: TextComponent) {
@ -239,21 +260,21 @@ internal object Nametags : Module(
val color = healthColorGradient.get(duraPercentage)
val text = duraPercentage.roundToInt().toString()
val textWidth = FontRenderAdapter.getStringWidth(text, customFont = customFont.value)
FontRenderAdapter.drawString(text, 8f - textWidth / 2f, 17f, textShadow.value, color, customFont = customFont.value)
FontRenderAdapter.drawString(text, 8f - textWidth / 2f, 17f, color = color, customFont = customFont.value)
}
if (count.value && itemStack.count > 1) {
val itemCount = itemStack.count.toString()
glTranslatef(0f, 0f, 60f)
val stringWidth = 17f - FontRenderAdapter.getStringWidth(itemCount, customFont = customFont.value)
FontRenderAdapter.drawString(itemCount, stringWidth, 9f, textShadow.value, customFont = customFont.value)
FontRenderAdapter.drawString(itemCount, stringWidth, 9f, customFont = customFont.value)
glTranslatef(0f, 0f, -60f)
}
glTranslatef(0f, -2f, 0f)
if (enchantment.value) {
val scale = if (customFont.value) 0.6f else 0.5f
enchantmentText.draw(lineSpace = 2, scale = scale, drawShadow = textShadow.value, verticalAlign = VAlign.BOTTOM, customFont = customFont.value)
enchantmentText.draw(lineSpace = 2, scale = scale, verticalAlign = VAlign.BOTTOM, customFont = customFont.value)
}
glTranslatef(28f, 2f, 0f)

View File

@ -133,7 +133,7 @@ internal object NoRender : Module(
}
}
listener<RenderEntityEvent> {
listener<RenderEntityEvent.All> {
if (it.phase != Phase.PRE) return@listener
if (entityList.contains(it.entity.javaClass)

View File

@ -1,9 +1,14 @@
package org.kamiblue.client.util
import net.minecraft.client.Minecraft
import net.minecraft.client.entity.EntityPlayerSP
import net.minecraft.entity.Entity
import net.minecraft.init.MobEffects
import net.minecraft.util.MovementInput
import net.minecraft.util.math.BlockPos
import org.kamiblue.client.event.SafeClientEvent
import org.kamiblue.client.util.EntityUtils.flooredPosition
import org.kamiblue.client.util.math.VectorUtils.toVec3d
import kotlin.math.cos
import kotlin.math.hypot
import kotlin.math.sin
@ -50,4 +55,42 @@ object MovementUtils {
player.getActivePotionEffect(MobEffects.SPEED)?.let {
speed * (1.0 + (it.amplifier + 1) * 0.2)
} ?: speed
fun EntityPlayerSP.centerPlayer(): Boolean {
val center = this.flooredPosition.toVec3d(0.5, 0.0, 0.5)
val centered = isCentered(this.flooredPosition)
if (!centered) {
this.motionX = (center.x - this.posX) / 2.0
this.motionZ = (center.z - this.posZ) / 2.0
val speed = this.speed
if (speed > 0.2805) {
val multiplier = 0.2805 / speed
this.motionX *= multiplier
this.motionZ *= multiplier
}
}
return centered
}
fun Entity.isCentered(pos: BlockPos) =
this.posX in pos.x + 0.31..pos.x + 0.69
&& this.posZ in pos.z + 0.31..pos.z + 0.69
fun MovementInput.resetMove() {
moveForward = 0.0f
moveStrafe = 0.0f
forwardKeyDown = false
backKeyDown = false
leftKeyDown = false
rightKeyDown = false
}
fun MovementInput.resetJumpSneak() {
jump = false
sneak = false
}
}

View File

@ -4,11 +4,9 @@ import net.minecraft.block.Block
import net.minecraft.entity.Entity
import net.minecraft.init.Blocks
import net.minecraft.util.math.BlockPos
import net.minecraft.util.math.Vec3d
import org.kamiblue.client.event.SafeClientEvent
import org.kamiblue.client.util.EntityUtils.flooredPosition
import org.kamiblue.client.util.Wrapper
import kotlin.math.round
object SurroundUtils {
private val mc = Wrapper.minecraft
@ -21,13 +19,6 @@ object SurroundUtils {
BlockPos(-1, 0, 0) // west
)
val surroundOffsetNoFloor = arrayOf(
BlockPos(0, 0, -1), // north
BlockPos(1, 0, 0), // east
BlockPos(0, 0, 1), // south
BlockPos(-1, 0, 0) // west
)
fun SafeClientEvent.checkHole(entity: Entity) =
checkHole(entity.flooredPosition)
@ -51,38 +42,10 @@ object SurroundUtils {
return type
}
fun checkBlock(block: Block): Boolean {
private fun checkBlock(block: Block): Boolean {
return block == Blocks.BEDROCK || block == Blocks.OBSIDIAN || block == Blocks.ENDER_CHEST || block == Blocks.ANVIL
}
fun centerPlayer(tp: Boolean): Boolean {
val centerDiff = getCenterDiff()
val centered = isCentered()
if (!centered) {
if (tp) {
val posX = mc.player.posX + (centerDiff.x).coerceIn(-0.2, 0.2)
val posZ = mc.player.posZ + (centerDiff.z).coerceIn(-0.2, 0.2)
mc.player.setPosition(posX, mc.player.posY, posZ)
} else {
mc.player.motionX = (centerDiff.x / 2.0).coerceIn(-0.2, 0.2)
mc.player.motionZ = (centerDiff.z / 2.0).coerceIn(-0.2, 0.2)
}
}
return centered
}
private fun isCentered(): Boolean {
return getCenterDiff().length() < 0.2
}
private fun getCenterDiff(): Vec3d {
return Vec3d(roundToCenter(mc.player.posX), mc.player.posY, roundToCenter(mc.player.posZ)).subtract(mc.player.positionVector)
}
private fun roundToCenter(doubleIn: Double): Double {
return round(doubleIn + 0.5) - 0.5
}
enum class HoleType {
NONE, OBBY, BEDROCK
}

View File

@ -29,10 +29,6 @@ object GlStateUtils {
}
}
@JvmStatic
var colorLock = false
private set
fun useVbo(): Boolean {
return mc.gameSettings.useVbo
}
@ -102,11 +98,6 @@ object GlStateUtils {
}
}
@JvmStatic
fun colorLock(state: Boolean) {
colorLock = state
}
fun rescaleActual() {
rescale(Wrapper.minecraft.displayWidth.toDouble(), Wrapper.minecraft.displayHeight.toDouble())
}

View File

@ -18,8 +18,8 @@ import org.kamiblue.client.util.threads.onMainThreadSafe
* or slot 0 if none
*/
inline fun <reified I : Block> SafeClientEvent.swapToBlockOrMove(
crossinline predicateItem: (ItemStack) -> Boolean = { true },
noinline predicateSlot: (ItemStack) -> Boolean = { true }
predicateItem: (ItemStack) -> Boolean = { true },
predicateSlot: (ItemStack) -> Boolean = { true }
): Boolean {
return if (swapToBlock<I>(predicateItem)) {
true
@ -59,8 +59,8 @@ fun SafeClientEvent.swapToBlockOrMove(
* or slot 0 if none
*/
inline fun <reified I : Item> SafeClientEvent.swapToItemOrMove(
crossinline predicateItem: (ItemStack) -> Boolean = { true },
noinline predicateSlot: (ItemStack) -> Boolean = { true }
predicateItem: (ItemStack) -> Boolean = { true },
predicateSlot: (ItemStack) -> Boolean = { true }
): Boolean {
return if (swapToItem<I>(predicateItem)) {
true
@ -117,7 +117,7 @@ fun SafeClientEvent.swapToItemOrMove(
/**
* Try to swap selected hotbar slot to [I] that matches with [predicate]
*/
inline fun <reified I : Block> SafeClientEvent.swapToBlock(crossinline predicate: (ItemStack) -> Boolean = { true }): Boolean {
inline fun <reified I : Block> SafeClientEvent.swapToBlock(predicate: (ItemStack) -> Boolean = { true }): Boolean {
return player.hotbarSlots.firstBlock<I, HotbarSlot>(predicate)?.let {
swapToSlot(it)
true
@ -137,7 +137,7 @@ fun SafeClientEvent.swapToBlock(block: Block, predicate: (ItemStack) -> Boolean
/**
* Try to swap selected hotbar slot to [I] that matches with [predicate]
*/
inline fun <reified I : Item> SafeClientEvent.swapToItem(crossinline predicate: (ItemStack) -> Boolean = { true }): Boolean {
inline fun <reified I : Item> SafeClientEvent.swapToItem(predicate: (ItemStack) -> Boolean = { true }): Boolean {
return player.hotbarSlots.firstItem<I, HotbarSlot>(predicate)?.let {
swapToSlot(it)
true
@ -184,7 +184,7 @@ fun SafeClientEvent.swapToSlot(slot: Int) {
* Swaps the item in [slotFrom] with the first empty hotbar slot
* or matches with [predicate] or slot 0 if none of those found
*/
fun SafeClientEvent.moveToHotbar(slotFrom: Slot, predicate: (ItemStack) -> Boolean): Short {
inline fun SafeClientEvent.moveToHotbar(slotFrom: Slot, predicate: (ItemStack) -> Boolean): Short {
return moveToHotbar(slotFrom.slotNumber, predicate)
}
@ -192,7 +192,7 @@ fun SafeClientEvent.moveToHotbar(slotFrom: Slot, predicate: (ItemStack) -> Boole
* Swaps the item in [slotFrom] with the first empty hotbar slot
* or matches with [predicate] or slot 0 if none of those found
*/
fun SafeClientEvent.moveToHotbar(slotFrom: Int, predicate: (ItemStack) -> Boolean): Short {
inline fun SafeClientEvent.moveToHotbar(slotFrom: Int, predicate: (ItemStack) -> Boolean): Short {
val hotbarSlots = player.hotbarSlots
val slotTo = hotbarSlots.firstItem(Items.AIR)?.hotbarSlot
?: hotbarSlots.firstByStack(predicate)?.hotbarSlot ?: 0

View File

@ -41,7 +41,7 @@ fun Container.getSlots(range: IntRange): List<Slot> =
fun Iterable<Slot>.countEmpty() =
count { it.stack.isEmpty }
inline fun <reified B : Block> Iterable<Slot>.countBlock(crossinline predicate: (ItemStack) -> Boolean = { true }) =
inline fun <reified B : Block> Iterable<Slot>.countBlock(predicate: (ItemStack) -> Boolean = { true }) =
countByStack { itemStack ->
itemStack.item.let { it is ItemBlock && it.block is B } && predicate(itemStack)
}
@ -51,7 +51,7 @@ fun Iterable<Slot>.countBlock(block: Block, predicate: (ItemStack) -> Boolean =
itemStack.item.let { it is ItemBlock && it.block == block } && predicate(itemStack)
}
inline fun <reified I : Item> Iterable<Slot>.countItem(crossinline predicate: (ItemStack) -> Boolean = { true }) =
inline fun <reified I : Item> Iterable<Slot>.countItem(predicate: (ItemStack) -> Boolean = { true }) =
countByStack { it.item is I && predicate(it) }
fun Iterable<Slot>.countItem(item: Item, predicate: (ItemStack) -> Boolean = { true }) =
@ -60,7 +60,7 @@ fun Iterable<Slot>.countItem(item: Item, predicate: (ItemStack) -> Boolean = { t
fun Iterable<Slot>.countID(itemID: Int, predicate: (ItemStack) -> Boolean = { true }) =
countByStack { it.item.id == itemID && predicate(it) }
fun Iterable<Slot>.countByStack(predicate: (ItemStack) -> Boolean = { true }) =
inline fun Iterable<Slot>.countByStack(predicate: (ItemStack) -> Boolean = { true }) =
sumBy { slot ->
slot.stack.let { if (predicate(it)) it.count else 0 }
}
@ -69,7 +69,7 @@ fun Iterable<Slot>.countByStack(predicate: (ItemStack) -> Boolean = { true }) =
fun <T : Slot> Iterable<T>.firstEmpty() =
firstByStack { it.isEmpty }
inline fun <reified B : Block, T : Slot> Iterable<T>.firstBlock(crossinline predicate: (ItemStack) -> Boolean = { true }) =
inline fun <reified B : Block, T : Slot> Iterable<T>.firstBlock(predicate: (ItemStack) -> Boolean = { true }) =
firstByStack { itemStack ->
itemStack.item.let { it is ItemBlock && it.block is B } && predicate(itemStack)
}
@ -79,7 +79,7 @@ fun <T : Slot> Iterable<T>.firstBlock(block: Block, predicate: (ItemStack) -> Bo
itemStack.item.let { it is ItemBlock && it.block == block } && predicate(itemStack)
}
inline fun <reified I : Item, T : Slot> Iterable<T>.firstItem(crossinline predicate: (ItemStack) -> Boolean = { true }) =
inline fun <reified I : Item, T : Slot> Iterable<T>.firstItem(predicate: (ItemStack) -> Boolean = { true }) =
firstByStack {
it.item is I && predicate(it)
}
@ -94,14 +94,14 @@ fun <T : Slot> Iterable<T>.firstID(itemID: Int, predicate: (ItemStack) -> Boolea
it.item.id == itemID && predicate(it)
}
fun <T : Slot> Iterable<T>.firstByStack(predicate: (ItemStack) -> Boolean): T? =
inline fun <T : Slot> Iterable<T>.firstByStack(predicate: (ItemStack) -> Boolean): T? =
firstOrNull { predicate(it.stack) }
inline fun <reified B : Block, T : Slot> Iterable<T>.forEmpty() =
filterByStack { it.isEmpty }
inline fun <reified B : Block, T : Slot> Iterable<T>.filterByBlock(crossinline predicate: (ItemStack) -> Boolean = { true }) =
inline fun <reified B : Block, T : Slot> Iterable<T>.filterByBlock(predicate: (ItemStack) -> Boolean = { true }) =
filterByStack { itemStack ->
itemStack.item.let { it is ItemBlock && it.block is B } && predicate(itemStack)
}
@ -111,7 +111,7 @@ fun <T : Slot> Iterable<T>.filterByBlock(block: Block, predicate: (ItemStack) ->
itemStack.item.let { it is ItemBlock && it.block == block } && predicate(itemStack)
}
inline fun <reified I : Item, T : Slot> Iterable<T>.filterByItem(crossinline predicate: (ItemStack) -> Boolean = { true }) =
inline fun <reified I : Item, T : Slot> Iterable<T>.filterByItem(predicate: (ItemStack) -> Boolean = { true }) =
filterByStack {
it.item is I && predicate(it)
}
@ -124,7 +124,7 @@ fun <T : Slot> Iterable<T>.filterByItem(item: Item, predicate: (ItemStack) -> Bo
fun <T : Slot> Iterable<T>.filterByID(itemID: Int, predicate: (ItemStack) -> Boolean = { true }) =
filterByStack { it.item.id == itemID && predicate(it) }
fun <T : Slot> Iterable<T>.filterByStack(predicate: (ItemStack) -> Boolean = { true }) =
inline fun <T : Slot> Iterable<T>.filterByStack(predicate: (ItemStack) -> Boolean = { true }) =
filter { predicate(it.stack) }
fun Slot.toHotbarSlotOrNull() =

View File

@ -29,14 +29,14 @@ object MainThreadExecutor {
runBlocking {
mutex.withLock {
jobs.forEach {
launch { it.run() }
it.run()
}
jobs.clear()
}
}
}
suspend fun <T> add(block: suspend () -> T) =
suspend fun <T> add(block: () -> T) =
MainThreadJob(block).apply {
if (Wrapper.minecraft.isCallingFromMinecraftThread) {
run()
@ -47,10 +47,10 @@ object MainThreadExecutor {
}
}.deferred
private class MainThreadJob<T>(private val block: suspend () -> T) {
private class MainThreadJob<T>(private val block: () -> T) {
val deferred = CompletableDeferred<T>()
suspend fun run() {
fun run() {
deferred.completeWith(
runCatching { block.invoke() }
)

View File

@ -11,11 +11,19 @@ import org.kamiblue.event.listener.DEFAULT_PRIORITY
import org.kamiblue.event.listener.Listener
inline fun <reified T : Any> Any.safeAsyncListener(noinline function: suspend SafeClientEvent.(T) -> Unit) {
ListenerManager.register(this, AsyncListener(this, T::class.java) { runSafeSuspend { function(it) } })
this.safeAsyncListener(T::class.java, function)
}
fun <T : Any> Any.safeAsyncListener(clazz: Class<T>, function: suspend SafeClientEvent.(T) -> Unit) {
ListenerManager.register(this, AsyncListener(this, clazz) { runSafeSuspend { function(it) } })
}
inline fun <reified T : Any> Any.safeListener(priority: Int = DEFAULT_PRIORITY, noinline function: SafeClientEvent.(T) -> Unit) {
ListenerManager.register(this, Listener(this, T::class.java, priority) { runSafe { function(it) } })
this.safeListener(priority, T::class.java, function)
}
fun <T : Any> Any.safeListener(priority: Int = DEFAULT_PRIORITY ,clazz: Class<T>, function: SafeClientEvent.(T) -> Unit) {
ListenerManager.register(this, Listener(this, clazz, priority) { runSafe { function(it) } })
}
fun ClientEvent.toSafe() =
@ -26,11 +34,11 @@ fun ClientExecuteEvent.toSafe() =
if (world != null && player != null && playerController != null && connection != null) SafeExecuteEvent(world, player, playerController, connection, this)
else null
fun runSafe(block: SafeClientEvent.() -> Unit) {
inline fun runSafe(block: SafeClientEvent.() -> Unit) {
ClientEvent().toSafe()?.let { block(it) }
}
fun <R> runSafeR(block: SafeClientEvent.() -> R): R? {
inline fun <R> runSafeR(block: SafeClientEvent.() -> R): R? {
return ClientEvent().toSafe()?.let { block(it) }
}
@ -46,7 +54,7 @@ suspend fun <R> runSafeSuspend(block: suspend SafeClientEvent.() -> R): R? {
*
* @see [onMainThread]
*/
suspend fun <T> onMainThreadSafe(block: suspend SafeClientEvent.() -> T) =
suspend fun <T> onMainThreadSafe(block: SafeClientEvent.() -> T) =
onMainThread { ClientEvent().toSafe()?.block() }
/**
@ -56,5 +64,5 @@ suspend fun <T> onMainThreadSafe(block: suspend SafeClientEvent.() -> T) =
*
* @see [onMainThreadSafe]
*/
suspend fun <T> onMainThread(block: suspend () -> T) =
suspend fun <T> onMainThread(block: () -> T) =
MainThreadExecutor.add(block)

View File

@ -52,22 +52,22 @@
"render.MixinDebugRendererChunkBorder",
"render.MixinEntityRenderer",
"render.MixinFontRenderer",
"render.MixinGlStateManager",
"render.MixinItemRenderer",
"render.MixinLayerArmorBase",
"render.MixinLayerCape",
"render.MixinLayerElytra",
"render.MixinLayerHeldItem",
"render.MixinMapItemRenderer",
"render.MixinModelBiped",
"render.MixinModelBoat",
"render.MixinParticleManager",
"render.MixinRender",
"render.MixinRenderGlobal",
"render.MixinRenderLivingBase",
"render.MixinRenderManager",
"render.MixinRenderPlayer",
"render.MixinTileEntityRendererDispatcher",
"render.MixinTileEntitySignRenderer",
"render.MixinViewFrustum",
"render.MixinVisGraph",
"world.MixinBlockLiquid",
"world.MixinBlockSoulSand",