mirror of
https://github.com/CarmJos/ScriptItems
synced 2026-06-25 05:21:08 +08:00
完成指令部分
This commit is contained in:
@@ -0,0 +1,99 @@
|
||||
package cc.carm.plugin.scriptitems;
|
||||
|
||||
import cc.carm.lib.easyplugin.EasyPlugin;
|
||||
import cc.carm.lib.easyplugin.i18n.EasyPluginMessageProvider;
|
||||
import cc.carm.plugin.scriptitems.command.ScriptItemsCommand;
|
||||
import cc.carm.plugin.scriptitems.configuration.PluginConfig;
|
||||
import cc.carm.plugin.scriptitems.hooker.GHUpdateChecker;
|
||||
import cc.carm.plugin.scriptitems.listener.ItemListener;
|
||||
import cc.carm.plugin.scriptitems.manager.ConfigManager;
|
||||
import cc.carm.plugin.scriptitems.manager.ItemsManager;
|
||||
import cc.carm.plugin.scriptitems.util.JarResourceUtils;
|
||||
import org.bstats.bukkit.Metrics;
|
||||
import org.bukkit.Bukkit;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
public class Main extends EasyPlugin {
|
||||
|
||||
private static Main instance;
|
||||
|
||||
public Main() {
|
||||
super(new EasyPluginMessageProvider.zh_CN());
|
||||
instance = this;
|
||||
}
|
||||
|
||||
public static Main getInstance() {
|
||||
return instance;
|
||||
}
|
||||
|
||||
protected ConfigManager configManager;
|
||||
protected ItemsManager itemsManager;
|
||||
|
||||
@Override
|
||||
protected boolean initialize() {
|
||||
|
||||
info("加载配置文件...");
|
||||
this.configManager = new ConfigManager(this);
|
||||
if (!configManager.initConfig()) {
|
||||
severe("配置文件初始化失败,请检查。");
|
||||
setEnabled(false);
|
||||
return false;
|
||||
}
|
||||
|
||||
info("加载物品配置...");
|
||||
this.itemsManager = new ItemsManager();
|
||||
this.itemsManager.initialize();
|
||||
|
||||
info("注册指令...");
|
||||
registerCommand("ScriptItems", new ScriptItemsCommand());
|
||||
|
||||
info("注册监听器...");
|
||||
regListener(new ItemListener());
|
||||
|
||||
if (PluginConfig.METRICS.get()) {
|
||||
info("启用统计数据...");
|
||||
new Metrics(this, 14615);
|
||||
}
|
||||
|
||||
if (PluginConfig.CHECK_UPDATE.get()) {
|
||||
log("开始检查更新...");
|
||||
GHUpdateChecker checker = new GHUpdateChecker(getLogger(), "CarmJos", "CommandItem");
|
||||
getScheduler().runAsync(() -> checker.checkUpdate(getDescription().getVersion()));
|
||||
} else {
|
||||
log("已禁用检查更新,跳过。");
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void shutdown() {
|
||||
|
||||
log("卸载监听器...");
|
||||
Bukkit.getServicesManager().unregisterAll(this);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDebugging() {
|
||||
return PluginConfig.DEBUG.get();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void outputInfo() {
|
||||
Optional.ofNullable(JarResourceUtils.readResource(this.getResource("PLUGIN_INFO"))).ifPresent(this::log);
|
||||
}
|
||||
|
||||
public static void info(String... messages) {
|
||||
getInstance().log(messages);
|
||||
}
|
||||
|
||||
public static void severe(String... messages) {
|
||||
getInstance().error(messages);
|
||||
}
|
||||
|
||||
public static void debugging(String... messages) {
|
||||
getInstance().debug(messages);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
package cc.carm.plugin.scriptitems;
|
||||
|
||||
import cc.carm.plugin.scriptitems.manager.ConfigManager;
|
||||
import cc.carm.plugin.scriptitems.manager.ItemsManager;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.util.stream.IntStream;
|
||||
|
||||
public class ScriptItemsAPI {
|
||||
|
||||
public static ItemsManager getItemsManager() {
|
||||
return Main.getInstance().itemsManager;
|
||||
}
|
||||
|
||||
public static ConfigManager getConfigManager() {
|
||||
return Main.getInstance().configManager;
|
||||
}
|
||||
|
||||
public static boolean hasEmptySlot(Player player) {
|
||||
return IntStream.range(0, 36)
|
||||
.mapToObj(i -> player.getInventory().getItem(i))
|
||||
.anyMatch(i -> i == null || i.getType() == Material.AIR);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,166 @@
|
||||
package cc.carm.plugin.scriptitems.command;
|
||||
|
||||
import cc.carm.plugin.scriptitems.ScriptItemsAPI;
|
||||
import cc.carm.plugin.scriptitems.configuration.PluginMessages;
|
||||
import cc.carm.plugin.scriptitems.item.ItemSettings;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.CommandExecutor;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.command.TabCompleter;
|
||||
import org.bukkit.entity.HumanEntity;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.util.StringUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
|
||||
public class ScriptItemsCommand implements CommandExecutor, TabCompleter {
|
||||
|
||||
|
||||
@Override
|
||||
public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command,
|
||||
@NotNull String alias, @NotNull String[] args) {
|
||||
if (args.length >= 1) {
|
||||
String aim = args[0];
|
||||
if (aim.equalsIgnoreCase("reload")) {
|
||||
try {
|
||||
ScriptItemsAPI.getConfigManager().reload();
|
||||
sender.sendMessage("配置文件重载完成!");
|
||||
} catch (Exception e) {
|
||||
sender.sendMessage("配置文件重载失败!");
|
||||
e.printStackTrace();
|
||||
}
|
||||
return true;
|
||||
} else if (aim.equalsIgnoreCase("apply")) {
|
||||
if (args.length < 2) {
|
||||
PluginMessages.USAGE.send(sender);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!(sender instanceof Player)) {
|
||||
PluginMessages.ONLY_PLAYER.send(sender);
|
||||
return true;
|
||||
}
|
||||
|
||||
ItemSettings settings = ScriptItemsAPI.getItemsManager().getItemSettings(args[1]);
|
||||
if (settings == null) {
|
||||
PluginMessages.NOT_EXISTS.send(sender);
|
||||
return true;
|
||||
}
|
||||
|
||||
Player player = (Player) sender;
|
||||
ItemStack item = player.getInventory().getItemInMainHand();
|
||||
if (item.getType() == Material.AIR) {
|
||||
PluginMessages.USE_ITEM.send(sender);
|
||||
return true;
|
||||
}
|
||||
|
||||
ItemStack after = settings.applyItem(item);
|
||||
player.getInventory().setItemInMainHand(after);
|
||||
PluginMessages.APPLIED.send(sender);
|
||||
|
||||
return true;
|
||||
} else if (aim.equalsIgnoreCase("give")) {
|
||||
|
||||
if (args.length < 3) {
|
||||
PluginMessages.USAGE.send(sender);
|
||||
return true;
|
||||
}
|
||||
|
||||
Player player = Bukkit.getPlayer(args[1]);
|
||||
|
||||
if (player == null) {
|
||||
PluginMessages.NOT_ONLINE.send(sender);
|
||||
return true;
|
||||
}
|
||||
|
||||
ItemSettings settings = ScriptItemsAPI.getItemsManager().getItemSettings(args[2]);
|
||||
if (settings == null) {
|
||||
PluginMessages.NOT_EXISTS.send(sender);
|
||||
return true;
|
||||
}
|
||||
|
||||
int amount = 1;
|
||||
if (args.length >= 4) {
|
||||
try {
|
||||
amount = Integer.parseInt(args[3]);
|
||||
} catch (Exception ignored) {
|
||||
amount = -1;
|
||||
}
|
||||
}
|
||||
if (amount < 1) {
|
||||
PluginMessages.WRONG_AMOUNT.send(sender);
|
||||
return true;
|
||||
}
|
||||
|
||||
ItemStack item = settings.generateItem(amount);
|
||||
if (item == null) {
|
||||
PluginMessages.WRONG_ITEM.send(sender);
|
||||
return true;
|
||||
}
|
||||
|
||||
HashMap<Integer, ItemStack> remain = player.getInventory().addItem(item);
|
||||
if (remain.isEmpty()) {
|
||||
PluginMessages.GIVEN_ALL.send(sender, player, item.getAmount(), settings.getName());
|
||||
} else {
|
||||
int remainAmount = remain.values().stream().mapToInt(ItemStack::getAmount).sum();
|
||||
PluginMessages.GIVEN_SOME.send(sender, player, item.getAmount() - remainAmount, settings.getName(), remainAmount);
|
||||
}
|
||||
|
||||
return true;
|
||||
} else {
|
||||
PluginMessages.USAGE.send(sender);
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
PluginMessages.USAGE.send(sender);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public List<String> onTabComplete(@NotNull CommandSender sender, @NotNull Command command,
|
||||
@NotNull String alias, @NotNull String[] args) {
|
||||
List<String> allCompletes = new ArrayList<>();
|
||||
switch (args.length) {
|
||||
case 1: {
|
||||
allCompletes.add("help");
|
||||
allCompletes.add("give");
|
||||
if (sender instanceof Player) allCompletes.add("apply");
|
||||
allCompletes.add("reload");
|
||||
break;
|
||||
}
|
||||
case 2: {
|
||||
String aim = args[args.length - 1];
|
||||
if (aim.equalsIgnoreCase("give")) {
|
||||
allCompletes = Bukkit.getOnlinePlayers().stream().map(HumanEntity::getName).collect(Collectors.toList());
|
||||
} else if (aim.equalsIgnoreCase("apply")) {
|
||||
allCompletes = new ArrayList<>(ScriptItemsAPI.getItemsManager().listItemSettings().keySet());
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 3: {
|
||||
String aim = args[args.length - 1];
|
||||
if (aim.equalsIgnoreCase("give")) {
|
||||
allCompletes = new ArrayList<>(ScriptItemsAPI.getItemsManager().listItemSettings().keySet());
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return allCompletes.stream()
|
||||
.filter(s -> StringUtil.startsWithIgnoreCase(s, args[args.length - 1]))
|
||||
.limit(10).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
package cc.carm.plugin.scriptitems.configuration;
|
||||
|
||||
import cc.carm.lib.easyplugin.configuration.values.ConfigValue;
|
||||
|
||||
public class PluginConfig {
|
||||
|
||||
public static final ConfigValue<Boolean> DEBUG = new ConfigValue<>(
|
||||
"debug", Boolean.class, false
|
||||
);
|
||||
|
||||
public static final ConfigValue<Boolean> METRICS = new ConfigValue<>(
|
||||
"metrics", Boolean.class, true
|
||||
);
|
||||
|
||||
public static final ConfigValue<Boolean> CHECK_UPDATE = new ConfigValue<>(
|
||||
"check-update", Boolean.class, true
|
||||
);
|
||||
|
||||
public static final ConfigValue<Boolean> LOG_STORAGE = new ConfigValue<>(
|
||||
"log-storage.enable", Boolean.class, true
|
||||
);
|
||||
|
||||
public static class CustomStorage {
|
||||
|
||||
public static ConfigValue<Boolean> ENABLE = new ConfigValue<>("custom-storage.enable", Boolean.class, false);
|
||||
|
||||
public static ConfigValue<String> PATH = new ConfigValue<>("custom-storage.path", String.class, "items/");
|
||||
|
||||
}
|
||||
|
||||
public static class CoolDown {
|
||||
|
||||
public static ConfigValue<Boolean> ENABLE = new ConfigValue<>("cooldown.enable", Boolean.class, true);
|
||||
|
||||
public static ConfigValue<Long> TIME = new ConfigValue<>("cooldown.time", Long.class, 3000L);
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
package cc.carm.plugin.scriptitems.configuration;
|
||||
|
||||
|
||||
import cc.carm.lib.easyplugin.configuration.language.EasyMessageList;
|
||||
import cc.carm.lib.easyplugin.configuration.language.MessagesRoot;
|
||||
|
||||
public class PluginMessages extends MessagesRoot {
|
||||
|
||||
public static final EasyMessageList USAGE = EasyMessageList.builder().contents(
|
||||
"&2&l脚本指令 &f指令帮助",
|
||||
"&8#&f give &a<玩家名> &a<箱子ID> &2[数量]",
|
||||
"&8-&7 给予指定玩家指定数量的物品。",
|
||||
"&8#&f apply &a<箱子ID>",
|
||||
"&8-&7 为手中的物品直接绑定一个配置。",
|
||||
"&8#&f reload",
|
||||
"&8-&7 重载配置文件。"
|
||||
).build();
|
||||
|
||||
|
||||
public final static EasyMessageList COOLDOWN = EasyMessageList.builder()
|
||||
.contents("&f您需要等待 &c%(time)秒 &f才可再次使用该物品。")
|
||||
.params("time").build();
|
||||
|
||||
public final static EasyMessageList ONLY_PLAYER = EasyMessageList.builder()
|
||||
.contents("&c抱歉,只有作为玩家时才能使用该指令。").build();
|
||||
|
||||
public final static EasyMessageList USE_ITEM = EasyMessageList.builder()
|
||||
.contents("&f请手持任意物品后再使用该指令。").build();
|
||||
|
||||
public final static EasyMessageList NOT_ONLINE = EasyMessageList.builder()
|
||||
.contents("&f玩家 &a%(player) &f并不在线。")
|
||||
.params("player").build();
|
||||
|
||||
public final static EasyMessageList NOT_EXISTS = EasyMessageList.builder()
|
||||
.contents("&f脚本配置 &a%(id) &f并不存在。")
|
||||
.params("id").build();
|
||||
|
||||
public final static EasyMessageList WRONG_AMOUNT = EasyMessageList.builder()
|
||||
.contents("&f请输入正确的数量!")
|
||||
.build();
|
||||
|
||||
public final static EasyMessageList WRONG_ITEM = EasyMessageList.builder()
|
||||
.contents("&f该脚本并未成功配置具体物品,请使用 &a/ScriptItems apply &f来绑定到指定物品上,或在配置文件中正确配置物品。")
|
||||
.build();
|
||||
|
||||
public final static EasyMessageList GIVEN_ALL = EasyMessageList.builder()
|
||||
.contents("&f您成功给予 &a%(player) &f了 &a%(amount) &f个 &a%(item) &f。")
|
||||
.params("player", "amount", "item").build();
|
||||
|
||||
public final static EasyMessageList GIVEN_SOME = EasyMessageList.builder().contents(
|
||||
"&f您成功给予 &a%(player) &f了 &a%(amount) &f个 &a%(item) &f。",
|
||||
"&f但由于目标玩家背包已满,仍有 &a%(remain) &f个 &a%(item) &f未成功放入背包。"
|
||||
).params("player", "amount", "item", "remain").build();
|
||||
|
||||
|
||||
public final static EasyMessageList APPLIED = EasyMessageList.builder()
|
||||
.contents("&f已成功为手上物品绑定脚本。").build();
|
||||
|
||||
public static class Restrictions {
|
||||
|
||||
public final static EasyMessageList INVALID = EasyMessageList.builder()
|
||||
.contents("&c&l抱歉!&f由于配置的时间限制错误,该物品目前暂不可用。")
|
||||
.build();
|
||||
|
||||
public final static EasyMessageList NOT_STARTED = EasyMessageList.builder()
|
||||
.contents("&f该物品目前还到可使用的时间,请在 &c%(time) &f后使用~")
|
||||
.params("time")
|
||||
.build();
|
||||
|
||||
public final static EasyMessageList EXPIRED = EasyMessageList.builder()
|
||||
.contents("&c&l抱歉!&f由于该物品已过最后使用期限,故无法继续使用。")
|
||||
.params("time")
|
||||
.build();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
package cc.carm.plugin.scriptitems.database;
|
||||
|
||||
import cc.carm.lib.easyplugin.configuration.values.ConfigValue;
|
||||
|
||||
public class DBConfiguration {
|
||||
|
||||
protected static final ConfigValue<String> DRIVER_NAME = new ConfigValue<>(
|
||||
"log-storage.database.driver", String.class,
|
||||
"com.mysql.cj.jdbc.Driver"
|
||||
);
|
||||
|
||||
protected static final ConfigValue<String> HOST = new ConfigValue<>(
|
||||
"log-storage.database.host", String.class,
|
||||
"127.0.0.1"
|
||||
);
|
||||
|
||||
protected static final ConfigValue<Integer> PORT = new ConfigValue<>(
|
||||
"log-storage.database.port", Integer.class,
|
||||
3306
|
||||
);
|
||||
|
||||
protected static final ConfigValue<String> DATABASE = new ConfigValue<>(
|
||||
"log-storage.database.database", String.class,
|
||||
"minecraft"
|
||||
);
|
||||
|
||||
protected static final ConfigValue<String> USERNAME = new ConfigValue<>(
|
||||
"log-storage.database.username", String.class,
|
||||
"root"
|
||||
);
|
||||
|
||||
protected static final ConfigValue<String> PASSWORD = new ConfigValue<>(
|
||||
"log-storage.database.password", String.class,
|
||||
"password"
|
||||
);
|
||||
|
||||
protected static final ConfigValue<String> EXTRA_SETTINGS = new ConfigValue<>(
|
||||
"log-storage.database.extra", String.class,
|
||||
"?useSSL=false"
|
||||
);
|
||||
|
||||
protected static String buildJDBC() {
|
||||
return String.format("jdbc:mysql://%s:%s/%s%s",
|
||||
HOST.get(), PORT.get(), DATABASE.get(), EXTRA_SETTINGS.get()
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
package cc.carm.plugin.scriptitems.database;
|
||||
|
||||
import cc.carm.lib.easyplugin.configuration.values.ConfigValue;
|
||||
|
||||
public class DBTables {
|
||||
|
||||
/**
|
||||
* 物品发放记录表
|
||||
* 用于记录每个物品的发放情况,包含发放时间,发放人,发放数量以及发放给了谁。
|
||||
*/
|
||||
public static class GiveTable {
|
||||
|
||||
protected static final ConfigValue<String> TABLE_NAME = new ConfigValue<>(
|
||||
"log-storage.database.tables.give", String.class,
|
||||
"log_item_give"
|
||||
);
|
||||
|
||||
protected static final String[] TABLE_COLUMNS = new String[]{
|
||||
"`id` INT UNSIGNED NOT NULL AUTO_INCREMENT UNIQUE KEY",
|
||||
"`uuid` VARCHAR(36) NOT NULL PRIMARY KEY", // ItemUUID
|
||||
"`settings` VARCHAR(36) NOT NULL", // 该物品配置对应的Identifier
|
||||
"`operator` VARCHAR(36)", "`operator_name` VARCHAR(32)", // 发放人的相关信息
|
||||
"`receiver` VARCHAR(36)", "`receiver_name` VARCHAR(32)", // 接受者的相关信息
|
||||
"`amount` INT UNSIGNED NOT NULL DEFAULT 1", // 同uuid物品的发放数量
|
||||
"`time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP" // 发放时间
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 物品拿取记录表
|
||||
* 改表用于记录物品的使用情况,即谁在什么时候使用了哪个物品,以及领取时任务的执行情况。
|
||||
* 请注意:只有在发生物品拿取(即 take action )事件时才会记录!
|
||||
*/
|
||||
public static class TakeTable {
|
||||
|
||||
protected static final ConfigValue<String> TABLE_NAME = new ConfigValue<>(
|
||||
"log-storage.database.tables.received", String.class,
|
||||
"log_item_received"
|
||||
);
|
||||
|
||||
protected static final String[] TABLE_COLUMNS = new String[]{
|
||||
"`id` INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY",
|
||||
"`uuid` VARCHAR(36) NOT NULL", // ItemUUID
|
||||
"`receiver` VARCHAR(36)", "`receiver_name` VARCHAR(32)", // 接受者的相关信息
|
||||
"`result` TINYINT(2) NOT NULL DEFAULT 0",// 领取结果
|
||||
"`time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP",
|
||||
"INDEX `item`(`uuid`)"
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
package cc.carm.plugin.scriptitems.database;
|
||||
|
||||
import cc.carm.lib.easysql.EasySQL;
|
||||
import cc.carm.lib.easysql.api.SQLManager;
|
||||
import cc.carm.plugin.scriptitems.Main;
|
||||
import cc.carm.plugin.scriptitems.util.DatabaseTable;
|
||||
|
||||
import java.sql.SQLException;
|
||||
|
||||
public class DataManager {
|
||||
private SQLManager sqlManager;
|
||||
|
||||
private DatabaseTable givenTable;
|
||||
private DatabaseTable receivedTable;
|
||||
|
||||
public boolean initialize() {
|
||||
try {
|
||||
Main.info(" 尝试连接到数据库...");
|
||||
this.sqlManager = EasySQL.createManager(
|
||||
DBConfiguration.DRIVER_NAME.get(), DBConfiguration.buildJDBC(),
|
||||
DBConfiguration.USERNAME.get(), DBConfiguration.PASSWORD.get()
|
||||
);
|
||||
this.sqlManager.setDebugMode(() -> Main.getInstance().isDebugging());
|
||||
} catch (Exception exception) {
|
||||
Main.severe("无法连接到数据库,请检查配置文件。");
|
||||
exception.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
Main.info(" 创建插件记录所需表...");
|
||||
|
||||
this.givenTable = new DatabaseTable(DBTables.GiveTable.TABLE_NAME.get(), DBTables.GiveTable.TABLE_COLUMNS);
|
||||
this.receivedTable = new DatabaseTable(DBTables.TakeTable.TABLE_NAME.get(), DBTables.TakeTable.TABLE_COLUMNS);
|
||||
|
||||
this.givenTable.createTable(this.sqlManager);
|
||||
this.receivedTable.createTable(this.sqlManager);
|
||||
|
||||
} catch (SQLException exception) {
|
||||
Main.severe("无法创建插件所需的表,请检查数据库权限。");
|
||||
exception.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public void shutdown() {
|
||||
Main.info(" 关闭数据库连接...");
|
||||
EasySQL.shutdownManager(getSQLManager());
|
||||
this.sqlManager = null;
|
||||
}
|
||||
|
||||
public SQLManager getSQLManager() {
|
||||
return sqlManager;
|
||||
}
|
||||
|
||||
public DatabaseTable getGivenTable() {
|
||||
return givenTable;
|
||||
}
|
||||
|
||||
public DatabaseTable getReceivedTable() {
|
||||
return receivedTable;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
package cc.carm.plugin.scriptitems.hooker;
|
||||
|
||||
import cc.carm.lib.githubreleases4j.GithubReleases4J;
|
||||
|
||||
import java.util.logging.Logger;
|
||||
|
||||
|
||||
public class GHUpdateChecker {
|
||||
|
||||
private final Logger logger;
|
||||
private final String owner;
|
||||
private final String repo;
|
||||
|
||||
public GHUpdateChecker(Logger logger, String owner, String repo) {
|
||||
this.logger = logger;
|
||||
this.owner = owner;
|
||||
this.repo = repo;
|
||||
}
|
||||
|
||||
public void checkUpdate(String currentVersion) {
|
||||
Integer behindVersions = GithubReleases4J.getVersionBehind(owner, repo, currentVersion);
|
||||
String downloadURL = GithubReleases4J.getReleasesURL(owner, repo);
|
||||
if (behindVersions == null) {
|
||||
logger.severe("检查更新失败,请您定期查看插件是否更新,避免安全问题。");
|
||||
logger.severe("下载地址 " + downloadURL);
|
||||
} else if (behindVersions == 0) {
|
||||
logger.info("检查完成,当前已是最新版本。");
|
||||
} else if (behindVersions > 0) {
|
||||
logger.info("发现新版本! 目前已落后 " + behindVersions + " 个版本。");
|
||||
logger.info("最新版下载地址 " + downloadURL);
|
||||
} else {
|
||||
logger.severe("检查更新失败! 当前版本未知,请您使用原生版本以避免安全问题。");
|
||||
logger.severe("最新版下载地址 " + downloadURL);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
package cc.carm.plugin.scriptitems.item;
|
||||
|
||||
import org.bukkit.entity.Player;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public class ItemAction {
|
||||
|
||||
@NotNull ItemActionType type;
|
||||
@Nullable String actionContent;
|
||||
|
||||
public ItemAction(@NotNull ItemActionType type, @Nullable String actionContent) {
|
||||
this.type = type;
|
||||
this.actionContent = actionContent;
|
||||
}
|
||||
|
||||
public @NotNull ItemActionType getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public @Nullable String getActionContent() {
|
||||
return actionContent;
|
||||
}
|
||||
|
||||
public boolean execute(Player player) {
|
||||
return getType().execute(player, getActionContent());
|
||||
}
|
||||
|
||||
public static @Nullable ItemAction read(@Nullable String actionString) {
|
||||
if (actionString == null) return null;
|
||||
int prefixStart = actionString.indexOf("[");
|
||||
int prefixEnd = actionString.indexOf("]");
|
||||
if (prefixStart < 0 || prefixEnd < 0) return null;
|
||||
|
||||
String prefix = actionString.substring(prefixStart + 1, prefixEnd);
|
||||
ItemActionType actionType = ItemActionType.read(prefix);
|
||||
if (actionType == null) return null;
|
||||
|
||||
return new ItemAction(actionType, actionString.substring(prefixEnd + 1).trim());
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
package cc.carm.plugin.scriptitems.item;
|
||||
|
||||
import org.bukkit.entity.Player;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class ItemActionGroup {
|
||||
|
||||
|
||||
List<ItemAction> actions;
|
||||
|
||||
public ItemActionGroup(List<ItemAction> actions) {
|
||||
this.actions = actions;
|
||||
}
|
||||
|
||||
public void execute(Player player) {
|
||||
actions.forEach(action -> action.execute(player));
|
||||
}
|
||||
|
||||
public static @NotNull ItemActionGroup read(@NotNull List<String> actionsString) {
|
||||
List<ItemAction> actions = actionsString.stream()
|
||||
.map(ItemAction::read).filter(Objects::nonNull).collect(Collectors.toList());
|
||||
return new ItemActionGroup(actions);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,121 @@
|
||||
package cc.carm.plugin.scriptitems.item;
|
||||
|
||||
import cc.carm.lib.easyplugin.utils.MessageUtils;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.Sound;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.function.BiFunction;
|
||||
|
||||
public enum ItemActionType {
|
||||
|
||||
/**
|
||||
* 以玩家聊天的形式执行
|
||||
* 若内容以 “/" 开头,则会以玩家身份执行命令。
|
||||
*/
|
||||
CHAT((player, string) -> {
|
||||
if (string == null) return true; //没有需要执行的
|
||||
List<String> finalContents = MessageUtils.setPlaceholders(player, Collections.singletonList(string));
|
||||
boolean success = true;
|
||||
for (String finalContent : finalContents) {
|
||||
try {
|
||||
player.chat(finalContent);
|
||||
} catch (Exception ex) {
|
||||
success = false;
|
||||
}
|
||||
}
|
||||
return success;
|
||||
}),
|
||||
|
||||
/**
|
||||
* 以后台的形式执行指令
|
||||
* 指令内容不需要以“/”开头。
|
||||
*/
|
||||
CONSOLE((player, string) -> {
|
||||
if (string == null) return true;
|
||||
List<String> finalCommands = MessageUtils.setPlaceholders(player, Collections.singletonList(string));
|
||||
boolean success = true;
|
||||
for (String finalCommand : finalCommands) {
|
||||
try {
|
||||
Bukkit.dispatchCommand(Bukkit.getConsoleSender(), finalCommand);
|
||||
} catch (Exception ex) {
|
||||
success = false;
|
||||
}
|
||||
}
|
||||
return success;
|
||||
}),
|
||||
|
||||
/**
|
||||
* 向玩家发送消息。
|
||||
*/
|
||||
MESSAGE((sender, messages) -> {
|
||||
MessageUtils.send(sender, messages);
|
||||
return true;
|
||||
}),
|
||||
|
||||
/**
|
||||
* 向玩家发送声音。
|
||||
* 允许配置音量与音调
|
||||
* <ul>
|
||||
* <li>SOUND_NAME</li>
|
||||
* <li>SOUND_NAME:VOLUME</li>
|
||||
* <li>SOUND_NAME:VOLUME:PITCH</li>
|
||||
* </ul>
|
||||
*/
|
||||
SOUND((player, string) -> {
|
||||
if (string == null) return true;
|
||||
try {
|
||||
String[] args = string.contains(":") ? string.split(":") : new String[]{string};
|
||||
Sound sound = Arrays.stream(Sound.values())
|
||||
.filter(s -> s.name().equals(args[0]))
|
||||
.findFirst().orElse(null);
|
||||
|
||||
if (sound == null) return true;
|
||||
float volume = args.length > 1 ? Float.parseFloat(args[1]) : 1F;
|
||||
float pitch = args.length > 2 ? Float.parseFloat(args[2]) : 1F;
|
||||
|
||||
player.playSound(player.getLocation(), sound, volume, pitch);
|
||||
} catch (Exception ignored) {
|
||||
}
|
||||
return true; // 声音放不放无关紧要
|
||||
}),
|
||||
|
||||
/**
|
||||
* 拿取玩家手上的一个物品
|
||||
*/
|
||||
TAKE((player, string) -> {
|
||||
if (player.getInventory().getItemInMainHand().getType() != Material.AIR) {
|
||||
int current = player.getInventory().getItemInMainHand().getAmount();
|
||||
player.getInventory().getItemInMainHand().setAmount(current - 1);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
|
||||
BiFunction<@NotNull Player, @Nullable String, @NotNull Boolean> executor;
|
||||
|
||||
ItemActionType(BiFunction<@NotNull Player, @Nullable String, @NotNull Boolean> executor) {
|
||||
this.executor = executor;
|
||||
}
|
||||
|
||||
public BiFunction<Player, String, Boolean> getExecutor() {
|
||||
return executor;
|
||||
}
|
||||
|
||||
public boolean execute(@NotNull Player player, @Nullable String content) {
|
||||
return getExecutor().apply(player, content);
|
||||
}
|
||||
|
||||
public static ItemActionType read(String string) {
|
||||
return Arrays.stream(ItemActionType.values())
|
||||
.filter(action -> action.name().equalsIgnoreCase(string))
|
||||
.findFirst().orElse(null);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package cc.carm.plugin.scriptitems.item;
|
||||
|
||||
public enum ItemExecuteResult {
|
||||
|
||||
SUCCESS(0),
|
||||
FAILED(1),
|
||||
|
||||
;
|
||||
|
||||
int id;
|
||||
|
||||
ItemExecuteResult(int id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public int getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,98 @@
|
||||
package cc.carm.plugin.scriptitems.item;
|
||||
|
||||
import cc.carm.lib.easyplugin.configuration.language.EasyMessageList;
|
||||
import cc.carm.lib.easysql.api.util.TimeDateUtils;
|
||||
import cc.carm.plugin.scriptitems.configuration.PluginMessages;
|
||||
import org.bukkit.configuration.ConfigurationSection;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
public class ItemRestrictions {
|
||||
|
||||
long startTime;
|
||||
long endTime;
|
||||
|
||||
public ItemRestrictions() {
|
||||
this(-1, -1);
|
||||
}
|
||||
|
||||
public ItemRestrictions(long startTime, long endTime) {
|
||||
this.startTime = startTime;
|
||||
this.endTime = endTime;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return 限定的开始时间,-1表示不限定。
|
||||
*/
|
||||
public long getStartTime() {
|
||||
return startTime;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return 限定的结束时间,-1表示不限定。
|
||||
*/
|
||||
public long getEndTime() {
|
||||
return endTime;
|
||||
}
|
||||
|
||||
public CheckResult check() {
|
||||
if (getStartTime() < 0 && getEndTime() < 0) return CheckResult.AVAILABLE;
|
||||
if (getStartTime() > 0 && getEndTime() > 0 && getStartTime() > getEndTime()) return CheckResult.INVALID;
|
||||
if (getStartTime() > 0 && getStartTime() > System.currentTimeMillis()) return CheckResult.NOT_STARTED;
|
||||
if (getEndTime() > 0 && getEndTime() < System.currentTimeMillis()) return CheckResult.EXPIRED;
|
||||
return CheckResult.AVAILABLE;
|
||||
}
|
||||
|
||||
public enum CheckResult {
|
||||
|
||||
AVAILABLE(() -> null, (res) -> null),
|
||||
|
||||
INVALID(() -> PluginMessages.Restrictions.INVALID, (res) -> null),
|
||||
|
||||
NOT_STARTED(
|
||||
() -> PluginMessages.Restrictions.NOT_STARTED,
|
||||
(res) -> new Object[]{TimeDateUtils.getTimeString(res.getStartTime())}
|
||||
),
|
||||
|
||||
EXPIRED(
|
||||
() -> PluginMessages.Restrictions.EXPIRED,
|
||||
(res) -> new Object[]{TimeDateUtils.getTimeString(res.getEndTime())}
|
||||
);
|
||||
|
||||
Supplier<@Nullable EasyMessageList> message;
|
||||
Function<@NotNull ItemRestrictions, Object[]> params;
|
||||
|
||||
CheckResult(@NotNull Supplier<@Nullable EasyMessageList> message,
|
||||
@NotNull Function<@NotNull ItemRestrictions, @Nullable Object[]> params) {
|
||||
this.message = message;
|
||||
this.params = params;
|
||||
}
|
||||
|
||||
public Supplier<EasyMessageList> getMessage() {
|
||||
return message;
|
||||
}
|
||||
|
||||
public void send(Player player, ItemRestrictions restrictions) {
|
||||
Object[] params = this.params.apply(restrictions);
|
||||
if (params == null) {
|
||||
getMessage().get().send(player);
|
||||
} else {
|
||||
getMessage().get().send(player, params);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static @NotNull ItemRestrictions read(@Nullable ConfigurationSection section) {
|
||||
if (section == null) return new ItemRestrictions();
|
||||
return new ItemRestrictions(
|
||||
TimeDateUtils.parseTimeMillis(section.getString("time.start")),
|
||||
TimeDateUtils.parseTimeMillis(section.getString("time.end"))
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,112 @@
|
||||
package cc.carm.plugin.scriptitems.item;
|
||||
|
||||
import cc.carm.plugin.scriptitems.ScriptItemsAPI;
|
||||
import cc.carm.plugin.scriptitems.manager.ConfigManager;
|
||||
import org.bukkit.configuration.file.FileConfiguration;
|
||||
import org.bukkit.configuration.file.YamlConfiguration;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
public class ItemSettings {
|
||||
|
||||
protected final @NotNull String identifier;
|
||||
@Nullable String name;
|
||||
|
||||
@Nullable ItemStackConfig item;
|
||||
@NotNull ItemRestrictions restrictions;
|
||||
|
||||
@NotNull Map<String, String> permissions;
|
||||
@NotNull Map<String, ItemActionGroup> actions;
|
||||
|
||||
public ItemSettings(@NotNull String identifier, @Nullable String name,
|
||||
@Nullable ItemStackConfig item, @NotNull ItemRestrictions restrictions,
|
||||
@NotNull Map<String, String> permissions,
|
||||
@NotNull Map<String, ItemActionGroup> actions) {
|
||||
this.identifier = identifier;
|
||||
this.name = name;
|
||||
this.item = item;
|
||||
this.restrictions = restrictions;
|
||||
this.permissions = permissions;
|
||||
this.actions = actions;
|
||||
}
|
||||
|
||||
public @NotNull String getIdentifier() {
|
||||
return identifier;
|
||||
}
|
||||
|
||||
public @Nullable String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public ItemStackConfig getItemConfig() {
|
||||
return item;
|
||||
}
|
||||
|
||||
public @Nullable ItemStack generateItem(int amount) {
|
||||
ItemStackConfig config = getItemConfig();
|
||||
ItemStack originalItem = config == null ? null : config.getItemStack(amount);
|
||||
if (originalItem == null) return null;
|
||||
return applyItem(originalItem);
|
||||
}
|
||||
|
||||
public @Nullable ItemStack generateItem() {
|
||||
return generateItem(1);
|
||||
}
|
||||
|
||||
public @NotNull Map<String, String> getPermissions() {
|
||||
return this.permissions;
|
||||
}
|
||||
|
||||
|
||||
public @NotNull ItemRestrictions getRestrictions() {
|
||||
return restrictions;
|
||||
}
|
||||
|
||||
public ItemRestrictions.CheckResult checkRestrictions() {
|
||||
return getRestrictions().check();
|
||||
}
|
||||
|
||||
public @NotNull Map<String, ItemActionGroup> getActions() {
|
||||
return this.actions;
|
||||
}
|
||||
|
||||
public @Nullable ItemActionGroup getDefaultActions() {
|
||||
return getActions().get("default");
|
||||
}
|
||||
|
||||
public @Nullable ItemActionGroup getPlayerActions(@NotNull Player player) {
|
||||
@NotNull String actionGroup = getPermissions().entrySet().stream()
|
||||
.filter(entry -> player.hasPermission(entry.getValue()))
|
||||
.map(Map.Entry::getKey).findFirst().orElse("default");
|
||||
|
||||
return getActions().get(actionGroup);
|
||||
}
|
||||
|
||||
public @NotNull ItemStack applyItem(ItemStack originalItem) {
|
||||
return ScriptItemsAPI.getItemsManager().applyTag(originalItem, identifier, UUID.randomUUID());
|
||||
}
|
||||
|
||||
public static @NotNull ItemSettings load(@NotNull File file) throws Exception {
|
||||
return load(YamlConfiguration.loadConfiguration(file));
|
||||
}
|
||||
|
||||
public static @NotNull ItemSettings load(@NotNull FileConfiguration config) throws Exception {
|
||||
String identifier = config.getString("identifier");
|
||||
if (identifier == null) throw new Exception("identifier not provided.");
|
||||
return new ItemSettings(
|
||||
identifier, config.getString("name"),
|
||||
config.isItemStack("item") ?
|
||||
ItemStackConfig.create(config.getItemStack("item")) :
|
||||
ItemStackConfig.read(config.getConfigurationSection("item")),
|
||||
ItemRestrictions.read(config.getConfigurationSection("restrictions")),
|
||||
ConfigManager.readStringMap(config.getConfigurationSection("permissions"), (s -> s)),
|
||||
ConfigManager.readListMap(config.getConfigurationSection("actions"), ItemActionGroup::read)
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
package cc.carm.plugin.scriptitems.item;
|
||||
|
||||
import cc.carm.lib.easyplugin.utils.ColorParser;
|
||||
import cc.carm.lib.easyplugin.utils.ItemStackFactory;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.configuration.ConfigurationSection;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
@SuppressWarnings("UnusedReturnValue")
|
||||
public class ItemStackConfig {
|
||||
|
||||
protected @Nullable ItemStack item;
|
||||
|
||||
public ItemStackConfig() {
|
||||
}
|
||||
|
||||
public ItemStackConfig(@Nullable Material material, @Nullable String displayName, @Nullable List<String> lore) {
|
||||
if (material == null) {
|
||||
this.item = null;
|
||||
return;
|
||||
}
|
||||
|
||||
ItemStackFactory factory = new ItemStackFactory(material);
|
||||
if (displayName != null) factory.setDisplayName(ColorParser.parse(displayName));
|
||||
if (lore != null && !lore.isEmpty()) factory.setLore(lore);
|
||||
this.item = factory.toItemStack();
|
||||
}
|
||||
|
||||
public ItemStackConfig(@Nullable ItemStack item) {
|
||||
this.item = item;
|
||||
}
|
||||
|
||||
public @Nullable ItemStack getItemStack(int amount) {
|
||||
if (amount <= 0 || item == null) return null;
|
||||
ItemStack item = this.item.clone();
|
||||
item.setAmount(amount);
|
||||
return item;
|
||||
}
|
||||
|
||||
public @Nullable ItemStack getItemStack() {
|
||||
return getItemStack(1);
|
||||
}
|
||||
|
||||
public static @Nullable ItemStackConfig read(@Nullable ConfigurationSection section) {
|
||||
if (section == null) return null;
|
||||
return new ItemStackConfig(
|
||||
Optional.ofNullable(section.getString("type")).map(Material::matchMaterial).orElse(null),
|
||||
section.getString("name"),
|
||||
section.getStringList("lore")
|
||||
);
|
||||
}
|
||||
|
||||
public static @Nullable ItemStackConfig create(@Nullable ItemStack item) {
|
||||
if (item == null) return null;
|
||||
return new ItemStackConfig(item);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
package cc.carm.plugin.scriptitems.item;
|
||||
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
public class ScriptItem {
|
||||
|
||||
@NotNull UUID uuid;
|
||||
|
||||
@NotNull ItemSettings settings;
|
||||
@NotNull ItemStack itemStack;
|
||||
|
||||
public ScriptItem(@NotNull UUID uuid, @NotNull ItemSettings settings, @NotNull ItemStack itemStack) {
|
||||
this.uuid = uuid;
|
||||
this.settings = settings;
|
||||
this.itemStack = itemStack;
|
||||
}
|
||||
|
||||
public @NotNull UUID getUUID() {
|
||||
return uuid;
|
||||
}
|
||||
|
||||
public @NotNull ItemSettings getSettings() {
|
||||
return settings;
|
||||
}
|
||||
|
||||
public @NotNull ItemStack getItemStack() {
|
||||
return itemStack;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,134 @@
|
||||
package cc.carm.plugin.scriptitems.listener;
|
||||
|
||||
import cc.carm.plugin.scriptitems.ScriptItemsAPI;
|
||||
import cc.carm.plugin.scriptitems.configuration.PluginConfig;
|
||||
import cc.carm.plugin.scriptitems.configuration.PluginMessages;
|
||||
import cc.carm.plugin.scriptitems.item.ScriptItem;
|
||||
import cc.carm.plugin.scriptitems.item.ItemActionGroup;
|
||||
import cc.carm.plugin.scriptitems.item.ItemRestrictions;
|
||||
import cc.carm.plugin.scriptitems.item.ItemSettings;
|
||||
import org.bukkit.entity.EntityType;
|
||||
import org.bukkit.entity.Item;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.block.Action;
|
||||
import org.bukkit.event.entity.EntityDamageEvent;
|
||||
import org.bukkit.event.entity.EntityPickupItemEvent;
|
||||
import org.bukkit.event.inventory.CraftItemEvent;
|
||||
import org.bukkit.event.player.PlayerInteractEvent;
|
||||
import org.bukkit.event.player.PlayerQuitEvent;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.UUID;
|
||||
|
||||
public class ItemListener implements Listener {
|
||||
|
||||
private final HashMap<UUID, Long> clickTime = new HashMap<>();
|
||||
|
||||
/**
|
||||
* 监听玩家点击,并执行物品对应的操作。
|
||||
*
|
||||
* @param event 玩家点击事件
|
||||
*/
|
||||
@EventHandler
|
||||
public void onClick(PlayerInteractEvent event) {
|
||||
if (event.getAction() != Action.RIGHT_CLICK_AIR && event.getAction() != Action.RIGHT_CLICK_BLOCK) return;
|
||||
|
||||
ItemStack item = event.getPlayer().getInventory().getItemInMainHand();
|
||||
ScriptItem scriptItem = ScriptItemsAPI.getItemsManager().parseItem(item);
|
||||
if (scriptItem == null) return;
|
||||
event.setCancelled(true); // 阻止事件执行
|
||||
|
||||
Player player = event.getPlayer();
|
||||
if (!isClickable(player.getUniqueId())) {
|
||||
PluginMessages.COOLDOWN.send(player, getRemainSeconds(player.getUniqueId()));
|
||||
return;
|
||||
}
|
||||
updateTime(player.getUniqueId());
|
||||
|
||||
ItemSettings settings = scriptItem.getSettings();
|
||||
|
||||
// 检查物品的相关使用限制是否满足要求
|
||||
ItemRestrictions.CheckResult result = settings.getRestrictions().check();
|
||||
if (result != ItemRestrictions.CheckResult.AVAILABLE) {
|
||||
result.send(player, settings.getRestrictions()); // 发送提示
|
||||
return;
|
||||
}
|
||||
|
||||
// 获取玩家的对应操作组
|
||||
ItemActionGroup actions = settings.getPlayerActions(player);
|
||||
if (actions == null) return;
|
||||
|
||||
actions.execute(player);
|
||||
}
|
||||
|
||||
/**
|
||||
* 监听玩家合成,阻止玩家将指令物品合成浪费掉。
|
||||
*
|
||||
* @param event 合成事件
|
||||
*/
|
||||
@EventHandler
|
||||
public void onCraft(CraftItemEvent event) {
|
||||
boolean shouldCancel = Arrays.stream(event.getInventory().getMatrix())
|
||||
.anyMatch(matrix -> ScriptItemsAPI.getItemsManager().isScriptItem(matrix));
|
||||
|
||||
if (shouldCancel) event.setCancelled(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* 阻止非玩家捡起指令物品
|
||||
*
|
||||
* @param event 捡起事件
|
||||
*/
|
||||
@EventHandler
|
||||
public void onPickup(EntityPickupItemEvent event) {
|
||||
if (event.getEntity().getType() == EntityType.PLAYER) return;
|
||||
|
||||
ItemStack item = event.getItem().getItemStack();
|
||||
if (ScriptItemsAPI.getItemsManager().isScriptItem(item)) {
|
||||
event.setCancelled(true);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 阻止物品被烧掉
|
||||
*
|
||||
* @param event 伤害事件
|
||||
*/
|
||||
@EventHandler
|
||||
public void onEntityDamage(EntityDamageEvent event) {
|
||||
if (event.getEntity().getType() != EntityType.DROPPED_ITEM) return;
|
||||
Item droppedItem = ((org.bukkit.entity.Item) event.getEntity());
|
||||
ItemStack item = droppedItem.getItemStack();
|
||||
if (ScriptItemsAPI.getItemsManager().isScriptItem(item)) {
|
||||
event.setCancelled(true);
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onLeave(PlayerQuitEvent event) {
|
||||
this.clickTime.remove(event.getPlayer().getUniqueId());
|
||||
}
|
||||
|
||||
public void updateTime(UUID uuid) {
|
||||
this.clickTime.put(uuid, System.currentTimeMillis());
|
||||
}
|
||||
|
||||
public boolean isClickable(UUID uuid) {
|
||||
return !PluginConfig.CoolDown.ENABLE.get()
|
||||
|| !this.clickTime.containsKey(uuid)
|
||||
|| System.currentTimeMillis() - this.clickTime.get(uuid) > PluginConfig.CoolDown.TIME.get();
|
||||
}
|
||||
|
||||
public int getRemainSeconds(UUID uuid) {
|
||||
if (!this.clickTime.containsKey(uuid)) return 0;
|
||||
if (!PluginConfig.CoolDown.ENABLE.get()) return 0;
|
||||
long start = this.clickTime.get(uuid);
|
||||
return (int) ((PluginConfig.CoolDown.TIME.get() - (System.currentTimeMillis() - start)) / 1000) + 1;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,100 @@
|
||||
package cc.carm.plugin.scriptitems.manager;
|
||||
|
||||
import cc.carm.lib.easyplugin.configuration.file.FileConfig;
|
||||
import cc.carm.lib.easyplugin.configuration.language.MessagesConfig;
|
||||
import cc.carm.lib.easyplugin.configuration.language.MessagesInitializer;
|
||||
import cc.carm.plugin.scriptitems.configuration.PluginMessages;
|
||||
import org.bukkit.configuration.ConfigurationSection;
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.function.Function;
|
||||
|
||||
public class ConfigManager {
|
||||
|
||||
private final JavaPlugin plugin;
|
||||
|
||||
private FileConfig config;
|
||||
private MessagesConfig messageConfig;
|
||||
|
||||
public ConfigManager(JavaPlugin plugin) {
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
public boolean initConfig() {
|
||||
try {
|
||||
this.config = new FileConfig(plugin);
|
||||
this.messageConfig = new MessagesConfig(plugin);
|
||||
|
||||
FileConfig.pluginConfiguration = () -> config;
|
||||
FileConfig.messageConfiguration = () -> messageConfig;
|
||||
|
||||
MessagesInitializer.initialize(messageConfig, PluginMessages.class);
|
||||
|
||||
return true;
|
||||
} catch (IOException e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public FileConfig getPluginConfig() {
|
||||
return config;
|
||||
}
|
||||
|
||||
public FileConfig getMessageConfig() {
|
||||
return messageConfig;
|
||||
}
|
||||
|
||||
public void reload() throws Exception {
|
||||
getPluginConfig().reload();
|
||||
getMessageConfig().reload();
|
||||
}
|
||||
|
||||
public void saveConfig() throws Exception {
|
||||
getPluginConfig().save();
|
||||
getMessageConfig().save();
|
||||
}
|
||||
|
||||
public static <V> Map<String, V> readStringMap(@Nullable ConfigurationSection section,
|
||||
@NotNull Function<String, V> valueCast) {
|
||||
if (section == null) return new LinkedHashMap<>();
|
||||
Map<String, V> result = new LinkedHashMap<>();
|
||||
for (String key : section.getKeys(false)) {
|
||||
V finalValue = valueCast.apply(section.getString(key));
|
||||
if (finalValue != null) result.put(key, finalValue);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public static <V> Map<String, V> readSectionMap(@Nullable ConfigurationSection section,
|
||||
@NotNull Function<ConfigurationSection, V> valueCast) {
|
||||
if (section == null) return new LinkedHashMap<>();
|
||||
Map<String, V> result = new LinkedHashMap<>();
|
||||
for (String key : section.getKeys(false)) {
|
||||
if (!section.isConfigurationSection(key)) continue;
|
||||
V finalValue = valueCast.apply(section.getConfigurationSection(key));
|
||||
if (finalValue != null) result.put(key, finalValue);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
public static <V> Map<String, V> readListMap(@Nullable ConfigurationSection section,
|
||||
@NotNull Function<@NotNull List<String>, V> valueCast) {
|
||||
if (section == null) return new LinkedHashMap<>();
|
||||
Map<String, V> result = new LinkedHashMap<>();
|
||||
for (String key : section.getKeys(false)) {
|
||||
if (!section.isList(key)) continue;
|
||||
V finalValue = valueCast.apply(section.getStringList(key));
|
||||
if (finalValue != null) result.put(key, finalValue);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,128 @@
|
||||
package cc.carm.plugin.scriptitems.manager;
|
||||
|
||||
import cc.carm.plugin.scriptitems.Main;
|
||||
import cc.carm.plugin.scriptitems.item.ItemSettings;
|
||||
import cc.carm.plugin.scriptitems.item.ScriptItem;
|
||||
import cc.carm.plugin.scriptitems.util.JarResourceUtils;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.NamespacedKey;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.inventory.meta.ItemMeta;
|
||||
import org.bukkit.inventory.meta.tags.CustomItemTagContainer;
|
||||
import org.bukkit.inventory.meta.tags.ItemTagType;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.annotations.Unmodifiable;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class ItemsManager {
|
||||
|
||||
private static final String FOLDER_NAME = "items";
|
||||
|
||||
public HashMap<String, ItemSettings> items = new HashMap<>();
|
||||
|
||||
protected NamespacedKey idKey;
|
||||
protected NamespacedKey uuidKey;
|
||||
|
||||
public void initialize() {
|
||||
this.idKey = new NamespacedKey(Main.getInstance(), "id");
|
||||
this.uuidKey = new NamespacedKey(Main.getInstance(), "uuid");
|
||||
loadItems();
|
||||
Main.info("成功加载了 " + items.size() + " 个脚本物品。");
|
||||
}
|
||||
|
||||
public void loadItems() {
|
||||
File prefixDataFolder = getStorageFolder();
|
||||
if (!prefixDataFolder.isDirectory() || !prefixDataFolder.exists()) {
|
||||
try {
|
||||
JarResourceUtils.copyFolderFromJar(
|
||||
FOLDER_NAME, Main.getInstance().getDataFolder(),
|
||||
JarResourceUtils.CopyOption.COPY_IF_NOT_EXIST
|
||||
);
|
||||
} catch (Exception ex) {
|
||||
boolean success = prefixDataFolder.mkdirs();
|
||||
}
|
||||
}
|
||||
|
||||
String[] filesList = prefixDataFolder.list();
|
||||
if (filesList == null || filesList.length < 1) {
|
||||
Main.severe(" 配置文件夹中暂无任何物品,请检查。");
|
||||
Main.severe(" There's no configured items.");
|
||||
return;
|
||||
}
|
||||
|
||||
List<File> files = Arrays.stream(filesList)
|
||||
.map(s -> new File(prefixDataFolder, s))
|
||||
.filter(File::isFile)
|
||||
.collect(Collectors.toList());
|
||||
|
||||
HashMap<String, ItemSettings> dataItems = new HashMap<>();
|
||||
|
||||
if (files.size() > 0) {
|
||||
for (File file : files) {
|
||||
String fileName = file.getName();
|
||||
if (fileName.startsWith(".")) continue;
|
||||
try {
|
||||
ItemSettings item = ItemSettings.load(file);
|
||||
Main.info(" 完成物品加载 [#" + item.getIdentifier() + "] " + item.getName() + " (" + fileName + ")");
|
||||
dataItems.put(item.getIdentifier(), item);
|
||||
} catch (Exception ex) {
|
||||
Main.severe("在加载物品 " + file.getAbsolutePath() + " 时出错,请检查配置!");
|
||||
Main.severe("Error occurred when loading item #" + file.getAbsolutePath() + " !");
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
items = dataItems;
|
||||
}
|
||||
|
||||
private static File getStorageFolder() {
|
||||
return new File(Main.getInstance().getDataFolder(), FOLDER_NAME);
|
||||
}
|
||||
|
||||
@Unmodifiable
|
||||
public Map<String, ItemSettings> listItemSettings() {
|
||||
return ImmutableMap.copyOf(items);
|
||||
}
|
||||
|
||||
public @Nullable ItemSettings getItemSettings(@NotNull String identifier) {
|
||||
return items.get(identifier);
|
||||
}
|
||||
|
||||
public ItemStack applyTag(@NotNull ItemStack originalItem, String identifier, UUID uuid) {
|
||||
if (!originalItem.hasItemMeta()) return originalItem;
|
||||
ItemMeta meta = originalItem.getItemMeta();
|
||||
if (meta == null) return originalItem;
|
||||
CustomItemTagContainer container = meta.getCustomTagContainer();
|
||||
container.setCustomTag(idKey, ItemTagType.STRING, identifier);
|
||||
container.setCustomTag(uuidKey, ItemTagType.STRING, uuid.toString());
|
||||
originalItem.setItemMeta(meta);
|
||||
return originalItem;
|
||||
}
|
||||
|
||||
public @Nullable ScriptItem parseItem(@Nullable ItemStack item) {
|
||||
if (item == null || item.getType() == Material.AIR) return null;
|
||||
if (!item.hasItemMeta()) return null;
|
||||
ItemMeta meta = item.getItemMeta();
|
||||
if (meta == null) return null;
|
||||
CustomItemTagContainer container = meta.getCustomTagContainer();
|
||||
String settingsID = container.getCustomTag(this.idKey, ItemTagType.STRING);
|
||||
String itemUUID = container.getCustomTag(this.uuidKey, ItemTagType.STRING);
|
||||
if (settingsID == null || itemUUID == null) return null;
|
||||
ItemSettings settings = getItemSettings(settingsID);
|
||||
if (settings == null) return null;
|
||||
return new ScriptItem(UUID.fromString(itemUUID), settings, item);
|
||||
}
|
||||
|
||||
public boolean isScriptItem(ItemStack item) {
|
||||
return item.hasItemMeta() && item.getItemMeta() != null
|
||||
&& item.getItemMeta().getCustomTagContainer().hasCustomTag(idKey, ItemTagType.STRING);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
package cc.carm.plugin.scriptitems.util;
|
||||
|
||||
import cc.carm.lib.easysql.api.SQLManager;
|
||||
import cc.carm.lib.easysql.api.action.PreparedSQLUpdateAction;
|
||||
import cc.carm.lib.easysql.api.action.PreparedSQLUpdateBatchAction;
|
||||
import cc.carm.lib.easysql.api.builder.*;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.sql.SQLException;
|
||||
|
||||
public class DatabaseTable {
|
||||
|
||||
private final @NotNull String tableName;
|
||||
private final @NotNull String[] columns;
|
||||
|
||||
@Nullable String tableSettings;
|
||||
|
||||
public DatabaseTable(@NotNull String tableName, @NotNull String[] columns) {
|
||||
this(tableName, columns, null);
|
||||
}
|
||||
|
||||
public DatabaseTable(@NotNull String tableName, @NotNull String[] columns,
|
||||
@Nullable String tableSettings) {
|
||||
this.tableName = tableName;
|
||||
this.columns = columns;
|
||||
this.tableSettings = tableSettings;
|
||||
}
|
||||
|
||||
public @NotNull String getTableName() {
|
||||
return tableName;
|
||||
}
|
||||
|
||||
public @NotNull String[] getColumns() {
|
||||
return columns;
|
||||
}
|
||||
|
||||
public @Nullable String getTableSettings() {
|
||||
return tableSettings;
|
||||
}
|
||||
|
||||
public int createTable(SQLManager sqlManager) throws SQLException {
|
||||
TableCreateBuilder createAction = sqlManager.createTable(getTableName());
|
||||
createAction.setColumns(getColumns());
|
||||
if (getTableSettings() != null) createAction.setTableSettings(getTableSettings());
|
||||
return createAction.build().execute();
|
||||
}
|
||||
|
||||
public TableQueryBuilder createQuery(SQLManager sqlManager) {
|
||||
return sqlManager.createQuery().inTable(getTableName());
|
||||
}
|
||||
|
||||
public DeleteBuilder createDelete(SQLManager sqlManager) {
|
||||
return sqlManager.createDelete(getTableName());
|
||||
}
|
||||
|
||||
public UpdateBuilder createUpdate(SQLManager sqlManager) {
|
||||
return sqlManager.createUpdate(getTableName());
|
||||
}
|
||||
|
||||
public InsertBuilder<PreparedSQLUpdateAction> createInsert(SQLManager sqlManager) {
|
||||
return sqlManager.createInsert(getTableName());
|
||||
}
|
||||
|
||||
public InsertBuilder<PreparedSQLUpdateBatchAction> createInsertBatch(SQLManager sqlManager) {
|
||||
return sqlManager.createInsertBatch(getTableName());
|
||||
}
|
||||
|
||||
public ReplaceBuilder<PreparedSQLUpdateAction> createReplace(SQLManager sqlManager) {
|
||||
return sqlManager.createReplace(getTableName());
|
||||
}
|
||||
|
||||
public ReplaceBuilder<PreparedSQLUpdateBatchAction> createReplaceBatch(SQLManager sqlManager) {
|
||||
return sqlManager.createReplaceBatch(getTableName());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,106 @@
|
||||
package cc.carm.plugin.scriptitems.util;
|
||||
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.io.*;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Scanner;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipInputStream;
|
||||
|
||||
@SuppressWarnings("ResultOfMethodCallIgnored")
|
||||
public class JarResourceUtils {
|
||||
public static final char JAR_SEPARATOR = '/';
|
||||
|
||||
public static @Nullable String[] readResource(@Nullable InputStream resourceStream) {
|
||||
if (resourceStream == null) return null;
|
||||
try (Scanner scanner = new Scanner(resourceStream, StandardCharsets.UTF_8.name())) {
|
||||
List<String> contents = new ArrayList<>();
|
||||
while (scanner.hasNextLine()) {
|
||||
contents.add(scanner.nextLine());
|
||||
}
|
||||
return contents.toArray(new String[0]);
|
||||
} catch (Exception e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static void copyFolderFromJar(String folderName, File destFolder, CopyOption option)
|
||||
throws IOException {
|
||||
copyFolderFromJar(folderName, destFolder, option, null);
|
||||
}
|
||||
|
||||
public static void copyFolderFromJar(String folderName, File destFolder,
|
||||
CopyOption option, PathTrimmer trimmer) throws IOException {
|
||||
if (!destFolder.exists())
|
||||
destFolder.mkdirs();
|
||||
|
||||
byte[] buffer = new byte[1024];
|
||||
|
||||
File fullPath;
|
||||
String path = JarResourceUtils.class.getProtectionDomain().getCodeSource().getLocation().getPath();
|
||||
if (trimmer != null)
|
||||
path = trimmer.trim(path);
|
||||
try {
|
||||
if (!path.startsWith("file"))
|
||||
path = "file://" + path;
|
||||
|
||||
fullPath = new File(new URI(path));
|
||||
} catch (URISyntaxException e) {
|
||||
e.printStackTrace();
|
||||
return;
|
||||
}
|
||||
|
||||
ZipInputStream zis = new ZipInputStream(new FileInputStream(fullPath));
|
||||
|
||||
ZipEntry entry;
|
||||
while ((entry = zis.getNextEntry()) != null) {
|
||||
if (!entry.getName().startsWith(folderName + JAR_SEPARATOR))
|
||||
continue;
|
||||
|
||||
String fileName = entry.getName();
|
||||
|
||||
if (fileName.charAt(fileName.length() - 1) == JAR_SEPARATOR) {
|
||||
File file = new File(destFolder + File.separator + fileName);
|
||||
if (file.isFile()) {
|
||||
file.delete();
|
||||
}
|
||||
file.mkdirs();
|
||||
continue;
|
||||
}
|
||||
|
||||
File file = new File(destFolder + File.separator + fileName);
|
||||
if (option == CopyOption.COPY_IF_NOT_EXIST && file.exists())
|
||||
continue;
|
||||
|
||||
if (!file.getParentFile().exists())
|
||||
file.getParentFile().mkdirs();
|
||||
|
||||
if (!file.exists())
|
||||
file.createNewFile();
|
||||
FileOutputStream fos = new FileOutputStream(file);
|
||||
|
||||
int len;
|
||||
while ((len = zis.read(buffer)) > 0) {
|
||||
fos.write(buffer, 0, len);
|
||||
}
|
||||
fos.close();
|
||||
}
|
||||
|
||||
zis.closeEntry();
|
||||
zis.close();
|
||||
}
|
||||
|
||||
public enum CopyOption {
|
||||
COPY_IF_NOT_EXIST, REPLACE_IF_EXIST
|
||||
}
|
||||
|
||||
@FunctionalInterface
|
||||
public interface PathTrimmer {
|
||||
String trim(String original);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user