feat: 适配新版API更新

This commit is contained in:
2023-06-16 21:55:23 +08:00
parent 1fec3fb429
commit 4a76b774d1
64 changed files with 30 additions and 37 deletions

View File

@@ -0,0 +1,72 @@
package cn.hamster3.mc.plugin.ball.bukkit;
import cn.hamster3.mc.plugin.ball.bukkit.api.BallBukkitAPI;
import cn.hamster3.mc.plugin.ball.bukkit.hook.PlaceholderHook;
import cn.hamster3.mc.plugin.ball.bukkit.listener.BallBukkitListener;
import cn.hamster3.mc.plugin.ball.common.api.BallAPI;
import cn.hamster3.mc.plugin.ball.common.event.server.ServerOnlineEvent;
import org.bukkit.Bukkit;
import org.bukkit.plugin.java.JavaPlugin;
import java.util.logging.Logger;
public class HamsterBallPlugin extends JavaPlugin {
private static HamsterBallPlugin instance;
public static HamsterBallPlugin getInstance() {
return instance;
}
public static void sync(Runnable runnable) {
Bukkit.getScheduler().runTask(instance, runnable);
}
@Override
public void onLoad() {
instance = this;
Logger logger = getLogger();
BallBukkitAPI.init();
logger.info("BallBukkitAPI 已初始化.");
try {
BallBukkitAPI.getInstance().enable();
logger.info("BallBukkitAPI 已启动.");
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
public void onEnable() {
Logger logger = getLogger();
if (!BallAPI.getInstance().isConnected()) {
sync(() -> {
logger.info("由于 HamsterBall 未能成功连接, 服务器将立即关闭.");
Bukkit.shutdown();
});
return;
}
Bukkit.getPluginManager().registerEvents(BallBukkitListener.INSTANCE, this);
logger.info("已注册 BallBukkitListener.");
BallAPI.getInstance().sendBallMessage(
BallAPI.BALL_CHANNEL,
ServerOnlineEvent.ACTION,
new ServerOnlineEvent(BallAPI.getInstance().getLocalServerInfo())
);
logger.info("HamsterBall 已启动.");
sync(() -> {
if (Bukkit.getPluginManager().isPluginEnabled("PlaceholderAPI")) {
PlaceholderHook.INSTANCE.register();
logger.info("已挂载 PlaceholderAPI 变量!");
}
});
}
@Override
public void onDisable() {
try {
BallBukkitAPI.getInstance().disable();
} catch (Exception e) {
e.printStackTrace();
}
}
}

View File

@@ -0,0 +1,82 @@
package cn.hamster3.mc.plugin.ball.bukkit.api;
import cn.hamster3.mc.plugin.ball.bukkit.HamsterBallPlugin;
import cn.hamster3.mc.plugin.ball.bukkit.listener.BallBukkitListener;
import cn.hamster3.mc.plugin.ball.common.api.BallAPI;
import cn.hamster3.mc.plugin.ball.common.config.BallConfig;
import cn.hamster3.mc.plugin.ball.common.entity.BallServerInfo;
import cn.hamster3.mc.plugin.ball.common.entity.BallServerType;
import cn.hamster3.mc.plugin.ball.common.listener.BallDebugListener;
import org.bukkit.configuration.file.FileConfiguration;
import org.jetbrains.annotations.NotNull;
import java.sql.SQLException;
import java.util.Map;
import java.util.logging.Logger;
public class BallBukkitAPI extends BallAPI {
public BallBukkitAPI(@NotNull BallConfig config) {
super(config);
}
public static BallBukkitAPI getInstance() {
return (BallBukkitAPI) instance;
}
public static void init() {
if (instance != null) {
return;
}
HamsterBallPlugin plugin = HamsterBallPlugin.getInstance();
plugin.saveDefaultConfig();
FileConfiguration pluginConfig = plugin.getConfig();
Map<String, String> env = System.getenv();
String serverInfoID = env.getOrDefault("BALL_SERVER_INFO_ID",
pluginConfig.getString("server-info.id"));
String serverInfoName = env.getOrDefault("BALL_SERVER_INFO_NAME",
pluginConfig.getString("server-info.name"));
String serverInfoHost = env.getOrDefault("SERVER_IP",
pluginConfig.getString("server-info.host", "0.0.0.0"));
int serverInfoPort = Integer.parseInt(env.getOrDefault("SERVER_PORT",
String.valueOf(pluginConfig.getInt("server-info.port", 25577))));
BallServerInfo serverInfo = new BallServerInfo(
serverInfoID,
serverInfoName,
BallServerType.GAME,
serverInfoHost.isEmpty() ? "127.0.0.1" : serverInfoHost,
serverInfoPort
);
String serverHost = env.getOrDefault("BALL_SERVER_HOST",
pluginConfig.getString("ball-server.host", "ball.hamster3.cn"));
int serverPort = Integer.parseInt(env.getOrDefault("BALL_SERVER_PORT",
String.valueOf(pluginConfig.getInt("ball-server.port", 58888))));
int eventLoopThread = Integer.parseInt(env.getOrDefault("BALL_EVENT_LOOP_THREAD",
String.valueOf(pluginConfig.getInt("ball-server.event-loop-thread", 2))));
BallConfig config = new BallConfig(serverInfo, serverHost, serverPort, eventLoopThread);
instance = new BallBukkitAPI(config);
instance.addListener(BallBukkitListener.INSTANCE);
if (pluginConfig.getBoolean("debug", false)) {
instance.addListener(BallDebugListener.INSTANCE);
}
}
@Override
public void enable() throws SQLException, InterruptedException {
super.enable();
}
@Override
public void disable() throws SQLException, InterruptedException {
super.disable();
}
@Override
public @NotNull Logger getLogger() {
return HamsterBallPlugin.getInstance().getLogger();
}
}

View File

@@ -0,0 +1,82 @@
package cn.hamster3.mc.plugin.ball.bukkit.data;
import cn.hamster3.mc.plugin.ball.common.api.BallAPI;
import cn.hamster3.mc.plugin.ball.common.data.BallBlockPos;
import cn.hamster3.mc.plugin.core.common.util.CoreUtils;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.block.Block;
import org.bukkit.entity.Entity;
import org.jetbrains.annotations.NotNull;
@SuppressWarnings("unused")
public class BukkitBlockPos extends BallBlockPos {
public BukkitBlockPos(@NotNull String serverID, @NotNull String worldName, int x, int y, int z) {
super(serverID, worldName, x, y, z);
}
public BukkitBlockPos(@NotNull Entity player) {
this(player.getLocation());
}
public BukkitBlockPos(@NotNull Block block) {
super(
BallAPI.getInstance().getLocalServerId(),
block.getWorld().getName(),
block.getX(),
block.getY(),
block.getZ()
);
}
@SuppressWarnings("DataFlowIssue")
public BukkitBlockPos(@NotNull Location location) {
super(
BallAPI.getInstance().getLocalServerId(),
location.getWorld().getName(),
location.getBlockX(),
location.getBlockY(),
location.getBlockZ()
);
}
public BukkitBlockPos(@NotNull BallBlockPos location) {
super(
BallAPI.getInstance().getLocalServerId(),
location.getWorldName(),
location.getX(),
location.getY(),
location.getZ()
);
}
public static BukkitBlockPos fromJson(String json) {
return CoreUtils.GSON.fromJson(json, BukkitBlockPos.class);
}
@NotNull
public Location toBukkitLocation() {
return new Location(Bukkit.getWorld(getWorldName()), getX(), getY(), getZ(), 0, 0);
}
@NotNull
public BukkitLocation toServiceLocation() {
return new BukkitLocation(getServerID(), getWorldName(), getX(), getY(), getZ());
}
public boolean equals(@NotNull Block block) {
if (!BallAPI.getInstance().isLocalServer(getServerID())) {
return false;
}
if (!getWorldName().equals(block.getWorld().getName())) {
return false;
}
if (getX() != block.getX()) {
return false;
}
if (getY() != block.getY()) {
return false;
}
return getZ() == block.getZ();
}
}

View File

@@ -0,0 +1,84 @@
package cn.hamster3.mc.plugin.ball.bukkit.data;
import cn.hamster3.mc.plugin.ball.common.api.BallAPI;
import cn.hamster3.mc.plugin.ball.common.data.BallLocation;
import cn.hamster3.mc.plugin.core.common.util.CoreUtils;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.block.Block;
import org.bukkit.entity.Entity;
import org.jetbrains.annotations.NotNull;
@SuppressWarnings("unused")
public class BukkitLocation extends BallLocation {
public BukkitLocation(@NotNull String serverID, @NotNull String worldName, double x, double y, double z) {
super(serverID, worldName, x, y, z, 0, 0);
}
public BukkitLocation(@NotNull String serverID, @NotNull String worldName, double x, double y, double z, float yaw, float pitch) {
super(serverID, worldName, x, y, z, yaw, pitch);
}
public BukkitLocation(@NotNull Entity player) {
this(player.getLocation());
}
public BukkitLocation(@NotNull Block block) {
this(block.getLocation());
}
@SuppressWarnings("DataFlowIssue")
public BukkitLocation(@NotNull Location location) {
super(
BallAPI.getInstance().getLocalServerId(),
location.getWorld().getName(),
location.getX(),
location.getY(),
location.getZ(),
location.getYaw(),
location.getPitch()
);
}
public BukkitLocation(@NotNull BallLocation location) {
super(
location.getServerID(),
location.getWorldName(),
location.getX(),
location.getY(),
location.getZ(),
location.getYaw(),
location.getPitch()
);
}
public static BukkitLocation fromJson(String json) {
return CoreUtils.GSON.fromJson(json, BukkitLocation.class);
}
@NotNull
public Location toBukkitLocation() {
return new Location(Bukkit.getWorld(getWorldName()), getX(), getY(), getZ(), getYaw(), getPitch());
}
@NotNull
public BukkitBlockPos toBukkitBlockPos() {
return new BukkitBlockPos(getServerID(), getWorldName(), getBlockX(), getBlockY(), getBlockZ());
}
public boolean equals(@NotNull Block block) {
if (!BallAPI.getInstance().isLocalServer(getServerID())) {
return false;
}
if (!getWorldName().equals(block.getWorld().getName())) {
return false;
}
if (getX() != block.getX()) {
return false;
}
if (getY() != block.getY()) {
return false;
}
return getZ() == block.getZ();
}
}

View File

@@ -0,0 +1,55 @@
package cn.hamster3.mc.plugin.ball.bukkit.hook;
import cn.hamster3.mc.plugin.ball.common.api.BallAPI;
import me.clip.placeholderapi.expansion.PlaceholderExpansion;
import org.bukkit.OfflinePlayer;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public class PlaceholderHook extends PlaceholderExpansion {
public static final PlaceholderHook INSTANCE = new PlaceholderHook();
private PlaceholderHook() {
}
@Override
public @NotNull String getIdentifier() {
return "ball";
}
@Override
public @NotNull String getAuthor() {
return "MiniDay";
}
@Override
public @NotNull String getVersion() {
return "1.0.0";
}
@Override
public @Nullable String onRequest(OfflinePlayer player, @NotNull String params) {
switch (params) {
case "local_server_id": {
return BallAPI.getInstance().getLocalServerInfo().getId();
}
case "local_server_name": {
return BallAPI.getInstance().getLocalServerInfo().getName();
}
case "proxy_id": {
return BallAPI.getInstance().getPlayerInfo(player.getUniqueId()).getProxyServer();
}
case "proxy_name": {
String id = BallAPI.getInstance().getPlayerInfo(player.getUniqueId()).getProxyServer();
return BallAPI.getInstance().getServerInfo(id).getName();
}
}
return null;
}
@Override
public @Nullable String onPlaceholderRequest(Player player, @NotNull String params) {
return onRequest(player, params);
}
}

View File

@@ -0,0 +1,188 @@
package cn.hamster3.mc.plugin.ball.bukkit.listener;
import cn.hamster3.mc.plugin.ball.bukkit.HamsterBallPlugin;
import cn.hamster3.mc.plugin.ball.bukkit.data.BukkitLocation;
import cn.hamster3.mc.plugin.ball.common.api.BallAPI;
import cn.hamster3.mc.plugin.ball.common.data.BallMessageInfo;
import cn.hamster3.mc.plugin.ball.common.entity.BallServerType;
import cn.hamster3.mc.plugin.ball.common.event.operate.*;
import cn.hamster3.mc.plugin.ball.common.listener.BallListener;
import cn.hamster3.mc.plugin.core.bukkit.api.CoreBukkitAPI;
import cn.hamster3.mc.plugin.core.common.api.CoreAPI;
import cn.hamster3.mc.plugin.core.common.data.DisplayMessage;
import cn.hamster3.mc.plugin.core.common.util.CoreUtils;
import cn.hamster3.mc.plugin.core.common.util.Pair;
import cn.hamster3.mc.plugin.core.lib.net.kyori.adventure.audience.Audience;
import cn.hamster3.mc.plugin.core.lib.net.kyori.adventure.text.TextReplacementConfig;
import lombok.AllArgsConstructor;
import lombok.Data;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerJoinEvent;
import org.bukkit.event.player.PlayerTeleportEvent;
import org.jetbrains.annotations.NotNull;
import java.util.HashMap;
import java.util.UUID;
public class BallBukkitListener implements Listener, BallListener {
public static final BallBukkitListener INSTANCE = new BallBukkitListener();
private final HashMap<UUID, Pair<Location, DisplayMessage>> playerToLocation = new HashMap<>();
private final HashMap<UUID, ToPlayerData> playerToPlayer = new HashMap<>();
private BallBukkitListener() {
}
@Override
public void onServiceDead() {
Bukkit.shutdown();
}
@Override
public void onMessageReceived(@NotNull BallMessageInfo info) {
switch (info.getAction()) {
case BroadcastPlayerMessageEvent.ACTION: {
BroadcastPlayerMessageEvent event = CoreUtils.GSON.fromJson(info.getContent(), BroadcastPlayerMessageEvent.class);
DisplayMessage message = event.getMessage();
Audience audience = CoreAPI.getInstance().getAudienceProvider().all();
message.show(audience);
break;
}
case DispatchConsoleCommandEvent.ACTION: {
DispatchConsoleCommandEvent event = CoreUtils.GSON.fromJson(info.getContent(), DispatchConsoleCommandEvent.class);
if (event.getType() != null && event.getType() != BallServerType.GAME) {
return;
}
if (event.getServerID() != null && !BallAPI.getInstance().isLocalServer(event.getServerID())) {
return;
}
Bukkit.dispatchCommand(Bukkit.getConsoleSender(), event.getCommand());
break;
}
case DispatchPlayerCommandEvent.ACTION: {
DispatchPlayerCommandEvent event = CoreUtils.GSON.fromJson(info.getContent(), DispatchPlayerCommandEvent.class);
if (event.getType() != null && event.getType() != BallServerType.GAME) {
return;
}
if (event.getUuid() != null) {
Player player = Bukkit.getPlayer(event.getUuid());
if (player == null) {
return;
}
Bukkit.dispatchCommand(player, event.getCommand());
return;
}
for (Player player : Bukkit.getOnlinePlayers()) {
Bukkit.dispatchCommand(player, event.getCommand());
}
break;
}
case SendPlayerToLocationEvent.ACTION: {
SendPlayerToLocationEvent event = CoreUtils.GSON.fromJson(info.getContent(), SendPlayerToLocationEvent.class);
BukkitLocation location = new BukkitLocation(event.getLocation());
if (BallAPI.getInstance().isLocalServer(location.getServerID())) {
for (UUID uuid : event.getSendPlayerUUID()) {
Player player = Bukkit.getPlayer(uuid);
if (player != null) {
HamsterBallPlugin.sync(() -> {
player.teleport(location.toBukkitLocation());
if (event.getDoneMessage() != null) {
Audience audience = CoreBukkitAPI.getInstance().getAudienceProvider().player(player);
event.getDoneMessage().show(audience);
}
});
} else {
playerToLocation.put(uuid, new Pair<>(location.toBukkitLocation(), event.getDoneMessage()));
}
}
}
break;
}
case SendPlayerToPlayerEvent.ACTION: {
SendPlayerToPlayerEvent event = CoreUtils.GSON.fromJson(info.getContent(), SendPlayerToPlayerEvent.class);
Player toPlayer = Bukkit.getPlayer(event.getToPlayerUUID());
if (toPlayer == null) {
break;
}
Location location = toPlayer.getLocation();
for (UUID uuid : event.getSendPlayerUUID()) {
Player sendPlayer = Bukkit.getPlayer(uuid);
if (sendPlayer != null) {
HamsterBallPlugin.sync(() -> {
sendPlayer.teleport(location);
if (event.getDoneMessage() != null) {
Audience audience = CoreBukkitAPI.getInstance().getAudienceProvider().player(sendPlayer);
event.getDoneMessage().show(audience, TextReplacementConfig.builder()
.matchLiteral("%player_name%")
.replacement(toPlayer.getName())
.build());
}
if (event.getDoneTargetMessage() != null) {
Audience audience = CoreBukkitAPI.getInstance().getAudienceProvider().player(toPlayer);
event.getDoneTargetMessage().show(audience, TextReplacementConfig.builder()
.matchLiteral("%player_name%")
.replacement(sendPlayer.getName())
.build());
}
});
} else {
ToPlayerData data = new ToPlayerData(
toPlayer.getUniqueId(),
toPlayer.getLocation(),
event.getDoneMessage(),
event.getDoneTargetMessage()
);
playerToPlayer.put(uuid, data);
}
}
break;
}
}
}
@EventHandler(ignoreCancelled = true, priority = EventPriority.HIGH)
public void onPlayerJoin(PlayerJoinEvent event) {
Player player = event.getPlayer();
UUID uuid = player.getUniqueId();
Pair<Location, DisplayMessage> pair = playerToLocation.remove(uuid);
if (pair != null) {
player.teleport(pair.getKey(), PlayerTeleportEvent.TeleportCause.PLUGIN);
if (pair.getValue() != null) {
Audience audience = CoreBukkitAPI.getInstance().getAudienceProvider().player(player);
pair.getValue().show(audience);
}
}
ToPlayerData toPlayerData = playerToPlayer.remove(uuid);
if (toPlayerData != null) {
player.teleport(toPlayerData.location);
if (toPlayerData.doneMessage != null) {
Audience audience = CoreBukkitAPI.getInstance().getAudienceProvider().player(player);
toPlayerData.doneMessage.show(audience, TextReplacementConfig.builder()
.matchLiteral("%player_name%")
.replacement(BallAPI.getInstance().getPlayerName(toPlayerData.toPlayerUUID, ""))
.build());
}
if (toPlayerData.doneTargetMessage != null) {
Audience audience = CoreBukkitAPI.getInstance().getAudienceProvider().player(toPlayerData.toPlayerUUID);
toPlayerData.doneTargetMessage.show(audience, TextReplacementConfig.builder()
.matchLiteral("%player_name%")
.replacement(player.getName())
.build());
}
}
}
@Data
@AllArgsConstructor
private static class ToPlayerData {
private UUID toPlayerUUID;
private Location location;
private DisplayMessage doneMessage;
private DisplayMessage doneTargetMessage;
}
}

View File

@@ -0,0 +1,27 @@
# 是否允许在控制台输出调试信息
debug: false
ball-server:
host: "ball.hamster3.cn"
port: 58888
event-loop-thread: 2
server-info:
# 服务器唯一识别码,最长 32 字符
# 推荐格式:全小写英文+横杠+数字尾号
# 例如:
# survival-1, survival-2生存1区生存2区
# plot-1, plot-2地皮1区地皮2区
# resource-1, resource-2资源1区资源2区
id: "test-1"
# 服务端名称,用于展示给玩家看
name: "测试1区"
# 当前子服的内网地址
# 不填则自动获取 server.properties 文件中的设置
# 若都为空,则自动设定为 127.0.0.1
# BC 端的插件会自动将这个服务器的地址和端口加入到列表
# 因此只需在这里配置好,以后新增子服时无需每次都手动更改 BC 的配置文件
# host: "127.0.0.1"
# 当前子服的内网端口
# 不填则自动获取 server.properties 文件中的设置
# port: 25577

View File

@@ -0,0 +1,16 @@
name: HamsterBall
main: cn.hamster3.mc.plugin.ball.bukkit.HamsterBallPlugin
version: ${version}
api-version: 1.13
author: MiniDay
website: https://gitee.com/MiniDay/hamster-ball
description: 仓鼠球:一个基于 Netty 的 Minecraft 服务端通用消息中间件原HamsterService
load: STARTUP
depend:
- HamsterCore
softdepend:
- PlaceholderAPI