From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: violetc <58360096+s-yh-china@users.noreply.github.com> Date: Sun, 2 Feb 2025 15:28:11 +0800 Subject: [PATCH] Leaves Fakeplayer diff --git a/net/minecraft/advancements/critereon/SimpleCriterionTrigger.java b/net/minecraft/advancements/critereon/SimpleCriterionTrigger.java index a82d84283632342bd30bc3449983431ba43583e0..f59526f6bfa1b4af5b474f0b438513c96afb491c 100644 --- a/net/minecraft/advancements/critereon/SimpleCriterionTrigger.java +++ b/net/minecraft/advancements/critereon/SimpleCriterionTrigger.java @@ -39,6 +39,7 @@ public abstract class SimpleCriterionTrigger testTrigger) { + if (player instanceof org.leavesmc.leaves.bot.ServerBot) return; // Leaves - bot skip PlayerAdvancements advancements = player.getAdvancements(); Set> set = (Set) advancements.criterionData.get(this); // Paper - fix PlayerAdvancements leak if (set != null && !set.isEmpty()) { diff --git a/net/minecraft/network/Connection.java b/net/minecraft/network/Connection.java index 14addbaf68b7ad80490187d12d9c9b00891e2ce1..b186b5e0d3b32d7b51b2f58f0ef4b2bf36ae5c13 100644 --- a/net/minecraft/network/Connection.java +++ b/net/minecraft/network/Connection.java @@ -95,7 +95,7 @@ public class Connection extends SimpleChannelInboundHandler> { @Nullable private volatile PacketListener disconnectListener; @Nullable - private volatile PacketListener packetListener; + protected volatile PacketListener packetListener; // Leaves - private -> protected @Nullable private DisconnectionDetails disconnectionDetails; private boolean encrypted; diff --git a/net/minecraft/server/MinecraftServer.java b/net/minecraft/server/MinecraftServer.java index 2493722c47b92cbcd13c08af0caf38a543ac7e37..309ff4c55b2a4ccf3d18951b51c2e10d0ff39bfc 100644 --- a/net/minecraft/server/MinecraftServer.java +++ b/net/minecraft/server/MinecraftServer.java @@ -378,6 +378,8 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop S spin(Function threadFunction) { ca.spottedleaf.dataconverter.minecraft.datatypes.MCTypeRegistry.init(); // Paper - rewrite data converter system AtomicReference atomicReference = new AtomicReference<>(); @@ -1013,6 +1015,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop 0) { - if (this.playerList.getPlayerCount() == 0 && !this.tickRateManager.isSprinting() && this.pluginsBlockingSleep.isEmpty()) { // Paper - API to allow/disallow tick sleeping + if (this.playerList.getPlayerCount() == 0 && this.botList.bots.isEmpty() && !this.tickRateManager.isSprinting() && this.pluginsBlockingSleep.isEmpty()) { // Paper - API to allow/disallow tick sleeping // Leaves - fakeplayer this.emptyTicks++; } else { this.emptyTicks = 0; @@ -1857,6 +1860,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop players, @Nullable Component reason) throws CommandSyntaxException { UserBanList bans = source.getServer().getPlayerList().getBans(); int i = 0; - + boolean hasBot = false; // Leaves - disable kick for (NameAndId nameAndId : players) { + // Leaves start - disable ban + if (nameAndId.isBot()) { + source.sendFailure(Component.literal("Permission denied")); + hasBot = true; + continue; + } + // Leaves end - disable ban if (!bans.isBanned(nameAndId)) { UserBanListEntry userBanListEntry = new UserBanListEntry( nameAndId, null, source.getTextName(), null, reason == null ? null : reason.getString() @@ -63,7 +70,13 @@ public class BanPlayerCommands { } if (i == 0) { - throw ERROR_ALREADY_BANNED.create(); + // Leaves start - disable kick + if (hasBot) { + return i; + } else { + throw ERROR_ALREADY_BANNED.create(); + } + // Leaves end - disable kick } else { return i; } diff --git a/net/minecraft/server/commands/KickCommand.java b/net/minecraft/server/commands/KickCommand.java index a5e5b0e0cd67a65b9fe3f69416070429196c5fa8..1a756a09cd281e60e8802a4111f71b0be1c70dcf 100644 --- a/net/minecraft/server/commands/KickCommand.java +++ b/net/minecraft/server/commands/KickCommand.java @@ -46,9 +46,17 @@ public class KickCommand { if (!source.getServer().isPublished()) { throw ERROR_SINGLEPLAYER.create(); } else { + boolean hasBot = false; // Leaves - disable kick int i = 0; for (ServerPlayer serverPlayer : players) { + // Leaves start - disable kick + if (serverPlayer instanceof org.leavesmc.leaves.bot.ServerBot) { + source.sendFailure(Component.literal("Permission denied")); + hasBot = true; + continue; + } + // Leaves end - disable kick if (!source.getServer().isSingleplayerOwner(serverPlayer.nameAndId())) { serverPlayer.connection.disconnect(reason, org.bukkit.event.player.PlayerKickEvent.Cause.KICK_COMMAND); // Paper - kick event cause source.sendSuccess(() -> Component.translatable("commands.kick.success", serverPlayer.getDisplayName(), reason), true); @@ -57,7 +65,13 @@ public class KickCommand { } if (i == 0) { - throw ERROR_KICKING_OWNER.create(); + // Leaves start - disable kick + if (hasBot) { + return i; + } else { + throw ERROR_KICKING_OWNER.create(); + } + // Leaves end - disable kick } else { return i; } diff --git a/net/minecraft/server/commands/OpCommand.java b/net/minecraft/server/commands/OpCommand.java index 4c7bccc00b9e84c4744f6cdc2c2e574a33ffe324..065af7f615711d7830002cd8f3046fab706082c1 100644 --- a/net/minecraft/server/commands/OpCommand.java +++ b/net/minecraft/server/commands/OpCommand.java @@ -43,6 +43,7 @@ public class OpCommand { int i = 0; for (NameAndId nameAndId : players) { + if (nameAndId.isBot()) continue; // Leaves - disable op if (!playerList.isOp(nameAndId)) { playerList.op(nameAndId); i++; diff --git a/net/minecraft/server/dedicated/DedicatedServer.java b/net/minecraft/server/dedicated/DedicatedServer.java index 361034289bb5e4241f3313581ddbc4e33823a9eb..8d73fffb41346851d088ca0dee206661ff85ec29 100644 --- a/net/minecraft/server/dedicated/DedicatedServer.java +++ b/net/minecraft/server/dedicated/DedicatedServer.java @@ -255,6 +255,7 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface } // Spigot start + this.setBotList(new org.leavesmc.leaves.bot.BotList(this)); // Leaves - fakeplayer this.setPlayerList(new DedicatedPlayerList(this, this.registries(), this.playerDataStorage)); org.spigotmc.SpigotConfig.init((java.io.File) this.options.valueOf("spigot-settings")); org.spigotmc.SpigotConfig.registerCommands(); @@ -278,6 +279,7 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface com.destroystokyo.paper.VersionHistoryManager.INSTANCE.getClass(); // Paper - load version history now org.leavesmc.leaves.LeavesConfig.init((java.io.File) options.valueOf("leaves-settings")); // Leaves - Server Config + this.getBotList().loadResumeBotInfo(); // Leaves - load resident bot info com.destroystokyo.paper.Metrics.PaperMetrics.startMetrics(); // Paper - start metrics // Leaves - down diff --git a/net/minecraft/server/level/ChunkMap.java b/net/minecraft/server/level/ChunkMap.java index ce53eb1e966e07b04e6a13785a858a3318b2c573..1993907c606b231b879a7279d3880876f5307b1c 100644 --- a/net/minecraft/server/level/ChunkMap.java +++ b/net/minecraft/server/level/ChunkMap.java @@ -1365,6 +1365,13 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider } } else { this.removePlayer(player); + // Leaves start - render bot + if (entity instanceof org.leavesmc.leaves.bot.ServerBot bot) { + if (bot.needSendFakeData(player)) { + bot.sendFakeData(player.connection, false); + } + } + // Leaves end - render bot } } } diff --git a/net/minecraft/server/level/ServerLevel.java b/net/minecraft/server/level/ServerLevel.java index 0c9002b6ceaf5f11a059db356976215d5acf5cce..2bab1246cf658508228c7f662175692bfd82cad4 100644 --- a/net/minecraft/server/level/ServerLevel.java +++ b/net/minecraft/server/level/ServerLevel.java @@ -222,6 +222,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe public boolean hasPhysicsEvent = true; // Paper - BlockPhysicsEvent public boolean hasEntityMoveEvent; // Paper - Add EntityMoveEvent private final alternate.current.wire.WireHandler wireHandler = new alternate.current.wire.WireHandler(this); // Paper - optimize redstone (Alternate Current) + final List realPlayers; // Leaves - skip @Override public @Nullable LevelChunk getChunkIfLoaded(int x, int z) { @@ -699,6 +700,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe this.chunkDataController = new ca.spottedleaf.moonrise.patches.chunk_system.io.datacontroller.ChunkDataController((ServerLevel)(Object)this, this.chunkTaskScheduler); // Paper end - rewrite chunk system this.getCraftServer().addWorld(this.getWorld()); // CraftBukkit + this.realPlayers = Lists.newArrayList(); // Leaves - skip } // Paper start @@ -2279,6 +2281,12 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe return this.players; } + // Leaves start - fakeplayer skip + public List realPlayers() { + return this.realPlayers; + } + // Leaves end - fakeplayer skip + @Override public void updatePOIOnBlockStateChange(BlockPos pos, BlockState oldState, BlockState newState) { Optional> optional = PoiTypes.forState(oldState); @@ -2728,6 +2736,11 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe // ServerLevel.this.getChunkSource().addEntity(entity); // Paper - ignore and warn about illegal addEntity calls instead of crashing server; moved down below valid=true if (entity instanceof ServerPlayer serverPlayer) { ServerLevel.this.players.add(serverPlayer); + // Leaves start - skip + if (!(serverPlayer instanceof org.leavesmc.leaves.bot.ServerBot)) { + ServerLevel.this.realPlayers.add(serverPlayer); + } + // Leaves end - skip if (serverPlayer.isReceivingWaypoints()) { ServerLevel.this.getWaypointManager().addPlayer(serverPlayer); } @@ -2806,6 +2819,11 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe ServerLevel.this.getChunkSource().removeEntity(entity); if (entity instanceof ServerPlayer serverPlayer) { ServerLevel.this.players.remove(serverPlayer); + // Leaves start - skip + if (!(serverPlayer instanceof org.leavesmc.leaves.bot.ServerBot)) { + ServerLevel.this.realPlayers.remove(serverPlayer); + } + // Leaves end - skip ServerLevel.this.getWaypointManager().removePlayer(serverPlayer); ServerLevel.this.updateSleepingPlayerList(); } diff --git a/net/minecraft/server/level/ServerPlayer.java b/net/minecraft/server/level/ServerPlayer.java index b4a996ac6c570e988b38237a32f90ec5042cbc17..04ea4e33504703c4074aef6e74ec06dc772b1bb9 100644 --- a/net/minecraft/server/level/ServerPlayer.java +++ b/net/minecraft/server/level/ServerPlayer.java @@ -228,7 +228,7 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc private static final boolean DEFAULT_SPAWN_EXTRA_PARTICLES_ON_FALL = false; public ServerGamePacketListenerImpl connection; private final MinecraftServer server; - public final ServerPlayerGameMode gameMode; + public ServerPlayerGameMode gameMode; // Leaves - not final private final PlayerAdvancements advancements; private final ServerStatsCounter stats; private float lastRecordedHealthAndAbsorption = Float.MIN_VALUE; @@ -249,7 +249,7 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc private Entity camera; public boolean isChangingDimension; public boolean seenCredits = false; - private final ServerRecipeBook recipeBook; + protected ServerRecipeBook recipeBook; // Leaves - not final and private -> protected @Nullable private Vec3 levitationStartPos; private int levitationStartTime; @@ -1250,7 +1250,7 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc this.setClientLoaded(false); } - private void tellNeutralMobsThatIDied() { + protected void tellNeutralMobsThatIDied() { // Leaves private -> protected AABB aabb = new AABB(this.blockPosition()).inflate(32.0, 10.0, 32.0); this.level() .getEntitiesOfClass(Mob.class, aabb, EntitySelector.NO_SPECTATORS) @@ -1562,6 +1562,11 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc this.lastSentHealth = -1.0F; this.lastSentFood = -1; this.teleportSpectators(teleportTransition, serverLevel); + // Leaves start - bot support + if (org.leavesmc.leaves.LeavesConfig.modify.fakeplayer.enable) { + this.server.getBotList().bots.forEach(bot -> bot.sendFakeDataIfNeed(this, true)); // Leaves - render bot + } + // Leaves end - bot support // CraftBukkit start org.bukkit.event.player.PlayerChangedWorldEvent changeEvent = new org.bukkit.event.player.PlayerChangedWorldEvent(this.getBukkitEntity(), serverLevel.getWorld()); this.level().getCraftServer().getPluginManager().callEvent(changeEvent); diff --git a/net/minecraft/server/players/CachedUserNameToIdResolver.java b/net/minecraft/server/players/CachedUserNameToIdResolver.java index 3dc78b91cc853cfa6dce69979273b5f35b5f87f1..0625ebf19b5c514e096e6a91539c807ccf0b3f87 100644 --- a/net/minecraft/server/players/CachedUserNameToIdResolver.java +++ b/net/minecraft/server/players/CachedUserNameToIdResolver.java @@ -121,6 +121,12 @@ public class CachedUserNameToIdResolver implements UserNameToIdResolver { @Override public Optional get(String name) { + // Leaves start - fix bot + org.leavesmc.leaves.bot.ServerBot bot = org.leavesmc.leaves.bot.BotList.INSTANCE.getBotByName(name); + if (bot != null) { + return Optional.of(bot.nameAndId()); + } + // Leaves end - fix bot String string = name.toLowerCase(Locale.ROOT); boolean stateLocked = true; try { this.stateLock.lock(); // Paper - Fix GameProfileCache concurrency CachedUserNameToIdResolver.GameProfileInfo gameProfileInfo = this.profilesByName.get(string); diff --git a/net/minecraft/server/players/NameAndId.java b/net/minecraft/server/players/NameAndId.java index fdcc23c618b5db59e384a38f9ef91b6d2e922a8a..ccb56f29e79805f3286bbb80ce6c4d4b36a6e9e8 100644 --- a/net/minecraft/server/players/NameAndId.java +++ b/net/minecraft/server/players/NameAndId.java @@ -8,18 +8,22 @@ import java.util.UUID; import javax.annotation.Nullable; import net.minecraft.core.UUIDUtil; -public record NameAndId(UUID id, String name) { +public record NameAndId(UUID id, String name, boolean isBot) { // Leaves - fakeplayer public static final Codec CODEC = RecordCodecBuilder.create( instance -> instance.group(UUIDUtil.STRING_CODEC.fieldOf("id").forGetter(NameAndId::id), Codec.STRING.fieldOf("name").forGetter(NameAndId::name)) .apply(instance, NameAndId::new) ); public NameAndId(GameProfile profile) { - this(profile.id(), profile.name()); + this(profile.id(), profile.name(), com.google.common.collect.Iterables.getFirst(profile.properties().get("is_bot"), "false").equals("true")); // Leaves - fakeplayer } public NameAndId(com.mojang.authlib.yggdrasil.response.NameAndId nameAndId) { - this(nameAndId.id(), nameAndId.name()); + this(nameAndId.id(), nameAndId.name(), false); // Leaves - fakeplayer + } + + public NameAndId(UUID uuid, String name) { + this(uuid, name, false); // Leaves - fakeplayer } @Nullable @@ -34,7 +38,7 @@ public record NameAndId(UUID id, String name) { return null; } - return new NameAndId(uuid, json.get("name").getAsString()); + return new NameAndId(uuid, json.get("name").getAsString(), false); // Leaves - fakeplayer } else { return null; } @@ -47,7 +51,7 @@ public record NameAndId(UUID id, String name) { public static NameAndId createOffline(String name) { UUID uuid = UUIDUtil.createOfflinePlayerUUID(name); - return new NameAndId(uuid, name); + return new NameAndId(uuid, name, false); // Leaves - fakeplayer } // Paper start - utility method for common conversion back to the game profile diff --git a/net/minecraft/server/players/PlayerList.java b/net/minecraft/server/players/PlayerList.java index 4abf4ea7f86955351b5e4da2c89a707003802d2e..6dec8565e9d290302ce7766357a56b8c2295c163 100644 --- a/net/minecraft/server/players/PlayerList.java +++ b/net/minecraft/server/players/PlayerList.java @@ -241,6 +241,19 @@ public abstract class PlayerList { org.leavesmc.leaves.protocol.core.LeavesProtocolManager.handlePlayerJoin(player); + // Leaves start - bot support + if (org.leavesmc.leaves.LeavesConfig.modify.fakeplayer.enable) { + org.leavesmc.leaves.bot.ServerBot bot = this.server.getBotList().getBotByName(player.getScoreboardName()); + if (bot != null) { + this.server.getBotList().removeBot(bot, org.leavesmc.leaves.event.bot.BotRemoveEvent.RemoveReason.INTERNAL, player.getBukkitEntity(), false, false); + } + this.server.getBotList().bots.forEach(bot1 -> { + bot1.sendPlayerInfo(player); + bot1.sendFakeDataIfNeed(player, true); + }); // Leaves - render bot + } + // Leaves end - bot support + final net.kyori.adventure.text.Component jm = playerJoinEvent.joinMessage(); if (jm != null && !jm.equals(net.kyori.adventure.text.Component.empty())) { // Paper - Adventure @@ -700,6 +713,12 @@ public abstract class PlayerList { respawnReason ).callEvent(); // Paper end + // Leaves start - bot support + if (org.leavesmc.leaves.LeavesConfig.modify.fakeplayer.enable) { + this.server.getBotList().bots.forEach(bot -> bot.sendFakeDataIfNeed(serverPlayer, true)); // Leaves - render bot + } + // Leaves end - bot support + return serverPlayer; } @@ -802,11 +821,16 @@ public abstract class PlayerList { } public String[] getPlayerNamesArray() { - String[] strings = new String[this.players.size()]; + String[] strings = new String[this.players.size() + this.server.getBotList().bots.size()]; // Leaves - fakeplayer support for (int i = 0; i < this.players.size(); i++) { strings[i] = this.players.get(i).getGameProfile().name(); } + // Leaves start - fakeplayer support + for (int i = this.players.size(); i < strings.length; ++i) { + strings[i] = this.server.getBotList().bots.get(i - this.players.size()).getGameProfile().getName(); + } + // Leaves end - fakeplayer support return strings; } @@ -919,7 +943,14 @@ public abstract class PlayerList { @Nullable public ServerPlayer getPlayerByName(String username) { - return this.playersByName.get(username.toLowerCase(java.util.Locale.ROOT)); // Spigot + // Leaves start - fakeplayer support + username = username.toLowerCase(java.util.Locale.ROOT); + ServerPlayer player = this.playersByName.get(username); + if (player == null) { + player = this.server.getBotList().getBotByName(username); + } + return player; // Spigot + // Leaves end - fakeplayer support } public void broadcast(@Nullable Player except, double x, double y, double z, double radius, ResourceKey dimension, Packet packet) { @@ -960,6 +991,7 @@ public abstract class PlayerList { } // Paper end - Incremental chunk and player saving } + org.leavesmc.leaves.bot.BotList.INSTANCE.saveAllResumeBots(); // Leaves - resident fakeplayer return null; }); // Paper - ensure main } @@ -1226,7 +1258,13 @@ public abstract class PlayerList { @Nullable public ServerPlayer getPlayer(UUID playerUUID) { - return this.playersByUUID.get(playerUUID); + // Leaves start - fakeplayer support + ServerPlayer player = this.playersByUUID.get(playerUUID); + if (player == null) { + player = this.server.getBotList().getBot(playerUUID); + } + return player; + // Leaves start - fakeplayer support } @Nullable diff --git a/net/minecraft/server/waypoints/ServerWaypointManager.java b/net/minecraft/server/waypoints/ServerWaypointManager.java index f9e7532f86122a379692561a639a209a126e8bba..2412f46837e967694222730e68e7d25ac32225cf 100644 --- a/net/minecraft/server/waypoints/ServerWaypointManager.java +++ b/net/minecraft/server/waypoints/ServerWaypointManager.java @@ -22,6 +22,11 @@ public class ServerWaypointManager implements WaypointManager public final boolean xZero = movement.x == 0.0; final boolean yZero = movement.y == 0.0; final boolean zZero = movement.z == 0.0; diff --git a/net/minecraft/world/entity/LivingEntity.java b/net/minecraft/world/entity/LivingEntity.java index 025ef0b83e5d481c8b2ef25206cafd30897caabd..c18b0155edd695524246e5c2134de94008d8a023 100644 --- a/net/minecraft/world/entity/LivingEntity.java +++ b/net/minecraft/world/entity/LivingEntity.java @@ -3157,7 +3157,7 @@ public abstract class LivingEntity extends Entity implements Attackable, Waypoin private void travelRidden(Player player, Vec3 travelVector) { Vec3 riddenInput = this.getRiddenInput(player, travelVector); this.tickRidden(player, riddenInput); - if (this.canSimulateMovement()) { + if (this.canSimulateMovement() || this.getControllingPassenger() instanceof org.leavesmc.leaves.bot.ServerBot) { // Leaves - Fakeplayer this.setSpeed(this.getRiddenSpeed(player)); this.travel(riddenInput); } else { @@ -4006,7 +4006,7 @@ public abstract class LivingEntity extends Entity implements Attackable, Waypoin // Paper start - lag compensate eating // we add 1 to the expected time to avoid lag compensating when we should not final boolean shouldLagCompensate = this.useItem.has(DataComponents.FOOD) && this.eatStartTime != -1 && (System.nanoTime() - this.eatStartTime) > ((1L + this.totalEatTimeTicks) * 50L * (1000L * 1000L)); - if ((--this.useItemRemaining == 0 || shouldLagCompensate) && !this.level().isClientSide() && !usingItem.useOnRelease()) { + if ((--this.useItemRemaining == 0 || shouldLagCompensate) && !(this instanceof org.leavesmc.leaves.bot.ServerBot) && !this.level().isClientSide() && !usingItem.useOnRelease()) { this.useItemRemaining = 0; // Paper end - lag compensate eating this.completeUsingItem(); @@ -4183,6 +4183,23 @@ public abstract class LivingEntity extends Entity implements Attackable, Waypoin this.stopUsingItem(); } + // Leaves start - Fakeplayer + public boolean releaseUsingItemWithResult() { + ItemStack itemInHand = this.getItemInHand(this.getUsedItemHand()); + boolean result = false; + if (!this.useItem.isEmpty() && ItemStack.isSameItem(itemInHand, this.useItem)) { + this.useItem = itemInHand; + result = this.useItem.releaseUsingWithResult(this.level(), this, this.getUseItemRemainingTicks()); + if (this.useItem.useOnRelease()) { + this.updatingUsingItem(); + } + } + + this.stopUsingItem(); + return result; + } + // Leaves end - Fakeplayer + public void stopUsingItem() { if (!this.level().isClientSide()) { boolean isUsingItem = this.isUsingItem(); diff --git a/net/minecraft/world/entity/player/Player.java b/net/minecraft/world/entity/player/Player.java index e95e259e5be5bb14a4ba2473d6ce850ebbedcb6d..e4c7262ded690e56ba2eef71bb7d46f9cd99b8b7 100644 --- a/net/minecraft/world/entity/player/Player.java +++ b/net/minecraft/world/entity/player/Player.java @@ -167,7 +167,7 @@ public abstract class Player extends Avatar implements ContainerUser { private int lastLevelUpTime; public GameProfile gameProfile; private boolean reducedDebugInfo; - private ItemStack lastItemInMainHand = ItemStack.EMPTY; + protected ItemStack lastItemInMainHand = ItemStack.EMPTY; private final ItemCooldowns cooldowns = this.createItemCooldowns(); private Optional lastDeathLocation = Optional.empty(); @Nullable @@ -309,6 +309,12 @@ public abstract class Player extends Avatar implements ContainerUser { } } + // Leaves start - fakeplayer + protected void livingEntityTick() { + super.tick(); + } + // Leaves end - fakeplayer + @Override protected float getMaxHeadRotationRelativeToBody() { return this.isBlocking() ? 15.0F : super.getMaxHeadRotationRelativeToBody(); @@ -537,7 +543,7 @@ public abstract class Player extends Avatar implements ContainerUser { public void removeEntitiesOnShoulder() { } - private void touch(Entity entity) { + public void touch(Entity entity) { // Leaves - private -> public entity.playerTouch(this); } @@ -1148,7 +1154,7 @@ public abstract class Player extends Avatar implements ContainerUser { 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 207e30f822f286a6358055fcd5bc3af6ee7a553d..2c79332e148375c2f277df94b16ce7dd2422c004 100644 --- a/net/minecraft/world/entity/projectile/FishingHook.java +++ b/net/minecraft/world/entity/projectile/FishingHook.java @@ -59,7 +59,7 @@ public class FishingHook extends Projectile { public static final EntityDataAccessor DATA_HOOKED_ENTITY = SynchedEntityData.defineId(FishingHook.class, EntityDataSerializers.INT); private static final EntityDataAccessor DATA_BITING = SynchedEntityData.defineId(FishingHook.class, EntityDataSerializers.BOOLEAN); private int life; - private int nibble; + public int nibble; // Leaves - private -> public public int timeUntilLured; public int timeUntilHooked; public float fishAngle; diff --git a/net/minecraft/world/entity/vehicle/AbstractBoat.java b/net/minecraft/world/entity/vehicle/AbstractBoat.java index adab5dc640a7a0299c04020225a68317282aebe9..e127a670935186ba3d96a8d85640cf465ef52b7e 100644 --- a/net/minecraft/world/entity/vehicle/AbstractBoat.java +++ b/net/minecraft/world/entity/vehicle/AbstractBoat.java @@ -269,6 +269,11 @@ public abstract class AbstractBoat extends VehicleEntity implements Leashable { } this.move(MoverType.SELF, this.getDeltaMovement()); + } else if (this.getControllingPassenger() instanceof org.leavesmc.leaves.bot.ServerBot) { // Leaves start - Fakeplayer + this.floatBoat(); + this.controlBoat(); + this.move(MoverType.SELF, this.getDeltaMovement()); + // Leaves end - Fakeplayer } else { this.setDeltaMovement(Vec3.ZERO); } @@ -377,6 +382,13 @@ public abstract class AbstractBoat extends VehicleEntity implements Leashable { } } + // Leaves start - Fakeplayer + @Override + public boolean canSimulateMovement() { + return super.canSimulateMovement() || this.getControllingPassenger() instanceof org.leavesmc.leaves.bot.ServerBot; + } + // Leaves end - Fakeplayer + @Nullable protected SoundEvent getPaddleSound() { return switch (this.getStatus()) { diff --git a/net/minecraft/world/inventory/AbstractContainerMenu.java b/net/minecraft/world/inventory/AbstractContainerMenu.java index 670090c4466d6472a83263e1769f19e3e491c927..4e53e7c05af11cae2ce8cf313c69a83336e22ba6 100644 --- a/net/minecraft/world/inventory/AbstractContainerMenu.java +++ b/net/minecraft/world/inventory/AbstractContainerMenu.java @@ -400,6 +400,7 @@ public abstract class AbstractContainerMenu { private void doClick(int slotIndex, int button, ClickType clickType, Player player) { Inventory inventory = player.getInventory(); + if (!doClickCheck(slotIndex, button, clickType, player)) return; // Leaves - doClick check if (clickType == ClickType.QUICK_CRAFT) { int i = this.quickcraftStatus; this.quickcraftStatus = getQuickcraftHeader(button); @@ -674,6 +675,22 @@ public abstract class AbstractContainerMenu { } } + // Leaves start - doClick check + private boolean doClickCheck(int slotIndex, int button, ClickType actionType, Player player) { + if (slotIndex < 0) { + return true; + } + + Slot slot = getSlot(slotIndex); + ItemStack itemStack = slot.getItem(); + net.minecraft.world.item.component.CustomData customData = itemStack.get(net.minecraft.core.component.DataComponents.CUSTOM_DATA); + if (customData != null && customData.contains("Leaves.Gui.Placeholder")) { + return !customData.copyTag().getBoolean("Leaves.Gui.Placeholder").orElse(false); + } + return true; + } + // Leaves end - doClick check + 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/item/ItemStack.java b/net/minecraft/world/item/ItemStack.java index 47862c00e9e01c7cdd5fcd808cc1b76740b85a57..14c74eb71b5bfb67d0fcf9d660f748c7b1dba63d 100644 --- a/net/minecraft/world/item/ItemStack.java +++ b/net/minecraft/world/item/ItemStack.java @@ -443,7 +443,7 @@ public final class ItemStack implements DataComponentHolder { placeEvent = org.bukkit.craftbukkit.event.CraftEventFactory.callBlockPlaceEvent(serverLevel, player, hand, blocks.getFirst(), clickedPos); } - if (placeEvent != null && (placeEvent.isCancelled() || !placeEvent.canBuild())) { + if (placeEvent != null && (placeEvent.isCancelled() || !placeEvent.canBuild()) && (!(player instanceof org.leavesmc.leaves.bot.ServerBot))) { // Leaves - Fakeplayer skip this check interactionResult = InteractionResult.FAIL; // cancel placement // PAIL: Remove this when MC-99075 fixed player.containerMenu.forceHeldSlot(hand); @@ -939,6 +939,20 @@ public final class ItemStack implements DataComponentHolder { } } + // Leaves start - Fakeplayer + public boolean releaseUsingWithResult(Level level, LivingEntity livingEntity, int timeLeft) { + ItemStack itemStack = this.copy(); + if (this.getItem().releaseUsing(this, level, livingEntity, timeLeft)) { + ItemStack itemStack1 = this.applyAfterUseComponentSideEffects(livingEntity, itemStack); + if (itemStack1 != this) { + livingEntity.setItemInHand(livingEntity.getUsedItemHand(), itemStack1); + } + return true; + } + return false; + } + // Leaves end - Fakeplayer + public boolean useOnRelease() { return this.getItem().useOnRelease(this); } diff --git a/net/minecraft/world/level/block/piston/PistonMovingBlockEntity.java b/net/minecraft/world/level/block/piston/PistonMovingBlockEntity.java index 59a002711531f8337a86d85b6e8b11b5fad8ced7..0a76cf42aaaaf210a4e43ed9bd3d177f0003ba57 100644 --- a/net/minecraft/world/level/block/piston/PistonMovingBlockEntity.java +++ b/net/minecraft/world/level/block/piston/PistonMovingBlockEntity.java @@ -135,7 +135,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 801a50ba4d202df0289339f26968e7f6bb9ca767..196f5dd260701d520cc8a037a896f34c87f74934 100644 --- a/net/minecraft/world/level/levelgen/PhantomSpawner.java +++ b/net/minecraft/world/level/levelgen/PhantomSpawner.java @@ -48,6 +48,11 @@ public class PhantomSpawner implements CustomSpawner { ServerStatsCounter stats = serverPlayer.getStats(); int i = Mth.clamp(stats.getValue(Stats.CUSTOM.get(Stats.TIME_SINCE_REST)), 1, Integer.MAX_VALUE); int i1 = 24000; + // Leaves start - fakeplayer spawn + if (serverPlayer instanceof org.leavesmc.leaves.bot.ServerBot bot && bot.getConfigValue(org.leavesmc.leaves.bot.agent.Configs.SPAWN_PHANTOM)) { + i1 = Math.max(bot.notSleepTicks, 1); + } + // Leaves end - fakeplayer spawn if (randomSource.nextInt(i) >= 72000) { BlockPos blockPos1 = blockPos.above(20 + randomSource.nextInt(15)) .east(-10 + randomSource.nextInt(21)) diff --git a/net/minecraft/world/level/storage/LevelResource.java b/net/minecraft/world/level/storage/LevelResource.java index bef794c3f58c41d910aa0bcc63fbdeea7225fddf..a601da588e6973cc5b87d3e3eeba49b53f6d9a6d 100644 --- a/net/minecraft/world/level/storage/LevelResource.java +++ b/net/minecraft/world/level/storage/LevelResource.java @@ -15,7 +15,7 @@ public class LevelResource { public static final LevelResource ROOT = new LevelResource("."); private final String id; - private LevelResource(String id) { + public LevelResource(String id) { // Leaves - private -> public this.id = id; }