在 第 1 部分、第 2 部分 和 第 3 部分 中,您看到了如何在 Docker 容器内启动您自己的 Minecraft 服务器,首先在本地启动,然后在 Bluemix 上的 IBM Container 服务内启动。您还学习了如何为 Minecraft 构建服务器端插件,以及将这些插件添加到在 Docker 中运行的 Minecraft 服务器。
所有这些都是学习本教程(本系列的最后一篇)的前奏,本教程展示如何在您的插件开发中利用 IBM Bluemix 环境的强大功能,并在此期间向 Minecraft 中的游戏体验添加一定的科学性。在本文中,您将了解如何使用一个使用 Watson 认知服务的插件扩展 Spigot 服务器。
第 1 部分:设置您的本地 Minecraft 和 Docker 开发环境,开始在您自己的服务器上使用 Minecraft。
第 2 部分:设置您的本地 Eclipse 开发环境,然后开发、构建您自己的服务器端 Minecraft 插件并导出到一个本地 Docker 映像中。
第 3 部分:将 Docker 映像部署到 Bluemix,然后将它们作为可通过云访问的 Docker 容器来运行。
第 4 部分
使用一个插件扩展 Spigot 服务器,该插件使用 Bluemix 上的 Watson 认知服务为您的游戏体验增添一定的科学性。
IBM 在 Bluemix 上提供了多个 Watson 服务,您可使用它们来构建认知解决方案。这些服务包括 Watson Question and Answer 服务、Personality Insights、Watson Natural Language Classifier、Tradeoff Analytics 和其他一些服务。浏览 Watson 服务 的完整列表。
在本教程中,您将看到如何构建一个使用 Watson Q&A 服务回答疾病问题的插件 — 以及如何将该插件与另一个第三方 Minecraft 插件相组合,向 Minecraft 村民添加传染病。将这二者相结合时,您就有理由在该游戏中学习如何诊断和治疗疾病。这种概念证明集成展示了如何将第三方插件与您自己的插件相组合来利用 Watson 和 Bluemix 的强大功能。
让我们开始吧。首先,我们需要获取 Watson Q&A 服务的一个实例,并从该服务实例获取一些凭据,以便在我们的新插件中使用它们。然后我们将构建该插件,将它安装到 Docker 中并推送到 IBM Container 服务中。
要获取相关的凭据来访问当前 Bluemix 版本中的 Watson Q&A 实例,我们需要执行一个迂回流程。如果您使用一个 Cloud Foundry 运行时编写一个应用程序,可创建一个服务,然后将该服务绑定到您的运行时,以便获取该服务的凭据,凭据信息会通过一组环境变量自动传输到您的运行时。但是,同样的绑定流程还无法对 Docker 容器无缝地执行,所以我们需要引入一个 “虚拟” 应用程序,我们将它绑定到 Watson Q&A 服务来获取正确的凭据。为此,执行此过程:
"url": "https://gateway.watsonplatform.net/question-and-answer-beta/api", "username": "some-long-hyphenated-set-of-characters", "password": "AVeryL0ngSer1esOfCharact3rs"
拥有正确的凭据后,我们就可以构建自己的 Spigot 插件。
备注:本教程系列中引用的所有代码都可在 GitHub 上您在 第 1 部分 中克隆的相同项目中找到。如果您还未克隆(假设您直接跳到了本教程),那么可从 GitHub 克隆以下项目:
git clone https://github.com/kgb1001001/minecraft-project.git
minecraft-project/spigot-plugin-watson/ 目录包含一个 spigot-plugin-watson.zip,这是一个 Eclipse 项目归档文件,包含本教程剩余部分所引用的代码。
在您的 Ubuntu 环境中(您已在第 1、2 和 3 部分中使用):
cd $HOME/refLibs
mkdir minecraft
wget "https://hub.spigotmc.org/jenkins/job/BuildTools/lastSuccessfulBuild/artifact/target/BuildTools.jar" -O minecraft/BuildTools.jar
git config --global core.autocrlf input
java -jar minecraft/BuildTools.jar
完成这些步骤后,您的目录中应有一个 craftbukkit-1.8.8.jar。
./eclipse/eclipse
选择一个工作区目录。(Eclipse 将它的文件写入该目录中。)
备注:如果 Eclipse 启动时没有显示 File 菜单,可结束 Eclipse 并使用下面这个命令重新启动它:UBUNTU_MENUPROXY=0 ./eclipse/eclipse
指定 WatsonSpigotPlugin 作为名称。
单击 Next,在 Libraries 下,单击 Add External Jars...。
导航到 $HOME/refLibs 并选择 craftbukkit-1.8.8.jar。
单击 OK,然后在下一个屏幕上单击 Finish。将使用名称 WatsonSpigotPlugin 在您的 Eclipse 工作区中创建一个新项目。
在您的 WatsonSpigotPlugin 项目下创建一个新文件夹并将它命名为 lib。
将以下 jar 从您的 $HOME/refLibs 目录复制到您刚创建的 lib 目录中:
将这些 jar 添加到您项目的构建路径:在 Eclipse 中选择它们,右键单击,然后选择 Build Path > Add to Build Path。
// Begin WatsonQA.java 1) package com.ibm.minecraft.spigotplugin; 2) 3) import org.bukkit.command.Command; 4) import org.bukkit.command.CommandSender; 5) import org.bukkit.plugin.java.JavaPlugin; 6) 7) public class WatsonQA extends JavaPlugin { 8) // Fired when plugin is first enabled 9) @Override 10) public void onEnable() { 11) getLogger().info("WatsonSpigotPlugin"); 12) } 13) // Fired when plugin is disabled 14) @Override 15) public void onDisable() { 16) 17) } 18) 19) public boolean onCommand(CommandSender sender, Command cmd, String label, 20) String[] args) { 21) getLogger().info("command: " + cmd.getName()); 22) //getServer().dispatchCommand(getServer().getConsoleSender(), cmd.getName()); 23) if (cmd.getName().equalsIgnoreCase("hello")) { 24) sender.sendMessage("Hello Watson"); 25) } 26) if (cmd.getName().equalsIgnoreCase("watson")) { 27) if (args.length == 0) { 28) sender.sendMessage("WATSON Rocks"); 29) return true; 30) } 31) 32) if (args.length >= 1) { 33) StringBuilder str = new StringBuilder(); 34) for(int i=0; i < args.length; i++) { 35) str.append(args[i]); 36) if(i < args.length-1) { 37) str.append(" "); 38) } 39) } 40) String question = str.toString(); 41) sender.sendMessage("asking Watson: " + question); 42) //String response = SpigotQAAPI.getQAAPIResponse(question); 43) //sender.sendMessage("Watson response: " + response); 44) 45) return true; 46) } 47) 48) } 49) 50) return false; 51) } 52) } // End WatsonQA.java
WatsonQA.java 中的示例代码类似于您在开始为 Spigot 服务器开发插件时所找到的示例代码。
// Begin SpigotQAAPI.java package com.ibm.minecraft.spigotplugin; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.OutputStream; import java.net.HttpURLConnection; import java.net.URL; import java.util.logging.Level; import java.util.logging.Logger; import org.apache.commons.codec.binary.Base64; import org.codehaus.jackson.JsonNode; import org.codehaus.jackson.map.ObjectMapper; public class SpigotQAAPI { private static final Logger logger = Logger.getLogger(SpigotQAAPI.class.getName()); /* Insert the credentials for the Watson Question and Answer service credentials": { "url": "https://gateway.watsonplatform.net/question-and-answer-beta/api", "username": qa_username, "password": qa_password } */ static String QAAPI_URL = "https://gateway.watsonplatform.net/question-and-answer-beta/api/v1/question/healthcare"; static String QA_USERNAME = qa_username; static String QA_PASSWORD = qa_password; static String BASIC_AUTH = "Basic " + new String(Base64.encodeBase64((QA_USERNAME+":"+QA_PASSWORD).getBytes())); /* * Create HTTP connection */ static public HttpURLConnection createConnection(String address, String method) throws IOException { URL url = new URL(address); HttpURLConnection connection = (HttpURLConnection)url.openConnection(); if (method == "PUT" || method == "POST") { connection.setDoOutput(true); } connection.setRequestMethod(method); connection.setRequestProperty("Authorization", BASIC_AUTH); connection.setRequestProperty("Accept", "application/json"); connection.setRequestProperty("Content-Type", "application/json"); return connection; } /* * Accepts as input a string of the question text, calls Watson * QAAPI and returns the answer back as a String. */ public static String getQAAPIResponse(String questionText) { ObjectMapper mapper = new ObjectMapper(); JsonNode resp=null; String ans=null; System.out.println("QAAPI url: " + QAAPI_URL); HttpURLConnection connection; try { connection = createConnection(QAAPI_URL,"POST"); connection.setRequestProperty("X-SyncTimeout", "30"); questionText = questionText.replaceAll("/"", ""); questionText = "/"" + questionText + "/""; String s = "{ /"question/" : { /"questionText/" : " + questionText + "}}"; JsonNode nd = mapper.readValue(s, JsonNode.class); connection.setInstanceFollowRedirects(false); OutputStream wr = connection.getOutputStream(); wr.write(nd.toString().getBytes()); wr.flush(); wr.close(); if (connection.getResponseCode() != HttpURLConnection.HTTP_CREATED && connection.getResponseCode() != HttpURLConnection.HTTP_OK && connection.getResponseCode() != HttpURLConnection.HTTP_MOVED_TEMP) { throw new RuntimeException("Failed : HTTP error code : " + connection.getResponseCode()); } BufferedReader br = new BufferedReader(new InputStreamReader( (connection.getInputStream()))); String output=null; while ((output = br.readLine()) != null) { resp = mapper.readValue(output, JsonNode.class); if(resp == null) { logger.log(Level.WARNING,"system response is null"); } else { ans = resp.get(0).get("question").get("evidencelist").get(0).get("text").toString(); } } connection.disconnect(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } return ans; } } // End SpigotQAAPI.java
请注意,代码中使用的实际 Watson QA URL 为:
https://gateway.watsonplatform.net/question-and-answer-beta/api/v1/question/healthcare
但是凭据返回的 URL 为
https://gateway.watsonplatform.net/question-and-answer-beta/
Bluemix 中的 Watson Q&A 服务的 REST API 文档解释道,为旅游启用了一个语料库,为医疗启用了另一个语料库,所以要向医疗语料库询问问题,需要使用 /api/v1/question/healthcare 扩展该 URL。
另外,一定要将 qa_username
和 qa_password
替换为您在 本教程前面 创建一个 Watson QA 服务实例时获得的凭据:
static String QA_USERNAME = qa_username; static String QA_PASSWORD = qa_password;
42) String response = SpigotQAAPI.getQAAPIResponse(question); 43) sender.sendMessage("Watson response: " + response);
name: WatsonSpigotPlugin main: com.ibm.minecraft.spigotplugin.WatsonQA version: 1.0 commands: hello: description: A new command watson: description: watson initial command
Manifest-Version: 1.0 Main-Class: com.ibm.minecraft.spigotplugin.WatsonQA Class-Path: lib/jackson-core-asl-1.9.13.jar lib/commons-codec-1.10.jar lib/jackson-mapper-asl-1.9.13.jar
mkdir $HOME/watsonspigotdir
# Version 0.0.3 # This version builds a spigot server # using the recommended build strategy for spigot # This is advantageous in that it's better for plugin development # and fits well with the Docker approach # it also adds a first Minecraft plugin into the bare spigot server # FROM ubuntu:14.04 MAINTAINER Kyle Brown “brownkyl@us.ibm.com” RUN apt-get update RUN apt-get install -y git RUN apt-get install -y default-jdk RUN apt-get install -y wget RUN mkdir minecraft RUN wget "https://hub.spigotmc.org//jenkins/job/BuildTools/lastSuccessfulBuild/artifact/target/BuildTools.jar" -O minecraft/BuildTools.jar RUN git config --global core.autocrlf input RUN java -jar minecraft/BuildTools.jar RUN echo "eula=true" > eula.txt RUN mkdir plugins ADD watsonqa.jar /plugins/watsonqa.jar # Install unzip RUN apt-get install -y unzip RUN unzip -uo /plugins/watsonqa.jar -d /plugins/ CMD java -XX:MaxPermSize=128M -Xms512m -Xmx1024m -jar spigot-1.8.8.jar nogui EXPOSE 25565
前面的代码清单中以粗体突出显示的行是与您在以前的代码中看到的其他 Docker 文件的主要区别。实际上,这些行在 $HOME/watsonspigot 下创建一个名为 plugins 的新目录,将 watsonqa.jar 复制到 plugins 目录,将该 jar 解压到 plugins 目录,然后运行 Spigot 服务器。需要这样才能确保该插件可访问所有需要的依赖项 jar,前面已经介绍过,这些 jar 已复制到 Eclipse 项目的 lib 目录下并已在 MANIFEST.MF 文件中引用。
docker build -t="parallels/watsonspigotplugin" .
docker run -i -t -p=25565:25565 parallels/watsonspigotplugin
如果您看到以下行,则表明您具有 Watson 插件的 Spigot 服务器已成功启动:
[00:04:07 INFO]: [WatsonSpigotPlugin] Enabling WatsonSpigotPlugin v1.0 [00:04:07 INFO]: [WatsonSpigotPlugin] WatsonSpigotPlugin [00:04:07 INFO]: Done (12.659s)! For help, type "help" or "?"
目前为止,我们已使用 Watson 插件在 Docker 容器本地验证了 Spigot 服务器的功能。接下来,让我们将此服务器托管在 Bluemix 上。
mkdir $HOME/watsonspigotbluemix
cp $HOME/watsonspigot/watsonqa.jar $HOME/watsonspigotbluemix/
#Minecraft server properties #(File modification datestamp) spawn-protection=16 max-tick-time=60000 generator-settings= force-gamemode=false allow-nether=true gamemode=0 enable-query=false player-idle-timeout=0 difficulty=1 spawn-monsters=true op-permission-level=4 resource-pack-hash= announce-player-achievements=true pvp=true snooper-enabled=true level-type=DEFAULT hardcore=false enable-command-block=false max-players=20 network-compression-threshold=256 max-world-size=29999984 server-port=9085 server-ip= spawn-npcs=true allow-flight=false level-name=world view-distance=10 resource-pack= spawn-animals=true white-list=false generate-structures=true online-mode=false max-build-height=256 level-seed= use-native-transport=true motd=A Minecraft Server enable-rcon=false
# Version 0.0.3 # This version builds a spigot server # using the recommended build strategy for spigot # This is advantageous in that it's better for plugin development # and fits well with the Docker approach # it also adds a first Minecraft plugin into the bare spigot server # FROM ubuntu:14.04 MAINTAINER Kyle Brown “brownkyl@us.ibm.com” RUN apt-get update RUN apt-get install -y git RUN apt-get install -y openjdk-7-jre-headless RUN apt-get install -y wget RUN mkdir minecraft RUN wget "https://hub.spigotmc.org//jenkins/job/BuildTools/lastSuccessfulBuild/artifact/target/BuildTools.jar" -O minecraft/BuildTools.jar RUN git config --global core.autocrlf input RUN java -jar minecraft/BuildTools.jar RUN echo "eula=true" > eula.txt ADD server.properties ./server.properties RUN mkdir plugins ADD watsonqa.jar /plugins/watsonqa.jar RUN apt-get install -y unzip RUN unzip -uo /plugins/watsonqa.jar -d /plugins/ CMD java -XX:MaxPermSize=128M -Xms512m -Xmx1024m -jar spigot-1.8.8.jar nogui EXPOSE 9085
与我们之前为本地运行 Spigot 服务器而创建的 Dockerfile 的唯一区别是,我们添加了 server.properties 文件并公开了 9085 端口。
cf login cf ic login cf ic namespace set kozhaya
docker build -t watsonspigotbluemix .
docker tag watsonspigotbluemix registry.ng.bluemix.net/kozhaya/watsonspigot
docker push registry.ng.bluemix.net/kozhaya/watsonspigot
cf ic run --name=watsonspigot --publish=9085 registry.ng.bluemix.net/Kozhaya/watsonspigot
此命令成功运行后,它会返回一个 id:1b5fa8fe-c988-4b64-b238-546d6031da1e
cf ic ip request
cf ic ip bind <ip address> watsonspigot
/watson “What is Diabetes”
在本节中,我们引入一个第三方插件 Disease 插件,它允许玩家将对传染病的恐惧带到 Minecraft 城镇中。加入了这些疾病后,您可通过我们之前介绍的插件来利用 Doctor Watson,获取这些疾病的定义和症状的信息,以及最佳的治疗方案。
要添加 Disease 插件,我们将需要向我们之前使用的 Dockerfile 中添加一个步骤来创建 Watson 插件。也就是说,我们需要下载 Disease 插件的 jar 并将它添加到 plugins 目录中。要引用它,我们需要编辑 Dockerfile(下面包含了一个副本)并添加下面以粗体突出显示的一行代码(靠近清单底部)。
# Version 0.0.3 # This version builds a spigot server # using the recommended build strategy for spigot # This is advantageous in that it’s better for plugin development # and fits well with the Docker approach # it also adds a first Minecraft plugin into the bare spigot server # FROM ubuntu:14.04 MAINTAINER Kyle Brown “brownkyl@us.ibm.com” RUN apt-get update RUN apt-get install -y git RUN apt-get install -y default-jdk RUN apt-get install -y wget RUN mkdir minecraft RUN wget "https://hub.spigotmc.org//jenkins/job/BuildTools/lastSuccessfulBuild/artifact/target/BuildTools.jar" -O minecraft/BuildTools.jar RUN git config --global core.autocrlf input RUN java -jar minecraft/BuildTools.jar RUN echo "eula=true" > eula.txt RUN mkdir plugins ADD watsonqa.jar /plugins/watsonqa.jar # Install unzip RUN apt-get install -y unzip RUN unzip -uo /plugins/watsonqa.jar -d /plugins/ RUN wget “http://dev.bukkit.org/media/files/898/525/Disease-1.7.jar” -O plugings/Disease-1.7.jar CMD java -XX:MaxPermSize=128M -Xms512m -Xmx1024m -jar spigot-1.8.8.jar nogui EXPOSE 25565
对于这个 Dockerfile,您需要执行之前运行的相同步骤来构建一个 Docker 映像并运行它:
cd $HOME/watsonspigot
docker build -t="parallels/diseasewatsonspigotplugin" .
docker run -i -t -p=25565:25565 parallels/diseasewatsonspigotplugin
如果您看到以下行,则表明您具有 Disease 插件和 Watson 插件的 Spigot 服务器已成功启动:
连接之后,探究 Disease 插件和关联的命令,比如:
/disease help
/disease list
/disease check
/disease infect <player> <disease>
查阅完整的 命令列表。(一些命令需要管理员权限。)
现在您已可通过该插件访问针对医疗的 Watson QA,您可向 Doctor Watson 发送任何与疾病相关的问题。例如,发出下面这个命令来向 Watson 询问肺炎的最佳治疗方案:
/watson “How to treat Pneumonia”
我们将在 Bluemix 上托管具有 Disease 和 Watson QA 插件的 Spigot 服务器的任务留给读者练习。您现在已知道如何将多个插件(包括 Watson 服务)组合到您的 Minecraft 服务器来创建一种更有吸引力的游戏体验。
现在您已了解如何在 Spigot 服务器中集成 Watson Q&A 服务并将它托管在 Bluemix 上的一个 Docker 容器中。尽管我们重点介绍的是 Watson Q&A 服务,但您也可使用一个或多个其他 Watson 服务来通过相同方法实现更有吸引力的游戏体验,比如 Dialog(想想在玩游戏时订购披萨)、Personality Insights(想想组建玩家团队)、Natural Language Classifier(想想通过玩家的问题理解他们的意图),以及 Visual Recognition(想想从图像中识别疾病症状)。
这个 developerWorks 教程系列 到此就结束了。在这里让您的 Minecraft 体验更上一层楼吧!