1
mirror of https://github.com/CarmJos/ScriptItems synced 2024-09-19 13:25:50 +00:00

feat(execute): 支持以OP身份执行命令

This commit is contained in:
Carm Jos 2023-02-07 22:29:52 +08:00
parent 0c56954402
commit 4f86daa541
35 changed files with 686 additions and 825 deletions

View File

@ -35,7 +35,7 @@ jobs:
run: |
mkdir artifacts
cp -vrf target/ artifacts/target/
cp -vrf asset/*.jar artifacts
cp -vrf .asset/*.jar artifacts
- name: "Upload artifact"
uses: actions/upload-artifact@v2

View File

@ -37,5 +37,5 @@ jobs:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
upload_url: ${{ github.event.release.upload_url }}
asset_path: asset/*.jar
asset_path: .asset/*.jar
asset_content_type: application/java-archive

View File

@ -14,17 +14,19 @@
脚本物品插件给予玩家可执行对应操作的物品基于EasyPlugin实现。
本插件由 [ArtStyle(艺式)](https://artstyle.wiki/)、[猫窝](https://maowo.moe) 提供开发资助。
## 插件功能与优势
> 加 * 的功能仍在开发中。
- 物品操作绑定给予玩家可执行对应操作设置的物品支持PlaceholderAPI变量。
- 目前支持的操作有:
- 控制台执行命令
- 玩家聊天消息 (加/前缀即为以玩家身份执行命令)
- 为玩家播放音效
- 给玩家发送消息 (支持RGB颜色格式为 `&(#颜色代码)` )
- 拿取对应物品 (若不配置则物品保留可继续使用)
- 目前支持的操作有:
- 控制台执行命令
- 玩家聊天消息 (加/前缀即为以玩家身份执行命令)
- 为玩家播放音效
- 给玩家发送消息 (支持RGB颜色格式为 `&(#颜色代码)` )
- 拿取对应物品 (若不配置则物品保留可继续使用)
- **允许限定。** 允许给物品对应的指令组设定“总共可执行次数*”、“每日执行次数*”与“允许使用时间”限定。
- **\*详细记录。** 每个物品均有独立ID并对使用的玩家与执行结果进行详细记录便于追踪查询。
- **异步存取。** 数据读取与存储均为异步操作,不影响服务器性能。
@ -33,7 +35,8 @@
## 插件依赖
- **[必须]** 插件本体基于 [Spigot-API](https://hub.spigotmc.org/stash/projects/SPIGOT) 、 [BukkitAPI](http://bukkit.org/) 实现。
- **[必须]** 插件本体基于 [Spigot-API](https://hub.spigotmc.org/stash/projects/SPIGOT) 、 [BukkitAPI](http://bukkit.org/)
实现。
- **[自带]** 插件功能基于 [EasyPlugin](https://github.com/CarmJos/EasyPlugin) 实现。
- **[自带]** 数据功能基于 [EasySQL](https://github.com/CarmJos/EasySQL) 实现。
- **[推荐]** 消息变量基于 [PlaceholderAPI](https://www.spigotmc.org/resources/6245/) 实现。
@ -46,7 +49,7 @@
详见源文件。
### 消息配置文件 ([messages.yml](src/main/java/cc/carm/plugin/scriptitems/configuration/PluginMessages.java))
### 消息配置文件 ([messages.yml](src/main/java/cc/carm/plugin/scriptitems/conf/PluginMessages.java))
详见代码源文件,将在首次启动时生成配置。
@ -100,9 +103,11 @@
> #### 可以用来盈利
> 你可以在分发软件的时候收费,但你必须在收费前向你的客户提供该软件的 GNU GPL 许可协议,以便让他们知道,他们可以从别的渠道免费得到这份软件,以及你收费的理由。
> #### 可自由修改
> 如果你想添加或删除某个功能,没问题,如果你想在别的项目中使用部分代码,也没问题,唯一的要求是,使用了这段代码的项目也必须使用 GPL 协议。
> 如果你想添加或删除某个功能,没问题,如果你想在别的项目中使用部分代码,也没问题,唯一的要求是,使用了这段代码的项目也必须使用
> GPL 协议。
>
> 需要注意的是,分发的时候,需要明确提供源代码和二进制文件,另外,用于某些程序的某些协议有一些问题和限制,你可以看一下 @PierreJoye 写的 Practical Guide to GPL Compliance 一文。使用 GPL 协议,你必须在源代码代码中包含相应信息,以及协议本身。
> 需要注意的是,分发的时候,需要明确提供源代码和二进制文件,另外,用于某些程序的某些协议有一些问题和限制,你可以看一下
> @PierreJoye 写的 Practical Guide to GPL Compliance 一文。使用 GPL 协议,你必须在源代码代码中包含相应信息,以及协议本身。
>
> *以上文字来自 [五种开源协议GPL,LGPL,BSD,MIT,Apache](https://www.oschina.net/question/54100_9455) 。*
</details>

52
pom.xml
View File

@ -5,16 +5,20 @@
<modelVersion>4.0.0</modelVersion>
<properties>
<java.version>8</java.version>
<maven.compiler.source>${java.version}</maven.compiler.source>
<maven.compiler.target>${java.version}</maven.compiler.target>
<easyplugin.version>1.3.9</easyplugin.version>
<easysql.version>0.3.8</easysql.version>
<project.jdk.version>8</project.jdk.version>
<maven.compiler.source>${project.jdk.version}</maven.compiler.source>
<maven.compiler.target>${project.jdk.version}</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.encoding>UTF-8</maven.compiler.encoding>
<deps.easyplugin.version>1.4.18</deps.easyplugin.version>
<deps.easysql.version>0.4.6</deps.easysql.version>
<deps.mineconfig.version>2.3.0</deps.mineconfig.version>
</properties>
<groupId>cc.carm.plugin</groupId>
<artifactId>scriptitems</artifactId>
<version>1.0.0</version>
<version>1.1.0</version>
<name>ScriptItems</name>
<description>物品操作绑定插件给予玩家可执行对应操作的物品基于EasyPlugin实现。</description>
@ -74,7 +78,7 @@
<dependency>
<groupId>cc.carm.lib</groupId>
<artifactId>easysql-beecp</artifactId>
<version>${easysql.version}</version>
<version>${deps.easysql.version}</version>
<scope>compile</scope>
<optional>true</optional>
</dependency>
@ -82,23 +86,31 @@
<dependency>
<groupId>cc.carm.lib</groupId>
<artifactId>easyplugin-main</artifactId>
<version>${easyplugin.version}</version>
<version>${deps.easyplugin.version}</version>
<scope>compile</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>cc.carm.lib</groupId>
<artifactId>easyplugin-configuration</artifactId>
<version>${easyplugin.version}</version>
<artifactId>easyplugin-command</artifactId>
<version>${deps.easyplugin.version}</version>
<scope>compile</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>cc.carm.lib</groupId>
<artifactId>githubreleases4j</artifactId>
<version>1.3.1</version>
<artifactId>easyplugin-githubchecker</artifactId>
<version>${deps.easyplugin.version}</version>
<scope>compile</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>cc.carm.lib</groupId>
<artifactId>mineconfiguration-bukkit</artifactId>
<version>${deps.mineconfig.version}</version>
<scope>compile</scope>
<optional>true</optional>
</dependency>
@ -118,13 +130,6 @@
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.spigotmc</groupId>
<artifactId>spigot</artifactId>
<version>1.13.2-R0.1-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>me.clip</groupId>
<artifactId>placeholderapi</artifactId>
@ -159,7 +164,7 @@
<configuration>
<filesets>
<fileset>
<directory>${project.basedir}/asset/</directory>
<directory>${project.basedir}/.asset/</directory>
<useDefaultExcludes>true</useDefaultExcludes>
<includes>
<include>**/*</include>
@ -188,8 +193,8 @@
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<source>${java.version}</source>
<target>${java.version}</target>
<source>${project.jdk.version}</source>
<target>${project.jdk.version}</target>
<encoding>UTF-8</encoding>
<compilerArgument>-parameters</compilerArgument>
</configuration>
@ -229,8 +234,7 @@
</executions>
<configuration>
<finalName>${project.name}-${project.version}</finalName>
<outputDirectory>${project.basedir}/asset</outputDirectory>
<minimizeJar>true</minimizeJar>
<outputDirectory>${project.basedir}/.asset</outputDirectory>
<relocations>
<relocation>
<pattern>cc.carm.lib</pattern>

View File

@ -1,65 +1,59 @@
package cc.carm.plugin.scriptitems;
import cc.carm.lib.configuration.core.source.ConfigurationProvider;
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.lib.easyplugin.updatechecker.GHUpdateChecker;
import cc.carm.lib.mineconfiguration.bukkit.MineConfiguration;
import cc.carm.plugin.scriptitems.command.MainCommand;
import cc.carm.plugin.scriptitems.conf.PluginConfig;
import cc.carm.plugin.scriptitems.conf.PluginMessages;
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 ConfigurationProvider<?> configProvider;
protected ConfigurationProvider<?> messageProvider;
protected ConfigManager configManager;
protected ItemsManager itemsManager;
@Override
protected boolean initialize() {
info("加载配置文件...");
this.configManager = new ConfigManager(this);
if (!configManager.initConfig()) {
severe("配置文件初始化失败,请检查。");
setEnabled(false);
return false;
}
log("加载插件配置文件...");
this.configProvider = MineConfiguration.from(this, "config.yml");
this.configProvider.initialize(PluginConfig.class);
this.messageProvider = MineConfiguration.from(this, "messages.yml");
this.messageProvider.initialize(PluginMessages.class);
info("加载物品配置...");
this.itemsManager = new ItemsManager();
this.itemsManager.initialize();
info("注册指令...");
registerCommand("ScriptItems", new ScriptItemsCommand());
registerCommand("ScriptItems", new MainCommand(this));
info("注册监听器...");
regListener(new ItemListener());
registerListener(new ItemListener());
if (PluginConfig.METRICS.get()) {
if (PluginConfig.METRICS.getNotNull()) {
info("启用统计数据...");
new Metrics(this, 14615);
}
if (PluginConfig.CHECK_UPDATE.get()) {
if (PluginConfig.CHECK_UPDATE.getNotNull()) {
log("开始检查更新...");
GHUpdateChecker checker = new GHUpdateChecker(getLogger(), "CarmJos", "CommandItem");
getScheduler().runAsync(() -> checker.checkUpdate(getDescription().getVersion()));
getScheduler().runAsync(GHUpdateChecker.runner(this));
} else {
log("已禁用检查更新,跳过。");
}
@ -77,12 +71,11 @@ public class Main extends EasyPlugin {
@Override
public boolean isDebugging() {
return PluginConfig.DEBUG.get();
return PluginConfig.DEBUG.getNotNull();
}
@Override
public void outputInfo() {
Optional.ofNullable(JarResourceUtils.readResource(this.getResource("PLUGIN_INFO"))).ifPresent(this::log);
public static Main getInstance() {
return instance;
}
public static void info(String... messages) {
@ -96,4 +89,12 @@ public class Main extends EasyPlugin {
public static void debugging(String... messages) {
getInstance().debug(messages);
}
public ConfigurationProvider<?> getConfigProvider() {
return configProvider;
}
public ConfigurationProvider<?> getMessageProvider() {
return messageProvider;
}
}

View File

@ -1,6 +1,5 @@
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;
@ -13,10 +12,6 @@ public class ScriptItemsAPI {
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))

View File

@ -0,0 +1,43 @@
package cc.carm.plugin.scriptitems.command;
import cc.carm.lib.easyplugin.command.CommandHandler;
import cc.carm.plugin.scriptitems.command.sub.ApplyCommand;
import cc.carm.plugin.scriptitems.command.sub.GetCommand;
import cc.carm.plugin.scriptitems.command.sub.GiveCommand;
import cc.carm.plugin.scriptitems.command.sub.ReloadCommand;
import cc.carm.plugin.scriptitems.conf.PluginMessages;
import org.bukkit.command.CommandSender;
import org.bukkit.plugin.java.JavaPlugin;
import org.jetbrains.annotations.NotNull;
public class MainCommand extends CommandHandler {
public MainCommand(@NotNull JavaPlugin plugin) {
super(plugin);
registerSubCommand(new ReloadCommand(this, "reload"));
registerSubCommand(new ApplyCommand(this, "apply"));
registerSubCommand(new GetCommand(this, "get"));
registerSubCommand(new GiveCommand(this, "give"));
}
@Override
public Void noArgs(CommandSender sender) {
PluginMessages.USAGE.send(sender);
return null;
}
@Override
public Void noPermission(CommandSender sender) {
PluginMessages.NO_PERMISSION.send(sender);
return null;
}
@Override
public boolean hasPermission(CommandSender sender) {
return sender.hasPermission("ScriptItems.admin");
}
public Void onlyPlay(CommandSender sender) {
PluginMessages.ONLY_PLAYER.send(sender);
return null;
}
}

View File

@ -1,166 +0,0 @@
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.ScriptConfiguration;
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;
}
ScriptConfiguration settings = ScriptItemsAPI.getItemsManager().getItemSettings(args[1]);
if (settings == null) {
PluginMessages.NOT_EXISTS.send(sender, args[1]);
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.clone());
player.getInventory().setItemInMainHand(after);
PluginMessages.APPLIED.send(sender, item.getType().name(), settings.getName());
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, args[1]);
return true;
}
ScriptConfiguration settings = ScriptItemsAPI.getItemsManager().getItemSettings(args[2]);
if (settings == null) {
PluginMessages.NOT_EXISTS.send(sender, args[2]);
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.getName(), amount, settings.getName());
} else {
int remainAmount = remain.values().stream().mapToInt(ItemStack::getAmount).sum();
PluginMessages.GIVEN_SOME.send(sender, player.getName(), amount - 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[0];
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[0];
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());
}
}

View File

@ -0,0 +1,55 @@
package cc.carm.plugin.scriptitems.command.sub;
import cc.carm.lib.easyplugin.command.SimpleCompleter;
import cc.carm.lib.easyplugin.command.SubCommand;
import cc.carm.plugin.scriptitems.ScriptItemsAPI;
import cc.carm.plugin.scriptitems.command.MainCommand;
import cc.carm.plugin.scriptitems.conf.PluginMessages;
import cc.carm.plugin.scriptitems.item.ScriptConfiguration;
import org.bukkit.Material;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import org.bukkit.plugin.java.JavaPlugin;
import org.jetbrains.annotations.NotNull;
import java.util.List;
public class ApplyCommand extends SubCommand<MainCommand> {
public ApplyCommand(@NotNull MainCommand parent, String name, String... aliases) {
super(parent, name, aliases);
}
@Override
public Void execute(JavaPlugin plugin, CommandSender sender, String[] args) throws Exception {
if (!(sender instanceof Player)) return getParent().onlyPlay(sender);
if (args.length < 1) return getParent().noArgs(sender);
ScriptConfiguration settings = ScriptItemsAPI.getItemsManager().getItemSettings(args[0]);
if (settings == null) {
PluginMessages.NOT_EXISTS.send(sender, args[1]);
return null;
}
Player player = (Player) sender;
ItemStack item = player.getInventory().getItemInMainHand();
if (item.getType() == Material.AIR) {
PluginMessages.USE_ITEM.send(sender);
return null;
}
ItemStack after = settings.applyItem(item.clone());
player.getInventory().setItemInMainHand(after);
PluginMessages.APPLIED.send(sender, item.getType().name(), settings.getName());
return null;
}
@Override
public List<String> tabComplete(JavaPlugin plugin, CommandSender sender, String[] args) {
if (args.length == 1) {
return SimpleCompleter.objects(args[0], ScriptItemsAPI.getItemsManager().listItemSettings().keySet());
} else return SimpleCompleter.none();
}
}

View File

@ -0,0 +1,74 @@
package cc.carm.plugin.scriptitems.command.sub;
import cc.carm.lib.easyplugin.command.SimpleCompleter;
import cc.carm.lib.easyplugin.command.SubCommand;
import cc.carm.plugin.scriptitems.ScriptItemsAPI;
import cc.carm.plugin.scriptitems.command.MainCommand;
import cc.carm.plugin.scriptitems.conf.PluginMessages;
import cc.carm.plugin.scriptitems.item.ScriptConfiguration;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import org.bukkit.plugin.java.JavaPlugin;
import org.jetbrains.annotations.NotNull;
import java.util.HashMap;
import java.util.List;
public class GetCommand extends SubCommand<MainCommand> {
public GetCommand(@NotNull MainCommand parent, String name, String... aliases) {
super(parent, name, aliases);
}
@Override
public Void execute(JavaPlugin plugin, CommandSender sender, String[] args) {
if (!(sender instanceof Player)) return getParent().onlyPlay(sender);
if (args.length < 1) return getParent().noArgs(sender);
Player player = (Player) sender;
ScriptConfiguration settings = ScriptItemsAPI.getItemsManager().getItemSettings(args[0]);
if (settings == null) {
PluginMessages.NOT_EXISTS.send(sender, args[0]);
return null;
}
int amount = 1;
if (args.length >= 2) {
try {
amount = Integer.parseInt(args[1]);
} catch (Exception ignored) {
amount = -1;
}
}
if (amount < 1) {
PluginMessages.WRONG_AMOUNT.send(sender);
return null;
}
ItemStack item = settings.generateItem(amount);
if (item == null) {
PluginMessages.WRONG_ITEM.send(sender);
return null;
}
HashMap<Integer, ItemStack> remain = player.getInventory().addItem(item);
if (remain.isEmpty()) {
PluginMessages.GIVEN_ALL.send(sender, player.getName(), amount, settings.getName());
} else {
int remainAmount = remain.values().stream().mapToInt(ItemStack::getAmount).sum();
PluginMessages.GIVEN_SOME.send(sender, player.getName(), amount - remainAmount, settings.getName(), remainAmount);
}
return null;
}
@Override
public List<String> tabComplete(JavaPlugin plugin, CommandSender sender, String[] args) {
if (args.length == 1) {
return SimpleCompleter.objects(args[0], ScriptItemsAPI.getItemsManager().listItemSettings().keySet());
} else return SimpleCompleter.none();
}
}

View File

@ -0,0 +1,82 @@
package cc.carm.plugin.scriptitems.command.sub;
import cc.carm.lib.easyplugin.command.SimpleCompleter;
import cc.carm.lib.easyplugin.command.SubCommand;
import cc.carm.plugin.scriptitems.ScriptItemsAPI;
import cc.carm.plugin.scriptitems.command.MainCommand;
import cc.carm.plugin.scriptitems.conf.PluginMessages;
import cc.carm.plugin.scriptitems.item.ScriptConfiguration;
import org.bukkit.Bukkit;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import org.bukkit.plugin.java.JavaPlugin;
import org.jetbrains.annotations.NotNull;
import java.util.HashMap;
import java.util.List;
public class GiveCommand extends SubCommand<MainCommand> {
public GiveCommand(@NotNull MainCommand parent, String name, String... aliases) {
super(parent, name, aliases);
}
@Override
public Void execute(JavaPlugin plugin, CommandSender sender, String[] args) throws Exception {
if (args.length < 2) return getParent().noArgs(sender);
Player player = Bukkit.getPlayer(args[0]);
if (player == null) {
PluginMessages.NOT_ONLINE.send(sender, args[0]);
return null;
}
ScriptConfiguration settings = ScriptItemsAPI.getItemsManager().getItemSettings(args[1]);
if (settings == null) {
PluginMessages.NOT_EXISTS.send(sender, args[1]);
return null;
}
int amount = 1;
if (args.length >= 3) {
try {
amount = Integer.parseInt(args[2]);
} catch (Exception ignored) {
amount = -1;
}
}
if (amount < 1) {
PluginMessages.WRONG_AMOUNT.send(sender);
return null;
}
ItemStack item = settings.generateItem(amount);
if (item == null) {
PluginMessages.WRONG_ITEM.send(sender);
return null;
}
HashMap<Integer, ItemStack> remain = player.getInventory().addItem(item);
if (remain.isEmpty()) {
PluginMessages.GIVEN_ALL.send(sender, player.getName(), amount, settings.getName());
} else {
int remainAmount = remain.values().stream().mapToInt(ItemStack::getAmount).sum();
PluginMessages.GIVEN_SOME.send(sender, player.getName(), amount - remainAmount, settings.getName(), remainAmount);
}
return null;
}
@Override
public List<String> tabComplete(JavaPlugin plugin, CommandSender sender, String[] args) {
if (args.length == 1) {
return SimpleCompleter.allPlayers(args[0]);
} else if (args.length == 2) {
return SimpleCompleter.objects(args[1], ScriptItemsAPI.getItemsManager().listItemSettings().keySet());
} else return SimpleCompleter.none();
}
}

View File

@ -0,0 +1,30 @@
package cc.carm.plugin.scriptitems.command.sub;
import cc.carm.lib.easyplugin.command.SubCommand;
import cc.carm.plugin.scriptitems.Main;
import cc.carm.plugin.scriptitems.ScriptItemsAPI;
import cc.carm.plugin.scriptitems.command.MainCommand;
import org.bukkit.command.CommandSender;
import org.bukkit.plugin.java.JavaPlugin;
import org.jetbrains.annotations.NotNull;
public class ReloadCommand extends SubCommand<MainCommand> {
public ReloadCommand(@NotNull MainCommand parent, String name, String... aliases) {
super(parent, name, aliases);
}
@Override
public Void execute(JavaPlugin plugin, CommandSender sender, String[] args) {
try {
Main.getInstance().getConfigProvider().reload();
Main.getInstance().getMessageProvider().reload();
ScriptItemsAPI.getItemsManager().loadItems();
sender.sendMessage("配置文件重载完成!");
} catch (Exception e) {
sender.sendMessage("配置文件重载失败: " + e.getMessage());
e.printStackTrace();
}
return null;
}
}

View File

@ -0,0 +1,42 @@
package cc.carm.plugin.scriptitems.conf;
import cc.carm.lib.configuration.core.ConfigurationRoot;
import cc.carm.lib.configuration.core.annotation.HeaderComment;
import cc.carm.lib.configuration.core.value.ConfigValue;
import cc.carm.lib.configuration.core.value.type.ConfiguredValue;
public class PluginConfig extends ConfigurationRoot {
public static final ConfigValue<Boolean> DEBUG = ConfiguredValue.of(Boolean.class, false);
@HeaderComment({
"统计数据设定",
"该选项用于帮助开发者统计插件版本与使用情况,且绝不会影响性能与使用体验。",
"当然您也可以选择在这里关闭或在plugins/bStats下的配置文件中关闭。"
})
public static final ConfigValue<Boolean> METRICS = ConfiguredValue.of(Boolean.class, true);
@HeaderComment({
"检查更新设定",
"该选项用于插件判断是否要检查更新,若您不希望插件检查更新并提示您,可以选择关闭。",
"检查更新为异步操作,绝不会影响性能与使用体验。"
})
public static final ConfigValue<Boolean> CHECK_UPDATE = ConfiguredValue.of(Boolean.class, true);
@HeaderComment({
"物品使用冷却,避免短时间重复使用物品,也避免网络延迟而导致物品被错误使用而对玩家造成的损失。",
"强烈建议开启,且建议设置为 2000毫秒 以上。(1s = 1000ms)"
})
public static class COOLDOWN extends ConfigurationRoot {
@HeaderComment("是否启用冷却功能")
public static final ConfigValue<Boolean> ENABLE = ConfiguredValue.of(Boolean.class, true);
@HeaderComment("冷却的时长,单位为毫秒 1秒 = 1000毫秒 = 20ticks")
public static final ConfigValue<Long> DURATION = ConfiguredValue.of(Long.class, 3000L);
}
}

View File

@ -0,0 +1,83 @@
package cc.carm.plugin.scriptitems.conf;
import cc.carm.lib.configuration.core.ConfigurationRoot;
import cc.carm.lib.mineconfiguration.bukkit.value.ConfiguredMessageList;
public class PluginMessages extends ConfigurationRoot {
public static final ConfiguredMessageList<String> USAGE = ConfiguredMessageList.asStrings().defaults(
"&2&l脚本物品 &f指令帮助",
"&8#&f give &a<玩家名> &a<脚本ID> &2[数量]",
"&8-&7 给予指定玩家指定数量的物品。",
"&8#&f get &a<脚本ID> &2[数量]",
"&8-&7 给予自己指定数量的物品。",
"&8#&f apply &a<脚本ID>",
"&8-&7 为手中的物品直接绑定一个配置。",
"&8#&f reload",
"&8-&7 重载配置文件。"
).build();
public static final ConfiguredMessageList<String> NO_PERMISSION = ConfiguredMessageList.asStrings()
.defaults("&c&l抱歉&f但您没有权限使用该命令。")
.build();
public final static ConfiguredMessageList<String> COOLDOWN = ConfiguredMessageList.asStrings()
.defaults("&f您需要等待 &a%(time)秒 &f才可再次使用该物品。")
.params("time").build();
public final static ConfiguredMessageList<String> ONLY_PLAYER = ConfiguredMessageList.asStrings()
.defaults("&c抱歉只有作为玩家时才能使用该指令。").build();
public final static ConfiguredMessageList<String> USE_ITEM = ConfiguredMessageList.asStrings()
.defaults("&f请手持任意物品后再使用该指令。").build();
public final static ConfiguredMessageList<String> NOT_ONLINE = ConfiguredMessageList.asStrings()
.defaults("&f玩家 &a%(player) &f并不在线。")
.params("player").build();
public final static ConfiguredMessageList<String> NOT_EXISTS = ConfiguredMessageList.asStrings()
.defaults("&f脚本配置 &a%(id) &f并不存在。")
.params("id").build();
public final static ConfiguredMessageList<String> WRONG_AMOUNT = ConfiguredMessageList.asStrings()
.defaults("&f请输入正确的数量")
.build();
public final static ConfiguredMessageList<String> WRONG_ITEM = ConfiguredMessageList.asStrings()
.defaults("&f该脚本并未成功配置具体物品请使用 &a/ScriptItems apply &f来绑定到指定物品上或在配置文件中正确配置物品。")
.build();
public final static ConfiguredMessageList<String> GIVEN_ALL = ConfiguredMessageList.asStrings()
.defaults("&f您成功给予 &2%(player) &f了 &a%(amount) &f个 &a%(name) &f。")
.params("player", "amount", "name").build();
public final static ConfiguredMessageList<String> GIVEN_SOME = ConfiguredMessageList.asStrings()
.defaults(
"&f您成功给予 &2%(player) &f了 &a%(amount) &f个 &a%(name) &f。",
"&f但由于目标玩家背包已满仍有 &a%(remain) &f个 &a%(name) &f未成功放入背包。"
).params("player", "amount", "name", "remain").build();
public final static ConfiguredMessageList<String> APPLIED = ConfiguredMessageList.asStrings()
.defaults("&f成功为手上的 &2%(type) &f绑定了脚本 &a%(name) &f。")
.params("type", "name").build();
public static class RESTRICTIONS extends ConfigurationRoot {
public final static ConfiguredMessageList<String> INVALID = ConfiguredMessageList.asStrings()
.defaults("&c&l抱歉&f由于配置的时间限制错误该物品目前暂不可用。")
.build();
public final static ConfiguredMessageList<String> NOT_STARTED = ConfiguredMessageList.asStrings()
.defaults("&f该物品目前还到可使用的时间请在 &a%(time) &f后使用~")
.params("time")
.build();
public final static ConfiguredMessageList<String> EXPIRED = ConfiguredMessageList.asStrings()
.defaults("&c&l抱歉&f由于该物品已过最后使用期限故无法继续使用。")
.params("time")
.build();
}
}

View File

@ -1,40 +0,0 @@
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);
}
}

View File

@ -1,77 +0,0 @@
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您需要等待 &a%(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您成功给予 &2%(player) &f了 &a%(amount) &f个 &a%(name) &f。")
.params("player", "amount", "name").build();
public final static EasyMessageList GIVEN_SOME = EasyMessageList.builder().contents(
"&f您成功给予 &2%(player) &f了 &a%(amount) &f个 &a%(name) &f。",
"&f但由于目标玩家背包已满仍有 &a%(remain) &f个 &a%(name) &f未成功放入背包。"
).params("player", "amount", "name", "remain").build();
public final static EasyMessageList APPLIED = EasyMessageList.builder()
.contents("&f成功为手上的 &2%(type) &f绑定了脚本 &a%(name) &f。")
.params("type", "name").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该物品目前还到可使用的时间请在 &a%(time) &f后使用~")
.params("time")
.build();
public final static EasyMessageList EXPIRED = EasyMessageList.builder()
.contents("&c&l抱歉&f由于该物品已过最后使用期限故无法继续使用。")
.params("time")
.build();
}
}

View File

@ -1,49 +0,0 @@
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()
);
}
}

View File

@ -1,54 +0,0 @@
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`)"
};
}
}

View File

@ -3,22 +3,18 @@ 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()
DatabaseConfig.DRIVER_NAME.getNotNull(), DatabaseConfig.buildJDBC(),
DatabaseConfig.USERNAME.getNotNull(), DatabaseConfig.PASSWORD.get()
);
this.sqlManager.setDebugMode(() -> Main.getInstance().isDebugging());
} catch (Exception exception) {
@ -29,13 +25,9 @@ public class DataManager {
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);
for (DatabaseTables value : DatabaseTables.values()) {
value.create(this.sqlManager);
}
} catch (SQLException exception) {
Main.severe("无法创建插件所需的表,请检查数据库权限。");
exception.printStackTrace();
@ -55,15 +47,6 @@ public class DataManager {
return sqlManager;
}
public DatabaseTable getGivenTable() {
return givenTable;
}
public DatabaseTable getReceivedTable() {
return receivedTable;
}
}

View File

@ -0,0 +1,40 @@
package cc.carm.plugin.scriptitems.database;
import cc.carm.lib.configuration.core.ConfigurationRoot;
import cc.carm.lib.configuration.core.annotation.ConfigPath;
import cc.carm.lib.configuration.core.annotation.HeaderComment;
import cc.carm.lib.configuration.core.value.ConfigValue;
import cc.carm.lib.configuration.core.value.type.ConfiguredValue;
@HeaderComment("选择 database (如mysql) 存储方式时的数据库配置")
@ConfigPath("storage.database")
public class DatabaseConfig extends ConfigurationRoot {
@ConfigPath("driver")
protected static final ConfigValue<String> DRIVER_NAME = ConfiguredValue.of(
String.class, "com.mysql.jdbc.Driver"
);
protected static final ConfigValue<String> HOST = ConfiguredValue.of(String.class, "127.0.0.1");
protected static final ConfigValue<Integer> PORT = ConfiguredValue.of(Integer.class, 3306);
protected static final ConfigValue<String> DATABASE = ConfiguredValue.of(String.class, "minecraft");
protected static final ConfigValue<String> USERNAME = ConfiguredValue.of(String.class, "root");
protected static final ConfigValue<String> PASSWORD = ConfiguredValue.of(String.class, "password");
protected static final ConfigValue<String> EXTRA = ConfiguredValue.of(String.class, "?useSSL=false");
@HeaderComment("插件相关表的名称")
public static final class TABLES extends ConfigurationRoot {
public static final ConfigValue<String> TAKEN = ConfiguredValue.of(String.class, "log_item_take");
public static final ConfigValue<String> GIVEN = ConfiguredValue.of(String.class, "log_item_give");
}
protected static String buildJDBC() {
return String.format("jdbc:mysql://%s:%s/%s%s",
HOST.getNotNull(), PORT.getNotNull(), DATABASE.getNotNull(), EXTRA.getNotNull()
);
}
}

View File

@ -0,0 +1,97 @@
package cc.carm.plugin.scriptitems.database;
import cc.carm.lib.configuration.core.value.ConfigValue;
import cc.carm.lib.easysql.api.SQLManager;
import cc.carm.lib.easysql.api.SQLTable;
import cc.carm.lib.easysql.api.builder.TableCreateBuilder;
import cc.carm.lib.easysql.api.enums.IndexType;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.sql.SQLException;
import java.util.function.Consumer;
public enum DatabaseTables implements SQLTable {
/**
* 物品发放记录表
* 用于记录每个物品的发放情况包含发放时间发放人发放数量以及发放给了谁
*/
GIVE(DatabaseConfig.TABLES.GIVEN, (table) -> {
table.setColumns("`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" // 发放时间
);
table.addAutoIncrementColumn("id", false, true);
table.addColumn("uuid", "CHAR(36) NOT NULL PRIMARY KEY"); // 该物品的 ItemUUID
table.addColumn("type", "VARCHAR(36) NOT NULL"); // 该物品的 类型
// 发放人的相关信息
table.addColumn("operator_uuid", "CHAR(36)");
table.addColumn("operator_name", "VARCHAR(32)");
// 领取者的相关信息
table.addColumn("receiver_uuid", "CHAR(36)");
table.addColumn("receiver_name", "VARCHAR(32)");
// 发放时间
table.addColumn("time", "DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP");
}),
/**
* 物品拿取记录表
* 改表用于记录物品的使用情况即谁在什么时候使用了哪个物品以及领取时任务的执行情况
* 请注意只有在发生物品拿取( take action )事件时才会记录
*/
HOMES(DatabaseConfig.TABLES.TAKEN, (table) -> {
table.addAutoIncrementColumn("id", true, true);
table.addColumn("uuid", "CHAR(36) NOT NULL"); // ItemUUID
table.addColumn("item", "VARCHAR(36) NOT NULL"); // Item ID
// 领取者者的相关信息
table.addColumn("user_uuid", "CHAR(36) NOT NULL");
table.addColumn("user_name", "VARCHAR(32) NOT NULL");
// 领取结果 (是否成功)
table.addColumn("success", "BIT NOT NULL DEFAULT 0");
table.addColumn("time", "DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP");
table.setIndex(IndexType.UNIQUE_KEY, "uk_item_receive", "uuid");
});
private final Consumer<TableCreateBuilder> builder;
private final ConfigValue<String> name;
private @Nullable SQLManager manager;
DatabaseTables(ConfigValue<String> name,
Consumer<TableCreateBuilder> builder) {
this.name = name;
this.builder = builder;
}
@Override
public @Nullable SQLManager getSQLManager() {
return this.manager;
}
@Override
public @NotNull String getTableName() {
return this.name.getNotNull();
}
@Override
public boolean create(SQLManager sqlManager) throws SQLException {
if (this.manager == null) this.manager = sqlManager;
TableCreateBuilder tableBuilder = sqlManager.createTable(getTableName());
if (builder != null) builder.accept(tableBuilder);
return tableBuilder.build().executeFunction(l -> l > 0, false);
}
}

View File

@ -1,38 +0,0 @@
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);
}
}
}

View File

@ -39,5 +39,4 @@ public class ScriptAction {
return new ScriptAction(actionType, actionString.substring(prefixEnd + 1).trim());
}
}

View File

@ -33,6 +33,26 @@ public enum ScriptActionType {
return success;
}),
/**
* 让玩家以OP的身份执行命令
*/
OP((player, string) -> {
if (string == null) return true;
List<String> finalCommands = MessageUtils.setPlaceholders(player, Collections.singletonList(string));
boolean success = true;
boolean opBefore = player.isOp();
player.setOp(true);
for (String finalCommand : finalCommands) {
try {
player.chat(finalCommand.startsWith("/") ? finalCommand : "/" + finalCommand);
} catch (Exception ex) {
success = false;
}
}
player.setOp(opBefore);
return success;
}),
/**
* 以后台的形式执行指令
* 指令内容不需要以/开头
@ -43,7 +63,8 @@ public enum ScriptActionType {
boolean success = true;
for (String finalCommand : finalCommands) {
try {
Bukkit.dispatchCommand(Bukkit.getConsoleSender(), finalCommand);
String cmd = finalCommand.startsWith("/") ? finalCommand.substring(1) : finalCommand;
Bukkit.dispatchCommand(Bukkit.getConsoleSender(), cmd);
} catch (Exception ex) {
success = false;
}
@ -98,7 +119,7 @@ public enum ScriptActionType {
return false;
});
BiFunction<@NotNull Player, @Nullable String, @NotNull Boolean> executor;
final BiFunction<@NotNull Player, @Nullable String, @NotNull Boolean> executor;
ScriptActionType(BiFunction<@NotNull Player, @Nullable String, @NotNull Boolean> executor) {
this.executor = executor;

View File

@ -1,7 +1,7 @@
package cc.carm.plugin.scriptitems.item;
import cc.carm.plugin.scriptitems.ScriptItemsAPI;
import cc.carm.plugin.scriptitems.manager.ConfigManager;
import cc.carm.plugin.scriptitems.utils.ConfigUtils;
import org.bukkit.configuration.file.FileConfiguration;
import org.bukkit.configuration.file.YamlConfiguration;
import org.bukkit.entity.Player;
@ -105,8 +105,9 @@ public class ScriptConfiguration {
ItemStackConfig.create(config.getItemStack("item")) :
ItemStackConfig.read(config.getConfigurationSection("item")),
ScriptRestrictions.read(config.getConfigurationSection("restrictions")),
ConfigManager.readStringMap(config.getConfigurationSection("permissions"), (s -> s)),
ConfigManager.readListMap(config.getConfigurationSection("actions"), ScriptActionGroup::read)
ConfigUtils.readStringMap(config.getConfigurationSection("permissions"), (s -> s)),
ConfigUtils.readListMap(config.getConfigurationSection("actions"), ScriptActionGroup::read)
);
}
}

View File

@ -1,8 +1,8 @@
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 cc.carm.lib.mineconfiguration.bukkit.value.ConfiguredMessageList;
import cc.carm.plugin.scriptitems.conf.PluginMessages;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
@ -51,28 +51,28 @@ public class ScriptRestrictions {
AVAILABLE(() -> null, (res) -> null),
INVALID(() -> PluginMessages.Restrictions.INVALID, (res) -> null),
INVALID(() -> PluginMessages.RESTRICTIONS.INVALID, (res) -> null),
NOT_STARTED(
() -> PluginMessages.Restrictions.NOT_STARTED,
() -> PluginMessages.RESTRICTIONS.NOT_STARTED,
(res) -> new Object[]{TimeDateUtils.getTimeString(res.getStartTime())}
),
EXPIRED(
() -> PluginMessages.Restrictions.EXPIRED,
() -> PluginMessages.RESTRICTIONS.EXPIRED,
(res) -> new Object[]{TimeDateUtils.getTimeString(res.getEndTime())}
);
Supplier<@Nullable EasyMessageList> message;
Function<@NotNull ScriptRestrictions, Object[]> params;
private final Supplier<@Nullable ConfiguredMessageList<?>> message;
private final Function<@NotNull ScriptRestrictions, Object[]> params;
CheckResult(@NotNull Supplier<@Nullable EasyMessageList> message,
CheckResult(@NotNull Supplier<@Nullable ConfiguredMessageList<?>> message,
@NotNull Function<@NotNull ScriptRestrictions, @Nullable Object[]> params) {
this.message = message;
this.params = params;
}
public Supplier<EasyMessageList> getMessage() {
public Supplier<ConfiguredMessageList<?>> getMessage() {
return message;
}

View File

@ -1,12 +1,14 @@
package cc.carm.plugin.scriptitems.listener;
import cc.carm.lib.easyplugin.utils.EasyCooldown;
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.conf.PluginConfig;
import cc.carm.plugin.scriptitems.conf.PluginMessages;
import cc.carm.plugin.scriptitems.item.ScriptActionGroup;
import cc.carm.plugin.scriptitems.item.ScriptRestrictions;
import cc.carm.plugin.scriptitems.item.ScriptConfiguration;
import cc.carm.plugin.scriptitems.item.ScriptItem;
import cc.carm.plugin.scriptitems.item.ScriptRestrictions;
import org.bukkit.entity.Entity;
import org.bukkit.entity.EntityType;
import org.bukkit.entity.Item;
import org.bukkit.entity.Player;
@ -19,14 +21,19 @@ import org.bukkit.event.inventory.CraftItemEvent;
import org.bukkit.event.player.PlayerInteractEvent;
import org.bukkit.event.player.PlayerQuitEvent;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.NotNull;
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<>();
private final EasyCooldown<Player, UUID> cooldown = new EasyCooldown<Player, UUID>(Entity::getUniqueId) {
@Override
public long getDuration(@NotNull Player provider) {
return PluginConfig.COOLDOWN.ENABLE.getNotNull() ? PluginConfig.COOLDOWN.DURATION.getNotNull() : -1;
}
};
/**
* 监听玩家点击并执行物品对应的操作
@ -43,11 +50,11 @@ public class ItemListener implements Listener {
event.setCancelled(true); // 阻止事件执行
Player player = event.getPlayer();
if (!isClickable(player.getUniqueId())) {
PluginMessages.COOLDOWN.send(player, getRemainSeconds(player.getUniqueId()));
if (cooldown.isCoolingDown(player)) {
PluginMessages.COOLDOWN.send(player, cooldown.getCooldownSeconds(player));
return;
}
updateTime(player.getUniqueId());
cooldown.updateTime(player);
ScriptConfiguration settings = scriptItem.getSettings();
@ -110,24 +117,7 @@ public class ItemListener implements Listener {
@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;
cooldown.clear(event.getPlayer());
}

View File

@ -1,9 +1,9 @@
package cc.carm.plugin.scriptitems.manager;
import cc.carm.lib.easyplugin.utils.JarResourceUtils;
import cc.carm.plugin.scriptitems.Main;
import cc.carm.plugin.scriptitems.item.ScriptConfiguration;
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;

View File

@ -1,77 +0,0 @@
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());
}
}

View File

@ -1,106 +0,0 @@
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);
}
}

View File

@ -1,64 +1,15 @@
package cc.carm.plugin.scriptitems.manager;
package cc.carm.plugin.scriptitems.utils;
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 class ConfigUtils {
public static <V> Map<String, V> readStringMap(@Nullable ConfigurationSection section,
@NotNull Function<String, V> valueCast) {

View File

@ -2,4 +2,4 @@
&a / __/_______(_)__ / /_&2/ _/ /____ __ _ ___
&a _\ \/ __/ __/ / _ \/ __/&2/ // __/ -_) ' \(_-<
&a/___/\__/_/ /_/ .__/\__/&2___/\__/\__/_/_/_/___/
&a /_/
&a /_/ &8by &7@&dCarmJos

View File

@ -1,24 +0,0 @@
# ${project.name} - ${project.description}
# 项目地址: ${project.url}
# 下载地址: ${project.distributionManagement.downloadUrl}
version: ${project.version}
debug: false
# 统计数据设定
# 该选项用于帮助开发者统计插件版本与使用情况,且绝不会影响性能与使用体验。
# 当然您也可以选择在这里关闭或在plugins/bStats下的配置文件中关闭。
metrics: true
# 检查更新设定
# 该选项用于插件判断是否要检查更新,若您不希望插件检查更新并提示您,可以选择关闭。
# 检查更新为异步操作,绝不会影响性能与使用体验。
check-update: true
# 物品使用冷却,避免短时间重复使用物品,也避免网络延迟而导致物品被错误使用而对玩家造成的损失。
# 强烈建议开启,且建议设置为 2000毫秒 以上。(1s = 1000ms)
cooldown:
#是否启用冷却功能
enable: true
# 冷却的事件,单位为毫秒 1秒 = 1000毫秒 = 20ticks
time: 3000

View File

@ -1,5 +0,0 @@
# ${project.name} - ${project.description}
# 项目地址: ${project.url}
# 下载地址: ${project.distributionManagement.downloadUrl}
version: ${project.version}

View File

@ -15,7 +15,8 @@ api-version: 1.13
commands:
"ScriptItems":
aliases: "sitems"
aliases:
- sitems
usage: "/ScriptItems help"
description: "ScriptItems 的主指令。"
permission: "ScriptItems.admin"