Compare commits

..

3 Commits

Author SHA1 Message Date
Helvetica Volubi dd7ef6701a feat: update fakeplayer code from Leaves 2026-07-30 02:13:08 +08:00
Helvetica Volubi 43036f971c feat: update Entity tick and removal limiter 2026-07-30 00:58:37 +08:00
Helvetica Volubi 25ce58c40d fix: fix folia nether portal ticket placement 2026-07-28 21:23:43 +08:00
65 changed files with 571 additions and 473 deletions
@@ -53,3 +53,15 @@ index c4d9d890db784d376b876d70f0468df6edb75168..0641b98ef3298eb682ceae83f60b730f
} finally { foliaProfiler.stopTimer(ca.spottedleaf.leafprofiler.LProfilerRegistry.ENTITY_TICK); } // Folia - profiler
if (this.paperConfig().unsupportedSettings.ticking.blockEntities) { // Paper - option to disable ticking
profiler.popPush("blockEntities");
diff --git a/net/minecraft/world/entity/EntityType.java b/net/minecraft/world/entity/EntityType.java
index 6efaa78faca15c7a48bdffb24480d1bac29f3ba8..31619890f1bd4f458b6f9a31fac8cefaafe09e8e 100644
--- a/net/minecraft/world/entity/EntityType.java
+++ b/net/minecraft/world/entity/EntityType.java
@@ -73,6 +73,7 @@ public class EntityType<T extends Entity> implements EntityTypeTest<Entity, T>,
private final float spawnDimensionsScale;
private final FeatureFlagSet requiredFeatures;
private final boolean allowedInPeaceful;
+ public volatile dev.kaiijumc.kaiiju.KaiijuEntityLimits.EntityLimit entityLimit;
public static Identifier getKey(final EntityType<?> type) {
return BuiltInRegistries.ENTITY_TYPE.getKey(type);
@@ -80,10 +80,10 @@ index 43e07a3c98e80f874f55411beac39e215ffdc3cf..cddf44f5da5cba5603dcff4913b4658d
+ // Lophine end - Add config to enable raytracing tracker
}
diff --git a/net/minecraft/world/entity/EntityType.java b/net/minecraft/world/entity/EntityType.java
index 6efaa78faca15c7a48bdffb24480d1bac29f3ba8..8a328a41673a3d720f0b1a5de8ce049e360fac1b 100644
index 31619890f1bd4f458b6f9a31fac8cefaafe09e8e..50643bd0b546a1ff70031ea39e2610f219ef8a79 100644
--- a/net/minecraft/world/entity/EntityType.java
+++ b/net/minecraft/world/entity/EntityType.java
@@ -84,6 +84,11 @@ public class EntityType<T extends Entity> implements EntityTypeTest<Entity, T>,
@@ -85,6 +85,11 @@ public class EntityType<T extends Entity> implements EntityTypeTest<Entity, T>,
public final int passengerTickTimerId;
public final int passengerInactiveTickTimerId;
// Folia end - profiler
@@ -240,7 +240,7 @@ index 3021b70b941ed09c5c58b98d30830a2279b8339c..d289f59475b617ae527d123239297f69
}
}
diff --git a/net/minecraft/server/dedicated/DedicatedServer.java b/net/minecraft/server/dedicated/DedicatedServer.java
index 2dae0f4249eade60ac55c9fa289dd146dc3675e1..239cad02f85f0d14d4abfa746ecdc4dd82b04657 100644
index 2dae0f4249eade60ac55c9fa289dd146dc3675e1..f70f6501254b40cf76dc7f9bcd621a1f68e39ea9 100644
--- a/net/minecraft/server/dedicated/DedicatedServer.java
+++ b/net/minecraft/server/dedicated/DedicatedServer.java
@@ -230,6 +230,7 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface
@@ -251,16 +251,17 @@ index 2dae0f4249eade60ac55c9fa289dd146dc3675e1..239cad02f85f0d14d4abfa746ecdc4dd
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();
@@ -251,6 +252,7 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface
consoleThread.start(); // Paper - Enhance console tab completions for brigadier commands; start console thread after MinecraftServer.console & PaperConfig are initialized
io.papermc.paper.command.PaperCommands.registerCommands(this); // Paper - setup /paper command
if (false) this.server.spark.registerCommandBeforePlugins(this.server); // Paper - spark // Luminol - Force disable builtin spark
+ this.getBotList().loadResumeBotInfo(); // Leaves - load resident bot info
@@ -254,6 +255,8 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface
com.destroystokyo.paper.Metrics.PaperMetrics.startMetrics(); // Paper - start metrics
com.destroystokyo.paper.VersionHistoryManager.INSTANCE.getClass(); // Paper - load version history now
+ this.getBotList().loadResumeBotInfo(); // Leaves - load resident bot info
+
// this.worldData.setGameType(properties.gameMode.get()); // CraftBukkit - moved to world loading
LOGGER.info("Default game type: {}", properties.gameMode.get());
// Paper start - Unix domain socket support
diff --git a/net/minecraft/server/level/ChunkMap.java b/net/minecraft/server/level/ChunkMap.java
index 5196431f52e81608a5575f8a262cd5c855b06182..6d43ca34f38192faf5bb4254d849c5ac51197f48 100644
index 5196431f52e81608a5575f8a262cd5c855b06182..84c047ed0242778a9e6bca5e41561bd1bdcf633c 100644
--- a/net/minecraft/server/level/ChunkMap.java
+++ b/net/minecraft/server/level/ChunkMap.java
@@ -972,7 +972,7 @@ public class ChunkMap extends SimpleRegionStorage implements ChunkHolder.PlayerP
@@ -272,7 +273,21 @@ index 5196431f52e81608a5575f8a262cd5c855b06182..6d43ca34f38192faf5bb4254d849c5ac
org.spigotmc.AsyncCatcher.catchOp("entity track"); // Spigot
// Paper start - ignore and warn about illegal addEntity calls instead of crashing server
if (!entity.valid || entity.level() != this.level || entity.moonrise$getTrackedEntity() != null) { // Folia - region threading
@@ -1389,6 +1389,13 @@ public class ChunkMap extends SimpleRegionStorage implements ChunkHolder.PlayerP
@@ -1258,6 +1258,13 @@ public class ChunkMap extends SimpleRegionStorage implements ChunkHolder.PlayerP
ServerPlayer player = conn.getPlayer();
if (!ca.spottedleaf.moonrise.common.util.TickThread.isTickThreadFor(player)) {
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
}
}
}
@@ -1389,6 +1396,13 @@ public class ChunkMap extends SimpleRegionStorage implements ChunkHolder.PlayerP
}
} else {
this.removePlayer(player);
@@ -564,9 +579,18 @@ index cddf44f5da5cba5603dcff4913b4658dcfcc48db..9eaed81a330a22e7fd6585cd286ec613
final boolean xZero = movement.x == 0.0;
final boolean yZero = movement.y == 0.0;
diff --git a/net/minecraft/world/entity/LivingEntity.java b/net/minecraft/world/entity/LivingEntity.java
index cb1589e3aa663ca058fb5c3a24da700d4482cf35..d64c68651b7142869a06ce0200fb625cd45ae235 100644
index cb1589e3aa663ca058fb5c3a24da700d4482cf35..1de8eac336e2dd6335c433b7708ce6b6684553c9 100644
--- a/net/minecraft/world/entity/LivingEntity.java
+++ b/net/minecraft/world/entity/LivingEntity.java
@@ -2001,7 +2001,7 @@ public abstract class LivingEntity extends Entity implements Attackable, Waypoin
return 0; // CraftBukkit
}
- protected void dropExperience(ServerLevel level, @Nullable Entity entity) {
+ public void dropExperience(ServerLevel level, @Nullable Entity entity) {
// CraftBukkit start - Update getExpReward() above if the removed if() changes!
if (!(this instanceof net.minecraft.world.entity.boss.enderdragon.EnderDragon)) { // CraftBukkit - SPIGOT-2420: Special case ender dragon will drop the xp over time
ExperienceOrb.awardWithDirection(level, this.position(), Vec3.ZERO, this.expToDrop, this instanceof ServerPlayer ? org.bukkit.entity.ExperienceOrb.SpawnReason.PLAYER_DEATH : org.bukkit.entity.ExperienceOrb.SpawnReason.ENTITY_DEATH, entity, this); // Paper
@@ -3348,7 +3348,7 @@ public abstract class LivingEntity extends Entity implements Attackable, Waypoin
private void travelRidden(final Player controller, final Vec3 selfInput) {
Vec3 riddenInput = this.getRiddenInput(controller, selfInput);
@@ -551,7 +551,7 @@ index ed50484ca24ef24b1e5bef9f6369dfa4b30c359c..575b4eabcaac48ae87b69dd037493ebf
// Leaves end - fakeplayer support
diff --git a/net/minecraft/world/entity/LivingEntity.java b/net/minecraft/world/entity/LivingEntity.java
index d64c68651b7142869a06ce0200fb625cd45ae235..1fe317cf3251bff7bb3e0335452a5714d4d31017 100644
index 1de8eac336e2dd6335c433b7708ce6b6684553c9..dae262a073acb3bb3464d169dd5a0b6d67f27846 100644
--- a/net/minecraft/world/entity/LivingEntity.java
+++ b/net/minecraft/world/entity/LivingEntity.java
@@ -276,7 +276,7 @@ public abstract class LivingEntity extends Entity implements Attackable, Waypoin
@@ -424,7 +424,7 @@ index b95c56e0699fbe16e65efcf010cd514f0ac0962f..0125d59551accd9005aa33a5c7cc8ec2
return this.entityData.get(DATA_VALUE);
}
diff --git a/net/minecraft/world/entity/LivingEntity.java b/net/minecraft/world/entity/LivingEntity.java
index 1fe317cf3251bff7bb3e0335452a5714d4d31017..14a79e8ef5a98b1eef2f2d3e0c63f21cb5bb4dbf 100644
index dae262a073acb3bb3464d169dd5a0b6d67f27846..0990e393c8695b17571d9a7646d895ab07ec30ba 100644
--- a/net/minecraft/world/entity/LivingEntity.java
+++ b/net/minecraft/world/entity/LivingEntity.java
@@ -623,7 +623,10 @@ public abstract class LivingEntity extends Entity implements Attackable, Waypoin
@@ -34,7 +34,7 @@ index 9a6f18fd0eb7e2aef174b25d14cfd0f5a3ade6af..b43bbe461500782a75a49c9238bd4d4d
}
diff --git a/net/minecraft/world/entity/LivingEntity.java b/net/minecraft/world/entity/LivingEntity.java
index 14a79e8ef5a98b1eef2f2d3e0c63f21cb5bb4dbf..429116ab6bac69054a30b0c766ea5d0186877fae 100644
index 0990e393c8695b17571d9a7646d895ab07ec30ba..386033fa4ba0fb705593e0c9f9cc6574c0ab55ac 100644
--- a/net/minecraft/world/entity/LivingEntity.java
+++ b/net/minecraft/world/entity/LivingEntity.java
@@ -4004,7 +4004,7 @@ public abstract class LivingEntity extends Entity implements Attackable, Waypoin
@@ -0,0 +1,69 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Helvetica Volubi <suisuroru@blue-millennium.fun>
Date: Tue, 28 Jul 2026 20:40:01 +0800
Subject: [PATCH] Anonymous Object: Fix folia nether portal ticket placement
As requested by the original author, this patch will be anonymous and hide the original commit address.
This patch is used with permission from the original author.
Licensed under: GPL-3.0 (https://www.gnu.org/licenses/gpl-3.0.html)
diff --git a/net/minecraft/util/BlockUtil.java b/net/minecraft/util/BlockUtil.java
index ea93ac07ec6d4e83d1d0904daf721132e2bbecc3..4252672ad2aaf03d50e5ea6a681e9964fd9a6137 100644
--- a/net/minecraft/util/BlockUtil.java
+++ b/net/minecraft/util/BlockUtil.java
@@ -138,12 +138,20 @@ public class BlockUtil {
public final BlockPos minCorner;
public final int axis1Size;
public final int axis2Size;
+ public BlockPos foundOrigin; // Anonymous - Fix folia nether portal ticket placement
public FoundRectangle(final BlockPos minCorner, final int axis1Size, final int axis2Size) {
this.minCorner = minCorner;
this.axis1Size = axis1Size;
this.axis2Size = axis2Size;
+ this.foundOrigin = minCorner; // Anonymous - Fix folia nether portal ticket placement - prevent edge conditions(idk if someone would do this so just prevent it)
}
+ // Anonymous start - Fix folia nether portal ticket placement
+ public FoundRectangle withFoundOrigin(BlockPos origin) {
+ this.foundOrigin = origin;
+ return this;
+ }
+ // Anonymous end
}
public static class IntBounds {
diff --git a/net/minecraft/world/entity/Entity.java b/net/minecraft/world/entity/Entity.java
index acc9caf8559cd341ea17d3b58f13cdac7de18564..489011f9af49fa3407038bd2f00439443307d179 100644
--- a/net/minecraft/world/entity/Entity.java
+++ b/net/minecraft/world/entity/Entity.java
@@ -4851,7 +4851,7 @@ public abstract class Entity
portalInfoCompletable.complete(
new TeleportTransition(destination, Vec3.atCenterOf(targetPos), Vec3.ZERO,
90.0f, 0.0f,
- TeleportTransition.PLAY_PORTAL_SOUND.then(TeleportTransition.PLACE_PORTAL_TICKET))
+ TeleportTransition.PLAY_PORTAL_SOUND.then(ent -> ent.placePortalTicket(targetPos))) // Anonymous - Fix folia nether portal ticket placement
);
return;
}
@@ -4863,7 +4863,7 @@ public abstract class Entity
portalInfoCompletable.complete(
net.minecraft.world.level.block.NetherPortalBlock.createDimensionTransition(
destination, portal, originalPortalDirection, relativePos,
- Entity.this, TeleportTransition.PLAY_PORTAL_SOUND.then(TeleportTransition.PLACE_PORTAL_TICKET)
+ Entity.this, TeleportTransition.PLAY_PORTAL_SOUND.then(ent -> ent.placePortalTicket(portal.foundOrigin)) // Anonymous - Fix folia nether portal ticket placement
)
);
}
diff --git a/net/minecraft/world/level/block/NetherPortalBlock.java b/net/minecraft/world/level/block/NetherPortalBlock.java
index 29fc9521c2c8333c999647dd833899393a838064..e8d2b52a3948755c8d3912a4ad1204cea5f78674 100644
--- a/net/minecraft/world/level/block/NetherPortalBlock.java
+++ b/net/minecraft/world/level/block/NetherPortalBlock.java
@@ -204,7 +204,7 @@ public class NetherPortalBlock extends Block implements Portal {
return BlockUtil.getLargestRectangleAround(found, portalState.getValue(BlockStateProperties.HORIZONTAL_AXIS), 21, Direction.Axis.Y, 21, (pos) -> {
return world.getBlockStateFromEmptyChunk(pos) == portalState;
- });
+ }).withFoundOrigin(found); // Anonymous - Fix folia nether portal ticket placement
}
// Folia end - region threading
@@ -19,51 +19,35 @@ package dev.kaiijumc.kaiiju;
import com.google.common.base.Throwables;
import com.mojang.logging.LogUtils;
import io.github.classgraph.ClassGraph;
import io.github.classgraph.ClassInfo;
import io.github.classgraph.ScanResult;
import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;
import net.minecraft.world.entity.Entity;
import net.minecraft.core.Holder;
import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.resources.Identifier;
import net.minecraft.world.entity.EntityType;
import org.bukkit.Bukkit;
import org.bukkit.configuration.InvalidConfigurationException;
import org.bukkit.configuration.file.YamlConfiguration;
import org.jspecify.annotations.NonNull;
import org.slf4j.Logger;
import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
import java.util.logging.Level;
@SuppressWarnings("unused")
public class KaiijuEntityLimits {
private static final Logger LOGGER = LogUtils.getLogger();
private static final File CONFIG_FOLDER = new File("luminol_config");
private static final File CONFIG_FOLDER = new File("shiroha_config");
protected static final String HEADER =
"Per region entity limits for Kaiiju.\n"
+ "If there are more of particular entity type in a region than limit, entity ticking will be throttled.\n"
+ "Example: for Wither limit 100 & 300 Withers in a region -> 100 Withers tick every tick & every Wither ticks every 3 ticks.\n"
+ "Available entities: GlowSquid, Ambient, Bat, Animal, Bee, Cat, Chicken, Cod, Cow, Dolphin, Fish, FishSchool, Fox, Golem, IronGolem, "
+ "MushroomCow, Ocelot, Panda, Parrot, Perchable, Pig, PolarBear, PufferFish, Rabbit, Salmon, Sheep, Snowman, Squid, TropicalFish, Turtle, "
+ "WaterAnimal, Wolf, Allay, Axolotl, Camel, Frog, Tadpole, Goat, Horse, HorseAbstract, HorseChestedAbstract, HorseDonkey, HorseMule, "
+ "HorseSkeleton, HorseZombie, Llama, LlamaTrader, Sniffer, EnderCrystal, EnderDragon, Wither, ArmorStand, Hanging, ItemFrame, Leash, "
+ "Painting, GlowItemFrame, FallingBlock, Item, TNTPrimed, Blaze, CaveSpider, Creeper, Drowned, Enderman, Endermite, Evoker, Ghast, "
+ "GiantZombie, Guardian, GuardianElder, IllagerAbstract, IllagerIllusioner, IllagerWizard, MagmaCube, Monster, MonsterPatrolling, Phantom, "
+ "ZombifiedPiglin, Pillager, Ravager, Shulker, Silverfish, Skeleton, SkeletonAbstract, SkeletonStray, SkeletonWither, Slime, Spider, Strider, Vex, "
+ "Vindicator, Witch, Zoglin, Zombie, ZombieHusk, ZombieVillager, Hoglin, Piglin, PiglinAbstract, PiglinBrute, Warden, Villager, "
+ "VillagerTrader, Arrow, DragonFireball, Egg, EnderPearl, EnderSignal, EvokerFangs, Fireball, FireballFireball, Fireworks, FishingHook, "
+ "LargeFireball, LlamaSpit, Potion, Projectile, ProjectileThrowable, ShulkerBullet, SmallFireball, Snowball, SpectralArrow, ThrownExpBottle, "
+ "ThrownTrident, TippedArrow, WitherSkull, Raider, ChestBoat, Boat, MinecartAbstract, MinecartChest, MinecartCommandBlock, MinecartContainer, "
+ "MinecartFurnace, MinecartHopper, MinecartMobSpawner, MinecartRideable, MinecartTNT\n";
+ "Entity names are named under the registry of minecraft's entity type";
protected static final File ENTITY_LIMITS_FILE = new File(CONFIG_FOLDER, "kaiiju_entity_limits.yml");
public static YamlConfiguration entityLimitsConfig;
public static boolean enabled = false;
protected static Map<Class<? extends Entity>, EntityLimit> entityLimits;
static final String ENTITY_PREFIX = "Entity";
public static void init() {
init(true);
}
@@ -84,8 +68,9 @@ public class KaiijuEntityLimits {
entityLimitsConfig.options().header(HEADER);
entityLimitsConfig.options().copyDefaults(true);
entityLimitsConfig.set("enabled", enabled);
entityLimitsConfig.set("Axolotl.limit", 1000);
entityLimitsConfig.set("Axolotl.removal", 2000);
entityLimitsConfig.set("axolotl.limit", 1000);
entityLimitsConfig.set("axolotl.removal", 2000);
try {
entityLimitsConfig.save(ENTITY_LIMITS_FILE);
} catch (IOException ex) {
@@ -96,62 +81,42 @@ public class KaiijuEntityLimits {
enabled = entityLimitsConfig.getBoolean("enabled");
entityLimits = new Object2ObjectOpenHashMap<>();
try (ScanResult scanResult = new ClassGraph().enableAllInfo().acceptPackages("net.minecraft.world.entity").scan()) {
Map<String, ClassInfo> entityClasses = new HashMap<>();
for (ClassInfo classInfo : scanResult.getAllClasses()) {
Class<?> entityClass = Class.forName(classInfo.getName());
if (Entity.class.isAssignableFrom(entityClass)) {
String entityName = extractEntityName(entityClass.getSimpleName());
entityClasses.put(entityName, classInfo);
}
}
for (String key : entityLimitsConfig.getKeys(false)) {
if (key.equals("enabled")) {
continue;
}
if (!entityClasses.containsKey(key)) {
LOGGER.error("Unknown entity '" + key + "' in kaiiju-entity-limits.yml, skipping");
continue;
}
int limit = entityLimitsConfig.getInt(key + ".limit");
int removal = entityLimitsConfig.getInt(key + ".removal");
if (limit < 1) {
LOGGER.error(key + " has a limit less than the minimum of 1, ignoring");
continue;
}
if (removal <= limit && removal != -1) {
LOGGER.error(key + " has a removal limit that is less than or equal to its limit, setting removal to limit * 10");
removal = limit * 10;
}
entityLimits.put((Class<? extends Entity>) Class.forName(entityClasses.get(key).getName()), new EntityLimit(limit, removal));
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
if (!enabled) {
return;
}
}
public static EntityLimit getEntityLimit(Entity entity) {
return entityLimits.get(entity.getClass());
}
for (String key : entityLimitsConfig.getKeys(false)) {
if (key.equals("enabled")) {
continue;
}
private static String extractEntityName(String input) {
int prefixLength = ENTITY_PREFIX.length();
final Optional<Holder.Reference<EntityType<?>>> lookup = BuiltInRegistries.ENTITY_TYPE.get(Identifier.fromNamespaceAndPath(Identifier.DEFAULT_NAMESPACE, key));
if (lookup.isEmpty()) {
LOGGER.error("Unknown entity '{}' in kaiiju-entity-limits.yml, skipping", key);
continue;
}
if (input.length() <= prefixLength || !input.startsWith(ENTITY_PREFIX)) {
return input;
} else {
return input.substring(prefixLength);
final EntityType<?> value = lookup.get().value();
int limit = entityLimitsConfig.getInt(key + ".limit");
int removal = entityLimitsConfig.getInt(key + ".removal");
if (limit < 1) {
LOGGER.error("{} has a limit less than the minimum of 1, ignoring", key);
continue;
}
if (removal <= limit && removal != -1) {
LOGGER.error("{} has a removal limit that is less than or equal to its limit, setting removal to limit * 10", key);
removal = limit * 10;
}
value.entityLimit = new EntityLimit(limit, removal);
}
}
public record EntityLimit(int limit, int removal) {
@Override
public String toString() {
public @NonNull String toString() {
return "EntityLimit{limit=" + limit + ", removal=" + removal + "}";
}
}
@@ -45,7 +45,8 @@ public class KaiijuEntityThrottler {
public EntityThrottlerReturn tickLimiterShouldSkip(Entity entity) {
EntityThrottlerReturn retVal = new EntityThrottlerReturn();
if (entity.isRemoved()) return retVal;
KaiijuEntityLimits.EntityLimit entityLimit = KaiijuEntityLimits.getEntityLimit(entity);
KaiijuEntityLimits.EntityLimit entityLimit = entity.getType().entityLimit;
if (entityLimit != null) {
TickInfo tickInfo = entityLimitTickInfoMap.computeIfAbsent(entityLimit, el -> {
@@ -1,8 +1,6 @@
package fun.bm.lophine.config.modules.experiment;
import fun.bm.lophine.enums.GlobalEntitiesCounterType;
import me.earthme.luminol.config.ConfigManager;
import me.earthme.luminol.config.ConfigsInstance;
import me.earthme.luminol.config.IConfigModule;
import me.earthme.luminol.config.flags.ConfigClassInfo;
import me.earthme.luminol.config.flags.ConfigInfo;
@@ -464,7 +464,8 @@ public class BufferedLinearRegionFile implements io.anonymous.anonymous.data.Reg
// acquired after the region lock is fully released, never inside it (lock hierarchy)
this.masterFileParser.close();
} catch (IOException e) {
if (failure == null) failure = e; else failure.addSuppressed(e);
if (failure == null) failure = e;
else failure.addSuppressed(e);
}
if (failure != null) {
@@ -1,9 +1,9 @@
package io.anonymous.anonymous.enums;
import abomination.LinearRegionFile;
import me.earthme.luminol.config.modules.function.RegionFormatConfig;
import io.anonymous.anonymous.data.BufferedLinearRegionFile;
import io.anonymous.anonymous.utils.RegionFileFactory;
import me.earthme.luminol.config.modules.function.RegionFormatConfig;
import net.minecraft.world.level.chunk.storage.RegionFile;
public enum EnumRegionFormat {
@@ -2,6 +2,8 @@ package me.earthme.luminol.config.modules.function;
import abomination.LinearRegionFile;
import com.electronwill.nightconfig.core.file.CommentedFileConfig;
import io.anonymous.anonymous.data.BufferedLinearRegionFileFlusher;
import io.anonymous.anonymous.enums.EnumRegionFormat;
import me.earthme.luminol.config.IConfigModule;
import me.earthme.luminol.config.IllegalFormatConversionExceptionWithOrigin;
import me.earthme.luminol.config.flags.ConfigClassInfo;
@@ -9,8 +11,6 @@ import me.earthme.luminol.config.flags.ConfigInfo;
import me.earthme.luminol.config.flags.DoNotLoad;
import me.earthme.luminol.config.flags.HotReloadUnsupported;
import me.earthme.luminol.enums.EnumConfigCategory;
import io.anonymous.anonymous.enums.EnumRegionFormat;
import io.anonymous.anonymous.data.BufferedLinearRegionFileFlusher;
import net.minecraft.server.MinecraftServer;
import org.jetbrains.annotations.Nullable;
@@ -96,11 +96,11 @@ public class CheckAndCacheBlockChecker {
}
}
public int getChunkSize(){
public int getChunkSize() {
return this.chunkSections2MaybeContainsMatchingBlock.numChunks;
}
public boolean hasUnloadedPossibleChunks(){
public boolean hasUnloadedPossibleChunks() {
return this.unloadedPossibleChunkSections > 0;
}
@@ -129,14 +129,14 @@ public class CheckAndCacheBlockChecker {
return this.chunkSections2MaybeContainsMatchingBlock.getChunkAccess(blockPos);
}
public boolean shouldStop(){
public boolean shouldStop() {
return this.chunkSections2MaybeContainsMatchingBlock.hasNoTrueChunkSections();
}
public boolean checkPosition(BlockPos blockPos) {
if(!this.chunkSections2MaybeContainsMatchingBlock.getChunkSectionBit(blockPos)) return false;
if (!this.chunkSections2MaybeContainsMatchingBlock.getChunkSectionBit(blockPos)) return false;
ChunkAccess chunkAccess = this.chunkSections2MaybeContainsMatchingBlock.getChunkAccess(blockPos);
if(chunkAccess == null) {
if (chunkAccess == null) {
if (!this.shouldChunkLoad) {
return false;
}
@@ -35,12 +35,12 @@ public class CommonBlockSearchesCheckAndCache {
public static Optional<BlockPos> blockPosFindClosestMatch(LevelReader levelReader, LivingEntity livingEntity,
int horizontalRange, int verticalRange,
Predicate<BlockState> blockStatePredicate,
boolean shouldChunkLoad){
boolean shouldChunkLoad) {
BlockPos mobPos = livingEntity.blockPosition();
CheckAndCacheBlockChecker checker = new CheckAndCacheBlockChecker(
mobPos, horizontalRange, verticalRange, levelReader, blockStatePredicate, shouldChunkLoad);
checker.initializeChunks();
if(checker.shouldStop()) {
if (checker.shouldStop()) {
return Optional.empty();
}
return BlockPos.findClosestMatch(mobPos, horizontalRange, verticalRange, checker::checkPosition);
@@ -34,7 +34,7 @@ public class NonPOISearchDistances {
return getVanillaSortOrderInt(getRing(dX, dZ), dX, dZ);
}
public static int getRing(final int dX, final int dZ){
public static int getRing(final int dX, final int dZ) {
return Math.max(Math.abs(dX), Math.abs(dZ));
}
@@ -58,8 +58,8 @@ public class NonPOISearchDistances {
* You can convert to longs if you somehow exceed that, but also seriously consider POIs instead.
*
* @param ring Which square ring the block is at relative to the center
* @param dX Relative x position of the block to the center
* @param dZ Relative z position of the block to the center
* @param dX Relative x position of the block to the center
* @param dZ Relative z position of the block to the center
*/
public static int getVanillaSortOrderInt(final int ring, final int dX, final int dZ) {
return (ring << 16 | Math.abs(dX) << 9 | Math.abs(dZ) << 1) - ((dX > 0 ? 1 : 0) << 8 | (dZ > 0 ? 1 : 0));
@@ -25,12 +25,15 @@ public class Pos {
public static int getYSize(LevelHeightAccessor view) {
return view.getHeight();
}
public static int getMinY(LevelHeightAccessor view) {
return view.getMinY();
}
public static int getMaxYInclusive(LevelHeightAccessor view) {
return view.getMaxY();
}
public static int getMaxYExclusive(LevelHeightAccessor view) {
return view.getMaxY() + 1;
}
@@ -39,7 +42,7 @@ public class Pos {
return 15 + getMinInSectionCoord(sectionCoord);
}
public static int getMaxYInSectionIndex(LevelHeightAccessor view, int sectionIndex){
public static int getMaxYInSectionIndex(LevelHeightAccessor view, int sectionIndex) {
return getMaxInSectionCoord(SectionYCoord.fromSectionIndex(view, sectionIndex));
}
@@ -66,12 +69,15 @@ public class Pos {
public static int getNumYSections(LevelHeightAccessor view) {
return view.getSectionsCount();
}
public static int getMinYSection(LevelHeightAccessor view) {
return view.getMinSectionY();
}
public static int getMaxYSectionInclusive(LevelHeightAccessor view) {
return view.getMaxSectionY();
}
public static int getMaxYSectionExclusive(LevelHeightAccessor view) {
return view.getMaxSectionY() + 1;
}
@@ -79,6 +85,7 @@ public class Pos {
public static int fromSectionIndex(LevelHeightAccessor view, int sectionCoord) {
return sectionCoord + SectionYCoord.getMinYSection(view);
}
public static int fromBlockCoord(int blockCoord) {
return SectionPos.blockToSectionCoord(blockCoord);
}
@@ -88,12 +95,15 @@ public class Pos {
public static int getNumYSections(LevelHeightAccessor view) {
return view.getSectionsCount();
}
public static int getMinYSectionIndex(LevelHeightAccessor view) {
return 0;
}
public static int getMaxYSectionIndexInclusive(LevelHeightAccessor view) {
return view.getSectionsCount() - 1;
}
public static int getMaxYSectionIndexExclusive(LevelHeightAccessor view) {
return view.getSectionsCount();
}
@@ -102,6 +112,7 @@ public class Pos {
public static int fromSectionCoord(LevelHeightAccessor view, int sectionCoord) {
return sectionCoord - SectionYCoord.getMinYSection(view);
}
public static int fromBlockCoord(LevelHeightAccessor view, int blockCoord) {
return fromSectionCoord(view, SectionPos.blockToSectionCoord(blockCoord));
}
@@ -50,7 +50,7 @@ public class FixedChunkAccessSectionBitBuffer {
this.numSections = yLength * xLength * zLength;
this.chunkSectionBits = new BitSet(numSections);
this.chunkAccesses = new ArrayList<>(Collections.nCopies(xLength * zLength,null));
this.chunkAccesses = new ArrayList<>(Collections.nCopies(xLength * zLength, null));
}
public FixedChunkAccessSectionBitBuffer(BlockPos center, int horizontalRangeInclusive, int verticalRangeInclusive) {
@@ -102,11 +102,11 @@ public class FixedChunkAccessSectionBitBuffer {
return this.getChunkIndex(ChunkPos.getX(chunkPos), ChunkPos.getZ(chunkPos));
}
public ChunkAccess getChunkAccess(long chunkPos){
public ChunkAccess getChunkAccess(long chunkPos) {
return this.chunkAccesses.get(this.getChunkIndex(chunkPos));
}
public ChunkAccess getChunkAccess(BlockPos blockPos){
public ChunkAccess getChunkAccess(BlockPos blockPos) {
return this.getChunkAccess(ChunkPos.pack(blockPos));
}
@@ -118,14 +118,14 @@ public class FixedChunkAccessSectionBitBuffer {
this.setChunkAccess(ChunkPos.pack(blockPos), chunkAccess);
}
public boolean hasNoTrueChunkSections(){
public boolean hasNoTrueChunkSections() {
return this.chunkSectionBits.nextSetBit(0) == -1;
}
public LongIterable getChunkPosInRange() {
return new LongIterable() {
@Override
public @NotNull LongIterator iterator(){
public @NotNull LongIterator iterator() {
return getChunkPosInRangeIterator();
}
};
@@ -141,7 +141,7 @@ public class FixedChunkAccessSectionBitBuffer {
int z = zMin;
@Override
public long nextLong () {
public long nextLong() {
long result = ChunkPos.pack(x, z);
if (z < zMax) {
z++;
@@ -153,7 +153,7 @@ public class FixedChunkAccessSectionBitBuffer {
}
@Override
public boolean hasNext(){
public boolean hasNext() {
return x <= xMax;
}
};
@@ -162,7 +162,7 @@ public class FixedChunkAccessSectionBitBuffer {
public IntIterable getSectionYInRange() {
return new IntIterable() {
@Override
public @NotNull IntIterator iterator(){
public @NotNull IntIterator iterator() {
return getSectionYInRangeIterator();
}
};
@@ -175,12 +175,12 @@ public class FixedChunkAccessSectionBitBuffer {
int y = yMin;
@Override
public int nextInt(){
public int nextInt() {
return y++;
}
@Override
public boolean hasNext(){
public boolean hasNext() {
return y < yLimit;
}
};
@@ -116,7 +116,7 @@ public record BotCreateState(String rawName, String fullName, String skinName, S
}
public void spawnWithSkin(Consumer<Bot> consumer) {
Bukkit.getAsyncScheduler().runNow(MinecraftInternalPlugin.INSTANCE, (task0) -> {
Bukkit.getAsyncScheduler().runNow(MinecraftInternalPlugin.INSTANCE, (_) -> {
this.mojangAPISkin();
Bukkit.getRegionScheduler().execute(
MinecraftInternalPlugin.INSTANCE,
@@ -22,6 +22,7 @@ import net.minecraft.core.UUIDUtil;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.NbtAccounter;
import net.minecraft.nbt.NbtIo;
import net.minecraft.nbt.Tag;
import net.minecraft.util.ProblemReporter;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.level.storage.LevelResource;
@@ -34,7 +35,10 @@ import org.slf4j.Logger;
import java.io.File;
import java.io.IOException;
import java.util.Locale;
import java.util.Map;
import java.util.Optional;
import java.util.UUID;
public class BotDataStorage {
@@ -42,7 +46,7 @@ public class BotDataStorage {
private final File botDir;
private final File botListFile;
private CompoundTag savedBotList;
private final CompoundTag savedBotList;
public BotDataStorage(LevelStorageSource.@NotNull LevelStorageAccess session, String dataDir, String listFileName) {
this.botDir = session.getLevelPath(new LevelResource(dataDir)).toFile();
@@ -52,7 +56,11 @@ public class BotDataStorage {
this.savedBotList = new CompoundTag();
if (this.botListFile.exists() && this.botListFile.isFile()) {
try {
Optional.of(NbtIo.readCompressed(this.botListFile.toPath(), NbtAccounter.unlimitedHeap())).ifPresent(tag -> this.savedBotList = tag);
Optional.of(NbtIo.readCompressed(this.botListFile.toPath(), NbtAccounter.unlimitedHeap())).ifPresent(tag -> {
for (Map.Entry<String, Tag> entry : tag.entrySet()) {
savedBotList.put(entry.getKey().toLowerCase(Locale.ROOT), entry.getValue());
}
});
} catch (Exception exception) {
BotDataStorage.LOGGER.warn("Failed to load player data list");
}
@@ -60,7 +68,6 @@ public class BotDataStorage {
}
public void save(Player player) {
boolean flag = true;
try {
CompoundTag nbt = TagUtil.saveEntityWithoutId(player);
File file = new File(this.botDir, player.getStringUUID() + ".dat");
@@ -76,20 +83,19 @@ public class BotDataStorage {
NbtIo.writeCompressed(nbt, file.toPath());
} catch (Exception exception) {
BotDataStorage.LOGGER.warn("Failed to save fakeplayer data for {}", player.getScoreboardName(), exception);
flag = false;
return;
}
if (flag && player instanceof ServerBot bot) {
if (player instanceof ServerBot bot) {
CompoundTag nbt = new CompoundTag();
nbt.putString("name", bot.createState.fullName());
nbt.store("uuid", UUIDUtil.CODEC, bot.getUUID());
nbt.putBoolean("resume", bot.resume);
this.savedBotList.put(bot.createState.fullName(), nbt);
this.savedBotList.put(bot.createState.fullName().toLowerCase(Locale.ROOT), nbt);
this.saveBotList();
}
}
public Optional<ValueInput> load(@NotNull ServerBot bot, ProblemReporter reporter) {
return this.load(bot.nameAndId().name(), bot.nameAndId().id().toString()).map(nbt -> {
ValueInput valueInput = TagValueInput.create(reporter, bot.registryAccess(), nbt);
@@ -98,27 +104,27 @@ public class BotDataStorage {
});
}
public void removeSavedData(@NotNull ServerBot bot) {
this.load(bot.nameAndId().name(), bot.nameAndId().id().toString());
public void removeSavedData(String name) {
this.savedBotList.remove(name.toLowerCase(Locale.ROOT));
this.saveBotList();
}
private Optional<CompoundTag> load(String name, String uuid) {
File file = new File(this.botDir, uuid + ".dat");
if (file.exists() && file.isFile()) {
try {
Optional<CompoundTag> optional = Optional.of(NbtIo.readCompressed(file.toPath(), NbtAccounter.unlimitedHeap()));
if (!file.delete()) {
throw new IOException("Failed to delete fakeplayer data");
}
this.savedBotList.remove(name);
this.saveBotList();
return optional;
} catch (Exception exception) {
BotDataStorage.LOGGER.warn("Failed to load fakeplayer data for {}", name);
}
if (!file.exists() || !file.isFile()) {
LOGGER.warn("Failed to load bot {}, the file {} DOES NOT EXIST!", name, file);
return Optional.empty();
}
try {
Optional<CompoundTag> optional = Optional.of(NbtIo.readCompressed(file.toPath(), NbtAccounter.unlimitedHeap()));
if (!file.delete()) {
throw new IOException("Failed to delete fakeplayer data");
}
this.removeSavedData(name);
return optional;
} catch (Exception exception) {
BotDataStorage.LOGGER.warn("Failed to load fakeplayer data for {}", name);
}
return Optional.empty();
}
@@ -153,4 +159,12 @@ public class BotDataStorage {
public CompoundTag getSavedBotList() {
return savedBotList;
}
public UUID getUUIDFromLower(String lowerName) {
return savedBotList.getCompoundOrEmpty(lowerName).read("uuid", UUIDUtil.CODEC).orElseThrow();
}
public String getNameFromLower(String lowerName) {
return savedBotList.getCompoundOrEmpty(lowerName).getString("name").orElseThrow();
}
}
@@ -28,11 +28,11 @@ import fun.bm.lophine.config.modules.function.OldFeatureConfig;
import io.papermc.paper.adventure.PaperAdventure;
import io.papermc.paper.profile.MutablePropertyMap;
import io.papermc.paper.threadedregions.RegionizedServer;
import io.papermc.paper.threadedregions.scheduler.FoliaGlobalRegionScheduler;
import io.papermc.paper.util.MCUtil;
import net.kyori.adventure.text.format.NamedTextColor;
import net.kyori.adventure.text.format.Style;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.Tag;
import net.minecraft.network.chat.Component;
import net.minecraft.network.protocol.game.ClientboundRemoveEntitiesPacket;
import net.minecraft.resources.ResourceKey;
@@ -76,7 +76,7 @@ public class BotList {
private final BotDataStorage resumeDataStorage;
private final Map<UUID, ServerBot> botsByUUID = Maps.newHashMap();
private final Map<String, ServerBot> botsByName = Maps.newHashMap();
private final Map<String, ServerBot> botsByLowerName = Maps.newHashMap();
private final Map<String, Set<String>> botsNameByWorldUuid = Maps.newHashMap();
private final Map<String, Set<String>> legacyBotsNameByWorldUuid = Maps.newHashMap();
@@ -141,20 +141,24 @@ public class BotList {
return this.loadNewBot(fullName, this.resumeDataStorage);
}
public ServerBot loadNewBot(String fullName, BotDataStorage storage) {
if (botsByName.containsKey(fullName)) {
public ServerBot loadNewBot(String inputName, BotDataStorage storage) {
String lowerName = inputName.toLowerCase(Locale.ROOT);
if (botsByLowerName.containsKey(lowerName)) {
return null;
}
try {
UUID uuid = BotUtil.getBotUUID(fullName);
BotLoadEvent event = new BotLoadEvent(fullName, uuid);
if (!storage.getSavedBotList().contains(lowerName)) {
return null;
}
String name = storage.getNameFromLower(lowerName);
UUID uuid = storage.getUUIDFromLower(lowerName);
BotLoadEvent event = new BotLoadEvent(name, uuid);
this.server.server.getPluginManager().callEvent(event);
if (event.isCancelled()) {
return null;
}
ServerBot bot = new ServerBot(this.server, this.server.getLevel(Level.OVERWORLD), new GameProfile(uuid, fullName));
ServerBot bot = new ServerBot(this.server, this.server.getLevel(Level.OVERWORLD), new GameProfile(uuid, name));
bot.connection = new ServerBotPacketListenerImpl(this.server, bot);
Optional<ValueInput> optional;
try (ProblemReporter.ScopedCollector scopedCollector = new ProblemReporter.ScopedCollector(bot.problemPath(), LOGGER)) {
@@ -182,7 +186,7 @@ public class BotList {
ServerLevel world = this.server.getLevel(resourcekey);
return this.placeNewBot(bot, world, bot.getLocation(), nbt);
} catch (Exception e) {
LOGGER.error("Failed to load bot {}", fullName, e);
LOGGER.error("Failed to load bot {}", inputName, e);
return null;
}
}
@@ -213,18 +217,20 @@ public class BotList {
bot.connection.teleport(bot.getX(), bot.getY(), bot.getZ(), bot.getYRot(), bot.getXRot());
this.bots.add(bot);
this.botsByName.put(bot.getScoreboardName().toLowerCase(Locale.ROOT), bot);
this.botsByLowerName.put(bot.getScoreboardName().toLowerCase(Locale.ROOT), bot);
this.botsByUUID.put(bot.getUUID(), bot);
bot.suppressTrackerForLogin = true;
Runnable task = () -> {
world.addNewPlayer(bot);
optional.ifPresent(nbt -> {
bot.loadAndSpawnEnderPearls(nbt);
bot.loadAndSpawnParentVehicle(nbt);
});
world.getCurrentWorldData().connections.add(bot.connection.connection);
world.addNewPlayer(bot);
BotJoinEvent event1 = new BotJoinEvent(bot.getBukkitEntity(), PaperAdventure.asAdventure(Component.translatable("multiplayer.player.joined", bot.getDisplayName())).style(Style.style(NamedTextColor.YELLOW)));
this.server.server.getPluginManager().callEvent(event1);
@@ -255,22 +261,7 @@ public class BotList {
return bot;
}
/*
* return true if async
*/
public boolean removeBot(@NotNull ServerBot bot, @NotNull BotRemoveEvent.RemoveReason reason, @Nullable CommandSender remover, boolean save, boolean resume, boolean async) {
if (async && !TickThread.isTickThreadFor(bot.level(), bot.getX(), bot.getZ())) {
bot.getBukkitEntity().taskScheduler.schedule((Entity unused) -> this.removeBot(bot, reason, remover, save, resume), null, 1L);
return true; // async always return true
}
return this.removeBot(bot, remover, reason, save, resume);
}
public boolean removeBot(@NotNull ServerBot bot, @NotNull BotRemoveEvent.RemoveReason reason, @Nullable CommandSender remover, boolean save, boolean resume) {
return this.removeBot(bot, reason, remover, save, resume, true);
}
public boolean removeBot(@NotNull ServerBot bot, @Nullable CommandSender remover, @NotNull BotRemoveEvent.RemoveReason reason, boolean save, boolean resume) {
BotRemoveEvent event = new BotRemoveEvent(bot.getBukkitEntity(), reason, remover, PaperAdventure.asAdventure(Component.translatable("multiplayer.player.left", bot.getDisplayName())).style(Style.style(NamedTextColor.YELLOW)), save);
this.server.server.getPluginManager().callEvent(event);
@@ -279,13 +270,13 @@ public class BotList {
}
if (bot.removeTaskId != -1) {
((FoliaGlobalRegionScheduler) Bukkit.getGlobalRegionScheduler()).cancelTask(bot.removeTaskId);
Bukkit.getScheduler().cancelTask(bot.removeTaskId);
bot.removeTaskId = -1;
}
bot.disconnect();
this.resumeDataStorage.removeSavedData(bot);
this.resumeDataStorage.removeSavedData(bot.nameAndId().name());
if (event.shouldSave()) {
if (resume) {
this.resumeDataStorage.save(bot);
@@ -293,6 +284,7 @@ public class BotList {
this.manualSaveDataStorage.save(bot);
}
} else {
bot.dropExperience(bot.level(), null);
bot.dropAll(true);
botsNameByWorldUuid.getOrDefault(bot.level().uuid.toString(), new HashSet<>()).remove(bot.getBukkitEntity().getName());
}
@@ -327,7 +319,7 @@ public class BotList {
bot.retireScheduler();
this.bots.remove(bot);
this.botsByName.remove(bot.getScoreboardName().toLowerCase(Locale.ROOT));
this.botsByLowerName.remove(bot.getScoreboardName().toLowerCase(Locale.ROOT));
UUID uuid = bot.getUUID();
ServerBot bot1 = this.botsByUUID.get(uuid);
@@ -400,7 +392,9 @@ public class BotList {
return;
}
CompoundTag savedBotList = this.getResumeBotList().copy();
for (String fullName : savedBotList.keySet()) {
for (Map.Entry<String, Tag> entry : savedBotList.entrySet()) {
String lowerName = entry.getKey();
String fullName = ((CompoundTag) entry.getValue()).getStringOr("name", lowerName);
UUID levelUuid = BotUtil.getBotLevel(fullName, this.resumeDataStorage);
if (levelUuid == null) {
LOGGER.warn("Bot {} has no world UUID, skipping loading.", fullName);
@@ -416,6 +410,7 @@ public class BotList {
private void loadLegacyResumeBotInfo() {
CompoundTag savedBotList = this.getManualSavedBotList().copy();
for (String fullName : savedBotList.keySet()) {
// Legacy format saved fullName as the key
CompoundTag nbt = savedBotList.getCompound(fullName).orElseThrow();
if (!nbt.getBoolean("resume").orElse(false)) {
continue;
@@ -461,7 +456,7 @@ public class BotList {
@Nullable
public ServerBot getBotByName(@NotNull String name) {
return this.botsByName.get(name.toLowerCase(Locale.ROOT));
return this.botsByLowerName.get(name.toLowerCase(Locale.ROOT));
}
public CompoundTag getManualSavedBotList() {
@@ -24,7 +24,6 @@ import net.minecraft.stats.ServerStatsCounter;
import net.minecraft.stats.Stat;
import net.minecraft.world.entity.player.Player;
import org.jetbrains.annotations.NotNull;
import org.jspecify.annotations.NonNull;
import java.io.File;
@@ -45,7 +44,7 @@ public class BotStatsCounter extends ServerStatsCounter {
}
@Override
public void parse(@NonNull DataFixer fixerUpper, @NonNull JsonElement json) {
public void parse(DataFixer fixerUpper, JsonElement json) {
}
@Override
@@ -18,15 +18,11 @@
package org.leavesmc.leaves.bot;
import com.google.common.base.Charsets;
import fun.bm.lophine.carpet.config.modules.FakePlayerCompatConfig;
import fun.bm.lophine.config.modules.function.FakeplayerConfig;
import net.minecraft.core.NonNullList;
import net.minecraft.core.component.DataComponents;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.tags.ItemTags;
import net.minecraft.world.entity.EquipmentSlot;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.component.ItemContainerContents;
import org.bukkit.Bukkit;
import org.jetbrains.annotations.NotNull;
@@ -38,66 +34,23 @@ public class BotUtil {
public static void replenishment(@NotNull ItemStack itemStack, NonNullList<ItemStack> itemStackList) {
int count = itemStack.getMaxStackSize() / 2;
if (itemStack.getCount() <= 8 && count > 8) {
if (pullMatchingStack(itemStack, itemStackList, count)) {
return;
}
if (FakePlayerCompatConfig.fakePlayerAutoReplenishmentFormShulkerBox) {
pullMatchingStackFromShulkerBox(itemStack, itemStackList, count);
}
}
}
private static boolean pullMatchingStack(@NotNull ItemStack targetStack, NonNullList<ItemStack> itemStackList, int transferLimit) {
for (ItemStack inventoryStack : itemStackList) {
if (inventoryStack == ItemStack.EMPTY || inventoryStack == targetStack) {
continue;
}
if (ItemStack.isSameItemSameComponents(inventoryStack, targetStack)) {
if (inventoryStack.getCount() > transferLimit) {
targetStack.setCount(targetStack.getCount() + transferLimit);
inventoryStack.setCount(inventoryStack.getCount() - transferLimit);
} else {
targetStack.setCount(targetStack.getCount() + inventoryStack.getCount());
inventoryStack.setCount(0);
}
return true;
}
}
return false;
}
private static boolean pullMatchingStackFromShulkerBox(@NotNull ItemStack targetStack, NonNullList<ItemStack> itemStackList, int transferLimit) {
for (ItemStack containerStack : itemStackList) {
if (containerStack == ItemStack.EMPTY || !containerStack.is(ItemTags.SHULKER_BOXES)) {
continue;
}
ItemContainerContents contents = containerStack.getOrDefault(DataComponents.CONTAINER, ItemContainerContents.EMPTY);
NonNullList<ItemStack> shulkerItems = NonNullList.withSize(contents.items.size(), ItemStack.EMPTY);
contents.copyInto(shulkerItems);
for (int slot = 0; slot < shulkerItems.size(); slot++) {
ItemStack shulkerStack = shulkerItems.get(slot);
if (shulkerStack.isEmpty() || !ItemStack.isSameItemSameComponents(shulkerStack, targetStack)) {
for (ItemStack itemStack1 : itemStackList) {
if (itemStack1 == ItemStack.EMPTY || itemStack1 == itemStack) {
continue;
}
int moved = Math.min(Math.min(transferLimit, shulkerStack.getCount()), targetStack.getMaxStackSize() - targetStack.getCount());
if (moved <= 0) {
return false;
if (ItemStack.isSameItemSameComponents(itemStack1, itemStack)) {
if (itemStack1.getCount() > count) {
itemStack.setCount(itemStack.getCount() + count);
itemStack1.setCount(itemStack1.getCount() - count);
} else {
itemStack.setCount(itemStack.getCount() + itemStack1.getCount());
itemStack1.setCount(0);
}
break;
}
targetStack.grow(moved);
shulkerStack.shrink(moved);
shulkerItems.set(slot, shulkerStack.isEmpty() ? ItemStack.EMPTY : shulkerStack);
containerStack.set(DataComponents.CONTAINER, ItemContainerContents.fromItems(shulkerItems));
return true;
}
}
return false;
}
public static void replaceTool(@NotNull EquipmentSlot slot, @NotNull ServerBot bot) {
@@ -93,7 +93,7 @@ public class ServerBot extends ServerPlayer {
private static final int AUTO_FISH_ENTITY_DELAY = 20;
private final List<AbstractBotAction<?>> actions;
private final Map<String, AbstractBotConfig<?, ?>> configs;
private final Map<String, AbstractBotConfig<?>> configs;
public boolean resume = false;
public BotCreateState createState;
@@ -116,9 +116,10 @@ public class ServerBot extends ServerPlayer {
this.gameMode = new ServerBotGameMode(this);
this.actions = new ArrayList<>();
ImmutableMap.Builder<String, AbstractBotConfig<?, ?>> configBuilder = ImmutableMap.builder();
for (AbstractBotConfig<?, ?> config : Configs.getConfigs()) {
configBuilder.put(config.getName(), config.create().setBot(this));
ImmutableMap.Builder<String, AbstractBotConfig<?>> configBuilder = ImmutableMap.builder();
for (Configs<?> config : Configs.getConfigs()) {
configBuilder.put(config.getName(), config.create(this));
}
this.configs = configBuilder.build();
@@ -147,7 +148,7 @@ public class ServerBot extends ServerPlayer {
this.joining = false;
}
// this.resetOperationCountPerTick(); // Leaves - player operation limiter
//this.resetOperationCountPerTick(); // Leaves - player operation limiter // Lophine
this.wardenSpawnTracker.tick();
if (this.invulnerableTime > 0) {
this.invulnerableTime--;
@@ -303,19 +304,6 @@ public class ServerBot extends ServerPlayer {
this.stopUsingItem();
teleportTransition.postTeleportTransition().onTransition(this);
this.isChangingDimension = false;
// Lophine - We don't have this
/* if (LeavesConfig.modify.netherPortalFix) {
final ResourceKey<Level> fromDim = fromLevel.dimension();
final ResourceKey<Level> toDim = level().dimension();
if (!((fromDim != Level.OVERWORLD || toDim != Level.NETHER) && (fromDim != Level.NETHER || toDim != Level.OVERWORLD))) {
BlockPos fromPortal = org.leavesmc.leaves.util.ReturnPortalManager.findPortalAt(this, fromDim, lastPos);
BlockPos toPos = this.blockPosition();
if (fromPortal != null) {
org.leavesmc.leaves.util.ReturnPortalManager.storeReturnPortal(this, toDim, toPos, fromPortal);
}
}
}*/
if (this.isBlocking()) {
this.stopUsingItem();
}
@@ -348,10 +336,8 @@ public class ServerBot extends ServerPlayer {
ItemStack item = this.getItemInHand(hand);
if (!item.isEmpty()) {
if (FakePlayerCompatConfig.fakePlayerAutoReplenishment) {
BotUtil.replenishment(item, getInventory().getNonEquipmentItems());
}
if (FakePlayerCompatConfig.fakePlayerAutoReplaceTool && BotUtil.isDamage(item, 10)) {
BotUtil.replenishment(item, getInventory().getNonEquipmentItems());
if (BotUtil.isDamage(item, 10)) {
BotUtil.replaceTool(hand == InteractionHand.MAIN_HAND ? EquipmentSlot.MAINHAND : EquipmentSlot.OFFHAND, this);
}
}
@@ -421,7 +407,7 @@ public class ServerBot extends ServerPlayer {
if (!this.configs.isEmpty()) {
ValueOutput.TypedOutputList<CompoundTag> configNbt = nbt.list("configs", CompoundTag.CODEC);
for (AbstractBotConfig<?, ?> config : this.configs.values()) {
for (AbstractBotConfig<?> config : this.configs.values()) {
configNbt.add(config.save(new CompoundTag()));
}
}
@@ -432,31 +418,23 @@ public class ServerBot extends ServerPlayer {
super.readAdditionalSaveData(nbt);
this.setShiftKeyDown(nbt.getBooleanOr("isShiftKeyDown", false));
CompoundTag createNbt = nbt.read("createStatus", CompoundTag.CODEC)
.orElseThrow(() -> new IllegalArgumentException("Missing bot createStatus"));
String rawName = createNbt.getString("rawName")
.orElseGet(() -> createNbt.getString("realName")
.orElseThrow(() -> new IllegalArgumentException("Missing bot rawName")));
String name = createNbt.getString("name")
.orElseThrow(() -> new IllegalArgumentException("Missing bot name"));
String skinName = createNbt.getStringOr("skinName", rawName);
CompoundTag createNbt = nbt.read("createStatus", CompoundTag.CODEC).orElseThrow();
BotCreateState.Builder createBuilder = BotCreateState
.builder(rawName, null) // Convert from legacy version, consider to use ca.spottedleaf.dataconverter.minecraft.MCDataConverter instead for release version
.name(name);
.builder(createNbt.getString("rawName")
.orElseGet(() -> createNbt.getString("realName")
.orElseThrow()), null) // Convert from legacy version, consider to use ca.spottedleaf.dataconverter.minecraft.MCDataConverter instead for release version
.name(createNbt.getString("name").orElseThrow());
String[] skin = null;
if (createNbt.contains("skin")) {
ListTag skinTag = createNbt.getList("skin")
.orElseThrow(() -> new IllegalArgumentException("Invalid bot skin list"));
ListTag skinTag = createNbt.getList("skin").orElseThrow();
skin = new String[skinTag.size()];
for (int i = 0; i < skinTag.size(); i++) {
final int skinIndex = i;
skin[i] = skinTag.getString(i)
.orElseThrow(() -> new IllegalArgumentException("Invalid bot skin entry at index " + skinIndex));
skin[i] = skinTag.getString(i).orElseThrow();
}
}
createBuilder.skinName(skinName).skin(skin);
createBuilder.skinName(createNbt.getString("skinName").orElseThrow()).skin(skin);
createBuilder.createReason(BotCreateEvent.CreateReason.INTERNAL).creator(null);
this.createState = createBuilder.build();
@@ -466,17 +444,11 @@ public class ServerBot extends ServerPlayer {
if (FakePlayerCompatConfig.fakePlayerReloadAction && nbt.list("actions", CompoundTag.CODEC).isPresent()) {
ValueInput.TypedInputList<CompoundTag> actionNbt = nbt.list("actions", CompoundTag.CODEC).orElseThrow();
actionNbt.forEach(actionTag -> {
try {
String actionName = actionTag.getString("actionName")
.orElseThrow(() -> new IllegalArgumentException("Missing actionName"));
AbstractBotAction<?> action = Actions.getForName(actionName);
if (action != null) {
AbstractBotAction<?> newAction = action.create();
newAction.load(actionTag);
this.actions.add(newAction);
}
} catch (RuntimeException exception) {
LophineLogger.LOGGER.warn("Skipped invalid saved action for bot {}", this.getScoreboardName(), exception);
Actions<?> holder = Actions.getByName(actionTag.getString("actionName").orElseThrow());
if (holder != null) {
AbstractBotAction<?> newAction = holder.create();
newAction.load(actionTag);
this.actions.add(newAction);
}
});
}
@@ -484,17 +456,12 @@ public class ServerBot extends ServerPlayer {
if (nbt.list("configs", CompoundTag.CODEC).isPresent()) {
ValueInput.TypedInputList<CompoundTag> configNbt = nbt.list("configs", CompoundTag.CODEC).orElseThrow();
for (CompoundTag configTag : configNbt) {
try {
String configName = configTag.getString("configName")
.orElseThrow(() -> new IllegalArgumentException("Missing configName"));
AbstractBotConfig<?, ?> config = Configs.getConfig(configName);
if (config != null) {
config.setBot(this);
config.load(configTag);
}
} catch (RuntimeException exception) {
LophineLogger.LOGGER.warn("Skipped invalid saved config for bot {}", this.getScoreboardName(), exception);
String key = configTag.getString("configName").orElseThrow();
if (!this.configs.containsKey(key)) {
LophineLogger.LOGGER.warn("Trying to load a unknown config \"{}\", discard.", key);
continue;
}
this.configs.get(key).load(configTag);
}
}
}
@@ -523,7 +490,7 @@ public class ServerBot extends ServerPlayer {
playerConnection.send(this.getAddEntityPacket(entityTracker.serverEntity));
if (login) {
Bukkit.getGlobalRegionScheduler().runDelayed(MinecraftInternalPlugin.INSTANCE, (task) -> playerConnection.send(new ClientboundRotateHeadPacket(this, (byte) ((getYRot() * 256f) / 360f))), 10);
Bukkit.getGlobalRegionScheduler().runDelayed(MinecraftInternalPlugin.INSTANCE, (_) -> playerConnection.send(new ClientboundRotateHeadPacket(this, (byte) ((getYRot() * 256f) / 360f))), 10);
} else {
playerConnection.send(new ClientboundRotateHeadPacket(this, (byte) ((getYRot() * 256f) / 360f)));
}
@@ -573,6 +540,11 @@ public class ServerBot extends ServerPlayer {
getServer().getBotList().removeBot(this, BotRemoveEvent.RemoveReason.DEATH, null, false, false);
}
@Override
protected int getBaseExperienceReward(@NotNull ServerLevel level) {
return this.isSpectator() ? 0 : Math.min(this.experienceLevel * 7, 100);
}
@Override
public boolean startRiding(@NotNull Entity vehicle, boolean force, boolean sendGameEvent) {
if (super.startRiding(vehicle, force, sendGameEvent)) {
@@ -764,15 +736,15 @@ public class ServerBot extends ServerPlayer {
}
@SuppressWarnings("unchecked")
public <T, E extends AbstractBotConfig<T, E>> AbstractBotConfig<T, E> getConfig(@NotNull AbstractBotConfig<T, E> config) {
return (AbstractBotConfig<T, E>) Objects.requireNonNull(this.configs.get(config.getName()));
public <T> AbstractBotConfig<T> getConfig(@NotNull Configs<? extends AbstractBotConfig<T>> config) {
return (AbstractBotConfig<T>) Objects.requireNonNull(this.configs.get(config.getName()));
}
public Collection<AbstractBotConfig<?, ?>> getAllConfigs() {
public Collection<AbstractBotConfig<?>> getAllConfigs() {
return configs.values();
}
public <T, E extends AbstractBotConfig<T, E>> T getConfigValue(@NotNull AbstractBotConfig<T, E> config) {
public <T> T getConfigValue(@NotNull Configs<? extends AbstractBotConfig<T>> config) {
return this.getConfig(config).getValue();
}
@@ -81,7 +81,7 @@ public class ServerBotGameMode extends ServerPlayerGameMode {
this.level.sendBlockUpdated(pos, blockState, blockState, 3);
return false;
} else {
BlockState blockState1 = /*isNoBlockUpdate() ? blockState : */block.playerWillDestroy(this.level, pos, blockState, this.player); // Leaves - no block update
BlockState blockState1 = /*isNoBlockUpdate() ? blockState : */block.playerWillDestroy(this.level, pos, blockState, this.player); // Leaves - no block update // Lophine
boolean flag = this.level.removeBlock(pos, false);
if (flag) {
block.destroy(this.level, pos, blockState1);
@@ -56,6 +56,11 @@ public class ServerBotPacketListenerImpl extends ServerGamePacketListenerImpl {
public void tick() {
}
@Override
public boolean hasClientLoaded() {
return true; // Don't kick me out!
}
public static class BotConnection extends Connection {
public BotConnection() {
@@ -17,49 +17,54 @@
package org.leavesmc.leaves.bot.agent;
import com.mojang.brigadier.exceptions.CommandSyntaxException;
import fun.bm.lophine.bot.BotActionGuiContainer;
import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.leavesmc.leaves.bot.agent.actions.*;
import org.leavesmc.leaves.command.CommandContext;
import org.leavesmc.leaves.entity.bot.action.*;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.function.Supplier;
public class Actions {
public class Actions<T extends AbstractBotAction<T>> {
private static final Map<String, AbstractBotAction<?>> actionsByName = new HashMap<>();
private static final Map<Class<?>, AbstractBotAction<?>> actionsByClass = new HashMap<>();
private static final Map<String, Actions<? extends AbstractBotAction<?>>> actionsByName = new HashMap<>();
private static final Map<Class<? extends BotAction<?>>, Actions<? extends AbstractBotAction<?>>> actionsByClass = new HashMap<>();
static {
register(new ServerAttackAction(), AttackAction.class);
register(new ServerBreakBlockAction(), BreakBlockAction.class);
register(new ServerDropAction(), DropAction.class);
register(new ServerJumpAction(), JumpAction.class);
register(new ServerSneakAction(), SneakAction.class);
register(new ServerUseItemAutoAction(), UseItemAutoAction.class);
register(new ServerUseItemAction(), UseItemAction.class);
register(new ServerUseItemOnAction(), UseItemOnAction.class);
register(new ServerUseItemToAction(), UseItemToAction.class);
register(new ServerUseItemOffhandAction(), UseItemOffhandAction.class);
register(new ServerUseItemOnOffhandAction(), UseItemOnOffhandAction.class);
register(new ServerUseItemToOffhandAction(), UseItemToOffhandAction.class);
register(new ServerLookAction(), LookAction.class);
register(new ServerFishAction(), FishAction.class);
register(new ServerSwimAction(), SwimAction.class);
register(new ServerRotationAction(), RotationAction.class);
register(new ServerMoveAction(), MoveAction.class);
register(new ServerMountAction(), MountAction.class);
register(new ServerSwapAction(), SwapAction.class);
register(AttackAction.class, ServerAttackAction::new);
register(BreakBlockAction.class, ServerBreakBlockAction::new);
register(DropAction.class, ServerDropAction::new);
register(JumpAction.class, ServerJumpAction::new);
register(SneakAction.class, ServerSneakAction::new);
register(UseItemAutoAction.class, ServerUseItemAutoAction::new);
register(UseItemAction.class, ServerUseItemAction::new);
register(UseItemOnAction.class, ServerUseItemOnAction::new);
register(UseItemToAction.class, ServerUseItemToAction::new);
register(UseItemOffhandAction.class, ServerUseItemOffhandAction::new);
register(UseItemOnOffhandAction.class, ServerUseItemOnOffhandAction::new);
register(UseItemToOffhandAction.class, ServerUseItemToOffhandAction::new);
register(LookAction.class, ServerLookAction::new);
register(FishAction.class, ServerFishAction::new);
register(SwimAction.class, ServerSwimAction::new);
register(RotationAction.class, ServerRotationAction::new);
register(MoveAction.class, ServerMoveAction::new);
register(MountAction.class, ServerMountAction::new);
register(SwapAction.class, ServerSwapAction::new);
}
public static boolean register(@NotNull AbstractBotAction<?> action, Class<?> type) {
public static <T extends AbstractBotAction<T>> boolean register(Class<? extends BotAction<?>> apiType, @NotNull Supplier<T> creator) {
AbstractBotAction<T> action = creator.get();
if (!actionsByName.containsKey(action.getName())) {
actionsByName.put(action.getName(), action);
actionsByClass.put(type, action);
Actions<?> actions = new Actions<>(creator.get().getName(), apiType, creator);
actionsByName.put(action.getName(), actions);
actionsByClass.put(apiType, actions);
if (action.getGuiData() != null) {
BotActionGuiContainer.registerGuiRootNode(action.getGuiData());
}
@@ -68,14 +73,37 @@ public class Actions {
return false;
}
public static boolean register(@NotNull AbstractBotAction<?> action) {
return register(action, action.getClass());
private final String name;
private final Class<?> apiType;
private final Supplier<T> creator;
private Actions(String name, Class<? extends BotAction<?>> apiType, Supplier<T> creator) {
this.name = name;
this.apiType = apiType;
this.creator = creator;
}
public String getName() {
return name;
}
public Class<?> getType() {
return apiType;
}
public T create() {
return creator.get();
}
public T createByCommand(CommandContext context) throws CommandSyntaxException {
T action = create();
action.loadCommand(context);
return action;
}
public static boolean unregister(@NotNull String name) {
AbstractBotAction<?> action = actionsByName.remove(name);
Actions<?> action = actionsByName.remove(name);
BotActionGuiContainer.unregisterGuiRootNode(name);
if (action != null) {
actionsByClass.remove(action.getClass());
return true;
@@ -85,7 +113,7 @@ public class Actions {
@NotNull
@Contract(pure = true)
public static Collection<AbstractBotAction<?>> getAll() {
public static Collection<Actions<? extends AbstractBotAction<?>>> getAll() {
return actionsByName.values();
}
@@ -95,12 +123,12 @@ public class Actions {
}
@Nullable
public static AbstractBotAction<?> getForName(String name) {
public static Actions<?> getByName(String name) {
return actionsByName.get(name);
}
@Nullable
public static AbstractBotAction<?> getForClass(@NotNull Class<?> type) {
public static Actions<?> getByClass(@NotNull Class<?> type) {
return actionsByClass.get(type);
}
}
@@ -19,41 +19,76 @@ package org.leavesmc.leaves.bot.agent;
import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.leavesmc.leaves.bot.ServerBot;
import org.leavesmc.leaves.bot.agent.configs.*;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
import java.util.function.Supplier;
@SuppressWarnings({"unused"})
public class Configs {
private static final Map<Class<?>, AbstractBotConfig<?, ?>> configs = new HashMap<>();
public class Configs<E extends AbstractBotConfig<?>> {
public static final SkipSleepConfig SKIP_SLEEP = register(new SkipSleepConfig());
public static final AlwaysSendDataConfig ALWAYS_SEND_DATA = register(new AlwaysSendDataConfig());
public static final SpawnPhantomConfig SPAWN_PHANTOM = register(new SpawnPhantomConfig());
public static final SimulationDistanceConfig SIMULATION_DISTANCE = register(new SimulationDistanceConfig());
public static final TickTypeConfig TICK_TYPE = register(new TickTypeConfig());
public static final LocatorBarConfig ENABLE_LOCATOR_BAR = register(new LocatorBarConfig());
private static final Map<String, Configs<? extends AbstractBotConfig<?>>> configs = new HashMap<>();
@Nullable
public static AbstractBotConfig<?, ?> getConfig(String name) {
public static final Configs<SkipSleepConfig> SKIP_SLEEP = register(SkipSleepConfig.class, SkipSleepConfig::new);
public static final Configs<AlwaysSendDataConfig> ALWAYS_SEND_DATA = register(AlwaysSendDataConfig.class, AlwaysSendDataConfig::new);
public static final Configs<SpawnPhantomConfig> SPAWN_PHANTOM = register(SpawnPhantomConfig.class, SpawnPhantomConfig::new);
public static final Configs<SimulationDistanceConfig> SIMULATION_DISTANCE = register(SimulationDistanceConfig.class, SimulationDistanceConfig::new);
public static final Configs<TickTypeConfig> TICK_TYPE = register(TickTypeConfig.class, TickTypeConfig::new);
public static final Configs<LocatorBarConfig> ENABLE_LOCATOR_BAR = register(LocatorBarConfig.class, LocatorBarConfig::new);
private final Class<? extends AbstractBotConfig<?>> configClass;
private final Supplier<? extends AbstractBotConfig<?>> configCreator;
private final String name;
private Configs(Class<? extends AbstractBotConfig<?>> configClass, Supplier<? extends AbstractBotConfig<?>> configCreator, String name) {
this.configClass = configClass;
this.configCreator = configCreator;
this.name = name;
}
public String getName() {
return name;
}
@SuppressWarnings("unchecked")
public E create() {
return (E) configCreator.get();
}
@SuppressWarnings("unchecked")
public E create(ServerBot bot) {
E config = (E) configCreator.get();
config.setBot(bot);
return config;
}
@NotNull
public static Optional<Configs<?>> getConfig(String name) {
return configs.values().stream()
.filter(config -> config.getName().equals(name))
.findFirst()
.orElse(null);
.filter(config -> config.name.equals(name))
.findFirst();
}
@NotNull
public static <T> Optional<Configs<?>> getConfig(Class<? extends AbstractBotConfig<T>> configClass) {
return configs.values().stream()
.filter(config -> config.configClass.equals(configClass))
.findFirst();
}
@NotNull
@Contract(pure = true)
public static Collection<AbstractBotConfig<?, ?>> getConfigs() {
public static Collection<Configs<? extends AbstractBotConfig<?>>> getConfigs() {
return configs.values();
}
@SuppressWarnings("unchecked")
private static <T, E extends AbstractBotConfig<T, E>> @NotNull E register(AbstractBotConfig<T, E> instance) {
configs.put(instance.getClass(), instance);
return (E) instance;
private static <T, E extends AbstractBotConfig<T>> @NotNull Configs<E> register(Class<? extends AbstractBotConfig<T>> configClass, Supplier<AbstractBotConfig<T>> configCreator) {
String name = configCreator.get().getName();
Configs<E> config = new Configs<>(configClass, configCreator, name);
configs.put(name, config);
return config;
}
}
@@ -1,3 +1,19 @@
/*
* This file is part of Leaves (https://github.com/LeavesMC/Leaves)
*
* Leaves is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Leaves is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Leaves. If not, see <https://www.gnu.org/licenses/>.
*/
package org.leavesmc.leaves.bot.agent;
import org.apache.commons.lang3.tuple.Pair;
@@ -30,20 +30,19 @@ import org.leavesmc.leaves.bot.ServerBot;
import org.leavesmc.leaves.bot.agent.ExtraData;
import org.leavesmc.leaves.command.CommandContext;
import org.leavesmc.leaves.command.WrappedArgument;
import org.leavesmc.leaves.entity.bot.actions.CraftBotAction;
import org.leavesmc.leaves.event.bot.BotActionExecuteEvent;
import org.leavesmc.leaves.event.bot.BotActionStopEvent;
import org.leavesmc.leaves.util.UpdateSuppressionException;
import java.util.*;
import java.util.function.Consumer;
import java.util.function.Supplier;
@SuppressWarnings("unchecked")
public abstract class AbstractBotAction<E extends AbstractBotAction<E>> {
private final String name;
private final Map<Integer, List<Pair<String, WrappedArgument<?>>>> arguments;
private final Supplier<E> creator;
private UUID uuid;
private int currentFork = 0;
@@ -61,10 +60,9 @@ public abstract class AbstractBotAction<E extends AbstractBotAction<E>> {
protected GuiRootNode guiData;
public AbstractBotAction(String name, Supplier<E> creator) {
public AbstractBotAction(String name) {
this.name = name;
this.uuid = UUID.randomUUID();
this.creator = creator;
this.arguments = new HashMap<>();
this.cancel = false;
@@ -75,7 +73,7 @@ public abstract class AbstractBotAction<E extends AbstractBotAction<E>> {
public abstract boolean doTick(@NotNull ServerBot bot);
public abstract Object asCraft();
public abstract CraftBotAction<?, E> asCraft();
public String getActionDataString() {
return getActionDataString(new ExtraData(new ArrayList<>()));
@@ -201,11 +199,6 @@ public abstract class AbstractBotAction<E extends AbstractBotAction<E>> {
public void loadCommand(@NotNull CommandContext context) throws CommandSyntaxException {
}
@NotNull
public E create() {
return this.creator.get();
}
public String getName() {
return this.name;
}
@@ -17,11 +17,9 @@
package org.leavesmc.leaves.bot.agent.actions;
import java.util.function.Supplier;
public abstract class AbstractStateBotAction<E extends AbstractStateBotAction<E>> extends AbstractBotAction<E> {
public AbstractStateBotAction(String name, Supplier<E> creator) {
super(name, creator);
public AbstractStateBotAction(String name) {
super(name);
this.setDoNumber(-1);
}
}
@@ -24,15 +24,13 @@ import org.jetbrains.annotations.NotNull;
import org.leavesmc.leaves.bot.agent.ExtraData;
import org.leavesmc.leaves.command.CommandContext;
import java.util.function.Supplier;
import static com.mojang.brigadier.arguments.IntegerArgumentType.integer;
import static org.leavesmc.leaves.command.ArgumentNode.ArgumentSuggestions.strings;
public abstract class AbstractTimerBotAction<E extends AbstractTimerBotAction<E>> extends AbstractBotAction<E> {
public AbstractTimerBotAction(String name, Supplier<E> creator, GuiRootNode guiData) {
super(name, creator);
public AbstractTimerBotAction(String name, GuiRootNode guiData) {
super(name);
String[] delaySuggestions = {"0", "5", "10", "20"};
String[] intervalSuggestions = {"20", "0", "5", "10"};
this.addArgument("delay", integer(0)).suggests(strings(delaySuggestions)).setOptional(true);
@@ -29,8 +29,6 @@ import org.leavesmc.leaves.bot.agent.ExtraData;
import org.leavesmc.leaves.command.CommandContext;
import org.leavesmc.leaves.event.bot.BotActionStopEvent;
import java.util.function.Supplier;
import static com.mojang.brigadier.arguments.IntegerArgumentType.integer;
public abstract class AbstractUseBotAction<T extends AbstractUseBotAction<T>> extends AbstractTimerBotAction<T> {
@@ -38,8 +36,8 @@ public abstract class AbstractUseBotAction<T extends AbstractUseBotAction<T>> ex
private int alreadyUsedTick = 0;
private int useItemRemainingTicks = 0;
public AbstractUseBotAction(String name, Supplier<T> supplier, GuiRootNode guiData) {
super(name, supplier, guiData);
public AbstractUseBotAction(String name, GuiRootNode guiData) {
super(name, guiData);
this.addArgument("use_timeout", integer(-1))
.suggests((context, builder) -> {
builder.suggest("-1", Component.literal("no use timeout"));
@@ -47,7 +45,6 @@ public abstract class AbstractUseBotAction<T extends AbstractUseBotAction<T>> ex
builder.suggest("10", Component.literal("minimum trident shoot time"));
})
.setOptional(true);
if (guiData == null) return;
for (GuiNode node : guiData.getAllFurthestChildren()) {
@@ -23,12 +23,13 @@ import net.minecraft.world.phys.EntityHitResult;
import org.jetbrains.annotations.NotNull;
import org.leavesmc.leaves.bot.ServerBot;
import org.leavesmc.leaves.entity.bot.actions.CraftAttackAction;
import org.leavesmc.leaves.entity.bot.actions.CraftBotAction;
public class ServerAttackAction extends AbstractTimerBotAction<ServerAttackAction> {
public ServerAttackAction() {
GuiRootNode guiData = new GuiRootNode("Attack", "Attack an entity", Items.DIAMOND_SWORD, "attack");
super("attack", ServerAttackAction::new, guiData);
super("attack", guiData);
}
@Override
@@ -43,7 +44,7 @@ public class ServerAttackAction extends AbstractTimerBotAction<ServerAttackActio
}
@Override
public Object asCraft() {
public CraftBotAction<?, ServerAttackAction> asCraft() {
return new CraftAttackAction(this);
}
}
@@ -30,13 +30,14 @@ import org.bukkit.block.Block;
import org.bukkit.craftbukkit.block.CraftBlock;
import org.jetbrains.annotations.NotNull;
import org.leavesmc.leaves.bot.ServerBot;
import org.leavesmc.leaves.entity.bot.actions.CraftBotAction;
import org.leavesmc.leaves.entity.bot.actions.CraftBreakBlockAction;
public class ServerBreakBlockAction extends AbstractTimerBotAction<ServerBreakBlockAction> {
public ServerBreakBlockAction() {
GuiRootNode guiRootNode = new GuiRootNode("Break", "Break a block", Items.DIAMOND_PICKAXE, "break");
super("break", ServerBreakBlockAction::new, guiRootNode);
super("break", guiRootNode);
}
private ItemStack lastItem = null;
@@ -122,7 +123,7 @@ public class ServerBreakBlockAction extends AbstractTimerBotAction<ServerBreakBl
}
@Override
public Object asCraft() {
public CraftBotAction<?, ServerBreakBlockAction> asCraft() {
return new CraftBreakBlockAction(this);
}
}
@@ -21,13 +21,14 @@ import fun.bm.lophine.bot.action.gui.GuiRootNode;
import net.minecraft.world.item.Items;
import org.jetbrains.annotations.NotNull;
import org.leavesmc.leaves.bot.ServerBot;
import org.leavesmc.leaves.entity.bot.actions.CraftBotAction;
import org.leavesmc.leaves.entity.bot.actions.CraftDropAction;
public class ServerDropAction extends AbstractTimerBotAction<ServerDropAction> {
public ServerDropAction() {
GuiRootNode guiRootNode = new GuiRootNode("Drop", "Drop all items", Items.BARRIER, "drop");
super("drop", ServerDropAction::new, guiRootNode);
super("drop", guiRootNode);
}
@Override
@@ -37,7 +38,7 @@ public class ServerDropAction extends AbstractTimerBotAction<ServerDropAction> {
}
@Override
public Object asCraft() {
public CraftBotAction<?, ServerDropAction> asCraft() {
return new CraftDropAction(this);
}
}
@@ -26,13 +26,14 @@ import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.Items;
import org.jetbrains.annotations.NotNull;
import org.leavesmc.leaves.bot.ServerBot;
import org.leavesmc.leaves.entity.bot.actions.CraftBotAction;
import org.leavesmc.leaves.entity.bot.actions.CraftFishAction;
public class ServerFishAction extends AbstractTimerBotAction<ServerFishAction> {
public ServerFishAction() {
GuiRootNode guiRootNode = new GuiRootNode("Fish", "Fish", Items.FISHING_ROD, "fish");
super("fish", ServerFishAction::new, guiRootNode);
super("fish", guiRootNode);
}
private static final int CATCH_ENTITY_DELAY = 20;
@@ -94,7 +95,7 @@ public class ServerFishAction extends AbstractTimerBotAction<ServerFishAction> {
}
@Override
public Object asCraft() {
public CraftBotAction<?, ServerFishAction> asCraft() {
return new CraftFishAction(this);
}
}
@@ -21,13 +21,14 @@ import fun.bm.lophine.bot.action.gui.GuiRootNode;
import net.minecraft.world.item.Items;
import org.jetbrains.annotations.NotNull;
import org.leavesmc.leaves.bot.ServerBot;
import org.leavesmc.leaves.entity.bot.actions.CraftBotAction;
import org.leavesmc.leaves.entity.bot.actions.CraftJumpAction;
public class ServerJumpAction extends AbstractTimerBotAction<ServerJumpAction> {
public ServerJumpAction() {
GuiRootNode guiRootNode = new GuiRootNode("Jump", "Jump", Items.ELYTRA, "jump");
super("jump", ServerJumpAction::new, guiRootNode);
super("jump", guiRootNode);
}
@Override
@@ -41,7 +42,7 @@ public class ServerJumpAction extends AbstractTimerBotAction<ServerJumpAction> {
}
@Override
public Object asCraft() {
public CraftBotAction<?, ServerJumpAction> asCraft() {
return new CraftJumpAction(this);
}
}
@@ -31,6 +31,7 @@ import org.bukkit.util.Vector;
import org.jetbrains.annotations.NotNull;
import org.leavesmc.leaves.bot.ServerBot;
import org.leavesmc.leaves.command.CommandContext;
import org.leavesmc.leaves.entity.bot.actions.CraftBotAction;
import org.leavesmc.leaves.entity.bot.actions.CraftLookAction;
public class ServerLookAction extends AbstractBotAction<ServerLookAction> {
@@ -41,7 +42,7 @@ public class ServerLookAction extends AbstractBotAction<ServerLookAction> {
private ServerPlayer target = null;
public ServerLookAction() {
super("look", ServerLookAction::new);
super("look");
this.addArgument("player", ArgumentTypes.player()).setOptional(true);
this.fork(1);
this.addArgument("location", ArgumentTypes.finePosition());
@@ -119,7 +120,7 @@ public class ServerLookAction extends AbstractBotAction<ServerLookAction> {
}
@Override
public Object asCraft() {
public CraftBotAction<?, ServerLookAction> asCraft() {
return new CraftLookAction(this);
}
}
@@ -24,6 +24,7 @@ import org.bukkit.craftbukkit.entity.CraftVehicle;
import org.bukkit.entity.Vehicle;
import org.jetbrains.annotations.NotNull;
import org.leavesmc.leaves.bot.ServerBot;
import org.leavesmc.leaves.entity.bot.actions.CraftBotAction;
import org.leavesmc.leaves.entity.bot.actions.CraftMountAction;
import java.util.Comparator;
@@ -32,7 +33,7 @@ import java.util.List;
public class ServerMountAction extends AbstractBotAction<ServerMountAction> {
public ServerMountAction() {
super("mount", ServerMountAction::new);
super("mount");
this.guiData = new GuiRootNode("Mount", "Mount", Items.SADDLE, "mount");
}
@@ -61,7 +62,7 @@ public class ServerMountAction extends AbstractBotAction<ServerMountAction> {
}
@Override
public Object asCraft() {
public CraftBotAction<?, ServerMountAction> asCraft() {
return new CraftMountAction(this);
}
}
@@ -25,6 +25,7 @@ import org.leavesmc.leaves.bot.agent.ExtraData;
import org.leavesmc.leaves.command.CommandContext;
import org.leavesmc.leaves.command.arguments.EnumArgumentType;
import org.leavesmc.leaves.entity.bot.action.MoveAction.MoveDirection;
import org.leavesmc.leaves.entity.bot.actions.CraftBotAction;
import org.leavesmc.leaves.entity.bot.actions.CraftMoveAction;
import org.leavesmc.leaves.event.bot.BotActionStopEvent;
@@ -32,7 +33,7 @@ public class ServerMoveAction extends AbstractStateBotAction<ServerMoveAction> {
private MoveDirection direction = MoveDirection.FORWARD;
public ServerMoveAction() {
super("move", ServerMoveAction::new);
super("move");
this.addArgument("direction", EnumArgumentType.fromEnum(MoveDirection.class));
this.guiData = new GuiRootNode("Move", "Move", null, "move", false);
@@ -83,7 +84,7 @@ public class ServerMoveAction extends AbstractStateBotAction<ServerMoveAction> {
}
@Override
public Object asCraft() {
public CraftBotAction<?, ServerMoveAction> asCraft() {
return new CraftMoveAction(this);
}
}
@@ -26,6 +26,7 @@ import org.jetbrains.annotations.NotNull;
import org.leavesmc.leaves.bot.ServerBot;
import org.leavesmc.leaves.bot.agent.ExtraData;
import org.leavesmc.leaves.command.CommandContext;
import org.leavesmc.leaves.entity.bot.actions.CraftBotAction;
import org.leavesmc.leaves.entity.bot.actions.CraftRotationAction;
import java.text.DecimalFormat;
@@ -35,7 +36,7 @@ public class ServerRotationAction extends AbstractBotAction<ServerRotationAction
private static final DecimalFormat DF = new DecimalFormat("0.00");
public ServerRotationAction() {
super("rotation", ServerRotationAction::new);
super("rotation");
this.addArgument("yaw", FloatArgumentType.floatArg(-180, 180))
.suggests((context, builder) -> {
CommandSender sender = context.getSender();
@@ -120,7 +121,7 @@ public class ServerRotationAction extends AbstractBotAction<ServerRotationAction
}
@Override
public Object asCraft() {
public CraftBotAction<?, ServerRotationAction> asCraft() {
return new CraftRotationAction(this);
}
}
@@ -20,13 +20,14 @@ package org.leavesmc.leaves.bot.agent.actions;
import fun.bm.lophine.bot.action.gui.GuiRootNode;
import org.jetbrains.annotations.NotNull;
import org.leavesmc.leaves.bot.ServerBot;
import org.leavesmc.leaves.entity.bot.actions.CraftBotAction;
import org.leavesmc.leaves.entity.bot.actions.CraftSneakAction;
import org.leavesmc.leaves.event.bot.BotActionStopEvent;
public class ServerSneakAction extends AbstractStateBotAction<ServerSneakAction> {
public ServerSneakAction() {
super("sneak", ServerSneakAction::new);
super("sneak");
this.guiData = new GuiRootNode("Sneak", "Sneak", null, "sneak");
}
@@ -48,7 +49,7 @@ public class ServerSneakAction extends AbstractStateBotAction<ServerSneakAction>
}
@Override
public Object asCraft() {
public CraftBotAction<?, ServerSneakAction> asCraft() {
return new CraftSneakAction(this);
}
}
@@ -23,12 +23,13 @@ import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.Items;
import org.jetbrains.annotations.NotNull;
import org.leavesmc.leaves.bot.ServerBot;
import org.leavesmc.leaves.entity.bot.actions.CraftBotAction;
import org.leavesmc.leaves.entity.bot.actions.CraftSwapAction;
public class ServerSwapAction extends AbstractBotAction<ServerSwapAction> {
public ServerSwapAction() {
super("swap", ServerSwapAction::new);
super("swap");
this.guiData = new GuiRootNode("Swap", "Swap", Items.SHIELD, "swap");
}
@@ -43,7 +44,7 @@ public class ServerSwapAction extends AbstractBotAction<ServerSwapAction> {
}
@Override
public Object asCraft() {
public CraftBotAction<?, ServerSwapAction> asCraft() {
return new CraftSwapAction(this);
}
}
@@ -22,12 +22,13 @@ import net.minecraft.world.item.Items;
import net.minecraft.world.phys.Vec3;
import org.jetbrains.annotations.NotNull;
import org.leavesmc.leaves.bot.ServerBot;
import org.leavesmc.leaves.entity.bot.actions.CraftBotAction;
import org.leavesmc.leaves.entity.bot.actions.CraftSwimAction;
public class ServerSwimAction extends AbstractStateBotAction<ServerSwimAction> {
public ServerSwimAction() {
super("swim", ServerSwimAction::new);
super("swim");
this.guiData = new GuiRootNode("Swim", "Swim", Items.WATER_BUCKET, "swim");
}
@@ -41,7 +42,7 @@ public class ServerSwimAction extends AbstractStateBotAction<ServerSwimAction> {
}
@Override
public Object asCraft() {
public CraftBotAction<?, ServerSwimAction> asCraft() {
return new CraftSwimAction(this);
}
}
@@ -21,12 +21,13 @@ import net.minecraft.world.InteractionHand;
import net.minecraft.world.InteractionResult;
import org.jetbrains.annotations.NotNull;
import org.leavesmc.leaves.bot.ServerBot;
import org.leavesmc.leaves.entity.bot.actions.CraftBotAction;
import org.leavesmc.leaves.entity.bot.actions.CraftUseItemAction;
public class ServerUseItemAction extends AbstractUseBotAction<ServerUseItemAction> {
public ServerUseItemAction() {
super("use", ServerUseItemAction::new, null);
super("use", null);
}
@Override
@@ -44,7 +45,7 @@ public class ServerUseItemAction extends AbstractUseBotAction<ServerUseItemActio
}
@Override
public Object asCraft() {
public CraftBotAction<?, ServerUseItemAction> asCraft() {
return new CraftUseItemAction(this);
}
}
@@ -30,6 +30,7 @@ import net.minecraft.world.phys.Vec3;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.leavesmc.leaves.bot.ServerBot;
import org.leavesmc.leaves.entity.bot.actions.CraftBotAction;
import org.leavesmc.leaves.entity.bot.actions.CraftUseItemAutoAction;
import static org.leavesmc.leaves.bot.agent.actions.ServerUseItemAction.useItem;
@@ -40,7 +41,7 @@ public class ServerUseItemAutoAction extends AbstractUseBotAction<ServerUseItemA
public ServerUseItemAutoAction() {
GuiRootNode guiRootNode = new GuiRootNode("Use", "Use Item", Items.BOW, "use_auto");
super("use_auto", ServerUseItemAutoAction::new, guiRootNode);
super("use_auto", guiRootNode);
}
@Override
@@ -100,7 +101,7 @@ public class ServerUseItemAutoAction extends AbstractUseBotAction<ServerUseItemA
}
@Override
public Object asCraft() {
public CraftBotAction<?, ServerUseItemAutoAction> asCraft() {
return new CraftUseItemAutoAction(this);
}
}
@@ -20,6 +20,7 @@ package org.leavesmc.leaves.bot.agent.actions;
import net.minecraft.world.InteractionHand;
import org.jetbrains.annotations.NotNull;
import org.leavesmc.leaves.bot.ServerBot;
import org.leavesmc.leaves.entity.bot.actions.CraftBotAction;
import org.leavesmc.leaves.entity.bot.actions.CraftUseItemOffhandAction;
import static org.leavesmc.leaves.bot.agent.actions.ServerUseItemAction.useItem;
@@ -27,7 +28,7 @@ import static org.leavesmc.leaves.bot.agent.actions.ServerUseItemAction.useItem;
public class ServerUseItemOffhandAction extends AbstractUseBotAction<ServerUseItemOffhandAction> {
public ServerUseItemOffhandAction() {
super("use_offhand", ServerUseItemOffhandAction::new, null);
super("use_offhand", null);
}
@Override
@@ -36,7 +37,7 @@ public class ServerUseItemOffhandAction extends AbstractUseBotAction<ServerUseIt
}
@Override
public Object asCraft() {
public CraftBotAction<?, ServerUseItemOffhandAction> asCraft() {
return new CraftUseItemOffhandAction(this);
}
}
@@ -21,14 +21,16 @@ import net.minecraft.core.BlockPos;
import net.minecraft.world.InteractionHand;
import net.minecraft.world.InteractionResult;
import net.minecraft.world.phys.BlockHitResult;
import net.minecraft.world.phys.HitResult;
import org.jetbrains.annotations.NotNull;
import org.leavesmc.leaves.bot.ServerBot;
import org.leavesmc.leaves.entity.bot.actions.CraftBotAction;
import org.leavesmc.leaves.entity.bot.actions.CraftUseItemOnAction;
public class ServerUseItemOnAction extends AbstractUseBotAction<ServerUseItemOnAction> {
public ServerUseItemOnAction() {
super("use_on", ServerUseItemOnAction::new, null);
super("use_on", null);
}
@Override
@@ -38,7 +40,7 @@ public class ServerUseItemOnAction extends AbstractUseBotAction<ServerUseItemOnA
}
public static InteractionResult useItemOn(ServerBot bot, BlockHitResult hitResult, InteractionHand hand) {
if (hitResult == null) {
if (hitResult == null || hitResult.getType() == HitResult.Type.MISS) {
return InteractionResult.FAIL;
}
@@ -57,7 +59,7 @@ public class ServerUseItemOnAction extends AbstractUseBotAction<ServerUseItemOnA
}
@Override
public Object asCraft() {
public CraftBotAction<?, ServerUseItemOnAction> asCraft() {
return new CraftUseItemOnAction(this);
}
}
@@ -21,6 +21,7 @@ import net.minecraft.world.InteractionHand;
import net.minecraft.world.phys.BlockHitResult;
import org.jetbrains.annotations.NotNull;
import org.leavesmc.leaves.bot.ServerBot;
import org.leavesmc.leaves.entity.bot.actions.CraftBotAction;
import org.leavesmc.leaves.entity.bot.actions.CraftUseItemOnOffhandAction;
import static org.leavesmc.leaves.bot.agent.actions.ServerUseItemOnAction.useItemOn;
@@ -28,7 +29,7 @@ import static org.leavesmc.leaves.bot.agent.actions.ServerUseItemOnAction.useIte
public class ServerUseItemOnOffhandAction extends AbstractUseBotAction<ServerUseItemOnOffhandAction> {
public ServerUseItemOnOffhandAction() {
super("use_on_offhand", ServerUseItemOnOffhandAction::new, null);
super("use_on_offhand", null);
}
@Override
@@ -38,7 +39,7 @@ public class ServerUseItemOnOffhandAction extends AbstractUseBotAction<ServerUse
}
@Override
public Object asCraft() {
public CraftBotAction<?, ServerUseItemOnOffhandAction> asCraft() {
return new CraftUseItemOnOffhandAction(this);
}
}
@@ -27,12 +27,13 @@ import net.minecraft.world.phys.EntityHitResult;
import net.minecraft.world.phys.Vec3;
import org.jetbrains.annotations.NotNull;
import org.leavesmc.leaves.bot.ServerBot;
import org.leavesmc.leaves.entity.bot.actions.CraftBotAction;
import org.leavesmc.leaves.entity.bot.actions.CraftUseItemToAction;
public class ServerUseItemToAction extends AbstractUseBotAction<ServerUseItemToAction> {
public ServerUseItemToAction() {
super("use_to", ServerUseItemToAction::new, null);
super("use_to", null);
}
@Override
@@ -73,7 +74,7 @@ public class ServerUseItemToAction extends AbstractUseBotAction<ServerUseItemToA
}
@Override
public Object asCraft() {
public CraftBotAction<?, ServerUseItemToAction> asCraft() {
return new CraftUseItemToAction(this);
}
}
@@ -21,6 +21,7 @@ import net.minecraft.world.InteractionHand;
import net.minecraft.world.phys.EntityHitResult;
import org.jetbrains.annotations.NotNull;
import org.leavesmc.leaves.bot.ServerBot;
import org.leavesmc.leaves.entity.bot.actions.CraftBotAction;
import org.leavesmc.leaves.entity.bot.actions.CraftUseItemToOffhandAction;
import static org.leavesmc.leaves.bot.agent.actions.ServerUseItemToAction.useItemTo;
@@ -28,7 +29,7 @@ import static org.leavesmc.leaves.bot.agent.actions.ServerUseItemToAction.useIte
public class ServerUseItemToOffhandAction extends AbstractUseBotAction<ServerUseItemToOffhandAction> {
public ServerUseItemToOffhandAction() {
super("use_to_offhand", ServerUseItemToOffhandAction::new, null);
super("use_to_offhand", null);
}
@Override
@@ -38,7 +39,7 @@ public class ServerUseItemToOffhandAction extends AbstractUseBotAction<ServerUse
}
@Override
public Object asCraft() {
public CraftBotAction<?, ServerUseItemToOffhandAction> asCraft() {
return new CraftUseItemToOffhandAction(this);
}
}
@@ -32,42 +32,36 @@ import org.leavesmc.leaves.command.WrappedArgument;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.function.Supplier;
public abstract class AbstractBotConfig<T, E extends AbstractBotConfig<T, E>> {
public abstract class AbstractBotConfig<T> {
private final String name;
private final WrappedArgument<T> argument;
private final Supplier<E> creator;
protected ServerBot bot;
public AbstractBotConfig(String name, ArgumentType<T> type, Supplier<E> creator) {
public AbstractBotConfig(String name, ArgumentType<T> type) {
this.name = name;
this.argument = new WrappedArgument<>(name, type);
if (shouldApplySuggestions()) {
this.argument.suggests(this::applySuggestions);
}
this.creator = creator;
}
@SuppressWarnings("RedundantThrows")
public void applySuggestions(final CommandContext context, final SuggestionsBuilder builder) throws CommandSyntaxException {
}
public AbstractBotConfig<T, E> setBot(ServerBot bot) {
public AbstractBotConfig<T> setBot(ServerBot bot) {
this.bot = bot;
return this;
}
public E create() {
return creator.get();
}
public abstract T getValue();
public abstract void setValue(T value) throws CommandSyntaxException;
public abstract T loadFromCommand(@NotNull CommandContext context) throws CommandSyntaxException;
public abstract T parseFromCommand(@NotNull CommandContext context) throws CommandSyntaxException;
public String getName() {
return name;
@@ -23,11 +23,11 @@ import net.minecraft.nbt.CompoundTag;
import org.jetbrains.annotations.NotNull;
import org.leavesmc.leaves.command.CommandContext;
public class AlwaysSendDataConfig extends AbstractBotConfig<Boolean, AlwaysSendDataConfig> {
public class AlwaysSendDataConfig extends AbstractBotConfig<Boolean> {
private boolean value;
public AlwaysSendDataConfig() {
super("always_send_data", BoolArgumentType.bool(), AlwaysSendDataConfig::new);
super("always_send_data", BoolArgumentType.bool());
this.value = FakeplayerConfig.canSendDataAlways;
}
@@ -42,7 +42,7 @@ public class AlwaysSendDataConfig extends AbstractBotConfig<Boolean, AlwaysSendD
}
@Override
public Boolean loadFromCommand(@NotNull CommandContext context) {
public Boolean parseFromCommand(@NotNull CommandContext context) {
return context.getBoolean(getName());
}
@@ -28,11 +28,11 @@ import org.jetbrains.annotations.NotNull;
import org.leavesmc.leaves.command.CommandContext;
import org.leavesmc.leaves.plugin.MinecraftInternalPlugin;
public class LocatorBarConfig extends AbstractBotConfig<Boolean, LocatorBarConfig> {
public class LocatorBarConfig extends AbstractBotConfig<Boolean> {
private boolean value;
public LocatorBarConfig() {
super("enable_locator_bar", BoolArgumentType.bool(), LocatorBarConfig::new);
super("enable_locator_bar", BoolArgumentType.bool());
this.value = FakeplayerConfig.enableLocatorBar && CommandConfig.waypointsAndWaypointCommand;
}
@@ -53,7 +53,7 @@ public class LocatorBarConfig extends AbstractBotConfig<Boolean, LocatorBarConfi
}
if (this.bot != null) {
this.value = value;
ServerWaypointManager manager = this.bot.level().getWaypointManager(); // Lophine - waypoint for adapt of luminol ver
ServerWaypointManager manager = this.bot.level().getWaypointManager();
if (value) {
manager.trackWaypoint(this.bot);
} else {
@@ -65,7 +65,7 @@ public class LocatorBarConfig extends AbstractBotConfig<Boolean, LocatorBarConfi
}
@Override
public Boolean loadFromCommand(@NotNull CommandContext context) {
public Boolean parseFromCommand(@NotNull CommandContext context) {
return context.getBoolean(getName());
}
@@ -29,10 +29,10 @@ import org.leavesmc.leaves.plugin.MinecraftInternalPlugin;
import static net.minecraft.network.chat.Component.literal;
public class SimulationDistanceConfig extends AbstractBotConfig<Integer, SimulationDistanceConfig> {
public class SimulationDistanceConfig extends AbstractBotConfig<Integer> {
public SimulationDistanceConfig() {
super("simulation_distance", IntegerArgumentType.integer(2, 32), SimulationDistanceConfig::new);
super("simulation_distance", IntegerArgumentType.integer(2, 32));
}
@Override
@@ -55,7 +55,7 @@ public class SimulationDistanceConfig extends AbstractBotConfig<Integer, Simulat
}
@Override
public Integer loadFromCommand(@NotNull CommandContext context) {
public Integer parseFromCommand(@NotNull CommandContext context) {
return context.getInteger(getName());
}
@@ -26,10 +26,10 @@ import org.jetbrains.annotations.NotNull;
import org.leavesmc.leaves.command.CommandContext;
import org.leavesmc.leaves.plugin.MinecraftInternalPlugin;
public class SkipSleepConfig extends AbstractBotConfig<Boolean, SkipSleepConfig> {
public class SkipSleepConfig extends AbstractBotConfig<Boolean> {
public SkipSleepConfig() {
super("skip_sleep", BoolArgumentType.bool(), SkipSleepConfig::new);
super("skip_sleep", BoolArgumentType.bool());
}
@Override
@@ -55,7 +55,7 @@ public class SkipSleepConfig extends AbstractBotConfig<Boolean, SkipSleepConfig>
}
@Override
public Boolean loadFromCommand(@NotNull CommandContext context) {
public Boolean parseFromCommand(@NotNull CommandContext context) {
return context.getBoolean(getName());
}
@@ -24,11 +24,11 @@ import org.jetbrains.annotations.NotNull;
import org.leavesmc.leaves.bot.agent.ExtraData;
import org.leavesmc.leaves.command.CommandContext;
public class SpawnPhantomConfig extends AbstractBotConfig<Boolean, SpawnPhantomConfig> {
public class SpawnPhantomConfig extends AbstractBotConfig<Boolean> {
private boolean value;
public SpawnPhantomConfig() {
super("spawn_phantom", BoolArgumentType.bool(), SpawnPhantomConfig::new);
super("spawn_phantom", BoolArgumentType.bool());
this.value = FakeplayerConfig.canSpawnPhantom;
}
@@ -49,7 +49,7 @@ public class SpawnPhantomConfig extends AbstractBotConfig<Boolean, SpawnPhantomC
}
@Override
public Boolean loadFromCommand(@NotNull CommandContext context) {
public Boolean parseFromCommand(@NotNull CommandContext context) {
return context.getBoolean(getName());
}
@@ -26,16 +26,16 @@ import org.leavesmc.leaves.command.arguments.EnumArgumentType;
import java.util.Locale;
public class TickTypeConfig extends AbstractBotConfig<ServerBot.TickType, TickTypeConfig> {
public class TickTypeConfig extends AbstractBotConfig<ServerBot.TickType> {
private ServerBot.TickType value;
public TickTypeConfig() {
super("tick_type", EnumArgumentType.fromEnum(ServerBot.TickType.class), TickTypeConfig::new);
super("tick_type", EnumArgumentType.fromEnum(ServerBot.TickType.class));
this.value = FakeplayerConfig.tickType();
}
@Override
public ServerBot.TickType loadFromCommand(@NotNull CommandContext context) {
public ServerBot.TickType parseFromCommand(@NotNull CommandContext context) {
return context.getArgument("tick_type", ServerBot.TickType.class);
}
@@ -64,7 +64,7 @@ public class ConfigCommand extends BotSubcommand {
}
@Contract(pure = true)
private @NotNull Supplier<LiteralNode> configNodeCreator(AbstractBotConfig<?, ?> config) {
private @NotNull Supplier<LiteralNode> configNodeCreator(Configs<? extends AbstractBotConfig<?>> config) {
return () -> new ConfigNode<>(config);
}
@@ -76,13 +76,13 @@ public class ConfigCommand extends BotSubcommand {
protected boolean execute(CommandContext context) {
ServerBot bot = BotArgument.getBot(context);
CommandSender sender = context.getSender();
Collection<AbstractBotConfig<?, ?>> botConfigs = bot.getAllConfigs();
Collection<AbstractBotConfig<?>> botConfigs = bot.getAllConfigs();
sender.sendMessage(join(spaces(),
text("Bot", GRAY),
asAdventure(bot.getDisplayName()).append(text("'s", GRAY)),
text("configs:", GRAY)
));
for (AbstractBotConfig<?, ?> botConfig : botConfigs) {
for (AbstractBotConfig<?> botConfig : botConfigs) {
sender.sendMessage(join(spaces(),
botConfig.getNameComponent(),
text("=", GRAY),
@@ -94,16 +94,17 @@ public class ConfigCommand extends BotSubcommand {
}
private static class ConfigNode<T> extends LiteralNode {
private final AbstractBotConfig<T, ?> config;
private final Configs<? extends AbstractBotConfig<T>> config;
private ConfigNode(@NotNull AbstractBotConfig<T, ?> config) {
@SuppressWarnings({"rawtypes", "unchecked"})
private ConfigNode(@NotNull Configs config) {
super(config.getName());
this.config = config;
}
@Override
protected ArgumentBuilder<CommandSourceStack, ?> compileBase() {
RequiredArgumentBuilder<CommandSourceStack, ?> argument = config.getArgument()
RequiredArgumentBuilder<CommandSourceStack, ?> argument = config.create().getArgument()
.compile()
.executes(mojangCtx -> {
CommandContext ctx = new CommandContext(mojangCtx);
@@ -115,7 +116,7 @@ public class ConfigCommand extends BotSubcommand {
@Override
protected boolean execute(@NotNull CommandContext context) {
ServerBot bot = BotArgument.getBot(context);
AbstractBotConfig<T, ?> botConfig = bot.getConfig(config);
AbstractBotConfig<?> botConfig = bot.getConfig(config);
context.getSender().sendMessage(join(spaces(),
text("Bot", GRAY),
asAdventure(bot.getDisplayName()).append(text("'s", GRAY)),
@@ -129,9 +130,9 @@ public class ConfigCommand extends BotSubcommand {
private boolean executeSet(CommandContext context) throws CommandSyntaxException {
ServerBot bot = BotArgument.getBot(context);
AbstractBotConfig<T, ?> botConfig = bot.getConfig(config);
AbstractBotConfig<T> botConfig = bot.getConfig(config);
try {
botConfig.setValue(botConfig.loadFromCommand(context));
botConfig.setValue(botConfig.parseFromCommand(context));
} catch (ClassCastException e) {
throw CommandSyntaxException.BUILT_IN_EXCEPTIONS.dispatcherUnknownArgument().create();
}
@@ -24,6 +24,7 @@ import com.mojang.brigadier.suggestion.SuggestionsBuilder;
import fun.bm.lophine.config.modules.function.FakeplayerConfig;
import io.papermc.paper.command.brigadier.CommandSourceStack;
import net.kyori.adventure.text.format.NamedTextColor;
import net.minecraft.nbt.CompoundTag;
import org.bukkit.command.CommandSender;
import org.jetbrains.annotations.NotNull;
import org.leavesmc.leaves.bot.BotList;
@@ -32,6 +33,7 @@ import org.leavesmc.leaves.command.ArgumentNode;
import org.leavesmc.leaves.command.CommandContext;
import org.leavesmc.leaves.command.bot.BotSubcommand;
import java.util.Locale;
import java.util.Set;
import java.util.concurrent.CompletableFuture;
@@ -63,7 +65,7 @@ public class LoadCommand extends BotSubcommand {
String botName = context.getArgument(BotNameArgument.class);
BotList botList = BotList.INSTANCE;
CommandSender sender = context.getSender();
if (!botList.getManualSavedBotList().contains(botName)) {
if (!botList.getManualSavedBotList().contains(botName.toLowerCase(Locale.ROOT))) {
throw CommandSyntaxException.BUILT_IN_EXCEPTIONS.dispatcherUnknownArgument().create();
}
if (botList.getBotByName(botName) != null) {
@@ -83,13 +85,14 @@ public class LoadCommand extends BotSubcommand {
@Override
protected CompletableFuture<Suggestions> getSuggestions(CommandContext context, @NotNull SuggestionsBuilder builder) {
BotList botList = BotList.INSTANCE;
Set<String> bots = botList.getManualSavedBotList().keySet();
CompoundTag list = botList.getManualSavedBotList();
Set<String> bots = list.keySet();
if (bots.isEmpty()) {
return builder
.suggest("<NO SAVED BOT EXISTS>", net.minecraft.network.chat.Component.literal("There are no bots saved before, save one first."))
.buildFuture();
}
bots.forEach(builder::suggest);
bots.forEach(key -> builder.suggest(list.getCompoundOrEmpty(key).getString("name").orElseThrow()));
return builder.buildFuture();
}
}
@@ -20,7 +20,6 @@ package org.leavesmc.leaves.command.bot.subcommands;
import com.mojang.brigadier.arguments.StringArgumentType;
import com.mojang.brigadier.exceptions.CommandSyntaxException;
import io.papermc.paper.adventure.PaperAdventure;
import io.papermc.paper.threadedregions.scheduler.FoliaGlobalRegionScheduler;
import net.minecraft.world.entity.LivingEntity;
import org.bukkit.Bukkit;
import org.bukkit.command.CommandSender;
@@ -57,7 +56,7 @@ public class RemoveCommand extends BotSubcommand {
private static boolean removeBot(@NotNull ServerBot bot, @Nullable CommandSender sender, boolean taskQueue) {
if (taskQueue) {
bot.getBukkitEntity().taskScheduler.schedule((LivingEntity nmsEntity) -> removeBotOrigin(bot, sender), null, 1L);
bot.getBukkitEntity().taskScheduler.schedule((LivingEntity _) -> removeBotOrigin(bot, sender), null, 1L);
} else {
return removeBotOrigin(bot, sender);
}
@@ -102,12 +101,12 @@ public class RemoveCommand extends BotSubcommand {
boolean isReschedule = bot.removeTaskId != -1;
if (isReschedule) {
((FoliaGlobalRegionScheduler) Bukkit.getGlobalRegionScheduler()).cancelTask(bot.removeTaskId);
Bukkit.getScheduler().cancelTask(bot.removeTaskId);
}
bot.removeTaskId = ((FoliaGlobalRegionScheduler.GlobalScheduledTask) Bukkit.getGlobalRegionScheduler().runDelayed(MinecraftInternalPlugin.INSTANCE, (unused) -> {
bot.removeTaskId = Bukkit.getScheduler().runTaskLater(MinecraftInternalPlugin.INSTANCE, () -> {
bot.removeTaskId = -1;
removeBot(bot, sender);
}, removeTimeSeconds * 20L)).getTaskId();
}, removeTimeSeconds * 20L).getTaskId();
sender.sendMessage(join(spaces(),
text("Bot", GRAY),
@@ -52,17 +52,15 @@ public class StartCommand extends LiteralNode {
Actions.getAll().stream().map(this::actionNodeCreator).forEach(this::children);
}
private boolean handleStartCommand(CommandContext context, @NotNull AbstractBotAction<?> action) throws CommandSyntaxException {
private boolean handleStartCommand(CommandContext context, @NotNull Actions<?> holder) throws CommandSyntaxException {
ServerBot bot = getBot(context);
CommandSender sender = context.getSender();
// Create a new instance of the action to avoid sharing state between multiple actions
AbstractBotAction<?> newAction = action.create();
newAction.loadCommand(context);
if (bot.addBotAction(newAction, sender)) {
AbstractBotAction<?> action = holder.createByCommand(context);
if (bot.addBotAction(action, sender)) {
sender.sendMessage(join(spaces(),
text("Action", GRAY),
text(newAction.getName(), AQUA).hoverEvent(showText(text(newAction.getActionDataString()))),
text(holder.getName(), AQUA).hoverEvent(showText(text(action.getActionDataString()))),
text("has been issued to", GRAY),
asAdventure(bot.getDisplayName())
));
@@ -72,25 +70,25 @@ public class StartCommand extends LiteralNode {
}
@Contract(pure = true)
private @NotNull Supplier<LiteralNode> actionNodeCreator(AbstractBotAction<?> action) {
private @NotNull Supplier<LiteralNode> actionNodeCreator(Actions<?> action) {
return () -> new ActionLiteralNode(action);
}
private class ActionLiteralNode extends LiteralNode {
private final AbstractBotAction<?> action;
private final Actions<?> holder;
private ActionLiteralNode(@NotNull AbstractBotAction<?> action) {
super(action.getName());
this.action = action;
private ActionLiteralNode(@NotNull Actions<?> holder) {
super(holder.getName());
this.holder = holder;
}
@Override
protected ArgumentBuilder<CommandSourceStack, ?> compile() {
ArgumentBuilder<CommandSourceStack, ?> builder = super.compile();
Map<Integer, List<Pair<String, WrappedArgument<?>>>> arguments = action.getArguments();
Map<Integer, List<Pair<String, WrappedArgument<?>>>> arguments = holder.create().getArguments();
Command<CommandSourceStack> executor = context -> {
if (handleStartCommand(new CommandContext(context), action)) {
if (handleStartCommand(new CommandContext(context), holder)) {
return Command.SINGLE_SUCCESS;
} else {
return 0;
@@ -70,7 +70,7 @@ public class CraftBot extends CraftPlayer implements Bot {
@Override
public BotAction<?> getAction(int index) {
return (BotAction<?>) this.getHandle().getBotActions().get(index).asCraft();
return this.getHandle().getBotActions().get(index).asCraft();
}
@Override
@@ -26,7 +26,6 @@ import org.leavesmc.leaves.bot.BotCreateState;
import org.leavesmc.leaves.bot.BotList;
import org.leavesmc.leaves.bot.ServerBot;
import org.leavesmc.leaves.bot.agent.Actions;
import org.leavesmc.leaves.bot.agent.actions.AbstractBotAction;
import org.leavesmc.leaves.entity.bot.action.BotAction;
import org.leavesmc.leaves.event.bot.BotCreateEvent;
@@ -72,7 +71,7 @@ public class CraftBotManager implements BotManager {
@SuppressWarnings("unchecked")
@Override
public <T extends BotAction<T>> T newAction(@NotNull Class<T> type) {
AbstractBotAction<?> action = Actions.getForClass(type);
Actions<?> action = Actions.getByClass(type);
if (action == null) {
throw new IllegalArgumentException("No action registered for type: " + type.getName());
} else {