Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ plugins {
}

group = 'com.springwater.easybot'
version = '2.1.1'
version = '2.1.2'

repositories {
mavenCentral()
Expand Down Expand Up @@ -60,7 +60,7 @@ tasks.build.dependsOn(tasks.shadowJar)

dependencies {
compileOnly "org.spigotmc:spigot-api:1.13.2-R0.1-SNAPSHOT"
implementation 'com.springwater.easybot:easybot-bridge:1.4-SNAPSHOT'
implementation 'com.springwater.easybot:easybot-bridge:1.5'
implementation 'org.javassist:javassist:3.28.0-GA'
implementation 'bot.inker.acj:runtime:1.5'
implementation 'org.reflections:reflections:0.10.2'
Expand All @@ -75,6 +75,9 @@ dependencies {

implementation("net.kyori:adventure-text-serializer-plain:4.17.0")
implementation("org.glavo:rcon-java:2.0.2")

compileOnly 'org.projectlombok:lombok:1.18.32'
annotationProcessor 'org.projectlombok:lombok:1.18.32'
}


Expand Down
Binary file added libs/fakeplayer-0.3.19.jar
Binary file not shown.
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
import java.util.logging.Logger;
import java.util.stream.Collectors;

public class EasyBotImpl implements BridgeBehavior {
public class BridgeImpl implements BridgeBehavior {
private final Logger logger = Logger.getLogger("EasyBotImpl");

@Override
Expand Down Expand Up @@ -187,6 +187,7 @@ public void SyncToChatExtra(List<Segment> segments, String text) {
@Override
public List<PlayerInfo> getPlayerList() {
return Bukkit.getOnlinePlayers().stream()
.filter(FakePlayerUtils::isNotFake)
.map(x -> {
PlayerInfo info = new PlayerInfo();
info.setPlayerName(GeyserUtils.getNameByPlayer(x));
Expand Down
15 changes: 11 additions & 4 deletions src/main/java/com/springwater/easybot/Easybot.java
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
import com.springwater.easybot.papi.OfflineStatisticExpansion;
import com.springwater.easybot.task.TaskManager;
import com.springwater.easybot.utils.BukkitUtils;
import com.springwater.easybot.utils.FakePlayerUtils;
import com.springwater.easybot.utils.ItemsAdderUtils;
import org.bukkit.Bukkit;
import org.bukkit.event.EventHandler;
Expand Down Expand Up @@ -57,7 +58,7 @@ public void onEnable() {
ClientProfile.setDebugMode(getConfig().getBoolean("debug", false));

instance = this;
bridgeBehavior = new EasyBotImpl();
bridgeBehavior = new BridgeImpl();

initHooks();

Expand All @@ -82,11 +83,11 @@ public void onEnable() {


private void handleSkinsRestorerCompatibility() {
if(BukkitUtils.hasSkinsRestorer() && !BukkitUtils.placeholderApiInstalled()){
if (BukkitUtils.hasSkinsRestorer() && !BukkitUtils.placeholderApiInstalled()) {
getLogger().info("\u001B[31m※ 检测到SkinsRestorer插件,但未检测到PlaceholderApi插件,EasyBot获取SkinsRestorer的皮肤需要依赖PlaceholderApi!\u001B[0m");
}

if (BukkitUtils.hasSkinsRestorer() && BukkitUtils.placeholderApiInstalled()) {
if (BukkitUtils.hasSkinsRestorer() && BukkitUtils.placeholderApiInstalled()) {
getLogger().info("\u001B[32m※ 检测到SkinsRestorer插件,玩家皮肤将通过该插件获取!\u001B[0m");
ClientProfile.setHasSkinsRestorer(true);
} else if (BukkitUtils.hasPaperSkinApi()) {
Expand All @@ -98,7 +99,7 @@ private void handleSkinsRestorerCompatibility() {
}

private void handleItemsAdderCompatibility() {
if(ItemsAdderUtils.isItemsAdderInstalled()){
if (ItemsAdderUtils.isItemsAdderInstalled()) {
getLogger().info("\u001B[32m※ 检测到ItemsAdder插件!\u001B[0m");
ClientProfile.setHasItemsAdder(true);
Bukkit.getPluginManager().registerEvents(new ItemsAdderEvents(), this);
Expand Down Expand Up @@ -238,6 +239,12 @@ private void initHooks() {
getLogger().info("\u001B[32m※ 已注册离线变量,专用文档: \u001B[33mhttps://docs.hualib.com/offline-papi.html\u001B[0m");
}

getLogger().info("\u001B[32m[>]\u001B[0m 假人插件");
if (FakePlayerUtils.isInstalled()) {
getLogger().info(" \u001B[32m[OK]\u001B[0m 已开启假人过滤");
} else {
getLogger().info(" \u001B[32m[OK]\u001B[0m 已关闭假人过滤");
}
}

private void uninstallPlaceholderApi() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import com.springwater.easybot.Easybot;
import com.springwater.easybot.bridge.packet.PlayerInfoWithRaw;
import com.springwater.easybot.utils.BridgeUtils;
import com.springwater.easybot.utils.FakePlayerUtils;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
Expand All @@ -12,6 +13,7 @@ public class BukkitSideMessageSyncEvents implements Listener {
@EventHandler(priority = EventPriority.LOWEST)
public static void syncMessage(AsyncPlayerChatEvent event){
if(Easybot.instance.getConfig().getBoolean("skip_options.skip_chat")) return;
if(FakePlayerUtils.isFake(event.getPlayer())) return;
if(!event.isCancelled()){
PlayerInfoWithRaw playerInfo = BridgeUtils.buildPlayerInfoFull(event.getPlayer());
new Thread(() -> Easybot.getClient().syncMessage(playerInfo, event.getMessage(), false), "EasyBotThread-SyncMessage(BukkitSide)").start();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import com.springwater.easybot.Easybot;
import com.springwater.easybot.bridge.packet.PlayerInfoWithRaw;
import com.springwater.easybot.utils.BridgeUtils;
import com.springwater.easybot.utils.FakePlayerUtils;
import io.papermc.paper.event.player.AsyncChatEvent;
import net.kyori.adventure.text.serializer.plain.PlainTextComponentSerializer;
import org.bukkit.event.EventHandler;
Expand All @@ -13,6 +14,7 @@ public class PaperSideMessageSyncEvents implements Listener {
@EventHandler(priority = EventPriority.LOWEST)
public static void syncMessage(AsyncChatEvent event){
if(Easybot.instance.getConfig().getBoolean("skip_options.skip_chat")) return;
if(FakePlayerUtils.isFake(event.getPlayer())) return;
if(!event.isCancelled()){
PlayerInfoWithRaw playerInfo = BridgeUtils.buildPlayerInfoFull(event.getPlayer());
String message = PlainTextComponentSerializer.plainText().serialize(event.message());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import com.springwater.easybot.Easybot;
import com.springwater.easybot.bridge.packet.PlayerInfoWithRaw;
import com.springwater.easybot.utils.BridgeUtils;
import com.springwater.easybot.utils.FakePlayerUtils;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
Expand All @@ -12,6 +13,7 @@ public class PlayerChatMessageSyncEvents implements Listener {
@EventHandler(priority = EventPriority.HIGHEST)
public static void syncMessage(PlayerChannelChatEvent event){
if(Easybot.instance.getConfig().getBoolean("skip_options.skip_chat")) return;
if(FakePlayerUtils.isFake(event.getPlayer())) return;
if(!event.isCancelled()){
PlayerInfoWithRaw playerInfo = BridgeUtils.buildPlayerInfoFull(event.getPlayer());
new Thread(() -> Easybot.getClient().syncMessage(playerInfo, event.getOriginalMessage(), false), "EasyBotThread-SyncMessage(PlayerChat)").start();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import com.springwater.easybot.Easybot;
import com.springwater.easybot.bridge.packet.PlayerInfoWithRaw;
import com.springwater.easybot.utils.BridgeUtils;
import com.springwater.easybot.utils.FakePlayerUtils;
import org.bukkit.block.Block;
import org.bukkit.entity.Arrow;
import org.bukkit.entity.Entity;
Expand Down Expand Up @@ -39,6 +40,7 @@ public String getKiller(Player player) {
@EventHandler(priority = EventPriority.LOWEST)
public void onPlayerDeath(PlayerDeathEvent event) {
if(Easybot.instance.getConfig().getBoolean("skip_options.skip_death")) return;
if(FakePlayerUtils.isFake(event.getPlayer())) return;
PlayerInfoWithRaw playerInfo = BridgeUtils.buildPlayerInfoFull(event.getEntity());
String deathMessage = event.getDeathMessage();
if(deathMessage == null){
Expand Down
7 changes: 2 additions & 5 deletions src/main/java/com/springwater/easybot/event/PlayerEvents.java
Original file line number Diff line number Diff line change
@@ -1,21 +1,18 @@
package com.springwater.easybot.event;

import com.google.errorprone.annotations.Var;
import com.springwater.easybot.Easybot;
import com.springwater.easybot.bridge.packet.PlayerLoginResultPacket;
import com.springwater.easybot.utils.BridgeUtils;
import com.springwater.easybot.utils.FakePlayerUtils;
import com.springwater.easybot.utils.GeyserUtils;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.player.AsyncPlayerPreLoginEvent;
import org.bukkit.event.player.PlayerJoinEvent;
import org.bukkit.event.player.PlayerLoginEvent;

public class PlayerEvents implements Listener {
@EventHandler
public void onPlayerLogin(AsyncPlayerPreLoginEvent event) {
try {
if(FakePlayerUtils.isFake(event.getName())) return;
String ip = event.getAddress().getHostAddress();
String name = GeyserUtils.getName(event.getUniqueId());
if (name == null) name = event.getPlayerProfile().getName();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import com.springwater.easybot.Easybot;
import com.springwater.easybot.bridge.packet.PlayerInfoWithRaw;
import com.springwater.easybot.utils.BridgeUtils;
import com.springwater.easybot.utils.FakePlayerUtils;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
Expand All @@ -13,13 +14,15 @@ public class PlayerJoinExitEvents implements Listener {
@EventHandler(priority = EventPriority.LOWEST)
public void onPlayerJoin(PlayerJoinEvent event) {
if(Easybot.instance.getConfig().getBoolean("skip_options.skip_join")) return;
if(FakePlayerUtils.isFake(event.getPlayer())) return;
PlayerInfoWithRaw playerInfo = BridgeUtils.buildPlayerInfoFull(event.getPlayer());
new Thread(() -> Easybot.getClient().syncEnterExit(playerInfo, true), "EasyBotThread-SyncPlayerJoinMessage").start();
}

@EventHandler(priority = EventPriority.LOWEST)
public void onPlayerQuit(PlayerQuitEvent event) {
if(Easybot.instance.getConfig().getBoolean("skip_options.skip_quit")) return;
if(FakePlayerUtils.isFake(event.getPlayer())) return;
PlayerInfoWithRaw playerInfo = BridgeUtils.buildPlayerInfoFull(event.getPlayer());
new Thread(() -> Easybot.getClient().syncEnterExit(playerInfo, false), "EasyBotThread-SyncPlayerExitMessage").start();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import com.springwater.easybot.Easybot;
import com.springwater.easybot.bridge.packet.PlayerInfoWithRaw;
import com.springwater.easybot.utils.BridgeUtils;
import com.springwater.easybot.utils.FakePlayerUtils;
import dev.unnm3d.redischat.api.events.AsyncRedisChatMessageEvent;
import net.kyori.adventure.text.serializer.plain.PlainTextComponentSerializer;
import org.bukkit.entity.Player;
Expand All @@ -17,6 +18,7 @@ public static void syncMessage(AsyncRedisChatMessageEvent event){
if(!event.isCancelled()){
if(event.getSender() instanceof Player){
Player player = (Player) event.getSender();
if(FakePlayerUtils.isFake(player)) return;
PlayerInfoWithRaw playerInfo = BridgeUtils.buildPlayerInfoFull(player);
String message = PlainTextComponentSerializer.plainText().serialize(event.getContent());
new Thread(() -> Easybot.getClient().syncMessage(playerInfo, message, false), "EasyBotThread-SyncMessage(PlayerChat)").start();
Expand Down
62 changes: 47 additions & 15 deletions src/main/java/com/springwater/easybot/rcon/NativeRcon.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,34 +8,66 @@

public class NativeRcon {
private Rcon rcon;
private String address;
private int port;
private String password;

public void start() throws AuthenticationException, IOException {
String address = Easybot.instance.getConfig().getString("adapter.native_rcon.address", "localhost");
int port = Easybot.instance.getConfig().getInt("adapter.native_rcon.port", 25575);
String password = Easybot.instance.getConfig().getString("adapter.native_rcon.password", "");
if(password.equals("")){
public synchronized void start() {
this.address = Easybot.instance.getConfig().getString("adapter.native_rcon.address", "localhost");
this.port = Easybot.instance.getConfig().getInt("adapter.native_rcon.port", 25575);
this.password = Easybot.instance.getConfig().getString("adapter.native_rcon.password", "");

if (this.password.isEmpty()) {
Easybot.instance.getLogger().warning("Rcon密码为空,可能无法连接到服务器!");
}
rcon = new Rcon(address, port, password);
attemptConnection();
}

public String executeCommand(String command){
if(rcon == null) return "Rcon不在线";
private void attemptConnection() {
close();

try {
rcon = new Rcon(address, port, password);
Easybot.instance.getLogger().info("Rcon连接成功: " + address + ":" + port);
} catch (IOException | AuthenticationException e) {
Easybot.instance.getLogger().warning("Rcon连接建立失败: " + e.getMessage());
rcon = null;
}
}

public synchronized String executeCommand(String command) {
if (rcon == null) {
attemptConnection();
if (rcon == null) {
return "Rcon离线,尝试重连失败";
}
}
try {
return rcon.command(command);
} catch (IOException e) {
Easybot.instance.getLogger().warning("NativeRCON执行失败: " + e);
return "NativeRCON执行失败,请查看服务器日志";
Easybot.instance.getLogger().warning("Rcon连接丢失,正在尝试自动重连...");
attemptConnection();
if (rcon != null) {
try {
return rcon.command(command);
} catch (IOException ex) {
Easybot.instance.getLogger().warning("Rcon重连后执行仍失败: " + ex);
return "Rcon重连成功,但命令执行失败: " + ex.getMessage();
}
} else {
return "Rcon连接断开,自动重连失败";
}
}
}

public void close(){
if(rcon == null) return;
public synchronized void close() {
if (rcon == null) return;
try {
rcon.close();
rcon = null;
} catch (IOException e) {
// 忽略关闭时的错误
} finally {
rcon = null;
}
}

}
}
56 changes: 56 additions & 0 deletions src/main/java/com/springwater/easybot/utils/FakePlayerUtils.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
package com.springwater.easybot.utils;
import io.github.hello09x.fakeplayer.core.Main;
import io.github.hello09x.fakeplayer.core.manager.FakeplayerList;
import io.github.hello09x.fakeplayer.core.manager.FakeplayerManager;
import lombok.SneakyThrows;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;

import java.lang.reflect.Field;
import java.util.Map;

public class FakePlayerUtils {
private static boolean installed = false;
private static FakeplayerList list;
private static volatile Map<String, Object> cachedPlayersMap;
public static boolean isInstalled() {
try {
// 找 io.github.hello09x.fakeplayer.core.Main
Class.forName("io.github.hello09x.fakeplayer.core.Main");
installed = true;
}catch (Exception ignored) {
installed = false;
}
return installed;
}

@SneakyThrows
private static void init(){
if(list != null) return;
list = Main.getInjector().getInstance(FakeplayerList.class);
// 解释一下为什么一定要通过这个字典获取
// https://github.com/tanyaofei/minecraft-fakeplayer/issues/191
Field field = list.getClass().getDeclaredField("playersByName");
field.setAccessible(true);
//noinspection unchecked
cachedPlayersMap = (Map<String, Object>) field.get(list);
}

public static boolean isNotFake(@NotNull Player player) {
if (!installed) return true;
init();
return !cachedPlayersMap.containsKey(player.getName());
}

public static boolean isFake(@NotNull Player player) {
if (!installed) return false;
init();
return cachedPlayersMap.containsKey(player.getName());
}

public static boolean isFake(@NotNull String name) {
if (!installed) return false;
init();
return cachedPlayersMap.containsKey(name);
}
}
2 changes: 1 addition & 1 deletion src/main/resources/plugin.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ version: '${version}'
main: com.springwater.easybot.Easybot
api-version: '1.13'
load: STARTUP
softdepend: [Essentials,PlaceHolderAPI,PlayerChat,RedisChat,TrChat,Geyser-Spigot,SkinsRestorer,ItemsAdder]
softdepend: [Essentials,PlaceHolderAPI,PlayerChat,RedisChat,TrChat,Geyser-Spigot,SkinsRestorer,ItemsAdder,FakePlayer]
folia-supported: true

commands:
Expand Down