feat: update fakeplayer code from Leaves

This commit is contained in:
Helvetica Volubi
2026-07-30 02:13:08 +08:00
parent 43036f971c
commit dd7ef6701a
60 changed files with 448 additions and 397 deletions
@@ -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 {