You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于Velocity代理的后端PaperMC插件跨服传送方法咨询

在PaperMC插件中实现Velocity代理下的跨服传送方法

核心思路

后端PaperMC服务器无法直接调用Velocity的传送逻辑,必须通过**插件消息通道(Plugin Message Channel)**与Velocity代理通信,由Velocity执行实际的跨服操作。以下是两种可行方案:


方案一:利用Velocity的BungeeCord兼容通道(无需额外Velocity插件)

Velocity原生兼容BungeeCord的插件消息协议,可直接通过内置的BungeeCord通道发送跨服请求,无需编写Velocity端插件。

1. 注册插件消息通道

在Paper插件的onEnable()方法中注册 outgoing 通道:

@Override
public void onEnable() {
    getServer().getMessenger().registerOutgoingPluginChannel(this, "BungeeCord");
}

2. 编写跨服传送方法

构建符合BungeeCord协议的消息包,发送给Velocity:

import org.bukkit.entity.Player;
import com.google.common.io.ByteStreams;
import java.io.ByteArrayDataOutput;

public void sendPlayerToServer(Player player, String targetServerName) {
    ByteArrayDataOutput out = ByteStreams.newDataOutput();
    // 指定操作类型为"Connect"(BungeeCord协议约定)
    out.writeUTF("Connect");
    // 目标服务器名称(需与Velocity配置文件中的server name一致)
    out.writeUTF(targetServerName);
    
    // 发送插件消息
    player.sendPluginMessage(this, "BungeeCord", out.toByteArray());
}

方案二:自定义插件消息通道(需编写Velocity端插件)

如果需要定制化逻辑(如传送前权限校验、状态同步),可通过自定义通道实现Paper与Velocity的双向通信。

Paper端实现

  1. 注册自定义通道:
@Override
public void onEnable() {
    getServer().getMessenger().registerOutgoingPluginChannel(this, "velocity:player-transfer");
}
  1. 发送传送请求:
import org.bukkit.entity.Player;
import com.google.common.io.ByteStreams;
import java.io.ByteArrayDataOutput;
import java.util.UUID;

public void transferPlayer(Player player, String targetServer) {
    ByteArrayDataOutput out = ByteStreams.newDataOutput();
    // 传递玩家UUID(Velocity端用于定位玩家)
    out.writeUTF(player.getUniqueId().toString());
    // 目标服务器名称
    out.writeUTF(targetServer);
    
    player.sendPluginMessage(this, "velocity:player-transfer", out.toByteArray());
}

Velocity端实现

  1. 注册自定义通道并监听消息:
import com.velocitypowered.api.event.Subscribe;
import com.velocitypowered.api.event.connection.PluginMessageEvent;
import com.velocitypowered.api.plugin.Plugin;
import com.velocitypowered.api.proxy.ProxyServer;
import com.velocitypowered.api.proxy.player.Player;
import com.velocitypowered.api.proxy.server.RegisteredServer;
import com.google.common.io.ByteStreams;
import java.io.ByteArrayDataInput;
import java.util.Optional;
import java.util.UUID;

@Plugin(id = "transferplugin", name = "TransferPlugin", version = "1.0")
public class TransferPlugin {
    private final ProxyServer proxy;

    public TransferPlugin(ProxyServer proxy) {
        this.proxy = proxy;
        // 注册自定义插件通道
        proxy.getPluginManager().registerPluginChannel(this, "velocity:player-transfer");
    }

    @Subscribe
    public void onPluginMessage(PluginMessageEvent event) {
        // 过滤非目标通道的消息
        if (!event.getIdentifier().getId().equals("velocity:player-transfer")) {
            return;
        }

        ByteArrayDataInput in = ByteStreams.newDataInput(event.getData());
        UUID playerId = UUID.fromString(in.readUTF());
        String targetServerName = in.readUTF();

        // 定位玩家与目标服务器
        Optional<Player> player = proxy.getPlayer(playerId);
        Optional<RegisteredServer> targetServer = proxy.getServer(targetServerName);

        // 执行传送
        if (player.isPresent() && targetServer.isPresent()) {
            player.get().createConnectionRequest(targetServer.get()).fireAndForget();
        }
    }
}

关键注意事项

  • 确保Velocity配置文件velocity.toml中已正确配置所有目标服务器,代码中使用的服务器名称必须与配置中的name字段完全一致。
  • 插件消息通道名称需在Paper和Velocity两端保持严格一致,自定义通道建议添加前缀(如velocity:)避免冲突。
  • 使用BungeeCord兼容通道时,Velocity会自动处理请求,但仅支持基础操作;自定义通道方案更灵活,可扩展复杂业务逻辑。
  • 发送插件消息前,务必确认通道已完成注册,否则会抛出IllegalArgumentException。

内容的提问来源于stack exchange,提问作者aquestry

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.26 04:43:34