mirror of https://github.com/kami-blue/client
[refactor] Rewrite and greatly improve Scaffold (#1760)
* Cleaned up old codes * Added connection to ExecuteEvent * Added getHitVec(), added side parameter to getNeighbour * Fixed SafeWalk disabling view bobbing * Rewrote Scaffold * Added spoof hotbar * Added max range option * Added tower mode * Fixed hotbar spoofing * Get tower mode actually work on other servers * Added sneak option
This commit is contained in:
parent
0a571361a9
commit
1a82b29873
|
@ -4,6 +4,7 @@ import me.zeroeightsix.kami.util.Wrapper
|
||||||
import net.minecraft.client.entity.EntityPlayerSP
|
import net.minecraft.client.entity.EntityPlayerSP
|
||||||
import net.minecraft.client.multiplayer.PlayerControllerMP
|
import net.minecraft.client.multiplayer.PlayerControllerMP
|
||||||
import net.minecraft.client.multiplayer.WorldClient
|
import net.minecraft.client.multiplayer.WorldClient
|
||||||
|
import net.minecraft.client.network.NetHandlerPlayClient
|
||||||
import org.kamiblue.command.ExecuteEvent
|
import org.kamiblue.command.ExecuteEvent
|
||||||
import org.kamiblue.command.IExecuteEvent
|
import org.kamiblue.command.IExecuteEvent
|
||||||
|
|
||||||
|
@ -12,18 +13,21 @@ abstract class AbstractClientEvent {
|
||||||
abstract val world: WorldClient?
|
abstract val world: WorldClient?
|
||||||
abstract val player: EntityPlayerSP?
|
abstract val player: EntityPlayerSP?
|
||||||
abstract val playerController: PlayerControllerMP?
|
abstract val playerController: PlayerControllerMP?
|
||||||
|
abstract val connection: NetHandlerPlayClient?
|
||||||
}
|
}
|
||||||
|
|
||||||
open class ClientEvent : AbstractClientEvent() {
|
open class ClientEvent : AbstractClientEvent() {
|
||||||
final override val world: WorldClient? = mc.world
|
final override val world: WorldClient? = mc.world
|
||||||
final override val player: EntityPlayerSP? = mc.player
|
final override val player: EntityPlayerSP? = mc.player
|
||||||
final override val playerController: PlayerControllerMP? = mc.playerController
|
final override val playerController: PlayerControllerMP? = mc.playerController
|
||||||
|
final override val connection: NetHandlerPlayClient? = mc.connection
|
||||||
}
|
}
|
||||||
|
|
||||||
open class SafeClientEvent(
|
open class SafeClientEvent(
|
||||||
override val world: WorldClient,
|
override val world: WorldClient,
|
||||||
override val player: EntityPlayerSP,
|
override val player: EntityPlayerSP,
|
||||||
override val playerController: PlayerControllerMP
|
override val playerController: PlayerControllerMP,
|
||||||
|
override val connection: NetHandlerPlayClient
|
||||||
) : AbstractClientEvent()
|
) : AbstractClientEvent()
|
||||||
|
|
||||||
class ClientExecuteEvent(
|
class ClientExecuteEvent(
|
||||||
|
@ -34,13 +38,14 @@ class SafeExecuteEvent(
|
||||||
world: WorldClient,
|
world: WorldClient,
|
||||||
player: EntityPlayerSP,
|
player: EntityPlayerSP,
|
||||||
playerController: PlayerControllerMP,
|
playerController: PlayerControllerMP,
|
||||||
|
connection: NetHandlerPlayClient,
|
||||||
event: ClientExecuteEvent
|
event: ClientExecuteEvent
|
||||||
) : SafeClientEvent(world, player, playerController), IExecuteEvent by event
|
) : SafeClientEvent(world, player, playerController, connection), IExecuteEvent by event
|
||||||
|
|
||||||
fun ClientEvent.toSafe() =
|
fun ClientEvent.toSafe() =
|
||||||
if (world != null && player != null && playerController != null) SafeClientEvent(world, player, playerController)
|
if (world != null && player != null && playerController != null && connection != null) SafeClientEvent(world, player, playerController, connection)
|
||||||
else null
|
else null
|
||||||
|
|
||||||
fun ClientExecuteEvent.toSafe() =
|
fun ClientExecuteEvent.toSafe() =
|
||||||
if (world != null && player != null && playerController != null) SafeExecuteEvent(world, player, playerController, this)
|
if (world != null && player != null && playerController != null && connection != null) SafeExecuteEvent(world, player, playerController, connection, this)
|
||||||
else null
|
else null
|
|
@ -13,12 +13,13 @@ import me.zeroeightsix.kami.mixin.extension.*
|
||||||
import me.zeroeightsix.kami.module.Module
|
import me.zeroeightsix.kami.module.Module
|
||||||
import me.zeroeightsix.kami.util.TimerUtils
|
import me.zeroeightsix.kami.util.TimerUtils
|
||||||
import me.zeroeightsix.kami.util.Wrapper
|
import me.zeroeightsix.kami.util.Wrapper
|
||||||
import org.kamiblue.event.listener.listener
|
|
||||||
import me.zeroeightsix.kami.util.math.Vec2f
|
import me.zeroeightsix.kami.util.math.Vec2f
|
||||||
|
import net.minecraft.item.ItemStack
|
||||||
import net.minecraft.network.play.client.CPacketHeldItemChange
|
import net.minecraft.network.play.client.CPacketHeldItemChange
|
||||||
import net.minecraft.network.play.client.CPacketPlayer
|
import net.minecraft.network.play.client.CPacketPlayer
|
||||||
import net.minecraft.util.math.Vec3d
|
import net.minecraft.util.math.Vec3d
|
||||||
import net.minecraftforge.fml.common.gameevent.TickEvent
|
import net.minecraftforge.fml.common.gameevent.TickEvent
|
||||||
|
import org.kamiblue.event.listener.listener
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
object PlayerPacketManager : Manager {
|
object PlayerPacketManager : Manager {
|
||||||
|
@ -49,16 +50,16 @@ object PlayerPacketManager : Manager {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
listener<PacketEvent.Send> {
|
listener<PacketEvent.Send>(-69420) {
|
||||||
if (it.packet is CPacketHeldItemChange) {
|
if (it.packet is CPacketHeldItemChange) {
|
||||||
if (spoofingHotbar && it.packet.slotId != serverSideHotbar) {
|
if (spoofingHotbar && it.packet.slotId != serverSideHotbar) {
|
||||||
if (hotbarResetTimer.tick(2L)) {
|
if (hotbarResetTimer.tick(2L)) {
|
||||||
spoofingHotbar = false
|
spoofingHotbar = false
|
||||||
} else {
|
} else {
|
||||||
it.cancel()
|
it.cancel()
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
listener<PacketEvent.PostSend>(-6969) {
|
listener<PacketEvent.PostSend>(-6969) {
|
||||||
|
@ -113,11 +114,14 @@ object PlayerPacketManager : Manager {
|
||||||
packetList[caller] = packet
|
packetList[caller] = packet
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun getHoldingItemStack(): ItemStack =
|
||||||
|
Wrapper.player?.inventory?.mainInventory?.get(serverSideHotbar) ?: ItemStack.EMPTY
|
||||||
|
|
||||||
fun spoofHotbar(slot: Int) {
|
fun spoofHotbar(slot: Int) {
|
||||||
Wrapper.minecraft.connection?.let {
|
Wrapper.minecraft.connection?.let {
|
||||||
if (serverSideHotbar != slot) {
|
if (serverSideHotbar != slot) {
|
||||||
it.sendPacket(CPacketHeldItemChange(slot))
|
|
||||||
serverSideHotbar = slot
|
serverSideHotbar = slot
|
||||||
|
it.sendPacket(CPacketHeldItemChange(slot))
|
||||||
spoofingHotbar = true
|
spoofingHotbar = true
|
||||||
}
|
}
|
||||||
hotbarResetTimer.reset()
|
hotbarResetTimer.reset()
|
||||||
|
|
|
@ -32,9 +32,11 @@ public class MixinEntity {
|
||||||
entity.isAirBorne = true;
|
entity.isAirBorne = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Redirect(method = "move", at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/Entity;isSneaking()Z"))
|
@Redirect(method = "move", at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/Entity;isSneaking()Z", ordinal = 0))
|
||||||
public boolean isSneaking(Entity entity) {
|
public boolean isSneaking(Entity entity) {
|
||||||
return SafeWalk.INSTANCE.shouldSafewalk() || Scaffold.INSTANCE.isEnabled() || entity.isSneaking();
|
return SafeWalk.INSTANCE.shouldSafewalk()
|
||||||
|
|| (Scaffold.INSTANCE.isEnabled() && Scaffold.INSTANCE.getSafeWalk().getValue())
|
||||||
|
|| entity.isSneaking();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Makes the camera guy instead of original player turn around when we move mouse
|
// Makes the camera guy instead of original player turn around when we move mouse
|
||||||
|
|
|
@ -3,6 +3,9 @@ package me.zeroeightsix.kami.module
|
||||||
import com.google.common.base.Converter
|
import com.google.common.base.Converter
|
||||||
import com.google.gson.JsonElement
|
import com.google.gson.JsonElement
|
||||||
import com.google.gson.JsonPrimitive
|
import com.google.gson.JsonPrimitive
|
||||||
|
import kotlinx.coroutines.CoroutineName
|
||||||
|
import kotlinx.coroutines.CoroutineScope
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
import me.zeroeightsix.kami.event.KamiEventBus
|
import me.zeroeightsix.kami.event.KamiEventBus
|
||||||
import me.zeroeightsix.kami.gui.kami.DisplayGuiScreen
|
import me.zeroeightsix.kami.gui.kami.DisplayGuiScreen
|
||||||
import me.zeroeightsix.kami.module.modules.client.ClickGUI
|
import me.zeroeightsix.kami.module.modules.client.ClickGUI
|
||||||
|
@ -211,5 +214,6 @@ open class Module {
|
||||||
|
|
||||||
protected companion object {
|
protected companion object {
|
||||||
@JvmField val mc: Minecraft = Minecraft.getMinecraft()
|
@JvmField val mc: Minecraft = Minecraft.getMinecraft()
|
||||||
|
val moduleScope = CoroutineScope(Dispatchers.Default + CoroutineName("KAMI Blue Module"))
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,168 +1,172 @@
|
||||||
package me.zeroeightsix.kami.module.modules.player
|
package me.zeroeightsix.kami.module.modules.player
|
||||||
|
|
||||||
import me.zeroeightsix.kami.event.events.SafeTickEvent
|
import kotlinx.coroutines.delay
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
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.PlayerTravelEvent
|
||||||
|
import me.zeroeightsix.kami.manager.managers.PlayerPacketManager
|
||||||
import me.zeroeightsix.kami.mixin.client.entity.MixinEntity
|
import me.zeroeightsix.kami.mixin.client.entity.MixinEntity
|
||||||
import me.zeroeightsix.kami.module.Module
|
import me.zeroeightsix.kami.module.Module
|
||||||
import me.zeroeightsix.kami.setting.Settings
|
import me.zeroeightsix.kami.setting.Settings
|
||||||
import me.zeroeightsix.kami.util.BlockUtils
|
import me.zeroeightsix.kami.util.*
|
||||||
import me.zeroeightsix.kami.util.EntityUtils
|
import me.zeroeightsix.kami.util.BlockUtils.placeBlock
|
||||||
import org.kamiblue.event.listener.listener
|
import me.zeroeightsix.kami.util.EntityUtils.prevPosVector
|
||||||
import net.minecraft.block.Block
|
import me.zeroeightsix.kami.util.math.RotationUtils
|
||||||
import net.minecraft.block.BlockContainer
|
import me.zeroeightsix.kami.util.math.Vec2f
|
||||||
import net.minecraft.block.BlockFalling
|
import me.zeroeightsix.kami.util.math.VectorUtils.toBlockPos
|
||||||
import net.minecraft.item.ItemBlock
|
import net.minecraft.item.ItemBlock
|
||||||
import net.minecraft.item.ItemStack
|
|
||||||
import net.minecraft.network.play.client.CPacketEntityAction
|
import net.minecraft.network.play.client.CPacketEntityAction
|
||||||
|
import net.minecraft.network.play.server.SPacketPlayerPosLook
|
||||||
|
import net.minecraft.util.EnumFacing
|
||||||
import net.minecraft.util.math.BlockPos
|
import net.minecraft.util.math.BlockPos
|
||||||
import net.minecraftforge.client.event.InputUpdateEvent
|
import net.minecraft.util.math.RayTraceResult
|
||||||
import kotlin.math.round
|
import net.minecraft.util.math.Vec3d
|
||||||
|
import org.kamiblue.event.listener.listener
|
||||||
|
import kotlin.math.floor
|
||||||
|
import kotlin.math.roundToInt
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see MixinEntity.isSneaking
|
* @see MixinEntity.isSneaking
|
||||||
*
|
|
||||||
* TODO: Rewrite this
|
|
||||||
*/
|
*/
|
||||||
@Module.Info(
|
@Module.Info(
|
||||||
name = "Scaffold",
|
name = "Scaffold",
|
||||||
category = Module.Category.PLAYER,
|
category = Module.Category.PLAYER,
|
||||||
description = "Places blocks under you"
|
description = "Places blocks under you",
|
||||||
|
modulePriority = 500
|
||||||
)
|
)
|
||||||
object Scaffold : Module() {
|
object Scaffold : Module() {
|
||||||
private val placeBlocks = register(Settings.b("PlaceBlocks", true))
|
|
||||||
private val tower = register(Settings.b("Tower", true))
|
private val tower = register(Settings.b("Tower", true))
|
||||||
private val modeSetting = register(Settings.e<Mode>("Mode", Mode.NORMAL))
|
private val spoofHotbar = register(Settings.b("SpoofHotbar", true))
|
||||||
private val randomDelay = register(Settings.booleanBuilder("RandomDelay").withValue(false).withVisibility { modeSetting.value == Mode.LEGIT })
|
val safeWalk = register(Settings.b("SafeWalk", true))
|
||||||
private val delayRange = register(Settings.integerBuilder("DelayRange").withValue(6).withRange(0, 10).withVisibility { modeSetting.value == Mode.LEGIT && randomDelay.value })
|
private val sneak = register(Settings.b("Sneak", true))
|
||||||
private val ticks = register(Settings.integerBuilder("Ticks").withValue(2).withRange(0, 60).withStep(2).withVisibility { modeSetting.value == Mode.NORMAL })
|
private val delay = register(Settings.integerBuilder("Delay").withValue(2).withRange(1, 10).withStep(1))
|
||||||
|
private val maxRange = register(Settings.integerBuilder("MaxRange").withValue(1).withRange(0, 3).withStep(1))
|
||||||
|
|
||||||
private var shouldSlow = false
|
private var lastRotation = Vec2f.ZERO
|
||||||
private var towerStart = 0.0
|
private var placeInfo: Pair<EnumFacing, BlockPos>? = null
|
||||||
private var holding = false
|
private var inactiveTicks = 69
|
||||||
|
|
||||||
private enum class Mode {
|
private val placeTimer = TimerUtils.TickTimer(TimerUtils.TimeUnit.TICKS)
|
||||||
NORMAL, LEGIT
|
private val rubberBandTimer = TimerUtils.TickTimer(TimerUtils.TimeUnit.TICKS)
|
||||||
|
|
||||||
|
override fun isActive(): Boolean {
|
||||||
|
return isEnabled && inactiveTicks <= 5
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onDisable() {
|
||||||
|
placeInfo = null
|
||||||
|
inactiveTicks = 69
|
||||||
}
|
}
|
||||||
|
|
||||||
init {
|
init {
|
||||||
listener<InputUpdateEvent> {
|
listener<PacketEvent.Receive> {
|
||||||
if (modeSetting.value == Mode.LEGIT && shouldSlow) {
|
if (it.packet !is SPacketPlayerPosLook) return@listener
|
||||||
if (randomDelay.value) {
|
rubberBandTimer.reset()
|
||||||
it.movementInput.moveStrafe *= 0.2f + randomInRange
|
|
||||||
it.movementInput.moveForward *= 0.2f + randomInRange
|
|
||||||
} else {
|
|
||||||
it.movementInput.moveStrafe *= 0.2f
|
|
||||||
it.movementInput.moveForward *= 0.2f
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
listener<SafeTickEvent> {
|
listener<PlayerTravelEvent> {
|
||||||
shouldSlow = false
|
if (mc.player == null || !tower.value || !mc.gameSettings.keyBindJump.isKeyDown || inactiveTicks > 5 || !isHoldingBlock) return@listener
|
||||||
|
if (rubberBandTimer.tick(10, false)) {
|
||||||
val towering = mc.gameSettings.keyBindJump.isKeyDown && tower.value
|
if (shouldTower) mc.player.motionY = 0.41999998688697815
|
||||||
var vec3d = EntityUtils.getInterpolatedPos(mc.player, ticks.value.toFloat())
|
} else if (mc.player.fallDistance <= 2.0f) {
|
||||||
|
mc.player.motionY = -0.169
|
||||||
if (modeSetting.value == Mode.LEGIT) vec3d = EntityUtils.getInterpolatedPos(mc.player, 0f)
|
|
||||||
|
|
||||||
val blockPos = BlockPos(vec3d).down()
|
|
||||||
val belowBlockPos = blockPos.down()
|
|
||||||
val legitPos = BlockPos(EntityUtils.getInterpolatedPos(mc.player, 2f))
|
|
||||||
|
|
||||||
/* when legitBridge is enabled */
|
|
||||||
/* check if block behind player is air or other replaceable block and if it is, make the player crouch */
|
|
||||||
if (modeSetting.value == Mode.LEGIT && mc.world.getBlockState(legitPos.down()).material.isReplaceable && mc.player.onGround && !towering) {
|
|
||||||
shouldSlow = true
|
|
||||||
mc.player.movementInput.sneak = true
|
|
||||||
mc.player.connection.sendPacket(CPacketEntityAction(mc.player, CPacketEntityAction.Action.START_SNEAKING))
|
|
||||||
}
|
|
||||||
|
|
||||||
if (towering) {
|
|
||||||
if (mc.player.posY <= blockPos.y + 1.0f) {
|
|
||||||
return@listener
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!mc.world.getBlockState(blockPos).material.isReplaceable) {
|
|
||||||
return@listener
|
|
||||||
}
|
|
||||||
|
|
||||||
val oldSlot = mc.player.inventory.currentItem
|
|
||||||
setSlotToBlocks(belowBlockPos)
|
|
||||||
|
|
||||||
/* check if we don't have a block adjacent to the blockPos */
|
|
||||||
val neighbor = BlockUtils.getNeighbour(blockPos, attempts = 1) ?: return@listener
|
|
||||||
|
|
||||||
/* place the block */
|
|
||||||
if (placeBlocks.value) BlockUtils.placeBlock(neighbor.second, neighbor.first)
|
|
||||||
|
|
||||||
/* Reset the slot */
|
|
||||||
if (!holding) mc.player.inventory.currentItem = oldSlot
|
|
||||||
|
|
||||||
if (towering) {
|
|
||||||
val motion = 0.42 // jump motion
|
|
||||||
if (mc.player.onGround) {
|
|
||||||
towerStart = mc.player.posY
|
|
||||||
mc.player.motionY = motion
|
|
||||||
}
|
|
||||||
if (mc.player.posY > towerStart + motion) {
|
|
||||||
mc.player.setPosition(mc.player.posX, round(mc.player.posY), mc.player.posZ)
|
|
||||||
mc.player.motionY = motion
|
|
||||||
towerStart = mc.player.posY
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
towerStart = 0.0
|
|
||||||
}
|
|
||||||
|
|
||||||
if (shouldSlow) {
|
|
||||||
mc.player.connection.sendPacket(CPacketEntityAction(mc.player, CPacketEntityAction.Action.STOP_SNEAKING))
|
|
||||||
shouldSlow = false
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private val randomInRange: Float
|
private val isHoldingBlock: Boolean
|
||||||
get() = 0.11f + Math.random().toFloat() * (delayRange.value / 10.0f - 0.11f)
|
get() = PlayerPacketManager.getHoldingItemStack().item is ItemBlock
|
||||||
|
|
||||||
private fun setSlotToBlocks(belowBlockPos: BlockPos) {
|
private val shouldTower: Boolean
|
||||||
if (isBlock(mc.player.heldItemMainhand, belowBlockPos)) {
|
get() = !mc.player.onGround
|
||||||
holding = true
|
&& mc.player.posY - floor(mc.player.posY) <= 0.1
|
||||||
return
|
init {
|
||||||
|
listener<OnUpdateWalkingPlayerEvent> { event ->
|
||||||
|
if (mc.world == null || mc.player == null || event.era != KamiEvent.Era.PRE) return@listener
|
||||||
|
inactiveTicks++
|
||||||
|
placeInfo = calcNextPos()?.let {
|
||||||
|
BlockUtils.getNeighbour(it, 1, sides = arrayOf(EnumFacing.DOWN))
|
||||||
|
?: BlockUtils.getNeighbour(it, 3, sides = EnumFacing.HORIZONTALS)
|
||||||
|
}
|
||||||
|
|
||||||
|
placeInfo?.let {
|
||||||
|
val hitVec = BlockUtils.getHitVec(it.second, it.first)
|
||||||
|
lastRotation = Vec2f(RotationUtils.getRotationTo(hitVec, true))
|
||||||
|
swapAndPlace(it.second, it.first)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (inactiveTicks > 5) {
|
||||||
|
PlayerPacketManager.resetHotbar()
|
||||||
|
} else if (isHoldingBlock) {
|
||||||
|
val packet = PlayerPacketManager.PlayerPacket(rotating = true, rotation = lastRotation)
|
||||||
|
PlayerPacketManager.addPacket(this, packet)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
holding = false
|
}
|
||||||
|
|
||||||
/* search blocks in hotbar */
|
private fun calcNextPos(): BlockPos? {
|
||||||
var newSlot = -1
|
val posVec = mc.player.positionVector
|
||||||
|
val blockPos = posVec.toBlockPos()
|
||||||
|
return checkPos(blockPos)
|
||||||
|
?: run {
|
||||||
|
val realMotion = posVec.subtract(mc.player.prevPosVector)
|
||||||
|
val nextPos = blockPos.add(roundToRange(realMotion.x), 0, roundToRange(realMotion.z))
|
||||||
|
checkPos(nextPos)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun checkPos(blockPos: BlockPos): BlockPos? {
|
||||||
|
val center = Vec3d(blockPos.x + 0.5, blockPos.y.toDouble(), blockPos.z + 0.5)
|
||||||
|
val rayTraceResult = mc.world.rayTraceBlocks(
|
||||||
|
center,
|
||||||
|
center.subtract(0.0, 0.5, 0.0),
|
||||||
|
false,
|
||||||
|
true,
|
||||||
|
false
|
||||||
|
)
|
||||||
|
return blockPos.down().takeIf { rayTraceResult?.typeOfHit != RayTraceResult.Type.BLOCK }
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun roundToRange(value: Double) =
|
||||||
|
(value * 2.5 * maxRange.value).roundToInt().coerceAtMost(maxRange.value)
|
||||||
|
|
||||||
|
private fun swapAndPlace(pos: BlockPos, side: EnumFacing) {
|
||||||
|
getBlockSlot()?.let { slot ->
|
||||||
|
if (spoofHotbar.value) PlayerPacketManager.spoofHotbar(slot)
|
||||||
|
else InventoryUtils.swapSlot(slot)
|
||||||
|
|
||||||
|
inactiveTicks = 0
|
||||||
|
|
||||||
|
if (placeTimer.tick(delay.value.toLong())) {
|
||||||
|
val shouldSneak = sneak.value && !mc.player.isSneaking
|
||||||
|
moduleScope.launch {
|
||||||
|
if (shouldSneak) {
|
||||||
|
mc.player?.let {
|
||||||
|
it.connection.sendPacket(CPacketEntityAction(it, CPacketEntityAction.Action.START_SNEAKING))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
delay(5)
|
||||||
|
onMainThreadSafe {
|
||||||
|
placeBlock(pos, side)
|
||||||
|
if (shouldSneak) {
|
||||||
|
connection.sendPacket(CPacketEntityAction(player, CPacketEntityAction.Action.STOP_SNEAKING))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getBlockSlot(): Int? {
|
||||||
|
mc.playerController.updateController()
|
||||||
for (i in 0..8) {
|
for (i in 0..8) {
|
||||||
/* filter out non-block items */
|
val itemStack = mc.player.inventory.mainInventory[i]
|
||||||
val stack = mc.player.inventory.getStackInSlot(i)
|
if (itemStack.isEmpty || itemStack.item !is ItemBlock) continue
|
||||||
|
return i
|
||||||
if (isBlock(stack, belowBlockPos)) {
|
|
||||||
newSlot = i
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* check if any blocks were found, and if they were then set the slot */
|
|
||||||
if (newSlot != -1) {
|
|
||||||
mc.player.inventory.currentItem = newSlot
|
|
||||||
}
|
}
|
||||||
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun isBlock(stack: ItemStack, belowBlockPos: BlockPos): Boolean {
|
|
||||||
/* filter out non-block items */
|
|
||||||
if (stack == ItemStack.EMPTY || stack.getItem() !is ItemBlock) return false
|
|
||||||
|
|
||||||
val block = (stack.getItem() as ItemBlock).block
|
|
||||||
if (BlockUtils.blackList.contains(block) || block is BlockContainer) return false
|
|
||||||
|
|
||||||
/* filter out non-solid blocks */
|
|
||||||
if (!Block.getBlockFromItem(stack.getItem()).defaultState.isFullBlock) return false
|
|
||||||
|
|
||||||
/* don't use falling blocks if it'd fall */
|
|
||||||
if ((stack.getItem() as ItemBlock).block is BlockFalling) {
|
|
||||||
if (mc.world.getBlockState(belowBlockPos).material.isReplaceable) return false
|
|
||||||
}
|
|
||||||
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
}
|
|
@ -1,12 +1,16 @@
|
||||||
package me.zeroeightsix.kami.util
|
package me.zeroeightsix.kami.util
|
||||||
|
|
||||||
|
import me.zeroeightsix.kami.command.SafeClientEvent
|
||||||
|
import me.zeroeightsix.kami.manager.managers.PlayerPacketManager
|
||||||
import me.zeroeightsix.kami.util.math.RotationUtils
|
import me.zeroeightsix.kami.util.math.RotationUtils
|
||||||
import net.minecraft.client.Minecraft
|
import net.minecraft.client.Minecraft
|
||||||
import net.minecraft.init.Blocks
|
import net.minecraft.init.Blocks
|
||||||
|
import net.minecraft.item.ItemBlock
|
||||||
import net.minecraft.network.play.client.CPacketPlayer
|
import net.minecraft.network.play.client.CPacketPlayer
|
||||||
import net.minecraft.network.play.client.CPacketPlayerTryUseItemOnBlock
|
import net.minecraft.network.play.client.CPacketPlayerTryUseItemOnBlock
|
||||||
import net.minecraft.util.EnumFacing
|
import net.minecraft.util.EnumFacing
|
||||||
import net.minecraft.util.EnumHand
|
import net.minecraft.util.EnumHand
|
||||||
|
import net.minecraft.util.SoundCategory
|
||||||
import net.minecraft.util.math.AxisAlignedBB
|
import net.minecraft.util.math.AxisAlignedBB
|
||||||
import net.minecraft.util.math.BlockPos
|
import net.minecraft.util.math.BlockPos
|
||||||
import net.minecraft.util.math.RayTraceResult
|
import net.minecraft.util.math.RayTraceResult
|
||||||
|
@ -54,16 +58,6 @@ object BlockUtils {
|
||||||
|
|
||||||
private val mc = Minecraft.getMinecraft()
|
private val mc = Minecraft.getMinecraft()
|
||||||
|
|
||||||
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)
|
|
||||||
}
|
|
||||||
|
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
fun faceVectorPacketInstant(vec: Vec3d) {
|
fun faceVectorPacketInstant(vec: Vec3d) {
|
||||||
val rotation = RotationUtils.getRotationTo(vec, true)
|
val rotation = RotationUtils.getRotationTo(vec, true)
|
||||||
|
@ -84,8 +78,14 @@ object BlockUtils {
|
||||||
return rayTraceTo(blockPos)?.sideHit ?: EnumFacing.UP
|
return rayTraceTo(blockPos)?.sideHit ?: EnumFacing.UP
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun getHitVec(pos: BlockPos, facing: EnumFacing): Vec3d {
|
||||||
|
val vec = facing.directionVec
|
||||||
|
return Vec3d(vec.x * 0.5 + 0.5 + pos.x, vec.y * 0.5 + 0.5 + pos.y, vec.z * 0.5 + 0.5 + pos.z)
|
||||||
|
}
|
||||||
|
|
||||||
fun getHitVecOffset(facing: EnumFacing): Vec3d {
|
fun getHitVecOffset(facing: EnumFacing): Vec3d {
|
||||||
return Vec3d(facing.directionVec).scale(0.5).add(0.5, 0.5, 0.5)
|
val vec = facing.directionVec
|
||||||
|
return Vec3d(vec.x * 0.5 + 0.5, vec.y * 0.5 + 0.5, vec.z * 0.5 + 0.5)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -178,8 +178,14 @@ object BlockUtils {
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getNeighbour(blockPos: BlockPos, attempts: Int = 3, range: Float = 4.25f, toIgnore: HashSet<BlockPos> = HashSet()): Pair<EnumFacing, BlockPos>? {
|
fun getNeighbour(
|
||||||
for (side in EnumFacing.values()) {
|
blockPos: BlockPos,
|
||||||
|
attempts: Int = 3,
|
||||||
|
range: Float = 4.25f,
|
||||||
|
sides: Array<EnumFacing> = EnumFacing.values(),
|
||||||
|
toIgnore: HashSet<BlockPos> = HashSet()
|
||||||
|
): Pair<EnumFacing, BlockPos>? {
|
||||||
|
for (side in sides) {
|
||||||
val pos = blockPos.offset(side)
|
val pos = blockPos.offset(side)
|
||||||
if (!toIgnore.add(pos)) continue
|
if (!toIgnore.add(pos)) continue
|
||||||
if (mc.world.getBlockState(pos).material.isReplaceable) continue
|
if (mc.world.getBlockState(pos).material.isReplaceable) continue
|
||||||
|
@ -188,10 +194,10 @@ object BlockUtils {
|
||||||
}
|
}
|
||||||
if (attempts > 1) {
|
if (attempts > 1) {
|
||||||
toIgnore.add(blockPos)
|
toIgnore.add(blockPos)
|
||||||
for (side in EnumFacing.values()) {
|
for (side in sides) {
|
||||||
val pos = blockPos.offset(side)
|
val pos = blockPos.offset(side)
|
||||||
if (!isPlaceable(pos)) continue
|
if (!isPlaceable(pos)) continue
|
||||||
return getNeighbour(pos, attempts - 1, range, toIgnore) ?: continue
|
return getNeighbour(pos, attempts - 1, range, sides, toIgnore) ?: continue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return null
|
return null
|
||||||
|
@ -211,4 +217,24 @@ object BlockUtils {
|
||||||
mc.player.swingArm(EnumHand.MAIN_HAND)
|
mc.player.swingArm(EnumHand.MAIN_HAND)
|
||||||
Thread.sleep((10f / placeSpeed).toLong())
|
Thread.sleep((10f / placeSpeed).toLong())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Placing block without desync
|
||||||
|
*/
|
||||||
|
fun SafeClientEvent.placeBlock(pos: BlockPos, side: EnumFacing) {
|
||||||
|
if (!isPlaceable(pos.offset(side))) return
|
||||||
|
|
||||||
|
val hitVecOffset = getHitVecOffset(side)
|
||||||
|
val placePacket = CPacketPlayerTryUseItemOnBlock(pos, side, EnumHand.MAIN_HAND, hitVecOffset.x.toFloat(), hitVecOffset.y.toFloat(), hitVecOffset.z.toFloat())
|
||||||
|
connection.sendPacket(placePacket)
|
||||||
|
player.swingArm(EnumHand.MAIN_HAND)
|
||||||
|
|
||||||
|
val itemStack = PlayerPacketManager.getHoldingItemStack()
|
||||||
|
val block = (itemStack.item as? ItemBlock?)?.block ?: return
|
||||||
|
val metaData = itemStack.metadata
|
||||||
|
val blockState = block.getStateForPlacement(world, pos, side, hitVecOffset.x.toFloat(), hitVecOffset.y.toFloat(), hitVecOffset.z.toFloat(), metaData, player, EnumHand.MAIN_HAND)
|
||||||
|
val soundType = blockState.block.getSoundType(blockState, world, pos, player)
|
||||||
|
world.playSound(player, pos, soundType.placeSound, SoundCategory.BLOCKS, (soundType.getVolume() + 1.0f) / 2.0f, soundType.getPitch() * 0.8f)
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -148,6 +148,6 @@ object VectorUtils {
|
||||||
}
|
}
|
||||||
|
|
||||||
fun BlockPos.toVec3d(): Vec3d {
|
fun BlockPos.toVec3d(): Vec3d {
|
||||||
return Vec3d(this).add(0.5, 0.5, 0.5)
|
return Vec3d(x + 0.5, y + 0.5, z + 0.5)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue