├── docs ├── scoreboard-not-api │ └── 1.png ├── create-your-first-bungeecord-plugin │ ├── 1.png │ ├── 2.png │ ├── 3.png │ ├── eclipse-new-1.png │ ├── eclipse-new-2.png │ ├── eclipse-new-3.png │ └── eclipse-new-4.png ├── .vuepress │ ├── nav.js │ ├── config.js │ └── sidebar.js ├── README.md ├── creating-basic-command-functions-in-bungeecord.md ├── using-the-bungee-configuration-system.md ├── scoreboard-not-api.md ├── common-development-pitfalls-bungeecord.md ├── sending-players-between-servers-in-bungeecord.md ├── event-api.md ├── the-chat-component-api.md ├── create-your-first-bungeecord-plugin.md └── bukkit-bungee-plugin-messaging-channel.md ├── package.json ├── README.md ├── .github └── workflows │ └── deploy.yml └── .gitignore /docs/scoreboard-not-api/1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mouse0w0/BungeeCord-CN-Translation/HEAD/docs/scoreboard-not-api/1.png -------------------------------------------------------------------------------- /docs/create-your-first-bungeecord-plugin/1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mouse0w0/BungeeCord-CN-Translation/HEAD/docs/create-your-first-bungeecord-plugin/1.png -------------------------------------------------------------------------------- /docs/create-your-first-bungeecord-plugin/2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mouse0w0/BungeeCord-CN-Translation/HEAD/docs/create-your-first-bungeecord-plugin/2.png -------------------------------------------------------------------------------- /docs/create-your-first-bungeecord-plugin/3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mouse0w0/BungeeCord-CN-Translation/HEAD/docs/create-your-first-bungeecord-plugin/3.png -------------------------------------------------------------------------------- /docs/create-your-first-bungeecord-plugin/eclipse-new-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mouse0w0/BungeeCord-CN-Translation/HEAD/docs/create-your-first-bungeecord-plugin/eclipse-new-1.png -------------------------------------------------------------------------------- /docs/create-your-first-bungeecord-plugin/eclipse-new-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mouse0w0/BungeeCord-CN-Translation/HEAD/docs/create-your-first-bungeecord-plugin/eclipse-new-2.png -------------------------------------------------------------------------------- /docs/create-your-first-bungeecord-plugin/eclipse-new-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mouse0w0/BungeeCord-CN-Translation/HEAD/docs/create-your-first-bungeecord-plugin/eclipse-new-3.png -------------------------------------------------------------------------------- /docs/create-your-first-bungeecord-plugin/eclipse-new-4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mouse0w0/BungeeCord-CN-Translation/HEAD/docs/create-your-first-bungeecord-plugin/eclipse-new-4.png -------------------------------------------------------------------------------- /docs/.vuepress/nav.js: -------------------------------------------------------------------------------- 1 | module.exports = [ 2 | { text: '首页', link: '/' }, 3 | { text: '捐助译者', link: 'https://afdian.net/@mouse'}, 4 | { text: '原文链接', link: 'https://www.spigotmc.org/wiki/bungeecord-plugin-development/'} 5 | ] -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "bungeecord-cn-translation", 3 | "scripts": { 4 | "dev": "vuepress dev docs", 5 | "build": "vuepress build docs" 6 | }, 7 | "devDependencies": { 8 | "vuepress": "^1.8.3", 9 | "vuepress-theme-vdoing": "^1.8.6" 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 《BungeeCord插件开发》中文翻译 2 | 3 | ![](https://img.shields.io/badge/license-CC--BY--SA--4.0-green) 4 | 5 | [原文链接](https://www.spigotmc.org/wiki/bungeecord-plugin-development/) 6 | 7 | ## 捐助译者 8 | 翻译本篇教程付出了译者大量的业余时间。如果本教程对你有帮助的话,恳请点击下方的链接捐助译者。 9 | 10 | [捐助译者](https://afdian.com/@mouse) ← 求求给孩子一份早餐钱吧 11 | 12 | ## 版权声明 13 | ![[http://creativecommons.org/licenses/by-sa/4.0/](知识共享许可协议)](https://i.creativecommons.org/l/by-sa/4.0/88x31.png) 14 | 15 | 本作品采用[知识共享-署名-相同方式共享 4.0 国际许可协议](http://creativecommons.org/licenses/by-sa/4.0/)进行许可。 16 | 17 | 转载请附上本作品链接: https://github.com/mouse0w0/BungeeCord-CN-Translation 18 | -------------------------------------------------------------------------------- /docs/README.md: -------------------------------------------------------------------------------- 1 | --- 2 | article: false 3 | --- 4 | # 《BungeeCord插件开发》中文翻译 5 | 6 | ![](https://img.shields.io/badge/license-CC--BY--SA--4.0-green) 7 | 8 | [原文链接](https://www.spigotmc.org/wiki/bungeecord-plugin-development/) 9 | 10 | ## 捐助译者 11 | 翻译本篇教程付出了译者大量的业余时间。如果本教程对你有帮助的话,恳请点击下方的链接捐助译者。 12 | 13 | [捐助译者](https://afdian.com/@mouse) ← 求求给孩子一份早餐钱吧 14 | 15 | ## 版权声明 16 | ![[http://creativecommons.org/licenses/by-sa/4.0/](知识共享许可协议)](https://i.creativecommons.org/l/by-sa/4.0/88x31.png) 17 | 18 | 本作品采用[知识共享-署名-相同方式共享 4.0 国际许可协议](http://creativecommons.org/licenses/by-sa/4.0/)进行许可。 19 | 20 | 转载请附上本作品链接: https://github.com/mouse0w0/BungeeCord-CN-Translation 21 | -------------------------------------------------------------------------------- /.github/workflows/deploy.yml: -------------------------------------------------------------------------------- 1 | name: Deploy 2 | 3 | on: 4 | push: 5 | branches: [ main ] 6 | 7 | jobs: 8 | build-and-deploy: 9 | runs-on: ubuntu-latest 10 | steps: 11 | - uses: actions/checkout@v2 12 | - name: Setup Node.js environment 13 | uses: actions/setup-node@v2.4.1 14 | with: 15 | node-version: 16.x 16 | - name: Build the project 17 | run: | 18 | npm install 19 | npm run build 20 | - name: Deploy to GitHub Pages 21 | uses: crazy-max/ghaction-github-pages@v2.5.0 22 | with: 23 | build_dir: ./docs/.vuepress/dist/ 24 | target_branch: pages 25 | keep_history: true 26 | env: 27 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 28 | 29 | 30 | -------------------------------------------------------------------------------- /docs/.vuepress/config.js: -------------------------------------------------------------------------------- 1 | const nav = require('./nav.js'); 2 | const sidebar = require('./sidebar.js'); 3 | 4 | module.exports = { 5 | title: '《BungeeCord插件开发》中文翻译', 6 | base: '/BungeeCord-CN-Translation/', 7 | markdown: { 8 | lineNumbers: true 9 | }, 10 | theme: 'vdoing', 11 | themeConfig: { 12 | repo: 'mouse0w0/BungeeCord-CN-Translation', 13 | docsDir: 'docs', 14 | docsBranch: 'main', 15 | editLinks: true, 16 | editLinkText: '编辑此页面', 17 | nav, 18 | sidebar, 19 | sidebarDepth: 2, 20 | updateBar: { 21 | showToArticle: false 22 | }, 23 | titleBadge: false, 24 | category: false, 25 | tag: false, 26 | archive: false, 27 | rightMenuBar: false 28 | } 29 | } -------------------------------------------------------------------------------- /docs/creating-basic-command-functions-in-bungeecord.md: -------------------------------------------------------------------------------- 1 | --- 2 | article: false 3 | --- 4 | # 在 BungeeCord 中创建基本的指令 5 | 6 | BungeeCord 提供一个命令接口,类似于 Bukkit。本篇教程中,我们将创建一个简单的 "Hello World" 指令。 7 | 8 | ## 创建指令 9 | 10 | 创建一个名为 HelloWorldCommand 的类。这个类应该继承 Command。你的IDE应该会自动补全代码,现在我们需要实现构造方法和 execute() 方法。我们首先实现构造方法,然后再实现 execute() 方法。 11 | 12 | ## 构造方法 13 | 14 | Command 类有两个构造方法:一个简单的只有指令名的构造方法,和一个额外添加了权限和别名的构造方法。我们现在使用第一个。添加以下代码到你的类中: 15 | ```java 16 | public HelloWorldCommand() { 17 | super("helloworld"); 18 | } 19 | ``` 20 | 这将创建一个指令,使用 /helloworld 来执行指令。 21 | 22 | ## 执行方法 23 | 24 | 现在我们可以为指令添加实际的功能了。添加以下代码到你的类中: 25 | ```java 26 | @Override 27 | public void execute(CommandSender commandSender, String[] strings) { 28 | commandSender.sendMessage(new ComponentBuilder("Hello world!").color(ChatColor.GREEN).create()); 29 | } 30 | ``` 31 | 当玩家执行 /helloworld 指令时,消息 "Hello world!" (绿色)将会被发送给玩家。 32 | 33 | ## 注册指令 34 | 35 | 添加以下代码到 onEnable() 方法: 36 | ```java 37 | getProxy().getPluginManager().registerCommand(this, new HelloWorldCommand()); 38 | ``` 39 | 现在你已经创建了你自己的指令。与 Bukkit 不同的是,BungeeCord 不要求将指令添加至 plugin.yml。 -------------------------------------------------------------------------------- /docs/.vuepress/sidebar.js: -------------------------------------------------------------------------------- 1 | module.exports = [{ 2 | title: '教程', 3 | collapsable: false, 4 | children: [ 5 | ['/', '首页'], 6 | ['/create-your-first-bungeecord-plugin', '第一个插件'], 7 | ['/common-development-pitfalls-bungeecord', '常见问题'], 8 | ['/creating-basic-command-functions-in-bungeecord', '创建指令'], 9 | ['/event-api', '事件API'], 10 | ['/using-the-bungee-configuration-system', '配置API'], 11 | ['/the-chat-component-api', '聊天组件API'], 12 | ['/bukkit-bungee-plugin-messaging-channel', '插件消息频道'], 13 | ['/sending-players-between-servers-in-bungeecord', '传送玩家'], 14 | ['/scoreboard-not-api', '记分板API'] 15 | ] 16 | }, 17 | { 18 | title: '资源', 19 | collapsable: false, 20 | children: [ 21 | ['https://github.com/SpigotMC/BungeeCord/tree/master/api', 'BungeeCord API (Github)'], 22 | ['http://ci.md-5.net/job/BungeeCord/ws/api/target/apidocs/overview-summary.html', 'BungeeCord API (JavaDoc)'], 23 | ['http://ci.md-5.net/job/BungeeCord/ws/chat/target/apidocs/overview-summary.html', 'BungeeCord API (Chat JavaDoc)'], 24 | ] 25 | } 26 | ] -------------------------------------------------------------------------------- /docs/using-the-bungee-configuration-system.md: -------------------------------------------------------------------------------- 1 | --- 2 | article: false 3 | --- 4 | # BungeeCord 配置 API 5 | BungeeCord 包含一个简单的配置 API,支持 YAML 文件。 6 | 7 | ## 载入配置文件 8 | 不像 Bukkit 你可以使用 YamlConfiguration.loadConfiguration() 来载入配置文件。BungeeCord API 需要获取一个配置文件提供器。YAML 提供器叫做 YamlConfiguration。你不能自己创建这个类的实例,你必须从 ConfigurationProvider 获取它。 9 | 10 | ```java 11 | Configuration configuration = ConfigurationProvider.getProvider(YamlConfiguration.class).load(new File(getDataFolder(), "config.yml")); 12 | ``` 13 | 跟Bukkit不同的是,这个方法在不能读入文件时会抛出 IOException,因此你需要第一时间创建文件。 14 | 15 | ## 使用 Configuration 实例 16 | 使用 Configuration 实例应该是非常简单的。最常用的部分API已经实现,例如 getString。 17 | 18 | ## 保存配置文件 19 | 如果你知道怎么载入配置文件,这应该是无用的: 20 | ```java 21 | ConfigurationProvider.getProvider(YamlConfiguration.class).save(configuration, new File(getDataFolder(), "config.yml")); 22 | ``` 23 | 24 | ## 一些不提供的功能 25 | ### 保存默认配置文件 26 | 这是很简单的,代码如下: 27 | 28 | ```java 29 | if (!getDataFolder().exists()) 30 | getDataFolder().mkdir(); 31 | 32 | File file = new File(getDataFolder(), "config.yml"); 33 | 34 | 35 | if (!file.exists()) { 36 | try (InputStream in = getResourceAsStream("config.yml")) { 37 | Files.copy(in, file.toPath()); 38 | } catch (IOException e) { 39 | e.printStackTrace(); 40 | } 41 | } 42 | ``` 43 | 44 | ### 重载配置文件 45 | 再加载一次配置文件。 -------------------------------------------------------------------------------- /docs/scoreboard-not-api.md: -------------------------------------------------------------------------------- 1 | --- 2 | article: false 3 | --- 4 | # BungeeCord 记分板 (无 API) 5 | 6 | @md_5 和 @Thinkofdeath 创建 Bungeecord 记分板 API (net.md_5.bungee.api.score.*) 很长时间了。但它还没有准备好使用。不过他们已经实现了一些包装。所以我们可以用它们来创建记分板。在下面的代码示例中 p 表示 ProxiedPlayer 对象。 7 | 8 | ## 记分板是如何工作的? 9 | 通过 BungeeCord 创建记分板,了解其如何工作是非常重要的。最好的方式是在[这里](http://wiki.vg/Protocol#Scoreboard_Objective)。 10 | 11 | ## 创建一个变量 12 | 现在我们知道记分板是如何工作了。首先我们需要创建一个变量`(译者注:objective没有准确的翻译,另有译作"目标")` 13 | ```java 14 | ScoreboardObjective objective = new ScoreboardObjective("test", "Test", "integer", (byte) 0); 15 | p.unsafe().sendPacket(objective); 16 | ``` 17 | 解释: 18 | - "test" 是记分板的唯一名称 19 | - "Test" 是记分板显示的名称 20 | - "integer" 或者使用 "hearts" - [更多信息](http://wiki.vg/Protocol#Scoreboard_Objective) 21 | - 0 - 0 表示创建记分板。1 表示移除记分板。2 表示更新显示文本。 22 | 23 | ## 创建或删除一个分数 24 | ```java 25 | ScoreboardScore score = new ScoreboardScore("Hallo", (byte) 0, "test", 0); 26 | p.unsafe().sendPacket(score); 27 | ``` 28 | 解释: 29 | - "Hallo" 是要更新或删除的分数的名称 30 | - 0 - 0表示创建或更新一个分数。1表示移除一个分数。 31 | - "test" 是分数所属的变量的名称 32 | - 0 - 是显示在条目旁边的分数 33 | 34 | ## 显示记分板 35 | 现在客户端知道这个记分板的所有信息了,但是我们必须告诉客户端显示这个记分板。 36 | ```java 37 | ScoreboardDisplay display = new ScoreboardDisplay((byte) 1, "test"); 38 | p.unsafe().sendPacket(display); 39 | ``` 40 | 解释: 41 | - 1 - 记分板的位置。0: 列表,1: 侧边栏,2: 名字下方。 42 | - "test" - 要显示的记分板的唯一名称。 43 | 44 | 就是这样,看起来非常简单。如果所有的代码都能正常运作,那么结果如下所示: 45 | 46 | ![记分板](./scoreboard-not-api/1.png) 47 | 48 | ## 附注 49 | 客户端只在游戏中接收这些数据包。这意味着,如果你想在某个玩家加入游戏时向他们发送记分板,你最早可以在`ServerSwitchEvent`事件(该事件也在你第一次加入服务器时发布)将记分板发送给他们。所有更早的事件(比如`PostLogin`或`ServerConnected`)都是在客户端准备就绪前发布的。 -------------------------------------------------------------------------------- /docs/common-development-pitfalls-bungeecord.md: -------------------------------------------------------------------------------- 1 | --- 2 | article: false 3 | --- 4 | # 常见的 BungeeCord 开发问题 5 | 6 | 本篇教程是关于 BungeeCord 插件开发时常见的问题以及如何解决它们。 7 | 8 | ## 创建新线程 9 | 10 | 创建新的线程 (例如,创建 Thread(线程),Timer(定时器),Executor(执行器)) 在#948及其以上版本是不被鼓励的,并且在未来的版本将被禁止。 11 | 12 | 推荐的解决方案是使用 BungeeCord 的线程调度器(Scheduler): 13 | ```java 14 | getProxy().getScheduler().runAsync(this, new Runnable() { 15 | @Override 16 | public void run() { 17 | 18 | } 19 | }); 20 | ``` 21 | 如果你需要获得一个 [Future](http://docs.oracle.com/javase/8/docs/api/java/util/concurrent/Future.html),包装 Callable/Runnable 在一个 [FutureTask](http://docs.oracle.com/javase/8/docs/api/java/util/concurrent/FutureTask.html) 中。 22 | 23 | 当你不能使用 BungeeCord 线程调度器来运行异步任务的情况下,你有以下两个选择: 24 | 25 | 1. 如果(外部)API 有能力提供一个 Executor 或 ExecutorService,那么提供它在你的 26 | Plugin.getExecutorService()。 27 | 28 | 2. 在异步任务中创建对象。 29 | 30 | ## 阻塞 I/O 线程 31 | 32 | 在 BungeeCord 中,绝大多数事件和指令都运行在网络I/O线程(network I/O threads)。由于 BungeeCord 的特性(在所有线程有着高复用率),执行阻塞操作(例如I/O操作,获取远端URL内容,查询数据库...)将会降低性能。 33 | 34 | 通常来说: 35 | 1. **总是异步运行可导致阻塞的任务。** 如果你不知道什么操作可导致阻塞,绝大多数情况下访问外部资源(例如硬盘,或者数据库)是可导致阻塞的。 36 | 37 | 2. **不要延迟事件或命令处理使其超过所需时间。** 如果你需要延迟处理一个事件并且它继承 [AsyncEvent](http://ci.md-5.net/job/BungeeCord/ws/api/target/apidocs/net/md_5/bungee/api/event/AsyncEvent.html),使用它的 registerIntent()(在事件处理器中开始处理异步事件)和 completeIntent()(结束任务,该方法应在异步任务中调用)`(译者注:该方法通知事件处理器当前异步任务完成,继续处理该事件)`方法。**你应该异步运行可导致阻塞的任务**,但是,这将允许事件被延迟处理,且当所有的异步操作完成时继续。 38 | 39 | ## 尝试混用 Bukkit 和 BungeeCord API 40 | BungeeCord 不包括 Bukkit API,即使包括 Bukkit API 也是没用的,它不能操作后端的 Bukkit 服务器。此外:Spigot 也不包括 BungeeCord API,即使包括也是没用的,它也不能操作你的 BungeeCord。 41 | 42 | 注意 BungeeCord 的聊天组件API(Chat Component API) 是包括在 Spigot 内的,然而这个API与 BungeeCord 是分离的。 -------------------------------------------------------------------------------- /docs/sending-players-between-servers-in-bungeecord.md: -------------------------------------------------------------------------------- 1 | --- 2 | article: false 3 | --- 4 | # BungeeCord 在服务器之间传送玩家 5 | 建议您阅读如何创建基本指令的教程,如果您还没有阅读它的话。 6 | 7 | 本篇教程中我们将创建一个简单的指令来使玩家连接 8 | 到其他服务器。在教程中我们使用 Hub 作为我们将要连接的服务器。 9 | 10 | ## 创建指令 11 | 12 | 首先,创建一个指令并在主类注册它: 13 | ```java 14 | public class CommandHub extends Command{ 15 | public CommandHub(){ 16 | super("hub","permission.hub",new String[0]); 17 | } 18 | public void execute(CommandSender sender, String[] args){ 19 | 20 | } 21 | } 22 | ``` 23 | 24 | 如果你不需要有一个指令,就不必有权限。 25 | 26 | 你需要在你的 BungeeCord 配置文件给予你 permission.hub 权限才能执行这个指令。 27 | ```java 28 | public void onEnable(){ 29 | getProxy().getPluginManager().registerCommand(this, new CommandHub()); 30 | } 31 | ``` 32 | ## 检查是否是一个玩家 33 | 34 | 我们不想在 CommandSender 转换为 ProxiedPlayer 时收到错误,因此我们需要检查指令是否是由玩家发出: 35 | 36 | ```java 37 | public void execute(CommandSender sender, String[] args){ 38 | if(sender instanceof ProxiedPlayer){ 39 | ProxiedPlayer player = (ProxiedPlayer) sender; 40 | }else{ 41 | sender.sendMessage(new ComponentBuilder("This command can only be run by a player!").color(ChatColor.RED).create()); 42 | } 43 | } 44 | ``` 45 | ## 检查玩家是否已经连接 46 | 47 | 在 'if' 语句中,我们需要检查玩家是否已经连接到服务器,否则命令将无法运行。 48 | 49 | ```java 50 | if(!player.getServer().getInfo().getName().equalsIgnoreCase("hub")){ 51 | }else{ 52 | player.sendMessage(new ComponentBuilder("You are already connected to the Hub!").color(ChatColor.RED).create()); 53 | } 54 | ``` 55 | 56 | ## 传送玩家 57 | 58 | 我们需要声明一个 ServerInfo 类型的变量来选择目标服务器,然后使用变量来改变玩家所在的服务器 59 | (放在if语句内): 60 | 61 | ```java 62 | ServerInfo target = ProxyServer.getInstance().getServerInfo("Hub"); 63 | player.connect(target); 64 | ``` -------------------------------------------------------------------------------- /docs/event-api.md: -------------------------------------------------------------------------------- 1 | --- 2 | article: false 3 | --- 4 | # BungeeCord 事件 API 5 | 6 | BungeeCord 有着丰富的事件(Event) API,类似于Bukkit的事件系统,但有些不同。本篇教程将介绍如何创建一个监听器(Listener)和新的事件(Event)。 7 | 8 | ## 创建你的监听器 9 | 10 | 要使用 BungeeCord 的事件系统,需要在你的项目中创建一个新的类。你可以为这个类取任何你喜欢的名字,但在本教程中我们暂且取名为"Events.java"。 11 | 12 | 如果你创建了一个你希望作为监听器的类,你就必须实现 BungeeCord 中的 Listener 类。代码看起来应该是这样的: 13 | ```java 14 | public class Events implements Listener 15 | ``` 16 | 17 | 如果你在你的类中实现了 Listener,你就可以在启动监听所有的 BungeeCord 事件([点击查看所有事件列表](https://ci.md-5.net/job/BungeeCord/ws/api/target/apidocs/net/md_5/bungee/api/event/package-summary.html))。 18 | 19 | 举个例子,我们使用 BungeeCord 的 PostLoginEvent(登录后事件)。让我们来添加我们的第一个监听器吧: 20 | ```java 21 | public class Events implements Listener { 22 | 23 | @EventHandler 24 | public void onPostLogin(PostLoginEvent event) { 25 | } 26 | 27 | } 28 | ``` 29 | PostLoginEvent(登录后事件)发生在每一次玩家(ProxiedPlayer)成功地通过身份验证并即将连接到一个服务器时。在我们的监听器中,我们可以发送一条信息告诉当前在线的所有玩家,有一个玩家加入了Bungee群组,例如: 30 | ```java 31 | public class Events implements Listener { 32 | 33 | @EventHandler 34 | public void onPostLogin(PostLoginEvent event) { 35 | for (ProxiedPlayer player : ProxyServer.getInstance().getPlayers()) { 36 | player.sendMessage(new TextComponent(event.getPlayer().getName() + " has joined the network.")); 37 | } 38 | } 39 | 40 | } 41 | ``` 42 | 当你完成了你的监听器类,你必须在你的插件主类注册该监听器。举个例子: 43 | ```java 44 | public class Main extends Plugin { 45 | @Override 46 | public void onEnable() { 47 | getProxy().getPluginManager().registerListener(this, new Events());//注册监听器 48 | } 49 | } 50 | ``` 51 | 确保使用完整的事件列表,以便你可以和插件进行适当的交互。 52 | 53 | ## 创建你的事件 54 | 55 | 要创建一个自定义的 BungeeCord 事件,需要创建一个类。我们可以命名为 MyAwesomeEvent,但是你可以给它取任何名字,这个类应该继承 Event。接下来添加一些属性来方便你的监听器使用。作为例子,我们将创建这个类: 56 | 57 | ```java 58 | public class MyAwesomeEvent extends Event { 59 | private final String message; 60 | 61 | public MyAwesomeEvent(String message) { 62 | this.message = message; 63 | } 64 | 65 | public String getMessage() { 66 | return message; 67 | } 68 | } 69 | ``` 70 | 接下来发出事件,这很简单: 71 | 72 | ```java 73 | getProxy().getPluginManager().callEvent(new MyAwesomeEvent("I'm awesome!")); 74 | ``` 75 | 你现在可以使用上一节中的监听器监听 MyAwesomeEvent 了。 -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | lerna-debug.log* 8 | .pnpm-debug.log* 9 | 10 | # Diagnostic reports (https://nodejs.org/api/report.html) 11 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json 12 | 13 | # Runtime data 14 | pids 15 | *.pid 16 | *.seed 17 | *.pid.lock 18 | 19 | # Directory for instrumented libs generated by jscoverage/JSCover 20 | lib-cov 21 | 22 | # Coverage directory used by tools like istanbul 23 | coverage 24 | *.lcov 25 | 26 | # nyc test coverage 27 | .nyc_output 28 | 29 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) 30 | .grunt 31 | 32 | # Bower dependency directory (https://bower.io/) 33 | bower_components 34 | 35 | # node-waf configuration 36 | .lock-wscript 37 | 38 | # Compiled binary addons (https://nodejs.org/api/addons.html) 39 | build/Release 40 | 41 | # Dependency directories 42 | node_modules/ 43 | jspm_packages/ 44 | 45 | # Snowpack dependency directory (https://snowpack.dev/) 46 | web_modules/ 47 | 48 | # TypeScript cache 49 | *.tsbuildinfo 50 | 51 | # Optional npm cache directory 52 | .npm 53 | 54 | # Optional eslint cache 55 | .eslintcache 56 | 57 | # Microbundle cache 58 | .rpt2_cache/ 59 | .rts2_cache_cjs/ 60 | .rts2_cache_es/ 61 | .rts2_cache_umd/ 62 | 63 | # Optional REPL history 64 | .node_repl_history 65 | 66 | # Output of 'npm pack' 67 | *.tgz 68 | 69 | # Yarn Integrity file 70 | .yarn-integrity 71 | 72 | # dotenv environment variables file 73 | .env 74 | .env.test 75 | .env.production 76 | 77 | # parcel-bundler cache (https://parceljs.org/) 78 | .cache 79 | .parcel-cache 80 | 81 | # Next.js build output 82 | .next 83 | out 84 | 85 | # Nuxt.js build / generate output 86 | .nuxt 87 | dist 88 | 89 | # Gatsby files 90 | .cache/ 91 | # Comment in the public line in if your project uses Gatsby and not Next.js 92 | # https://nextjs.org/blog/next-9-1#public-directory-support 93 | # public 94 | 95 | # vuepress build output 96 | .vuepress/dist 97 | 98 | # Serverless directories 99 | .serverless/ 100 | 101 | # FuseBox cache 102 | .fusebox/ 103 | 104 | # DynamoDB Local files 105 | .dynamodb/ 106 | 107 | # TernJS port file 108 | .tern-port 109 | 110 | # Stores VSCode versions used for testing VSCode extensions 111 | .vscode-test 112 | 113 | # yarn v2 114 | .yarn/cache 115 | .yarn/unplugged 116 | .yarn/build-state.yml 117 | .yarn/install-state.gz 118 | .pnp.* -------------------------------------------------------------------------------- /docs/the-chat-component-api.md: -------------------------------------------------------------------------------- 1 | --- 2 | article: false 3 | --- 4 | # 聊天组件 API 5 | 使用 BungeeCord 聊天 API 构建消息。 6 | 7 | [Chat API Javadoc](https://ci.md-5.net/job/BungeeCord/ws/chat/target/apidocs/overview-summary.html) 8 | 9 | ## 基础 10 | 最简单的组件是 TextComponent(文本组件),在 BungeeCord 的使用方法如下: 11 | ```java 12 | player.sendMessage( new TextComponent( "Hello world" ) ); 13 | ``` 14 | 或者你想在 Spigot 中使用: 15 | ```java 16 | player.spigot().sendMessage( new TextComponent( "Hello world" ) ); 17 | ``` 18 | 这是一个简单的消息,没有格式和颜色。 19 | 20 | ## 颜色与格式 21 | 每个组件都支持如下功能: 22 | - 颜色(Color) 23 | - 粗体(Bold) 24 | - 斜体(Italic) 25 | - 下划线(Underline) 26 | - 删除线(Strikethrough) 27 | - 乱码(Obfuscate) 28 | - 事件(Events)(在下文中会详细介绍) 29 | 30 | 举个例子: 31 | ```java 32 | TextComponent message = new TextComponent( "Hello world" ); 33 | message.setColor( ChatColor.RED ); 34 | message.setBold( true ); 35 | player.sendMessage( message ); 36 | ``` 37 | 这将显示 "Hello World"(红色,加粗). 任何格式和事件也应用于子组件,除非子组件覆盖设置。例如: 38 | ```java 39 | TextComponent message = new TextComponent( "Hello " ); 40 | message.setColor( ChatColor.RED ); 41 | message.setBold( true ); 42 | TextComponent world = new TextComponent( "world" ); 43 | world.setColor( ChatColor.BLUE ); 44 | message.addExtra( world ); 45 | message.addExtra( "!" ); 46 | player.sendMessage( message ); 47 | ``` 48 | 将会显示 "Hello world!"(全文为粗体,"Hello"和"!"为红色,"world"为蓝色) 49 | 50 | ## 事件 51 | 事件允许当文本被操作(点击或鼠标悬浮)时执行动作。目前 Minecraft 仅支持两个事件,分别是 HoverEvent(鼠标悬浮事件)和 ClickEvent(点击事件)。两个事件都有一个动作(当事件发生之后执行什么)和一个数值(这个动作的参数)。例如,如果一个点击事件的动作是 OPEN_URL(打开URL),那么它的值必须是一个有效的URL,例如"http://spigotmc.org"。 52 | ```java 53 | TextComponent message = new TextComponent( "Click me" ); 54 | message.setClickEvent( new ClickEvent( ClickEvent.Action.OPEN_URL, "http://spigotmc.org" ) ); 55 | message.setHoverEvent( new HoverEvent( HoverEvent.Action.SHOW_TEXT, new ComponentBuilder("Goto the Spigot website!").create() ) ); 56 | player.spigot().sendMessage( message ); 57 | ``` 58 | 59 | ## 客户端翻译 60 | TranslatableComponent(可翻译组件)可以用来发送翻译键(key)让客户端翻译,这意味着你只能使用 Minecraft 提供的文本([这里查看](https://github.com/SpigotMC/BungeeCord/blob/master/chat/src/main/resources/mojang-translations/en_US.properties)),除非使用一个资源包来添加更多文本。一些支持参数的翻译的参数可以是TranslatableComponent(或者只是 TextComponent)。 61 | ```java 62 | TranslatableComponent giveMessage = new TranslatableComponent( "commands.give.success" ); 63 | TranslatableComponent item = new TranslatableComponent( "item.swordDiamond.name" ); 64 | item.setColor( ChatColor.GOLD ); 65 | giveMessage.addWith( item ); 66 | giveMessage.addWith( "32" ); 67 | TextComponent username = new TextComponent( "Thinkofdeath" ); 68 | username.setColor( ChatColor.AQUA ); 69 | giveMessage.addWith( username ); 70 | player.sendMessage( giveMessage ); 71 | ``` 72 | 以上的代码在客户端使用的语言为en_US(美式英语)时将会显示"Given Diamond Sword * 32 to Thinkofdeath", 但如果客户端使用的语言为zh_CN(简体中文)时将会显示"成功将 钻石剑 * 32 给予 Thinkofdeath"。 73 | 74 | ## 组件建造者(Component Builder) 75 | 简单的消息可以使用 ComponentBuilder(组件建造者)节省很多工作。ComponentBuilder 是一个链式结构的对象,允许快速创建消息。例如: 76 | ```java 77 | player.sendMessage( new ComponentBuilder( "Hello " ).color( ChatColor.RED ).bold( true ).append( "world" ).color( ChatColor.BLUE ).append( "!" ).color( ChatColor.RED ).create() ); 78 | ``` 79 | 这将显示 "Hello world!" 80 | 81 | ## 常见的问题 82 | 直接创建`BaseComponent`实例是没用的(例如 `player.sendMessage( new BaseComponent(){} );`),应使用`TextComponent`或`TranslatableComponent`。 83 | 使用旧版的颜色代码(例如 `player.sendMessage( new TextComponent( ChatColor.RED + ":-(" ) );`)将会不能很好的显示甚至导致客户端异常。使用`TextComponent.fromLegacyText()`方法将旧格式转换为新格式 84 | 85 | ## 动作 86 | 所有的 ClickEvent(点击事件) 和 HoverEvent(悬浮事件)的动作如下所示: 87 | 88 | ### 点击事件动作 89 | 当用户点击消息时,这些动作将会执行: 90 | ```java 91 | Action.OPEN_URL //在用户的浏览器打开指定URL 92 | 93 | Action.OPEN_FILE //在用户的电脑打开指定文件 94 | 95 | Action.RUN_COMMAND //让用户运行指令 96 | 97 | Action.SUGGEST_COMMAND //在用户的输入框设置文字 98 | 99 | Action.CHANGE_PAGE //改变书本的页码 100 | ``` 101 | ### 悬浮事件动作 102 | 当用户鼠标指针悬浮在消息上时,这些动作将会执行: 103 | ```java 104 | Action.SHOW_TEXT //显示一个文本 105 | 106 | Action.SHOW_ACHIEVEMENT //显示一个成就及其介绍 107 | 108 | Action.SHOW_ITEM //显示一个物品的名字和其他信息 109 | 110 | Action.SHOW_ENTITY //显示一个实体的名字,ID和其他信息 111 | ``` -------------------------------------------------------------------------------- /docs/create-your-first-bungeecord-plugin.md: -------------------------------------------------------------------------------- 1 | --- 2 | article: false 3 | --- 4 | # 创建你的第一个 BungeeCord 插件 5 | 恭喜你决定创建你的第一个 BungeeCord 插件!本篇教程将让你快速入门。 6 | 7 | 本教程需要具有 Java 知识才能阅读。 8 | 9 | ::: tip 10 | 如果你迫不及待,想快速开始开发,你可以使用此[工具](https://utilities.shall.fail/bungeecord/pluginhelper/)得到项目框架,按照以下步骤导入它 File -> Import Project in IntelliJ IDEA or File -> Import -> Maven -> Existing Maven Projects in Eclipse (反复点击下一步),并继续阅读Wiki上的其他教程。你还应该继续阅读本篇教程,特别是编译部分。 11 | ::: 12 | 13 | ## 设置你的项目 14 | 本教程仅涵盖 IntelliJ IDEA,但是其他的IDE应该也是相似的步骤。 15 | 16 | 首先打开你的IDE,创建一个新项目,然后选择Maven。你的界面应该类似于这样: 17 | ![新建项目](./create-your-first-bungeecord-plugin/1.png) 18 | 19 | ::: details Eclipse用户所需的操作 20 | 创建一个新项目: 21 | 22 | ![新建项目](./create-your-first-bungeecord-plugin/eclipse-new-1.png) 23 | 24 | 选择Maven: 25 | 26 | ![选择Maven](./create-your-first-bungeecord-plugin/eclipse-new-2.png) 27 | ::: 28 | 29 | 点击下一步(Next),然后你将会看到这个界面: 30 | ![新建Maven项目](./create-your-first-bungeecord-plugin/2.png) 31 | 32 | ::: details Eclipse用户所需的操作 33 | ![新建Maven项目](./create-your-first-bungeecord-plugin/eclipse-new-3.png) 34 | ::: 35 | 36 | 在 GroupId 中,输入你的 Java 包名 (例如 *me.username*)。在 ArtifactId 中, 输入你的插件名称(接下来我们使用 TestPlugin 作为例子)。暂时不用理会 Version,点击下一步(Next)。将你的项目名称更改为你的插件名称,然后点击 "完成(Finish)"。 37 | 38 | IDE 将会打开一个名为 *pom.xml* 的文件。现在我们要添加一些内容到其中。在 `` 之前添加以下内容: 39 | 40 | ::: details Eclipse用户所需的操作 41 | 你需要将下列代码中的``中的依赖项放入你的*pom.xml*文件中的``下。 42 | 43 | ![新建项目](./create-your-first-bungeecord-plugin/eclipse-new-4.png) 44 | 45 | 你不需要知道为什么要这样做,但需要你在Eclipse中编辑它。 46 | ::: 47 | 48 | ```xml 49 | 50 | 51 | bungeecord-repo 52 | https://oss.sonatype.org/content/repositories/snapshots 53 | 54 | 55 | 56 | 57 | 58 | 59 | org.apache.maven.plugins 60 | maven-compiler-plugin 61 | 3.5.1 62 | 63 | 1.7 64 | 1.7 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | net.md-5 73 | bungeecord-api 74 | 1.10-SNAPSHOT 75 | jar 76 | provided 77 | 78 | 79 | net.md-5 80 | bungeecord-api 81 | 1.10-SNAPSHOT 82 | javadoc 83 | provided 84 | 85 | 86 | ``` 87 | 88 | 这将为你的项目添加 BungeeCord 依赖。如果你使用的是 IntelliJ,它将会询问你是否要导入 *pom.xml* 文件的更改。导入它们。如果它询问语言版本被改变,允许它重载项目。 89 | 90 | ## 创建你的主类 91 | 接下来,展开 *TestPlugin*,然后展开 *src*,再展开 *main*。现在看起来大概是这样: 92 | 93 | ![项目结构](./create-your-first-bungeecord-plugin/3.png) 94 | 95 | 右键 *java*,然后创建一个新的包。叫做 *me.username.testplugin*。接下来,右键刚刚创建的包,然后创建一个新的类,叫做 *TestPlugin*。现在 IDE 应该已经打开文件给你了。如果没有打开,那么现在打开它。 96 | 97 | 现在,我们可以制作一个基本的插件了。本篇教程的插件将不实现任何功能,除了在启动时显示一条消息。其他的教程将详细介绍所有功能,你可以制作另外的插件。 98 | 99 | 将 `extends Plugin` 添加在 *TestPlugin* 之后 *{* 之前。现在看起来应该像这样: 100 | 101 | ```java 102 | package me.username.testplugin; 103 | 104 | import net.md_5.bungee.api.plugin.Plugin; 105 | 106 | public class TestPlugin extends Plugin { 107 | @Override 108 | public void onEnable() { 109 | // You should not put an enable message in your plugin. 110 | // BungeeCord already does so 111 | getLogger().info("Yay! It loads!"); 112 | } 113 | } 114 | ``` 115 | ## 使插件载入 116 | 现在我们可以创建 *plugin.yml* 文件,使 BungeeCord 知道这是一个插件并告诉它如何载入本插件。右键 *resources*,然后创建一个叫做 *plugin.yml* 的文件。在文件中添加以下内容: 117 | 118 | ```yml 119 | name: TestPlugin 120 | main: me.username.testplugin.TestPlugin 121 | version: 1.0 122 | author: username 123 | ``` 124 | 如果 *plugin.yml* 已经由 Bukkit 载入了,你也可以创建一个 *bungee.yml* 文件。 125 | 126 | ## 编译 127 | 我们即将完成插件的制作了。现在是编译插件的时候了。展开右边的 Maven Projects 面板(如果你没有看到它,点击 *View* 然后点击 *Tool Buttons*), 展开你的项目,展开 *Lifecycle*,双击 *clean*,然后双击 *package*。Maven 将会马上编译你的项目。现在,打开你的项目文件夹,然后在 *target* 看到你的插件。把它安装在你的 BungeeCord 然后启动它。如果有一行显示类似于 `[INFO] Enabled plugin TestPlugin version 1.0 by username` 的信息,那么它就已经运行了,现在你已经创建了你的第一个 BungeeCord 插件!若要重新编译它,重复这些操作。 128 | 129 | ## 关于 Bukkit 开发者 130 | 如果你是 Bukkit 开发者,所有东西你似乎非常熟悉,这是因为 BungeeCord API 很大程度上受 Bukkit API 的影响。许多概念(EventHandler 和 Scheduler)保持不变,一些类和方法名称也是相同的。 -------------------------------------------------------------------------------- /docs/bukkit-bungee-plugin-messaging-channel.md: -------------------------------------------------------------------------------- 1 | --- 2 | article: false 3 | --- 4 | # BungeeCord 插件消息频道 5 | 6 | 本教程讲解 Bukkit 和 BungeeCord 的插件消息频道(Plugin Messaging Channel)的使用。该频道允许 BungeeCord 和其他服务器的插件通过连接该频道进行交流。 7 | 8 | ## 插件消息(Plugin message)是什么? 9 | 插件消息被实现后,服务端插件可以发送任何数据到客户端模组。在此之前,我们需要自行实现自定义的数据包,但问题是,Minecraft 客户端无法读取服务器自定义的数据包,而导致出现一些意义不明的错误,并与服务器断开连接。为了修复这个问题,Mojang 实现了 "自定义插件消息包(Custom Plugin Message Packets)" 10 | 11 | 一个插件消息数据包(Plugin Message Packet)的结构是这样的: 12 | 包含一个插件消息需要使用的频道(Channel)的名称(在 BungeeCord 里也叫标签(tag))。在[这里](http://wiki.vg/Protocol#Plugin_Message)了解更多信息 13 | 14 | ## BungeeCord 插件频道 15 | BungeeCord 暴露了一个叫 "BungeeCord" 的插件频道在后端/Bukkit 服务器。你需要使用 DataInputStream 和 DataOutputStream 类来处理你需要发送(接收)的字节数组(byte[])。为了方便起见,我们使用 Google 的 Guava 的 ByteArrayDataInput 和 ByteArrayDataOutput 类,因为这不会抛出 IOException 。 16 | 17 | 使用 BungeeCord 插件频道之前,你需要在 Bukkit 的 Messenger 注册它。通俗的说,你需要告诉 Bukkit "嘿,我想使用这个频道。"我们也需要告诉 Bukkit 当它收到来自频道 "BungeeCord" 的消息时调用的方法。这是一个简单的插件例子: 18 | 19 | ```java 20 | public class MyPlugin extends JavaPlugin implements PluginMessageListener { 21 | @Override 22 | public void onEnable() { 23 | this.getServer().getMessenger().registerOutgoingPluginChannel(this, "BungeeCord"); 24 | this.getServer().getMessenger().registerIncomingPluginChannel(this, "BungeeCord", this); 25 | } 26 | 27 | @Override 28 | public void onPluginMessageReceived(String channel, Player player, byte[] message) { 29 | if (!channel.equals("BungeeCord")) { 30 | return; 31 | } 32 | ByteArrayDataInput in = ByteStreams.newDataInput(message); 33 | String subchannel = in.readUTF(); 34 | if (subchannel.equals("SomeSubChannel")) { 35 | // 使用下文中的"返回(Response)"一节的代码进行读取 36 | // 数据处理 37 | } 38 | } 39 | } 40 | ``` 41 | 42 | 发送插件消息是非常简单的: 43 | ```java 44 | ByteArrayDataOutput out = ByteStreams.newDataOutput(); 45 | out.writeUTF("Subchannel"); 46 | out.writeUTF("Argument"); 47 | 48 | // 如果你不关心玩家是谁,可以使用下面的代码 49 | // Player player = Iterables.getFirst(Bukkit.getOnlinePlayers(), null); 50 | // 或者,你希望指定一个玩家接收消息 51 | Player player = Bukkit.getPlayerExact("Example"); 52 | 53 | player.sendPluginMessage(this, "BungeeCord", out.toByteArray()); 54 | ``` 55 | 注意,你不能直接在玩家加入事件(PlayerJoinEvent)发送插件消息。你必须有一点延迟。 56 | 57 | ## BungeeCord 频道约定 58 | ### 连接到服务器(Connect) 59 | 使一个玩家连接到指定服务器。 60 | 61 | #### 参数 (Arguments) 62 | - (String)你希望连接到的服务器名称,必须要在 BungeeCord 的配置文件(config.yml)内设置。 63 | 64 | #### 接收者(Receiver) 65 | 你希望传送的玩家 66 | 67 | #### 发送例子 68 | ```java 69 | out.writeUTF("Connect"); 70 | out.writeUTF("pvp"); 71 | ``` 72 | #### 返回(Response) 73 | 无 74 | 75 | ### 使玩家连接到服务器(ConnectOther) 76 | 使一个指定玩家连接到指定服务器。 77 | 78 | #### 参数 79 | 80 | - (String)你希望传送的玩家名称 81 | - (String)你希望连接到的服务器名称,必须要在 BungeeCord 的配置文件(config.yml)内设置。 82 | 83 | #### 接收者 84 | 任何玩家 85 | 86 | #### 发送例子 87 | ```java 88 | out.writeUTF("ConnectOther"); 89 | out.writeUTF("roblabla"); 90 | out.writeUTF("pvp"); 91 | ``` 92 | #### 返回 93 | 无 94 | 95 | ### 获取玩家IP(IP) 96 | 获取玩家的真实IP 97 | 98 | #### 参数 99 | 无 100 | 101 | #### 接收者 102 | 你希望获取IP的玩家 103 | 104 | #### 例子 105 | ```java 106 | out.writeUTF("IP"); 107 | ``` 108 | 109 | #### 返回 110 | ```java 111 | String ip = in.readUTF(); 112 | int port = in.readInt(); 113 | ``` 114 | 115 | ### 获取玩家数量(PlayerCount) 116 | 获取某个服务器或者所有服务器的玩家数量。 117 | 118 | #### 参数 119 | - (String) 你希望获取玩家数量的服务器名称,如果你希望获取所有服务器的玩家数量,使用 "ALL" 120 | 121 | #### 接收者 122 | 任何玩家 123 | 124 | #### 例子 125 | ```java 126 | out.writeUTF("PlayerCount"); 127 | out.writeUTF("pvp"); 128 | ``` 129 | 130 | #### 返回 131 | ```java 132 | String server = in.readUTF(); // 服务器的名称,如给定的参数所示 133 | int playercount = in.readInt(); 134 | ``` 135 | 136 | ### 获取玩家列表(PlayerList) 137 | 获取某个服务器或者所有服务器的玩家名称。 138 | 139 | #### 参数 140 | - (String) 你希望获取玩家名称的服务器名词,如果你希望获取全部服务器的玩家名称,使用 "ALL" 141 | 142 | #### 接收者 143 | 任何玩家 144 | 145 | #### 例子 146 | ```java 147 | out.writeUTF("PlayerList"); 148 | out.writeUTF("pvp"); 149 | ``` 150 | #### 返回 151 | ```java 152 | String server = in.readUTF(); // 你想要获取玩家列表的服务器的名称,如给定的参数所示 153 | String[] playerList = in.readUTF().split(", "); 154 | ``` 155 | 156 | ### 获取所有服务器名称(GetServers) 157 | 获取所有服务器的名称, 必须要在 BungeeCord 的配置文件(config.yml)内设置。 158 | 159 | #### 参数 160 | 无 161 | 162 | #### 接收者 163 | 任何玩家 164 | 165 | #### 例子 166 | ```java 167 | out.writeUTF("GetServers"); 168 | ``` 169 | 170 | #### 返回 171 | ```java 172 | String[] serverList = in.readUTF().split(", "); 173 | ``` 174 | 175 | ### 发送消息(Message) 176 | 向指定玩家发送一个消息(比如聊天消息)。 177 | 178 | #### 参数 179 | - (String)需要发送消息的玩家名称 180 | - (String)需要发送的消息内容 181 | 182 | #### 接收者 183 | 任何玩家 184 | 185 | #### 例子 186 | ```java 187 | out.writeUTF("Message"); 188 | out.writeUTF("roblabla"); 189 | out.writeUTF(ChatColor.RED + "Congrats, you just won 1$!"); 190 | ``` 191 | #### 返回 192 | 无 193 | 194 | ### 获取服务器名称(GetServer) 195 | 获得当前服务器名称,必须在 BungeeCord 的配置文件(config.yml)内设置。 196 | 197 | #### 参数 198 | 无 199 | 200 | #### 接收者 201 | 任何玩家 202 | 203 | #### 例子 204 | ```java 205 | out.writeUTF("GetServer"); 206 | ``` 207 | 208 | #### 返回 209 | ```java 210 | String servername = in.readUTF(); 211 | ``` 212 | 213 | ### 发送自定义插件消息(Forward) 214 | 发送一个自定义插件消息到指定服务器。这是最有效的方式之一。 215 | 216 | **记住,发送和接受服务器都需要有一个玩家在线。** 217 | 218 | #### 参数 219 | - (String)接受插件消息的服务器名, "ALL" 表示发送到所有服务器(除了发送插件消息的服务器), "ONLINE" 表示发送到每一个在线的服务器(除了发送插件消息的服务器) 220 | - (String)插件使用的子频道(Subchannel)名称 221 | - (Short)插件消息的数组长度 222 | - (Byte[])需要发送的插件消息 223 | 224 | #### 接收者 225 | 任何玩家 226 | 227 | #### 例子 228 | ```java 229 | out.writeUTF("Forward"); // 这样写BungeeCord就知道要转发它 230 | out.writeUTF("ALL"); 231 | out.writeUTF("MyChannel"); // 用于检查这是否是你的数据的频道名称 232 | 233 | ByteArrayOutputStream msgbytes = new ByteArrayOutputStream(); 234 | DataOutputStream msgout = new DataOutputStream(msgbytes); 235 | msgout.writeUTF("Some kind of data here"); // 你可以用msgout发送任何你想发送的数据 236 | msgout.writeShort(123); 237 | 238 | out.writeShort(msgbytes.toByteArray().length); 239 | out.write(msgbytes.toByteArray()); 240 | ``` 241 | 242 | #### 返回 243 | ```java 244 | String subChannel = in.readUTF(); 245 | short len = in.readShort(); 246 | byte[] msgbytes = new byte[len]; 247 | in.readFully(msgbytes); 248 | 249 | DataInputStream msgin = new DataInputStream(new ByteArrayInputStream(msgbytes)); 250 | String somedata = msgin.readUTF(); // 以与写入数据相同的顺序读取数据 251 | short somenumber = msgin.readShort(); 252 | ``` 253 | 254 | ### 发送自定义插件消息到玩家(ForwardToPlayer) 255 | 发送自定义插件消息到指定玩家。 256 | 257 | #### 参数 258 | - (String)接受消息的玩家名称 259 | - (String)插件使用的子频道(Subchannel)名称 260 | - (Short)插件消息的数组长度 261 | - (Byte[])需要发送的插件消息 262 | 263 | #### 接收者 264 | 任何玩家 265 | 266 | #### 例子 267 | ```java 268 | out.writeUTF("ForwardToPlayer"); 269 | out.writeUTF("md_5"); 270 | out.writeUTF("MyChannel"); 271 | 272 | ByteArrayOutputStream msgbytes = new ByteArrayOutputStream(); 273 | DataOutputStream msgout = new DataOutputStream(msgbytes); 274 | msgout.writeUTF("Some kind of data here"); 275 | msgout.writeShort(123); 276 | 277 | out.writeShort(msgbytes.toByteArray().length); 278 | out.write(msgbytes.toByteArray()); 279 | ``` 280 | 281 | #### 返回 282 | ```java 283 | String subChannel = in.readUTF(); 284 | short len = in.readShort(); 285 | byte[] msgbytes = new byte[len]; 286 | in.readFully(msgbytes); 287 | 288 | DataInputStream msgin = new DataInputStream(new ByteArrayInputStream(msgbytes)); 289 | String somedata = msgin.readUTF(); // 以与写入数据相同的顺序读取数据 290 | short somenumber = msgin.readShort(); 291 | ``` 292 | 293 | ### 获取玩家的UUID(UUID) 294 | 获取该玩家的UUID。 295 | 296 | #### 参数 297 | 无 298 | 299 | #### 接收者 300 | 需要获取UUID的玩家 301 | 302 | #### 例子 303 | ```java 304 | out.writeUTF("UUID"); 305 | ``` 306 | 307 | #### 返回 308 | ```java 309 | String uuid = in.readUTF(); 310 | ``` 311 | 312 | ### 获取指定玩家的UUID(UUIDOther) 313 | 获取指定玩家的UUID。 314 | 315 | #### 参数 316 | - (String)你需要获取UUID的玩家的名称 317 | 318 | #### 接收者 319 | 发送者(译注:原文如此,可能是任何玩家) 320 | 321 | #### 例子 322 | ```java 323 | out.writeUTF("UUIDOther"); 324 | out.writeUTF("Notch"); 325 | ``` 326 | 327 | #### 返回 328 | ```java 329 | String playerName = in.readUTF(); 330 | String uuid = in.readUTF(); 331 | ``` 332 | 333 | ### 获取服务器IP(ServerIP) 334 | 获取指定服务器在群组中的IP。 335 | 336 | #### 参数 337 | - (String) 需要获取IP的服务器名称 338 | 339 | #### 接收者 340 | 任何玩家 341 | 342 | #### 例子 343 | ```java 344 | out.writeUTF("ServerIP"); 345 | out.writeUTF("lobby"); 346 | ``` 347 | 348 | #### 返回 349 | ```java 350 | String serverName = in.readUTF(); 351 | String ip = in.readUTF(); 352 | int port = in.readUnsignedShort(); 353 | ``` 354 | 355 | ### 踢出玩家(KickPlayer) 356 | 从整个服务器踢出玩家。 357 | 358 | #### 参数 359 | - (String)玩家名 360 | - (String)踢出玩家的理由 361 | 362 | #### 接收者 363 | 任何玩家 364 | 365 | #### 例子 366 | ```java 367 | out.writeUTF("KickPlayer"); 368 | out.writeUTF("Notch"); 369 | out.writeUTF("You were kicked from the server"); 370 | ``` 371 | 372 | #### 返回 373 | 无 --------------------------------------------------------------------------------