mirror of https://github.com/kami-blue/client
[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:
parent
0d365ed58e
commit
b2448f041b
|
@ -2,7 +2,7 @@ complexity:
|
|||
active: true
|
||||
ComplexMethod:
|
||||
active: true
|
||||
threshold: 25
|
||||
threshold: 50
|
||||
|
||||
style:
|
||||
active: true
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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()
|
|
@ -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)
|
||||
}
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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))
|
||||
}
|
||||
}
|
|
@ -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
|
||||
}
|
||||
}
|
|
@ -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()
|
||||
}
|
||||
|
||||
|
|
|
@ -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()
|
||||
})
|
||||
}
|
|
@ -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
|
||||
}
|
||||
}
|
|
@ -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
|
||||
}
|
||||
}
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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] }
|
||||
}
|
|
@ -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()));
|
||||
}
|
||||
}
|
|
@ -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)
|
||||
};
|
||||
}
|
||||
}
|
|
@ -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)
|
||||
))
|
||||
}
|
||||
}
|
|
@ -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())
|
||||
}
|
||||
}
|
|
@ -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]
|
||||
}
|
||||
}
|
|
@ -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!");
|
||||
}
|
||||
}
|
|
@ -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 */
|
||||
}
|
|
@ -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()
|
||||
}
|
||||
}
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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
|
||||
}
|
||||
}
|
|
@ -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
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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)
|
||||
}
|
|
@ -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()
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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>>()
|
||||
|
|
|
@ -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())
|
||||
}
|
||||
}
|
|
@ -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)
|
||||
}
|
||||
}
|
|
@ -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)
|
||||
|
|
|
@ -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 */
|
||||
}
|
|
@ -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)
|
||||
}
|
||||
}
|
|
@ -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
|
||||
}
|
||||
}
|
|
@ -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 */
|
||||
}
|
|
@ -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
|
||||
}
|
||||
}
|
|
@ -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)
|
||||
}
|
||||
|
||||
|
|
|
@ -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())
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue