[feature] Combat update

Co-authored-by: wnuke <wnuke@wnuke.dev>
Co-authored-by: Dominika <sokolov.dominika@gmail.com>
Co-authored-by: epicfacethe3rd <mtmarting0702@gmail.com>
This commit is contained in:
Xiaro 2020-10-04 20:46:16 -04:00 committed by GitHub
parent 0d365ed58e
commit b2448f041b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
49 changed files with 2556 additions and 2208 deletions

View File

@ -2,7 +2,7 @@ complexity:
active: true
ComplexMethod:
active: true
threshold: 25
threshold: 50
style:
active: true

View File

@ -34,6 +34,8 @@ object ForgeEventProcessor {
@SubscribeEvent
fun onTick(event: TickEvent.ClientTickEvent) {
KamiMod.EVENT_BUS.post(event)
if (mc.displayWidth != displayWidth || mc.displayHeight != displayHeight) {
displayWidth = mc.displayWidth
displayHeight = mc.displayHeight

View File

@ -8,7 +8,7 @@ import me.zeroeightsix.kami.util.Wrapper.minecraft
* Updated by Xiaro on 18/08/20
*/
open class KamiEvent : Cancellable() {
val era = Era.PRE
var era: Era = Era.PRE
open val partialTicks: Float = minecraft.renderPartialTicks
enum class Era {

View File

@ -6,4 +6,4 @@ import net.minecraft.entity.Entity
/**
* Updated by Xiaro on 18/08/20
*/
class ClientPlayerAttackEvent(val targetEntity: Entity) : KamiEvent()
class ClientPlayerAttackEvent(val entity: Entity) : KamiEvent()

View File

@ -18,4 +18,5 @@ open class RenderEntityEvent(
class Pre(entity: Entity?, x: Double, y: Double, z: Double, yaw: Float, partialTicks: Float, debug: Boolean) : RenderEntityEvent(entity, x, y, z, yaw, partialTicks, debug)
class Post(entity: Entity?, x: Double, y: Double, z: Double, yaw: Float, partialTicks: Float, debug: Boolean) : RenderEntityEvent(entity, x, y, z, yaw, partialTicks, debug)
class Final(entity: Entity?, x: Double, y: Double, z: Double, yaw: Float, partialTicks: Float, debug: Boolean) : RenderEntityEvent(entity, x, y, z, yaw, partialTicks, debug)
}

View File

@ -0,0 +1,53 @@
package me.zeroeightsix.kami.manager.mangers
import me.zeroeightsix.kami.module.Module
import me.zeroeightsix.kami.module.ModuleManager
import me.zeroeightsix.kami.util.MotionTracker
import net.minecraft.entity.EntityLivingBase
import java.util.*
import kotlin.collections.ArrayList
/**
* @author Xiaro
*
* Created by Xiaro on 06/08/20
*/
object CombatManager {
private val combatModules = ArrayList<Module>()
var targetList = LinkedList<EntityLivingBase>()
var target: EntityLivingBase? = null
set(value) {
motionTracker.target = value
field = value
}
val motionTracker = MotionTracker(null)
fun isActiveAndTopPriority(module: Module) = module.isActive() && isOnTopPriority(module)
fun isOnTopPriority(module: Module): Boolean {
return getTopPriority() <= module.modulePriority
}
fun getTopPriority(): Int {
return getTopModule()?.modulePriority ?: -1
}
fun getTopModule(): Module? {
var topModule: Module? = null
for (module in combatModules) {
if (!module.isActive()) continue
if (module.modulePriority < topModule?.modulePriority ?: 0) continue
topModule = module
}
return topModule
}
init {
for (module in ModuleManager.getModules()) {
if (module.category != Module.Category.COMBAT) continue
if (module.modulePriority == -1) continue
combatModules.add(module)
}
}
}

View File

@ -3,10 +3,17 @@ package me.zeroeightsix.kami.manager.mangers
import me.zero.alpine.listener.EventHandler
import me.zero.alpine.listener.EventHook
import me.zero.alpine.listener.Listener
import me.zeroeightsix.kami.event.KamiEvent
import me.zeroeightsix.kami.event.events.OnUpdateWalkingPlayerEvent
import me.zeroeightsix.kami.event.events.PacketEvent
import me.zeroeightsix.kami.event.events.RenderEntityEvent
import me.zeroeightsix.kami.manager.Manager
import me.zeroeightsix.kami.module.Module
import me.zeroeightsix.kami.util.TimerUtils
import me.zeroeightsix.kami.util.Wrapper
import me.zeroeightsix.kami.util.math.Vec2f
import net.minecraft.network.play.client.CPacketHeldItemChange
import net.minecraft.network.play.client.CPacketPlayer
import net.minecraft.util.math.Vec3d
import java.util.*
@ -15,11 +22,26 @@ object PlayerPacketManager : Manager() {
/** TreeMap for all packets to be sent, sorted by their callers' priority */
private val packetList = TreeMap<Module, PlayerPacket>(compareByDescending { it.modulePriority })
var serverSidePosition = Vec3d(0.0, 0.0, 0.0)
private set
var prevServerSideRotation = Vec2f(0f, 0f)
private set
var serverSideRotation = Vec2f(0f, 0f)
private var clientSidePitch = Vec2f(0f, 0f)
var serverSideHotbar = 0
private set
private var spoofingHotbar = false
private var hotbarResetTimer = TimerUtils.TickTimer(TimerUtils.TimeUnit.SECONDS)
@EventHandler
private val onUpdateWalkingPlayerListener = Listener(EventHook { event: OnUpdateWalkingPlayerEvent ->
if (packetList.isEmpty()) return@EventHook
packetList.values.first().apply(event) // Apply the packet from the module that has the highest priority
packetList.clear()
if (event.era != KamiEvent.Era.PERI) return@EventHook
prevServerSideRotation = serverSideRotation
if (packetList.isNotEmpty()) {
packetList.values.first().apply(event) // Apply the packet from the module that has the highest priority
packetList.clear()
}
})
/**
@ -32,6 +54,64 @@ object PlayerPacketManager : Manager() {
packetList[caller] = packet
}
@EventHandler
private val sendListener = Listener(EventHook { event: PacketEvent.Send ->
with(event.packet) {
if (this is CPacketPlayer) {
if (this.moving) serverSidePosition = Vec3d(this.x, this.y, this.z)
if (this.rotating) {
serverSideRotation = Vec2f(this.yaw, this.pitch)
Wrapper.player?.let { it.rotationYawHead = this.yaw }
}
}
if (this is CPacketHeldItemChange) {
if (spoofingHotbar && this.slotId != serverSideHotbar) {
if (hotbarResetTimer.tick(1L)) {
spoofingHotbar = false
serverSideHotbar = this.slotId
} else {
event.cancel()
}
} else {
serverSideHotbar = this.slotId
}
}
}
})
@EventHandler
private val preRenderListener = Listener(EventHook { event: RenderEntityEvent.Pre ->
if (event.entity == null || event.entity != Wrapper.player) return@EventHook
with(event.entity) {
clientSidePitch = Vec2f(prevRotationPitch, rotationPitch)
prevRotationPitch = prevServerSideRotation.y
rotationPitch = serverSideRotation.y
}
})
@EventHandler
private val postRenderListener = Listener(EventHook { event: RenderEntityEvent.Final ->
if (event.entity == null || event.entity != Wrapper.player) return@EventHook
with(event.entity) {
prevRotationPitch = clientSidePitch.x
rotationPitch = clientSidePitch.y
}
})
fun spoofHotbar(slot: Int) {
Wrapper.minecraft.connection?.let {
it.sendPacket(CPacketHeldItemChange(slot))
serverSideHotbar = slot
spoofingHotbar = true
}
}
fun resetHotbar() {
if (!spoofingHotbar) return
spoofingHotbar = false
Wrapper.minecraft.connection?.sendPacket(CPacketHeldItemChange(Wrapper.minecraft.playerController?.currentPlayerItem ?: 0))
}
/**
* Used for PlayerPacketManager. All constructor parameters are optional.
* They are null by default. null values would not be used for modifying

View File

@ -2,6 +2,7 @@ package me.zeroeightsix.kami.mixin.client;
import com.mojang.authlib.GameProfile;
import me.zeroeightsix.kami.KamiMod;
import me.zeroeightsix.kami.event.KamiEvent;
import me.zeroeightsix.kami.event.events.OnUpdateWalkingPlayerEvent;
import me.zeroeightsix.kami.event.events.PlayerMoveEvent;
import me.zeroeightsix.kami.gui.mc.KamiGuiBeacon;
@ -117,6 +118,8 @@ public abstract class MixinEntityPlayerSP extends EntityPlayer {
OnUpdateWalkingPlayerEvent event = new OnUpdateWalkingPlayerEvent(moving, rotating, sprinting, sneaking, onGround, pos, rotation);
KamiMod.EVENT_BUS.post(event);
event.setEra(KamiEvent.Era.PERI);
KamiMod.EVENT_BUS.post(event);
if (event.isCancelled()) {
ci.cancel();
@ -185,6 +188,8 @@ public abstract class MixinEntityPlayerSP extends EntityPlayer {
}
}
event.setEra(KamiEvent.Era.POST);
KamiMod.EVENT_BUS.post(event);
}
private boolean isMoving() {

View File

@ -2,6 +2,7 @@ package me.zeroeightsix.kami.mixin.client;
import me.zeroeightsix.kami.KamiMod;
import me.zeroeightsix.kami.event.events.GuiScreenEvent;
import me.zeroeightsix.kami.module.modules.combat.CrystalAura;
import me.zeroeightsix.kami.module.modules.misc.DiscordRPC;
import me.zeroeightsix.kami.util.ConfigUtils;
import me.zeroeightsix.kami.util.Wrapper;
@ -9,9 +10,15 @@ import net.minecraft.client.Minecraft;
import net.minecraft.client.audio.SoundHandler;
import net.minecraft.client.entity.EntityPlayerSP;
import net.minecraft.client.gui.*;
import net.minecraft.client.multiplayer.PlayerControllerMP;
import net.minecraft.client.multiplayer.WorldClient;
import net.minecraft.client.renderer.EntityRenderer;
import net.minecraft.client.settings.GameSettings;
import net.minecraft.client.settings.KeyBinding;
import net.minecraft.item.ItemStack;
import net.minecraft.util.EnumActionResult;
import net.minecraft.util.EnumHand;
import net.minecraft.util.math.RayTraceResult;
import org.lwjgl.input.Keyboard;
import org.lwjgl.input.Mouse;
import org.spongepowered.asm.mixin.Mixin;
@ -33,6 +40,24 @@ public class MixinMinecraft {
@Shadow public GuiIngame ingameGUI;
@Shadow public boolean skipRenderWorld;
@Shadow public SoundHandler soundHandler;
@Shadow public RayTraceResult objectMouseOver;
@Shadow public PlayerControllerMP playerController;
@Shadow public EntityRenderer entityRenderer;
@Inject(method = "rightClickMouse", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/entity/EntityPlayerSP;getHeldItem(Lnet/minecraft/util/EnumHand;)Lnet/minecraft/item/ItemStack;"), cancellable = true)
public void processRightClickBlock(CallbackInfo ci) {
if (CrystalAura.INSTANCE.isActive()) {
ci.cancel();
for (EnumHand enumhand : EnumHand.values()) {
ItemStack itemstack = this.player.getHeldItem(enumhand);
if (itemstack.isEmpty() && (this.objectMouseOver == null || this.objectMouseOver.typeOfHit == RayTraceResult.Type.MISS))
net.minecraftforge.common.ForgeHooks.onEmptyClick(this.player, enumhand);
if (!itemstack.isEmpty() && this.playerController.processRightClick(this.player, this.world, enumhand) == EnumActionResult.SUCCESS) {
this.entityRenderer.itemRenderer.resetEquippedProgress(enumhand);
}
}
}
}
@Inject(method = "displayGuiScreen", at = @At("HEAD"), cancellable = true)
public void displayGuiScreen(GuiScreen guiScreenIn, CallbackInfo info) {

View File

@ -5,7 +5,6 @@ import me.zeroeightsix.kami.event.events.ClientPlayerAttackEvent;
import me.zeroeightsix.kami.module.modules.player.TpsSync;
import me.zeroeightsix.kami.util.LagCompensator;
import net.minecraft.block.state.IBlockState;
import net.minecraft.client.entity.EntityPlayerSP;
import net.minecraft.client.multiplayer.PlayerControllerMP;
import net.minecraft.entity.Entity;
import net.minecraft.entity.player.EntityPlayer;
@ -28,12 +27,10 @@ public class MixinPlayerControllerMP {
@Inject(method = "attackEntity", at = @At("HEAD"), cancellable = true)
public void attackEntity(EntityPlayer playerIn, Entity targetEntity, CallbackInfo ci) {
if (targetEntity == null) return;
if (targetEntity instanceof EntityPlayerSP) {
ClientPlayerAttackEvent e = new ClientPlayerAttackEvent(targetEntity);
KamiMod.EVENT_BUS.post(e);
if (e.isCancelled()) {
ci.cancel();
}
ClientPlayerAttackEvent event = new ClientPlayerAttackEvent(targetEntity);
KamiMod.EVENT_BUS.post(event);
if (event.isCancelled()) {
ci.cancel();
}
}
}

View File

@ -47,10 +47,13 @@ public class MixinRenderManager {
@Inject(method = "renderEntity", at = @At("RETURN"))
public void renderEntityPostReturn(Entity entity, double x, double y, double z, float yaw, float partialTicks, boolean debug, CallbackInfo ci) {
RenderEntityEvent.Final eventFinal = new RenderEntityEvent.Final(entity, x, y, z, yaw, partialTicks, debug);
KamiMod.EVENT_BUS.post(eventFinal);
if (!this.renderOutlines || (this.debugBoundingBox && !entity.isInvisible() && !debug && !Minecraft.getMinecraft().isReducedDebug()))
return;
RenderEntityEvent.Post event2 = new RenderEntityEvent.Post(entity, x, y, z, yaw, partialTicks, debug);
KamiMod.EVENT_BUS.post(event2);
RenderEntityEvent.Post event = new RenderEntityEvent.Post(entity, x, y, z, yaw, partialTicks, debug);
KamiMod.EVENT_BUS.post(event);
}
}

View File

@ -1,49 +1,29 @@
package me.zeroeightsix.kami.module.modules.combat
import me.zeroeightsix.kami.manager.mangers.CombatManager
import me.zeroeightsix.kami.module.Module
import me.zeroeightsix.kami.setting.Settings
import me.zeroeightsix.kami.util.EntityUtils.EntityPriority
import me.zeroeightsix.kami.util.EntityUtils.getPrioritizedTarget
import me.zeroeightsix.kami.util.EntityUtils.getTargetList
import me.zeroeightsix.kami.util.math.RotationUtils.faceEntity
import net.minecraft.item.ItemBow
import me.zeroeightsix.kami.util.InventoryUtils
import me.zeroeightsix.kami.util.math.RotationUtils.faceEntityClosest
import net.minecraft.init.Items
@Module.Info(
name = "AimBot",
description = "Automatically aims at entities for you.",
category = Module.Category.COMBAT
category = Module.Category.COMBAT,
modulePriority = 20
)
object AimBot : Module() {
private val priority = register(Settings.e<EntityPriority>("Priority", EntityPriority.DISTANCE))
private val range = register(Settings.floatBuilder("Range").withValue(16.0f).withMinimum(4.0f).withMaximum(24.0f).build())
private val useBow = register(Settings.booleanBuilder("UseBow").withValue(true).build())
private val ignoreWalls = register(Settings.booleanBuilder("IgnoreWalls").withValue(true).build())
private val players = register(Settings.booleanBuilder("Players").withValue(true).build())
private val friends = register(Settings.booleanBuilder("Friends").withValue(false).withVisibility { players.value == true }.build())
private val sleeping = register(Settings.booleanBuilder("Sleeping").withValue(false).withVisibility { players.value == true }.build())
private val mobs = register(Settings.b("Mobs", false))
private val passive = register(Settings.booleanBuilder("PassiveMobs").withValue(false).withVisibility { mobs.value }.build())
private val neutral = register(Settings.booleanBuilder("NeutralMobs").withValue(false).withVisibility { mobs.value }.build())
private val hostile = register(Settings.booleanBuilder("HostileMobs").withValue(false).withVisibility { mobs.value }.build())
private val invisible = register(Settings.b("Invisible", false))
private val bowOnly = register(Settings.b("BowOnly", true))
private val autoSwap = register(Settings.booleanBuilder("AutoSwap").withValue(false).withVisibility { bowOnly.value })
override fun onUpdate() {
if (Aura.isDisabled) return
if (useBow.value) {
var bowSlot = 0
while (bowSlot in 0..8 && mc.player.inventory.getStackInSlot(bowSlot).getItem() !is ItemBow) {
bowSlot++
}
if (bowSlot != 9) {
mc.player.inventory.currentItem = bowSlot
mc.playerController.syncCurrentPlayItem()
}
if (bowOnly.value && mc.player.heldItemMainhand.getItem() != Items.BOW) {
if (autoSwap.value) InventoryUtils.swapSlotToItem(261)
return
}
CombatManager.target?.let {
faceEntityClosest(it)
}
val player = arrayOf(players.value, friends.value, sleeping.value)
val mob = arrayOf(mobs.value, passive.value, neutral.value, hostile.value)
val targetList = getTargetList(player, mob, ignoreWalls.value, invisible.value, range.value)
if (targetList.isEmpty()) return
faceEntity(getPrioritizedTarget(targetList, priority.value))
}
}

View File

@ -0,0 +1,65 @@
package me.zeroeightsix.kami.module.modules.combat
import me.zero.alpine.listener.EventHandler
import me.zero.alpine.listener.EventHook
import me.zero.alpine.listener.Listener
import me.zeroeightsix.kami.event.events.ClientPlayerAttackEvent
import me.zeroeightsix.kami.event.events.ConnectionEvent
import me.zeroeightsix.kami.module.Module
import me.zeroeightsix.kami.setting.Settings
import me.zeroeightsix.kami.util.graphics.font.TextComponent
import me.zeroeightsix.kami.util.math.Vec2d
import net.minecraft.entity.player.EntityPlayer
import kotlin.math.abs
@Module.Info(
name = "AntiBot",
description = "Avoid attacking fake players",
category = Module.Category.COMBAT,
alwaysListening = true
)
object AntiBot : Module() {
private val tabList = register(Settings.b("TabList", true))
private val ping = register(Settings.b("Ping", true))
private val hp = register(Settings.b("HP", true))
private val sleeping = register(Settings.b("Sleeping", false))
private val hoverOnTop = register(Settings.b("HoverOnTop", true))
private val ticksExists = register(Settings.integerBuilder("TicksExists").withValue(200).withRange(0, 500))
val botSet = HashSet<EntityPlayer>()
private val textComponent = TextComponent().apply { addLine("BOT") }
@EventHandler
private val disconnectListener = Listener(EventHook { event: ConnectionEvent.Disconnect ->
botSet.clear()
})
@EventHandler
private val listener = Listener(EventHook { event: ClientPlayerAttackEvent ->
if (isEnabled && botSet.contains(event.entity)) event.cancel()
})
override fun onUpdate() {
val cacheSet = HashSet<EntityPlayer>()
for (entity in mc.world.loadedEntityList) {
if (entity !is EntityPlayer) continue
if (entity == mc.player) continue
if (!isBot(entity)) continue
cacheSet.add(entity)
}
botSet.removeIf { !cacheSet.contains(it) }
botSet.addAll(cacheSet)
}
private fun isBot(entity: EntityPlayer) = tabList.value && mc.connection?.getPlayerInfo(entity.name) == null
|| ping.value && mc.connection?.getPlayerInfo(entity.name)?.responseTime ?: -1 <= 0
|| hp.value && entity.health !in 0f..20f
|| sleeping.value && entity.isPlayerSleeping && !entity.onGround
|| hoverOnTop.value && hoverCheck(entity)
|| entity.ticksExisted < ticksExists.value
private fun hoverCheck(entity: EntityPlayer): Boolean {
val distXZ = Vec2d(entity.posX, entity.posZ).subtract(mc.player.posX, mc.player.posZ).lengthSquared()
return distXZ < 16 && entity.posY - mc.player.posY > 2.0 && abs(entity.posY - entity.prevPosY) < 0.1
}
}

View File

@ -41,14 +41,12 @@ object AntiChainPop : Module() {
private fun itemMode() {
val old = totems
if (InventoryUtils.countItemAll(449) < old) {
Surround.autoDisable.value = true
Surround.enable()
}
totems = InventoryUtils.countItemAll(449)
}
private fun packetMode() {
Surround.autoDisable.value = true
Surround.enable()
}

View File

@ -3,10 +3,11 @@ package me.zeroeightsix.kami.module.modules.combat
import me.zero.alpine.listener.EventHandler
import me.zero.alpine.listener.EventHook
import me.zero.alpine.listener.Listener
import me.zeroeightsix.kami.event.events.ClientPlayerAttackEvent
import me.zeroeightsix.kami.event.events.PacketEvent
import me.zeroeightsix.kami.module.Module
import me.zeroeightsix.kami.util.Friends
import net.minecraft.client.entity.EntityOtherPlayerMP
import net.minecraft.entity.player.EntityPlayer
import net.minecraft.network.play.client.CPacketUseEntity
@Module.Info(
name = "AntiFriendHit",
@ -15,11 +16,9 @@ import net.minecraft.client.entity.EntityOtherPlayerMP
)
object AntiFriendHit : Module() {
@EventHandler
private val listener = Listener(EventHook { event: ClientPlayerAttackEvent ->
if (mc.objectMouseOver == null) return@EventHook
val e = mc.objectMouseOver.entityHit
if (e is EntityOtherPlayerMP && Friends.isFriend(e.getName())) {
event.cancel()
}
private val sendListener = Listener(EventHook { event: PacketEvent.Send ->
if (event.packet !is CPacketUseEntity || event.packet.action != CPacketUseEntity.Action.ATTACK) return@EventHook
val entity = mc.world?.let { event.packet.getEntityFromWorld(it) } ?: return@EventHook
if (entity is EntityPlayer && Friends.isFriend(entity.name)) event.cancel()
})
}

View File

@ -1,21 +1,15 @@
package me.zeroeightsix.kami.module.modules.combat
import me.zeroeightsix.kami.manager.mangers.CombatManager
import me.zeroeightsix.kami.manager.mangers.PlayerPacketManager
import me.zeroeightsix.kami.module.Module
import me.zeroeightsix.kami.module.modules.misc.AutoTool
import me.zeroeightsix.kami.setting.Setting
import me.zeroeightsix.kami.setting.Settings
import me.zeroeightsix.kami.util.BaritoneUtils.pause
import me.zeroeightsix.kami.util.BaritoneUtils.unpause
import me.zeroeightsix.kami.util.EntityUtils.EntityPriority
import me.zeroeightsix.kami.util.EntityUtils.getPrioritizedTarget
import me.zeroeightsix.kami.util.EntityUtils.getTargetList
import me.zeroeightsix.kami.util.LagCompensator
import me.zeroeightsix.kami.util.math.RotationUtils.faceEntity
import me.zeroeightsix.kami.util.math.RotationUtils.getRotationToEntity
import me.zeroeightsix.kami.util.combat.CombatUtils
import me.zeroeightsix.kami.util.math.RotationUtils
import me.zeroeightsix.kami.util.math.RotationUtils.faceEntityClosest
import me.zeroeightsix.kami.util.math.Vec2f
import net.minecraft.entity.Entity
import net.minecraft.init.Items
import net.minecraft.util.EnumHand
@Module.Info(
@ -26,99 +20,59 @@ import net.minecraft.util.EnumHand
)
object Aura : Module() {
private val delayMode = register(Settings.e<WaitMode>("Mode", WaitMode.DELAY))
private val priority = register(Settings.e<EntityPriority>("Priority", EntityPriority.DISTANCE))
private val multi = register(Settings.b("Multi", false))
private val spoofRotation = register(Settings.booleanBuilder("SpoofRotation").withValue(true).withVisibility { !multi.value }.build())
private val lockView = register(Settings.booleanBuilder("LockView").withValue(false).withVisibility { !multi.value }.build())
private val waitTick = register(Settings.floatBuilder("SpamDelay").withMinimum(0.1f).withValue(2.0f).withMaximum(40.0f).withVisibility { delayMode.value == WaitMode.SPAM }.build())
private val eat = register(Settings.b("WhileEating", true))
private val players = register(Settings.b("Players", true))
private val friends = register(Settings.booleanBuilder("Friends").withValue(false).withVisibility { players.value }.build())
private val sleeping = register(Settings.booleanBuilder("Sleeping").withValue(false).withVisibility { players.value }.build())
private val mobs = register(Settings.b("Mobs", false))
private val passive = register(Settings.booleanBuilder("PassiveMobs").withValue(false).withVisibility { mobs.value }.build())
private val neutral = register(Settings.booleanBuilder("NeutralMobs").withValue(false).withVisibility { mobs.value }.build())
private val hostile = register(Settings.booleanBuilder("HostileMobs").withValue(false).withVisibility { mobs.value }.build())
private val invisible = register(Settings.b("Invisible", false))
private val ignoreWalls = register(Settings.b("IgnoreWalls", true))
private val minExistTime = register(Settings.integerBuilder("MinExistTime(s)").withValue(5).withRange(0, 20).build())
private val range = register(Settings.f("Range", 5.5f))
private val sync = register(Settings.b("TPSSync", false))
private val pauseBaritone: Setting<Boolean> = register(Settings.b("PauseBaritone", true))
private val timeAfterAttack = register(Settings.integerBuilder("ResumeDelay").withRange(1, 10).withValue(3).withVisibility { pauseBaritone.value }.build())
private val lockView = register(Settings.booleanBuilder("LockView").withValue(false).withVisibility { !multi.value })
private val spoofRotation = register(Settings.booleanBuilder("SpoofRotation").withValue(true).withVisibility { !multi.value && !lockView.value })
private val waitTick = register(Settings.floatBuilder("SpamDelay").withMinimum(0.1f).withValue(2.0f).withMaximum(40.0f).withVisibility { delayMode.value == WaitMode.SPAM })
val range = register(Settings.floatBuilder("Range").withValue(5f).withRange(0f, 10f))
private val tpsSync = register(Settings.b("TPSSync", false))
private val autoTool = register(Settings.b("AutoWeapon", true))
private val prefer = register(Settings.e<HitMode>("Prefer", HitMode.SWORD))
private val prefer = register(Settings.enumBuilder(CombatUtils.PreferWeapon::class.java).withName("Prefer").withValue(CombatUtils.PreferWeapon.SWORD).withVisibility { autoTool.value })
private val disableOnDeath = register(Settings.b("DisableOnDeath", false))
private var startTime: Long = 0
private var inactiveTicks = 0
private var tickCount = 0
var isAttacking = false // returned to AutoEat
private enum class WaitMode {
DELAY, SPAM
}
enum class HitMode {
SWORD, AXE, NONE
override fun isActive(): Boolean {
return inactiveTicks <= 20 && isEnabled
}
override fun onUpdate() {
inactiveTicks++
if (mc.player.isDead) {
if (mc.player.isDead && disableOnDeath.value) disable()
return
}
if (!CombatManager.isOnTopPriority(this) || CombatSetting.pause) return
val targetList = CombatManager.targetList
val target = CombatManager.target
val player = arrayOf(players.value, friends.value, sleeping.value)
val mob = arrayOf(mobs.value, passive.value, neutral.value, hostile.value)
val cacheList = getTargetList(player, mob, ignoreWalls.value, invisible.value, range.value)
val targetList = ArrayList<Entity>()
for (target in cacheList) {
if (target.ticksExisted < minExistTime.value * 20) continue
targetList.add(target)
}
if (targetList.isNotEmpty()) {
/* Pausing baritone and other stuff */
if (!isAttacking) {
isAttacking = true
if (pauseBaritone.value) {
startTime = 0L
pause()
if (multi.value && targetList.isNotEmpty()) {
inactiveTicks = 0
if (canAttack()) {
for (entity in targetList) {
if (mc.player.getDistance(entity) > range.value) continue
attack(entity)
}
}
if (autoTool.value) AutoTool.equipBestWeapon(prefer.value)
if (multi.value) {
if (canAttack()) for (target in targetList) {
attack(target)
}
} else {
val target = getPrioritizedTarget(targetList.toTypedArray(), priority.value)
if (spoofRotation.value) {
val rotation = getRotationToEntity(target)
val yaw = rotation.x.toFloat()
val pitch = rotation.y.toFloat()
val packet = PlayerPacketManager.PlayerPacket(rotating = true, rotation = Vec2f(yaw, pitch))
PlayerPacketManager.addPacket(this, packet)
}
if (lockView.value) faceEntity(target)
if (canAttack()) attack(target)
} else if (target != null && mc.player.getDistance(target) < range.value) {
inactiveTicks = 0
if (lockView.value) {
faceEntityClosest(target)
} else if (spoofRotation.value) {
val rotation = Vec2f(RotationUtils.getRotationToEntityClosest(target))
PlayerPacketManager.addPacket(this, PlayerPacketManager.PlayerPacket(rotating = true, rotation = rotation))
}
} else if (isAttacking && canResume()) {
isAttacking = false
unpause()
if (canAttack()) attack(target)
}
}
override fun onDisable() {
unpause()
}
private fun canAttack(): Boolean {
if (!eat.value) {
val shield = mc.player.heldItemOffhand.getItem() == Items.SHIELD && mc.player.activeHand == EnumHand.OFF_HAND
if (mc.player.isHandActive && !shield) return false
}
val adjustTicks = if (!sync.value) 0f else (LagCompensator.adjustTicks)
val adjustTicks = if (!tpsSync.value) 0f else LagCompensator.adjustTicks
return if (delayMode.value == WaitMode.DELAY) {
(mc.player.getCooledAttackStrength(adjustTicks) >= 1f)
} else {
@ -133,15 +87,8 @@ object Aura : Module() {
}
private fun attack(e: Entity) {
if (autoTool.value) CombatUtils.equipBestWeapon(prefer.value as CombatUtils.PreferWeapon)
mc.playerController.attackEntity(mc.player, e)
mc.player.swingArm(EnumHand.MAIN_HAND)
}
private fun canResume(): Boolean {
if (startTime == 0L) startTime = System.currentTimeMillis()
return if (startTime + timeAfterAttack.value * 1000 <= System.currentTimeMillis()) { // 1 timeout = 1 second = 1000 ms
startTime = System.currentTimeMillis()
true
} else false
}
}

View File

@ -1,258 +0,0 @@
package me.zeroeightsix.kami.module.modules.combat
import com.mojang.realmsclient.gui.ChatFormatting
import me.zeroeightsix.kami.module.Module
import me.zeroeightsix.kami.module.modules.player.NoBreakAnimation
import me.zeroeightsix.kami.setting.Settings
import me.zeroeightsix.kami.util.BlockUtils
import me.zeroeightsix.kami.util.text.MessageSendHelper
import net.minecraft.block.BlockAir
import net.minecraft.block.BlockLiquid
import net.minecraft.block.BlockObsidian
import net.minecraft.entity.item.EntityItem
import net.minecraft.entity.item.EntityXPOrb
import net.minecraft.item.ItemBlock
import net.minecraft.item.ItemStack
import net.minecraft.network.play.client.CPacketEntityAction
import net.minecraft.util.EnumFacing
import net.minecraft.util.EnumHand
import net.minecraft.util.math.AxisAlignedBB
import net.minecraft.util.math.BlockPos
import net.minecraft.util.math.Vec3d
@Module.Info(
name = "AutoFeetPlace",
category = Module.Category.COMBAT,
description = "Continually places obsidian around your feet"
)
object AutoFeetPlace : Module() {
private val mode = register(Settings.e<Mode>("Mode", Mode.FULL))
private val triggerable = register(Settings.b("Triggerable", true))
private val disableNone = register(Settings.b("DisableNoObby", true))
private val timeoutTicks = register(Settings.integerBuilder("TimeoutTicks").withMinimum(1).withValue(40).withMaximum(100).withVisibility { b: Int? -> triggerable.value }.build())
private val blocksPerTick = register(Settings.integerBuilder("BlocksPerTick").withMinimum(1).withValue(4).withMaximum(9).build())
private val tickDelay = register(Settings.integerBuilder("TickDelay").withMinimum(0).withValue(0).withMaximum(10).build())
private val rotate = register(Settings.b("Rotate", true))
private val infoMessage = register(Settings.b("InfoMessage", false))
private var offsetStep = 0
private var delayStep = 0
private var playerHotbarSlot = -1
private var lastHotbarSlot = -1
private var isSneaking = false
private var totalTicksRunning = 0
private var firstRun = false
private var missingObiDisable = false
override fun onEnable() {
if (mc.player == null) {
disable()
return
}
firstRun = true
// save initial player hand
playerHotbarSlot = mc.player.inventory.currentItem
lastHotbarSlot = -1
}
override fun onDisable() {
if (mc.player == null) return
// load initial player hand
if (lastHotbarSlot != playerHotbarSlot && playerHotbarSlot != -1) {
mc.player.inventory.currentItem = playerHotbarSlot
}
if (isSneaking) {
mc.player.connection.sendPacket(CPacketEntityAction(mc.player, CPacketEntityAction.Action.STOP_SNEAKING))
isSneaking = false
}
playerHotbarSlot = -1
lastHotbarSlot = -1
missingObiDisable = false
}
override fun onUpdate() {
if (triggerable.value && totalTicksRunning >= timeoutTicks.value) {
totalTicksRunning = 0
disable()
return
}
if (!firstRun) {
delayStep = if (delayStep < tickDelay.value) {
delayStep++
return
} else {
0
}
}
if (firstRun) {
firstRun = false
if (findObiInHotbar() == -1) {
missingObiDisable = true
}
}
var offsetPattern = arrayOfNulls<Vec3d>(0)
var maxSteps = 0
if (mode.value == Mode.FULL) {
offsetPattern = Offsets.FULL
maxSteps = Offsets.FULL.size
}
if (mode.value == Mode.SURROUND) {
offsetPattern = Offsets.SURROUND
maxSteps = Offsets.SURROUND.size
}
var blocksPlaced = 0
while (blocksPlaced < blocksPerTick.value) {
if (offsetStep >= maxSteps) {
offsetStep = 0
break
}
val offsetPos = BlockPos(offsetPattern[offsetStep])
val targetPos = BlockPos(mc.player.positionVector).add(offsetPos.x, offsetPos.y, offsetPos.z)
if (placeBlock(targetPos)) {
blocksPlaced++
}
offsetStep++
}
if (blocksPlaced > 0) {
if (lastHotbarSlot != playerHotbarSlot && playerHotbarSlot != -1) {
mc.player.inventory.currentItem = playerHotbarSlot
lastHotbarSlot = playerHotbarSlot
}
if (isSneaking) {
mc.player.connection.sendPacket(CPacketEntityAction(mc.player, CPacketEntityAction.Action.STOP_SNEAKING))
isSneaking = false
}
}
totalTicksRunning++
if (missingObiDisable && disableNone.value) {
missingObiDisable = false
if (infoMessage.value) {
MessageSendHelper.sendChatMessage("$chatName " + ChatFormatting.RED + "Disabled" + ChatFormatting.RESET + ", Obsidian missing!")
}
disable()
}
}
private fun placeBlock(pos: BlockPos): Boolean {
// check if block is already placed
val block = mc.world.getBlockState(pos).block
if (block !is BlockAir && block !is BlockLiquid) {
return false
}
// check if entity blocks placing
for (entity in mc.world.getEntitiesWithinAABBExcludingEntity(null, AxisAlignedBB(pos))) {
if (entity !is EntityItem && entity !is EntityXPOrb) {
return false
}
}
val side = getPlaceableSide(pos) ?: return false
// check if we have a block adjacent to blockpos to click at
val neighbour = pos.offset(side)
val opposite = side.opposite
// check if neighbor can be right clicked
if (!BlockUtils.canBeClicked(neighbour)) {
return false
}
val hitVec = Vec3d(neighbour).add(0.5, 0.5, 0.5).add(Vec3d(opposite.directionVec).scale(0.5))
val neighbourBlock = mc.world.getBlockState(neighbour).block
val obiSlot = findObiInHotbar()
if (obiSlot == -1) {
missingObiDisable = true
return false
}
if (lastHotbarSlot != obiSlot) {
mc.player.inventory.currentItem = obiSlot
lastHotbarSlot = obiSlot
}
if (!isSneaking && BlockUtils.blackList.contains(neighbourBlock) || BlockUtils.shulkerList.contains(neighbourBlock)) {
mc.player.connection.sendPacket(CPacketEntityAction(mc.player, CPacketEntityAction.Action.START_SNEAKING))
isSneaking = true
}
if (rotate.value) {
BlockUtils.faceVectorPacketInstant(hitVec)
}
mc.playerController.processRightClickBlock(mc.player, mc.world, neighbour, opposite, hitVec, EnumHand.MAIN_HAND)
mc.player.swingArm(EnumHand.MAIN_HAND)
mc.rightClickDelayTimer = 4
if (NoBreakAnimation.isEnabled) NoBreakAnimation.resetMining()
return true
}
private fun findObiInHotbar(): Int {
// search blocks in hotbar
var slot = -1
for (i in 0..8) {
// filter out non-block items
val stack = mc.player.inventory.getStackInSlot(i)
if (stack == ItemStack.EMPTY || stack.getItem() !is ItemBlock) {
continue
}
val block = (stack.getItem() as ItemBlock).block
if (block is BlockObsidian) {
slot = i
break
}
}
return slot
}
private enum class Mode {
SURROUND, FULL
}
private object Offsets {
val SURROUND = arrayOf<Vec3d?>(
Vec3d(1.0, 0.0, 0.0),
Vec3d(0.0, 0.0, 1.0),
Vec3d(-1.0, 0.0, 0.0),
Vec3d(0.0, 0.0, -1.0),
Vec3d(1.0, -1.0, 0.0),
Vec3d(0.0, -1.0, 1.0),
Vec3d(-1.0, -1.0, 0.0),
Vec3d(0.0, -1.0, -1.0)
)
val FULL = arrayOf<Vec3d?>(
Vec3d(1.0, 0.0, 0.0),
Vec3d(0.0, 0.0, 1.0),
Vec3d(-1.0, 0.0, 0.0),
Vec3d(0.0, 0.0, -1.0),
Vec3d(1.0, -1.0, 0.0),
Vec3d(0.0, -1.0, 1.0),
Vec3d(-1.0, -1.0, 0.0),
Vec3d(0.0, -1.0, -1.0),
Vec3d(0.0, -1.0, 0.0)
)
}
private fun getPlaceableSide(pos: BlockPos): EnumFacing? {
for (side in EnumFacing.values()) {
val neighbour = pos.offset(side)
if (!mc.world.getBlockState(neighbour).block.canCollideCheck(mc.world.getBlockState(neighbour), false)) {
continue
}
val blockState = mc.world.getBlockState(neighbour)
if (!blockState.material.isReplaceable) {
return side
}
}
return null
}
}

View File

@ -7,6 +7,7 @@ import me.zeroeightsix.kami.setting.Setting
import me.zeroeightsix.kami.setting.Settings
import me.zeroeightsix.kami.util.Friends
import me.zeroeightsix.kami.util.InventoryUtils
import me.zeroeightsix.kami.util.combat.CrystalUtils
import me.zeroeightsix.kami.util.math.MathUtils
import net.minecraft.client.audio.PositionedSoundRecord
import net.minecraft.client.gui.GuiMainMenu
@ -57,7 +58,7 @@ object AutoLog : Module() {
for (entity in mc.world.loadedEntityList) {
if (entity !is EntityEnderCrystal) continue
if (mc.player.getDistance(entity) > 8f) continue
if (mc.player.health - CrystalAura.calculateDamage(entity, mc.player) > health.value) continue
if (mc.player.health - CrystalUtils.calcDamage(entity, mc.player) > health.value) continue
log(END_CRYSTAL)
return
}

View File

@ -0,0 +1,130 @@
package me.zeroeightsix.kami.module.modules.combat
import me.zero.alpine.listener.EventHandler
import me.zero.alpine.listener.EventHook
import me.zero.alpine.listener.Listener
import me.zeroeightsix.kami.event.events.PacketEvent
import me.zeroeightsix.kami.manager.mangers.CombatManager
import me.zeroeightsix.kami.module.Module
import me.zeroeightsix.kami.setting.Settings
import me.zeroeightsix.kami.util.InventoryUtils
import me.zeroeightsix.kami.util.TimerUtils
import me.zeroeightsix.kami.util.combat.CombatUtils
import me.zeroeightsix.kami.util.combat.CrystalUtils
import net.minecraft.client.gui.inventory.GuiContainer
import net.minecraft.entity.item.EntityEnderCrystal
import net.minecraft.entity.monster.EntityMob
import net.minecraft.entity.player.EntityPlayer
import net.minecraft.item.Item
import net.minecraft.item.ItemAxe
import net.minecraft.item.ItemSword
import net.minecraft.network.play.server.SPacketConfirmTransaction
import kotlin.math.max
@Module.Info(
name = "AutoOffhand",
description = "Manages item in your offhand",
category = Module.Category.COMBAT
)
object AutoOffhand : Module() {
private val type = register(Settings.enumBuilder(Type::class.java, "Type").withValue(Type.TOTEM))
// Totem
private val hpThreshold = register(Settings.floatBuilder("HpThreshold").withValue(5f).withRange(1f, 20f).withVisibility { type.value == Type.TOTEM })
private val checkDamage = register(Settings.booleanBuilder("CheckDamage").withValue(true).withVisibility { type.value == Type.TOTEM })
private val mob = register(Settings.booleanBuilder("Mob").withValue(true).withVisibility { type.value == Type.TOTEM && checkDamage.value })
private val player = register(Settings.booleanBuilder("Player").withValue(true).withVisibility { type.value == Type.TOTEM && checkDamage.value })
private val crystal = register(Settings.booleanBuilder("Crystal").withValue(true).withVisibility { type.value == Type.TOTEM && checkDamage.value })
// Gapple
private val offhandGapple = register(Settings.booleanBuilder("OffhandGapple").withValue(false).withVisibility { type.value == Type.GAPPLE })
private val checkAura = register(Settings.booleanBuilder("CheckAura").withValue(true).withVisibility { type.value == Type.GAPPLE && offhandGapple.value })
private val checkWeapon = register(Settings.booleanBuilder("CheckWeapon").withValue(false).withVisibility { type.value == Type.GAPPLE && offhandGapple.value })
private val checkCAGapple = register(Settings.booleanBuilder("CheckCrystalAura").withValue(true).withVisibility { type.value == Type.GAPPLE && offhandGapple.value && !offhandCrystal.value })
// Crystal
private val offhandCrystal = register(Settings.booleanBuilder("OffhandCrystal").withValue(false).withVisibility { type.value == Type.CRYSTAL })
private val checkCACrystal = register(Settings.booleanBuilder("CheckCrystalAura").withValue(false).withVisibility { type.value == Type.CRYSTAL && offhandCrystal.value })
private enum class Type(val itemId: Int) {
TOTEM(449),
GAPPLE(322),
CRYSTAL(426)
}
private val transactionLog = HashMap<Short, Boolean>()
private val movingTimer = TimerUtils.TickTimer()
private var maxDamage = 0f
@EventHandler
private val receiveListener = Listener(EventHook { event: PacketEvent.Receive ->
if (mc.player == null || event.packet !is SPacketConfirmTransaction || event.packet.windowId != 0 || !transactionLog.containsKey(event.packet.actionNumber)) return@EventHook
transactionLog[event.packet.actionNumber] = event.packet.wasAccepted()
if (!transactionLog.containsValue(false)) movingTimer.reset(-200L) // If all the click packets were accepted then we reset the timer for next moving
})
override fun onRender() {
if (mc.player == null || mc.player.isDead || !movingTimer.tick(200L, false)) return // Delay 4 ticks by default
if (!mc.player.inventory.getItemStack().isEmpty()) { // If player is holding an in inventory
if (mc.currentScreen is GuiContainer) {// If inventory is open (playing moving item)
movingTimer.reset(-150) // delay for 1 tick
} else { // If inventory is not open (ex. inventory desync)
InventoryUtils.removeHoldingItem()
}
} else { // If player is not holding an item in inventory
val type = when {
checkTotem() -> Type.TOTEM
checkCrystal() -> Type.CRYSTAL
checkGapple() -> Type.GAPPLE
mc.player.heldItemOffhand.isEmpty() -> Type.TOTEM
else -> null
}
if (type != null && !checkOffhandItem(type)) getItemSlot(type)?.let { slot ->
transactionLog.clear()
transactionLog.putAll(InventoryUtils.moveToSlot(0, slot, 45).associate { it to false })
transactionLog[InventoryUtils.quickMoveSlot(0, slot)] = false
mc.playerController.updateController()
movingTimer.reset()
} ?: movingTimer.reset(-150) // Delay 1 tick if can't find an item
}
}
override fun onUpdate() {
maxDamage = 0f
if (!checkDamage.value) return
for (entity in mc.world.loadedEntityList) {
if (entity.name == mc.player.name) continue
if (entity !is EntityMob && entity !is EntityPlayer && entity !is EntityEnderCrystal) continue
if (mc.player.getDistance(entity) > 10f) continue
if (mob.value && entity is EntityMob) {
maxDamage = max(CombatUtils.calcDamageFromMob(entity), maxDamage)
}
if (player.value && entity is EntityPlayer) {
maxDamage = max(CombatUtils.calcDamageFromPlayer(entity), maxDamage)
}
if (crystal.value && entity is EntityEnderCrystal) {
maxDamage = max(CrystalUtils.calcDamage(entity, mc.player), maxDamage)
}
}
}
private fun checkTotem() = mc.player.health < hpThreshold.value
|| (checkDamage.value && mc.player.absorptionAmount + mc.player.health - maxDamage < hpThreshold.value)
private fun checkGapple(): Boolean {
val item = mc.player.heldItemMainhand.getItem()
return offhandGapple.value
&& (checkAura.value && CombatManager.isActiveAndTopPriority(Aura)
|| checkWeapon.value && (item is ItemSword || item is ItemAxe)
|| (checkCAGapple.value && !offhandCrystal.value) && CombatManager.isActiveAndTopPriority(CrystalAura))
}
private fun checkCrystal() = offhandCrystal.value && checkCACrystal.value && CombatManager.isActiveAndTopPriority(CrystalAura)
private fun checkOffhandItem(type: Type) = Item.getIdFromItem(mc.player.heldItemOffhand.getItem()) == type.itemId
private fun getItemSlot(type: Type): Int? = InventoryUtils.getSlotsFullInv(itemId = type.itemId)?.get(0)
?: if (type == Type.CRYSTAL) InventoryUtils.getSlotsFullInv(itemId = 449)?.get(0) else getItemSlot(getNextType(type))
private fun getNextType(type: Type) = with(Type.values()) { this[(type.ordinal + 1) % this.size] }
}

View File

@ -1,112 +0,0 @@
package me.zeroeightsix.kami.module.modules.combat;
import me.zeroeightsix.kami.module.Module;
import me.zeroeightsix.kami.setting.Setting;
import me.zeroeightsix.kami.setting.Settings;
import me.zeroeightsix.kami.util.InventoryUtils;
import net.minecraft.client.gui.inventory.GuiContainer;
import net.minecraft.init.Items;
import net.minecraft.inventory.ClickType;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
@Module.Info(
name = "AutoTotem",
category = Module.Category.COMBAT,
description = "Refills your offhand with totems or other items"
)
public class AutoTotem extends Module {
private final Setting<Mode> modeSetting = register(Settings.e("Mode", Mode.REPLACE_OFFHAND));
private final Setting<Boolean> smartOffhand = register(Settings.booleanBuilder("CustomItem").withValue(false).withVisibility(v -> modeSetting.getValue().equals(Mode.REPLACE_OFFHAND)).build());
private final Setting<Double> healthSetting = register(Settings.doubleBuilder("CustomItemHealth").withValue(14.0).withVisibility(v -> smartOffhand.getValue() && modeSetting.getValue().equals(Mode.REPLACE_OFFHAND)).build());
private final Setting<CustomItem> smartItemSetting = register(Settings.enumBuilder(CustomItem.class).withName("Item").withValue(CustomItem.GAPPLE).withVisibility(v -> smartOffhand.getValue() && modeSetting.getValue().equals(Mode.REPLACE_OFFHAND)).build());
private enum Mode {NEITHER, REPLACE_OFFHAND, INVENTORY;}
private enum CustomItem {CRYSTAL, GAPPLE}
private int totems;
private boolean moving = false;
private boolean returnI = false;
public static AutoTotem INSTANCE;
public AutoTotem() {
super();
INSTANCE = this;
}
@Override
public void onUpdate() {
if (!modeSetting.getValue().equals(Mode.INVENTORY) && mc.currentScreen instanceof GuiContainer)
return; // this stops autototem from running if you're in a chest or something
if (returnI) {
int t = -1;
for (int i = 0; i < 45; i++)
if (mc.player.inventory.getStackInSlot(i).isEmpty) {
t = i;
break;
}
if (t == -1) return;
mc.playerController.windowClick(0, t < 9 ? t + 36 : t, 0, ClickType.PICKUP, mc.player);
returnI = false;
}
totems = mc.player.inventory.mainInventory.stream().filter(itemStack -> itemStack.getItem() == settingToItem()).mapToInt(ItemStack::getCount).sum();
if (mc.player.getHeldItemOffhand().getItem() == settingToItem()) totems++;
else {
if (!modeSetting.getValue().equals(Mode.REPLACE_OFFHAND) && !mc.player.getHeldItemOffhand().isEmpty)
return;
if (moving) {
mc.playerController.windowClick(0, 45, 0, ClickType.PICKUP, mc.player);
moving = false;
if (!mc.player.inventory.itemStack.isEmpty()) returnI = true;
return;
}
if (mc.player.inventory.itemStack.isEmpty()) {
if (totems == 0) return;
int t = -1;
for (int i = 0; i < 45; i++)
if (mc.player.inventory.getStackInSlot(i).getItem() == settingToItem()) {
t = i;
break;
}
if (t == -1) return; // Should never happen!
mc.playerController.windowClick(0, t < 9 ? t + 36 : t, 0, ClickType.PICKUP, mc.player);
moving = true;
} else if (modeSetting.getValue().equals(Mode.REPLACE_OFFHAND)) {
int t = -1;
for (int i = 0; i < 45; i++)
if (mc.player.inventory.getStackInSlot(i).isEmpty) {
t = i;
break;
}
if (t == -1) return;
mc.playerController.windowClick(0, t < 9 ? t + 36 : t, 0, ClickType.PICKUP, mc.player);
}
}
}
private Item settingToItem() {
if (!smartOffhand.getValue() || passHealthCheck()) return Items.TOTEM_OF_UNDYING;
switch (smartItemSetting.getValue()) {
case GAPPLE:
return Items.GOLDEN_APPLE;
case CRYSTAL:
return Items.END_CRYSTAL;
}
return null;
}
private boolean passHealthCheck() {
if (modeSetting.getValue().equals(Mode.REPLACE_OFFHAND)) {
return mc.player.getHealth() + mc.player.getAbsorptionAmount() <= healthSetting.getValue();
}
return true;
}
@Override
public String getHudInfo() {
return "" + InventoryUtils.countItemAll(Item.getIdFromItem(settingToItem()));
}
}

View File

@ -1,382 +0,0 @@
package me.zeroeightsix.kami.module.modules.combat;
import com.mojang.realmsclient.gui.ChatFormatting;
import me.zeroeightsix.kami.module.Module;
import me.zeroeightsix.kami.module.modules.player.NoBreakAnimation;
import me.zeroeightsix.kami.setting.Setting;
import me.zeroeightsix.kami.setting.Settings;
import me.zeroeightsix.kami.util.BlockUtils;
import me.zeroeightsix.kami.util.EntityUtils;
import me.zeroeightsix.kami.util.Friends;
import net.minecraft.block.Block;
import net.minecraft.block.BlockAir;
import net.minecraft.block.BlockLiquid;
import net.minecraft.block.BlockObsidian;
import net.minecraft.block.state.IBlockState;
import net.minecraft.entity.Entity;
import net.minecraft.entity.item.EntityItem;
import net.minecraft.entity.item.EntityXPOrb;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.ItemBlock;
import net.minecraft.item.ItemStack;
import net.minecraft.network.play.client.CPacketEntityAction;
import net.minecraft.network.play.client.CPacketPlayerDigging;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.EnumHand;
import net.minecraft.util.math.AxisAlignedBB;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Vec3d;
import net.minecraft.world.GameType;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import static me.zeroeightsix.kami.util.BlockUtils.canBeClicked;
import static me.zeroeightsix.kami.util.BlockUtils.faceVectorPacketInstant;
import static me.zeroeightsix.kami.util.text.MessageSendHelper.sendChatMessage;
@Module.Info(
name = "AutoTrap",
category = Module.Category.COMBAT,
description = "Traps your enemies in obsidian"
)
public class AutoTrap extends Module {
private final Setting<Double> range = register(Settings.doubleBuilder("Range").withMinimum(3.5).withValue(5.5).withMaximum(10.0).build());
private final Setting<Integer> blocksPerTick = register(Settings.integerBuilder("BlocksPerTick").withMinimum(1).withValue(2).withMaximum(23).build());
private final Setting<Integer> tickDelay = register(Settings.integerBuilder("TickDelay").withMinimum(0).withValue(2).withMaximum(10).build());
private final Setting<Cage> cage = register(Settings.e("Cage", Cage.TRAP));
private final Setting<Boolean> rotate = register(Settings.b("Rotate", false));
private final Setting<Boolean> noGlitchBlocks = register(Settings.b("NoGlitchBlocks", true));
private final Setting<Boolean> selfTrap = register(Settings.b("SelfTrap", false));
private final Setting<Boolean> infoMessage = register(Settings.b("Debug", false));
private EntityPlayer closestTarget;
private String lastTargetName;
private int playerHotbarSlot = -1;
private int lastHotbarSlot = -1;
private boolean isSneaking = false;
private int delayStep = 0;
private int offsetStep = 0;
private boolean firstRun;
private boolean missingObiDisable = false;
public static AutoTrap INSTANCE;
public AutoTrap() {
super();
INSTANCE = this;
}
private static EnumFacing getPlaceableSide(BlockPos pos) {
for (EnumFacing side : EnumFacing.values()) {
BlockPos neighbour = pos.offset(side);
if (!mc.world.getBlockState(neighbour).getBlock().canCollideCheck(mc.world.getBlockState(neighbour), false)) {
continue;
}
IBlockState blockState = mc.world.getBlockState(neighbour);
if (!blockState.getMaterial().isReplaceable()) {
return side;
}
}
return null;
}
@Override
protected void onEnable() {
if (mc.player == null || mc.player.getHealth() <= 0) {
disable();
return;
}
firstRun = true;
// save initial player hand
playerHotbarSlot = mc.player.inventory.currentItem;
lastHotbarSlot = -1;
}
@Override
protected void onDisable() {
if (mc.player == null || mc.player.getHealth() <= 0) return;
if (lastHotbarSlot != playerHotbarSlot && playerHotbarSlot != -1) {
mc.player.inventory.currentItem = playerHotbarSlot;
}
if (isSneaking) {
mc.player.connection.sendPacket(new CPacketEntityAction(mc.player, CPacketEntityAction.Action.STOP_SNEAKING));
isSneaking = false;
}
playerHotbarSlot = -1;
lastHotbarSlot = -1;
missingObiDisable = false;
}
@Override
public void onUpdate() {
if (mc.player.getHealth() <= 0) return;
if (firstRun) {
if (findObiInHotbar() == -1) {
if (infoMessage.getValue()) {
sendChatMessage(getChatName() + " " + ChatFormatting.RED + "Disabled" + ChatFormatting.RESET + ", Obsidian missing!");
}
disable();
return;
}
} else {
if (delayStep < tickDelay.getValue()) {
delayStep++;
return;
} else {
delayStep = 0;
}
}
findClosestTarget();
if (closestTarget == null) {
return;
}
if (firstRun) {
firstRun = false;
lastTargetName = closestTarget.getName();
} else if (!lastTargetName.equals(closestTarget.getName())) {
offsetStep = 0;
lastTargetName = closestTarget.getName();
}
List<Vec3d> placeTargets = new ArrayList<>();
if (cage.getValue().equals(Cage.TRAP)) Collections.addAll(placeTargets, Offsets.TRAP);
if (cage.getValue().equals(Cage.CRYSTALEXA)) Collections.addAll(placeTargets, Offsets.CRYSTALEXA);
if (cage.getValue().equals(Cage.CRYSTALFULL)) Collections.addAll(placeTargets, Offsets.CRYSTALFULL);
int blocksPlaced = 0;
while (blocksPlaced < blocksPerTick.getValue()) {
if (offsetStep >= placeTargets.size()) {
offsetStep = 0;
break;
}
BlockPos offsetPos = new BlockPos(placeTargets.get(offsetStep));
BlockPos targetPos = new BlockPos(closestTarget.getPositionVector()).down().add(offsetPos.x, offsetPos.y, offsetPos.z);
if (placeBlockInRange(targetPos, range.getValue())) {
blocksPlaced++;
}
offsetStep++;
}
if (blocksPlaced > 0) {
if (lastHotbarSlot != playerHotbarSlot && playerHotbarSlot != -1) {
mc.player.inventory.currentItem = playerHotbarSlot;
lastHotbarSlot = playerHotbarSlot;
}
if (isSneaking) {
mc.player.connection.sendPacket(new CPacketEntityAction(mc.player, CPacketEntityAction.Action.STOP_SNEAKING));
isSneaking = false;
}
}
if (missingObiDisable) {
missingObiDisable = false;
if (infoMessage.getValue()) {
sendChatMessage(getChatName() + " " + ChatFormatting.RED + "Disabled" + ChatFormatting.RESET + ", Obsidian missing!");
}
disable();
}
}
private boolean placeBlockInRange(BlockPos pos, double range) {
// check if block is already placed
Block block = mc.world.getBlockState(pos).getBlock();
if (!(block instanceof BlockAir) && !(block instanceof BlockLiquid)) {
return false;
}
// check if entity blocks placing
for (Entity entity : mc.world.getEntitiesWithinAABBExcludingEntity(null, new AxisAlignedBB(pos))) {
if (!(entity instanceof EntityItem) && !(entity instanceof EntityXPOrb)) {
return false;
}
}
EnumFacing side = getPlaceableSide(pos);
// check if we have a block adjacent to blockpos to click at
if (side == null) {
return false;
}
BlockPos neighbour = pos.offset(side);
EnumFacing opposite = side.getOpposite();
// check if neighbor can be right clicked
if (!canBeClicked(neighbour)) {
return false;
}
Vec3d hitVec = new Vec3d(neighbour).add(0.5, 0.5, 0.5).add(new Vec3d(opposite.getDirectionVec()).scale(0.5));
Block neighbourBlock = mc.world.getBlockState(neighbour).getBlock();
if (mc.player.getPositionVector().distanceTo(hitVec) > range) {
return false;
}
int obiSlot = findObiInHotbar();
if (obiSlot == -1) {
missingObiDisable = true;
return false;
}
if (lastHotbarSlot != obiSlot) {
mc.player.inventory.currentItem = obiSlot;
lastHotbarSlot = obiSlot;
}
if (!isSneaking && BlockUtils.blackList.contains(neighbourBlock) || BlockUtils.shulkerList.contains(neighbourBlock)) {
mc.player.connection.sendPacket(new CPacketEntityAction(mc.player, CPacketEntityAction.Action.START_SNEAKING));
isSneaking = true;
}
if (rotate.getValue()) faceVectorPacketInstant(hitVec);
mc.playerController.processRightClickBlock(mc.player, mc.world, neighbour, opposite, hitVec, EnumHand.MAIN_HAND);
mc.player.swingArm(EnumHand.MAIN_HAND);
mc.rightClickDelayTimer = 4;
if (noGlitchBlocks.getValue() && !mc.playerController.getCurrentGameType().equals(GameType.CREATIVE)) {
mc.player.connection.sendPacket(new CPacketPlayerDigging(CPacketPlayerDigging.Action.START_DESTROY_BLOCK, neighbour, opposite));
}
if (NoBreakAnimation.INSTANCE.isEnabled()) NoBreakAnimation.INSTANCE.resetMining();
return true;
}
private int findObiInHotbar() {
// search blocks in hotbar
int slot = -1;
for (int i = 0; i < 9; i++) {
// filter out non-block items
ItemStack stack = mc.player.inventory.getStackInSlot(i);
if (stack == ItemStack.EMPTY || !(stack.getItem() instanceof ItemBlock)) {
continue;
}
Block block = ((ItemBlock) stack.getItem()).getBlock();
if (block instanceof BlockObsidian) {
slot = i;
break;
}
}
return slot;
}
private void findClosestTarget() {
List<EntityPlayer> playerList = mc.world.playerEntities;
closestTarget = null;
for (EntityPlayer target : playerList) {
if (target == mc.player && !selfTrap.getValue()) continue;
if (mc.player.getDistance(target) > range.getValue() + 3) continue;
if (!EntityUtils.isLiving(target)) continue;
if ((target).getHealth() <= 0) continue;
if (Friends.isFriend(target.getName())) continue;
if (closestTarget == null) {
closestTarget = target;
continue;
}
if (mc.player.getDistance(target) < mc.player.getDistance(closestTarget)) closestTarget = target;
}
}
@Override
public String getHudInfo() {
if (closestTarget != null) {
return closestTarget.getName().toUpperCase();
}
return "NO TARGET";
}
private enum Cage {
TRAP, CRYSTALEXA, CRYSTALFULL
}
private static class Offsets {
private static final Vec3d[] TRAP = {
new Vec3d(0, 0, -1),
new Vec3d(1, 0, 0),
new Vec3d(0, 0, 1),
new Vec3d(-1, 0, 0),
new Vec3d(0, 1, -1),
new Vec3d(1, 1, 0),
new Vec3d(0, 1, 1),
new Vec3d(-1, 1, 0),
new Vec3d(0, 2, -1),
new Vec3d(1, 2, 0),
new Vec3d(0, 2, 1),
new Vec3d(-1, 2, 0),
new Vec3d(0, 3, -1),
new Vec3d(0, 3, 0)
};
private static final Vec3d[] CRYSTALEXA = {
new Vec3d(0, 0, -1),
new Vec3d(0, 1, -1),
new Vec3d(0, 2, -1),
new Vec3d(1, 2, 0),
new Vec3d(0, 2, 1),
new Vec3d(-1, 2, 0),
new Vec3d(-1, 2, -1),
new Vec3d(1, 2, 1),
new Vec3d(1, 2, -1),
new Vec3d(-1, 2, 1),
new Vec3d(0, 3, -1),
new Vec3d(0, 3, 0)
};
private static final Vec3d[] CRYSTALFULL = {
new Vec3d(0, 0, -1),
new Vec3d(1, 0, 0),
new Vec3d(0, 0, 1),
new Vec3d(-1, 0, 0),
new Vec3d(-1, 0, 1),
new Vec3d(1, 0, -1),
new Vec3d(-1, 0, -1),
new Vec3d(1, 0, 1),
new Vec3d(-1, 1, -1),
new Vec3d(1, 1, 1),
new Vec3d(-1, 1, 1),
new Vec3d(1, 1, -1),
new Vec3d(0, 2, -1),
new Vec3d(1, 2, 0),
new Vec3d(0, 2, 1),
new Vec3d(-1, 2, 0),
new Vec3d(-1, 2, 1),
new Vec3d(1, 2, -1),
new Vec3d(0, 3, -1),
new Vec3d(0, 3, 0)
};
}
}

View File

@ -0,0 +1,108 @@
package me.zeroeightsix.kami.module.modules.combat
import me.zeroeightsix.kami.manager.mangers.CombatManager
import me.zeroeightsix.kami.manager.mangers.PlayerPacketManager
import me.zeroeightsix.kami.module.Module
import me.zeroeightsix.kami.setting.Settings
import me.zeroeightsix.kami.util.BlockUtils
import me.zeroeightsix.kami.util.InventoryUtils
import me.zeroeightsix.kami.util.math.VectorUtils.toBlockPos
import me.zeroeightsix.kami.util.text.MessageSendHelper
import net.minecraft.util.math.BlockPos
import java.util.concurrent.Executors
import java.util.concurrent.Future
@Module.Info(
name = "AutoTrap",
category = Module.Category.COMBAT,
description = "Traps your enemies in obsidian",
modulePriority = 60
)
object AutoTrap : Module() {
private val trapMode = register(Settings.e<TrapMode>("TrapMode", TrapMode.FULL_TRAP))
private val selfTrap = register(Settings.b("SelfTrap", false))
private val autoDisable = register(Settings.b("AutoDisable", true))
private val placeSpeed = register(Settings.floatBuilder("PlacesPerTick").withValue(4f).withRange(0.25f, 5f).withStep(0.25f))
private val placeThread = Thread { runAutoTrap() }.apply { name = "AutoTrap" }
private val threadPool = Executors.newSingleThreadExecutor()
private var future: Future<*>? = null
override fun isActive(): Boolean {
return isEnabled && future?.isDone == false
}
override fun onDisable() {
PlayerPacketManager.resetHotbar()
}
override fun onUpdate() {
if (future?.isDone != false && isPlaceable()) future = threadPool.submit(placeThread)
if (future?.isDone == false && future?.isCancelled == false) {
val slot = getObby()
if (slot != -1) PlayerPacketManager.spoofHotbar(getObby())
PlayerPacketManager.addPacket(this, PlayerPacketManager.PlayerPacket(rotating = false))
} else if (CombatManager.isOnTopPriority(this)) {
PlayerPacketManager.resetHotbar()
}
}
private fun isPlaceable(): Boolean {
(if (selfTrap.value) mc.player else CombatManager.target)?.positionVector?.toBlockPos()?.let {
for (offset in trapMode.value.offset) {
if (!BlockUtils.isPlaceable(it.add(offset))) continue
return true
}
}
return false
}
private fun getObby(): Int {
val slots = InventoryUtils.getSlotsHotbar(49)
if (slots == null) { // Obsidian check
MessageSendHelper.sendChatMessage("$chatName No obsidian in hotbar, disabling!")
disable()
return -1
}
return slots[0]
}
private fun runAutoTrap() {
BlockUtils.buildStructure(placeSpeed.value) {
if (isEnabled && CombatManager.isOnTopPriority(this)) {
val center = (if (selfTrap.value) mc.player else CombatManager.target)?.positionVector?.toBlockPos()
BlockUtils.getPlaceInfo(center, trapMode.value.offset, it, 3)
} else {
null
}
}
if (autoDisable.value) disable()
}
@Suppress("UNUSED")
private enum class TrapMode(val offset: Array<BlockPos>) {
FULL_TRAP(arrayOf(
BlockPos(1, 0, 0),
BlockPos(-1, 0, 0),
BlockPos(0, 0, 1),
BlockPos(0, 0, -1),
BlockPos(1, 1, 0),
BlockPos(-1, 1, 0),
BlockPos(0, 1, 1),
BlockPos(0, 1, -1),
BlockPos(0, 2, 0)
)),
CRYSTAL_TRAP(arrayOf(
BlockPos(1, 1, 1),
BlockPos(1, 1, 0),
BlockPos(1, 1, -1),
BlockPos(0, 1, -1),
BlockPos(-1, 1, -1),
BlockPos(-1, 1, 0),
BlockPos(-1, 1, 1),
BlockPos(0, 1, 1),
BlockPos(0, 2, 0)
))
}
}

View File

@ -0,0 +1,216 @@
package me.zeroeightsix.kami.module.modules.combat
import me.zero.alpine.listener.EventHandler
import me.zero.alpine.listener.EventHook
import me.zero.alpine.listener.Listener
import me.zeroeightsix.kami.event.events.PacketEvent
import me.zeroeightsix.kami.manager.mangers.CombatManager
import me.zeroeightsix.kami.manager.mangers.PlayerPacketManager
import me.zeroeightsix.kami.module.Module
import me.zeroeightsix.kami.setting.Settings
import me.zeroeightsix.kami.util.BlockUtils
import me.zeroeightsix.kami.util.InventoryUtils
import me.zeroeightsix.kami.util.TimerUtils
import me.zeroeightsix.kami.util.combat.CrystalUtils
import me.zeroeightsix.kami.util.math.RotationUtils
import me.zeroeightsix.kami.util.math.Vec2d
import me.zeroeightsix.kami.util.math.Vec2f
import me.zeroeightsix.kami.util.math.VectorUtils
import net.minecraft.init.Blocks
import net.minecraft.init.Items
import net.minecraft.network.play.client.CPacketPlayer
import net.minecraft.network.play.client.CPacketPlayerTryUseItemOnBlock
import net.minecraft.tileentity.TileEntityBed
import net.minecraft.util.EnumFacing
import net.minecraft.util.EnumHand
import net.minecraft.util.math.BlockPos
import net.minecraft.util.math.Vec3d
import java.util.*
import kotlin.collections.HashMap
import kotlin.math.pow
import kotlin.math.sqrt
@Module.Info(
name = "BedAura",
description = "Place bed and kills enemies",
category = Module.Category.COMBAT,
modulePriority = 70
)
object BedAura : Module() {
private val ignoreSecondBaseBlock = register(Settings.b("IgnoreSecondBaseBlock", false))
private val suicideMode = register(Settings.b("SuicideMode", false))
private val hitDelay = register(Settings.integerBuilder("HitDelay").withValue(5).withRange(1, 10))
private val refillDelay = register(Settings.integerBuilder("RefillDelay").withValue(2).withRange(1, 5))
private val minDamage = register(Settings.floatBuilder("MinDamage").withValue(10f).withRange(1f, 20f))
private val maxSelfDamage = register(Settings.floatBuilder("MaxSelfDamage").withValue(4f).withRange(1f, 10f).withVisibility { !suicideMode.value })
private val range = register(Settings.floatBuilder("Range").withValue(5f).withRange(1f, 5f))
private val wallRange = register(Settings.floatBuilder("WallRange").withValue(2.5f).withRange(1f, 5f))
private val placeMap = TreeMap<Pair<Float, Float>, BlockPos>(compareByDescending { it.first }) // <<TargetDamage, SelfDamage>, BlockPos>
private val bedMap = TreeMap<Float, BlockPos>(compareBy { it }) // <SquaredDistance, BlockPos>
private val refillTimer = TimerUtils.TickTimer(TimerUtils.TimeUnit.TICKS)
private var state = State.NONE
private var clickPos = BlockPos(0, -6969, 0)
private var lastRotation = Vec2d(0.0, 0.0)
private var hitTickCount = 0
private var inactiveTicks = 0
private enum class State {
NONE, PLACE, EXPLODE
}
override fun isActive(): Boolean {
return isEnabled && inactiveTicks <= 5
}
override fun onDisable() {
state = State.NONE
inactiveTicks = 6
}
@EventHandler
private val postSendListener = Listener(EventHook { event: PacketEvent.PostSend ->
if (!CombatManager.isOnTopPriority(this) || event.packet !is CPacketPlayer || state == State.NONE || CombatSetting.pause) return@EventHook
val hand = getBedHand() ?: EnumHand.MAIN_HAND
val facing = if (state == State.PLACE) EnumFacing.UP else BlockUtils.getHitSide(clickPos)
val hitVecOffset = BlockUtils.getHitVecOffset(facing)
val packet = CPacketPlayerTryUseItemOnBlock(clickPos, facing, hand, hitVecOffset.x.toFloat(), hitVecOffset.y.toFloat(), hitVecOffset.z.toFloat())
mc.connection!!.sendPacket(packet)
mc.player.swingArm(hand)
state = State.NONE
})
override fun onUpdate() {
if (mc.player.dimension == 0 || !CombatManager.isOnTopPriority(this) || CombatSetting.pause) {
state = State.NONE
resetRotation()
inactiveTicks = 6
return
}
inactiveTicks++
if (canRefill() && refillTimer.tick(refillDelay.value.toLong())) {
InventoryUtils.getSlotsFullInvNoHotbar(355)?.let {
InventoryUtils.quickMoveSlot(it[0])
mc.playerController.syncCurrentPlayItem()
}
}
updatePlaceMap()
updateBedMap()
if (hitTickCount >= hitDelay.value) {
bedMap.values.firstOrNull()?.let { preExplode(it) } ?: getPlacePos()?.let { prePlace(it) }
} else {
hitTickCount++
getPlacePos()?.let { prePlace(it) }
}
if (inactiveTicks <= 5) sendRotation()
else resetRotation()
}
private fun canRefill(): Boolean {
return InventoryUtils.getSlotsHotbar(0) != null
&& InventoryUtils.getSlotsNoHotbar(355) != null
}
private fun updatePlaceMap() {
val cacheMap = CombatManager.target?.let {
val posList = VectorUtils.getBlockPosInSphere(mc.player.getPositionEyes(1f), range.value)
val damagePosMap = HashMap<Pair<Float, Float>, BlockPos>()
for (pos in posList) {
val dist = sqrt(mc.player.getDistanceSqToCenter(pos))
if (BlockUtils.rayTraceTo(pos) == null && dist > wallRange.value) continue
val topSideVec = Vec3d(pos).add(0.5, 1.0, 0.5)
val rotation = RotationUtils.getRotationTo(topSideVec, true)
val facing = EnumFacing.fromAngle(rotation.x)
if (!canPlaceBed(pos)) continue
val targetDamage = CrystalUtils.calcDamage(pos.offset(facing), it)
val selfDamage = CrystalUtils.calcDamage(pos.offset(facing), mc.player)
if (targetDamage < minDamage.value && (suicideMode.value || selfDamage > maxSelfDamage.value))
damagePosMap[Pair(targetDamage, selfDamage)] = pos
}
damagePosMap
}
placeMap.clear()
if (cacheMap != null) placeMap.putAll(cacheMap)
}
private fun canPlaceBed(pos: BlockPos): Boolean {
if (!mc.world.getBlockState(pos).isSideSolid(mc.world, pos, EnumFacing.UP)) return false
val bedPos1 = pos.up()
val bedPos2 = getSecondBedPos(bedPos1)
return (!ignoreSecondBaseBlock.value || mc.world.getBlockState(bedPos2.down()).isSideSolid(mc.world, bedPos2.down(), EnumFacing.UP))
&& !isFire(bedPos1)
&& !isFire(bedPos2)
&& mc.world.getBlockState(bedPos1).material.isReplaceable
&& (!ignoreSecondBaseBlock.value || mc.world.getBlockState(bedPos2).material.isReplaceable)
}
private fun isFire(pos: BlockPos): Boolean {
return mc.world.getBlockState(pos).block == Blocks.FIRE
}
private fun updateBedMap() {
val cacheMap = CombatManager.target?.let {
val damagePosMap = HashMap<Float, BlockPos>()
for (tileEntity in mc.world.loadedTileEntityList) {
if (tileEntity !is TileEntityBed) continue
if (!tileEntity.isHeadPiece) continue
val dist = mc.player.getDistanceSqToCenter(tileEntity.pos).toFloat()
if (dist > range.value.pow(2)) continue
if (BlockUtils.rayTraceTo(tileEntity.pos) == null && dist > wallRange.value.pow(2)) continue
damagePosMap[dist] = tileEntity.pos
}
damagePosMap
}
bedMap.clear()
if (cacheMap != null) bedMap.putAll(cacheMap)
}
private fun getPlacePos() = placeMap.values.firstOrNull()
private fun prePlace(pos: BlockPos) {
if (getExplodePos() != null || InventoryUtils.countItemAll(355) == 0) return
if (getBedHand() == null) InventoryUtils.swapSlotToItem(355)
preClick(pos, Vec3d(0.5, 1.0, 0.5))
state = State.PLACE
}
private fun getExplodePos() = bedMap.values.firstOrNull()
private fun preExplode(pos: BlockPos) {
hitTickCount = 0
preClick(pos, Vec3d(0.5, 0.0, 0.5))
state = State.EXPLODE
}
private fun preClick(pos: BlockPos, hitOffset: Vec3d) {
inactiveTicks = 0
clickPos = pos
lastRotation = RotationUtils.getRotationTo(Vec3d(pos).add(hitOffset), true)
}
private fun getSecondBedPos(pos: BlockPos): BlockPos {
val vec3d = Vec3d(pos).add(0.5, 0.0, 0.5)
val rotation = RotationUtils.getRotationTo(vec3d, true)
val facing = EnumFacing.fromAngle(rotation.x)
return pos.offset(facing)
}
private fun getBedHand(): EnumHand? {
return when (Items.BED) {
mc.player.heldItemMainhand.getItem() -> EnumHand.MAIN_HAND
mc.player.heldItemMainhand.getItem() -> EnumHand.OFF_HAND
else -> null
}
}
private fun sendRotation() {
PlayerPacketManager.addPacket(this, PlayerPacketManager.PlayerPacket(rotating = true, rotation = Vec2f(lastRotation)))
}
private fun resetRotation() {
lastRotation = Vec2d(RotationUtils.normalizeAngle(mc.player.rotationYaw.toDouble()), mc.player.rotationPitch.toDouble())
}
}

View File

@ -0,0 +1,232 @@
package me.zeroeightsix.kami.module.modules.combat
import me.zeroeightsix.kami.manager.mangers.CombatManager
import me.zeroeightsix.kami.module.Module
import me.zeroeightsix.kami.setting.Settings
import me.zeroeightsix.kami.util.BaritoneUtils
import me.zeroeightsix.kami.util.EntityUtils
import me.zeroeightsix.kami.util.InfoCalculator
import me.zeroeightsix.kami.util.TimerUtils
import me.zeroeightsix.kami.util.color.ColorHolder
import me.zeroeightsix.kami.util.combat.CombatUtils
import me.zeroeightsix.kami.util.graphics.*
import me.zeroeightsix.kami.util.math.RotationUtils
import me.zeroeightsix.kami.util.math.Vec2d
import net.minecraft.entity.Entity
import net.minecraft.entity.EntityLivingBase
import net.minecraft.item.ItemFood
import net.minecraft.item.ItemPickaxe
import net.minecraft.util.EnumHand
import org.lwjgl.opengl.GL11.*
import java.util.*
import kotlin.collections.HashSet
import kotlin.math.ceil
@Module.Info(
name = "CombatSetting",
description = "Settings for combat module targeting",
category = Module.Category.COMBAT,
showOnArray = Module.ShowOnArray.OFF,
alwaysEnabled = true
)
object CombatSetting : Module() {
private val page = register(Settings.e<Page>("Page", Page.TARGETING))
/* Targeting */
private val filter = register(Settings.enumBuilder(TargetFilter::class.java, "Filter").withValue(TargetFilter.ALL).withVisibility { page.value == Page.TARGETING })
private val fov = register(Settings.floatBuilder("FOV").withValue(90f).withRange(0f, 180f).withVisibility { page.value == Page.TARGETING && filter.value == TargetFilter.FOV })
private val priority = register(Settings.enumBuilder(TargetPriority::class.java, "Priority").withValue(TargetPriority.DISTANCE).withVisibility { page.value == Page.TARGETING })
private val players = register(Settings.booleanBuilder("Players").withValue(true).withVisibility { page.value == Page.TARGETING })
private val friends = register(Settings.booleanBuilder("Friends").withValue(false).withVisibility { page.value == Page.TARGETING && players.value })
private val teammates = register(Settings.booleanBuilder("Teammates").withValue(false).withVisibility { page.value == Page.TARGETING && players.value })
private val sleeping = register(Settings.booleanBuilder("Sleeping").withValue(false).withVisibility { page.value == Page.TARGETING && players.value })
private val mobs = register(Settings.booleanBuilder("Mobs").withValue(true).withVisibility { page.value == Page.TARGETING })
private val passive = register(Settings.booleanBuilder("PassiveMobs").withValue(false).withVisibility { page.value == Page.TARGETING && mobs.value })
private val neutral = register(Settings.booleanBuilder("NeutralMobs").withValue(false).withVisibility { page.value == Page.TARGETING && mobs.value })
private val hostile = register(Settings.booleanBuilder("HostileMobs").withValue(false).withVisibility { page.value == Page.TARGETING && mobs.value })
private val invisible = register(Settings.booleanBuilder("Invisible").withValue(true).withVisibility { page.value == Page.TARGETING })
private val ignoreWalls = register(Settings.booleanBuilder("IgnoreWalls").withValue(false).withVisibility { page.value == Page.TARGETING })
private val range = register(Settings.floatBuilder("TargetRange").withValue(16.0f).withRange(2.0f, 64.0f).withVisibility { page.value == Page.TARGETING })
/* In Combat */
private val pauseForDigging = register(Settings.booleanBuilder("PauseForDigging").withValue(true).withVisibility { page.value == Page.IN_COMBAT })
private val pauseForEating = register(Settings.booleanBuilder("PauseForEating").withValue(true).withVisibility { page.value == Page.IN_COMBAT })
private val ignoreOffhandEating = register(Settings.booleanBuilder("IgnoreOffhandEating").withValue(true).withVisibility { page.value == Page.IN_COMBAT && pauseForEating.value })
private val pauseBaritone = register(Settings.booleanBuilder("PauseBaritone").withValue(true).withVisibility { page.value == Page.IN_COMBAT })
private val resumeDelay = register(Settings.integerBuilder("ResumeDelay").withRange(1, 10).withValue(3).withVisibility { page.value == Page.IN_COMBAT && pauseBaritone.value })
/* Render */
private val renderPredictedPos = register(Settings.booleanBuilder("RenderPredictedPosition").withValue(false).withVisibility { page.value == Page.RENDER })
private val pingSync = register(Settings.booleanBuilder("PingSync").withValue(true).withVisibility { page.value == Page.RENDER && renderPredictedPos.value })
private val ticksAhead = register(Settings.integerBuilder("TicksAhead").withValue(5).withRange(0, 20).withVisibility { page.value == Page.RENDER && renderPredictedPos.value && !pingSync.value })
private enum class Page {
TARGETING, IN_COMBAT, RENDER
}
private enum class TargetFilter {
ALL, FOV, MANUAL
}
private enum class TargetPriority {
DAMAGE, HEALTH, CROSS_HAIR, DISTANCE
}
private var overrideRange = range.value
private var paused = false
private val resumeTimer = TimerUtils.TickTimer(TimerUtils.TimeUnit.SECONDS)
val pause
get() = pauseForDigging.value && mc.player.heldItemMainhand.getItem() is ItemPickaxe && mc.playerController.isHittingBlock
|| pauseForEating.value && mc.player.isHandActive && mc.player.activeItemStack.getItem() is ItemFood && (mc.player.activeHand != EnumHand.OFF_HAND || !ignoreOffhandEating.value)
override fun isActive() = Aura.isActive() || BedAura.isActive() || CrystalAura.isActive() || Surround.isActive()
override fun onRender() {
if (!renderPredictedPos.value) return
CombatManager.target?.let {
val ticks = if (pingSync.value) ceil(InfoCalculator.ping() / 25f).toInt() else ticksAhead.value
val posCurrent = EntityUtils.getInterpolatedPos(it, KamiTessellator.pTicks())
val posAhead = CombatManager.motionTracker.calcPositionAhead(ticks, true) ?: return
val posAheadEye = posAhead.add(0.0, it.eyeHeight.toDouble(), 0.0)
val posCurrentScreen = Vec2d(ProjectionUtils.toScaledScreenPos(posCurrent))
val posAheadScreen = Vec2d(ProjectionUtils.toScaledScreenPos(posAhead))
val posAheadEyeScreen = Vec2d(ProjectionUtils.toScaledScreenPos(posAheadEye))
val vertexHelper = VertexHelper(GlStateUtils.useVbo())
val vertices = arrayOf(posCurrentScreen, posAheadScreen, posAheadEyeScreen)
glDisable(GL_TEXTURE_2D)
RenderUtils2D.drawLineStrip(vertexHelper, vertices, 2f, ColorHolder(80, 255, 80))
glEnable(GL_TEXTURE_2D)
}
}
override fun onUpdate() {
with(CombatManager.getTopModule()) {
overrideRange = if (this is Aura) this.range.value else range.value
}
getTargetList().let {
CombatManager.targetList = it
CombatManager.target = getTarget(it)
}
if (pauseBaritone.value && !paused && isActive()) {
BaritoneUtils.pause()
paused = true
} else if (paused && resumeTimer.tick(resumeDelay.value.toLong())) {
BaritoneUtils.unpause()
paused = false
}
}
private fun getTargetList(): LinkedList<EntityLivingBase> {
val player = arrayOf(players.value, friends.value, sleeping.value)
val mob = arrayOf(mobs.value, passive.value, neutral.value, hostile.value)
val targetList = LinkedList(EntityUtils.getTargetList(player, mob, invisible.value, overrideRange))
if ((targetList.isEmpty() || getTarget(targetList) == null) && overrideRange != range.value) {
targetList.addAll(EntityUtils.getTargetList(player, mob, invisible.value, range.value))
}
if (!shouldIgnoreWall()) targetList.removeIf {
!mc.player.canEntityBeSeen(it) && EntityUtils.canEntityFeetBeSeen(it) && EntityUtils.canEntityHitboxBeSeen(it) == null
}
if (!teammates.value) targetList.removeIf {
mc.player.isOnSameTeam(it)
}
if (AntiBot.isEnabled) targetList.removeIf {
AntiBot.botSet.contains(it)
}
return targetList
}
private fun shouldIgnoreWall(): Boolean {
val module = CombatManager.getTopModule()
return if (module is Aura || module is AimBot) ignoreWalls.value
else true
}
private fun getTarget(listIn: LinkedList<EntityLivingBase>): EntityLivingBase? {
val copiedList = LinkedList(listIn)
return filterTargetList(copiedList) ?: CombatManager.target?.let { entity ->
if (!entity.isDead && listIn.contains(entity)) entity else null
}
}
private fun filterTargetList(listIn: LinkedList<EntityLivingBase>): EntityLivingBase? {
if (listIn.isEmpty()) return null
return filterByPriority(filterByFilter(listIn))
}
private fun filterByFilter(listIn: LinkedList<EntityLivingBase>): LinkedList<EntityLivingBase> {
when (filter.value) {
TargetFilter.FOV -> {
listIn.removeIf { RotationUtils.getRelativeRotation(it) > fov.value }
}
TargetFilter.MANUAL -> {
if (!mc.gameSettings.keyBindAttack.isKeyDown && !mc.gameSettings.keyBindUseItem.isKeyDown) {
return LinkedList()
}
val eyePos = mc.player.getPositionEyes(KamiTessellator.pTicks())
val lookVec = mc.player.lookVec.scale(range.value.toDouble())
val sightEndPos = eyePos.add(lookVec)
listIn.removeIf { it.boundingBox.calculateIntercept(eyePos, sightEndPos) == null }
}
else -> { }
}
return listIn
}
private fun filterByPriority(listIn: LinkedList<EntityLivingBase>): EntityLivingBase? {
if (listIn.isEmpty()) return null
if (priority.value == TargetPriority.DAMAGE) filterByDamage(listIn)
if (priority.value == TargetPriority.HEALTH) filterByHealth(listIn)
return if (priority.value == TargetPriority.CROSS_HAIR) filterByCrossHair(listIn) else filterByDistance(listIn)
}
private fun filterByDamage(listIn: LinkedList<EntityLivingBase>) {
if (listIn.isEmpty()) return
var damage = Float.MIN_VALUE
val toKeep = HashSet<Entity>()
for (entity in listIn) {
val currentDamage = CombatUtils.calcDamage(entity, roundDamage = true)
if (currentDamage >= damage) {
if (currentDamage > damage) {
damage = currentDamage
toKeep.clear()
}
toKeep.add(entity)
}
}
listIn.removeIf { !toKeep.contains(it) }
}
private fun filterByHealth(listIn: LinkedList<EntityLivingBase>) {
if (listIn.isEmpty()) return
var health = Float.MAX_VALUE
val toKeep = HashSet<Entity>()
for (e in listIn) {
val currentHealth = e.health
if (currentHealth <= health) {
if (currentHealth < health) {
health = currentHealth
toKeep.clear()
}
toKeep.add(e)
}
}
listIn.removeIf { !toKeep.contains(it) }
}
private fun filterByCrossHair(listIn: LinkedList<EntityLivingBase>): EntityLivingBase? {
if (listIn.isEmpty()) return null
return listIn.sortedBy { RotationUtils.getRelativeRotation(it) }[0]
}
private fun filterByDistance(listIn: LinkedList<EntityLivingBase>): EntityLivingBase? {
if (listIn.isEmpty()) return null
return listIn.sortedBy { it.getDistance(mc.player) }[0]
}
}

View File

@ -1,624 +0,0 @@
package me.zeroeightsix.kami.module.modules.combat;
import me.zero.alpine.listener.EventHandler;
import me.zero.alpine.listener.Listener;
import me.zeroeightsix.kami.event.events.PacketEvent;
import me.zeroeightsix.kami.event.events.RenderEvent;
import me.zeroeightsix.kami.module.Module;
import me.zeroeightsix.kami.module.modules.render.PlayerModel;
import me.zeroeightsix.kami.setting.Setting;
import me.zeroeightsix.kami.setting.Settings;
import me.zeroeightsix.kami.util.EntityUtils;
import me.zeroeightsix.kami.util.Friends;
import me.zeroeightsix.kami.util.InfoCalculator;
import me.zeroeightsix.kami.util.InventoryUtils;
import me.zeroeightsix.kami.util.color.ColorHolder;
import me.zeroeightsix.kami.util.graphics.ESPRenderer;
import me.zeroeightsix.kami.util.math.Vec2d;
import net.minecraft.enchantment.EnchantmentHelper;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.SharedMonsterAttributes;
import net.minecraft.entity.item.EntityEnderCrystal;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.init.Blocks;
import net.minecraft.init.Items;
import net.minecraft.init.MobEffects;
import net.minecraft.item.ItemStack;
import net.minecraft.item.ItemSword;
import net.minecraft.item.ItemTool;
import net.minecraft.network.Packet;
import net.minecraft.network.play.client.CPacketPlayer;
import net.minecraft.network.play.client.CPacketPlayerTryUseItemOnBlock;
import net.minecraft.potion.Potion;
import net.minecraft.util.*;
import net.minecraft.util.math.*;
import net.minecraft.world.Explosion;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;
import static me.zeroeightsix.kami.util.math.RotationUtils.getRotationTo;
import static me.zeroeightsix.kami.util.text.MessageSendHelper.sendChatMessage;
/**
* Created by 086 on 28/12/2017.
* Updated 3 December 2019 by hub
* Updated 8 March 2020 by polymer
* Updated by qther on 27/03/20
* Updated by l1ving on 27/03/20
* Updated by Afel on 08/06/20
*/
@Module.Info(
name = "CrystalAura",
category = Module.Category.COMBAT,
description = "Places End Crystals to kill enemies"
)
public class CrystalAura extends Module {
private Setting<Boolean> defaultSetting = register(Settings.b("Defaults", false));
private Setting<Page> p = register(Settings.enumBuilder(Page.class).withName("Page").withValue(Page.ONE).build());
/* Page One */
private Setting<ExplodeBehavior> explodeBehavior = register(Settings.enumBuilder(ExplodeBehavior.class).withName("ExplodeBehavior").withValue(ExplodeBehavior.ALWAYS).withVisibility(v -> p.getValue().equals(Page.ONE)).build());
private Setting<PlaceBehavior> placeBehavior = register(Settings.enumBuilder(PlaceBehavior.class).withName("PlaceBehavior").withValue(PlaceBehavior.TRADITIONAL).withVisibility(v -> p.getValue().equals(Page.ONE)).build());
private Setting<Boolean> autoSwitch = register(Settings.booleanBuilder("AutoSwitch").withValue(true).withVisibility(v -> p.getValue().equals(Page.ONE)).build());
private Setting<Boolean> place = register(Settings.booleanBuilder("Place").withValue(false).withVisibility(v -> p.getValue().equals(Page.ONE)).build());
private Setting<Boolean> explode = register(Settings.booleanBuilder("Explode").withValue(false).withVisibility(v -> p.getValue().equals(Page.ONE)).build());
private Setting<Boolean> checkAbsorption = register(Settings.booleanBuilder("CheckAbsorption").withValue(true).withVisibility(v -> p.getValue().equals(Page.ONE)).build());
public Setting<Double> range = register(Settings.doubleBuilder("Range").withMinimum(1.0).withValue(4.0).withMaximum(10.0).withVisibility(v -> p.getValue().equals(Page.ONE)).build());
private Setting<Boolean> autoDelay = register(Settings.booleanBuilder("AutoDelay").withValue(false).withVisibility(v -> p.getValue().equals(Page.ONE)).build());
private Setting<Double> delay = register(Settings.doubleBuilder("HitDelay").withMinimum(0.0).withValue(5.0).withMaximum(10.0).withVisibility(v -> !autoDelay.getValue() && p.getValue().equals(Page.ONE)).build());
private Setting<Integer> hitAttempts = register(Settings.integerBuilder("HitAttempts").withValue(-1).withMinimum(-1).withMaximum(20).withVisibility(v -> p.getValue().equals(Page.ONE)).build());
private Setting<Double> minDmg = register(Settings.doubleBuilder("MinimumDamage").withMinimum(0.0).withValue(0.0).withMaximum(32.0).withVisibility(v -> p.getValue().equals(Page.ONE)).build());
private Setting<Boolean> sneakEnable = register(Settings.booleanBuilder("SneakSurround").withValue(true).withVisibility(v -> p.getValue().equals(Page.ONE)).build());
private Setting<Boolean> placePriority = register(Settings.booleanBuilder("PrioritizeManual").withValue(false).withVisibility(v -> p.getValue().equals(Page.ONE)).build());
/* Page Two */
private Setting<Boolean> antiWeakness = register(Settings.booleanBuilder("AntiWeakness").withValue(false).withVisibility(v -> p.getValue().equals(Page.TWO)).build());
private Setting<Boolean> noToolExplode = register(Settings.booleanBuilder("NoToolExplode").withValue(true).withVisibility(v -> !antiWeakness.getValue() && p.getValue().equals(Page.TWO)).build());
private Setting<Boolean> players = register(Settings.booleanBuilder("Players").withValue(true).withVisibility(v -> p.getValue().equals(Page.TWO)).build());
private Setting<Boolean> mobs = register(Settings.booleanBuilder("Mobs").withValue(false).withVisibility(v -> p.getValue().equals(Page.TWO)).build());
private Setting<Boolean> passive = register(Settings.booleanBuilder("PassiveMobs").withValue(false).withVisibility(v -> mobs.getValue() && p.getValue().equals(Page.TWO)).build());
private Setting<Boolean> neutral = register(Settings.booleanBuilder("NeutralMobs").withValue(false).withVisibility(v -> mobs.getValue() && p.getValue().equals(Page.TWO)).build());
private Setting<Boolean> hostile = register(Settings.booleanBuilder("HostileMobs").withValue(true).withVisibility(v -> mobs.getValue() && p.getValue().equals(Page.TWO)).build());
private Setting<Boolean> tracer = register(Settings.booleanBuilder("Tracer").withValue(true).withVisibility(v -> p.getValue().equals(Page.TWO)).build());
private Setting<Boolean> customColours = register(Settings.booleanBuilder("CustomColours").withValue(true).withVisibility(v -> p.getValue().equals(Page.TWO)).build());
private Setting<Integer> aBlock = register(Settings.integerBuilder("BlockTransparency").withMinimum(0).withValue(44).withMaximum(255).withVisibility(v -> p.getValue().equals(Page.TWO) && customColours.getValue()).build());
private Setting<Integer> aTracer = register(Settings.integerBuilder("TracerTransparency").withMinimum(0).withValue(200).withMaximum(255).withVisibility(v -> p.getValue().equals(Page.TWO) && customColours.getValue()).build());
private Setting<Integer> r = register(Settings.integerBuilder("Red").withMinimum(0).withValue(155).withMaximum(255).withVisibility(v -> p.getValue().equals(Page.TWO) && customColours.getValue()).build());
private Setting<Integer> g = register(Settings.integerBuilder("Green").withMinimum(0).withValue(144).withMaximum(255).withVisibility(v -> p.getValue().equals(Page.TWO) && customColours.getValue()).build());
private Setting<Integer> b = register(Settings.integerBuilder("Blue").withMinimum(0).withValue(255).withMaximum(255).withVisibility(v -> p.getValue().equals(Page.TWO) && customColours.getValue()).build());
private Setting<Boolean> statusMessages = register(Settings.booleanBuilder("StatusMessages").withValue(false).withVisibility(v -> p.getValue().equals(Page.TWO)).build());
private enum ExplodeBehavior {HOLE_ONLY, PREVENT_SUICIDE, LEFT_CLICK_ONLY, ALWAYS}
private enum PlaceBehavior {MULTI, TRADITIONAL}
private enum Page {ONE, TWO}
private BlockPos render;
private Entity renderEnt;
private long systemTime = -1;
// we need this cooldown to not place from old hotbar slot, before we have switched to crystals
private boolean switchCoolDown = false;
private boolean isAttacking = false;
private int oldSlot = -1;
public static CrystalAura INSTANCE;
private static EntityEnderCrystal lastCrystal;
private static List<EntityEnderCrystal> ignoredCrystals = new ArrayList<>();
private static int hitTries = 0;
private static boolean togglePitch = false;
public CrystalAura() {
super();
defaultSetting.settingListener = setting -> {
if (defaultSetting.getValue()) defaults();
};
INSTANCE = this;
}
public void onUpdate() {
if (mc.player == null) {
resetHitAttempts();
return;
}
resetHitAttempts(hitAttempts.getValue() == -1);
int holeBlocks = 0;
Vec3d[] holeOffset = {
mc.player.getPositionVector().add(1, 0, 0),
mc.player.getPositionVector().add(-1, 0, 0),
mc.player.getPositionVector().add(0, 0, 1),
mc.player.getPositionVector().add(0, 0, -1),
mc.player.getPositionVector().add(0, -1, 0)
};
EntityEnderCrystal crystal = mc.world.loadedEntityList.stream()
.filter(entity -> entity instanceof EntityEnderCrystal)
.filter(entity -> !ignored(entity))
.map(entity -> (EntityEnderCrystal) entity)
.min(Comparator.comparing(c -> mc.player.getDistance(c)))
.orElse(null);
if (explode.getValue() && crystal != null && mc.player.getDistance(crystal) <= range.getValue() && passSwordCheck()) {
// Added delay to stop ncp from flagging "hitting too fast"
if (((System.nanoTime() / 1000000f) - systemTime) >= 25 * getDelay()) {
if (antiWeakness.getValue() && mc.player.isPotionActive(MobEffects.WEAKNESS)) {
if (!isAttacking) {
// save initial player hand
oldSlot = mc.player.inventory.currentItem;
isAttacking = true;
}
// search for sword and tools in hotbar
int newSlot = -1;
for (int i = 0; i < 9; i++) {
ItemStack stack = mc.player.inventory.getStackInSlot(i);
if (stack == ItemStack.EMPTY) {
continue;
}
if ((stack.getItem() instanceof ItemSword)) {
newSlot = i;
break;
}
if ((stack.getItem() instanceof ItemTool)) {
newSlot = i;
break;
}
}
// check if any swords or tools were found
if (newSlot != -1) {
mc.player.inventory.currentItem = newSlot;
switchCoolDown = true;
}
}
if (placePriority.getValue()) {
boolean wasPlacing = place.getValue();
if (mc.gameSettings.keyBindUseItem.isKeyDown() && place.getValue()) {
place.setValue(false);
explode(crystal);
}
if (!place.getValue() && wasPlacing) place.setValue(true);
}
if (explodeBehavior.getValue() == ExplodeBehavior.ALWAYS) {
explode(crystal);
}
for (Vec3d vecOffset : holeOffset) { /* for placeholder offset for each BlockPos in the list holeOffset */
BlockPos offset = new BlockPos(vecOffset.x, vecOffset.y, vecOffset.z);
if (mc.world.getBlockState(offset).getBlock() == Blocks.OBSIDIAN || mc.world.getBlockState(offset).getBlock() == Blocks.BEDROCK) {
holeBlocks++;
}
}
if (explodeBehavior.getValue() == ExplodeBehavior.HOLE_ONLY) {
if (holeBlocks == 5) {
explode(crystal);
}
}
if (explodeBehavior.getValue() == ExplodeBehavior.PREVENT_SUICIDE) {
if (mc.player.getPositionVector().distanceTo(crystal.getPositionVector()) <= 0.5 && mc.player.getPosition().getY() == crystal.getPosition().getY() || mc.player.getPositionVector().distanceTo(crystal.getPositionVector()) >= 2.3 && mc.player.getPosition().getY() == crystal.getPosition().getY() || mc.player.getPositionVector().distanceTo(crystal.getPositionVector()) >= 0.5 && mc.player.getPosition().getY() != crystal.getPosition().getY()) {
explode(crystal);
}
}
if (explodeBehavior.getValue() == ExplodeBehavior.LEFT_CLICK_ONLY && mc.gameSettings.keyBindAttack.isKeyDown()) {
explode(crystal);
}
if (sneakEnable.getValue() && mc.player.isSneaking() && holeBlocks != 5) {
Surround.INSTANCE.enable();
}
return;
}
} else {
resetRotation();
if (oldSlot != -1) {
mc.player.inventory.currentItem = oldSlot;
oldSlot = -1;
}
isAttacking = false;
}
int crystalSlot = mc.player.getHeldItemMainhand().getItem() == Items.END_CRYSTAL ? mc.player.inventory.currentItem : -1;
if (crystalSlot == -1) {
for (int l = 0; l < 9; ++l) {
if (mc.player.inventory.getStackInSlot(l).getItem() == Items.END_CRYSTAL) {
crystalSlot = l;
break;
}
}
}
boolean offhand = false;
if (mc.player.getHeldItemOffhand().getItem() == Items.END_CRYSTAL) {
offhand = true;
} else if (crystalSlot == -1) {
return;
}
List<BlockPos> blocks = findCrystalBlocks();
List<Entity> entities = new ArrayList<>();
if (players.getValue()) {
entities.addAll(mc.world.playerEntities.stream().filter(entityPlayer -> !Friends.isFriend(entityPlayer.getName())).collect(Collectors.toList()));
}
entities.addAll(mc.world.loadedEntityList.stream().filter(entity -> EntityUtils.isLiving(entity) && (EntityUtils.mobTypeSettings(entity, mobs.getValue(), passive.getValue(), neutral.getValue(), hostile.getValue()))).collect(Collectors.toList()));
BlockPos q = null;
double damage = .5;
for (Entity entity : entities) {
// stop if the entities health is 0 or less then 0 (somehow) or if the entity is you, don't do excess calculation if multiplace is enabled
if (entity == mc.player || ((EntityLivingBase) entity).getHealth() <= 0 || placeBehavior.getValue() == PlaceBehavior.MULTI) {
continue;
}
for (BlockPos blockPos : blocks) {
double b = entity.getDistanceSq(blockPos);
if (b >= 169) {
continue; // If this block if further than 13 (3.6^2, less calc) blocks, ignore it. It'll take no or very little damage
}
double d = calculateDamage(blockPos.x + .5, blockPos.y + 1, blockPos.z + .5, entity);
if (d > damage) {
double self = calculateDamage(blockPos.x + .5, blockPos.y + 1, blockPos.z + .5, mc.player);
// Factor in absorption if wanted
float enemyAbsorption = 0.0f;
float playerAbsorption = 0.0f;
if (checkAbsorption.getValue()) {
enemyAbsorption = ((EntityLivingBase) entity).getAbsorptionAmount();
playerAbsorption = mc.player.getAbsorptionAmount();
}
// If this deals more damage to ourselves than it does to our target, continue. This is only ignored if the crystal is sure to kill our target but not us.
// Also continue if our crystal is going to hurt us.. alot
if ((self > d && !(d < ((EntityLivingBase) entity).getHealth() + enemyAbsorption)) || self - .5 > mc.player.getHealth() + playerAbsorption) {
continue;
}
damage = d;
q = blockPos;
renderEnt = entity;
PlayerModel.INSTANCE.setLastAttacked(System.currentTimeMillis());
mc.player.setLastAttackedEntity(entity);
}
}
}
if (place.getValue() && placeBehavior.getValue() == PlaceBehavior.MULTI) {
for (Entity entity : entities) {
if (entity == mc.player || ((EntityLivingBase) entity).getHealth() <= 0) {
continue;
}
for (BlockPos blockPos : blocks) {
double b = entity.getDistanceSq(blockPos);
if (b > 75) {
continue;
}
double d = calculateDamage(blockPos.x + .5, blockPos.y + 1, blockPos.z + .5, entity);
double self = calculateDamage(blockPos.x + .5, blockPos.y + 1, blockPos.z + .5, mc.player);
if (self >= mc.player.getHealth() + mc.player.getAbsorptionAmount() || self > d) continue;
if (b < 10 && d >= 15 || d >= ((EntityLivingBase) entity).getHealth() + ((EntityLivingBase) entity).getAbsorptionAmount() || 6 >= ((EntityLivingBase) entity).getHealth() + ((EntityLivingBase) entity).getAbsorptionAmount() && b < 4 || b < 9 && d >= minDmg.getValue() && minDmg.getValue() > 0.0) {
q = blockPos;
damage = d;
renderEnt = entity;
PlayerModel.INSTANCE.setLastAttacked(System.currentTimeMillis());
mc.player.setLastAttackedEntity(entity);
}
}
}
}
if (damage == .5) {
render = null;
renderEnt = null;
resetRotation();
return;
}
// this sends a constant packet flow for default packets
if (place.getValue()) {
render = q;
if (!offhand && mc.player.inventory.currentItem != crystalSlot) {
if (autoSwitch.getValue()) {
mc.player.inventory.currentItem = crystalSlot;
resetRotation();
switchCoolDown = true;
}
return;
}
lookAtPacket(new Vec3d(q.x + .5, q.y - .5, q.z + .5));
RayTraceResult result = mc.world.rayTraceBlocks(new Vec3d(mc.player.posX, mc.player.posY + mc.player.getEyeHeight(), mc.player.posZ), new Vec3d(q.x + .5, q.y - .5d, q.z + .5));
EnumFacing f;
if (result == null || result.sideHit == null) {
f = EnumFacing.UP;
} else {
f = result.sideHit;
}
// return after we did an autoswitch
if (switchCoolDown) {
switchCoolDown = false;
return;
}
//mc.playerController.processRightClickBlock(mc.player, mc.world, q, f, new Vec3d(0, 0, 0), EnumHand.MAIN_HAND);
mc.player.connection.sendPacket(new CPacketPlayerTryUseItemOnBlock(q, f, offhand ? EnumHand.OFF_HAND : EnumHand.MAIN_HAND, 0, 0, 0));
}
if (isSpoofingAngles) {
if (togglePitch) {
mc.player.rotationPitch += 0.0004;
togglePitch = false;
} else {
mc.player.rotationPitch -= 0.0004;
togglePitch = true;
}
}
}
@Override
public void onWorldRender(RenderEvent event) {
if (render != null) {
int tracerAlpha = 0;
if (tracer.getValue()) {
tracerAlpha = aTracer.getValue();
}
ColorHolder colour = new ColorHolder(255, 255, 255);
if (customColours.getValue()) {
colour = new ColorHolder(r.getValue(), g.getValue(), b.getValue());
}
ESPRenderer renderer = new ESPRenderer();
renderer.setAFilled(aBlock.getValue());
renderer.setATracer(tracerAlpha);
renderer.add(render, colour);
renderer.render(true);
}
}
private void lookAtPacket(Vec3d pos) {
Vec2d lookAt = getRotationTo(pos, true);
setYawAndPitch((float) lookAt.getX(), (float) lookAt.getY());
}
private boolean canPlaceCrystal(BlockPos blockPos) {
BlockPos boost = blockPos.add(0, 1, 0);
BlockPos boost2 = blockPos.add(0, 2, 0);
return (mc.world.getBlockState(blockPos).getBlock() == Blocks.BEDROCK
|| mc.world.getBlockState(blockPos).getBlock() == Blocks.OBSIDIAN)
&& mc.world.getBlockState(boost).getBlock() == Blocks.AIR
&& mc.world.getBlockState(boost2).getBlock() == Blocks.AIR
&& mc.world.getEntitiesWithinAABB(Entity.class, new AxisAlignedBB(boost)).isEmpty()
&& mc.world.getEntitiesWithinAABB(Entity.class, new AxisAlignedBB(boost2)).isEmpty();
}
public static BlockPos getPlayerPos() {
return new BlockPos(Math.floor(mc.player.posX), Math.floor(mc.player.posY), Math.floor(mc.player.posZ));
}
private List<BlockPos> findCrystalBlocks() {
NonNullList<BlockPos> positions = NonNullList.create();
positions.addAll(getSphere(getPlayerPos(), range.getValue().floatValue(), range.getValue().intValue(), false, true, 0).stream().filter(this::canPlaceCrystal).collect(Collectors.toList()));
return positions;
}
public List<BlockPos> getSphere(BlockPos loc, float r, int h, boolean hollow, boolean sphere, int plus_y) {
List<BlockPos> circleblocks = new ArrayList<>();
int cx = loc.getX();
int cy = loc.getY();
int cz = loc.getZ();
for (int x = cx - (int) r; x <= cx + r; x++) {
for (int z = cz - (int) r; z <= cz + r; z++) {
for (int y = (sphere ? cy - (int) r : cy); y < (sphere ? cy + r : cy + h); y++) {
double dist = (cx - x) * (cx - x) + (cz - z) * (cz - z) + (sphere ? (cy - y) * (cy - y) : 0);
if (dist < r * r && !(hollow && dist < (r - 1) * (r - 1))) {
BlockPos l = new BlockPos(x, y + plus_y, z);
circleblocks.add(l);
}
}
}
}
return circleblocks;
}
public static float calculateDamage(double posX, double posY, double posZ, Entity entity) {
float doubleExplosionSize = 6.0F * 2.0F;
double distancedSize = entity.getDistance(posX, posY, posZ) / (double) doubleExplosionSize;
Vec3d vec3d = new Vec3d(posX, posY, posZ);
double blockDensity = entity.world.getBlockDensity(vec3d, entity.getEntityBoundingBox());
double v = (1.0D - distancedSize) * blockDensity;
float damage = (float) ((int) ((v * v + v) / 2.0D * 7.0D * (double) doubleExplosionSize + 1.0D));
double finalD = 1;
/*if (entity instanceof EntityLivingBase)
finalD = getBlastReduction((EntityLivingBase) entity,getDamageMultiplied(damage));*/
if (entity instanceof EntityLivingBase) {
finalD = getBlastReduction((EntityLivingBase) entity, getDamageMultiplied(damage), new Explosion(mc.world, null, posX, posY, posZ, 6F, false, true));
}
return (float) finalD;
}
public static float getBlastReduction(EntityLivingBase entity, float damage, Explosion explosion) {
if (entity instanceof EntityPlayer) {
EntityPlayer ep = (EntityPlayer) entity;
DamageSource ds = DamageSource.causeExplosionDamage(explosion);
damage = CombatRules.getDamageAfterAbsorb(damage, (float) ep.getTotalArmorValue(), (float) ep.getEntityAttribute(SharedMonsterAttributes.ARMOR_TOUGHNESS).getAttributeValue());
int k = EnchantmentHelper.getEnchantmentModifierDamage(ep.getArmorInventoryList(), ds);
float f = MathHelper.clamp(k, 0.0F, 20.0F);
damage = damage * (1.0F - f / 25.0F);
if (entity.isPotionActive(Objects.requireNonNull(Potion.getPotionById(11)))) {
damage = damage - (damage / 5);
}
damage = Math.max(damage, 0.0F);
return damage;
}
damage = CombatRules.getDamageAfterAbsorb(damage, (float) entity.getTotalArmorValue(), (float) entity.getEntityAttribute(SharedMonsterAttributes.ARMOR_TOUGHNESS).getAttributeValue());
return damage;
}
private static float getDamageMultiplied(float damage) {
int diff = mc.world.getDifficulty().getId();
return damage * (diff == 0 ? 0 : (diff == 2 ? 1 : (diff == 1 ? 0.5f : 1.5f)));
}
public static float calculateDamage(EntityEnderCrystal crystal, Entity entity) {
return calculateDamage(crystal.posX, crystal.posY, crystal.posZ, entity);
}
//Better Rotation Spoofing System:
private static boolean isSpoofingAngles;
private static double yaw;
private static double pitch;
//this modifies packets being sent so no extra ones are made. NCP used to flag with "too many packets"
private static void setYawAndPitch(float yaw1, float pitch1) {
yaw = yaw1;
pitch = pitch1;
isSpoofingAngles = true;
}
private static void resetRotation() {
if (isSpoofingAngles) {
yaw = mc.player.rotationYaw;
pitch = mc.player.rotationPitch;
isSpoofingAngles = false;
}
}
@EventHandler
private Listener<PacketEvent.Send> cPacketListener = new Listener<>(event -> {
Packet packet = event.getPacket();
if (packet instanceof CPacketPlayer) {
if (isSpoofingAngles) {
((CPacketPlayer) packet).yaw = (float) yaw;
((CPacketPlayer) packet).pitch = (float) pitch;
}
}
});
public void onEnable() {
sendMessage("&aENABLED&r");
}
public void onDisable() {
sendMessage("&cDISABLED&r");
render = null;
renderEnt = null;
resetRotation();
}
public void explode(EntityEnderCrystal crystal) {
if (crystal == null) return;
if (lastCrystal == crystal) hitTries++;
else {
lastCrystal = crystal;
hitTries = 0;
}
try {
if (hitAttempts.getValue() != -1 && hitTries > hitAttempts.getValue()) {
ignoredCrystals.add(crystal);
hitTries = 0;
} else {
lookAtPacket(crystal.getPositionVector());
mc.playerController.attackEntity(mc.player, crystal);
mc.player.swingArm(EnumHand.MAIN_HAND);
}
} catch (Throwable ignored) {
}
systemTime = System.nanoTime() / 1000000L;
}
private boolean passSwordCheck() {
if (!noToolExplode.getValue() || antiWeakness.getValue()) return true;
else
return !noToolExplode.getValue() || (!(mc.player.getHeldItemMainhand().getItem() instanceof ItemTool) && !(mc.player.getHeldItemMainhand().getItem() instanceof ItemSword));
}
@Override
public String getHudInfo() {
return "" + InventoryUtils.countItemAll(426);
}
private boolean ignored(Entity e) {
if (ignoredCrystals == null) return false;
for (EntityEnderCrystal c : ignoredCrystals) if (e != null && e == c) return true;
return false;
}
private void resetHitAttempts() {
sendMessage("&l&9Reset&r&9 hit attempts crystals");
lastCrystal = null;
ignoredCrystals = null;
hitTries = 0;
}
private void resetHitAttempts(boolean should) {
if (should) {
lastCrystal = null;
ignoredCrystals = null;
hitTries = 0;
} else if (resetTime()) {
sendMessage("&l&9Reset&r&9 hit attempts crystals");
lastCrystal = null;
ignoredCrystals = null;
hitTries = 0;
}
}
private static long startTime = 0;
private boolean resetTime() {
if (startTime == 0) startTime = System.currentTimeMillis();
if (startTime + 900000 <= System.currentTimeMillis()) { // 15 minutes in milliseconds
startTime = System.currentTimeMillis();
return true;
}
return false;
}
private void sendMessage(String message) {
if (statusMessages.getValue()) {
sendChatMessage(getChatName() + " " + message);
}
}
private double getDelay() {
if (!autoDelay.getValue()) {
return delay.getValue();
}
int ping = InfoCalculator.ping();
return 2 * ping * (InfoCalculator.tps(2) / 20) + (ping / 10.0);
}
private void defaults() {
explodeBehavior.setValue(ExplodeBehavior.ALWAYS);
placeBehavior.setValue(PlaceBehavior.TRADITIONAL);
autoSwitch.setValue(true);
place.setValue(false);
explode.setValue(false);
checkAbsorption.setValue(true);
range.setValue(4.0);
delay.setValue(5.0);
hitAttempts.setValue(-1);
minDmg.setValue(0.0);
sneakEnable.setValue(true);
placePriority.setValue(false);
antiWeakness.setValue(false);
noToolExplode.setValue(true);
players.setValue(true);
mobs.setValue(false);
tracer.setValue(true);
customColours.setValue(true);
aBlock.setValue(44);
aTracer.setValue(200);
r.setValue(155);
g.setValue(144);
b.setValue(255);
statusMessages.setValue(false);
defaultSetting.setValue(false);
sendChatMessage(getChatName() + " Set to defaults!");
}
}

View File

@ -0,0 +1,376 @@
package me.zeroeightsix.kami.module.modules.combat
import me.zero.alpine.listener.EventHandler
import me.zero.alpine.listener.EventHook
import me.zero.alpine.listener.Listener
import me.zeroeightsix.kami.event.KamiEvent
import me.zeroeightsix.kami.event.events.OnUpdateWalkingPlayerEvent
import me.zeroeightsix.kami.event.events.PacketEvent
import me.zeroeightsix.kami.manager.mangers.CombatManager
import me.zeroeightsix.kami.manager.mangers.PlayerPacketManager
import me.zeroeightsix.kami.module.Module
import me.zeroeightsix.kami.setting.Settings
import me.zeroeightsix.kami.util.BlockUtils
import me.zeroeightsix.kami.util.EntityUtils
import me.zeroeightsix.kami.util.InfoCalculator
import me.zeroeightsix.kami.util.InventoryUtils
import me.zeroeightsix.kami.util.combat.CombatUtils
import me.zeroeightsix.kami.util.combat.CrystalUtils
import me.zeroeightsix.kami.util.math.RotationUtils
import me.zeroeightsix.kami.util.math.Vec2f
import net.minecraft.entity.item.EntityEnderCrystal
import net.minecraft.init.Items
import net.minecraft.init.MobEffects
import net.minecraft.init.SoundEvents
import net.minecraft.item.ItemSword
import net.minecraft.item.ItemTool
import net.minecraft.network.play.client.CPacketPlayerTryUseItemOnBlock
import net.minecraft.network.play.client.CPacketUseEntity
import net.minecraft.network.play.server.SPacketSoundEffect
import net.minecraft.util.EnumHand
import net.minecraft.util.SoundCategory
import net.minecraft.util.math.BlockPos
import net.minecraft.util.math.Vec3d
import java.util.*
import kotlin.collections.HashSet
import kotlin.math.abs
import kotlin.math.ceil
import kotlin.math.max
@Module.Info(
name = "CrystalAura",
description = "Places End Crystals to kill enemies",
category = Module.Category.COMBAT,
modulePriority = 80
)
object CrystalAura : Module() {
/* Settings */
private val page = register(Settings.e<Page>("Page", Page.GENERAL))
/* General */
private val facePlaceThreshold = register(Settings.floatBuilder("FacePlace").withValue(5.0f).withRange(0.0f, 20.0f).withVisibility { page.value == Page.GENERAL })
private val noSuicideThreshold = register(Settings.floatBuilder("NoSuicide").withValue(5.0f).withRange(0.0f, 20.0f).withVisibility { page.value == Page.GENERAL })
private val maxYawRate = register(Settings.integerBuilder("MaxYawRate").withValue(50).withRange(10, 100).withVisibility { page.value == Page.GENERAL })
private val motionPrediction = register(Settings.booleanBuilder("MotionPrediction").withValue(true).withVisibility { page.value == Page.GENERAL })
private val pingSync = register(Settings.booleanBuilder("PingSync").withValue(true).withVisibility { page.value == Page.GENERAL && motionPrediction.value })
private val ticksAhead = register(Settings.integerBuilder("TicksAhead").withValue(5).withRange(0, 20).withVisibility { page.value == Page.GENERAL && motionPrediction.value && !pingSync.value })
/* Place page one */
private val doPlace = register(Settings.booleanBuilder("Place").withValue(true).withVisibility { page.value == Page.PLACE_ONE })
private val forcePlace = register(Settings.booleanBuilder("RightClickForcePlace").withValue(false).withVisibility { page.value == Page.PLACE_ONE })
private val autoSwap = register(Settings.booleanBuilder("AutoSwap").withValue(true).withVisibility { page.value == Page.PLACE_ONE })
private val spoofHotbar = register(Settings.booleanBuilder("SpoofHotbar").withValue(true).withVisibility { page.value == Page.PLACE_ONE && autoSwap.value })
private val placeSwing = register(Settings.booleanBuilder("PlaceSwing").withValue(false).withVisibility { page.value == Page.PLACE_ONE })
/* Place page two */
private val minDamageP = register(Settings.integerBuilder("MinDamagePlace").withValue(4).withRange(0, 20).withVisibility { page.value == Page.PLACE_TWO })
private val maxSelfDamageP = register(Settings.integerBuilder("MaxSelfDamagePlace").withValue(4).withRange(0, 20).withVisibility { page.value == Page.PLACE_TWO })
private val placeOffset = register(Settings.floatBuilder("PlaceOffset").withValue(1.0f).withRange(0f, 1f).withStep(0.05f).withVisibility { page.value == Page.PLACE_TWO })
private val maxCrystal = register(Settings.integerBuilder("MaxCrystal").withValue(2).withRange(1, 5).withVisibility { page.value == Page.PLACE_TWO })
private val placeDelay = register(Settings.integerBuilder("PlaceDelay").withValue(1).withRange(1, 10).withVisibility { page.value == Page.PLACE_TWO })
private val placeRange = register(Settings.floatBuilder("PlaceRange").withValue(4.0f).withRange(0.0f, 5.0f).withVisibility { page.value == Page.PLACE_TWO })
private val wallPlaceRange = register(Settings.floatBuilder("WallPlaceRange").withValue(2.0f).withRange(0.0f, 5.0f).withVisibility { page.value == Page.PLACE_TWO })
/* Explode page one */
private val doExplode = register(Settings.booleanBuilder("Explode").withValue(true).withVisibility { page.value == Page.EXPLODE_ONE })
private val forceExplode = register(Settings.booleanBuilder("LeftClickForceExplode").withValue(false).withVisibility { page.value == Page.EXPLODE_ONE })
private val autoForceExplode = register(Settings.booleanBuilder("AutoForceExplode").withValue(true).withVisibility { page.value == Page.EXPLODE_ONE })
private val antiWeakness = register(Settings.booleanBuilder("AntiWeakness").withValue(true).withVisibility { page.value == Page.EXPLODE_ONE })
/* Explode page two */
private val checkDamage = register(Settings.booleanBuilder("CheckDamage").withValue(true).withVisibility { page.value == Page.EXPLODE_TWO })
private val minDamageE = register(Settings.integerBuilder("MinDamageExplode").withValue(8).withRange(0, 20).withVisibility { page.value == Page.EXPLODE_TWO && checkDamage.value })
private val maxSelfDamageE = register(Settings.integerBuilder("MaxSelfDamageExplode").withValue(6).withRange(0, 20).withVisibility { page.value == Page.EXPLODE_TWO && checkDamage.value })
private val hitDelay = register(Settings.integerBuilder("HitDelay").withValue(2).withRange(1, 10).withVisibility { page.value == Page.EXPLODE_TWO })
private val hitAttempts = register(Settings.integerBuilder("HitAttempts").withValue(2).withRange(0, 5).withVisibility { page.value == Page.EXPLODE_TWO })
private val explodeRange = register(Settings.floatBuilder("ExplodeRange").withValue(4.0f).withRange(0.0f, 5.0f).withVisibility { page.value == Page.EXPLODE_TWO })
private val wallExplodeRange = register(Settings.floatBuilder("WallExplodeRange").withValue(2.0f).withRange(0.0f, 5.0f).withVisibility { page.value == Page.EXPLODE_TWO })
/* End of settings */
private enum class Page {
GENERAL, PLACE_ONE, PLACE_TWO, EXPLODE_ONE, EXPLODE_TWO
}
/* Variables */
private val placeMap = TreeMap<Float, BlockPos>(Comparator.reverseOrder())
private val crystalList = HashSet<EntityEnderCrystal>()
private val ignoredList = HashSet<EntityEnderCrystal>()
private var lastCrystal: EntityEnderCrystal? = null
private var lastLookAt = Vec3d.ZERO
private var targetPosition = Vec3d.ZERO
private var placeTimer = 0
private var hitTimer = 0
private var hitCount = 0
private var inactiveTicks = 30
override fun isActive(): Boolean {
return isEnabled && InventoryUtils.countItemAll(426) > 0 && inactiveTicks <= 20
}
override fun onEnable() {
if (mc.player == null) disable()
else resetRotation()
}
override fun onDisable() {
placeMap.clear()
crystalList.clear()
ignoredList.clear()
lastCrystal = null
lastLookAt = Vec3d.ZERO
targetPosition = Vec3d.ZERO
placeTimer = 0
hitTimer = 0
hitCount = 0
inactiveTicks = 30
PlayerPacketManager.resetHotbar()
}
// Minecraft sends sounds packets a tick before removing the crystal lol
@EventHandler
private val receiveListener = Listener(EventHook { event: PacketEvent.Receive ->
if (!CombatManager.isOnTopPriority(this) || mc.player == null || event.packet !is SPacketSoundEffect) return@EventHook
if (event.packet.getCategory() == SoundCategory.BLOCKS && event.packet.getSound() == SoundEvents.ENTITY_GENERIC_EXPLODE) {
val crystalList = CrystalUtils.getCrystalList(Vec3d(event.packet.x, event.packet.y, event.packet.z), 5f)
for (crystal in crystalList) {
crystal.setDead()
mc.world.removeEntityFromWorld(crystal.entityId)
}
ignoredList.clear()
hitCount = 0
}
})
@EventHandler
private val onUpdateWalkingPlayerListener = Listener(EventHook { event: OnUpdateWalkingPlayerEvent ->
if (inactiveTicks > 20 || event.era != KamiEvent.Era.PRE || lastLookAt == Vec3d.ZERO || CombatSetting.pause) return@EventHook
val packet = PlayerPacketManager.PlayerPacket(rotating = true, rotation = Vec2f(getLastRotation()))
PlayerPacketManager.addPacket(this, packet)
})
override fun onUpdate() {
if (!CombatManager.isOnTopPriority(this) || CombatSetting.pause) return
inactiveTicks++
hitTimer++
placeTimer++
updateMap()
if (canExplode()) explode() else if (canPlace()) place()
if (inactiveTicks > 5 || getHand() == EnumHand.OFF_HAND) PlayerPacketManager.resetHotbar()
if (inactiveTicks > 20) resetRotation()
}
private fun updateMap() {
setPosition()
placeMap.clear()
placeMap.putAll(CrystalUtils.getPlacePos(CombatManager.target, mc.player, placeRange.value + 1f))
resetPosition()
crystalList.clear()
crystalList.addAll(CrystalUtils.getCrystalList(max(placeRange.value, explodeRange.value)))
if (inactiveTicks > 10 && getExplodingCrystal() == null && ignoredList.isNotEmpty()) {
ignoredList.clear()
hitCount = 0
}
}
private fun place() {
if (autoSwap.value && getHand() == null) {
InventoryUtils.getSlotsHotbar(426)?.get(0)?.let {
if (spoofHotbar.value) PlayerPacketManager.spoofHotbar(it)
else InventoryUtils.swapSlot(it)
}
}
getPlacingPos()?.let { pos ->
getHand()?.let { hand ->
placeTimer = 0
inactiveTicks = 0
lastLookAt = Vec3d(pos).add(0.5, placeOffset.value.toDouble(), 0.5)
mc.player.connection.sendPacket(CPacketPlayerTryUseItemOnBlock(pos, BlockUtils.getHitSide(pos), hand, 0.5f, placeOffset.value, 0.5f))
if (placeSwing.value) mc.player.swingArm(hand)
}
}
}
private fun explode() {
if (antiWeakness.value && mc.player.isPotionActive(MobEffects.WEAKNESS) && !isHoldingTool()) {
CombatUtils.equipBestWeapon()
PlayerPacketManager.resetHotbar()
}
getExplodingCrystal()?.let {
hitTimer = 0
inactiveTicks = 0
lastLookAt = it.positionVector
if (hitAttempts.value != 0 && it == lastCrystal) {
hitCount++
if (hitCount >= hitAttempts.value) ignoredList.add(it)
} else {
hitCount = 0
}
mc.connection!!.sendPacket(CPacketUseEntity(it))
mc.player.swingArm(getHand() ?: EnumHand.OFF_HAND)
mc.player.setLastAttackedEntity(CombatManager.target!!)
lastCrystal = it
}
}
/* End of main functions */
/* Placing */
private fun canPlace(): Boolean {
return doPlace.value
&& placeTimer >= placeDelay.value
&& InventoryUtils.countItemAll(426) > 0
&& getPlacingPos() != null
&& countValidCrystal() < maxCrystal.value
}
@Suppress("UnconditionalJumpStatementInLoop") // The linter is wrong here, it will continue until it's supposed to return
private fun getPlacingPos(): BlockPos? {
if (placeMap.isEmpty()) return null
for ((damage, pos) in placeMap) {
val hitVec = Vec3d(pos).add(0.5, 1.0, 0.5)
val dist = mc.player.getDistance(hitVec.x, hitVec.y, hitVec.z)
if (dist > placeRange.value) continue
if (!CrystalUtils.canPlaceCollide(pos)) continue
if (BlockUtils.rayTraceTo(pos) == null && dist > wallPlaceRange.value) continue
if (!shouldForcePlace()) {
val rotation = RotationUtils.getRotationTo(hitVec, true)
if (abs(rotation.x - getLastRotation().x) > maxYawRate.value + (inactiveTicks * 10f)) continue
val selfDamage = CrystalUtils.calcDamage(pos, mc.player)
if (!noSuicideCheck(selfDamage)) continue
if (!checkDamagePlace(damage, selfDamage)) continue
}
return pos
}
return null
}
private fun shouldForcePlace(): Boolean {
return forcePlace.value && mc.gameSettings.keyBindUseItem.isKeyDown
&& mc.player.heldItemMainhand.getItem() == Items.END_CRYSTAL
}
/**
* @return True if passed placing damage check
*/
private fun checkDamagePlace(damage: Float, selfDamage: Float): Boolean {
return (damage >= minDamageP.value || shouldFacePlace()) && (selfDamage <= maxSelfDamageP.value)
}
/* End of placing */
/* Exploding */
private fun canExplode(): Boolean {
return doExplode.value
&& hitTimer >= hitDelay.value
&& getExplodingCrystal() != null
&& CombatManager.target?.let { target ->
if (checkDamage.value && !shouldForceExplode()) {
var maxDamage = 0f
var maxSelfDamage = 0f
setPosition()
for (crystal in crystalList) {
maxDamage = max(maxDamage, CrystalUtils.calcDamage(crystal, target))
maxSelfDamage = max(maxSelfDamage, CrystalUtils.calcDamage(crystal, mc.player))
}
resetPosition()
if (!noSuicideCheck(maxSelfDamage)) return false
if (!checkDamageExplode(maxDamage, maxSelfDamage)) return false
}
return true
} ?: false
}
private fun getExplodingCrystal(): EntityEnderCrystal? {
if (crystalList.isEmpty()) return null
return crystalList.firstOrNull {
!ignoredList.contains(it)
&& (mc.player.canEntityBeSeen(it) || EntityUtils.canEntityFeetBeSeen(it))
&& it.getDistance(mc.player) < explodeRange.value
&& abs(RotationUtils.getRotationToEntity(it).x - getLastRotation().x) <= maxYawRate.value + (inactiveTicks * 10f)
} ?: crystalList.firstOrNull {
!ignoredList.contains(it)
&& EntityUtils.canEntityHitboxBeSeen(it) != null
&& it.getDistance(mc.player) < wallExplodeRange.value
}
}
private fun shouldForceExplode(): Boolean {
return (autoForceExplode.value && placeMap.isNotEmpty() && placeMap.firstKey() > minDamageE.value)
|| (forceExplode.value && mc.gameSettings.keyBindAttack.isKeyDown
&& mc.player.heldItemMainhand.getItem() != Items.DIAMOND_PICKAXE
&& mc.player.heldItemMainhand.getItem() != Items.GOLDEN_APPLE)
}
private fun checkDamageExplode(damage: Float, selfDamage: Float): Boolean {
return (damage >= minDamageE.value || shouldFacePlace()) && (selfDamage <= maxSelfDamageE.value)
}
/* End of exploding */
/* General */
private fun getHand(): EnumHand? {
val serverSideItem = if (spoofHotbar.value) mc.player.inventory.getStackInSlot(PlayerPacketManager.serverSideHotbar).getItem() else null
return when (Items.END_CRYSTAL) {
mc.player.heldItemOffhand.getItem() -> EnumHand.OFF_HAND
mc.player.heldItemMainhand.getItem() -> EnumHand.MAIN_HAND
serverSideItem -> EnumHand.MAIN_HAND
else -> null
}
}
private fun noSuicideCheck(selfDamage: Float) = mc.player.health - selfDamage > noSuicideThreshold.value
private fun isHoldingTool(): Boolean {
val item = mc.player.heldItemMainhand.getItem()
return item is ItemTool || item is ItemSword
}
private fun shouldFacePlace() = facePlaceThreshold.value > 0f && CombatManager.target?.let { it.health <= facePlaceThreshold.value } ?: false
private fun countValidCrystal(): Int {
var count = 0
CombatManager.target?.let { target ->
setPosition()
for (crystal in crystalList) {
if (ignoredList.contains(crystal)) continue
if (crystal.getDistance(mc.player) > placeRange.value) continue
val rotation = RotationUtils.getRotationToEntity(crystal)
if (abs(rotation.x - getLastRotation().x) > maxYawRate.value) continue
val damage = CrystalUtils.calcDamage(crystal, target)
val selfDamage = CrystalUtils.calcDamage(crystal, mc.player)
if (!checkDamagePlace(damage, selfDamage)) continue
count++
}
resetPosition()
}
return count
}
/* End of general */
/* Motion prediction */
private fun setPosition() {
if (!motionPrediction.value) return
val ticks = if (pingSync.value) ceil(InfoCalculator.ping() / 25f).toInt() else ticksAhead.value
val posAhead = CombatManager.motionTracker.calcPositionAhead(ticks, true) ?: return
CombatManager.target?.let {
targetPosition = it.positionVector
it.setPosition(posAhead.x, posAhead.y, posAhead.z)
}
}
private fun resetPosition() {
if (!motionPrediction.value) return
if (targetPosition == Vec3d.ZERO) return
CombatManager.target?.setPosition(targetPosition.x, targetPosition.y, targetPosition.z)
}
/* End of Motion prediction */
/* Rotation spoofing */
private fun getLastRotation() = RotationUtils.getRotationTo(lastLookAt, true)
private fun resetRotation() {
lastLookAt = CombatManager.target?.positionVector ?: Vec3d.ZERO
}
/* End of rotation spoofing */
}

View File

@ -0,0 +1,187 @@
package me.zeroeightsix.kami.module.modules.combat
import me.zeroeightsix.kami.event.events.RenderEvent
import me.zeroeightsix.kami.manager.mangers.CombatManager
import me.zeroeightsix.kami.module.Module
import me.zeroeightsix.kami.setting.Settings
import me.zeroeightsix.kami.util.color.ColorConverter
import me.zeroeightsix.kami.util.color.ColorHolder
import me.zeroeightsix.kami.util.combat.CrystalUtils
import me.zeroeightsix.kami.util.graphics.ESPRenderer
import me.zeroeightsix.kami.util.graphics.GlStateUtils
import me.zeroeightsix.kami.util.graphics.KamiTessellator
import me.zeroeightsix.kami.util.graphics.ProjectionUtils
import me.zeroeightsix.kami.util.math.MathUtils
import me.zeroeightsix.kami.util.math.Vec2f
import net.minecraft.entity.item.EntityEnderCrystal
import net.minecraft.util.math.AxisAlignedBB
import net.minecraft.util.math.BlockPos
import org.lwjgl.opengl.GL11.*
import java.util.concurrent.ConcurrentHashMap
import java.util.concurrent.Executors
import kotlin.math.PI
import kotlin.math.abs
import kotlin.math.min
import kotlin.math.sin
@Module.Info(
name = "CrystalESP",
description = "Renders ESP for End Crystals",
category = Module.Category.COMBAT
)
object CrystalESP : Module() {
private val page = register(Settings.e<Page>("Page", Page.DAMAGE_ESP))
private val damageESP = register(Settings.booleanBuilder("DamageESP").withValue(false).withVisibility { page.value == Page.DAMAGE_ESP }.build())
private val minAlpha = register(Settings.integerBuilder("MinAlpha").withValue(0).withRange(0, 255).withVisibility { page.value == Page.DAMAGE_ESP }.build())
private val maxAlpha = register(Settings.integerBuilder("MaxAlpha").withValue(63).withRange(0, 255).withVisibility { page.value == Page.DAMAGE_ESP }.build())
private val damageRange = register(Settings.floatBuilder("DamageESPRange").withValue(4.0f).withRange(0.0f, 16.0f).withVisibility { page.value == Page.DAMAGE_ESP }.build())
private val crystalESP = register(Settings.booleanBuilder("CrystalESP").withValue(true).withVisibility { page.value == Page.CRYSTAL_ESP }.build())
private val mode = register(Settings.enumBuilder(Mode::class.java).withName("Mode").withValue(Mode.BLOCK).withVisibility { page.value == Page.CRYSTAL_ESP && crystalESP.value }.build())
private val filled = register(Settings.booleanBuilder("Filled").withValue(true).withVisibility { page.value == Page.CRYSTAL_ESP && crystalESP.value }.build())
private val outline = register(Settings.booleanBuilder("Outline").withValue(true).withVisibility { page.value == Page.CRYSTAL_ESP && crystalESP.value }.build())
private val tracer = register(Settings.booleanBuilder("Tracer").withValue(true).withVisibility { page.value == Page.CRYSTAL_ESP && crystalESP.value }.build())
private val showDamage = register(Settings.booleanBuilder("Damage").withValue(true).withVisibility { page.value == Page.CRYSTAL_ESP && crystalESP.value }.build())
private val showSelfDamage = register(Settings.booleanBuilder("SelfDamage").withValue(false).withVisibility { page.value == Page.CRYSTAL_ESP && crystalESP.value }.build())
private val textScale = register(Settings.floatBuilder("TextScale").withValue(1.0f).withRange(0.0f, 4.0f).withVisibility { page.value == Page.CRYSTAL_ESP && crystalESP.value })
private val animationScale = register(Settings.floatBuilder("AnimationScale").withValue(1.0f).withRange(0.0f, 2.0f).withVisibility { page.value == Page.CRYSTAL_ESP && crystalESP.value })
private val crystalRange = register(Settings.floatBuilder("CrystalESPRange").withValue(16.0f).withRange(0.0f, 64.0f).withVisibility { page.value == Page.CRYSTAL_ESP }.build())
private val r = register(Settings.integerBuilder("Red").withValue(155).withRange(0, 255).withVisibility { page.value == Page.CRYSTAL_ESP_COLOR && crystalESP.value }.build())
private val g = register(Settings.integerBuilder("Green").withValue(144).withRange(0, 255).withVisibility { page.value == Page.CRYSTAL_ESP_COLOR && crystalESP.value }.build())
private val b = register(Settings.integerBuilder("Blue").withValue(255).withRange(0, 255).withVisibility { page.value == Page.CRYSTAL_ESP_COLOR && crystalESP.value }.build())
private val aFilled = register(Settings.integerBuilder("FilledAlpha").withValue(47).withRange(0, 255).withVisibility { page.value == Page.CRYSTAL_ESP_COLOR && crystalESP.value && filled.value }.build())
private val aOutline = register(Settings.integerBuilder("OutlineAlpha").withValue(127).withRange(0, 255).withVisibility { page.value == Page.CRYSTAL_ESP_COLOR && crystalESP.value && outline.value }.build())
private val aTracer = register(Settings.integerBuilder("TracerAlpha").withValue(200).withRange(0, 255).withVisibility { page.value == Page.CRYSTAL_ESP_COLOR && crystalESP.value && tracer.value }.build())
private val thickness = register(Settings.floatBuilder("Thickness").withValue(2.0f).withRange(0.0f, 4.0f).withVisibility { page.value == Page.CRYSTAL_ESP_COLOR && crystalESP.value && (outline.value || tracer.value) }.build())
private enum class Page {
DAMAGE_ESP, CRYSTAL_ESP, CRYSTAL_ESP_COLOR
}
private enum class Mode {
BLOCK, CRYSTAL
}
private val damageESPMap = ConcurrentHashMap<Float, BlockPos>()
private val crystalMap = ConcurrentHashMap<EntityEnderCrystal, Pair<Pair<Float, Float>, Vec2f>>() // <Crystal, <<Damage, SelfDamage>, <PrevAlpha, Alpha>>>
private val threads = arrayOf(Thread { updateDamageESP() }, Thread { updateCrystalESP() })
private val threadPool = Executors.newCachedThreadPool()
override fun onUpdate() {
for (thread in threads) {
threadPool.execute(thread)
}
}
private fun updateDamageESP() {
if (damageESP.value) {
val cacheMap = CrystalUtils.getPlacePos(CombatManager.target, CombatManager.target, damageRange.value)
damageESPMap.values.removeIf { !cacheMap.containsValue(it) }
damageESPMap.putAll(cacheMap)
} else {
damageESPMap.clear()
}
}
private fun updateCrystalESP() {
if (crystalESP.value) {
val cacheMap = HashMap(CrystalUtils.getCrystalList(crystalRange.value).map { crystal ->
val damages = calcDamages(crystal)
crystal to Pair(damages, Vec2f(0f, 0f))
}.toMap())
for ((crystal, pair) in crystalMap) {
val scale = 1f / animationScale.value
val damages = calcDamages(crystal)
cacheMap.computeIfPresent(crystal) { _, _ -> Pair(damages, Vec2f(pair.second.y, min(pair.second.y + 0.4f * scale, 1f))) }
cacheMap.computeIfAbsent(crystal) { Pair(damages, Vec2f(pair.second.y, min(pair.second.y + 0.2f * scale, 2f))) }
}
crystalMap.putAll(cacheMap)
crystalMap.values.removeIf { it.second.y >= 2.0f }
} else {
crystalMap.clear()
}
}
private fun calcDamages(crystal: EntityEnderCrystal): Pair<Float, Float> {
val damage = CombatManager.target?.let { CrystalUtils.calcDamage(crystal, it) } ?: -0.0f
val selfDamage = mc.player?.let { CrystalUtils.calcDamage(crystal, mc.player) } ?: -0.0f
return Pair(damage, selfDamage)
}
override fun onWorldRender(event: RenderEvent) {
val renderer = ESPRenderer()
/* Damage ESP */
if (damageESP.value && damageESPMap.isNotEmpty()) {
renderer.aFilled = 255
for ((damage, pos) in damageESPMap) {
val rgb = MathUtils.convertRange(damage.toInt(), 0, 20, 127, 255)
val a = MathUtils.convertRange(damage.toInt(), 0, 20, minAlpha.value, maxAlpha.value)
val rgba = ColorHolder(rgb, rgb, rgb, a)
renderer.add(pos, rgba)
}
renderer.render(true)
}
/* Crystal ESP */
if (crystalESP.value) {
renderer.aFilled = if (filled.value) aFilled.value else 0
renderer.aOutline = if (outline.value) aOutline.value else 0
renderer.aTracer = if (tracer.value) aTracer.value else 0
renderer.thickness = thickness.value
for ((crystal, pair) in crystalMap) {
val progress = getAnimationProgress(pair.second)
val box = if (mode.value == Mode.CRYSTAL) {
crystal.boundingBox.shrink(1.0 - progress)
} else {
AxisAlignedBB(crystal.position.down()).shrink(0.5 - progress * 0.5)
}
val rgba = ColorHolder(r.value, g.value, b.value, (progress * 255f).toInt())
renderer.add(box, rgba)
}
renderer.render(true)
}
}
override fun onRender() {
if (!showDamage.value && !showSelfDamage.value) return
GlStateUtils.rescale(mc.displayWidth.toDouble(), mc.displayHeight.toDouble())
val fontRenderer = mc.fontRenderer
for ((crystal, pair) in crystalMap) {
glPushMatrix()
val screenPos = ProjectionUtils.toScreenPos(if (mode.value == Mode.CRYSTAL) {
crystal.boundingBox.center
} else {
crystal.positionVector.subtract(0.0, 0.5, 0.0)
})
glTranslated(screenPos.x, screenPos.y, 0.0)
glScalef(textScale.value * 2f, textScale.value * 2f, 1f)
val damage = abs(MathUtils.round(pair.first.first, 1))
val selfDamage = abs(MathUtils.round(pair.first.second, 1))
val alpha = (getAnimationProgress(pair.second) * 255f).toInt()
val color = ColorConverter.rgbToInt(255, 255, 255, alpha)
if (showDamage.value) {
val text = "Target: $damage"
val halfWidth = fontRenderer.getStringWidth(text) / -2f
fontRenderer.drawStringWithShadow(text, halfWidth, 0f, color)
}
if (showSelfDamage.value) {
val text = "Self: $selfDamage"
val halfWidth = fontRenderer.getStringWidth(text) / -2f
fontRenderer.drawStringWithShadow(text, halfWidth, fontRenderer.FONT_HEIGHT + 2f, color)
}
glPopMatrix()
}
GlStateUtils.rescaleMc()
}
private fun getAnimationProgress(progressIn: Vec2f): Float {
val interpolated = progressIn.x + (progressIn.y - progressIn.x) * KamiTessellator.pTicks()
return sin(interpolated * 0.5 * PI).toFloat()
}
}

View File

@ -1,21 +1,19 @@
package me.zeroeightsix.kami.module.modules.render
package me.zeroeightsix.kami.module.modules.combat
import me.zeroeightsix.kami.event.events.RenderEvent
import me.zeroeightsix.kami.module.Module
import me.zeroeightsix.kami.setting.Settings
import me.zeroeightsix.kami.util.BlockUtils.surroundOffset
import me.zeroeightsix.kami.util.color.ColorHolder
import me.zeroeightsix.kami.util.combat.SurroundUtils
import me.zeroeightsix.kami.util.graphics.ESPRenderer
import me.zeroeightsix.kami.util.graphics.GeometryMasks
import me.zeroeightsix.kami.util.math.VectorUtils
import net.minecraft.init.Blocks
import net.minecraft.util.math.BlockPos
import java.util.concurrent.ConcurrentHashMap
import kotlin.math.ceil
@Module.Info(
name = "HoleESP",
category = Module.Category.RENDER,
category = Module.Category.COMBAT,
description = "Show safe holes for crystal pvp"
)
object HoleESP : Module() {
@ -55,30 +53,14 @@ object HoleESP : Module() {
safeHoles.clear()
val blockPosList = VectorUtils.getBlockPosInSphere(mc.player.positionVector, renderDistance.value)
for (pos in blockPosList) {
if (mc.world.getBlockState(pos).block != Blocks.AIR// block gotta be air
|| mc.world.getBlockState(pos.up()).block != Blocks.AIR // block 1 above gotta be air
|| mc.world.getBlockState(pos.up().up()).block != Blocks.AIR) continue // block 2 above gotta be air
val holeType = SurroundUtils.checkHole(pos)
if (holeType == SurroundUtils.HoleType.NONE) continue
var isSafe = true
var isBedrock = true
for (offset in surroundOffset) {
val block = mc.world.getBlockState(pos.add(offset)).block
if (block !== Blocks.BEDROCK && block !== Blocks.OBSIDIAN && block !== Blocks.ENDER_CHEST && block !== Blocks.ANVIL) {
isSafe = false
break
}
if (block !== Blocks.BEDROCK) {
isBedrock = false
}
if (holeType == SurroundUtils.HoleType.OBBY && shouldAddObby()) {
safeHoles[pos] = ColorHolder(r1.value, g1.value, b1.value)
}
if (isSafe) {
if (!isBedrock && shouldAddObby()) {
safeHoles[pos] = ColorHolder(r1.value, g1.value, b1.value)
}
if (isBedrock && shouldAddBedrock()) {
safeHoles[pos] = ColorHolder(r2.value, g2.value, b2.value)
}
if (holeType == SurroundUtils.HoleType.BEDROCK && shouldAddBedrock()) {
safeHoles[pos] = ColorHolder(r2.value, g2.value, b2.value)
}
}
}

View File

@ -0,0 +1,119 @@
package me.zeroeightsix.kami.module.modules.combat
import me.zeroeightsix.kami.manager.mangers.CombatManager
import me.zeroeightsix.kami.manager.mangers.PlayerPacketManager
import me.zeroeightsix.kami.module.Module
import me.zeroeightsix.kami.setting.Settings
import me.zeroeightsix.kami.util.InventoryUtils
import me.zeroeightsix.kami.util.combat.CrystalUtils
import me.zeroeightsix.kami.util.combat.SurroundUtils
import me.zeroeightsix.kami.util.math.RotationUtils
import me.zeroeightsix.kami.util.math.Vec2f
import me.zeroeightsix.kami.util.math.VectorUtils.toBlockPos
import me.zeroeightsix.kami.util.math.VectorUtils.toVec3d
import me.zeroeightsix.kami.util.text.MessageSendHelper
import net.minecraft.entity.Entity
import net.minecraft.init.Blocks
import net.minecraft.init.Items
import net.minecraft.network.play.client.CPacketPlayerDigging
import net.minecraft.util.EnumFacing
import net.minecraft.util.EnumHand
import net.minecraft.util.math.BlockPos
import kotlin.math.pow
@Module.Info(
name = "HoleMiner",
category = Module.Category.COMBAT,
description = "Mines your opponent's hole",
modulePriority = 100
)
object HoleMiner : Module() {
private val range = register(Settings.floatBuilder("Range").withValue(5.0f).withRange(0.0f, 10.0f))
private var miningPos: BlockPos? = null
private var start = true
override fun getHudInfo() = "${CombatManager.target?.name}"
override fun onDisable() {
miningPos = null
start = true
}
override fun onEnable() {
if (mc.player == null) {
disable()
return
}
val target = CombatManager.target
if (target != null) {
if (SurroundUtils.checkHole(target) != SurroundUtils.HoleType.OBBY) {
MessageSendHelper.sendChatMessage("$chatName Target is not in a valid hole, disabling")
disable()
} else {
miningPos = findHoleBlock(target)
}
} else {
MessageSendHelper.sendChatMessage("$chatName No target found, disabling")
disable()
}
}
override fun onUpdate() {
if (!CombatManager.isOnTopPriority(this)) return
if (mc.player.heldItemMainhand.getItem() != Items.DIAMOND_PICKAXE) {
val slot = InventoryUtils.getSlotsHotbar(278)?.get(0)
if (slot == null) {
MessageSendHelper.sendChatMessage("$chatName No pickaxe found, disabling")
disable()
return
} else {
InventoryUtils.swapSlot(slot)
}
}
val pos = miningPos
if (pos == null) {
MessageSendHelper.sendChatMessage("$chatName No hole block to mine, disabling")
disable()
} else if (mc.player.ticksExisted % 2 == 0) {
if (mc.world.isAirBlock(pos)) {
MessageSendHelper.sendChatMessage("$chatName Done mining")
disable()
return
}
val action = if (start) CPacketPlayerDigging.Action.START_DESTROY_BLOCK else CPacketPlayerDigging.Action.STOP_DESTROY_BLOCK
val rotation = Vec2f(RotationUtils.getRotationTo(pos.toVec3d(), true))
val diff = mc.player.getPositionEyes(1f).subtract(pos.toVec3d())
val normalizedVec = diff.scale(1.0 / diff.length())
val facing = EnumFacing.getFacingFromVector(normalizedVec.x.toFloat(), normalizedVec.y.toFloat(), normalizedVec.z.toFloat())
PlayerPacketManager.addPacket(this, PlayerPacketManager.PlayerPacket(rotating = true, rotation = rotation))
mc.connection!!.sendPacket(CPacketPlayerDigging(action, pos, facing))
mc.player.swingArm(EnumHand.MAIN_HAND)
start = false
}
}
private fun findHoleBlock(entity: Entity): BlockPos? {
val pos = entity.positionVector.toBlockPos()
var closestPos = 114.514 to BlockPos.ORIGIN
for (facing in EnumFacing.HORIZONTALS) {
val offsetPos = pos.offset(facing)
val dist = mc.player.getDistanceSqToCenter(offsetPos)
if (dist > range.value.pow(2) || dist > closestPos.first) continue
if (mc.world.getBlockState(offsetPos).block == Blocks.BEDROCK) continue
if (!checkPos(offsetPos, facing)) continue
closestPos = dist to offsetPos
}
return if (closestPos.second != BlockPos.ORIGIN) closestPos.second else null
}
private fun checkPos(pos: BlockPos, facingIn: EnumFacing): Boolean {
if (CrystalUtils.canPlaceOn(pos) && mc.world.isAirBlock(pos.up())) return true
for (facing in EnumFacing.HORIZONTALS) {
if (facing == facingIn.opposite) continue
if (!CrystalUtils.canPlace(pos.offset(facing))) continue
return true
}
return false
}
}

View File

@ -0,0 +1,61 @@
package me.zeroeightsix.kami.module.modules.combat
import me.zeroeightsix.kami.module.Module
import me.zeroeightsix.kami.module.modules.movement.Strafe
import me.zeroeightsix.kami.setting.Settings
import me.zeroeightsix.kami.util.combat.SurroundUtils
import me.zeroeightsix.kami.util.math.RotationUtils
import me.zeroeightsix.kami.util.math.VectorUtils
import me.zeroeightsix.kami.util.math.VectorUtils.toBlockPos
import me.zeroeightsix.kami.util.math.VectorUtils.toVec3d
import net.minecraft.util.math.BlockPos
import kotlin.math.*
@Module.Info(
name = "HoleSnap",
description = "Move you into the hole nearby",
category = Module.Category.COMBAT
)
object HoleSnap : Module() {
private val disableStrafe = register(Settings.b("DisableStrafe",true))
private val range = register(Settings.floatBuilder("Range").withValue(2.5f).withRange(0f, 5f))
override fun onEnable() {
if (mc.player == null) disable()
}
override fun onUpdate() {
if (SurroundUtils.checkHole(mc.player) != SurroundUtils.HoleType.NONE) {
disable()
return
}
findHole()?.toVec3d()?.let {
if (disableStrafe.value) Strafe.disable()
if (mc.player.onGround) {
val yawRad = Math.toRadians(RotationUtils.getRotationTo(mc.player.positionVector, it).x)
val speed = min(0.25, mc.player.positionVector.distanceTo(it) / 4.0)
mc.player.motionX = -sin(yawRad) * speed
mc.player.motionZ = cos(yawRad) * speed
}
if (mc.player.motionY <= 0.01) mc.player.motionY = -0.5
}
}
private fun findHole(): BlockPos? {
var closestHole = Pair(69.69, BlockPos.ORIGIN)
val playerPos = mc.player.positionVector.toBlockPos()
val ceilRange = ceil(range.value).toInt()
val posList = VectorUtils.getBlockPositionsInArea(playerPos.add(ceilRange, -1, ceilRange), playerPos.add(-ceilRange, -1, -ceilRange))
for (posXZ in posList) {
val dist = mc.player.getDistanceSqToCenter(posXZ)
if (dist > range.value.pow(2) || dist > closestHole.first) continue
for (posY in 0..5) {
val pos = posXZ.add(0, -posY, 0)
if (!mc.world.isAirBlock(pos.up())) break
if (SurroundUtils.checkHole(pos) == SurroundUtils.HoleType.NONE) continue
closestHole = dist to pos
}
}
return if (closestHole.second != BlockPos.ORIGIN) closestHole.second else null
}
}

View File

@ -1,170 +0,0 @@
package me.zeroeightsix.kami.module.modules.combat;
import me.zero.alpine.listener.EventHandler;
import me.zero.alpine.listener.Listener;
import me.zeroeightsix.kami.event.events.GuiScreenEvent;
import me.zeroeightsix.kami.event.events.PacketEvent;
import me.zeroeightsix.kami.module.Module;
import me.zeroeightsix.kami.setting.Setting;
import me.zeroeightsix.kami.setting.Settings;
import me.zeroeightsix.kami.util.InventoryUtils;
import net.minecraft.entity.item.EntityEnderCrystal;
import net.minecraft.init.Items;
import net.minecraft.inventory.ClickType;
import net.minecraft.item.*;
import net.minecraft.network.play.client.CPacketPlayerTryUseItem;
import java.util.Comparator;
import java.util.Objects;
@Module.Info(
name = "OffhandGap",
category = Module.Category.COMBAT,
description = "Holds a God apple when right clicking your sword!"
)
public class OffhandGap extends Module {
private final Setting<Double> disableHealth = register(Settings.doubleBuilder("DisableHealth").withMinimum(0.0).withValue(4.0).withMaximum(20.0).build());
private final Setting<Boolean> eatWhileAttacking = register(Settings.b("EatWhileAttacking", false));
private final Setting<Boolean> swordOrAxeOnly = register(Settings.b("SwordAndAxeOnly", true));
private final Setting<Boolean> preferBlocks = register(Settings.booleanBuilder("PreferPlacingBlocks").withValue(false).withVisibility(v -> !swordOrAxeOnly.getValue()).build());
private final Setting<Boolean> crystalCheck = register(Settings.b("CrystalCheck", false));
private int gaps = -1;
private boolean autoTotemWasEnabled = false;
private boolean cancelled = false;
private boolean isGuiOpened = false;
private Item usedItem;
public static OffhandGap INSTANCE;
public OffhandGap() {
super();
INSTANCE = this;
}
@EventHandler
public Listener<GuiScreenEvent.Displayed> listener = new Listener<>(event ->
isGuiOpened = event.getScreen() != null
);
@EventHandler
private final Listener<PacketEvent.Send> sendListener = new Listener<>(e -> {
if (e.getPacket() instanceof CPacketPlayerTryUseItem) {
if (cancelled) {
disableGaps();
return;
}
if (mc.player.getHeldItemMainhand().getItem() instanceof ItemSword || mc.player.getHeldItemMainhand().getItem() instanceof ItemAxe || passItemCheck()) {
if (AutoTotem.INSTANCE.isEnabled()) {
autoTotemWasEnabled = true;
AutoTotem.INSTANCE.disable();
}
if (!eatWhileAttacking.getValue()) { /* Save item for later when using preventDesync */
usedItem = mc.player.getHeldItemMainhand().getItem();
}
enableGaps(gaps);
}
}
try {
/* If you stop holding right click move totem back */
if (!mc.gameSettings.keyBindUseItem.isKeyDown() && mc.player.getHeldItemOffhand().getItem() == Items.GOLDEN_APPLE)
disableGaps();
/* In case you didn't stop right clicking but you switched items by scrolling or something */
else if ((usedItem != mc.player.getHeldItemMainhand().getItem()) && mc.player.getHeldItemOffhand().getItem() == Items.GOLDEN_APPLE) {
if (!eatWhileAttacking.getValue()) {
usedItem = mc.player.getHeldItemMainhand().getItem();
disableGaps();
}
}
/* Force disable if under health limit */
else if (mc.player.getHealth() + mc.player.getAbsorptionAmount() <= disableHealth.getValue()) {
disableGaps();
}
/* Disable if there are crystals in the range of CrystalAura */
if (crystalCheck.getValue() && CrystalAura.INSTANCE.isEnabled()) {
EntityEnderCrystal crystal = mc.world.loadedEntityList.stream()
.filter(entity -> entity instanceof EntityEnderCrystal)
.map(entity -> (EntityEnderCrystal) entity)
.min(Comparator.comparing(c -> mc.player.getDistance(c)))
.orElse(null);
if (Objects.requireNonNull(crystal).getPosition().distanceSq(mc.player.getPosition().x, mc.player.getPosition().y, mc.player.getPosition().z) <= CrystalAura.INSTANCE.range.getValue()) {
disableGaps();
}
}
} catch (NullPointerException ignored) { }
});
@Override
public void onUpdate() {
if (mc.player == null) return;
/* If your health doesn't meet the cutoff then set it to true */
cancelled = mc.player.getHealth() + mc.player.getAbsorptionAmount() <= disableHealth.getValue();
if (cancelled) {
disableGaps();
return;
}
if (mc.player.getHeldItemOffhand().getItem() != Items.GOLDEN_APPLE) {
for (int i = 0; i < 45; i++) {
if (mc.player.inventory.getStackInSlot(i).getItem() == Items.GOLDEN_APPLE) {
gaps = i;
break;
}
}
}
}
/* If weaponCheck is disabled, check if they're not holding an item you'd want to use normally */
private boolean passItemCheck() {
if (swordOrAxeOnly.getValue()) return false;
else {
Item item = mc.player.getHeldItemMainhand().getItem();
if (item instanceof ItemBow) return false;
if (item instanceof ItemSnowball) return false;
if (item instanceof ItemEgg) return false;
if (item instanceof ItemPotion) return false;
if (item instanceof ItemEnderEye) return false;
if (item instanceof ItemEnderPearl) return false;
if (item instanceof ItemFood) return false;
if (item instanceof ItemShield) return false;
if (item instanceof ItemFlintAndSteel) return false;
if (item instanceof ItemFishingRod) return false;
if (item instanceof ItemArmor) return false;
if (item instanceof ItemExpBottle) return false;
return !preferBlocks.getValue() || !(item instanceof ItemBlock);
}
}
private void disableGaps() {
if (autoTotemWasEnabled != AutoTotem.INSTANCE.isEnabled()) {
moveGapsWaitForNoGui();
AutoTotem.INSTANCE.enable();
autoTotemWasEnabled = false;
}
}
private void enableGaps(int slot) {
if (mc.player.getHeldItemOffhand().getItem() != Items.GOLDEN_APPLE) {
mc.playerController.windowClick(0, slot < 9 ? slot + 36 : slot, 0, ClickType.PICKUP, mc.player);
mc.playerController.windowClick(0, 45, 0, ClickType.PICKUP, mc.player);
}
}
private void moveGapsToInventory(int slot) {
if (mc.player.getHeldItemOffhand().getItem() == Items.GOLDEN_APPLE) {
mc.playerController.windowClick(0, 45, 0, ClickType.PICKUP, mc.player);
mc.playerController.windowClick(0, slot < 9 ? slot + 36 : slot, 0, ClickType.PICKUP, mc.player);
}
}
private void moveGapsWaitForNoGui() {
if (isGuiOpened) return;
moveGapsToInventory(gaps);
}
@Override
public String getHudInfo() {
return "" + InventoryUtils.countItemAll(322);
}
}

View File

@ -1,280 +1,215 @@
package me.zeroeightsix.kami.module.modules.combat
import me.zeroeightsix.kami.manager.mangers.CombatManager
import me.zeroeightsix.kami.manager.mangers.PlayerPacketManager
import me.zeroeightsix.kami.module.Module
import me.zeroeightsix.kami.module.modules.player.NoBreakAnimation
import me.zeroeightsix.kami.module.modules.movement.Strafe
import me.zeroeightsix.kami.setting.Setting
import me.zeroeightsix.kami.setting.Settings
import me.zeroeightsix.kami.util.BlockUtils
import me.zeroeightsix.kami.util.CenterPlayer
import me.zeroeightsix.kami.util.InventoryUtils
import me.zeroeightsix.kami.util.MovementUtils
import me.zeroeightsix.kami.util.TimerUtils
import me.zeroeightsix.kami.util.combat.SurroundUtils
import me.zeroeightsix.kami.util.math.VectorUtils.toBlockPos
import me.zeroeightsix.kami.util.text.MessageSendHelper
import net.minecraft.block.Block
import net.minecraft.block.BlockObsidian
import net.minecraft.block.state.IBlockState
import net.minecraft.item.ItemBlock
import net.minecraft.item.ItemStack
import net.minecraft.network.play.client.CPacketAnimation
import net.minecraft.network.play.client.CPacketEntityAction
import net.minecraft.network.play.client.CPacketHeldItemChange
import net.minecraft.network.play.client.CPacketPlayer
import net.minecraft.util.EnumFacing
import net.minecraft.util.EnumHand
import net.minecraft.util.math.BlockPos
import net.minecraft.util.math.MathHelper
import net.minecraft.util.math.Vec3d
import kotlin.math.atan2
import kotlin.math.floor
import kotlin.math.sqrt
import java.util.concurrent.Executors
import java.util.concurrent.Future
import kotlin.math.round
@Module.Info(
name = "Surround",
category = Module.Category.COMBAT,
description = "Surrounds you with obsidian to take less damage"
description = "Surrounds you with obsidian to take less damage",
modulePriority = 200
)
object Surround : Module() {
val autoDisable: Setting<Boolean> = register(Settings.b("DisableOnPlace", true))
private val spoofRotations = register(Settings.b("SpoofRotations", true))
private val spoofHotbar = register(Settings.b("SpoofHotbar", false))
private val blockPerTick = register(Settings.doubleBuilder("BlocksPerTick").withMinimum(1.0).withValue(4.0).withMaximum(10.0).build())
private val debugMsgs = register(Settings.e<DebugMsgs>("DebugMessages", DebugMsgs.IMPORTANT))
private val autoCenter = register(Settings.b("AutoCenter", true))
private val placeAnimation = register(Settings.b("PlaceAnimation", false))
private val autoCenter = register(Settings.e<AutoCenterMode>("AutoCenter", AutoCenterMode.MOTION))
private val placeSpeed = register(Settings.floatBuilder("PlacesPerTick").withValue(4f).withRange(0.25f, 5f).withStep(0.25f))
private val autoDisable = register(Settings.e<AutoDisableMode>("AutoDisable", AutoDisableMode.OUT_OF_HOLE))
private val outOfHoleTimeout = register(Settings.integerBuilder("OutOfHoleTimeout(t)").withValue(20).withRange(1, 50).withVisibility { autoDisable.value == AutoDisableMode.OUT_OF_HOLE })
private val enableInHole = register(Settings.b("EnableInHole", true))
private val inHoleTimeout = register(Settings.integerBuilder("InHoleTimeout(t)").withValue(50).withRange(1, 100).withVisibility { enableInHole.value })
private val disableStrafe = register(Settings.b("DisableStrafe", true))
private val surroundTargets = arrayOf(Vec3d(0.0, 0.0, 0.0), Vec3d(1.0, 1.0, 0.0), Vec3d(0.0, 1.0, 1.0), Vec3d(-1.0, 1.0, 0.0), Vec3d(0.0, 1.0, -1.0), Vec3d(1.0, 0.0, 0.0), Vec3d(0.0, 0.0, 1.0), Vec3d(-1.0, 0.0, 0.0), Vec3d(0.0, 0.0, -1.0), Vec3d(1.0, 1.0, 0.0), Vec3d(0.0, 1.0, 1.0), Vec3d(-1.0, 1.0, 0.0), Vec3d(0.0, 1.0, -1.0))
enum class AutoCenterMode {
OFF, TP, MOTION
}
private var basePos: BlockPos? = null
private var offsetStep = 0
private var playerHotbarSlot = -1
private var lastHotbarSlot = -1
enum class AutoDisableMode {
ONE_TIME, OUT_OF_HOLE
}
@Suppress("UNUSED")
private enum class DebugMsgs {
NONE, IMPORTANT, ALL
private var holePos: BlockPos? = null
private var toggleTimer = TimerUtils.StopTimer(TimerUtils.TimeUnit.TICKS)
private val placeThread = Thread { runSurround() }.apply { name = "Surround" }
private val threadPool = Executors.newSingleThreadExecutor()
private var future: Future<*>? = null
private var strafeEnabled = false
override fun onEnable() {
toggleTimer.reset()
mc.player?.setVelocity(0.0, -5.0, 0.0)
}
override fun onDisable() {
PlayerPacketManager.resetHotbar()
toggleTimer.reset()
holePos = null
if (strafeEnabled && disableStrafe.value) {
Strafe.enable()
strafeEnabled = false
}
}
override fun isActive(): Boolean {
return isEnabled && future?.isDone == false
}
// Runs the codes on rendering for more immediate reaction
override fun onRender() {
if (mc.world == null || mc.player == null) return
if (getObby() == -1) return
if (isDisabled) {
enableInHoleCheck()
return
}
// Following codes will not run if disabled
if (!mc.player.onGround || mc.player.positionVector.toBlockPos() != holePos) { // Out of hole check
outOfHoleCheck()
return
} else {
toggleTimer.reset()
}
if (!isPlaceable() || !centerPlayer()) { // Placeable & Centered check
if (!isPlaceable() && autoDisable.value == AutoDisableMode.ONE_TIME) disable()
return
}
if (future?.isDone != false) future = threadPool.submit(placeThread)
}
override fun onUpdate() {
if (autoCenter.value && (mc.player.posX != CenterPlayer.getPosX(1.0f) || mc.player.posZ != CenterPlayer.getPosZ(1.0f))) {
CenterPlayer.centerPlayer(1.0f)
if (debugMsgs.value == DebugMsgs.ALL) MessageSendHelper.sendChatMessage("$chatName Auto centering. Player position is " + mc.player.positionVector.toString())
if (isEnabled && holePos == null && centerPlayer()) holePos = mc.player.positionVector.toBlockPos()
if (future?.isDone == false && future?.isCancelled == false) {
val slot = getObby()
if (slot != -1) PlayerPacketManager.spoofHotbar(getObby())
PlayerPacketManager.addPacket(this, PlayerPacketManager.PlayerPacket(rotating = false))
} else if (isEnabled && CombatManager.isOnTopPriority(this)) {
PlayerPacketManager.resetHotbar()
}
}
private fun enableInHoleCheck() {
if (enableInHole.value && mc.player.onGround && MovementUtils.getSpeed() < 0.15 && SurroundUtils.checkHole(mc.player) != SurroundUtils.HoleType.NONE) {
if (toggleTimer.stop() > inHoleTimeout.value) {
MessageSendHelper.sendChatMessage("$chatName You are in hole for longer than ${inHoleTimeout.value} ticks, enabling")
enable()
}
} else {
if (offsetStep == 0) {
basePos = BlockPos(mc.player.positionVector).down()
playerHotbarSlot = mc.player.inventory.currentItem
if (debugMsgs.value == DebugMsgs.ALL) {
MessageSendHelper.sendChatMessage("$chatName Starting Loop, current Player Slot: $playerHotbarSlot")
}
if (!spoofHotbar.value) {
lastHotbarSlot = mc.player.inventory.currentItem
}
}
for (i in 0 until floor(blockPerTick.value).toInt()) {
if (debugMsgs.value == DebugMsgs.ALL) {
MessageSendHelper.sendChatMessage("$chatName Loop iteration: $offsetStep")
}
if (offsetStep >= surroundTargets.size) {
endLoop()
return
}
val offset = surroundTargets[offsetStep]
placeBlock(BlockPos(basePos!!.add(offset.x, offset.y, offset.z)))
++offsetStep
toggleTimer.reset()
}
}
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")
disable()
}
}
}
public override fun onEnable() {
if (mc.player == null) return
if (autoCenter.value) {
CenterPlayer.centerPlayer(0.5f)
if (debugMsgs.value == DebugMsgs.ALL) MessageSendHelper.sendChatMessage("$chatName Auto centering. Player position is " + mc.player.positionVector.toString())
}
playerHotbarSlot = mc.player.inventory.currentItem
lastHotbarSlot = -1
if (debugMsgs.value == DebugMsgs.ALL) {
MessageSendHelper.sendChatMessage("$chatName Saving initial Slot = $playerHotbarSlot")
private fun getObby(): Int {
val slots = InventoryUtils.getSlotsHotbar(49)
if (slots == null) { // Obsidian check
if (isEnabled) {
MessageSendHelper.sendChatMessage("$chatName No obsidian in hotbar, disabling!")
disable()
}
return -1
}
return slots[0]
}
public override fun onDisable() {
if (mc.player != null) {
if (debugMsgs.value == DebugMsgs.ALL) {
MessageSendHelper.sendChatMessage("$chatName Disabling")
}
private fun isPlaceable(): Boolean {
val playerPos = mc.player.positionVector.toBlockPos()
for (offset in SurroundUtils.surroundOffset) {
val pos = playerPos.add(offset)
if (BlockUtils.isPlaceable(pos)) return true
}
return false
}
if (lastHotbarSlot != playerHotbarSlot && playerHotbarSlot != -1) {
if (spoofHotbar.value) {
mc.player.connection.sendPacket(CPacketHeldItemChange(playerHotbarSlot))
private fun centerPlayer(): Boolean {
return if (autoCenter.value == AutoCenterMode.OFF) {
true
} else {
if (disableStrafe.value) {
strafeEnabled = Strafe.isEnabled
Strafe.disable()
}
val centerDiff = getCenterDiff()
val centered = isCentered()
if (!centered) {
mc.player.setVelocity(0.0, -5.0, 0.0)
if (autoCenter.value == AutoCenterMode.TP) {
val posX = mc.player.posX + MathHelper.clamp(centerDiff.x, -0.2, 0.2)
val posZ = mc.player.posZ + MathHelper.clamp(centerDiff.z, -0.2, 0.2)
mc.player.setPosition(posX, mc.player.posY, posZ)
} else {
mc.player.inventory.currentItem = playerHotbarSlot
mc.player.motionX = MathHelper.clamp(centerDiff.x / 2.0, -0.2, 0.2)
mc.player.motionZ = MathHelper.clamp(centerDiff.z / 2.0, -0.2, 0.2)
}
}
playerHotbarSlot = -1
lastHotbarSlot = -1
centered
}
}
private fun endLoop() {
offsetStep = 0
private fun isCentered(): Boolean {
return getCenterDiff().length() < 0.2
}
if (debugMsgs.value == DebugMsgs.ALL) {
MessageSendHelper.sendChatMessage("$chatName Ending Loop")
}
private fun getCenterDiff(): Vec3d {
return Vec3d(roundToCenter(mc.player.posX), mc.player.posY, roundToCenter(mc.player.posZ)).subtract(mc.player.positionVector)
}
if (lastHotbarSlot != playerHotbarSlot && playerHotbarSlot != -1) {
if (debugMsgs.value == DebugMsgs.ALL) {
MessageSendHelper.sendChatMessage("$chatName Setting Slot back to = $playerHotbarSlot")
}
if (spoofHotbar.value) {
mc.player.connection.sendPacket(CPacketHeldItemChange(playerHotbarSlot))
private fun roundToCenter(doubleIn: Double): Double {
return round(doubleIn + 0.5) - 0.5
}
private fun runSurround() {
BlockUtils.buildStructure(placeSpeed.value) {
if (isEnabled && CombatManager.isOnTopPriority(this)) {
BlockUtils.getPlaceInfo(mc.player.positionVector.toBlockPos(), SurroundUtils.surroundOffset, it, 2)
} else {
mc.player.inventory.currentItem = playerHotbarSlot
}
lastHotbarSlot = playerHotbarSlot
}
if (autoDisable.value) {
disable()
}
}
private fun placeBlock(blockPos: BlockPos) {
if (!mc.world.getBlockState(blockPos).material.isReplaceable) {
if (debugMsgs.value == DebugMsgs.ALL) {
MessageSendHelper.sendChatMessage("$chatName Block is already placed, skipping")
}
} else if (!BlockUtils.checkForNeighbours(blockPos) && debugMsgs.value == DebugMsgs.ALL) {
MessageSendHelper.sendChatMessage("$chatName !checkForNeighbours(blockPos), disabling! ")
} else {
if (placeAnimation.value) mc.player.connection.sendPacket(CPacketAnimation(mc.player.activeHand))
placeBlockExecute(blockPos)
}
if (NoBreakAnimation.isEnabled) NoBreakAnimation.resetMining()
}
private fun findObiInHotbar(): Int {
var slot = -1
for (i in 0..8) {
val stack = mc.player.inventory.getStackInSlot(i)
if (stack != ItemStack.EMPTY && stack.getItem() is ItemBlock) {
val block = (stack.getItem() as ItemBlock).block
if (block is BlockObsidian) {
slot = i
break
}
}
}
return slot
}
private fun placeBlockExecute(pos: BlockPos) {
val eyesPos = Vec3d(mc.player.posX, mc.player.posY + mc.player.getEyeHeight().toDouble(), mc.player.posZ)
val var3 = EnumFacing.values()
for (side in var3) {
val neighbor = pos.offset(side)
val side2 = side.opposite
if (!canBeClicked(neighbor)) {
if (debugMsgs.value == DebugMsgs.ALL) {
MessageSendHelper.sendChatMessage("$chatName No neighbor to click at!")
}
} else {
val hitVec = Vec3d(neighbor).add(0.5, 0.5, 0.5).add(Vec3d(side2.directionVec).scale(0.5))
if (eyesPos.squareDistanceTo(hitVec) <= 18.0625) {
if (spoofRotations.value) {
faceVectorPacketInstant(hitVec)
}
var needSneak = false
val blockBelow = mc.world.getBlockState(neighbor).block
if (BlockUtils.blackList.contains(blockBelow) || BlockUtils.shulkerList.contains(blockBelow)) {
if (debugMsgs.value == DebugMsgs.IMPORTANT) {
MessageSendHelper.sendChatMessage("$chatName Sneak enabled!")
}
needSneak = true
}
if (needSneak) {
mc.player.connection.sendPacket(CPacketEntityAction(mc.player, CPacketEntityAction.Action.START_SNEAKING))
}
val obiSlot = findObiInHotbar()
if (obiSlot == -1) {
if (debugMsgs.value == DebugMsgs.IMPORTANT) {
MessageSendHelper.sendChatMessage("$chatName No obsidian in hotbar, disabling!")
}
disable()
return
}
if (lastHotbarSlot != obiSlot) {
if (debugMsgs.value == DebugMsgs.ALL) {
MessageSendHelper.sendChatMessage("$chatName Setting Slot to obsidian at = $obiSlot")
}
if (spoofHotbar.value) {
mc.player.connection.sendPacket(CPacketHeldItemChange(obiSlot))
} else {
mc.player.inventory.currentItem = obiSlot
}
lastHotbarSlot = obiSlot
}
mc.playerController.processRightClickBlock(mc.player, mc.world, neighbor, side2, hitVec, EnumHand.MAIN_HAND)
mc.player.connection.sendPacket(CPacketAnimation(EnumHand.MAIN_HAND))
if (needSneak) {
if (debugMsgs.value == DebugMsgs.IMPORTANT) {
MessageSendHelper.sendChatMessage("$chatName Sneak disabled!")
}
mc.player.connection.sendPacket(CPacketEntityAction(mc.player, CPacketEntityAction.Action.STOP_SNEAKING))
}
return
}
if (debugMsgs.value == DebugMsgs.ALL) {
MessageSendHelper.sendChatMessage("$chatName Distance > 4.25 blocks!")
}
null
}
}
}
private fun canBeClicked(pos: BlockPos): Boolean {
return getBlock(pos).canCollideCheck(getState(pos), false)
private fun getPlaceInfo(toIgnore: List<BlockPos>, attempts: Int = 1): Pair<EnumFacing, BlockPos>? {
val playerPos = mc.player.positionVector.toBlockPos()
for (offset in SurroundUtils.surroundOffset) {
val pos = playerPos.add(offset)
if (toIgnore.contains(pos)) continue
if (!BlockUtils.isPlaceable(pos)) continue
return BlockUtils.getNeighbour(pos, attempts) ?: continue
}
if (attempts <= 2) {
return getPlaceInfo(toIgnore, attempts + 1)
}
return null
}
fun getBlock(pos: BlockPos): Block {
return getState(pos).block
init {
alwaysListening = enableInHole.value
enableInHole.settingListener = Setting.SettingListeners {
alwaysListening = enableInHole.value
}
}
private fun getState(pos: BlockPos): IBlockState {
return mc.world.getBlockState(pos)
}
private fun faceVectorPacketInstant(vec: Vec3d) {
val rotations = getLegitRotations(vec)
mc.player.connection.sendPacket(CPacketPlayer.Rotation(rotations[0], rotations[1], mc.player.onGround))
}
private fun getLegitRotations(vec: Vec3d): FloatArray {
val eyesPos = eyesPos
val diffX = vec.x - eyesPos.x
val diffY = vec.y - eyesPos.y
val diffZ = vec.z - eyesPos.z
val diffXZ = sqrt(diffX * diffX + diffZ * diffZ)
val yaw = Math.toDegrees(atan2(diffZ, diffX)).toFloat() - 90.0f
val pitch = (-Math.toDegrees(atan2(diffY, diffXZ))).toFloat()
return floatArrayOf(mc.player.rotationYaw + MathHelper.wrapDegrees(yaw - mc.player.rotationYaw), mc.player.rotationPitch + MathHelper.wrapDegrees(pitch - mc.player.rotationPitch))
}
private val eyesPos: Vec3d
get() = Vec3d(mc.player.posX, mc.player.posY + mc.player.getEyeHeight().toDouble(), mc.player.posZ)
}

View File

@ -4,17 +4,13 @@ import me.zero.alpine.listener.EventHandler
import me.zero.alpine.listener.EventHook
import me.zero.alpine.listener.Listener
import me.zeroeightsix.kami.module.Module
import me.zeroeightsix.kami.module.modules.combat.Aura.HitMode
import me.zeroeightsix.kami.setting.Setting
import me.zeroeightsix.kami.setting.Settings
import me.zeroeightsix.kami.util.combat.CombatUtils
import net.minecraft.block.state.IBlockState
import net.minecraft.enchantment.EnchantmentHelper
import net.minecraft.entity.EntityLivingBase
import net.minecraft.entity.EnumCreatureAttribute
import net.minecraft.init.Enchantments
import net.minecraft.item.ItemAxe
import net.minecraft.item.ItemSword
import net.minecraft.item.ItemTool
import net.minecraftforge.event.entity.player.AttackEntityEvent
import net.minecraftforge.event.entity.player.PlayerInteractEvent.LeftClickBlock
import org.lwjgl.input.Mouse
@ -29,7 +25,7 @@ object AutoTool : Module() {
private val switchBack = register(Settings.b("SwitchBack", true))
private val timeout = register(Settings.integerBuilder("Timeout").withRange(1, 100).withValue(20).withVisibility { switchBack.value }.build())
private val swapWeapon = register(Settings.b("SwitchWeapon", false))
private val preferWeapon = register(Settings.e<HitMode>("PreferWeapom", HitMode.SWORD))
private val preferWeapon = register(Settings.e<CombatUtils.PreferWeapon>("Prefer", CombatUtils.PreferWeapon.SWORD))
private var shouldMoveBack = false
private var lastSlot = 0
@ -43,7 +39,7 @@ object AutoTool : Module() {
@EventHandler
private val attackListener = Listener(EventHook { event: AttackEntityEvent ->
if (event.target !is EntityLivingBase) return@EventHook
if (swapWeapon.value) equipBestWeapon(preferWeapon.value)
if (swapWeapon.value) CombatUtils.equipBestWeapon(preferWeapon.value)
})
override fun onUpdate() {
@ -83,39 +79,6 @@ object AutoTool : Module() {
if (bestSlot != -1) equip(bestSlot)
}
@JvmStatic
fun equipBestWeapon(hitMode: HitMode) {
var bestSlot = -1
var maxDamage = 0.0
for (i in 0..8) {
val stack = mc.player.inventory.getStackInSlot(i)
if (stack.isEmpty) continue
if (stack.getItem() !is ItemAxe && hitMode == HitMode.AXE) continue
if (stack.getItem() !is ItemSword && hitMode == HitMode.SWORD) continue
if (stack.getItem() is ItemSword && (hitMode == HitMode.SWORD || hitMode == HitMode.NONE)) {
val damage = (stack.getItem() as ItemSword).attackDamage + EnchantmentHelper.getModifierForCreature(stack, EnumCreatureAttribute.UNDEFINED).toDouble()
if (damage > maxDamage) {
maxDamage = damage
bestSlot = i
}
} else if (stack.getItem() is ItemAxe && (hitMode == HitMode.AXE || hitMode == HitMode.NONE)) {
val damage = (stack.getItem() as ItemTool).attackDamage + EnchantmentHelper.getModifierForCreature(stack, EnumCreatureAttribute.UNDEFINED).toDouble()
if (damage > maxDamage) {
maxDamage = damage
bestSlot = i
}
} else if (stack.getItem() is ItemTool) {
val damage = (stack.getItem() as ItemTool).attackDamage + EnchantmentHelper.getModifierForCreature(stack, EnumCreatureAttribute.UNDEFINED).toDouble()
if (damage > maxDamage) {
maxDamage = damage
bestSlot = i
}
}
}
if (bestSlot != -1) equip(bestSlot)
}
private fun equip(slot: Int) {
mc.player.inventory.currentItem = slot
mc.playerController.syncCurrentPlayItem()

View File

@ -45,7 +45,7 @@ object AutoEat : Module() {
}
override fun onUpdate() {
if (Aura.isEnabled && Aura.isAttacking) return
if (Aura.isActive()) return
if (eating && !mc.player.isHandActive) {
if (lastSlot != -1) {

View File

@ -88,10 +88,10 @@ object Scaffold : Module() {
setSlotToBlocks(belowBlockPos)
/* check if we don't have a block adjacent to the blockPos */
if (!BlockUtils.checkForNeighbours(blockPos)) return
val neighbor = BlockUtils.getNeighbour(blockPos, attempts = 1)?: return
/* place the block */
if (placeBlocks.value) BlockUtils.placeBlockScaffold(blockPos)
if (placeBlocks.value) BlockUtils.placeBlock(neighbor.second, neighbor.first)
/* Reset the slot */
if (!holding) mc.player.inventory.currentItem = oldSlot

View File

@ -114,7 +114,7 @@ object ESP : Module() {
entityList.add(entity)
}
} else {
entityList.addAll(getTargetList(player, mob, true, invisible.value, range.value.toFloat()))
entityList.addAll(getTargetList(player, mob, invisible.value, range.value.toFloat()))
for (entity in mc.world.loadedEntityList) {
if (entity == mc.player) continue
if (mc.player.getDistance(entity) > range.value) continue

View File

@ -62,9 +62,9 @@ object EyeFinder : Module() {
val player = arrayOf(players.value, friends.value, sleeping.value)
val mob = arrayOf(mobs.value, passive.value, neutral.value, hostile.value)
val entityList = if (isEnabled) {
getTargetList(player, mob, true, invisible.value, range.value.toFloat())
getTargetList(player, mob, invisible.value, range.value.toFloat())
} else {
emptyArray()
ArrayList()
}
val cacheMap = HashMap<Entity, Pair<RayTraceResult, Float>>()
for (entity in entityList) {

View File

@ -78,9 +78,9 @@ object Tracers : Module() {
val player = arrayOf(players.value, friends.value, sleeping.value)
val mob = arrayOf(mobs.value, passive.value, neutral.value, hostile.value)
val entityList = if (isEnabled) {
getTargetList(player, mob, true, invisible.value, range.value.toFloat())
getTargetList(player, mob, invisible.value, range.value.toFloat())
} else {
emptyArray()
ArrayList()
}
val cacheMap = HashMap<Entity, Pair<ColorHolder, Float>>()

View File

@ -1,18 +1,17 @@
package me.zeroeightsix.kami.util
import net.minecraft.block.Block
import net.minecraft.block.state.IBlockState
import me.zeroeightsix.kami.util.math.RotationUtils
import net.minecraft.client.Minecraft
import net.minecraft.init.Blocks
import net.minecraft.network.play.client.CPacketPlayer
import net.minecraft.network.play.client.CPacketPlayerTryUseItemOnBlock
import net.minecraft.util.EnumFacing
import net.minecraft.util.EnumHand
import net.minecraft.util.math.AxisAlignedBB
import net.minecraft.util.math.BlockPos
import net.minecraft.util.math.MathHelper
import net.minecraft.util.math.RayTraceResult
import net.minecraft.util.math.Vec3d
import kotlin.math.atan2
import kotlin.math.floor
import kotlin.math.sqrt
/**
* Created by hub on 15/06/19
@ -20,7 +19,6 @@ import kotlin.math.sqrt
* Updated by Xiaro on 22/08/20
*/
object BlockUtils {
@JvmField
val blackList = listOf(
Blocks.ENDER_CHEST,
Blocks.CHEST,
@ -35,7 +33,6 @@ object BlockUtils {
Blocks.ENCHANTING_TABLE
)
@JvmField
val shulkerList = listOf(
Blocks.WHITE_SHULKER_BOX,
Blocks.ORANGE_SHULKER_BOX,
@ -55,100 +52,22 @@ object BlockUtils {
Blocks.BLACK_SHULKER_BOX
)
@JvmField
val surroundOffset = arrayOf(
BlockPos(0, -1, 0), // down
BlockPos(0, 0, -1), // north
BlockPos(1, 0, 0), // east
BlockPos(0, 0, 1), // south
BlockPos(-1, 0, 0) // west
)
private val mc = Minecraft.getMinecraft()
fun placeBlockScaffold(pos: BlockPos) {
val eyesPos = Vec3d(mc.player.posX,
mc.player.posY + mc.player.getEyeHeight(),
mc.player.posZ)
for (side in EnumFacing.values()) {
val neighbor = pos.offset(side)
val side2 = side.opposite
// check if neighbor can be right clicked
if (!canBeClicked(neighbor)) {
continue
}
val hitVec = Vec3d(neighbor).add(0.5, 0.5, 0.5)
.add(Vec3d(side2.directionVec).scale(0.5))
// check if hitVec is within range (4.25 blocks)
if (eyesPos.squareDistanceTo(hitVec) > 18.0625) {
continue
}
// place block
faceVectorPacketInstant(hitVec)
processRightClickBlock(neighbor, side2, hitVec)
mc.player.swingArm(EnumHand.MAIN_HAND)
mc.rightClickDelayTimer = 4
return
}
fun placeBlock(pos: BlockPos, facing: EnumFacing) {
val hitVecOffset = getHitVecOffset(facing)
val rotation = RotationUtils.getRotationTo(Vec3d(pos).add(hitVecOffset), true)
val rotationPacket = CPacketPlayer.PositionRotation(mc.player.posX, mc.player.posY, mc.player.posZ, rotation.x.toFloat(), rotation.y.toFloat(), mc.player.onGround)
val placePacket = CPacketPlayerTryUseItemOnBlock(pos, facing, EnumHand.MAIN_HAND, hitVecOffset.x.toFloat(), hitVecOffset.y.toFloat(), hitVecOffset.z.toFloat())
mc.connection!!.sendPacket(rotationPacket)
mc.connection!!.sendPacket(placePacket)
mc.player.swingArm(EnumHand.MAIN_HAND)
}
private fun getLegitRotations(vec: Vec3d): FloatArray {
val eyesPos = eyesPos
val diffX = vec.x - eyesPos.x
val diffY = vec.y - eyesPos.y
val diffZ = vec.z - eyesPos.z
val diffXZ = sqrt(diffX * diffX + diffZ * diffZ)
val yaw = Math.toDegrees(atan2(diffZ, diffX)).toFloat() - 90f
val pitch = (-Math.toDegrees(atan2(diffY, diffXZ))).toFloat()
return floatArrayOf(mc.player.rotationYaw
+ MathHelper.wrapDegrees(yaw - mc.player.rotationYaw),
mc.player.rotationPitch + MathHelper
.wrapDegrees(pitch - mc.player.rotationPitch))
}
private val eyesPos = Vec3d(mc.player.posX, mc.player.posY + mc.player.getEyeHeight(), mc.player.posZ)
@JvmStatic
fun faceVectorPacketInstant(vec: Vec3d) {
val rotations = getLegitRotations(vec)
mc.player.connection.sendPacket(CPacketPlayer.Rotation(rotations[0],
rotations[1], mc.player.onGround))
}
private fun processRightClickBlock(pos: BlockPos, side: EnumFacing, hitVec: Vec3d) {
mc.playerController.processRightClickBlock(mc.player,
mc.world, pos, side, hitVec, EnumHand.MAIN_HAND)
}
@JvmStatic
fun canBeClicked(pos: BlockPos): Boolean {
return getBlock(pos).canCollideCheck(getState(pos), false)
}
private fun getBlock(pos: BlockPos): Block {
return getState(pos).block
}
private fun getState(pos: BlockPos): IBlockState {
return mc.world.getBlockState(pos)
}
fun checkForNeighbours(blockPos: BlockPos): Boolean {
// check if we don't have a block adjacent to blockpos
if (!hasNeighbour(blockPos)) {
// find air adjacent to blockpos that does have a block adjacent to it, let's fill this first as to form a bridge between the player and the original blockpos. necessary if the player is going diagonal.
for (side in EnumFacing.values()) {
val neighbour = blockPos.offset(side)
if (hasNeighbour(neighbour)) {
return true
}
}
return false
}
return true
val rotation = RotationUtils.getRotationTo(vec, true)
mc.player.connection.sendPacket(CPacketPlayer.Rotation(rotation.x.toFloat(), rotation.y.toFloat(), mc.player.onGround))
}
fun hasNeighbour(blockPos: BlockPos): Boolean {
@ -161,6 +80,13 @@ object BlockUtils {
return false
}
fun getHitSide(blockPos: BlockPos): EnumFacing {
return rayTraceTo(blockPos)?.sideHit ?: EnumFacing.UP
}
fun getHitVecOffset(facing: EnumFacing): Vec3d {
return Vec3d(facing.directionVec).scale(0.5).add(0.5, 0.5, 0.5)
}
/**
* @return true if there is liquid below
@ -201,21 +127,16 @@ object BlockUtils {
return mc.world.getBlockState(pos).block == Blocks.WATER
}
fun rayTraceTo(blockPos: BlockPos): RayTraceResult? {
return mc.world.rayTraceBlocks(mc.player.getPositionEyes(1f), Vec3d(blockPos).add(0.5, 0.5, 0.5))
}
/**
* Checks if given [pos] is able to place block in it
*
* @return true playing is not colliding with [pos] and there is block below it
*/
fun isPlaceable(pos: BlockPos): Boolean {
val bBox = mc.player.boundingBox
val xArray = arrayOf(floor(bBox.minX).toInt(), floor(bBox.maxX).toInt())
val yArray = arrayOf(floor(bBox.minY).toInt(), floor(bBox.maxY).toInt())
val zArray = arrayOf(floor(bBox.minZ).toInt(), floor(bBox.maxZ).toInt())
for (x in 0..1) for (y in 0..1) for (z in 0..1) {
if (pos == BlockPos(xArray[x], yArray[y], zArray[z])) return false
}
return mc.world.isAirBlock(pos) && !mc.world.isAirBlock(pos.down())
}
fun isPlaceable(pos: BlockPos) = mc.world.getBlockState(pos).material.isReplaceable && mc.world.checkNoEntityCollision(AxisAlignedBB(pos))
/**
* Checks if given [pos] is able to chest (air above) block in it
@ -223,6 +144,70 @@ object BlockUtils {
* @return true playing is not colliding with [pos] and there is block below it
*/
fun isPlaceableForChest(pos: BlockPos): Boolean {
return isPlaceable(pos) && mc.world.isAirBlock(pos.up())
return isPlaceable(pos) && !mc.world.getBlockState(pos.down()).material.isReplaceable && mc.world.isAirBlock(pos.up())
}
fun buildStructure(placeSpeed: Float, getPlaceInfo: (HashSet<BlockPos>) -> Pair<EnumFacing, BlockPos>?) {
val emptyHashSet = HashSet<BlockPos>()
val placed = HashSet<BlockPos>()
var placeCount = 0
while (getPlaceInfo(emptyHashSet) != null) {
val placingInfo = getPlaceInfo(placed) ?: getPlaceInfo(emptyHashSet)?: break
placeCount++
placed.add(placingInfo.second.offset(placingInfo.first))
doPlace(placingInfo.second, placingInfo.first, placeSpeed)
if (placeCount >= 4) {
Thread.sleep(100L)
placeCount = 0
placed.clear()
}
}
}
fun getPlaceInfo(center: BlockPos?, structureOffset: Array<BlockPos>, toIgnore: HashSet<BlockPos>, maxAttempts: Int, attempts: Int = 1): Pair<EnumFacing, BlockPos>? {
center?.let {
for (offset in structureOffset) {
val pos = it.add(offset)
if (toIgnore.contains(pos)) continue
if (!isPlaceable(pos)) continue
return getNeighbour(pos, attempts) ?: continue
}
if (attempts <= maxAttempts) return getPlaceInfo(it, structureOffset, toIgnore, maxAttempts, attempts + 1)
}
return null
}
fun getNeighbour(blockPos: BlockPos, attempts: Int = 3, range: Float = 4.25f, toIgnore: HashSet<BlockPos> = HashSet()): Pair<EnumFacing, BlockPos>? {
for (side in EnumFacing.values()) {
val pos = blockPos.offset(side)
if (!toIgnore.add(pos)) continue
if (mc.world.getBlockState(pos).material.isReplaceable) continue
if (mc.player.getPositionEyes(1f).distanceTo(Vec3d(pos).add(getHitVecOffset(side))) > range) continue
return Pair(side.opposite, pos)
}
if (attempts > 1) {
toIgnore.add(blockPos)
for (side in EnumFacing.values()) {
val pos = blockPos.offset(side)
if (!isPlaceable(pos)) continue
return getNeighbour(pos, attempts - 1, range, toIgnore) ?: continue
}
}
return null
}
/**
* Placing function for multithreading only
*/
fun doPlace(pos: BlockPos, facing: EnumFacing, placeSpeed: Float) {
val hitVecOffset = getHitVecOffset(facing)
val rotation = RotationUtils.getRotationTo(Vec3d(pos).add(hitVecOffset), true)
val rotationPacket = CPacketPlayer.PositionRotation(mc.player.posX, mc.player.posY, mc.player.posZ, rotation.x.toFloat(), rotation.y.toFloat(), mc.player.onGround)
val placePacket = CPacketPlayerTryUseItemOnBlock(pos, facing, EnumHand.MAIN_HAND, hitVecOffset.x.toFloat(), hitVecOffset.y.toFloat(), hitVecOffset.z.toFloat())
mc.connection!!.sendPacket(rotationPacket)
Thread.sleep((40f / placeSpeed).toLong())
mc.connection!!.sendPacket(placePacket)
mc.player.swingArm(EnumHand.MAIN_HAND)
Thread.sleep((10f / placeSpeed).toLong())
}
}

View File

@ -1,38 +0,0 @@
package me.zeroeightsix.kami.util
import net.minecraft.client.Minecraft
import net.minecraft.network.play.client.CPacketPlayer
import kotlin.math.round
/**
* @author Xiaro
*/
object CenterPlayer {
private val mc = Minecraft.getMinecraft()
/**
* @return the position x of the nearest block center
*/
fun getPosX(offsetMultiplier: Float): Double {
val offset = round(mc.player.posX + 0.5) - 0.5 - mc.player.posX
return mc.player.posX + offset * offsetMultiplier
}
/**
* @return the position z of the nearest block center
*/
fun getPosZ(offsetMultiplier: Float): Double {
val offset = round(mc.player.posZ + 0.5) - 0.5 - mc.player.posZ
return mc.player.posZ + offset * offsetMultiplier
}
/**
* Move player to the nearest block center
*/
fun centerPlayer(offsetMultiplier: Float) {
val posX = getPosX(offsetMultiplier)
val posZ = getPosZ(offsetMultiplier)
mc.player.connection.sendPacket(CPacketPlayer.Position(posX, mc.player.posY, posZ, mc.player.onGround))
mc.player.setPosition(posX, mc.player.posY, posZ)
}
}

View File

@ -201,7 +201,7 @@ object EntityUtils {
DISTANCE, HEALTH
}
fun getPrioritizedTarget(targetList: Array<Entity>, priority: EntityPriority): Entity {
fun getPrioritizedTarget(targetList: ArrayList<EntityLivingBase>, priority: EntityPriority): EntityLivingBase {
var entity = targetList[0]
when (priority) {
EntityPriority.DISTANCE -> {
@ -215,9 +215,9 @@ object EntityUtils {
}
}
EntityPriority.HEALTH -> {
var health = (targetList[0] as EntityLivingBase).health
var health = targetList[0].health
for (i in targetList.indices) {
val currentHealth = (targetList[i] as EntityLivingBase).health
val currentHealth = targetList[i].health
if (currentHealth < health) {
health = currentHealth
entity = targetList[i]
@ -228,12 +228,12 @@ object EntityUtils {
return entity
}
fun getTargetList(player: Array<Boolean>, mobs: Array<Boolean>, ignoreWalls: Boolean, invisible: Boolean, range: Float): Array<Entity> {
if (mc.world.loadedEntityList == null) return emptyArray()
val entityList = ArrayList<Entity>()
fun getTargetList(player: Array<Boolean>, mobs: Array<Boolean>, invisible: Boolean, range: Float): ArrayList<EntityLivingBase> {
if (mc.world.loadedEntityList == null) return ArrayList()
val entityList = ArrayList<EntityLivingBase>()
for (entity in mc.world.loadedEntityList) {
/* Entity type check */
if (!isLiving(entity)) continue
if (entity !is EntityLivingBase) continue
if (entity.name == mc.player.name) continue
if (entity is EntityPlayer) {
if (!player[0]) continue
@ -242,12 +242,11 @@ object EntityUtils {
if (mc.player.isRiding && entity == mc.player.ridingEntity) continue // Riding entity check
if (mc.player.getDistance(entity) > range) continue // Distance check
if ((entity as EntityLivingBase).health <= 0) continue // HP check
if (!ignoreWalls && !mc.player.canEntityBeSeen(entity) && !canEntityFeetBeSeen(entity)) continue // If walls is on & you can't see the feet or head of the target, skip. 2 raytraces needed
if (entity.health <= 0) continue // HP check
if (!invisible && entity.isInvisible) continue
entityList.add(entity)
}
return entityList.toTypedArray()
return entityList
}
@JvmStatic
@ -263,9 +262,9 @@ object EntityUtils {
fun canEntityHitboxBeSeen(entity: Entity): Vec3d? {
val playerPos = mc.player.positionVector.add(0.0, mc.player.eyeHeight.toDouble(), 0.0)
val box = entity.boundingBox
val xArray = arrayOf(box.minX, box.maxX)
val yArray = arrayOf(box.minY, box.maxY)
val zArray = arrayOf(box.minZ, box.maxZ)
val xArray = arrayOf(box.minX + 0.1, box.maxX - 0.1)
val yArray = arrayOf(box.minY + 0.1, box.maxY - 0.1)
val zArray = arrayOf(box.minZ + 0.1, box.maxZ - 0.1)
for (x in xArray) for (y in yArray) for (z in zArray) {
val vertex = Vec3d(x, y, z)

View File

@ -70,7 +70,7 @@ object InventoryUtils {
*
* @return Array contains full inventory slot index, null if no item found
*/
fun getSlotsFullInv(min: Int, max: Int, itemId: Int): Array<Int>? {
fun getSlotsFullInv(min: Int = 9, max: Int = 44, itemId: Int): Array<Int>? {
val slots = arrayListOf<Int>()
for (i in min..max) {
if (getIdFromItem(mc.player.inventoryContainer.inventory[i].getItem()) == itemId) {
@ -106,14 +106,7 @@ object InventoryUtils {
* @return Number of item with given [itemId] in hotbar
*/
fun countItemHotbar(itemId: Int): Int {
val itemList = getSlots(0, 8, itemId)
var currentCount = 0
if (itemList != null) {
for (i in itemList) {
currentCount += mc.player.inventory.getStackInSlot(i).count
}
}
return currentCount
return countItem(36, 44, itemId)
}
/**
@ -122,14 +115,7 @@ object InventoryUtils {
* @return Number of item with given [itemId] in non hotbar
*/
fun countItemNoHotbar(itemId: Int): Int {
val itemList = getSlots(9, 35, itemId)
var currentCount = 0
if (itemList != null) {
for (i in itemList) {
currentCount += mc.player.inventory.getStackInSlot(i).count
}
}
return currentCount
return countItem(0, 35, itemId)
}
/**
@ -139,14 +125,7 @@ object InventoryUtils {
*/
@JvmStatic
fun countItemAll(itemId: Int): Int {
val itemList = getSlots(0, 35, itemId)
var currentCount = 0
if (itemList != null) {
for (i in itemList) {
currentCount += mc.player.inventory.getStackInSlot(i).count
}
}
return currentCount
return countItem(0, 45, itemId)
}
/**
@ -155,12 +134,10 @@ object InventoryUtils {
* @return Number of item with given [itemId] from slot [min] to slot [max]
*/
fun countItem(min: Int, max: Int, itemId: Int): Int {
val itemList = getSlots(min, max, itemId)
val itemList = getSlotsFullInv(min, max, itemId)
var currentCount = 0
if (itemList != null) {
for (i in itemList) {
currentCount += mc.player.inventory.getStackInSlot(i).count
}
if (itemList != null) for (i in itemList) {
currentCount += mc.player.inventoryContainer.inventory[i].count
}
return currentCount
}
@ -209,18 +186,21 @@ object InventoryUtils {
* Move the item in [slotFrom] to [slotTo] in player inventory,
* if [slotTo] contains an item, then move it to [slotFrom]
*/
fun moveToSlot(slotFrom: Int, slotTo: Int) {
moveToSlot(0, slotFrom, slotTo)
fun moveToSlot(slotFrom: Int, slotTo: Int): ShortArray {
val transactionIds = moveToSlot(0, slotFrom, slotTo)
return transactionIds
}
/**
* Move the item in [slotFrom] to [slotTo] in [windowId],
* if [slotTo] contains an item, then move it to [slotFrom]
*/
fun moveToSlot(windowId: Int, slotFrom: Int, slotTo: Int) {
inventoryClick(windowId, slotFrom, type = ClickType.PICKUP)
inventoryClick(windowId, slotTo, type = ClickType.PICKUP)
inventoryClick(windowId, slotFrom, type = ClickType.PICKUP)
fun moveToSlot(windowId: Int, slotFrom: Int, slotTo: Int): ShortArray {
return shortArrayOf(
inventoryClick(windowId, slotFrom, type = ClickType.PICKUP),
inventoryClick(windowId, slotTo, type = ClickType.PICKUP),
inventoryClick(windowId, slotFrom, type = ClickType.PICKUP)
)
}
/**
@ -234,16 +214,18 @@ object InventoryUtils {
/**
* Quick move (Shift + Click) the item in [slotFrom] in player inventory
*
* @return Transaction id
*/
fun quickMoveSlot(slotFrom: Int) {
quickMoveSlot(0, slotFrom)
fun quickMoveSlot(slotFrom: Int): Short {
return quickMoveSlot(0, slotFrom)
}
/**
* Quick move (Shift + Click) the item in [slotFrom] in specified [windowId]
*/
fun quickMoveSlot(windowId: Int, slotFrom: Int) {
inventoryClick(windowId, slotFrom, type = ClickType.QUICK_MOVE)
fun quickMoveSlot(windowId: Int, slotFrom: Int): Short {
return inventoryClick(windowId, slotFrom, type = ClickType.QUICK_MOVE)
}
/**
@ -271,11 +253,17 @@ object InventoryUtils {
inventoryClick(slot = slot, type = ClickType.PICKUP)
}
private fun inventoryClick(windowId: Int = 0, slot: Int, mousedButton: Int = 0, type: ClickType) {
/**
* Performs inventory clicking in specific window, slot, mouseButton, add click type
*
* @return Transaction id
*/
fun inventoryClick(windowId: Int = 0, slot: Int, mouseButton: Int = 0, type: ClickType): Short {
val container = if (windowId == 0) mc.player.inventoryContainer else mc.player.openContainer
val transactionID = container.getNextTransactionID(mc.player.inventory)
val itemStack = container.slotClick(slot, mousedButton, type, mc.player)
mc.connection!!.sendPacket(CPacketClickWindow(windowId, slot, mousedButton, type, itemStack, transactionID))
val itemStack = container.slotClick(slot, mouseButton, type, mc.player)
mc.connection!!.sendPacket(CPacketClickWindow(windowId, slot, mouseButton, type, itemStack, transactionID))
return transactionID
}
/* End of inventory management */
}

View File

@ -0,0 +1,125 @@
package me.zeroeightsix.kami.util
import me.zero.alpine.listener.EventHandler
import me.zero.alpine.listener.EventHook
import me.zero.alpine.listener.Listener
import me.zeroeightsix.kami.KamiMod
import me.zeroeightsix.kami.util.graphics.KamiTessellator
import net.minecraft.entity.Entity
import net.minecraft.util.math.AxisAlignedBB
import net.minecraft.util.math.Vec3d
import net.minecraft.world.World
import net.minecraftforge.fml.common.gameevent.TickEvent
import java.util.*
/**
* Tracking the motion of an Entity tick by tick
*/
class MotionTracker(targetIn: Entity?, private val trackLength: Int = 20) {
var target: Entity? = targetIn
set(value) {
if (value != field) {
reset()
field = value
}
}
private val motionLog = LinkedList<Vec3d>()
private var prevMotion = Vec3d(0.0, 0.0, 0.0)
private var motion = Vec3d(0.0, 0.0, 0.0)
@EventHandler
private val onUpdateListener = Listener(EventHook { event: TickEvent.ClientTickEvent ->
if (Wrapper.player == null || Wrapper.world == null) return@EventHook
target?.let {
motionLog.add(calcActualMotion(it))
while (motionLog.size > trackLength) motionLog.pollFirst()
prevMotion = motion
motion = calcAverageMotion()
}
})
/**
* Calculate the actual motion of given entity
*
* @param entity The entity for motion calculation
* @return Actual motion vector
*/
private fun calcActualMotion(entity: Entity): Vec3d {
return entity.positionVector.subtract(entity.prevPosX, entity.prevPosY, entity.prevPosZ)
}
/**
* Calculate the average motion of the target entity in [trackLength]
*
* @return Average motion vector
*/
private fun calcAverageMotion(): Vec3d {
var sumX = 0.0
var sumY = 0.0
var sumZ = 0.0
for (motion in motionLog) {
sumX += motion.x
sumY += motion.y
sumZ += motion.z
}
return Vec3d(sumX, sumY, sumZ).scale(1.0 / motionLog.size)
}
/**
* Calculate the predicted position of the target entity based on [calcAverageMotion]
*
* @param [ticksAhead] Amount of prediction ahead
* @param [interpolation] Whether to return interpolated position or not, default value is false (no interpolation)
* @return Predicted position of the target entity
*/
fun calcPositionAhead(ticksAhead: Int, interpolation: Boolean = false): Vec3d? {
return target?.let { target ->
calcMovedVectorAhead(ticksAhead, interpolation)?.let {
val partialTicks = if (interpolation) KamiTessellator.pTicks() else 1f
EntityUtils.getInterpolatedPos(target, partialTicks).add(it)
}
}
}
/**
* Calculate the predicted moved vector of the target entity based on [calcAverageMotion]
*
* @param [ticksAhead] Amount of prediction ahead
* @param [interpolation] Whether to return interpolated position or not, default value is false (no interpolation)
* @return Predicted moved vector of the target entity
*/
fun calcMovedVectorAhead(ticksAhead: Int, interpolation: Boolean = false): Vec3d? {
return Wrapper.world?.let { world ->
target?.let {
val partialTicks = if (interpolation) KamiTessellator.pTicks() else 1f
val averageMotion = prevMotion.add(motion.subtract(prevMotion).scale(partialTicks.toDouble()))
var movedVec = Vec3d(0.0, 0.0, 0.0)
for (ticks in 0..ticksAhead) {
movedVec = if (canMove(world, it.boundingBox, movedVec.add(averageMotion))) { // Attempt to move with full motion
movedVec.add(averageMotion)
} else if (canMove(world, it.boundingBox, movedVec.add(averageMotion.x, 0.0, averageMotion.z))) { // Attempt to move horizontally
movedVec.add(averageMotion.x, 0.0, averageMotion.z)
} else break
}
movedVec
}
}
}
private fun canMove(world: World, bbox: AxisAlignedBB, offset: Vec3d): Boolean {
return !world.collidesWithAnyBlock(bbox.offset(offset))
}
/**
* Reset motion tracker
*/
fun reset() {
motionLog.clear()
prevMotion = Vec3d(0.0, 0.0, 0.0)
motion = Vec3d(0.0, 0.0, 0.0)
}
init {
KamiMod.EVENT_BUS.subscribe(this)
}
}

View File

@ -0,0 +1,127 @@
package me.zeroeightsix.kami.util.combat
import me.zeroeightsix.kami.util.InventoryUtils
import net.minecraft.client.Minecraft
import net.minecraft.enchantment.Enchantment
import net.minecraft.enchantment.EnchantmentHelper
import net.minecraft.entity.EntityLivingBase
import net.minecraft.entity.EnumCreatureAttribute
import net.minecraft.entity.SharedMonsterAttributes
import net.minecraft.entity.monster.EntityMob
import net.minecraft.entity.player.EntityPlayer
import net.minecraft.init.Enchantments
import net.minecraft.init.MobEffects
import net.minecraft.item.ItemAxe
import net.minecraft.item.ItemStack
import net.minecraft.item.ItemSword
import net.minecraft.item.ItemTool
import net.minecraft.util.CombatRules
import net.minecraft.util.DamageSource
import net.minecraft.util.math.MathHelper
import kotlin.concurrent.fixedRateTimer
import kotlin.math.max
import kotlin.math.round
object CombatUtils {
private val mc: Minecraft = Minecraft.getMinecraft()
@JvmStatic
fun calcDamageFromPlayer(entity: EntityPlayer, assumeCritical: Boolean = false): Float {
val itemStack = entity.heldItemMainhand
var damage = when (val item = itemStack.getItem()) {
is ItemSword -> item.attackDamage
is ItemTool -> item.attackDamage
else -> 1f
}
val sharpnessLevel = getEnchantmentLevel(itemStack, 16) // 16 is the id for Sharpness
damage += sharpnessLevel * 0.5f + 0.5f
if (assumeCritical) damage *= 1.5f
return damage
}
@JvmStatic
fun calcDamageFromMob(entity: EntityMob): Float {
var damage = entity.getEntityAttribute(SharedMonsterAttributes.ATTACK_DAMAGE).attributeValue.toFloat()
damage += EnchantmentHelper.getModifierForCreature(entity.heldItemMainhand, mc.player.creatureAttribute)
return calcDamage(mc.player, damage)
}
@JvmStatic
fun calcDamage(entity: EntityLivingBase, damageIn: Float = 100f, source: DamageSource = DamageSource.GENERIC, roundDamage: Boolean = false): Float {
if (entity is EntityPlayer && entity.isCreative) return 0.0f // Return 0 directly if entity is a player and in creative mode
var damage = CombatRules.getDamageAfterAbsorb(damageIn, entity.totalArmorValue.toFloat(), entity.getEntityAttribute(SharedMonsterAttributes.ARMOR_TOUGHNESS).attributeValue.toFloat())
if (source != DamageSource.OUT_OF_WORLD) {
entity.getActivePotionEffect(MobEffects.RESISTANCE)?.let {
damage *= max(1f - it.amplifier * 0.2f, 0f)
}
}
if (entity is EntityPlayer) {
damage *= getProtectionModifier(entity, source)
}
return if (roundDamage) round(damage) else damage
}
@JvmStatic
fun getProtectionModifier(entity: EntityPlayer, damageSource: DamageSource): Float {
var modifier = 0
for (armor in entity.armorInventoryList) {
if (armor.isEmpty()) continue // Skip if item stack is empty
val nbtTagList = armor.enchantmentTagList
for (i in 0 until nbtTagList.tagCount()) {
val id = nbtTagList.getCompoundTagAt(i).getShort("id").toInt()
val level = nbtTagList.getCompoundTagAt(i).getShort("lvl").toInt()
Enchantment.getEnchantmentByID(id)?.let { modifier += it.calcModifierDamage(level, damageSource) }
}
}
modifier = MathHelper.clamp(modifier, 0, 20)
return (1.0f - modifier / 25.0f)
}
@JvmStatic
fun getEnchantmentLevel(itemStack: ItemStack, enchantmentId: Int): Int {
for (i in 0 until itemStack.enchantmentTagList.tagCount()) {
val id = itemStack.enchantmentTagList.getCompoundTagAt(i).getShort("id").toInt()
if (id != enchantmentId) continue
return itemStack.enchantmentTagList.getCompoundTagAt(i).getShort("lvl").toInt()
}
return 0
}
@JvmStatic
fun equipBestWeapon(hitMode: PreferWeapon = PreferWeapon.NONE) {
var bestSlot = -1
var maxDamage = 0.0
for (i in 0..8) {
val stack = mc.player.inventory.getStackInSlot(i)
if (stack.isEmpty) continue
if (stack.getItem() !is ItemAxe && hitMode == PreferWeapon.AXE) continue
if (stack.getItem() !is ItemSword && hitMode == PreferWeapon.SWORD) continue
if (stack.getItem() is ItemSword && (hitMode == PreferWeapon.SWORD || hitMode == PreferWeapon.NONE)) {
val damage = (stack.getItem() as ItemSword).attackDamage + EnchantmentHelper.getModifierForCreature(stack, EnumCreatureAttribute.UNDEFINED).toDouble()
if (damage > maxDamage) {
maxDamage = damage
bestSlot = i
}
} else if (stack.getItem() is ItemAxe && (hitMode == PreferWeapon.AXE || hitMode == PreferWeapon.NONE)) {
val damage = (stack.getItem() as ItemTool).attackDamage + EnchantmentHelper.getModifierForCreature(stack, EnumCreatureAttribute.UNDEFINED).toDouble()
if (damage > maxDamage) {
maxDamage = damage
bestSlot = i
}
} else if (stack.getItem() is ItemTool) {
val damage = (stack.getItem() as ItemTool).attackDamage + EnchantmentHelper.getModifierForCreature(stack, EnumCreatureAttribute.UNDEFINED).toDouble()
if (damage > maxDamage) {
maxDamage = damage
bestSlot = i
}
}
}
if (bestSlot != -1) InventoryUtils.swapSlot(bestSlot)
}
enum class PreferWeapon {
SWORD, AXE, NONE
}
}

View File

@ -0,0 +1,137 @@
package me.zeroeightsix.kami.util.combat
import me.zeroeightsix.kami.util.math.VectorUtils
import net.minecraft.client.Minecraft
import net.minecraft.entity.Entity
import net.minecraft.entity.EntityLivingBase
import net.minecraft.entity.item.EntityEnderCrystal
import net.minecraft.entity.player.EntityPlayer
import net.minecraft.init.Blocks
import net.minecraft.util.DamageSource
import net.minecraft.util.math.AxisAlignedBB
import net.minecraft.util.math.BlockPos
import net.minecraft.util.math.Vec3d
import net.minecraft.world.Explosion
import kotlin.math.ceil
import kotlin.math.floor
import kotlin.math.max
object CrystalUtils {
private val mc = Minecraft.getMinecraft()
/* Position Finding */
@JvmStatic
fun getPlacePos(target: EntityLivingBase?, center: Entity?, radius: Float): Map<Float, BlockPos> {
if (target == null || center == null) return emptyMap()
val centerPos = if (center == mc.player) center.getPositionEyes(1f) else center.positionVector
val posList = VectorUtils.getBlockPosInSphere(centerPos, radius)
val damagePosMap = HashMap<Float, BlockPos>()
for (pos in posList) {
if (!canPlace(pos, target)) continue
damagePosMap[calcDamage(pos, target)] = pos
}
return damagePosMap
}
fun getAxisRange(d1: Double, d2: Float): IntRange {
return IntRange(floor(d1 - d2).toInt(), ceil(d1 + d2).toInt())
}
@JvmStatic
fun getCrystalList(range: Float): ArrayList<EntityEnderCrystal> {
return getCrystalList(mc.player.positionVector, range)
}
@JvmStatic
fun getCrystalList(center: Vec3d, range: Float): ArrayList<EntityEnderCrystal> {
val crystalList = ArrayList<EntityEnderCrystal>()
val entityList = ArrayList<Entity>()
synchronized(mc.world.loadedEntityList) {
entityList.addAll(mc.world.loadedEntityList)
}
for (entity in entityList) {
if (entity.isDead) continue
if (entity !is EntityEnderCrystal) continue
if (center.distanceTo(entity.positionVector) > range) continue
crystalList.add(entity)
}
return crystalList
}
@JvmStatic
fun canPlace(blockPos: BlockPos): Boolean {
val placingBB = getCrystalPlacingBB(blockPos.up())
return mc.world.checkNoEntityCollision(placingBB)
&& (mc.world.getBlockState(blockPos).block == Blocks.BEDROCK
|| mc.world.getBlockState(blockPos).block == Blocks.OBSIDIAN)
&& !mc.world.checkBlockCollision(placingBB)
}
/** Checks colliding with blocks and given entity only */
@JvmStatic
fun canPlace(blockPos: BlockPos, entity: Entity): Boolean {
val entityBB = entity.boundingBox
val placingBB = getCrystalPlacingBB(blockPos.up())
return !entityBB.intersects(placingBB)
&& (mc.world.getBlockState(blockPos).block == Blocks.BEDROCK
|| mc.world.getBlockState(blockPos).block == Blocks.OBSIDIAN)
&& !mc.world.checkBlockCollision(placingBB)
}
/** Checks if the block below is valid for placing crystal */
@JvmStatic
fun canPlaceOn(blockPos: BlockPos) = mc.world.getBlockState(blockPos.down()).block == Blocks.BEDROCK || mc.world.getBlockState(blockPos.down()).block == Blocks.OBSIDIAN
@JvmStatic
private fun getCrystalPlacingBB(blockPos: BlockPos): AxisAlignedBB {
return crystalPlacingBB.offset(Vec3d(blockPos).add(0.5, 0.0, 0.5))
}
private val crystalPlacingBB: AxisAlignedBB get() = AxisAlignedBB(-0.5, 0.0, -0.5, 0.5, 2.0, 0.5)
/* Checks colliding with all entity */
@JvmStatic
fun canPlaceCollide(blockPos: BlockPos): Boolean {
val placingBB = getCrystalPlacingBB(blockPos.up())
return mc.world.checkNoEntityCollision(placingBB)
}
/* End of position finding */
/* Damage calculation */
@JvmStatic
fun calcDamage(crystal: EntityEnderCrystal, entity: EntityLivingBase, calcBlastReduction: Boolean = true): Float {
return calcDamage(crystal.positionVector, entity, calcBlastReduction)
}
@JvmStatic
fun calcDamage(blockPos: BlockPos, entity: EntityLivingBase, calcBlastReduction: Boolean = true): Float {
return calcDamage(Vec3d(blockPos).add(0.5, 1.0, 0.5), entity, calcBlastReduction)
}
@JvmStatic
fun calcDamage(pos: Vec3d, entity: EntityLivingBase, calcBlastReduction: Boolean = true): Float {
if (entity is EntityPlayer && entity.isCreative) return 0.0f // Return 0 directly if entity is a player and in creative mode
var damage = calcRawDamage(pos, entity)
if (calcBlastReduction) damage = CombatUtils.calcDamage(entity, damage, getDamageSource(pos))
if (entity is EntityPlayer) damage *= getDamageMultiplier()
return max(damage, 0f)
}
@JvmStatic
private fun calcRawDamage(pos: Vec3d, entity: Entity): Float {
val distance = pos.distanceTo(entity.positionVector)
val v = (1.0 - (distance / 12.0)) * entity.world.getBlockDensity(pos, entity.boundingBox)
return ((v * v + v) / 2.0 * 84.0 + 1.0).toFloat()
}
@JvmStatic
private fun getDamageSource(damagePos: Vec3d): DamageSource {
return DamageSource.causeExplosionDamage(Explosion(mc.world, mc.player, damagePos.x, damagePos.y, damagePos.z, 6F, false, true))
}
@JvmStatic
private fun getDamageMultiplier(): Float {
return mc.world.difficulty.id * 0.5f
}
/* End of damage calculation */
}

View File

@ -0,0 +1,65 @@
package me.zeroeightsix.kami.util.combat
import me.zeroeightsix.kami.util.Wrapper
import net.minecraft.block.Block
import net.minecraft.entity.Entity
import net.minecraft.init.Blocks
import net.minecraft.util.math.BlockPos
import kotlin.math.floor
/**
* @author Xiaro
*
* Created by Xiaro on 08/09/20
*/
object SurroundUtils {
private val mc = Wrapper.minecraft
@JvmStatic
val surroundOffset = arrayOf(
BlockPos(0, -1, 0), // down
BlockPos(0, 0, -1), // north
BlockPos(1, 0, 0), // east
BlockPos(0, 0, 1), // south
BlockPos(-1, 0, 0) // west
)
@JvmStatic
val surroundOffsetNoFloor = arrayOf(
BlockPos(0, 0, -1), // north
BlockPos(1, 0, 0), // east
BlockPos(0, 0, 1), // south
BlockPos(-1, 0, 0) // west
)
@JvmStatic
fun checkHole(entity: Entity): HoleType {
return checkHole(BlockPos(floor(entity.posX).toInt(), floor(entity.posY).toInt(), floor(entity.posZ).toInt()))
}
@JvmStatic
fun checkHole(pos: BlockPos): HoleType {
// Must be a 1 * 3 * 1 empty space
if (!mc.world.isAirBlock(pos) || !mc.world.isAirBlock(pos.up()) || !mc.world.isAirBlock(pos.up().up())) return HoleType.NONE
var type = HoleType.BEDROCK
for (offset in surroundOffset) {
val block = mc.world.getBlockState(pos.add(offset)).block
if (!checkBlock(block)) {
type = HoleType.NONE
break
}
if (block != Blocks.BEDROCK) type = HoleType.OBBY
}
return type
}
@JvmStatic
fun checkBlock(block: Block): Boolean {
return block == Blocks.BEDROCK || block == Blocks.OBSIDIAN || block == Blocks.ENDER_CHEST || block == Blocks.ANVIL
}
enum class HoleType {
NONE, OBBY, BEDROCK
}
}

View File

@ -2,11 +2,10 @@ package me.zeroeightsix.kami.util.math
import me.zeroeightsix.kami.util.EntityUtils
import me.zeroeightsix.kami.util.Wrapper
import me.zeroeightsix.kami.util.graphics.KamiTessellator
import net.minecraft.entity.Entity
import net.minecraft.util.math.MathHelper
import net.minecraft.util.math.Vec3d
import kotlin.math.atan2
import kotlin.math.sqrt
import kotlin.math.*
/**
* Utils for calculating angles and rotations
@ -14,14 +13,50 @@ import kotlin.math.sqrt
object RotationUtils {
val mc = Wrapper.minecraft
fun faceEntity(entity: Entity) {
val rotation = getRotationToEntity(entity)
fun faceEntityClosest(entity: Entity, pTicks: Float = 1f) {
val rotation = getRotationToEntityClosest(entity, pTicks)
mc.player.rotationYaw = rotation.x.toFloat()
mc.player.rotationPitch = rotation.y.toFloat()
}
fun getRotationToEntity(entity: Entity): Vec2d {
val posTo = EntityUtils.getInterpolatedPos(entity, KamiTessellator.pTicks())
fun faceEntity(entity: Entity, pTicks: Float = 1f) {
val rotation = getRotationToEntity(entity, pTicks)
mc.player.rotationYaw = rotation.x.toFloat()
mc.player.rotationPitch = rotation.y.toFloat()
}
fun getRelativeRotation(entity: Entity, pTicks: Float = 1f): Double {
return getRotationDiff(getRotationToEntity(entity, pTicks), getPlayerRotation())
}
fun getRelativeRotation(posTo: Vec3d, pTicks: Float = 1f): Double {
return getRotationDiff(getRotationTo(posTo, true, pTicks), getPlayerRotation())
}
fun getPlayerRotation(pTicks: Float = 1f): Vec2d {
val rotation = Vec2d(mc.player.rotationYaw.toDouble(), mc.player.rotationPitch.toDouble())
val prevRotation = Vec2d(mc.player.rotationYaw.toDouble(), mc.player.rotationPitch.toDouble())
return prevRotation.add(rotation.subtract(prevRotation).multiply(pTicks.toDouble()))
}
fun getRotationDiff(r1: Vec2d, r2: Vec2d): Double {
val r1Radians = r1.toRadians()
val r2Radians = r2.toRadians()
return Math.toDegrees(acos(cos(r1Radians.y) * cos(r2Radians.y) * cos(r1Radians.x - r2Radians.x) + sin(r1Radians.y) * sin(r2Radians.y)))
}
fun getRotationToEntityClosest(entity: Entity, pTicks: Float = 1f): Vec2d {
val box = entity.boundingBox
val eyePos = mc.player.getPositionEyes(1f)
val x = MathHelper.clamp(eyePos.x, box.minX + 0.1, box.maxX - 0.1)
val y = MathHelper.clamp(eyePos.y, box.minY + 0.1, box.maxY - 0.1)
val z = MathHelper.clamp(eyePos.z, box.minZ + 0.1, box.maxZ - 0.1)
val hitVec = Vec3d(x, y, z)
return getRotationTo(hitVec, true, pTicks)
}
fun getRotationToEntity(entity: Entity, pTicks: Float = 1f): Vec2d {
val posTo = EntityUtils.getInterpolatedPos(entity, pTicks)
return getRotationTo(posTo, true)
}
@ -33,10 +68,10 @@ object RotationUtils {
* @return [Pair]<Yaw, Pitch>
*/
@JvmStatic
fun getRotationTo(posTo: Vec3d, eyeHeight: Boolean): Vec2d {
fun getRotationTo(posTo: Vec3d, eyeHeight: Boolean, pTicks: Float = 1f): Vec2d {
val player = mc.player
val posFrom = if (eyeHeight) player.getPositionEyes(KamiTessellator.pTicks())
else EntityUtils.getInterpolatedPos(player, KamiTessellator.pTicks())
val posFrom = if (eyeHeight) player.getPositionEyes(pTicks)
else EntityUtils.getInterpolatedPos(player, pTicks)
return getRotationTo(posFrom, posTo)
}

View File

@ -10,6 +10,10 @@ class Vec2d(var x: Double = 0.0, var y: Double = 0.0) {
constructor(vec2d: Vec2d) : this(vec2d.x, vec2d.y)
fun toRadians(): Vec2d {
return Vec2d(this.x / 180.0 * Math.PI, this.y / 180.0 * Math.PI)
}
fun length(): Double {
return sqrt(lengthSquared())
}

View File

@ -16,6 +16,8 @@ class Vec2f(@JvmField var x: Float, @JvmField var y: Float) {
*/
constructor(entity: Entity) : this(entity.rotationYaw, entity.rotationPitch)
constructor(vec2d: Vec2d): this(vec2d.x.toFloat(), vec2d.y.toFloat())
fun toRadians(): Vec2d {
return Vec2d(this.x / 180.0 * Math.PI, this.y / 180.0 * Math.PI)
}