Skip to content

Commit

Permalink
feat: antibot improvements (#4038)
Browse files Browse the repository at this point in the history
- fix not using EntityID (fixes AntiBot for Matrix)
- added attributes option (works on Matrix)
- added swung option
- added critted option (works only on newer server)
- adjusted default settings
  • Loading branch information
1zun4 authored Oct 1, 2024
1 parent 02a01a9 commit e5ff976
Show file tree
Hide file tree
Showing 2 changed files with 91 additions and 33 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,12 @@ package net.ccbluex.liquidbounce.features.module.modules.misc.antibot

import com.mojang.authlib.GameProfile
import net.ccbluex.liquidbounce.event.events.TagEntityEvent
import net.ccbluex.liquidbounce.event.events.WorldChangeEvent
import net.ccbluex.liquidbounce.event.handler
import net.ccbluex.liquidbounce.features.module.Category
import net.ccbluex.liquidbounce.features.module.Module
import net.ccbluex.liquidbounce.features.module.modules.misc.antibot.modes.CustomAntiBotMode
import net.ccbluex.liquidbounce.features.module.modules.misc.antibot.modes.CustomAntiBotMode.reset
import net.ccbluex.liquidbounce.features.module.modules.misc.antibot.modes.HorizonAntiBotMode
import net.ccbluex.liquidbounce.features.module.modules.misc.antibot.modes.IntaveHeavyAntiBotMode
import net.ccbluex.liquidbounce.features.module.modules.misc.antibot.modes.MatrixAntiBotMode
Expand Down Expand Up @@ -53,6 +55,13 @@ object ModuleAntiBot : Module("AntiBot", Category.MISC) {
}
}

@Suppress("unused")
private val handleWorldChange = handler<WorldChangeEvent> {
this.modes.choices.forEach {
(it as IAntiBotMode).reset()
}
}

fun isADuplicate(profile: GameProfile): Boolean {
return network.playerList.count { it.profile.name == profile.name && it.profile.id != profile.id } == 1
}
Expand Down Expand Up @@ -86,7 +95,7 @@ object ModuleAntiBot : Module("AntiBot", Category.MISC) {
}

interface IAntiBotMode {
fun reset() {}
fun reset() { }
fun isBot(entity: PlayerEntity): Boolean
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,17 +23,20 @@ import net.ccbluex.liquidbounce.config.ChoiceConfigurable
import net.ccbluex.liquidbounce.config.ToggleableConfigurable
import net.ccbluex.liquidbounce.event.events.AttackEvent
import net.ccbluex.liquidbounce.event.events.PacketEvent
import net.ccbluex.liquidbounce.event.events.WorldChangeEvent
import net.ccbluex.liquidbounce.event.handler
import net.ccbluex.liquidbounce.event.repeatable
import net.ccbluex.liquidbounce.features.module.modules.misc.antibot.ModuleAntiBot
import net.ccbluex.liquidbounce.features.module.modules.misc.antibot.ModuleAntiBot.isADuplicate
import net.minecraft.entity.Entity
import net.minecraft.entity.player.PlayerEntity
import net.minecraft.network.packet.s2c.play.EntitiesDestroyS2CPacket
import net.minecraft.network.packet.s2c.play.EntityAnimationS2CPacket
import net.minecraft.network.packet.s2c.play.EntityAttributesS2CPacket
import net.minecraft.network.packet.s2c.play.EntityS2CPacket
import java.util.*
import kotlin.math.abs

object CustomAntiBotMode : Choice("Custom"), ModuleAntiBot.IAntiBotMode {

override val parent: ChoiceConfigurable<*>
get() = ModuleAntiBot.modes

Expand All @@ -46,56 +49,95 @@ object CustomAntiBotMode : Choice("Custom"), ModuleAntiBot.IAntiBotMode {
tree(AlwaysInRadius)
}

private val duplicate by boolean("Duplicate", true)
private val duplicate by boolean("Duplicate", false)
private val noGameMode by boolean("NoGameMode", true)
private val illegalPitch by boolean("IllegalPitch", true)
private val fakeEntityID by boolean("FakeEntityID", false)
private val illegalName by boolean("IllegalName", false)
private val fakeEntityID by boolean("FakeEntityID", true)
private val illegalName by boolean("IllegalName", true)
private val needHit by boolean("NeedHit", false)
private val health by boolean("IllegalHealth", false)
private val swung by boolean("Swung", false)
private val critted by boolean("Critted", false)
private val attributes by boolean("Attributes", false)

private object AlwaysInRadius : ToggleableConfigurable(ModuleAntiBot, "AlwaysInRadius", false) {
val alwaysInRadiusRange by float("AlwaysInRadiusRange", 20f, 5f..30f)
}

private val invalidGroundList = mutableMapOf<Entity, Int>()
private val hitList = HashSet<UUID>()
private val notAlwaysInRadius = HashSet<UUID>()
private val flyingSet = mutableMapOf<Int, Int>()
private val hitListSet = hashSetOf<Int>()
private val notAlwaysInRadiusSet = hashSetOf<Int>()

private val swungSet = hashSetOf<Int>()
private val crittedSet = hashSetOf<Int>()
private val attributesSet = mutableListOf<Int>()

val repeatable = repeatable {
for (entity in world.players) {
if (player.distanceTo(entity) > AlwaysInRadius.alwaysInRadiusRange) {
notAlwaysInRadius.add(entity.uuid)
notAlwaysInRadiusSet.add(entity.id)
}
}
}

val attackHandler = handler<AttackEvent> {
hitList.add(it.enemy.uuid)
@Suppress("unused")
private val attackHandler = handler<AttackEvent> {
hitListSet.add(it.enemy.id)
}

val packetHandler = handler<PacketEvent> {
if (it.packet !is EntityS2CPacket || !it.packet.isPositionChanged || !InvalidGround.enabled) {
return@handler
}
@Suppress("unused")
private val packetHandler = handler<PacketEvent> { event ->
when (val packet = event.packet) {
is EntityS2CPacket -> {
if (!packet.isPositionChanged || !InvalidGround.enabled) {
return@handler
}

val entity = packet.getEntity(world) ?: return@handler
if (entity.isOnGround && entity.prevY != entity.y) {
flyingSet[entity.id] = flyingSet.getOrDefault(entity.id, 0) + 1
} else if (!entity.isOnGround && flyingSet.getOrDefault(entity.id, 0) > 0) {
val newVL = flyingSet.getOrDefault(entity.id, 0) / 2

if (newVL <= 0) {
flyingSet -= entity.id
} else {
flyingSet[entity.id] = newVL
}
}
}

val entity = it.packet.getEntity(world) ?: return@handler
is EntityAttributesS2CPacket -> {
attributesSet += packet.entityId
}

if (entity.isOnGround && entity.prevY != entity.y) {
invalidGroundList[entity] = invalidGroundList.getOrDefault(entity, 0) + 1
} else if (!entity.isOnGround && invalidGroundList.getOrDefault(entity, 0) > 0) {
val newVL = invalidGroundList.getOrDefault(entity, 0) / 2
is EntityAnimationS2CPacket -> {
val animationId = packet.animationId

if (newVL <= 0) {
invalidGroundList.remove(entity)
} else {
invalidGroundList[entity] = newVL
if (animationId == EntityAnimationS2CPacket.SWING_MAIN_HAND ||
animationId == EntityAnimationS2CPacket.SWING_OFF_HAND) {
swungSet += packet.entityId
} else if (animationId == EntityAnimationS2CPacket.CRIT ||
animationId == EntityAnimationS2CPacket.ENCHANTED_HIT) {
crittedSet += packet.entityId
}
}

is EntitiesDestroyS2CPacket -> {
for (entityId in packet.entityIds) {
attributesSet -= entityId
flyingSet -= entityId
hitListSet -= entityId
notAlwaysInRadiusSet -= entityId
}
}
}


}

private fun hasInvalidGround(player: PlayerEntity): Boolean {
return invalidGroundList.getOrDefault(player, 0) >= InvalidGround.vlToConsiderAsBot
return flyingSet.getOrDefault(player.id, 0) >= InvalidGround.vlToConsiderAsBot
}

private fun hasIllegalName(player: PlayerEntity): Boolean {
Expand All @@ -115,25 +157,32 @@ object CustomAntiBotMode : Choice("Custom"), ModuleAntiBot.IAntiBotMode {
private fun meetsCustomConditions(player: PlayerEntity): Boolean {
val noGameMode = noGameMode && network.getPlayerListEntry(player.uuid)?.gameMode == null
val invalidGround = InvalidGround.enabled && hasInvalidGround(player)
val fakeID = fakeEntityID && (player.id < 0 || player.id >= 1E+9)
val fakeId = fakeEntityID && (player.id < 0 || player.id >= 1E+9)
val isADuplicate = duplicate && isADuplicate(player.gameProfile)
val illegalName = illegalName && hasIllegalName(player)
val illegalPitch = illegalPitch && abs(player.pitch) > 90
val alwaysInRadius = AlwaysInRadius.enabled && !notAlwaysInRadius.contains(player.uuid)
val needHit = needHit && !hitList.contains(player.uuid)
val alwaysInRadius = AlwaysInRadius.enabled && !notAlwaysInRadiusSet.contains(player.id)
val needHit = needHit && !hitListSet.contains(player.id)
val health = health && player.health > 20f
val swung = swung && !swungSet.contains(player.id)
val critted = critted && !crittedSet.contains(player.id)
val attributes = attributes && !attributesSet.contains(player.id)

return noGameMode || invalidGround || fakeID || isADuplicate
return noGameMode || invalidGround || fakeId || isADuplicate
|| illegalName || illegalPitch || alwaysInRadius || needHit || health
|| swung || critted || attributes
}

override fun isBot(entity: PlayerEntity): Boolean {
return meetsCustomConditions(entity)
}

override fun reset() {
invalidGroundList.clear()
notAlwaysInRadius.clear()
hitList.clear()
flyingSet.clear()
notAlwaysInRadiusSet.clear()
hitListSet.clear()
swungSet.clear()
crittedSet.clear()
attributesSet.clear()
}
}

0 comments on commit e5ff976

Please sign in to comment.