feat: 初版完成

初版完成
This commit is contained in:
2022-10-23 05:41:01 +08:00
parent b0e4920e63
commit bcd0410fe1
37 changed files with 1453 additions and 174 deletions

View File

@@ -8,20 +8,18 @@ dependencies {
}
compileOnly 'org.spigotmc:spigot-api:1.12.2-R0.1-SNAPSHOT'
compileOnly 'net.milkbowl.vault:VaultAPI:1.7'
compileOnly 'org.black_ixx:playerpoints:2.1.3'
// https://mvnrepository.com/artifact/com.zaxxer/HikariCP
//noinspection GradlePackageUpdate
apiShade 'com.zaxxer:HikariCP:4.0.3'
// https://mvnrepository.com/artifact/mysql/mysql-connector-java
shade 'mysql:mysql-connector-java:8.0.31'
// https://mvnrepository.com/artifact/com.squareup.okhttp3/okhttp
apiShade 'com.squareup.okhttp3:okhttp:4.10.0'
// https://mvnrepository.com/artifact/net.kyori/adventure-platform-bukkit
apiShade 'net.kyori:adventure-platform-bukkit:4.1.2'
testImplementation 'org.junit.jupiter:junit-jupiter-api:5.9.0'
testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.9.0'
}
test {
useJUnitPlatform()
}
processResources {
@@ -38,11 +36,14 @@ tasks.create("shadowJar", Jar) {
tasks.jar.outputs.files.collect {
it.isDirectory() ? it : zipTree(it)
},
configurations.implementationShade.collect {
configurations.shade.collect {
it.isDirectory() ? it : zipTree(it)
},
configurations.apiShade.collect {
it.isDirectory() ? it : zipTree(it)
},
configurations.implementationShade.collect {
it.isDirectory() ? it : zipTree(it)
}
])
destinationDir(getRootProject().buildDir)

View File

@@ -1,11 +1,25 @@
package cn.hamster3.mc.plugin.core.bukkit;
import cn.hamster3.mc.plugin.core.bukkit.api.CoreBukkitAPI;
import cn.hamster3.mc.plugin.core.bukkit.command.ParentCommand;
import cn.hamster3.mc.plugin.core.bukkit.command.debug.BlockInfoCommand;
import cn.hamster3.mc.plugin.core.bukkit.command.debug.YamlCommand;
import cn.hamster3.mc.plugin.core.bukkit.hook.PointAPI;
import cn.hamster3.mc.plugin.core.bukkit.hook.VaultAPI;
import cn.hamster3.mc.plugin.core.bukkit.listener.CallbackListener;
import cn.hamster3.mc.plugin.core.bukkit.listener.DebugListener;
import cn.hamster3.mc.plugin.core.bukkit.page.listener.PageListener;
import cn.hamster3.mc.plugin.core.common.constant.CoreConstantObjects;
import org.bukkit.Bukkit;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import org.bukkit.plugin.java.JavaPlugin;
import java.util.List;
import java.util.logging.Logger;
public class HamsterCorePlugin extends JavaPlugin {
private static final ParentCommand COMMAND_EXECUTOR = new ParentCommand("core");
private static HamsterCorePlugin instance;
public static HamsterCorePlugin getInstance() {
@@ -16,10 +30,6 @@ public class HamsterCorePlugin extends JavaPlugin {
Bukkit.getScheduler().runTask(instance, runnable);
}
public static void async(Runnable runnable) {
Bukkit.getScheduler().runTaskAsynchronously(instance, runnable);
}
@Override
public void onLoad() {
instance = this;
@@ -27,23 +37,49 @@ public class HamsterCorePlugin extends JavaPlugin {
@Override
public void onEnable() {
Logger logger = getLogger();
long start = System.currentTimeMillis();
getLogger().info("仓鼠核心正在启动...");
logger.info("仓鼠核心正在启动...");
CoreBukkitAPI.init();
logger.info("CoreAPI 已初始化.");
VaultAPI.reloadVaultHook();
logger.info("完成 VaultAPI 挂载.");
PointAPI.reloadPlayerPointAPIHook();
logger.info("完成 PlayerPoints 挂载.");
Bukkit.getPluginManager().registerEvents(PageListener.INSTANCE, this);
getLogger().info("已注册 PageListener.");
logger.info("已注册 PageListener.");
Bukkit.getPluginManager().registerEvents(CallbackListener.INSTANCE, this);
logger.info("已注册 CallbackListener.");
Bukkit.getPluginManager().registerEvents(DebugListener.INSTANCE, this);
logger.info("已注册 DebugListener.");
COMMAND_EXECUTOR.addChildCommand(BlockInfoCommand.INSTANCE);
logger.info("已添加指令: " + BlockInfoCommand.INSTANCE.getName() + " .");
COMMAND_EXECUTOR.addChildCommand(YamlCommand.INSTANCE);
logger.info("已添加指令: " + YamlCommand.INSTANCE.getName() + " .");
long time = System.currentTimeMillis() - start;
getLogger().info("仓鼠核心已启动,总计耗时 " + time + " ms.");
logger.info("仓鼠核心已启动,总计耗时 " + time + " ms.");
}
@Override
public void onDisable() {
Logger logger = getLogger();
long start = System.currentTimeMillis();
getLogger().info("仓鼠核心正在关闭...");
logger.info("仓鼠核心正在关闭...");
CoreConstantObjects.WORKER_EXECUTOR.shutdownNow();
getLogger().info("已暂停 WORKER_EXECUTOR.");
logger.info("已暂停 WORKER_EXECUTOR.");
CoreConstantObjects.SCHEDULED_EXECUTOR.shutdownNow();
getLogger().info("已暂停 SCHEDULED_EXECUTOR.");
logger.info("已暂停 SCHEDULED_EXECUTOR.");
long time = System.currentTimeMillis() - start;
getLogger().info("仓鼠核心已关闭,总计耗时 " + time + " ms.");
logger.info("仓鼠核心已关闭,总计耗时 " + time + " ms.");
}
@Override
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
return COMMAND_EXECUTOR.onCommand(sender, command, label, args);
}
@Override
public List<String> onTabComplete(CommandSender sender, Command command, String alias, String[] args) {
return COMMAND_EXECUTOR.onTabComplete(sender, command, alias, args);
}
}

View File

@@ -1,31 +1,46 @@
package cn.hamster3.mc.plugin.core.bukkit.api;
import cn.hamster3.mc.plugin.core.bukkit.HamsterCorePlugin;
import cn.hamster3.mc.plugin.core.common.api.CoreCommonAPI;
import cn.hamster3.mc.plugin.core.common.api.CoreAPI;
import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;
import net.kyori.adventure.platform.AudienceProvider;
import net.kyori.adventure.platform.bukkit.BukkitAudiences;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.configuration.file.FileConfiguration;
import org.jetbrains.annotations.NotNull;
import java.sql.Connection;
import java.sql.SQLException;
@SuppressWarnings("unused")
public class CoreBukkitAPI extends CoreCommonAPI {
private BukkitAudiences audienceProvider;
private HikariDataSource datasource;
public class CoreBukkitAPI extends CoreAPI {
private final BukkitAudiences audienceProvider;
private final HikariDataSource datasource;
public CoreBukkitAPI() {
HamsterCorePlugin plugin = HamsterCorePlugin.getInstance();
audienceProvider = BukkitAudiences.create(plugin);
plugin.saveDefaultConfig();
FileConfiguration config = plugin.getConfig();
ConfigurationSection datasourceConfig = config.getConfigurationSection("datasource");
HikariConfig hikariConfig = new HikariConfig();
hikariConfig.setDriverClassName(datasourceConfig.getString("driver"));
hikariConfig.setJdbcUrl(datasourceConfig.getString("url"));
hikariConfig.setUsername(datasourceConfig.getString("username"));
hikariConfig.setPassword(datasourceConfig.getString("password"));
hikariConfig.setMaximumPoolSize(datasourceConfig.getInt("maximum-pool-size", 3));
hikariConfig.setMinimumIdle(datasourceConfig.getInt("minimum-idle", 1));
hikariConfig.setIdleTimeout(datasourceConfig.getLong("idle-timeout", 5 * 60 * 1000));
hikariConfig.setMaxLifetime(datasourceConfig.getLong("max-lifetime", 0));
datasource = new HikariDataSource(hikariConfig);
}
public static CoreBukkitAPI getInstance() {
return (CoreBukkitAPI) instance;
}
public static void init() {
CoreBukkitAPI api = new CoreBukkitAPI();
instance = api;
api.audienceProvider = BukkitAudiences.create(HamsterCorePlugin.getInstance());
HikariConfig hikariConfig = new HikariConfig();
instance = new CoreBukkitAPI();
}
@Override
@@ -38,17 +53,9 @@ public class CoreBukkitAPI extends CoreCommonAPI {
return datasource;
}
@Override
public @NotNull Connection getConnection() throws SQLException {
return datasource.getConnection();
public void reportError(@NotNull String projectID, @NotNull Throwable exception) {
}
@Override
public void reportError(@NotNull String apiKey, @NotNull String projectID, @NotNull Throwable exception) {
}
@Override
public void reportFile(@NotNull String apiKey, @NotNull String projectID, @NotNull String filename, byte @NotNull [] bytes) {
public void reportFile(@NotNull String projectID, @NotNull String filename, byte @NotNull [] bytes) {
}
}

View File

@@ -0,0 +1,20 @@
package cn.hamster3.mc.plugin.core.bukkit.command;
import org.bukkit.command.TabExecutor;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public abstract class ChildCommand implements TabExecutor {
@NotNull
public abstract String getName();
@NotNull
public abstract String getUsage();
@Nullable
public abstract String getPermission();
@NotNull
public abstract String getDescription();
}

View File

@@ -0,0 +1,93 @@
package cn.hamster3.mc.plugin.core.bukkit.command;
import cn.hamster3.mc.plugin.core.bukkit.constant.CoreMessage;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import org.bukkit.command.TabExecutor;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
@SuppressWarnings("unused")
public class ParentCommand implements TabExecutor {
@NotNull
private final String name;
@Nullable
private final ParentCommand parent;
@NotNull
private final List<ChildCommand> childCommands;
public ParentCommand(@NotNull String name) {
this.name = name;
parent = null;
childCommands = new ArrayList<>();
}
public ParentCommand(@NotNull String name, @Nullable ParentCommand parent) {
this.name = name;
this.parent = parent;
childCommands = new ArrayList<>();
}
@NotNull
public String getUsage() {
if (parent == null) {
return "/" + name;
}
return parent.getUsage() + " " + name;
}
@NotNull
public List<ChildCommand> getChildCommands() {
return childCommands;
}
public void addChildCommand(@NotNull ChildCommand command) {
childCommands.add(command);
}
@Override
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
if (args.length == 0) {
sender.sendMessage("§e==================== [" + name + "使用帮助] ====================");
int maxLength = childCommands.stream()
.filter(o -> o.getPermission() == null || sender.hasPermission(o.getPermission()))
.map(o -> o.getUsage().length())
.max(Integer::compareTo)
.orElse(-1);
for (ChildCommand child : childCommands) {
String permission = child.getPermission();
if (permission != null && !sender.hasPermission(permission)) {
continue;
}
sender.sendMessage(String.format("§a%s %-" + maxLength + "s - %s", getUsage(), child.getUsage(), child.getDescription()));
}
return true;
}
for (ChildCommand childCommand : childCommands) {
if (childCommand.getName().equalsIgnoreCase(args[0])) {
return childCommand.onCommand(sender, command, label, Arrays.copyOfRange(args, 1, args.length));
}
}
CoreMessage.COMMAND_NOT_FOUND.show(sender);
return true;
}
@Override
public List<String> onTabComplete(CommandSender sender, Command command, String alias, String[] args) {
for (ChildCommand child : childCommands) {
if (args[0].equalsIgnoreCase(child.getName())) {
return child.onTabComplete(sender, command, alias, Arrays.copyOfRange(args, 1, args.length));
}
}
args[0] = args[0].toLowerCase();
return childCommands.stream()
.map(ChildCommand::getName)
.filter(o -> o.toLowerCase().startsWith(args[0]))
.collect(Collectors.toList());
}
}

View File

@@ -0,0 +1,81 @@
package cn.hamster3.mc.plugin.core.bukkit.command.debug;
import cn.hamster3.mc.plugin.core.bukkit.command.ChildCommand;
import cn.hamster3.mc.plugin.core.bukkit.constant.CoreMessage;
import cn.hamster3.mc.plugin.core.bukkit.listener.DebugListener;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.List;
import java.util.UUID;
@SuppressWarnings("SpellCheckingInspection")
public class BlockInfoCommand extends ChildCommand {
public static final BlockInfoCommand INSTANCE = new BlockInfoCommand();
private BlockInfoCommand() {
}
@Override
public @NotNull String getName() {
return "blockinfo";
}
@Override
public @NotNull String getUsage() {
return "blockinfo [on/off]";
}
@Override
public @Nullable String getPermission() {
return null;
}
@Override
public @NotNull String getDescription() {
return "开启方块信息查询模式";
}
@Override
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
if (!(sender instanceof Player)) {
CoreMessage.COMMAND_MUST_USED_BY_PLAYER.show(sender);
return true;
}
Player player = (Player) sender;
UUID uuid = player.getUniqueId();
if (args.length >= 1) {
switch (args[0]) {
case "1":
case "on": {
DebugListener.BLOCK_INFO.add(uuid);
CoreMessage.COMMAND_DEBUG_BLOCK_INFO_ON.show(player);
return true;
}
case "0":
case "off": {
DebugListener.BLOCK_INFO.remove(uuid);
CoreMessage.COMMAND_DEBUG_BLOCK_INFO_OFF.show(player);
return true;
}
}
}
if (DebugListener.BLOCK_INFO.contains(uuid)) {
DebugListener.BLOCK_INFO.remove(uuid);
CoreMessage.COMMAND_DEBUG_BLOCK_INFO_OFF.show(player);
} else {
DebugListener.BLOCK_INFO.add(uuid);
CoreMessage.COMMAND_DEBUG_BLOCK_INFO_ON.show(player);
}
return true;
}
@Override
public List<String> onTabComplete(CommandSender sender, Command command, String alias, String[] args) {
return null;
}
}

View File

@@ -0,0 +1,98 @@
package cn.hamster3.mc.plugin.core.bukkit.command.debug;
import cn.hamster3.mc.plugin.core.bukkit.HamsterCorePlugin;
import cn.hamster3.mc.plugin.core.bukkit.command.ChildCommand;
import cn.hamster3.mc.plugin.core.bukkit.util.BukkitUtils;
import org.bukkit.Bukkit;
import org.bukkit.Material;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import org.bukkit.configuration.file.YamlConfiguration;
import org.bukkit.enchantments.Enchantment;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemFlag;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class YamlCommand extends ChildCommand {
public static final YamlCommand INSTANCE = new YamlCommand();
private YamlCommand() {
}
@Override
public @NotNull String getName() {
return "yaml";
}
@Override
public @NotNull String getUsage() {
return "yaml";
}
@Override
public @Nullable String getPermission() {
return null;
}
@Override
public @NotNull String getDescription() {
return "将当前信息保存至 yaml 中";
}
@SuppressWarnings("deprecation")
@Override
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
YamlConfiguration config = new YamlConfiguration();
config.set("mc-version", BukkitUtils.getMCVersion());
config.set("nms-version", BukkitUtils.getNMSVersion());
config.set("server-version", Bukkit.getBukkitVersion());
config.set("bukkit-version", Bukkit.getVersion());
if (sender instanceof Player) {
Player player = (Player) sender;
config.set("player-name", player.getName());
config.set("player-uuid", player.getUniqueId().toString());
config.set("location", player.getLocation());
config.set("hand-item", player.getInventory().getItemInHand());
}
ItemStack stack = new ItemStack(Material.DIAMOND_SWORD);
ItemMeta meta = stack.getItemMeta();
List<String> lore = new ArrayList<>();
lore.add("§e测试 lore 1");
lore.add("§e测试 lore 2");
lore.add("§e测试 lore 3");
meta.addEnchant(Enchantment.DAMAGE_ALL, 1, true);
meta.setDisplayName("§a测试物品");
meta.setLore(lore);
meta.addItemFlags(ItemFlag.values());
stack.setItemMeta(meta);
config.set("test-item", stack);
File dataFolder = new File(HamsterCorePlugin.getInstance().getDataFolder(), "yaml");
if (dataFolder.mkdirs()) {
HamsterCorePlugin.getInstance().getLogger().info("创建 yaml 存档文件夹...");
}
File saveFile = new File(dataFolder, sender.getName() + "_" + System.currentTimeMillis() + ".yml");
try {
config.save(saveFile);
} catch (IOException e) {
e.printStackTrace();
}
sender.sendMessage("§a信息已保存至文件 " + saveFile.getAbsolutePath());
return true;
}
@Override
public List<String> onTabComplete(CommandSender sender, Command command, String alias, String[] args) {
return Collections.emptyList();
}
}

View File

@@ -0,0 +1,20 @@
package cn.hamster3.mc.plugin.core.bukkit.constant;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
public enum CoreMessage {
COMMAND_NOT_FOUND,
COMMAND_MUST_USED_BY_PLAYER,
COMMAND_DEBUG_BLOCK_INFO_ON,
COMMAND_DEBUG_BLOCK_INFO_OFF;
public void show(CommandSender sender) {
sender.sendMessage(name());
}
public void show(Player player) {
player.sendMessage(name());
}
}

View File

@@ -0,0 +1,158 @@
package cn.hamster3.mc.plugin.core.bukkit.hook;
import org.bukkit.Bukkit;
import org.bukkit.OfflinePlayer;
import org.jetbrains.annotations.NotNull;
import java.util.UUID;
/**
* Vault Economy API
*/
@SuppressWarnings("unused")
public class EconomyAPI {
private EconomyAPI() {
}
/**
* 返回服务器是否安装了经济插件
*
* @return true代表安装了false代表未安装
*/
public static boolean isSetupEconomy() {
return VaultAPI.isSetupVault() && VaultAPI.getEconomy() != null;
}
/**
* 给玩家钱
*
* @param player 玩家
* @param money 钱的数量
* @return 成功则返回 true
*/
public static boolean giveMoney(@NotNull final OfflinePlayer player, final double money) {
if (isSetupEconomy()) {
return VaultAPI.getEconomy().depositPlayer(player, money).transactionSuccess();
}
return false;
}
/**
* 给玩家钱
*
* @param uuid 玩家的uuid
* @param money 钱的数量
* @return 成功则返回 true
*/
public static boolean giveMoney(@NotNull final UUID uuid, final double money) {
return giveMoney(Bukkit.getOfflinePlayer(uuid), money);
}
/**
* 从玩家账户上扣钱
*
* @param player 玩家
* @param money 钱的数量
* @return 成功则返回 true
*/
public static boolean takeMoney(@NotNull final OfflinePlayer player, final double money) {
if (isSetupEconomy()) {
return VaultAPI.getEconomy().withdrawPlayer(player, money).transactionSuccess();
}
return false;
}
/**
* 从玩家账户上扣钱
*
* @param uuid 玩家的uuid
* @param money 钱的数量
* @return 成功则返回 true
*/
public static boolean takeMoney(@NotNull final UUID uuid, final double money) {
return takeMoney(Bukkit.getOfflinePlayer(uuid), money);
}
/**
* 设置玩家的余额
*
* @param player 玩家
* @param money 钱的数量
* @return 成功则返回 true
*/
public static boolean setMoney(@NotNull OfflinePlayer player, final double money) {
if (!isSetupEconomy()) {
return false;
}
double v = seeMoney(player);
if (v > money) {
return takeMoney(player, v - money);
} else if (v < money) {
return giveMoney(player, money - v);
}
return true;
}
/**
* 设置玩家的余额
*
* @param uuid 玩家的uuid
* @param money 钱的数量
* @return 成功则返回 true
*/
public static boolean setMoney(@NotNull final UUID uuid, final double money) {
return setMoney(Bukkit.getOfflinePlayer(uuid), money);
}
/**
* 检查玩家有多少钱
* <p>
* 若没有安装经济插件则返回NaN
*
* @param player 玩家
* @return 玩家的余额
*/
public static double seeMoney(@NotNull final OfflinePlayer player) {
if (!isSetupEconomy()) {
return Double.NaN;
}
return VaultAPI.getEconomy().getBalance(player);
}
/**
* 检查玩家有多少钱
* <p>
* 若没有安装经济插件则返回NaN
*
* @param uuid 玩家的uuid
* @return 玩家的余额
*/
public static double seeMoney(@NotNull final UUID uuid) {
return seeMoney(Bukkit.getOfflinePlayer(uuid));
}
/**
* 检测玩家是否有足够的钱
*
* @param player 玩家
* @param money 金钱的数量
* @return 是否有足够的钱(若没有安装经济插件则直接返回 false
*/
public static boolean hasMoney(@NotNull final OfflinePlayer player, final double money) {
if (!isSetupEconomy()) {
return false;
}
return VaultAPI.getEconomy().has(player, money);
}
/**
* 检测玩家是否有足够的钱
*
* @param uuid 玩家的uuid
* @param money 金钱的数量
* @return 是否有足够的钱(若没有安装经济插件则直接返回 false
*/
public static boolean hasMoney(@NotNull final UUID uuid, final double money) {
return hasMoney(Bukkit.getOfflinePlayer(uuid), money);
}
}

View File

@@ -0,0 +1,178 @@
package cn.hamster3.mc.plugin.core.bukkit.hook;
import cn.hamster3.mc.plugin.core.bukkit.HamsterCorePlugin;
import org.black_ixx.playerpoints.PlayerPoints;
import org.black_ixx.playerpoints.PlayerPointsAPI;
import org.bukkit.Bukkit;
import org.bukkit.OfflinePlayer;
import org.bukkit.plugin.Plugin;
import java.util.UUID;
/**
* PlayerPointsAPI
*/
@SuppressWarnings("unused")
public class PointAPI {
private static PlayerPointsAPI playerPointsAPI;
private PointAPI() {
}
/**
* 重载 PlayerPointAPI 点券系统挂接
*/
public static void reloadPlayerPointAPIHook() {
Plugin plugin = Bukkit.getPluginManager().getPlugin("PlayerPoints");
if (plugin == null) {
HamsterCorePlugin.getInstance().getLogger().warning("未检测到 PlayerPointAPI 插件!");
return;
}
playerPointsAPI = ((PlayerPoints) plugin).getAPI();
HamsterCorePlugin.getInstance().getLogger().info("PlayerPointAPI 挂接成功!");
}
/**
* 获取 PlayerPointsAPI 实例
*
* @return PlayerPointsAPI 实例
*/
public static PlayerPointsAPI getPlayerPointsAPI() {
return playerPointsAPI;
}
/**
* 返回服务器是否安装了 PlayerPointAPI 插件
*
* @return true代表安装了false代表未安装
*/
public static boolean isSetupPlayerPointAPI() {
return playerPointsAPI != null;
}
/**
* 给予玩家点券
*
* @param player 玩家
* @param point 点券数量
*/
public static void givePoint(final OfflinePlayer player, final int point) {
if (playerPointsAPI != null) {
playerPointsAPI.give(player.getUniqueId(), point);
}
}
/**
* 给予玩家点券
*
* @param uuid 玩家的uuid
* @param point 点券数量
*/
public static void givePoint(final UUID uuid, final int point) {
if (playerPointsAPI != null) {
playerPointsAPI.give(uuid, point);
}
}
/**
* 扣除玩家点券
*
* @param player 玩家
* @param point 点券数量
*/
public static void takePoint(final OfflinePlayer player, final int point) {
if (playerPointsAPI != null) {
playerPointsAPI.take(player.getUniqueId(), point);
}
}
/**
* 扣除玩家点券
*
* @param uuid 玩家的uuid
* @param point 点券数量
*/
public static void takePoint(final UUID uuid, final int point) {
if (playerPointsAPI != null) {
playerPointsAPI.take(uuid, point);
}
}
/**
* 设置玩家的点券
*
* @param player 玩家
* @param point 点券数量
*/
public static void setPoint(final OfflinePlayer player, final int point) {
if (playerPointsAPI != null) {
playerPointsAPI.set(player.getUniqueId(), point);
}
}
/**
* 设置玩家的点券
*
* @param uuid 玩家的uuid
* @param point 点券数量
*/
public static void setPoint(final UUID uuid, final int point) {
if (playerPointsAPI != null) {
playerPointsAPI.set(uuid, point);
}
}
/**
* 查看玩家的点券数量
*
* @param player 玩家
* @return 玩家的点券数量
*/
public static int seePoint(final OfflinePlayer player) {
if (playerPointsAPI != null) {
return playerPointsAPI.look(player.getUniqueId());
}
return 0;
}
/**
* 查看玩家的点券数量
*
* @param uuid 玩家的uuid
* @return 玩家的点券数量
*/
public static int seePoint(final UUID uuid) {
if (playerPointsAPI != null) {
return playerPointsAPI.look(uuid);
}
return 0;
}
/**
* 检查玩家是否有足够的点券
*
* @param player 玩家
* @param point 点券数量
* @return 若未安装 PlayerPointAPI 则直接返回 false
*/
public static boolean hasPoint(final OfflinePlayer player, final int point) {
if (playerPointsAPI != null) {
return playerPointsAPI.look(player.getUniqueId()) >= point;
}
return false;
}
/**
* 检查玩家是否有足够的点券
*
* @param uuid 玩家的uuid
* @param point 点券数量
* @return 若未安装 PlayerPointAPI 则直接返回 false
*/
public static boolean hasPoint(final UUID uuid, final int point) {
if (playerPointsAPI != null) {
return playerPointsAPI.look(uuid) >= point;
}
return false;
}
}

View File

@@ -0,0 +1,96 @@
package cn.hamster3.mc.plugin.core.bukkit.hook;
import cn.hamster3.mc.plugin.core.bukkit.HamsterCorePlugin;
import net.milkbowl.vault.chat.Chat;
import net.milkbowl.vault.economy.Economy;
import net.milkbowl.vault.permission.Permission;
import org.bukkit.Bukkit;
import org.bukkit.plugin.RegisteredServiceProvider;
/**
* Vault API
*/
@SuppressWarnings("unused")
public class VaultAPI {
private static boolean vaultEnabled;
private static Chat chat;
private static Economy economy;
private static Permission permission;
private VaultAPI() {
}
public static void reloadVaultHook() {
chat = null;
economy = null;
permission = null;
vaultEnabled = Bukkit.getPluginManager().isPluginEnabled("Vault");
if (!vaultEnabled) {
HamsterCorePlugin.getInstance().getLogger().warning("未检测到 Vault 插件!");
return;
}
HamsterCorePlugin.getInstance().getLogger().info("已连接 Vault!");
RegisteredServiceProvider<Chat> chatProvider = Bukkit.getServer().getServicesManager().getRegistration(Chat.class);
if (chatProvider != null) {
chat = chatProvider.getProvider();
HamsterCorePlugin.getInstance().getLogger().info("聊天系统挂接成功.");
} else {
HamsterCorePlugin.getInstance().getLogger().warning("未检测到聊天系统!");
}
RegisteredServiceProvider<Economy> economyProvider = Bukkit.getServer().getServicesManager().getRegistration(Economy.class);
if (economyProvider != null) {
economy = economyProvider.getProvider();
HamsterCorePlugin.getInstance().getLogger().info("经济系统挂接成功.");
} else {
HamsterCorePlugin.getInstance().getLogger().warning("未检测到经济系统!");
}
RegisteredServiceProvider<Permission> permissionProvider = Bukkit.getServer().getServicesManager().getRegistration(Permission.class);
if (permissionProvider != null) {
permission = permissionProvider.getProvider();
HamsterCorePlugin.getInstance().getLogger().info("权限系统挂接成功.");
} else {
HamsterCorePlugin.getInstance().getLogger().warning("未检测到权限插件!");
}
}
/**
* 返回服务器是否安装了 Vault 插件
*
* @return true 代表服务器已安装
*/
public static boolean isSetupVault() {
return vaultEnabled;
}
/**
* 返回 Vault 的 Chat 前置系统
*
* @return Chat 系统
*/
public static Chat getChat() {
return chat;
}
/**
* 返回 Vault 的 Economy 前置系统
*
* @return Economy 系统
*/
public static Economy getEconomy() {
return economy;
}
/**
* 返回 Vault 的 Permission 前置系统
*
* @return Permission 系统
*/
public static Permission getPermission() {
return permission;
}
}

View File

@@ -0,0 +1,78 @@
package cn.hamster3.mc.plugin.core.bukkit.listener;
import org.bukkit.block.Block;
import org.bukkit.entity.Entity;
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.player.AsyncPlayerChatEvent;
import org.bukkit.event.player.PlayerInteractEntityEvent;
import org.bukkit.event.player.PlayerInteractEvent;
import org.bukkit.event.player.PlayerQuitEvent;
import java.util.HashMap;
import java.util.UUID;
import java.util.concurrent.CompletableFuture;
public class CallbackListener implements Listener {
public static final CallbackListener INSTANCE = new CallbackListener();
public static final HashMap<UUID, CompletableFuture<String>> CHATS = new HashMap<>();
public static final HashMap<UUID, CompletableFuture<Block>> BLOCKS = new HashMap<>();
public static final HashMap<UUID, CompletableFuture<Entity>> ENTITIES = new HashMap<>();
private CallbackListener() {
}
@EventHandler(ignoreCancelled = true)
public void onAsyncPlayerChat(AsyncPlayerChatEvent event) {
Player player = event.getPlayer();
CompletableFuture<String> future = CHATS.remove(player.getUniqueId());
if (future == null) {
return;
}
future.complete(event.getMessage());
}
@EventHandler(ignoreCancelled = true)
public void onPlayerInteract(PlayerInteractEvent event) {
if (event.getAction() != Action.RIGHT_CLICK_BLOCK) {
return;
}
Player player = event.getPlayer();
CompletableFuture<Block> future = BLOCKS.remove(player.getUniqueId());
if (future == null) {
return;
}
future.complete(event.getClickedBlock());
}
@EventHandler(ignoreCancelled = true)
public void onPlayerInteractEntity(PlayerInteractEntityEvent event) {
Player player = event.getPlayer();
CompletableFuture<Entity> future = ENTITIES.remove(player.getUniqueId());
if (future == null) {
return;
}
future.complete(event.getRightClicked());
}
@EventHandler(ignoreCancelled = true)
public void onPlayerQuit(PlayerQuitEvent event) {
Player player = event.getPlayer();
UUID uuid = player.getUniqueId();
CompletableFuture<String> chat = CHATS.remove(uuid);
if (chat != null) {
chat.cancel(true);
}
CompletableFuture<Block> block = BLOCKS.remove(uuid);
if (block != null) {
block.cancel(true);
}
CompletableFuture<Entity> entity = ENTITIES.remove(uuid);
if (entity != null) {
entity.cancel(true);
}
}
}

View File

@@ -0,0 +1,57 @@
package cn.hamster3.mc.plugin.core.bukkit.listener;
import org.bukkit.block.Block;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerInteractEvent;
import org.bukkit.event.player.PlayerQuitEvent;
import java.util.HashSet;
import java.util.UUID;
public class DebugListener implements Listener {
public static final DebugListener INSTANCE = new DebugListener();
/**
* 要查看方块信息的玩家
*/
public static final HashSet<UUID> BLOCK_INFO = new HashSet<>();
private DebugListener() {
}
@EventHandler(ignoreCancelled = true)
public void onPlayerQuit(PlayerQuitEvent event) {
Player player = event.getPlayer();
UUID uuid = player.getUniqueId();
BLOCK_INFO.remove(uuid);
}
@EventHandler(ignoreCancelled = true)
public void onPlayerInteract(PlayerInteractEvent event) {
Player player = event.getPlayer();
UUID uuid = player.getUniqueId();
if (!BLOCK_INFO.contains(uuid)) {
return;
}
switch (event.getAction()) {
case LEFT_CLICK_BLOCK:
case LEFT_CLICK_AIR: {
break;
}
default: {
return;
}
}
Block block = event.getClickedBlock();
player.sendMessage("§e==============================");
player.sendMessage(String.format("§a方块位置: %s %d %d %d", block.getWorld().getName(), block.getX(), block.getY(), block.getZ()));
player.sendMessage("§a方块材质: " + block.getType().name());
player.sendMessage("§a方块能量: " + block.getBlockPower());
player.sendMessage("§a方块湿度: " + block.getHumidity());
player.sendMessage("§a自发光亮度: " + block.getLightLevel());
player.sendMessage("§a获取天空亮度: " + block.getLightFromSky());
player.sendMessage("§a方块吸收亮度: " + block.getLightFromBlocks());
event.setCancelled(true);
}
}

View File

@@ -1,9 +1,9 @@
package cn.hamster3.mc.plugin.core.bukkit.page.handler;
import cn.hamster3.mc.plugin.core.bukkit.page.ButtonGroup;
import cn.hamster3.mc.plugin.core.bukkit.page.PageManager;
import cn.hamster3.mc.plugin.core.bukkit.HamsterCorePlugin;
import cn.hamster3.mc.plugin.core.bukkit.page.ButtonGroup;
import cn.hamster3.mc.plugin.core.bukkit.page.PageConfig;
import cn.hamster3.mc.plugin.core.bukkit.page.PageManager;
import org.bukkit.Bukkit;
import org.bukkit.Sound;
import org.bukkit.entity.HumanEntity;

View File

@@ -1,8 +1,8 @@
package cn.hamster3.mc.plugin.core.bukkit.page.handler;
import cn.hamster3.mc.plugin.core.bukkit.page.ButtonGroup;
import cn.hamster3.mc.plugin.core.bukkit.page.PageElement;
import cn.hamster3.mc.plugin.core.bukkit.page.PageConfig;
import cn.hamster3.mc.plugin.core.bukkit.page.PageElement;
import org.bukkit.entity.HumanEntity;
import org.bukkit.event.inventory.ClickType;
import org.bukkit.event.inventory.InventoryAction;

View File

@@ -1,12 +1,9 @@
package cn.hamster3.mc.plugin.core.bukkit.util;
import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;
import org.bukkit.Bukkit;
import org.bukkit.Material;
import org.bukkit.OfflinePlayer;
import org.bukkit.World;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.entity.HumanEntity;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
@@ -17,7 +14,10 @@ import org.jetbrains.annotations.NotNull;
import java.util.UUID;
@SuppressWarnings("unused")
public class BukkitUtils {
public final class BukkitUtils {
private BukkitUtils() {
}
@NotNull
public static String getMCVersion() {
return Bukkit.getBukkitVersion().split("-")[0];
@@ -68,8 +68,10 @@ public class BukkitUtils {
/**
* 获取玩家的头颅
* 在1.11以上的服务端中获取头颅材质是在服务器上运行的
* 因此建议使用异步线程调用该方法
* <p>
* 在 1.11 以上的服务端建议使用异步线程调用该方法
* <p>
* 因为这些服务端中通过网络获取头颅材质是在服务器上运行的
*
* @param offlinePlayer 要获取的玩家
* @return 玩家的头颅物品
@@ -165,30 +167,4 @@ public class BukkitUtils {
}
return stack.getType().name();
}
/**
* 创建 SQL 连接池
*
* @param config SQL 配置
* @return SQL 连接池
*/
@NotNull
public static HikariDataSource getHikariDataSource(@NotNull ConfigurationSection config) {
HikariConfig hikariConfig = new HikariConfig();
hikariConfig.setDriverClassName(config.getString("driver"));
hikariConfig.setJdbcUrl(config.getString("url"));
hikariConfig.setUsername(config.getString("user"));
hikariConfig.setPassword(config.getString("password"));
hikariConfig.setMaximumPoolSize(config.getInt("maximumPoolSize", 3));
hikariConfig.setMinimumIdle(config.getInt("minimumIdle", 1));
hikariConfig.setIdleTimeout(config.getLong("idleTimeout", 5 * 60 * 1000));
hikariConfig.setMaxLifetime(config.getLong("maxLifetime", 0));
return new HikariDataSource(hikariConfig);
}
// todo public static TextComponent getItemDisplayInfo(@NotNull ItemStack stack)
}

View File

@@ -0,0 +1,26 @@
package cn.hamster3.mc.plugin.core.bukkit.util;
import cn.hamster3.mc.plugin.core.bukkit.listener.CallbackListener;
import org.bukkit.block.Block;
import org.bukkit.entity.Entity;
import org.bukkit.entity.HumanEntity;
import java.util.concurrent.CompletableFuture;
@SuppressWarnings("unused")
public final class CallbackUtils {
private CallbackUtils() {
}
public static CompletableFuture<String> getPlayerChat(HumanEntity player) {
return CallbackListener.CHATS.computeIfAbsent(player.getUniqueId(), o -> new CompletableFuture<>());
}
public static CompletableFuture<Block> getPlayerClickedBlock(HumanEntity player) {
return CallbackListener.BLOCKS.computeIfAbsent(player.getUniqueId(), o -> new CompletableFuture<>());
}
public static CompletableFuture<Entity> getPlayerClickedEntity(HumanEntity player) {
return CallbackListener.ENTITIES.computeIfAbsent(player.getUniqueId(), o -> new CompletableFuture<>());
}
}

View File

@@ -0,0 +1,23 @@
datasource:
# 数据库链接驱动地址
# 除非你知道自己在做什么,否则不建议更改该项
driver: "com.mysql.cj.jdbc.Driver"
# 数据库链接填写格式:
# jdbc:mysql://{数据库地址}:{数据库端口}/{使用的库名}?参数
# 除非你知道自己在做什么,否则不建议随意更改参数
url: "jdbc:mysql://sql.hamster3.cn:3306/Test1?serverTimezone=UTC&useUnicode=true&characterEncoding=utf8&autoReconnect=true&useSSL=false"
# 用户名
username: "Test"
# 密码
password: "Test123.."
# 最大链接数
maximum-pool-size: 10
# 最小链接数
minimum-idle: 1
# 超时回收时间
# 单位:毫秒
idle-timeout: 300000
# 链接最长存活时间
# 单位:毫秒
# 建议设置为比数据库上的 wait_timeout 参数少 30 秒
max-lifetime: 1800000

View File

@@ -1,3 +1,22 @@
name: HamsterCore
main: cn.hamster3.mc.plugin.core.bukkit.HamsterCorePlugin
version: ${version}
author: MiniDay
website: https://github.com/MiniDay/hamster-core
description: 仓鼠核心Minecraft 插件开发通用工具包
softdepend:
- Vault
- PlayerPoints
commands:
hamstercore:
aliases: [ hcore, core ]
description: 仓鼠核心调试指令
permission: hamster.core.admin
permission-message: §c你没有这个权限
permissions:
hamster.core.admin:
default: op