增加一些动作/结构并且补注释:( 呜呜呜补注释好累头号疼
This commit is contained in:
@@ -4,27 +4,48 @@ import org.bukkit.event.Listener;
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
import top.sunsetlab.event.EventListener;
|
||||
import top.sunsetlab.utils.ActionManager;
|
||||
import top.sunsetlab.utils.LangUtils;
|
||||
import top.sunsetlab.utils.StructureManager;
|
||||
|
||||
import java.util.logging.Logger;
|
||||
|
||||
/**
|
||||
* 插件主类
|
||||
*/
|
||||
public class PluginMain extends JavaPlugin implements Listener {
|
||||
/// 插件版本
|
||||
public static final String VERSION = "0.0.1-alpha";
|
||||
/// 插件语言
|
||||
public static final String LANG = "zh_CN";
|
||||
/// 调试模式
|
||||
public static final boolean DEBUG = true;
|
||||
/// 日志类 - 仅在初始化后调用
|
||||
public static Logger LOGGER;
|
||||
/// 结构管理器,用于加载/匹配预设的结构
|
||||
public static StructureManager structureManager;
|
||||
/// 动作管理器,用于加载/调用预设的动作
|
||||
public static ActionManager actionManager;
|
||||
/// 插件实例
|
||||
public static JavaPlugin plugin;
|
||||
/// 语言管理,本地化用
|
||||
public static LangUtils langUtils;
|
||||
|
||||
/**
|
||||
* 插件启用时调用
|
||||
*/
|
||||
@Override
|
||||
public void onEnable() {
|
||||
// 初始化
|
||||
plugin = this;
|
||||
LOGGER = getLogger();
|
||||
langUtils = new LangUtils();
|
||||
langUtils.init(LANG);
|
||||
structureManager = new StructureManager();
|
||||
structureManager.load();
|
||||
actionManager = new ActionManager();
|
||||
actionManager.load();
|
||||
getLogger().info("Plugin ver" + VERSION + " loaded." + (DEBUG?"(DEBUG)":""));
|
||||
// 注册时间监听器
|
||||
getServer().getPluginManager().registerEvents(new EventListener(), this);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,7 +3,14 @@ package top.sunsetlab.actions;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
/// 打雷动作
|
||||
public class ActionLightning implements IActionBase{
|
||||
/**
|
||||
* 调用动作
|
||||
* @param location 动作执行位置
|
||||
* @param caller 动作执行者
|
||||
* @return 是否成功
|
||||
*/
|
||||
@Override
|
||||
public boolean call(Location location, Player caller) {
|
||||
location.getWorld().strikeLightning(location);
|
||||
|
||||
35
src/main/java/top/sunsetlab/actions/CastDelay.java
Normal file
35
src/main/java/top/sunsetlab/actions/CastDelay.java
Normal file
@@ -0,0 +1,35 @@
|
||||
package top.sunsetlab.actions;
|
||||
|
||||
import org.bukkit.Color;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Particle;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
/// 施放延迟
|
||||
public class CastDelay implements IActionBase{
|
||||
/**
|
||||
* 调用动作
|
||||
* @param location 动作执行位置
|
||||
* @param caller 动作执行者
|
||||
* @return 是否成功
|
||||
*/
|
||||
@Override
|
||||
public boolean call(Location location, Player caller) {
|
||||
int count = 0;
|
||||
while (count < 50) {
|
||||
try {
|
||||
Thread.sleep(100);
|
||||
}catch (InterruptedException ignored){}
|
||||
location.getWorld().spawnParticle(
|
||||
Particle.DUST,
|
||||
location,
|
||||
20,
|
||||
1.0,
|
||||
0.0,
|
||||
1.0,
|
||||
new Particle.DustOptions(Color.RED, 1.0f));
|
||||
count++;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
32
src/main/java/top/sunsetlab/actions/CheckGlowDust.java
Normal file
32
src/main/java/top/sunsetlab/actions/CheckGlowDust.java
Normal file
@@ -0,0 +1,32 @@
|
||||
package top.sunsetlab.actions;
|
||||
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.TextComponent;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.entity.Player;
|
||||
import top.sunsetlab.PluginMain;
|
||||
|
||||
/// 门控动作,检查莹石存量
|
||||
public class CheckGlowDust implements IActionBase {
|
||||
/**
|
||||
* 调用动作
|
||||
* @param location 动作执行位置
|
||||
* @param caller 动作执行者
|
||||
* @return 是否成功
|
||||
*/
|
||||
@Override
|
||||
public boolean call(Location location, Player caller) {
|
||||
if (PluginMain.DEBUG) {
|
||||
PluginMain.LOGGER.info("Checking amount of glow dust");
|
||||
}
|
||||
if (caller.getInventory().getItemInMainHand().getType() == Material.GLOWSTONE_DUST
|
||||
&& caller.getInventory().getItemInMainHand().getAmount() >= 20) {
|
||||
int amount = caller.getInventory().getItemInMainHand().getAmount();
|
||||
caller.getInventory().getItemInMainHand().setAmount(amount - 20);
|
||||
return true;
|
||||
}
|
||||
caller.sendMessage(PluginMain.langUtils.translateC("starlight.message.glowdust_lack"));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -3,6 +3,13 @@ package top.sunsetlab.actions;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
/// 动作基类
|
||||
public interface IActionBase {
|
||||
/**
|
||||
* 调用动作
|
||||
* @param location 动作执行位置
|
||||
* @param caller 动作执行者
|
||||
* @return 是否成功
|
||||
*/
|
||||
boolean call(Location location, Player caller);
|
||||
}
|
||||
|
||||
34
src/main/java/top/sunsetlab/actions/PlaceFire.java
Normal file
34
src/main/java/top/sunsetlab/actions/PlaceFire.java
Normal file
@@ -0,0 +1,34 @@
|
||||
package top.sunsetlab.actions;
|
||||
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
/// 放置火焰
|
||||
public class PlaceFire implements IActionBase {
|
||||
/**
|
||||
* 调用动作
|
||||
* @param location 动作执行位置
|
||||
* @param caller 动作执行者
|
||||
* @return 是否成功
|
||||
*/
|
||||
@Override
|
||||
public boolean call(Location location, Player caller) {
|
||||
placeFire(location.clone().add(1,0,0));
|
||||
placeFire(location.clone().add(-1,0,0));
|
||||
placeFire(location.clone().add(0,0,1));
|
||||
placeFire(location.clone().add(0,0,-1));
|
||||
placeFire(location.clone().add(0,0,0));
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 在指定位置放置火焰
|
||||
* @param location 位置
|
||||
*/
|
||||
private void placeFire(Location location) {
|
||||
World world = location.getWorld();
|
||||
world.setBlockData(location, Material.FIRE.createBlockData());
|
||||
}
|
||||
}
|
||||
20
src/main/java/top/sunsetlab/actions/PlayAnvilSound.java
Normal file
20
src/main/java/top/sunsetlab/actions/PlayAnvilSound.java
Normal file
@@ -0,0 +1,20 @@
|
||||
package top.sunsetlab.actions;
|
||||
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Sound;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
/// 向调用者播放铁砧的声音
|
||||
public class PlayAnvilSound implements IActionBase {
|
||||
/**
|
||||
* 调用动作
|
||||
* @param location 动作执行位置
|
||||
* @param caller 动作执行者
|
||||
* @return 是否成功
|
||||
*/
|
||||
@Override
|
||||
public boolean call(Location location, Player caller) {
|
||||
caller.playSound(location, Sound.BLOCK_ANVIL_LAND, 1, 1);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
33
src/main/java/top/sunsetlab/actions/Transformation.java
Normal file
33
src/main/java/top/sunsetlab/actions/Transformation.java
Normal file
@@ -0,0 +1,33 @@
|
||||
package top.sunsetlab.actions;
|
||||
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
/// 嬗变!(神奇炼金术)
|
||||
public class Transformation implements IActionBase {
|
||||
/**
|
||||
* 调用动作
|
||||
* @param location 动作执行位置
|
||||
* @param caller 动作执行者
|
||||
* @return 是否成功
|
||||
*/
|
||||
@Override
|
||||
public boolean call(Location location, Player caller) {
|
||||
location.getWorld().setBlockData(
|
||||
location.getBlockX(),
|
||||
location.getBlockY(),
|
||||
location.getBlockZ(),
|
||||
Material.NETHERITE_BLOCK.createBlockData()
|
||||
);
|
||||
location.getWorld().setBlockData(
|
||||
location.clone().subtract(1,0,0),
|
||||
Material.AIR.createBlockData()
|
||||
);
|
||||
location.getWorld().setBlockData(
|
||||
location.clone().add(1,0,0),
|
||||
Material.AIR.createBlockData()
|
||||
);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,9 @@
|
||||
package top.sunsetlab.event;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.block.Action;
|
||||
@@ -11,21 +13,27 @@ import top.sunsetlab.utils.JsonStructure;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
/// 事件监听器
|
||||
public class EventListener implements Listener {
|
||||
/**
|
||||
* 当玩家与世界交互时触发
|
||||
* @param event 事件实例
|
||||
*/
|
||||
@EventHandler
|
||||
public void clickEvent(PlayerInteractEvent event) {
|
||||
if (event.getAction() != Action.RIGHT_CLICK_BLOCK) {
|
||||
return;
|
||||
}
|
||||
if (event.getPlayer().getInventory().getItemInMainHand().getType() != Material.GLOWSTONE_DUST) {
|
||||
Player player = event.getPlayer();
|
||||
if (player.getInventory().getItemInMainHand().getType() != Material.GLOWSTONE_DUST) {
|
||||
return;
|
||||
}
|
||||
if (event.getClickedBlock() != null && event.getClickedBlock().getType() != Material.REDSTONE_WIRE) {
|
||||
return;
|
||||
}
|
||||
|
||||
Bukkit.getScheduler().runTaskAsynchronously(PluginMain.plugin, () -> {
|
||||
String structid = PluginMain.structureManager.match(event.getClickedBlock().getLocation());
|
||||
Location location = event.getClickedBlock().getLocation();
|
||||
String structid = PluginMain.structureManager.match(location);
|
||||
if (structid == null) {
|
||||
return;
|
||||
}
|
||||
@@ -33,9 +41,19 @@ public class EventListener implements Listener {
|
||||
if (structure == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (structure.getPreConditionTask() != null
|
||||
&& !PluginMain.actionManager.call(structure.getPreConditionTask(), location, player)) {
|
||||
return;
|
||||
}
|
||||
|
||||
structure.breakStructure(location);
|
||||
|
||||
// 异步执行动作
|
||||
Bukkit.getScheduler().runTaskAsynchronously(PluginMain.plugin, () -> {
|
||||
ArrayList<String> actions = structure.getActions();
|
||||
for (String action : actions) {
|
||||
PluginMain.actionManager.call(action, event.getClickedBlock().getLocation(), event.getPlayer());
|
||||
PluginMain.actionManager.call(action, location, player);
|
||||
}
|
||||
});
|
||||
event.setCancelled(true);
|
||||
|
||||
@@ -16,20 +16,29 @@ class ActionList {
|
||||
ArrayList<String> locations;
|
||||
}
|
||||
|
||||
/**
|
||||
* 动作管理器
|
||||
*/
|
||||
public class ActionManager {
|
||||
private final HashMap<String, JsonAction> actions;
|
||||
public ActionManager() {
|
||||
actions = new HashMap<>();
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化
|
||||
*/
|
||||
public void load() {
|
||||
// 从本地文件读取
|
||||
InputStream is = ActionManager.class.getResourceAsStream("/actions.json");
|
||||
if (is == null) {
|
||||
throw new RuntimeException("actions.json file not found!");
|
||||
}
|
||||
BufferedReader reader = new BufferedReader(new InputStreamReader(is));
|
||||
// 解析json
|
||||
Gson gson = new Gson();
|
||||
ActionList actionList = gson.fromJson(reader, ActionList.class);
|
||||
// 加载单个动作
|
||||
for (String location : actionList.locations) {
|
||||
JsonAction action = new JsonAction(location);
|
||||
actions.put(action.getId(), action);
|
||||
@@ -37,7 +46,15 @@ public class ActionManager {
|
||||
PluginMain.LOGGER.info("Loaded " + actions.size() + " actions.");
|
||||
}
|
||||
|
||||
/**
|
||||
* 调用动作
|
||||
* @param actionId 动作id
|
||||
* @param location 执行位置
|
||||
* @param caller 执行者
|
||||
* @return 动作是否执行成功,sync动作始终返回true
|
||||
*/
|
||||
public boolean call(String actionId, Location location, Player caller) {
|
||||
// 获取动作
|
||||
JsonAction action = actions.get(actionId);
|
||||
if (action == null) {
|
||||
throw new RuntimeException("Invalid action id " + actionId);
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
package top.sunsetlab.utils;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.entity.Player;
|
||||
import top.sunsetlab.PluginMain;
|
||||
import top.sunsetlab.actions.IActionBase;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
@@ -14,11 +16,19 @@ import java.lang.reflect.InvocationTargetException;
|
||||
class ActionData {
|
||||
String id;
|
||||
String classname;
|
||||
boolean sync;
|
||||
}
|
||||
|
||||
/**
|
||||
* Json定义的动作
|
||||
*/
|
||||
public class JsonAction {
|
||||
private final ActionData data;
|
||||
|
||||
/**
|
||||
* 构造器
|
||||
* @param location 资源文件(json)的位置
|
||||
*/
|
||||
public JsonAction(String location) {
|
||||
InputStream is = JsonAction.class.getResourceAsStream("/" + location);
|
||||
if (is == null) {
|
||||
@@ -29,15 +39,32 @@ public class JsonAction {
|
||||
data = gson.fromJson(br, ActionData.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* 调用动作
|
||||
* @param location 调用位置
|
||||
* @param caller 执行者
|
||||
* @return 动作是否成功运行,sync动作始终为true
|
||||
*/
|
||||
public boolean run(Location location, Player caller) {
|
||||
try {
|
||||
// 通过反射加载动作类
|
||||
Class<?> clazz = Class.forName(data.classname);
|
||||
if (!IActionBase.class.isAssignableFrom(clazz)) {
|
||||
throw new RuntimeException(data.classname + " is not a Action");
|
||||
}
|
||||
// 获取构造器
|
||||
Constructor<?> constructor = clazz.getConstructor();
|
||||
IActionBase action = (IActionBase) constructor.newInstance();
|
||||
if (data.sync) {
|
||||
// 在Minecraft线程内执行,一般用于世界交互
|
||||
Bukkit.getScheduler().runTask(PluginMain.plugin, () -> {
|
||||
action.call(location, caller);
|
||||
});
|
||||
return true;
|
||||
}else {
|
||||
// 异步执行
|
||||
return action.call(location, caller);
|
||||
}
|
||||
}catch (ClassNotFoundException
|
||||
| NoSuchMethodException
|
||||
| SecurityException
|
||||
@@ -51,6 +78,10 @@ public class JsonAction {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取动作id
|
||||
* @return 动作id
|
||||
*/
|
||||
public String getId() {
|
||||
return data.id;
|
||||
}
|
||||
|
||||
@@ -1,11 +1,9 @@
|
||||
package top.sunsetlab.utils;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.NamespacedKey;
|
||||
import org.bukkit.Registry;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.*;
|
||||
import org.bukkit.block.BlockType;
|
||||
import org.jspecify.annotations.NonNull;
|
||||
import top.sunsetlab.PluginMain;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
@@ -22,12 +20,22 @@ class JsonStructureData {
|
||||
int[] center;
|
||||
String id;
|
||||
ArrayList<String> actions;
|
||||
String precondition_task;
|
||||
ArrayList<String> noclear;
|
||||
}
|
||||
|
||||
/// Json定义的结构
|
||||
public class JsonStructure {
|
||||
/// 结构数据
|
||||
private final JsonStructureData data;
|
||||
/// 结构资源文件位置
|
||||
private final String structure_loc;
|
||||
|
||||
/**
|
||||
* 构造函数
|
||||
* @param location 资源文件的位置
|
||||
* @throws RuntimeException 在无法读取资源文件时抛出
|
||||
*/
|
||||
public JsonStructure(String location) throws RuntimeException {
|
||||
InputStream file = JsonStructure.class.getResourceAsStream("/" + location);
|
||||
if (file == null) {
|
||||
@@ -40,7 +48,13 @@ public class JsonStructure {
|
||||
structure_loc = location;
|
||||
}
|
||||
|
||||
/**
|
||||
* 尝试匹配结构
|
||||
* @param pos 结构中心点位置
|
||||
* @return 结构是否匹配?
|
||||
*/
|
||||
public boolean match(Location pos) {
|
||||
// 确定起始点,终点
|
||||
World world = pos.getWorld();
|
||||
Location currentpos = new Location(
|
||||
world,
|
||||
@@ -59,7 +73,14 @@ public class JsonStructure {
|
||||
PluginMain.LOGGER.log(Level.INFO, "Matching structure " + structure_loc
|
||||
+ "; From " + currentpos + " To " + endpos);
|
||||
}
|
||||
|
||||
// 记录方块种类 - 仅在需要时生成
|
||||
ArrayList<BlockType> types = null;
|
||||
|
||||
// 循环匹配每个方块
|
||||
// TODO 有没有更好的方法
|
||||
while (!currentpos.equals(endpos)) {
|
||||
// 相对西北角的位置
|
||||
int rx = currentpos.getBlockX() - startpos.getBlockX();
|
||||
int rz = currentpos.getBlockZ() - startpos.getBlockZ();
|
||||
// if (PluginMain.DEBUG) {
|
||||
@@ -67,19 +88,16 @@ public class JsonStructure {
|
||||
// + currentpos
|
||||
// + "(relative (" + rx + "," + rz + "))");
|
||||
// }
|
||||
// 应该存在的方块
|
||||
String mark = String.valueOf(data.structure.get(rz).charAt(rx));
|
||||
String type = data.marks.get(mark);
|
||||
if (type == null) {
|
||||
throw new RuntimeException("In Structure "+ structure_loc +"; Undefined mark: " + mark);
|
||||
}
|
||||
NamespacedKey key = NamespacedKey.fromString(type);
|
||||
if (key == null) {
|
||||
throw new RuntimeException("In Structure "+ structure_loc +"; Invalid key: " + type);
|
||||
}
|
||||
BlockType blockType = Registry.BLOCK.get(key);
|
||||
if (blockType == null) {
|
||||
throw new RuntimeException("In Structure "+ structure_loc +"; Invalid block type: " + type);
|
||||
}
|
||||
|
||||
if (!type.equals("any")) {
|
||||
// 匹配特定方块
|
||||
BlockType blockType = getBlockType(type);
|
||||
if (!Objects.equals(world.getBlockAt(currentpos).getType().asBlockType(), blockType)) {
|
||||
if (PluginMain.DEBUG) {
|
||||
PluginMain.LOGGER.log(Level.INFO, "Block Mismatch at " + currentpos
|
||||
@@ -89,6 +107,31 @@ public class JsonStructure {
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}else {
|
||||
// 匹配任意方块
|
||||
if (types == null) {
|
||||
types = new ArrayList<>();
|
||||
for (String s : data.marks.values()) {
|
||||
if (s.equals("any")) {
|
||||
continue;
|
||||
}
|
||||
types.add(getBlockType(s));
|
||||
}
|
||||
}
|
||||
// 是否为空气
|
||||
boolean isAir = Objects.equals(world.getBlockAt(currentpos).getType().asBlockType(), Material.AIR.asBlockType());
|
||||
// 是否在列表内 - 为了防止玩家摆个正方形导致怪异的匹配
|
||||
boolean isInList = types.contains(world.getBlockAt(currentpos).getType().asBlockType());
|
||||
// 当非空气且在列表内时终止
|
||||
if (!isAir && isInList ) {
|
||||
PluginMain.LOGGER.log(Level.INFO, "Block Mismatch at " + currentpos
|
||||
+ "(relative (" + rx + "," + rz + "))"
|
||||
+ " Tried any, but got " + world.getBlockAt(currentpos).getType());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// 递增当前坐标
|
||||
currentpos.add(1,0,0);
|
||||
if (currentpos.getBlockX() == endpos.getBlockX() + 1) {
|
||||
currentpos.setX(startpos.getBlockX());
|
||||
@@ -101,11 +144,96 @@ public class JsonStructure {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过id获取方块类型
|
||||
* @param type 方块id
|
||||
* @return 方块类型
|
||||
*/
|
||||
private @NonNull BlockType getBlockType(String type) {
|
||||
NamespacedKey key = NamespacedKey.fromString(type);
|
||||
if (key == null) {
|
||||
throw new RuntimeException("In Structure " + structure_loc + "; Invalid key: " + type);
|
||||
}
|
||||
BlockType blockType = Registry.BLOCK.get(key);
|
||||
if (blockType == null) {
|
||||
throw new RuntimeException("In Structure " + structure_loc + "; Invalid block type: " + type);
|
||||
}
|
||||
return blockType;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取结构id
|
||||
* @return 结构id
|
||||
*/
|
||||
public String getId() {
|
||||
return data.id;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取要执行的动作列表
|
||||
* @return 动作列表
|
||||
*/
|
||||
public ArrayList<String> getActions() {
|
||||
return data.actions;
|
||||
}
|
||||
|
||||
/**
|
||||
* 破坏整个结构
|
||||
* @param pos 结构中心位置
|
||||
*/
|
||||
public void breakStructure(Location pos) {
|
||||
// 清理赦免:D (学生物学的)
|
||||
// FIXME 这东西用不了
|
||||
ArrayList<BlockType> noclears = new ArrayList<>();
|
||||
if (data.noclear != null) {
|
||||
// 已知这里正常
|
||||
for (String s : data.noclear) {
|
||||
if (PluginMain.DEBUG) {
|
||||
PluginMain.LOGGER.log(Level.INFO, "Will not clear " + s);
|
||||
}
|
||||
noclears.add(getBlockType(s));
|
||||
}
|
||||
}
|
||||
|
||||
// 确认起始点和终点
|
||||
World world = pos.getWorld();
|
||||
Location beginPos = new Location(
|
||||
pos.getWorld(),
|
||||
pos.getBlockX() - data.center[0],
|
||||
pos.getBlockY(),
|
||||
pos.getBlockZ() - data.center[1]
|
||||
);
|
||||
Location currentPos = beginPos.clone();
|
||||
Location endPos = new Location(
|
||||
pos.getWorld(),
|
||||
pos.getBlockX() + data.center[0],
|
||||
pos.getBlockY(),
|
||||
pos.getBlockZ() + data.center[1]
|
||||
);
|
||||
|
||||
// 遍历每一个方块
|
||||
// TODO 有没有更好的方法
|
||||
while (!beginPos.equals(endPos)) {
|
||||
// 这里的判断貌似有问题
|
||||
if (!noclears.contains(world.getBlockAt(beginPos).getType().asBlockType())) {
|
||||
world.getBlockAt(currentPos).setType(Material.AIR);
|
||||
}
|
||||
currentPos.add(1,0,0);
|
||||
if (currentPos.getBlockX() == endPos.getBlockX() + 1) {
|
||||
currentPos.setX(beginPos.getBlockX());
|
||||
currentPos.setZ(currentPos.getBlockZ() + 1);
|
||||
if (currentPos.getBlockZ() == endPos.getBlockZ() + 1) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取门控任务(仅当该任务成功时执行任务列表)
|
||||
* @return 门控任务id
|
||||
*/
|
||||
public String getPreConditionTask() {
|
||||
return data.precondition_task;
|
||||
}
|
||||
}
|
||||
|
||||
51
src/main/java/top/sunsetlab/utils/LangUtils.java
Normal file
51
src/main/java/top/sunsetlab/utils/LangUtils.java
Normal file
@@ -0,0 +1,51 @@
|
||||
package top.sunsetlab.utils;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.reflect.TypeToken;
|
||||
import net.kyori.adventure.text.Component;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.util.HashMap;
|
||||
|
||||
/// 本地化工具
|
||||
public class LangUtils {
|
||||
/// 一个很好用的键值对
|
||||
private HashMap<String,String> map;
|
||||
|
||||
/**
|
||||
* 初始化
|
||||
* @param lang 使用的语言
|
||||
*/
|
||||
public void init(String lang){
|
||||
InputStream is = LangUtils.class.getResourceAsStream("/assets/lang/" + lang + ".json");
|
||||
if (is == null) {
|
||||
throw new RuntimeException("Unable to load language file: " + lang + ".json");
|
||||
}
|
||||
BufferedReader reader = new BufferedReader(new InputStreamReader(is));
|
||||
Gson gson = new Gson();
|
||||
map = gson.fromJson(reader, new TypeToken<HashMap<String, String>>(){}.getType());
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取本地化文本
|
||||
* @param key 本地化键
|
||||
* @return 本地化文本
|
||||
*/
|
||||
public String translate(String key) {
|
||||
if (map.containsKey(key)) {
|
||||
return map.get(key);
|
||||
}
|
||||
return key;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取本地化文本组件
|
||||
* @param key 本地化键
|
||||
* @return 本地化文本组件
|
||||
*/
|
||||
public Component translateC(String key) {
|
||||
return Component.text(translate(key));
|
||||
}
|
||||
}
|
||||
@@ -16,14 +16,25 @@ class StructureList {
|
||||
ArrayList<String> locations = new ArrayList<>();
|
||||
}
|
||||
|
||||
// 呜呜呜补文档补的快哭了
|
||||
|
||||
/// 结构管理器
|
||||
public class StructureManager {
|
||||
/// 又是一个好用的键值对
|
||||
private final HashMap<String,JsonStructure> structures;
|
||||
|
||||
/**
|
||||
* 构造函数
|
||||
*/
|
||||
public StructureManager() {
|
||||
structures = new HashMap<>();
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化函数
|
||||
*/
|
||||
public void load() {
|
||||
InputStream is = StructureList.class.getResourceAsStream("/structures.json");
|
||||
InputStream is = StructureManager.class.getResourceAsStream("/structures.json");
|
||||
if (is == null) {
|
||||
throw new RuntimeException("structures.json not found");
|
||||
}
|
||||
@@ -37,6 +48,11 @@ public class StructureManager {
|
||||
PluginMain.LOGGER.log(Level.INFO, "Loaded " + structures.size() + " structures");
|
||||
}
|
||||
|
||||
/**
|
||||
* 在所有结构中尝试匹配
|
||||
* @param location 结构的中心位置
|
||||
* @return 匹配到的id,没有匹配到则为null
|
||||
*/
|
||||
public @Nullable String match(Location location) {
|
||||
for (JsonStructure structure : structures.values()) {
|
||||
if (structure.match(location)) {
|
||||
@@ -46,7 +62,25 @@ public class StructureManager {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据id获取结构
|
||||
* @param id 结构id
|
||||
* @return 结构对象
|
||||
*/
|
||||
public @Nullable JsonStructure getStructure(String id) {
|
||||
return structures.get(id);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据id破坏结构
|
||||
* @param id 结构id
|
||||
* @param location 结构的中心位置
|
||||
*/
|
||||
public void breakStructure(String id, Location location) {
|
||||
JsonStructure structure = structures.get(id);
|
||||
if (structure == null) {
|
||||
throw new RuntimeException("structure with id " + id + " not found");
|
||||
}
|
||||
structure.breakStructure(location);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,10 @@
|
||||
{
|
||||
"locations": [
|
||||
"actions/lightning.json"
|
||||
"actions/lightning.json",
|
||||
"actions/castdelay.json",
|
||||
"actions/checkglowdust.json",
|
||||
"actions/transformation.json",
|
||||
"actions/placefire.json",
|
||||
"actions/playanvilsound.json"
|
||||
]
|
||||
}
|
||||
5
src/main/resources/actions/castdelay.json
Normal file
5
src/main/resources/actions/castdelay.json
Normal file
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"id": "castdelay",
|
||||
"classname": "top.sunsetlab.actions.CastDelay",
|
||||
"sync": false
|
||||
}
|
||||
5
src/main/resources/actions/checkglowdust.json
Normal file
5
src/main/resources/actions/checkglowdust.json
Normal file
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"id": "checkglowdust",
|
||||
"classname": "top.sunsetlab.actions.CheckGlowDust",
|
||||
"sync": false
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
{
|
||||
"id": "lightning",
|
||||
"classname": "top.sunsetlab.actions.ActionLightning"
|
||||
"classname": "top.sunsetlab.actions.ActionLightning",
|
||||
"sync": true
|
||||
}
|
||||
5
src/main/resources/actions/placefire.json
Normal file
5
src/main/resources/actions/placefire.json
Normal file
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"id": "placefire",
|
||||
"classname": "top.sunsetlab.actions.PlaceFire",
|
||||
"sync": true
|
||||
}
|
||||
5
src/main/resources/actions/playanvilsound.json
Normal file
5
src/main/resources/actions/playanvilsound.json
Normal file
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"id": "playanvilsound",
|
||||
"classname": "top.sunsetlab.actions.PlayAnvilSound",
|
||||
"sync": false
|
||||
}
|
||||
5
src/main/resources/actions/transformation.json
Normal file
5
src/main/resources/actions/transformation.json
Normal file
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"id": "transformation",
|
||||
"classname": "top.sunsetlab.actions.Transformation",
|
||||
"sync": true
|
||||
}
|
||||
3
src/main/resources/assets/lang/en_US.json
Normal file
3
src/main/resources/assets/lang/en_US.json
Normal file
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"starlight.message.glowdust_lack": "Seems i cannot afford this spell"
|
||||
}
|
||||
3
src/main/resources/assets/lang/zh_CN.json
Normal file
3
src/main/resources/assets/lang/zh_CN.json
Normal file
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"starlight.message.glowdust_lack": "貌似我无法承受这个法阵的消耗"
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
{
|
||||
"locations": [
|
||||
"structures/01.json"
|
||||
"structures/01.json",
|
||||
"structures/transformation.json"
|
||||
]
|
||||
}
|
||||
@@ -16,11 +16,12 @@
|
||||
" xxx "
|
||||
],
|
||||
"marks": {
|
||||
" ": "minecraft:air",
|
||||
" ": "any",
|
||||
"x": "minecraft:redstone_wire"
|
||||
},
|
||||
"center": [6,6],
|
||||
"actions": [
|
||||
"castdelay",
|
||||
"lightning"
|
||||
]
|
||||
}
|
||||
31
src/main/resources/structures/transformation.json
Normal file
31
src/main/resources/structures/transformation.json
Normal file
@@ -0,0 +1,31 @@
|
||||
{
|
||||
"id": "transformation",
|
||||
"structure": [
|
||||
" x ",
|
||||
" xxxxx ",
|
||||
" x p x ",
|
||||
"xxoxoxx",
|
||||
" x p x ",
|
||||
" xxxxx ",
|
||||
" x "
|
||||
],
|
||||
"marks": {
|
||||
"x": "minecraft:redstone_wire",
|
||||
"o": "minecraft:diamond_block",
|
||||
"p": "minecraft:redstone_block",
|
||||
" ": "any"
|
||||
},
|
||||
"center": [3,3],
|
||||
"actions": [
|
||||
"placefire",
|
||||
"playanvilsound",
|
||||
"castdelay",
|
||||
"playanvilsound",
|
||||
"transformation",
|
||||
"lightning"
|
||||
],
|
||||
"precondition_task": "checkglowdust",
|
||||
"noclear": [
|
||||
"minecraft:diamond_block"
|
||||
]
|
||||
}
|
||||
Reference in New Issue
Block a user