From 4795c851638e96ceb6082b24d1e341d7fdf04d0f Mon Sep 17 00:00:00 2001 From: violetc <58360096+s-yh-china@users.noreply.github.com> Date: Mon, 17 Mar 2025 01:13:58 +0800 Subject: [PATCH] Fakeplayer Tick Type, fix knockback and piston SlimeBlock --- .../features/0006-Leaves-Fakeplayer.patch | 67 ++-- .../0030-Player-operation-limiter.patch | 4 +- .../0033-MC-Technical-Survival-Mode.patch | 4 +- .../0034-Return-nether-portal-fix.patch | 4 +- .../org/leavesmc/leaves/LeavesConfig.java | 29 +- .../java/org/leavesmc/leaves/bot/BotList.java | 3 +- .../org/leavesmc/leaves/bot/ServerBot.java | 338 +++++++++--------- .../leavesmc/leaves/bot/agent/Configs.java | 1 + .../bot/agent/configs/TickTypeConfig.java | 47 +++ 9 files changed, 273 insertions(+), 224 deletions(-) create mode 100644 leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/configs/TickTypeConfig.java diff --git a/leaves-server/minecraft-patches/features/0006-Leaves-Fakeplayer.patch b/leaves-server/minecraft-patches/features/0006-Leaves-Fakeplayer.patch index 9f0c8ff5..a5f6ae17 100644 --- a/leaves-server/minecraft-patches/features/0006-Leaves-Fakeplayer.patch +++ b/leaves-server/minecraft-patches/features/0006-Leaves-Fakeplayer.patch @@ -188,7 +188,7 @@ index 60425aade859c03ec21669b33d6b5096e444f6e9..9fba04e8a8e95546f7d7cc1210b4b324 } diff --git a/net/minecraft/server/level/ServerPlayer.java b/net/minecraft/server/level/ServerPlayer.java -index 3de65c4025be91d938a350c884975cb6edc234d3..d0adf5df51dc47b1569e1ee2c307fe62933e145f 100644 +index 3de65c4025be91d938a350c884975cb6edc234d3..339cec1f040d47bb37834c6ebe0633b7c991e0cd 100644 --- a/net/minecraft/server/level/ServerPlayer.java +++ b/net/minecraft/server/level/ServerPlayer.java @@ -197,7 +197,7 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc @@ -200,46 +200,7 @@ index 3de65c4025be91d938a350c884975cb6edc234d3..d0adf5df51dc47b1569e1ee2c307fe62 private final PlayerAdvancements advancements; private final ServerStatsCounter stats; private float lastRecordedHealthAndAbsorption = Float.MIN_VALUE; -@@ -811,16 +811,20 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc - this.invulnerableTime--; - } - -- // Paper start - Configurable container update tick rate -- if (--this.containerUpdateDelay <= 0) { -- this.containerMenu.broadcastChanges(); -- this.containerUpdateDelay = this.level().paperConfig().tickRates.containerUpdate; -- } -- // Paper end - Configurable container update tick rate -- if (this.containerMenu != this.inventoryMenu && (this.isImmobile() || !this.containerMenu.stillValid(this))) { // Paper - Prevent opening inventories when frozen -- this.closeContainer(org.bukkit.event.inventory.InventoryCloseEvent.Reason.CANT_USE); // Paper - Inventory close reason -- this.containerMenu = this.inventoryMenu; -+ // Leaves start - skip bot -+ if (!(this instanceof org.leavesmc.leaves.bot.ServerBot)) { -+ // Paper start - Configurable container update tick rate -+ if (--this.containerUpdateDelay <= 0) { -+ this.containerMenu.broadcastChanges(); -+ this.containerUpdateDelay = this.level().paperConfig().tickRates.containerUpdate; -+ } -+ // Paper end - Configurable container update tick rate -+ if (this.containerMenu != this.inventoryMenu && (this.isImmobile() || !this.containerMenu.stillValid(this))) { // Paper - Prevent opening inventories when frozen -+ this.closeContainer(org.bukkit.event.inventory.InventoryCloseEvent.Reason.CANT_USE); // Paper - Inventory close reason -+ this.containerMenu = this.inventoryMenu; -+ } - } -+ // Leaves end - skip bot - - Entity camera = this.getCamera(); - if (camera != this) { -@@ -835,7 +839,7 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc - } - } - -- CriteriaTriggers.TICK.trigger(this); -+ if (!(this instanceof org.leavesmc.leaves.bot.ServerBot)) CriteriaTriggers.TICK.trigger(this); // Leaves - skip bot - if (this.levitationStartPos != null) { - CriteriaTriggers.LEVITATION.trigger(this, this.levitationStartPos, this.tickCount - this.levitationStartTime); - } -@@ -1469,6 +1473,11 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc +@@ -1469,6 +1469,11 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc this.lastSentHealth = -1.0F; this.lastSentFood = -1; @@ -351,7 +312,7 @@ index e6bbcfed42233a31b72533c1f45b88b401b273a3..c599b8196d0eb72290081a533e565144 final boolean yZero = movement.y == 0.0; final boolean zZero = movement.z == 0.0; diff --git a/net/minecraft/world/entity/player/Player.java b/net/minecraft/world/entity/player/Player.java -index a0813aa9ebf5b32375b1bc9f294d8fc34cc867fe..6fa522d6935c277f2fc35bb772aa7b18b4adf6e3 100644 +index a0813aa9ebf5b32375b1bc9f294d8fc34cc867fe..4ff40881c2d58881497794d2abb6efbfcd53d524 100644 --- a/net/minecraft/world/entity/player/Player.java +++ b/net/minecraft/world/entity/player/Player.java @@ -186,7 +186,7 @@ public abstract class Player extends LivingEntity { @@ -385,6 +346,15 @@ index a0813aa9ebf5b32375b1bc9f294d8fc34cc867fe..6fa522d6935c277f2fc35bb772aa7b18 entity.playerTouch(this); } +@@ -1347,7 +1353,7 @@ public abstract class Player extends LivingEntity { + this.sweepAttack(); + } + +- if (target instanceof ServerPlayer && target.hurtMarked) { ++ if ((target instanceof ServerPlayer && !(target instanceof org.leavesmc.leaves.bot.ServerBot)) && target.hurtMarked) { // Leaves - bot knockback + // CraftBukkit start - Add Velocity Event + boolean cancelled = false; + org.bukkit.entity.Player player = (org.bukkit.entity.Player) target.getBukkitEntity(); diff --git a/net/minecraft/world/entity/projectile/FishingHook.java b/net/minecraft/world/entity/projectile/FishingHook.java index 1e012c7ef699a64ff3f1b00f897bb893ab25ecbd..f2bf0cdbd29438ca51b74ae2fcdf49dba0d52804 100644 --- a/net/minecraft/world/entity/projectile/FishingHook.java @@ -433,6 +403,19 @@ index acca8c51d2030c675c157b10d0bbc6af631afe61..b4721c4e81cc2ae989765d86bd51ebf0 private boolean tryItemClickBehaviourOverride(Player player, ClickAction action, Slot slot, ItemStack clickedItem, ItemStack carriedItem) { FeatureFlagSet featureFlagSet = player.level().enabledFeatures(); return carriedItem.isItemEnabled(featureFlagSet) && carriedItem.overrideStackedOnOther(slot, action, player) +diff --git a/net/minecraft/world/level/block/piston/PistonMovingBlockEntity.java b/net/minecraft/world/level/block/piston/PistonMovingBlockEntity.java +index ee2f8e8deb35059824b5730a1442f383dc79f01c..190377ccd52458c6b490fad25983fe992b0aa0da 100644 +--- a/net/minecraft/world/level/block/piston/PistonMovingBlockEntity.java ++++ b/net/minecraft/world/level/block/piston/PistonMovingBlockEntity.java +@@ -132,7 +132,7 @@ public class PistonMovingBlockEntity extends BlockEntity { + break; + } + +- if (!(entity instanceof ServerPlayer)) { ++ if (!(entity instanceof ServerPlayer) || (entity instanceof org.leavesmc.leaves.bot.ServerBot)) { // Leaves - bot slime block + Vec3 deltaMovement = entity.getDeltaMovement(); + double d1 = deltaMovement.x; + double d2 = deltaMovement.y; diff --git a/net/minecraft/world/level/levelgen/PhantomSpawner.java b/net/minecraft/world/level/levelgen/PhantomSpawner.java index 11d25e64349b27bf54dc1620e4cce444c79f581c..82d9d53ef0aa57342173af29d14d00e4039fb583 100644 --- a/net/minecraft/world/level/levelgen/PhantomSpawner.java diff --git a/leaves-server/minecraft-patches/features/0030-Player-operation-limiter.patch b/leaves-server/minecraft-patches/features/0030-Player-operation-limiter.patch index 140f60b8..be0fc72e 100644 --- a/leaves-server/minecraft-patches/features/0030-Player-operation-limiter.patch +++ b/leaves-server/minecraft-patches/features/0030-Player-operation-limiter.patch @@ -6,7 +6,7 @@ Subject: [PATCH] Player operation limiter This patch is Powered by plusls-carpet-addition(https://github.com/plusls/plusls-carpet-addition) diff --git a/net/minecraft/server/level/ServerPlayer.java b/net/minecraft/server/level/ServerPlayer.java -index d0adf5df51dc47b1569e1ee2c307fe62933e145f..f68ef6c8209b0bfa288800ac8bd42e1673bb4077 100644 +index 339cec1f040d47bb37834c6ebe0633b7c991e0cd..b18a818e4d795b6fb269ad57ffb49840c8d879ab 100644 --- a/net/minecraft/server/level/ServerPlayer.java +++ b/net/minecraft/server/level/ServerPlayer.java @@ -400,6 +400,10 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc @@ -28,7 +28,7 @@ index d0adf5df51dc47b1569e1ee2c307fe62933e145f..f68ef6c8209b0bfa288800ac8bd42e16 this.gameMode.tick(); this.wardenSpawnTracker.tick(); if (this.invulnerableTime > 0) { -@@ -3094,4 +3099,31 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc +@@ -3090,4 +3095,31 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc return (org.bukkit.craftbukkit.entity.CraftPlayer) super.getBukkitEntity(); } // CraftBukkit end diff --git a/leaves-server/minecraft-patches/features/0033-MC-Technical-Survival-Mode.patch b/leaves-server/minecraft-patches/features/0033-MC-Technical-Survival-Mode.patch index 2fa2959f..cac80e2a 100644 --- a/leaves-server/minecraft-patches/features/0033-MC-Technical-Survival-Mode.patch +++ b/leaves-server/minecraft-patches/features/0033-MC-Technical-Survival-Mode.patch @@ -6,10 +6,10 @@ Subject: [PATCH] MC Technical Survival Mode Will automatically overwrite some configuration after startup diff --git a/net/minecraft/server/level/ServerPlayer.java b/net/minecraft/server/level/ServerPlayer.java -index f68ef6c8209b0bfa288800ac8bd42e1673bb4077..863bf19a9c235be422f6cafb2b77735076801181 100644 +index b18a818e4d795b6fb269ad57ffb49840c8d879ab..0df1160ce4e027cc1c1bf7071a4d8730aaa7fde6 100644 --- a/net/minecraft/server/level/ServerPlayer.java +++ b/net/minecraft/server/level/ServerPlayer.java -@@ -1691,7 +1691,7 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc +@@ -1687,7 +1687,7 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc public boolean isInvulnerableTo(ServerLevel level, DamageSource damageSource) { return (super.isInvulnerableTo(level, damageSource) // Paper - disable player cramming; || this.isChangingDimension() && !damageSource.is(DamageTypes.ENDER_PEARL) diff --git a/leaves-server/minecraft-patches/features/0034-Return-nether-portal-fix.patch b/leaves-server/minecraft-patches/features/0034-Return-nether-portal-fix.patch index 2cd74e09..47ed7f93 100644 --- a/leaves-server/minecraft-patches/features/0034-Return-nether-portal-fix.patch +++ b/leaves-server/minecraft-patches/features/0034-Return-nether-portal-fix.patch @@ -6,10 +6,10 @@ Subject: [PATCH] Return nether portal fix This patch is powered by NetherPortalFix(https://github.com/TwelveIterationMods/NetherPortalFix) diff --git a/net/minecraft/server/level/ServerPlayer.java b/net/minecraft/server/level/ServerPlayer.java -index 863bf19a9c235be422f6cafb2b77735076801181..ad7df15ad454d896f9b243bad973dcf8496a06af 100644 +index 0df1160ce4e027cc1c1bf7071a4d8730aaa7fde6..eba1717566a8ea534bbf149e0593cc7656df2db9 100644 --- a/net/minecraft/server/level/ServerPlayer.java +++ b/net/minecraft/server/level/ServerPlayer.java -@@ -1488,6 +1488,21 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc +@@ -1484,6 +1484,21 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc org.bukkit.event.player.PlayerChangedWorldEvent changeEvent = new org.bukkit.event.player.PlayerChangedWorldEvent(this.getBukkitEntity(), serverLevel.getWorld()); this.level().getCraftServer().getPluginManager().callEvent(changeEvent); // CraftBukkit end diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/LeavesConfig.java b/leaves-server/src/main/java/org/leavesmc/leaves/LeavesConfig.java index 83636502..7a3d19c8 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/LeavesConfig.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/LeavesConfig.java @@ -7,21 +7,25 @@ import net.minecraft.server.level.ServerLevel; import org.bukkit.command.Command; import org.bukkit.configuration.file.YamlConfiguration; import org.jetbrains.annotations.NotNull; +import org.leavesmc.leaves.bot.ServerBot; import org.leavesmc.leaves.command.LeavesCommand; +import org.leavesmc.leaves.config.ConfigValidatorImpl.BooleanConfigValidator; +import org.leavesmc.leaves.config.ConfigValidatorImpl.DoubleConfigValidator; +import org.leavesmc.leaves.config.ConfigValidatorImpl.EnumConfigValidator; +import org.leavesmc.leaves.config.ConfigValidatorImpl.IntConfigValidator; +import org.leavesmc.leaves.config.ConfigValidatorImpl.ListConfigValidator; +import org.leavesmc.leaves.config.ConfigValidatorImpl.StringConfigValidator; +import org.leavesmc.leaves.config.GlobalConfigManager; import org.leavesmc.leaves.config.annotations.GlobalConfig; import org.leavesmc.leaves.config.annotations.GlobalConfigCategory; import org.leavesmc.leaves.config.annotations.RemovedConfig; -import org.leavesmc.leaves.config.GlobalConfigManager; +import org.leavesmc.leaves.protocol.CarpetServerProtocol.CarpetRule; +import org.leavesmc.leaves.protocol.CarpetServerProtocol.CarpetRules; +import org.leavesmc.leaves.protocol.bladeren.BladerenProtocol.LeavesFeature; +import org.leavesmc.leaves.protocol.bladeren.BladerenProtocol.LeavesFeatureSet; import org.leavesmc.leaves.region.RegionFileFormat; import org.leavesmc.leaves.util.MathUtils; -import org.leavesmc.leaves.config.ConfigValidatorImpl.BooleanConfigValidator; -import org.leavesmc.leaves.config.ConfigValidatorImpl.IntConfigValidator; -import org.leavesmc.leaves.config.ConfigValidatorImpl.StringConfigValidator; -import org.leavesmc.leaves.config.ConfigValidatorImpl.DoubleConfigValidator; -import org.leavesmc.leaves.config.ConfigValidatorImpl.ListConfigValidator; -import org.leavesmc.leaves.config.ConfigValidatorImpl.EnumConfigValidator; - import java.io.File; import java.io.IOException; import java.util.Collections; @@ -29,12 +33,6 @@ import java.util.List; import java.util.Locale; import java.util.Random; -import org.leavesmc.leaves.protocol.CarpetServerProtocol.CarpetRule; -import org.leavesmc.leaves.protocol.CarpetServerProtocol.CarpetRules; - -import org.leavesmc.leaves.protocol.bladeren.BladerenProtocol.LeavesFeatureSet; -import org.leavesmc.leaves.protocol.bladeren.BladerenProtocol.LeavesFeature; - public final class LeavesConfig { public static final String CONFIG_HEADER = "Configuration file for Leaves."; @@ -188,6 +186,9 @@ public final class LeavesConfig { @GlobalConfig(value = "cache-skin", lock = true) public boolean useSkinCache = false; + + @GlobalConfig(value = "tick-type") + public ServerBot.TickType tickType = ServerBot.TickType.NETWORK; } public MinecraftOLDConfig oldMC = new MinecraftOLDConfig(); diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/bot/BotList.java b/leaves-server/src/main/java/org/leavesmc/leaves/bot/BotList.java index 3881aa5c..fb950349 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/bot/BotList.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/bot/BotList.java @@ -23,6 +23,7 @@ import org.bukkit.craftbukkit.CraftWorld; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.leavesmc.leaves.LeavesConfig; +import org.leavesmc.leaves.bot.agent.Configs; import org.leavesmc.leaves.event.bot.BotCreateEvent; import org.leavesmc.leaves.event.bot.BotJoinEvent; import org.leavesmc.leaves.event.bot.BotLoadEvent; @@ -248,7 +249,7 @@ public class BotList { } public void networkTick() { - this.bots.forEach(ServerBot::doTick); + this.bots.stream().filter(bot -> bot.getConfigValue(Configs.TICK_TYPE) == ServerBot.TickType.NETWORK).forEach(ServerBot::doTick); // TODO perf? } @Nullable diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/bot/ServerBot.java b/leaves-server/src/main/java/org/leavesmc/leaves/bot/ServerBot.java index 467f48f2..1f72bb39 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/bot/ServerBot.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/bot/ServerBot.java @@ -3,7 +3,6 @@ package org.leavesmc.leaves.bot; import com.google.common.collect.ImmutableMap; import com.mojang.authlib.GameProfile; import io.papermc.paper.adventure.PaperAdventure; -import io.papermc.paper.event.entity.EntityKnockbackEvent; import net.minecraft.core.BlockPos; import net.minecraft.core.particles.BlockParticleOption; import net.minecraft.core.particles.ParticleTypes; @@ -40,7 +39,6 @@ import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.gameevent.GameEvent; import net.minecraft.world.level.portal.TeleportTransition; import net.minecraft.world.phys.EntityHitResult; -import net.minecraft.world.phys.Vec3; import org.bukkit.Bukkit; import org.bukkit.Location; import org.bukkit.command.CommandSender; @@ -72,8 +70,8 @@ import java.util.function.Predicate; public class ServerBot extends ServerPlayer { - private final Map, AbstractBotConfig> configs; private final List> actions; + private final Map, AbstractBotConfig> configs; public boolean resume = false; public BotCreateState createState; @@ -87,15 +85,13 @@ public class ServerBot extends ServerPlayer { public int removeTaskId = -1; - private Vec3 knockback = Vec3.ZERO; - public ServerBot(MinecraftServer server, ServerLevel world, GameProfile profile) { super(server, world, profile, ClientInformation.createDefault()); this.entityData.set(Player.DATA_PLAYER_MODE_CUSTOMISATION, (byte) -2); this.gameMode = new ServerBotGameMode(this); - this.actions = new ArrayList<>(); + this.actions = new ArrayList<>(); ImmutableMap.Builder, AbstractBotConfig> configBuilder = ImmutableMap.builder(); for (Configs config : Configs.getConfigs()) { configBuilder.put(config, config.createConfig(this)); @@ -108,78 +104,112 @@ public class ServerBot extends ServerPlayer { this.notSleepTicks = 0; this.fauxSleeping = LeavesConfig.modify.fakeplayer.canSkipSleep; - } - - public void sendPlayerInfo(ServerPlayer player) { - player.connection.send(new ClientboundPlayerInfoUpdatePacket(EnumSet.of(ClientboundPlayerInfoUpdatePacket.Action.ADD_PLAYER, ClientboundPlayerInfoUpdatePacket.Action.UPDATE_LISTED, ClientboundPlayerInfoUpdatePacket.Action.UPDATE_DISPLAY_NAME), List.of(this))); - } - - public boolean needSendFakeData(ServerPlayer player) { - return this.getConfigValue(Configs.ALWAYS_SEND_DATA) && (player.level() == this.level() && player.position().distanceToSqr(this.position()) > this.tracingRange); - } - - public void sendFakeDataIfNeed(ServerPlayer player, boolean login) { - if (needSendFakeData(player)) { - this.sendFakeData(player.connection, login); - } - } - - public void sendFakeData(ServerPlayerConnection playerConnection, boolean login) { - ChunkMap.TrackedEntity entityTracker = ((ServerLevel) this.level()).getChunkSource().chunkMap.entityMap.get(this.getId()); - - if (entityTracker == null) { - LeavesLogger.LOGGER.warning("Fakeplayer cant get entity tracker for " + this.getId()); - return; - } - - playerConnection.send(this.getAddEntityPacket(entityTracker.serverEntity)); - if (login) { - Bukkit.getScheduler().runTaskLater(MinecraftInternalPlugin.INSTANCE, () -> playerConnection.send(new ClientboundRotateHeadPacket(this, (byte) ((getYRot() * 256f) / 360f))), 10); - } else { - playerConnection.send(new ClientboundRotateHeadPacket(this, (byte) ((getYRot() * 256f) / 360f))); - } - } - - public void renderAll() { - this.server.getPlayerList().getPlayers().forEach( - player -> { - this.sendPlayerInfo(player); - this.sendFakeDataIfNeed(player, false); - } - ); - } - - private void sendPacket(Packet packet) { - this.server.getPlayerList().getPlayers().forEach(player -> player.connection.send(packet)); + this.setClientLoaded(true); } @Override - public void die(@NotNull DamageSource damageSource) { - boolean flag = this.serverLevel().getGameRules().getBoolean(GameRules.RULE_SHOWDEATHMESSAGES); - Component defaultMessage = this.getCombatTracker().getDeathMessage(); - - BotDeathEvent event = new BotDeathEvent(this.getBukkitEntity(), PaperAdventure.asAdventure(defaultMessage), flag); - this.server.server.getPluginManager().callEvent(event); - - if (event.isCancelled()) { - if (this.getHealth() <= 0) { - this.setHealth(0.1f); - } + public void tick() { + if (!this.isAlive()) { return; } - this.gameEvent(GameEvent.ENTITY_DIE); - - net.kyori.adventure.text.Component deathMessage = event.deathMessage(); - if (event.isSendDeathMessage() && deathMessage != null && !deathMessage.equals(net.kyori.adventure.text.Component.empty())) { - this.server.getPlayerList().broadcastSystemMessage(PaperAdventure.asVanilla(deathMessage), false); + if (this.getConfigValue(Configs.TICK_TYPE) == TickType.ENTITY_LIST) { + this.runAction(); } - this.server.getBotList().removeBot(this, BotRemoveEvent.RemoveReason.DEATH, null, false); + // copy ServerPlayer start + if (this.joining) { + this.joining = false; + } + + this.gameMode.tick(); + this.wardenSpawnTracker.tick(); + if (this.invulnerableTime > 0) { + this.invulnerableTime--; + } + // copy ServerPlayer end + + if (this.getConfigValue(Configs.SPAWN_PHANTOM)) { + notSleepTicks++; + } + + if (LeavesConfig.modify.fakeplayer.regenAmount > 0.0 && server.getTickCount() % 20 == 0) { + float health = getHealth(); + float maxHealth = getMaxHealth(); + float regenAmount = (float) (LeavesConfig.modify.fakeplayer.regenAmount * 20); + float amount; + + if (health < maxHealth - regenAmount) { + amount = health + regenAmount; + } else { + amount = maxHealth; + } + + this.setHealth(amount); + } + + if (this.getConfigValue(Configs.TICK_TYPE) == TickType.ENTITY_LIST) { + this.doTick(); + } } - public void removeTab() { - this.sendPacket(new ClientboundPlayerInfoRemovePacket(List.of(this.getUUID()))); + @Override + public void doTick() { + this.absMoveTo(this.getX(), this.getY(), this.getZ(), this.getYRot(), this.getXRot()); + + if (this.isPassenger()) { + this.setOnGround(false); + } + + if (this.takeXpDelay > 0) { + --this.takeXpDelay; + } + + if (this.isSleeping()) { + ++this.sleepCounter; + if (this.sleepCounter > 100) { + this.sleepCounter = 100; + this.notSleepTicks = 0; + } + + if (!this.level().isClientSide && this.level().isDay()) { + this.stopSleepInBed(false, true); + } + } else if (this.sleepCounter > 0) { + ++this.sleepCounter; + if (this.sleepCounter >= 110) { + this.sleepCounter = 0; + } + } + + this.updateIsUnderwater(); + + if (this.getConfigValue(Configs.TICK_TYPE) == TickType.NETWORK) { + this.server.scheduleOnMain(this::runAction); + } + + this.livingEntityTick(); + + this.foodData.tick(this); + + double d = Mth.clamp(this.getX(), -2.9999999E7, 2.9999999E7); + double d1 = Mth.clamp(this.getZ(), -2.9999999E7, 2.9999999E7); + if (d != this.getX() || d1 != this.getZ()) { + this.setPos(d, this.getY(), d1); + } + + ++this.attackStrengthTicker; + ItemStack itemstack = this.getMainHandItem(); + if (!ItemStack.matches(this.lastItemInMainHand, itemstack)) { + if (!ItemStack.isSameItem(this.lastItemInMainHand, itemstack)) { + this.resetAttackStrengthTicker(); + } + + this.lastItemInMainHand = itemstack.copy(); + } + + this.getCooldowns().tick(); + this.updatePlayerPose(); } @Override @@ -205,33 +235,6 @@ public class ServerBot extends ServerPlayer { public void handlePortal() { } - @Override - public void tick() { - if (!this.isAlive()) { - return; - } - super.tick(); - - if (this.getConfigValue(Configs.SPAWN_PHANTOM)) { - notSleepTicks++; - } - - if (LeavesConfig.modify.fakeplayer.regenAmount > 0.0 && server.getTickCount() % 20 == 0) { - float health = getHealth(); - float maxHealth = getMaxHealth(); - float regenAmount = (float) (LeavesConfig.modify.fakeplayer.regenAmount * 20); - float amount; - - if (health < maxHealth - regenAmount) { - amount = health + regenAmount; - } else { - amount = maxHealth; - } - - this.setHealth(amount); - } - } - @Override public void onItemPickup(@NotNull ItemEntity item) { super.onItemPickup(item); @@ -305,71 +308,6 @@ public class ServerBot extends ServerPlayer { } } - @Override - public void doTick() { - this.absMoveTo(this.getX(), this.getY(), this.getZ(), this.getYRot(), this.getXRot()); - - if (this.takeXpDelay > 0) { - --this.takeXpDelay; - } - - if (this.isSleeping()) { - ++this.sleepCounter; - if (this.sleepCounter > 100) { - this.sleepCounter = 100; - this.notSleepTicks = 0; - } - - if (!this.level().isClientSide && this.level().isDay()) { - this.stopSleepInBed(false, true); - } - } else if (this.sleepCounter > 0) { - ++this.sleepCounter; - if (this.sleepCounter >= 110) { - this.sleepCounter = 0; - } - } - - this.updateIsUnderwater(); - - this.addDeltaMovement(knockback); - this.knockback = Vec3.ZERO; - - this.server.scheduleOnMain(this::runAction); - - this.livingEntityTick(); - - this.foodData.tick(this); - - ++this.attackStrengthTicker; - ItemStack itemstack = this.getMainHandItem(); - if (!ItemStack.matches(this.lastItemInMainHand, itemstack)) { - if (!ItemStack.isSameItem(this.lastItemInMainHand, itemstack)) { - this.resetAttackStrengthTicker(); - } - - this.lastItemInMainHand = itemstack.copy(); - } - - this.getCooldowns().tick(); - this.updatePlayerPose(); - - if (this.hurtTime > 0) { - this.hurtTime -= 1; - } - } - - @Override - public void knockback(double strength, double x, double z, @Nullable Entity attacker, @NotNull EntityKnockbackEvent.Cause cause) { - strength *= 1.0D - this.getAttributeValue(Attributes.KNOCKBACK_RESISTANCE); - if (strength > 0.0D) { - Vec3 vec3d = this.getDeltaMovement(); - Vec3 vec3d1 = (new Vec3(x, 0.0D, z)).normalize().scale(strength); - this.hasImpulse = true; - this.knockback = new Vec3(vec3d.x / 2.0D - vec3d1.x, this.onGround() ? Math.min(0.4D, vec3d.y / 2.0D + strength) : vec3d.y, vec3d.z / 2.0D - vec3d1.z).subtract(vec3d); - } - } - @Override public void attack(@NotNull Entity target) { super.attack(target); @@ -462,6 +400,78 @@ public class ServerBot extends ServerPlayer { } } + public void sendPlayerInfo(ServerPlayer player) { + player.connection.send(new ClientboundPlayerInfoUpdatePacket(EnumSet.of(ClientboundPlayerInfoUpdatePacket.Action.ADD_PLAYER, ClientboundPlayerInfoUpdatePacket.Action.UPDATE_LISTED, ClientboundPlayerInfoUpdatePacket.Action.UPDATE_DISPLAY_NAME), List.of(this))); + } + + public boolean needSendFakeData(ServerPlayer player) { + return this.getConfigValue(Configs.ALWAYS_SEND_DATA) && (player.level() == this.level() && player.position().distanceToSqr(this.position()) > this.tracingRange); + } + + public void sendFakeDataIfNeed(ServerPlayer player, boolean login) { + if (needSendFakeData(player)) { + this.sendFakeData(player.connection, login); + } + } + + public void sendFakeData(ServerPlayerConnection playerConnection, boolean login) { + ChunkMap.TrackedEntity entityTracker = ((ServerLevel) this.level()).getChunkSource().chunkMap.entityMap.get(this.getId()); + + if (entityTracker == null) { + LeavesLogger.LOGGER.warning("Fakeplayer cant get entity tracker for " + this.getId()); + return; + } + + playerConnection.send(this.getAddEntityPacket(entityTracker.serverEntity)); + if (login) { + Bukkit.getScheduler().runTaskLater(MinecraftInternalPlugin.INSTANCE, () -> playerConnection.send(new ClientboundRotateHeadPacket(this, (byte) ((getYRot() * 256f) / 360f))), 10); + } else { + playerConnection.send(new ClientboundRotateHeadPacket(this, (byte) ((getYRot() * 256f) / 360f))); + } + } + + public void renderAll() { + this.server.getPlayerList().getPlayers().forEach( + player -> { + this.sendPlayerInfo(player); + this.sendFakeDataIfNeed(player, false); + } + ); + } + + private void sendPacket(Packet packet) { + this.server.getPlayerList().getPlayers().forEach(player -> player.connection.send(packet)); + } + + @Override + public void die(@NotNull DamageSource damageSource) { + boolean flag = this.serverLevel().getGameRules().getBoolean(GameRules.RULE_SHOWDEATHMESSAGES); + Component defaultMessage = this.getCombatTracker().getDeathMessage(); + + BotDeathEvent event = new BotDeathEvent(this.getBukkitEntity(), PaperAdventure.asAdventure(defaultMessage), flag); + this.server.server.getPluginManager().callEvent(event); + + if (event.isCancelled()) { + if (this.getHealth() <= 0) { + this.setHealth(0.1f); + } + return; + } + + this.gameEvent(GameEvent.ENTITY_DIE); + + net.kyori.adventure.text.Component deathMessage = event.deathMessage(); + if (event.isSendDeathMessage() && deathMessage != null && !deathMessage.equals(net.kyori.adventure.text.Component.empty())) { + this.server.getPlayerList().broadcastSystemMessage(PaperAdventure.asVanilla(deathMessage), false); + } + + this.server.getBotList().removeBot(this, BotRemoveEvent.RemoveReason.DEATH, null, false); + } + + public void removeTab() { + this.sendPacket(new ClientboundPlayerInfoRemovePacket(List.of(this.getUUID()))); + } + public void faceLocation(@NotNull Location loc) { this.look(loc.toVector().subtract(getLocation().toVector()), false); } @@ -531,7 +541,8 @@ public class ServerBot extends ServerPlayer { } @Override - public @NotNull ServerStatsCounter getStats() { + @NotNull + public ServerStatsCounter getStats() { return stats; } @@ -549,4 +560,9 @@ public class ServerBot extends ServerPlayer { public CraftBot getBukkitEntity() { return (CraftBot) super.getBukkitEntity(); } + + public enum TickType { + NETWORK, + ENTITY_LIST + } } diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/Configs.java b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/Configs.java index 0a42d42c..8418ae91 100644 --- a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/Configs.java +++ b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/Configs.java @@ -20,6 +20,7 @@ public class Configs { public static final Configs ALWAYS_SEND_DATA = register(AlwaysSendDataConfig.class, AlwaysSendDataConfig::new); public static final Configs SPAWN_PHANTOM = register(SpawnPhantomConfig.class, SpawnPhantomConfig::new); public static final Configs SIMULATION_DISTANCE = register(SimulationDistanceConfig.class, SimulationDistanceConfig::new); + public static final Configs TICK_TYPE = register(TickTypeConfig.class, TickTypeConfig::new); private final Class> configClass; private final Supplier> configCreator; diff --git a/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/configs/TickTypeConfig.java b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/configs/TickTypeConfig.java new file mode 100644 index 00000000..94c8ddde --- /dev/null +++ b/leaves-server/src/main/java/org/leavesmc/leaves/bot/agent/configs/TickTypeConfig.java @@ -0,0 +1,47 @@ +package org.leavesmc.leaves.bot.agent.configs; + +import net.minecraft.nbt.CompoundTag; +import org.jetbrains.annotations.NotNull; +import org.leavesmc.leaves.LeavesConfig; +import org.leavesmc.leaves.bot.ServerBot; +import org.leavesmc.leaves.bot.agent.AbstractBotConfig; +import org.leavesmc.leaves.command.CommandArgument; +import org.leavesmc.leaves.command.CommandArgumentType; + +import java.util.List; + +public class TickTypeConfig extends AbstractBotConfig { + + private static final String NAME = "tick_type"; + private static final CommandArgumentType TICK_TYPE_ARGUMENT = CommandArgumentType.of(ServerBot.TickType.class, (string -> ServerBot.TickType.valueOf(string.toUpperCase()))); + + private ServerBot.TickType value; + + public TickTypeConfig() { + super(NAME, CommandArgument.of(TICK_TYPE_ARGUMENT).setTabComplete(0, List.of("network", "entity_list"))); + this.value = LeavesConfig.modify.fakeplayer.tickType; + } + + @Override + public ServerBot.TickType getValue() { + return value; + } + + @Override + public void setValue(ServerBot.TickType value) throws IllegalArgumentException { + this.value = value; + } + + @Override + @NotNull + public CompoundTag save(@NotNull CompoundTag nbt) { + super.save(nbt); + nbt.putString(NAME, this.getValue().toString()); + return nbt; + } + + @Override + public void load(@NotNull CompoundTag nbt) { + this.setValue(TICK_TYPE_ARGUMENT.parse(nbt.getString(NAME))); + } +}