昨天才把Ver 1.0放出来,只实现了简单的功能还没进行细节的完善
子命令配置
将目前功能命令进行修改
/bvote setid [room_id]
:设置绑定房间id号
/bvote setworld
:设置当前世界为受影响世界
/bvote time [random|static] <args>
:设置间隔时间为随机或定时
/bvote switch
:设置插件状态
对于子命令的实现,之前进行time指令的实现中使用参数的方式可以进行实现
但是在游戏中输入指令的时候没用补全提示,现在需要实现的就是补全提示
在查阅了文档和一些开源代码后,在插件主类中可以覆写一个onTabComplete
方法,其声明如下
1
| public List<String> onTabComplete(CommandSender sender, Command command, String alias, String[] args);
|
在主类中,可以通过判断参数然后返回一个列表作为待选的可以通过tab补全的子命令,而在onCommand
中可以使用参数实现子命令
项目中的命令是通过实现CommandExecutor
的接口进行命令的实现的,这个地方把所有命令封装到一个bvote
命令下的类中,然后在这个类下调用已经实现的其他命令类
但是这个地方需要实现的是TabExecutor
接口,在其中实现onCommand
方法和onTabComplete
方法
现在,VoteCommands
类的实现如下,实现还是比较的繁琐,或许还会有更简单的方法(现在的一些开源代码这一部分的实现还不是看的很清楚)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49
| public class VoteCommands implements TabExecutor { private DanmakuVote plugin; private String[] subCommands = {"setid", "setworld", "switch", "time", "status"};
public VoteCommands(DanmakuVote plugin) { this.plugin = plugin; }
@Override public boolean onCommand(CommandSender sender, Command command, String label, String[] args) { switch (args[0]) { case "setid": { VoteIdSetExecutor idSetExecutor = new VoteIdSetExecutor(plugin); return idSetExecutor.onCommand(sender, command, label, args); } case "setworld": { VoteWorldSetExecutor worldSetExecutor = new VoteWorldSetExecutor(plugin); return worldSetExecutor.onCommand(sender, command, label, args); } case "switch": { VoteSwitchExecutor switchExecutor = new VoteSwitchExecutor(plugin); return switchExecutor.onCommand(sender, command, label, args); } case "time": { VoteTimeSetExecutor timeSetExecutor = new VoteTimeSetExecutor(plugin); return timeSetExecutor.onCommand(sender, command, label, args); } case "status": { VoteStatusExecutor statusExecutor = new VoteStatusExecutor(plugin); return statusExecutor.onCommand(sender, command, label, args); } default: { sender.sendMessage(ChatColor.RED + "BVote command argument error"); } } return false; }
@Override public List<String> onTabComplete(CommandSender sender, Command command, String alias, String[] args) { if (args.length == 1) { return Arrays.asList(subCommands); } else { return new ArrayList<>(); } } }
|
配置文件添加实体/事件
之前代码中的实体选择是直接写死了的,考虑一定的灵活性就需要通过配置文件进行实体的增删
考虑在配置文件中添加如下内容
1 2 3 4 5 6 7 8
| Monsters: -"creeper" -"" ... Animals: -"pig" _"cow" ...
|
通过写入指定字符串进行实体选择的添加,但是这样做带来的问题是代码实现的复杂
实体生成的代码是这样的
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| public class MonsterPut extends WorldEvent { ... public final void effect() { Player player = randomChosePlayer(); Location location = player.getLocation(); Bukkit.getWorld(worldName).spawnEntity(location, RandomChooser.RandomMonsterChoose()); } }
public final class RandomChooser { public static EntityType RandomMonsterChoose() { EntityType[] MonsterArray = {EntityType.ENDERMAN, EntityType.SPIDER, EntityType.CREEPER, EntityType.SKELETON}; Random random = new Random(); return MonsterArray[random.nextInt(MonsterArray.length)]; } }
|
在这里是有实体的Enum
进行实体的生成,需要通过接收字符串映射到Enum
值
当然最简单的方法就是通过switch进行实现,这个作为最后的一个方案,现在先看看能不能有其他的方法进行替代
Enum可以通过方法valueof
通过字符串获取Enum值,所以此处的实现就比较简单了
配置文件中进行如下配置
1 2 3 4 5 6
| Monsters: - ENDERMAN - CREEPER - SPIDER - SHULKER - ZOMBIE
|
添加RandomEntityChoose
方法,实现进行实体的随机选择
1 2 3 4 5 6 7 8 9
| private static EntityType RandomEntityChoose(DanmakuVote plugin, String _path) { FileConfiguration config = plugin.getConfig(); List monsterList = config.getStringList(_path); Random random = new Random(); int listSize = monsterList.size(); int randomInteger = random.nextInt(listSize); EntityType type = EntityType.valueOf(String.valueOf(monsterList.get(randomInteger))); return type; }
|
对于Monster
的选择,传入参数调用RandomEntityChoose
方法即可
1 2 3
| public static EntityType RandomMonsterChoose(DanmakuVote plugin) { return RandomEntityChoose(plugin, "Monsters"); }
|
配置文件进行命令名修改
这里需要建立一个新的配置文件events.yml
来实现对事件相关参数的配置
文件的格式如下
1 2 3 4 5 6 7
| WeatherClear: name: "Weather Clear" switch: true description: "将天气修改为无天气" hint: "" ticks: 0 ...
|
在读取配置文件的时候,自然与config.yml
不一样,需要使用YamlConfiguration
类中的方法读取该配置文件,在不检查文件是否存在的情况下,读取配置文件的方式如下
1 2
| File f = new File(_plugin.getDataFolder(), _fileName); FileConfiguration config = YamlConfiguration.loadConfiguration(f);
|
进行文件检查,将其封装为一个工具进行调用:
1 2 3 4 5 6 7 8
| public static FileConfiguration getFileConfig(Plugin _plugin, String _fileName) { File f = new File(_plugin.getDataFolder(), _fileName); if (!f.exists()) { _plugin.saveResource(_fileName, true); f = new File(_plugin.getDataFolder(), _fileName); } return YamlConfiguration.loadConfiguration(f); }
|
于是可以在VoteEvent
类中获取对应的配置文件,进行读取
在抽取事件时,检查配置文件中对应事件的switch
是否为 true
,否则丢弃该事件进行重新选取
由于配置文件中进行了对description与name的配置,在实例化对象的时候进行初始化,而不需要传入值
这样,用户可以直接修改配置文件自定义投票名称以及事件效果描述
1 2 3 4 5 6 7 8 9 10 11
| public VoteEvent(String _worldName, String _configName, EventEnum _type, DanmakuVote _plugin) { worldName = _worldName; configName = _configName; EventType = _type; count = 0; plugin = _plugin;
FileConfiguration config = FileUtil.getFileConfig(_plugin, configFileName); eventName = config.getString(String.format("%s.name", configName)); description = config.getString(String.format("%s.description", configName)); }
|