- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
一些话来介绍情况。
上下文:为了在编写 Bukkit 插件时简化我的工作流程(在 Sponge 实现它之前基本上是 Minecraft 服务器的事实上的 API),我决定为自己组装一个“迷你框架”,而不必重复相同的任务再三,一而再再而三。 (另外,我试图将它设计为不太依赖 Bukkit,所以我可以通过改变我的实现来继续在 Sponge 上使用它)
意向:坦率地说,Bukkit 中的命令处理一团糟。您必须在 YML 文件(而不是调用某种工厂?)中定义您的根命令(例如,您要运行/test ingame,“test”是根),子命令处理不存在,实现细节是隐藏所以很难产生 100% 可靠的结果。这是 Bukkit 唯一让我恼火的部分,也是我决定编写框架的主要发起者。
目标:抽象掉讨厌的 Bukkit 命令处理,并用干净的东西替换它。
为之努力:
这将是一个很长的段落,我将在其中解释 Bukkit 命令处理最初是如何实现的,因为这将使对重要命令参数等有更深入的了解。
任何连接到 Minecraft 服务器的用户都可以使用“/”开始聊天消息,这将导致它被解析为命令。
举个例子,Minecraft 中的任何玩家都有一个生命条,默认上限为 10 颗心,并在受到伤害时耗尽。服务器可以随时设置最大和当前的“心脏”(读取:健康)。
假设我们想定义一个这样的命令:
/sethealth <current/maximum> <player or * for all> <value>
# Full name of the file extending JavaPlugin
# My best guess? Makes lazy-loading the plugin possible
# (aka: just load classes that are actually used by replacing classloader methods)
main: com.gmail.zkfreddit.sampleplugin.SampleJavaPlugin
# Name of the plugin.
# Why not have this as an annotation on the plugin class?
name: SamplePlugin
# Version of the plugin. Why is this even required? Default could be 1.0.
# And again, could be an annotation on the plugin class...
version: 1.0
# Command section. Instead of calling some sort of factory method...
commands:
# Our '/sethealth' command, which we want to have registered.
sethealth:
# The command description to appear in Help Topics
# (available via '/help' on almost any Bukkit implementation)
description: Set the maximum or current health of the player
# Usage of the command (will explain later)
usage: /sethealth <current/maximum> <player/* for all> <newValue>
# Bukkit has a simple string-based permission system,
# this will be the command permission
# (and as no default is specified,
# will default to "everybody has it")
permission: sampleplugin.sethealth
package com.gmail.zkfreddit.sampleplugin;
import org.bukkit.command.PluginCommand;
import org.bukkit.plugin.java.JavaPlugin;
public class SampleJavaPlugin extends JavaPlugin {
//Called when the server enables our plugin
@Override
public void onEnable() {
//Get the command object for our "sethealth" command.
//This basically ties code to configuration, and I'm pretty sure is considered bad practice...
PluginCommand command = getCommand("sethealth");
//Set the executor of that command to our executor.
command.setExecutor(new SampleCommandExecutor());
}
}
package com.gmail.zkfreddit.sampleplugin;
import org.bukkit.Bukkit;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
public class SampleCommandExecutor implements CommandExecutor {
private static enum HealthOperationType {
CURRENT,
MAXIMUM;
public void executeOn(Player player, double newHealth) {
switch (this) {
case CURRENT:
player.setHealth(newHealth);
break;
case MAXIMUM:
player.setMaxHealth(newHealth);
break;
}
}
}
@Override
public boolean onCommand(
//The sender of the command - may be a player, but might also be the console
CommandSender commandSender,
//The command object representing this command
//Why is this included? We know this is our SetHealth executor,
//so why add this as another parameter?
Command command,
//This is the "label" of the command - when a command gets registered,
//it's name may have already been taken, so it gets prefixed with the plugin name
//(example: 'sethealth' unavailable, our command will be registered as 'SamplePlugin:sethealth')
String label,
//The command arguments - everything after the command name gets split by spaces.
//If somebody would run "/sethealth a c b", this would be {"a", "c", "b"}.
String[] args) {
if (args.length != 3) {
//Our command does not match the requested form {"<current/maximum>", "<player>", "<value>"},
//returning false will, ladies and gentleman...
//display the usage message defined in plugin.yml. Hooray for some documented code /s
return false;
}
HealthOperationType operationType;
double newHealth;
try {
//First argument: <current/maximum>
operationType = HealthOperationType.valueOf(args[0].toUpperCase());
} catch (IllegalArgumentException e) {
return false;
}
try {
//Third argument: The new health value
newHealth = Double.parseDouble(args[2]);
} catch (NumberFormatException e) {
return false;
}
//Second argument: Player to operate on (or all)
if (args[1].equalsIgnoreCase("*")) {
//Run for all players
for (Player player : Bukkit.getOnlinePlayers()) {
operationType.executeOn(player, newHealth);
}
} else {
//Run for a specific player
Player player = Bukkit.getPlayerExact(args[1]);
if (player == null) {
//Player offline
return false;
}
operationType.executeOn(player, newHealth);
}
//Handled successfully, return true to not display usage message
return true;
}
}
Bukkit.getPluginManager().registerEvents(Listener, Plugin)
)来注册命令。
CommandResult <anyMethodName>(CommandContext)
.
package com.gmail.zkfreddit.pluginframework.api.command;
public interface CommandRegistration {
public static enum ResultType {
REGISTERED,
RENAMED_AND_REGISTERED,
FAILURE
}
public static interface Result {
ResultType getType();
//For RENAMED_AND_REGISTERED
Command getConflictCommand();
//For FAILURE
Throwable getException();
//If the command got registered in some way
boolean registered();
}
Result register(Object commandObject);
}
package com.gmail.zkfreddit.pluginframework.api.command;
public enum CommandResult {
//Command executed and handlded
HANDLED,
//Show the usage for this command as some parameter is wrong
SHOW_USAGE,
//Possibly more?
}
package com.gmail.zkfreddit.pluginframework.api.command;
import org.bukkit.command.CommandSender;
import java.util.List;
public interface CommandContext {
CommandSender getSender();
List<Object> getArguments();
@Deprecated
String getLabel();
@Deprecated
//Get the command annotation of the executed command
Command getCommand();
}
package com.gmail.zkfreddit.pluginframework.api.command;
import org.bukkit.permissions.PermissionDefault;
public @interface Command {
public static final String DEFAULT_STRING = "";
String name();
String description() default DEFAULT_STRING;
String usageMessage() default DEFAULT_STRING;
String permission() default DEFAULT_STRING;
PermissionDefault permissionDefault() default PermissionDefault.TRUE;
Class[] autoParse() default {};
}
package com.gmail.zkfreddit.sampleplugin;
import de.web.paulschwandes.pluginframework.api.command.Command;
import de.web.paulschwandes.pluginframework.api.command.CommandContext;
import org.bukkit.entity.Player;
import org.bukkit.permissions.PermissionDefault;
public class BetterCommandExecutor {
public static enum HealthOperationType {
CURRENT,
MAXIMUM;
public void executeOn(Player player, double newHealth) {
switch (this) {
case CURRENT:
player.setHealth(newHealth);
break;
case MAXIMUM:
player.setMaxHealth(newHealth);
break;
}
}
}
@Command(
name = "sethealth",
description = "Set health values for any or all players",
usageMessage = "/sethealth <current/maximum> <player/* for all> <newHealth>",
permission = "sampleplugin.sethealth",
autoParse = {HealthOperationType.class, Player[].class, Double.class} //Player[] as there may be multiple players matched
)
public CommandResult setHealth(CommandContext context) {
HealthOperationType operationType = (HealthOperationType) context.getArguments().get(0);
Player[] matchedPlayers = (Player[]) context.getArguments().get(1);
double newHealth = (Double) context.getArguments().get(2);
for (Player player : matchedPlayers) {
operationType.executeOn(player, newHealth);
}
return CommandResult.HANDLED;
}
}
/team create ...
/team delete ...
/team addmember/join ...
/team removemember/leave ...
/team [player] info
childs
我的
Command
中的参数批注,并使其采用某种@ChildCommand 批注列表(批注中的批注?天啊,为什么不呢?)。
extends
是 2011 年和
implements
是今年的味道,所以每次我创建某种命令处理程序时,我不应该强制自己扩展某些东西。
最佳答案
我唯一能想到的就是拆分您的注释。您将拥有一个将 Base Command 作为注释的类,然后该类中的方法使用不同的子命令:
@Command("/test")
class TestCommands {
@Command("sub1"// + more parameters and stuff)
public Result sub1Command(...) {
// do stuff
}
@Command("sub2"// + more parameters and stuff)
public Result sub2Command(...) {
// do stuff
}
}
/team [player] info
例子虽然,但我认为这是一件小事。无论如何,在命令的不同参数中显示子命令都会令人困惑。
关于java - 设计 Bukkit 插件框架 - 通过注释处理子命令,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28557059/
我正在编写一个具有以下签名的 Java 方法。 void Logger(Method method, Object[] args); 如果一个方法(例如 ABC() )调用此方法 Logger,它应该
我是 Java 新手。 我的问题是我的 Java 程序找不到我试图用作的图像文件一个 JButton。 (目前这段代码什么也没做,因为我只是得到了想要的外观第一的)。这是我的主课 代码: packag
好的,今天我在接受采访,我已经编写 Java 代码多年了。采访中说“Java 垃圾收集是一个棘手的问题,我有几个 friend 一直在努力弄清楚。你在这方面做得怎么样?”。她是想骗我吗?还是我的一生都
我的 friend 给了我一个谜语让我解开。它是这样的: There are 100 people. Each one of them, in his turn, does the following
如果我将使用 Java 5 代码的应用程序编译成字节码,生成的 .class 文件是否能够在 Java 1.4 下运行? 如果后者可以工作并且我正在尝试在我的 Java 1.4 应用程序中使用 Jav
有关于why Java doesn't support unsigned types的问题以及一些关于处理无符号类型的问题。我做了一些搜索,似乎 Scala 也不支持无符号数据类型。限制是Java和S
我只是想知道在一个 java 版本中生成的字节码是否可以在其他 java 版本上运行 最佳答案 通常,字节码无需修改即可在 较新 版本的 Java 上运行。它不会在旧版本上运行,除非您使用特殊参数 (
我有一个关于在命令提示符下执行 java 程序的基本问题。 在某些机器上我们需要指定 -cp 。 (类路径)同时执行java程序 (test为java文件名与.class文件存在于同一目录下) jav
我已经阅读 StackOverflow 有一段时间了,现在我才鼓起勇气提出问题。我今年 20 岁,目前在我的家乡(罗马尼亚克卢日-纳波卡)就读 IT 大学。足以介绍:D。 基本上,我有一家提供簿记应用
我有 public JSONObject parseXML(String xml) { JSONObject jsonObject = XML.toJSONObject(xml); r
我已经在 Java 中实现了带有动态类型的简单解释语言。不幸的是我遇到了以下问题。测试时如下代码: def main() { def ks = Map[[1, 2]].keySet()
一直提示输入 1 到 10 的数字 - 结果应将 st、rd、th 和 nd 添加到数字中。编写一个程序,提示用户输入 1 到 10 之间的任意整数,然后以序数形式显示该整数并附加后缀。 public
我有这个 DownloadFile.java 并按预期下载该文件: import java.io.*; import java.net.URL; public class DownloadFile {
我想在 GUI 上添加延迟。我放置了 2 个 for 循环,然后重新绘制了一个标签,但这 2 个 for 循环一个接一个地执行,并且标签被重新绘制到最后一个。 我能做什么? for(int i=0;
我正在对对象 Student 的列表项进行一些测试,但是我更喜欢在 java 类对象中创建硬编码列表,然后从那里提取数据,而不是连接到数据库并在结果集中选择记录。然而,自从我这样做以来已经很长时间了,
我知道对象创建分为三个部分: 声明 实例化 初始化 classA{} classB extends classA{} classA obj = new classB(1,1); 实例化 它必须使用
我有兴趣使用 GPRS 构建车辆跟踪系统。但是,我有一些问题要问以前做过此操作的人: GPRS 是最好的技术吗?人们意识到任何问题吗? 我计划使用 Java/Java EE - 有更好的技术吗? 如果
我可以通过递归方法反转数组,例如:数组={1,2,3,4,5} 数组结果={5,4,3,2,1}但我的结果是相同的数组,我不知道为什么,请帮助我。 public class Recursion { p
有这样的标准方式吗? 包括 Java源代码-测试代码- Ant 或 Maven联合单元持续集成(可能是巡航控制)ClearCase 版本控制工具部署到应用服务器 最后我希望有一个自动构建和集成环境。
我什至不知道这是否可能,我非常怀疑它是否可能,但如果可以,您能告诉我怎么做吗?我只是想知道如何从打印机打印一些文本。 有什么想法吗? 最佳答案 这里有更简单的事情。 import javax.swin
我是一名优秀的程序员,十分优秀!