1
mirror of https://github.com/CarmJos/UltraDepository.git synced 2026-06-04 16:48:21 +08:00

完成出售GUI,插件更名

This commit is contained in:
2021-12-28 19:31:03 +08:00
parent a8a8f11799
commit 7011d55707
64 changed files with 1169 additions and 1038 deletions
@@ -0,0 +1,173 @@
package cc.carm.plugin.ultrastorehouse;
import cc.carm.plugin.ultrastorehouse.configuration.PluginConfig;
import cc.carm.plugin.ultrastorehouse.hooker.PAPIExpansion;
import cc.carm.plugin.ultrastorehouse.listener.CollectListener;
import cc.carm.plugin.ultrastorehouse.listener.UserListener;
import cc.carm.plugin.ultrastorehouse.manager.DepositoryManager;
import cc.carm.plugin.ultrastorehouse.manager.ConfigManager;
import cc.carm.plugin.ultrastorehouse.manager.EconomyManager;
import cc.carm.plugin.ultrastorehouse.manager.UserManager;
import cc.carm.plugin.ultrastorehouse.storage.DataStorage;
import cc.carm.plugin.ultrastorehouse.storage.FileStorage;
import cc.carm.plugin.ultrastorehouse.storage.MySQLStorage;
import cc.carm.plugin.ultrastorehouse.util.ColorParser;
import cc.carm.plugin.ultrastorehouse.util.MessageUtil;
import cc.carm.plugin.ultrastorehouse.util.SchedulerUtils;
import org.bukkit.Bukkit;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.PluginCommand;
import org.bukkit.command.TabCompleter;
import org.bukkit.event.Listener;
import org.bukkit.plugin.java.JavaPlugin;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public class Main extends JavaPlugin {
private static Main instance;
private static SchedulerUtils scheduler;
private static DataStorage storage;
private static UserManager userManager;
private static EconomyManager economyManager;
private static DepositoryManager depositoryManager;
@Override
public void onEnable() {
instance = this;
scheduler = new SchedulerUtils(this);
log(getName() + " " + getDescription().getVersion() + " &7开始加载...");
long startTime = System.currentTimeMillis();
log("加载配置文件...");
ConfigManager.initConfig();
log("初始化存储方式...");
if (PluginConfig.STORAGE_METHOD.get().equalsIgnoreCase("mysql")) {
log(" 正在使用 MySQL 进行数据存储");
storage = new MySQLStorage();
} else {
log(" 正在使用 文件 进行数据存储");
storage = new FileStorage();
}
if (!storage.initialize()) {
error("存储初始化失败,请检查配置文件。");
setEnabled(false);
return;
}
log("加载用户系统...");
userManager = new UserManager();
log("加载经济系统...");
if (Bukkit.getPluginManager().getPlugin("Vault") != null) {
economyManager = new EconomyManager();
if (!economyManager.initialize()) {
error("经济系统初始化失败,关闭出售功能。");
}
} else {
log(" &7[-] 检测到未安装Vault,关闭出售功能。");
}
log("加载背包管理器...");
depositoryManager = new DepositoryManager();
log("注册监听器...");
regListener(new UserListener());
regListener(new CollectListener());
log("注册指令...");
if (MessageUtil.hasPlaceholderAPI()) {
log("注册变量...");
new PAPIExpansion(this).register();
} else {
log("检测到未安装PlaceholderAPI,跳过变量注册。");
}
log("加载完成 ,共耗时 " + (System.currentTimeMillis() - startTime) + " ms 。");
}
@Override
public void onDisable() {
log(getName() + " " + getDescription().getVersion() + " 开始卸载...");
long startTime = System.currentTimeMillis();
log("保存现有用户数据...");
log("释放存储源...");
getStorage().shutdown();
log("卸载监听器...");
Bukkit.getServicesManager().unregisterAll(this);
log("卸载完成 ,共耗时 " + (System.currentTimeMillis() - startTime) + " ms 。");
}
public static DataStorage getStorage() {
return storage;
}
public static SchedulerUtils getScheduler() {
return scheduler;
}
public static UserManager getUserManager() {
return userManager;
}
public static EconomyManager getEconomyManager() {
return economyManager;
}
public static DepositoryManager getBackpackManager() {
return depositoryManager;
}
/**
* 注册监听器
*
* @param listener 监听器
*/
public static void regListener(@NotNull Listener listener) {
Bukkit.getPluginManager().registerEvents(listener, getInstance());
}
public static void log(@Nullable String message) {
Bukkit.getConsoleSender().sendMessage(ColorParser.parse("[" + getInstance().getName() + "] " + message));
}
public static void error(String message) {
log("&c[ERROR] &r" + message);
}
public static void debug(@Nullable String message) {
if (PluginConfig.DEBUG.get()) log("[DEBUG] " + message);
}
public static Main getInstance() {
return instance;
}
public static void registerCommand(String commandName,
@NotNull CommandExecutor executor) {
registerCommand(commandName, executor, null);
}
public static void registerCommand(String commandName,
@NotNull CommandExecutor executor,
@Nullable TabCompleter tabCompleter) {
PluginCommand command = Bukkit.getPluginCommand(commandName);
if (command == null) return;
command.setExecutor(executor);
if (tabCompleter != null) command.setTabCompleter(tabCompleter);
}
}
@@ -0,0 +1,4 @@
package cc.carm.plugin.ultrastorehouse.command;
public class BackpackCommand {
}
@@ -0,0 +1,194 @@
package cc.carm.plugin.ultrastorehouse.configuration;
import cc.carm.plugin.ultrastorehouse.configuration.message.ConfigMessage;
import cc.carm.plugin.ultrastorehouse.configuration.message.ConfigMessageList;
import cc.carm.plugin.ultrastorehouse.configuration.values.ConfigStringCast;
import cc.carm.plugin.ultrastorehouse.configuration.values.ConfigValue;
import org.bukkit.Material;
public class PluginConfig {
public static final ConfigValue<Boolean> DEBUG = new ConfigValue<>(
"debug", Boolean.class
);
public static final ConfigValue<String> STORAGE_METHOD = new ConfigValue<>(
"storage.method", String.class
);
/**
* 收集配置
*/
public static class Collect {
public static final ConfigValue<Boolean> PICKUP = new ConfigValue<>(
"collect.pickup", Boolean.class, true
);
public static final ConfigValue<Boolean> KILL = new ConfigValue<>(
"collect.kill", Boolean.class, true
);
public static final ConfigValue<Boolean> BREAK = new ConfigValue<>(
"collect.break", Boolean.class, true
);
}
/**
* 通用配置
*/
public static class General {
/**
* 针对每一件物品的额外介绍
* 将添加到背包界面内的物品上,避免重复配置
*/
public static final ConfigMessageList ADDITIONAL_LORE = new ConfigMessageList(
"general.additional-lore", new String[]{
"%(item_name)", "%(amount)", "%(price)", "%(sold)", "%(limit)"
});
/**
* 提示玩家点击行为的介绍
* 将添加到背包界面内的物品上,避免重复配置
*/
public static final ConfigMessageList CLICK_LORE = new ConfigMessageList(
"general.click-lore", new String[]{
"%(item_name)", "%(amount)", "%(price)"
});
/**
* 售出界面的配置
*/
public static class SellGUI {
public static final ConfigMessage TITLE = new ConfigMessage(
"general.sell-gui.title", "&a&l出售",
new String[]{
"%(item_name)", "%(backpack_name)"
}
);
public static class Items {
public static class Add {
public static final ConfigStringCast<Material> TYPE = new ConfigStringCast<>(
"general.sell-gui.items.add.type",
Material::matchMaterial, Material.STONE
);
public static final ConfigValue<Integer> DATA = new ConfigValue<>(
"general.sell-gui.items.add.data", Integer.class, 0
);
public static final ConfigMessage NAME = new ConfigMessage(
"general.sell-gui.items.add.name", "&a添加物品 %(amount) 个",
new String[]{
"%(item_name)", "%(amount)"
}
);
public static final ConfigMessageList LORE = new ConfigMessageList(
"general.sell-gui.items.add.lore", null,
new String[]{
"%(item_name)", "%(amount)"
}
);
}
public static class Remove {
public static final ConfigStringCast<Material> TYPE = new ConfigStringCast<>(
"general.sell-gui.items.remove.type",
Material::matchMaterial, Material.STONE
);
public static final ConfigValue<Integer> DATA = new ConfigValue<>(
"general.sell-gui.items.remove.data", Integer.class, 0
);
public static final ConfigMessage NAME = new ConfigMessage(
"general.sell-gui.items.remove.name", "&c減少物品 %(amount) 个",
new String[]{
"%(item_name)", "%(amount)"
}
);
public static final ConfigMessageList LORE = new ConfigMessageList(
"general.sell-gui.items.remove.lore", null,
new String[]{
"%(item_name)", "%(amount)"
}
);
}
public static class Confirm {
public static final ConfigStringCast<Material> TYPE = new ConfigStringCast<>(
"general.sell-gui.items.confirm.type",
Material::matchMaterial, Material.EMERALD
);
public static final ConfigValue<Integer> DATA = new ConfigValue<>(
"general.sell-gui.items.confirm.data", Integer.class, 0
);
public static final ConfigMessage NAME = new ConfigMessage(
"general.sell-gui.items.confirm.name", "&2确认售出",
new String[]{
"%(item_name)", "%(amount)", "%(money)"
}
);
public static final ConfigMessageList LORE = new ConfigMessageList(
"general.sell-gui.items.confirm.lore", null,
new String[]{
"%(item_name)", "%(amount)", "%(money)"
}
);
}
public static class Cancel {
public static final ConfigStringCast<Material> TYPE = new ConfigStringCast<>(
"general.sell-gui.items.cancel.type",
Material::matchMaterial, Material.REDSTONE
);
public static final ConfigValue<Integer> DATA = new ConfigValue<>(
"general.sell-gui.items.cancel.data", Integer.class, 0
);
public static final ConfigMessage NAME = new ConfigMessage(
"general.sell-gui.items.cancel.name", "&4取消售出"
);
public static final ConfigMessageList LORE = new ConfigMessageList(
"general.sell-gui.items.cancel.lore"
);
}
}
}
}
}
@@ -0,0 +1,16 @@
package cc.carm.plugin.ultrastorehouse.configuration;
import cc.carm.plugin.ultrastorehouse.configuration.message.ConfigMessageList;
public class PluginMessages {
public static final ConfigMessageList SOLD = new ConfigMessageList(
"item-sold", new String[0], new String[]{
"%(item)", "%(amount)", "%(money)"
});
public static final ConfigMessageList COLLECTED = new ConfigMessageList(
"item-collected", new String[0], new String[]{
"%(item)", "%(amount)", "%(backpack)"
});
}
@@ -0,0 +1,53 @@
package cc.carm.plugin.ultrastorehouse.configuration.depository;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class DepositoryCapacity {
int defaultCapacity;
Map<String, Integer> permissions;
public DepositoryCapacity(int defaultCapacity, List<String> permissionStrings) {
this.defaultCapacity = defaultCapacity;
Map<String, Integer> permissions = new HashMap<>();
permissionStrings.stream()
.filter(s -> s.contains(":"))
.map(s -> s.split(":", 1))
.forEach(args -> {
try {
permissions.put(args[0], Integer.parseInt(args[1]));
} catch (Exception ignored) {
}
});
this.permissions = permissions;
}
public DepositoryCapacity(int defaultCapacity, Map<String, Integer> permissions) {
this.defaultCapacity = defaultCapacity;
this.permissions = permissions;
}
public int getDefault() {
return defaultCapacity;
}
public @NotNull Map<String, Integer> getPermissions() {
return permissions;
}
public int getPlayerCapacity(Player player) {
return getPermissions().entrySet().stream()
.filter(entry -> player.hasPermission(entry.getKey()))
.map(Map.Entry::getValue)
.min(Comparator.comparingInt(Integer::intValue))
.orElse(defaultCapacity);
}
}
@@ -0,0 +1,75 @@
package cc.carm.plugin.ultrastorehouse.configuration.depository;
import cc.carm.plugin.ultrastorehouse.util.ItemStackFactory;
import org.bukkit.Material;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.List;
public class DepositoryItem {
final @NotNull Material material;
final int data;
int slot;
double price;
int limit;
@Nullable String name;
@Nullable List<String> lore;
public DepositoryItem(@NotNull Material material, int data,
int slot, int price, int limit,
@Nullable String name, @Nullable List<String> lore) {
this.material = material;
this.data = data;
this.slot = slot;
this.price = price;
this.limit = limit;
this.name = name;
this.lore = lore;
}
public @NotNull String getTypeID() {
return getMaterial().name() + (getData() != 0 ? ":" + getData() : "");
}
public @NotNull Material getMaterial() {
return material;
}
public int getData() {
return data;
}
public int getSlot() {
return slot;
}
public double getPrice() {
return price;
}
public int getLimit() {
return limit;
}
public @Nullable String getName() {
return name;
}
public @Nullable List<String> getLore() {
return lore;
}
public ItemStack getDisplayItem() {
ItemStackFactory factory = new ItemStackFactory(getMaterial(), 1, getData());
if (getName() != null) factory.setDisplayName(getName());
if (getLore() != null) factory.setLore(getLore());
return factory.toItemStack();
}
}
@@ -0,0 +1,50 @@
package cc.carm.plugin.ultrastorehouse.configuration.depository;
import cc.carm.plugin.ultrastorehouse.configuration.gui.GUIConfiguration;
import org.jetbrains.annotations.NotNull;
import java.util.Map;
public class ItemDepository {
final String identifier;
String name;
GUIConfiguration guiConfiguration;
DepositoryCapacity capacity;
Map<String, DepositoryItem> items;
public ItemDepository(String identifier, String name,
GUIConfiguration guiConfiguration,
DepositoryCapacity capacity,
Map<String, DepositoryItem> items) {
this.identifier = identifier;
this.name = name;
this.guiConfiguration = guiConfiguration;
this.capacity = capacity;
this.items = items;
}
public @NotNull String getIdentifier() {
return this.identifier;
}
public @NotNull String getName() {
return this.name;
}
public @NotNull GUIConfiguration getGUIConfiguration() {
return this.guiConfiguration;
}
public @NotNull DepositoryCapacity getCapacity() {
return this.capacity;
}
public @NotNull Map<String, DepositoryItem> getItems() {
return this.items;
}
}
@@ -0,0 +1,76 @@
package cc.carm.plugin.ultrastorehouse.configuration.file;
import org.bukkit.configuration.file.FileConfiguration;
import org.bukkit.configuration.file.YamlConfiguration;
import org.bukkit.plugin.java.JavaPlugin;
import java.io.File;
import java.io.IOException;
public class FileConfig {
private long updateTime;
private final JavaPlugin plugin;
private final String fileName;
private File file;
private FileConfiguration config;
public FileConfig(final JavaPlugin plugin) {
this(plugin, "config.yml");
}
public FileConfig(final JavaPlugin plugin, final String name) {
this.plugin = plugin;
this.fileName = name;
initFile();
}
private void initFile() {
this.updateTime = System.currentTimeMillis();
this.file = new File(plugin.getDataFolder(), fileName);
if (!this.file.exists()) {
if (!this.file.getParentFile().exists()) {
boolean success = this.file.getParentFile().mkdirs();
}
plugin.saveResource(fileName, true);
}
this.config = YamlConfiguration.loadConfiguration(this.file);
}
public File getFile() {
return file;
}
public FileConfiguration getConfig() {
return config;
}
public void save() {
try {
getConfig().save(getFile());
} catch (IOException e) {
e.printStackTrace();
}
}
public void reload() {
this.updateTime = System.currentTimeMillis();
if (getFile().exists()) {
this.config = YamlConfiguration.loadConfiguration(getFile());
} else {
initFile();
}
}
public long getUpdateTime() {
return updateTime;
}
public boolean isExpired(long time) {
return getUpdateTime() > time;
}
}
@@ -0,0 +1,51 @@
package cc.carm.plugin.ultrastorehouse.configuration.gui;
import cc.carm.plugin.ultrastorehouse.util.gui.GUIItem;
import org.bukkit.entity.Player;
import org.bukkit.event.inventory.ClickType;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public class GUIActionConfiguration {
@Nullable ClickType clickType;
final @NotNull GUIActionType actionType;
final @Nullable String actionContent;
public GUIActionConfiguration(@Nullable ClickType clickType, @NotNull GUIActionType actionType, @Nullable String actionContent) {
this.clickType = clickType;
this.actionType = actionType;
this.actionContent = actionContent;
}
public @Nullable ClickType getClickType() {
return clickType;
}
public @NotNull GUIActionType getActionType() {
return actionType;
}
public @Nullable String getActionContent() {
return actionContent;
}
public void checkAction(Player player, ClickType type) {
if (getClickType() == null || getClickType() == type) executeAction(player);
}
public void executeAction(Player targetPlayer) {
getActionType().getExecutor().accept(targetPlayer, getActionContent());
}
public GUIItem.GUIClickAction toClickAction() {
return new GUIItem.GUIClickAction() {
@Override
public void run(ClickType type, Player player) {
checkAction(player, type);
}
};
}
}
@@ -0,0 +1,88 @@
package cc.carm.plugin.ultrastorehouse.configuration.gui;
import cc.carm.plugin.ultrastorehouse.util.MessageUtil;
import org.bukkit.Bukkit;
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.function.BiConsumer;
public enum GUIActionType {
/**
* 以玩家聊天的形式执行
* 若内容以 “/" 开头,则会以玩家身份执行命令。
*/
CHAT((player, string) -> {
if (string == null) return;
MessageUtil.setPlaceholders(player, Collections.singletonList(string)).forEach(player::chat);
}),
/**
* 以后台的形式执行指令
* 指令内容不需要以“/”开头。
*/
CONSOLE((player, string) -> {
if (string == null) return;
MessageUtil.setPlaceholders(player, Collections.singletonList(string))
.forEach(message -> Bukkit.dispatchCommand(Bukkit.getConsoleSender(), message));
}),
/**
* 向玩家发送消息。
*/
MESSAGE(MessageUtil::send),
/**
* 向玩家发送声音。
* 允许配置音量与音调
* <ul>
* <li>SOUND_NAME</li>
* <li>SOUND_NAME:VOLUME</li>
* <li>SOUND_NAME:VOLUME:PITCH</li>
* </ul>
*/
SOUND((player, string) -> {
if (string == null) return;
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;
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) {
}
}),
/**
* 为玩家关闭GUI。
*/
CLOSE((player, string) -> player.closeInventory());
BiConsumer<@NotNull Player, @Nullable String> executor;
GUIActionType(BiConsumer<@NotNull Player, @Nullable String> executor) {
this.executor = executor;
}
public BiConsumer<@NotNull Player, @Nullable String> getExecutor() {
return executor;
}
public static GUIActionType readActionType(String string) {
return Arrays.stream(GUIActionType.values())
.filter(action -> action.name().equalsIgnoreCase(string))
.findFirst().orElse(null);
}
}
@@ -0,0 +1,55 @@
package cc.carm.plugin.ultrastorehouse.configuration.gui;
import cc.carm.plugin.ultrastorehouse.util.ColorParser;
import cc.carm.plugin.ultrastorehouse.util.gui.GUI;
import cc.carm.plugin.ultrastorehouse.util.gui.GUIItem;
import cc.carm.plugin.ultrastorehouse.util.gui.GUIType;
import com.google.common.collect.Multimap;
public class GUIConfiguration {
String title;
int lines;
Multimap<GUIItem, Integer> guiItems;
public GUIConfiguration(String title, int lines, Multimap<GUIItem, Integer> guiItems) {
this.title = title;
this.lines = lines;
this.guiItems = guiItems;
}
public String getTitle() {
return ColorParser.parse(title);
}
public int getLines() {
return lines;
}
public GUIType getGUIType() {
switch (lines) {
case 1:
return GUIType.ONE_BY_NINE;
case 2:
return GUIType.TWO_BY_NINE;
case 3:
return GUIType.THREE_BY_NINE;
case 4:
return GUIType.FOUR_BY_NINE;
case 5:
return GUIType.FIVE_BY_NINE;
default:
return GUIType.SIX_BY_NINE;
}
}
public Multimap<GUIItem, Integer> getGuiItems() {
return guiItems;
}
public void setupItems(GUI gui) {
getGuiItems().forEach((gui::setItem));
}
}
@@ -0,0 +1,54 @@
package cc.carm.plugin.ultrastorehouse.configuration.message;
import cc.carm.plugin.ultrastorehouse.util.MessageUtil;
import cc.carm.plugin.ultrastorehouse.configuration.values.ConfigValue;
import cc.carm.plugin.ultrastorehouse.manager.ConfigManager;
import org.bukkit.command.CommandSender;
import java.util.Collections;
import java.util.List;
public class ConfigMessage extends ConfigValue<String> {
String[] messageParams;
public ConfigMessage(String configSection) {
this(configSection, null);
}
public ConfigMessage(String configSection, String defaultValue) {
this(configSection, defaultValue, null);
}
public ConfigMessage(String configSection, String defaultValue, String[] messageParams) {
super(ConfigManager.getMessageConfig(), configSection, String.class, defaultValue);
this.messageParams = messageParams;
}
public String get(CommandSender sender, Object[] values) {
if (messageParams != null) {
return get(sender, messageParams, values);
} else {
return get(sender, new String[0], new Object[0]);
}
}
public String get(CommandSender sender, String[] params, Object[] values) {
List<String> messages = MessageUtil.setPlaceholders(sender, Collections.singletonList(get()), params, values);
return messages != null && !messages.isEmpty() ? messages.get(0) : "";
}
public void send(CommandSender sender) {
MessageUtil.send(sender, get());
}
public void sendWithPlaceholders(CommandSender sender) {
MessageUtil.sendWithPlaceholders(sender, get());
}
public void sendWithPlaceholders(CommandSender sender, String[] params, Object[] values) {
MessageUtil.sendWithPlaceholders(sender, Collections.singletonList(get()), params, values);
}
}
@@ -0,0 +1,64 @@
package cc.carm.plugin.ultrastorehouse.configuration.message;
import cc.carm.plugin.ultrastorehouse.util.MessageUtil;
import cc.carm.plugin.ultrastorehouse.configuration.values.ConfigValueList;
import cc.carm.plugin.ultrastorehouse.manager.ConfigManager;
import org.bukkit.command.CommandSender;
import org.jetbrains.annotations.Nullable;
import java.util.List;
public class ConfigMessageList extends ConfigValueList<String> {
String[] messageParams;
public ConfigMessageList(String configSection) {
super(ConfigManager.getMessageConfig(), configSection, String.class);
}
public ConfigMessageList(String configSection, String[] defaultValue) {
this(configSection, defaultValue, null);
}
public ConfigMessageList(String configSection, String[] defaultValue, String[] messageParams) {
super(ConfigManager.getMessageConfig(), configSection, String.class, defaultValue);
this.messageParams = messageParams;
}
public List<String> get(@Nullable CommandSender sender) {
return MessageUtil.setPlaceholders(sender, get());
}
public List<String> get(@Nullable CommandSender sender, Object[] values) {
if (messageParams != null) {
return get(sender, messageParams, values);
} else {
return get(sender);
}
}
public List<String> get(@Nullable CommandSender sender, String[] params, Object[] values) {
return MessageUtil.setPlaceholders(sender, get(), params, values);
}
public void send(@Nullable CommandSender sender) {
MessageUtil.send(sender, get());
}
public void sendWithPlaceholders(@Nullable CommandSender sender) {
MessageUtil.sendWithPlaceholders(sender, get());
}
public void sendWithPlaceholders(@Nullable CommandSender sender, Object[] values) {
if (messageParams != null) {
sendWithPlaceholders(sender, messageParams, values);
} else {
sendWithPlaceholders(sender);
}
}
public void sendWithPlaceholders(@Nullable CommandSender sender, String[] params, Object[] values) {
MessageUtil.sendWithPlaceholders(sender, get(), params, values);
}
}
@@ -0,0 +1,72 @@
package cc.carm.plugin.ultrastorehouse.configuration.values;
import cc.carm.plugin.ultrastorehouse.configuration.file.FileConfig;
import cc.carm.plugin.ultrastorehouse.manager.ConfigManager;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.configuration.file.FileConfiguration;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.function.Function;
public class ConfigSectionCast<V> {
FileConfig source;
String configSection;
@NotNull Function<ConfigurationSection, V> valueCast;
V defaultValue;
V valueCache;
long updateTime;
public ConfigSectionCast(String configSection, @NotNull Function<ConfigurationSection, V> valueCast) {
this(configSection, valueCast, null);
}
public ConfigSectionCast(String configSection,
@NotNull Function<ConfigurationSection, V> valueCast,
V defaultValue) {
this(ConfigManager.getPluginConfig(), configSection, valueCast, defaultValue);
}
public ConfigSectionCast(FileConfig source, String configSection,
@NotNull Function<ConfigurationSection, V> valueCast,
V defaultValue) {
this.source = source;
this.configSection = configSection;
this.valueCast = valueCast;
this.defaultValue = defaultValue;
}
public FileConfiguration getConfiguration() {
return this.source.getConfig();
}
public @Nullable V get() {
if (valueCache != null && !this.source.isExpired(this.updateTime)) return valueCache;
if (!getConfiguration().contains(this.configSection)) return defaultValue;
try {
V finalValue = this.valueCast.apply(getConfiguration().getConfigurationSection(this.configSection));
if (finalValue != null) {
this.valueCache = finalValue;
this.updateTime = System.currentTimeMillis();
return finalValue;
} else {
return defaultValue;
}
} catch (Exception ignore) {
return defaultValue;
}
}
public void set(ConfigurationSection section) {
}
public void save() {
this.source.save();
}
}
@@ -0,0 +1,72 @@
package cc.carm.plugin.ultrastorehouse.configuration.values;
import cc.carm.plugin.ultrastorehouse.configuration.file.FileConfig;
import cc.carm.plugin.ultrastorehouse.manager.ConfigManager;
import org.bukkit.configuration.file.FileConfiguration;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.function.Function;
public class ConfigStringCast<V> {
FileConfig source;
String configSection;
@NotNull Function<String, V> valueCast;
V defaultValue;
V valueCache;
long updateTime;
public ConfigStringCast(String configSection, @NotNull Function<String, V> valueCast) {
this(configSection, valueCast, null);
}
public ConfigStringCast(String configSection, @NotNull Function<String, V> valueCast, V defaultValue) {
this(ConfigManager.getPluginConfig(), configSection, valueCast, defaultValue);
}
public ConfigStringCast(FileConfig source, String configSection, @NotNull Function<String, V> valueCast, V defaultValue) {
this.source = source;
this.configSection = configSection;
this.valueCast = valueCast;
this.defaultValue = defaultValue;
}
public FileConfiguration getConfiguration() {
return this.source.getConfig();
}
public @Nullable V get() {
if (valueCache != null && !this.source.isExpired(this.updateTime)) return valueCache;
if (!getConfiguration().contains(this.configSection)) return setDefault();
try {
V finalValue = this.valueCast.apply(getConfiguration().getString(this.configSection));
if (finalValue != null) {
this.valueCache = finalValue;
this.updateTime = System.currentTimeMillis();
return finalValue;
} else {
return defaultValue;
}
} catch (Exception ignore) {
return defaultValue;
}
}
public void set(V value) {
getConfiguration().set(this.configSection, value);
this.save();
}
public void save() {
this.source.save();
}
public V setDefault() {
set(this.defaultValue);
return this.defaultValue;
}
}
@@ -0,0 +1,58 @@
package cc.carm.plugin.ultrastorehouse.configuration.values;
import cc.carm.plugin.ultrastorehouse.configuration.file.FileConfig;
import cc.carm.plugin.ultrastorehouse.manager.ConfigManager;
import org.bukkit.configuration.file.FileConfiguration;
public class ConfigValue<V> {
FileConfig source;
String configSection;
Class<V> clazz;
V defaultValue;
public ConfigValue(String configSection, Class<V> clazz) {
this(configSection, clazz, null);
}
public ConfigValue(String configSection, Class<V> clazz, V defaultValue) {
this(ConfigManager.getPluginConfig(), configSection, clazz, defaultValue);
}
public ConfigValue(FileConfig source, String configSection, Class<V> clazz, V defaultValue) {
this.source = source;
this.configSection = configSection;
this.clazz = clazz;
this.defaultValue = defaultValue;
}
public FileConfiguration getConfiguration() {
return this.source.getConfig();
}
public V get() {
if (getConfiguration().contains(this.configSection)) {
Object val = getConfiguration().get(this.configSection, this.defaultValue);
return this.clazz.isInstance(val) ? this.clazz.cast(val) : this.defaultValue;
} else {
// 如果没有默认值,就把配置写进去,便于配置
return setDefault();
}
}
public void set(V value) {
getConfiguration().set(this.configSection, value);
this.save();
}
public void save() {
this.source.save();
}
public V setDefault() {
set(this.defaultValue);
return this.defaultValue;
}
}
@@ -0,0 +1,72 @@
package cc.carm.plugin.ultrastorehouse.configuration.values;
import cc.carm.plugin.ultrastorehouse.configuration.file.FileConfig;
import cc.carm.plugin.ultrastorehouse.manager.ConfigManager;
import org.bukkit.configuration.file.FileConfiguration;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class ConfigValueList<V> {
FileConfig source;
String configSection;
Class<V> clazz;
V[] defaultValue;
public ConfigValueList(String configSection, Class<V> clazz) {
this(ConfigManager.getPluginConfig(), configSection, clazz);
}
public ConfigValueList(String configSection, Class<V> clazz, V[] defaultValue) {
this(ConfigManager.getPluginConfig(), configSection, clazz, defaultValue);
}
public ConfigValueList(FileConfig configuration, String configSection, Class<V> clazz) {
this(configuration, configSection, clazz, null);
}
public ConfigValueList(FileConfig configuration, String configSection, Class<V> clazz, V[] defaultValue) {
this.source = configuration;
this.configSection = configSection;
this.clazz = clazz;
this.defaultValue = defaultValue;
}
public FileConfiguration getConfiguration() {
return this.source.getConfig();
}
public ArrayList<V> get() {
List<?> list = getConfiguration().getList(this.configSection);
if (list == null) {
if (defaultValue != null) {
return new ArrayList<>(Arrays.asList(defaultValue));
} else {
return new ArrayList<>();
}
} else {
ArrayList<V> result = new ArrayList<>();
for (Object object : list) {
if (this.clazz.isInstance(object)) {
result.add(this.clazz.cast(object));
}
}
return result;
}
}
public void set(ArrayList<V> value) {
getConfiguration().set(this.configSection, value);
this.save();
}
public void save() {
this.source.save();
}
}
@@ -0,0 +1,82 @@
package cc.carm.plugin.ultrastorehouse.configuration.values;
import cc.carm.plugin.ultrastorehouse.configuration.file.FileConfig;
import cc.carm.plugin.ultrastorehouse.manager.ConfigManager;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.configuration.file.FileConfiguration;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Set;
import java.util.function.Function;
public class ConfigValueMap<K, V> {
@NotNull FileConfig source;
@NotNull String configSection;
@NotNull Function<String, K> keyCast;
@NotNull Class<V> valueClazz;
@Nullable LinkedHashMap<K, V> valueCache;
long updateTime;
public ConfigValueMap(@NotNull String configSection, @NotNull Function<String, K> keyCast,
@NotNull Class<V> valueClazz) {
this(ConfigManager.getPluginConfig(), configSection, keyCast, valueClazz);
}
public ConfigValueMap(@NotNull FileConfig configuration, @NotNull String configSection,
@NotNull Function<String, K> keyCast, @NotNull Class<V> valueClazz) {
this.source = configuration;
this.configSection = configSection;
this.keyCast = keyCast;
this.valueClazz = valueClazz;
}
public @NotNull FileConfiguration getConfiguration() {
return this.source.getConfig();
}
public void clearCache() {
this.valueCache = null;
}
@NotNull
public Map<K, V> get() {
if (valueCache != null && !this.source.isExpired(this.updateTime)) return valueCache;
ConfigurationSection section = getConfiguration().getConfigurationSection(this.configSection);
if (section == null) return new LinkedHashMap<>();
Set<String> keys = section.getKeys(false);
if (keys.isEmpty()) return new LinkedHashMap<>();
else {
LinkedHashMap<K, V> result = new LinkedHashMap<>();
for (String key : keys) {
K finalKey = keyCast.apply(key);
Object val = section.get(key);
V finalValue = this.valueClazz.isInstance(val) ? this.valueClazz.cast(val) : null;
if (finalKey != null && finalValue != null) {
result.put(finalKey, finalValue);
}
}
this.updateTime = System.currentTimeMillis();
this.valueCache = result;
return result;
}
}
public void set(HashMap<K, V> valuesMap) {
getConfiguration().createSection(this.configSection, valuesMap);
this.save();
}
public void save() {
this.source.save();
}
}
@@ -0,0 +1,32 @@
package cc.carm.plugin.ultrastorehouse.data;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
public class DepositoryData {
private final Map<@NotNull String, @NotNull ItemData> contents;
public DepositoryData(Map<@NotNull String, @NotNull ItemData> contents) {
this.contents = contents;
}
public @NotNull Map<String, ItemData> getContents() {
return this.contents;
}
public @Nullable ItemData getItemData(@NotNull String itemType) {
return getContents().get(itemType);
}
public static DepositoryData emptyContents(Set<String> itemTypes) {
return new DepositoryData(itemTypes.stream().collect(Collectors.toMap(
item -> item, item -> ItemData.emptyItemData(), (a, b) -> b
)));
}
}
@@ -0,0 +1,44 @@
package cc.carm.plugin.ultrastorehouse.data;
public class ItemData {
int amount;
int sold;
public ItemData(int amount, int sold) {
this.amount = amount;
this.sold = sold;
}
public int getAmount() {
return amount;
}
public int getSold() {
return sold;
}
public void setAmount(int amount) {
this.amount = Math.max(0, amount);
}
public void setSold(int sold) {
this.sold = Math.max(0, sold);
}
public void clearSold() {
this.sold = 0;
}
public static ItemData emptyItemData() {
return new ItemData(0, 0);
}
@Override
public String toString() {
return "UBItemData{" +
"amount=" + amount +
", sold=" + sold +
'}';
}
}
@@ -0,0 +1,162 @@
package cc.carm.plugin.ultrastorehouse.data;
import cc.carm.plugin.ultrastorehouse.Main;
import cc.carm.plugin.ultrastorehouse.configuration.depository.DepositoryItem;
import cc.carm.plugin.ultrastorehouse.configuration.depository.ItemDepository;
import cc.carm.plugin.ultrastorehouse.storage.DataStorage;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.sql.Date;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
public class UserData {
public final UUID userUUID;
DataStorage storage;
Map<String, DepositoryData> backpacks;
Date day;
public UserData(UUID userUUID, DataStorage storage,
Map<String, DepositoryData> backpacks, Date day) {
this.userUUID = userUUID;
this.storage = storage;
this.backpacks = backpacks;
this.day = day;
}
public @NotNull UUID getUserUUID() {
return this.userUUID;
}
public @NotNull Map<String, DepositoryData> getBackpacks() {
return this.backpacks;
}
public @Nullable DepositoryData getBackpackData(String backpackID) {
ItemDepository configuration = Main.getBackpackManager().getDepository(backpackID);
if (configuration == null) return null;
return getBackpackData(configuration);
}
public @NotNull DepositoryData getBackpackData(ItemDepository backpack) {
if (!getBackpacks().containsKey(backpack.getIdentifier())) {
getBackpacks().put(backpack.getIdentifier(), DepositoryData.emptyContents(backpack.getItems().keySet()));
}
return getBackpacks().get(backpack.getIdentifier());
}
public @NotNull Set<String> getBackpackIDs() {
return getBackpacks().keySet();
}
public @Nullable ItemData getItemData(@NotNull String backpackID, @NotNull String typeID) {
DepositoryData data = getBackpackData(backpackID);
if (data == null) return null;
if (!Main.getBackpackManager().hasItem(backpackID, typeID)) return null;
ItemData itemData = data.getItemData(typeID);
if (itemData == null) {
itemData = ItemData.emptyItemData();
data.getContents().put(typeID, itemData);
}
return itemData;
}
public @NotNull ItemData getItemData(@NotNull ItemDepository backpack, @NotNull DepositoryItem itemType) {
DepositoryData data = getBackpackData(backpack);
ItemData itemData = data.getItemData(itemType.getTypeID());
if (itemData == null) {
itemData = ItemData.emptyItemData();
data.getContents().put(itemType.getTypeID(), itemData);
}
return itemData;
}
public @Nullable Integer getItemAmount(@NotNull String backpackID, @NotNull String typeID) {
ItemData data = getItemData(backpackID, typeID);
if (data == null) return null;
return data.getAmount();
}
public @Nullable Integer getItemSold(@NotNull String backpackID, @NotNull String typeID) {
checkoutDate();
ItemData data = getItemData(backpackID, typeID);
if (data == null) return null;
return data.getSold();
}
public @Nullable Integer setItemAmount(@NotNull String backpackID, @NotNull String typeID, int amount) {
ItemData data = getItemData(backpackID, typeID);
if (data == null) return null;
data.setAmount(amount);
return amount;
}
public @Nullable Integer setItemSold(@NotNull String backpackID, @NotNull String typeID, int soldAmount) {
ItemData data = getItemData(backpackID, typeID);
if (data == null) return null;
data.setSold(soldAmount);
return soldAmount;
}
public @Nullable Integer addItemAmount(@NotNull String backpackID, @NotNull String typeID, int amount) {
Integer current = getItemAmount(backpackID, typeID);
if (current == null) return null;
return setItemAmount(backpackID, typeID, current + amount);
}
public @Nullable Integer addItemSold(@NotNull String backpackID, @NotNull String typeID, int amount) {
Integer current = getItemSold(backpackID, typeID);
if (current == null) return null;
return setItemSold(backpackID, typeID, current + amount);
}
public @Nullable Integer removeItemAmount(@NotNull String backpackID, @NotNull String typeID, int amount) {
return addItemAmount(backpackID, typeID, -amount);
}
public @Nullable Integer removeItemSold(@NotNull String backpackID, @NotNull String typeID, int amount) {
return addItemSold(backpackID, typeID, -amount);
}
public Date getDate() {
return this.day;
}
public boolean isCurrentDay() {
return this.day.equals(new Date(System.currentTimeMillis()));
}
public void checkoutDate() {
if (isCurrentDay()) return;
this.day = new Date(System.currentTimeMillis()); //更新日期
getBackpacks().values().stream()
.flatMap(value -> value.getContents().values().stream())
.forEach(ItemData::clearSold);
}
public void save() throws Exception {
this.storage.saveUserData(this);
}
}
@@ -0,0 +1,106 @@
package cc.carm.plugin.ultrastorehouse.hooker;
import cc.carm.plugin.ultrastorehouse.Main;
import me.clip.placeholderapi.expansion.PlaceholderExpansion;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
import java.util.Arrays;
import java.util.List;
public class PAPIExpansion extends PlaceholderExpansion {
private static final List<String> PLACEHOLDERS = Arrays.asList(
"%UltraDepository_amount_<BackpackID>_<ItemTypeID>%",
"%UltraDepository_sold_<BackpackID>_<ItemTypeID>%",
"%UltraDepository_price_<BackpackID>_<ItemTypeID>%",
"%UltraDepository_remain_<BackpackID>_<ItemTypeID>%",
"%UltraDepository_capacity_<BackpackID>%"
);
Main main;
public PAPIExpansion(Main main) {
this.main = main;
}
@Override
public @NotNull List<String> getPlaceholders() {
return PLACEHOLDERS;
}
@Override
public boolean canRegister() {
return true;
}
@Override
public @NotNull String getAuthor() {
return main.getDescription().getAuthors().toString();
}
@Override
public @NotNull String getIdentifier() {
return main.getDescription().getName();
}
@Override
public @NotNull String getVersion() {
return main.getDescription().getVersion();
}
@Override
public String onPlaceholderRequest(Player player, @NotNull String identifier) {
if (player == null) return "加载中...";
String[] args = identifier.split("_");
if (args.length < 1) {
return "参数不足";
}
switch (args[0].toLowerCase()) {
case "amount": {
if (args.length < 3) return "参数不足";
Integer amount = Main.getUserManager().getData(player).getItemAmount(args[2], args[3]);
if (amount == null) return "仓库或物品不存在";
else return amount.toString();
}
case "sold": {
if (args.length < 3) return "参数不足";
Integer sold = Main.getUserManager().getData(player).getItemSold(args[2], args[3]);
if (sold == null) return "仓库或物品不存在";
else return sold.toString();
}
case "remain": {
if (args.length < 3) return "参数不足";
Integer sold = Main.getUserManager().getData(player).getItemSold(args[2], args[3]);
if (sold == null) return "仓库或物品不存在";
Integer limit = Main.getBackpackManager().getItemSellLimit(args[2], args[3]);
if (limit == null) return "仓库或物品不存在";
return Integer.toString(limit - sold);
}
case "limit": {
if (args.length < 3) return "参数不足";
Integer limit = Main.getBackpackManager().getItemSellLimit(args[2], args[3]);
if (limit == null) return "仓库或物品不存在";
else return limit.toString();
}
case "price": {
if (args.length < 3) return "参数不足";
Double price = Main.getBackpackManager().getItemPrice(args[2], args[3]);
if (price == null) return "仓库或物品不存在";
else return price.toString();
}
case "version": {
return getVersion();
}
default: {
return "参数错误";
}
}
}
}
@@ -0,0 +1,71 @@
package cc.carm.plugin.ultrastorehouse.hooker;
import net.milkbowl.vault.economy.Economy;
import net.milkbowl.vault.economy.EconomyResponse;
import org.bukkit.Bukkit;
import org.bukkit.OfflinePlayer;
import org.bukkit.entity.Player;
import org.bukkit.plugin.RegisteredServiceProvider;
public class VaultHooker {
private Economy econ = null;
private EconomyResponse response;
public static boolean hasVault() {
return Bukkit.getServer().getPluginManager().getPlugin("Vault") != null;
}
public boolean setupEconomy() {
if (!hasVault()) {
return false;
}
RegisteredServiceProvider<Economy> rsp = Bukkit.getServer().getServicesManager().getRegistration(Economy.class);
if (rsp == null) {
return false;
}
this.econ = rsp.getProvider();
return true;
}
public Economy getEconomy() {
return econ;
}
public double getMoney(Player player) {
if (player != null) {
try {
return getEconomy().getBalance(player);
} catch (NullPointerException ignore) {
}
}
return 0L;
}
public double getMoney(OfflinePlayer player) {
if (player != null) {
try {
return getEconomy().getBalance(player);
} catch (NullPointerException ignore) {
}
}
return 0L;
}
public void removeMoney(Player player, double amount) {
getEconomy().withdrawPlayer(player, amount);
}
public void removeMoney(OfflinePlayer player, double amount) {
getEconomy().withdrawPlayer(player, amount);
}
public void addMoney(Player player, double amount) {
getEconomy().depositPlayer(player, amount);
}
public void addMoney(OfflinePlayer player, double amount) {
getEconomy().depositPlayer(player, amount);
}
}
@@ -0,0 +1,79 @@
package cc.carm.plugin.ultrastorehouse.listener;
import cc.carm.plugin.ultrastorehouse.Main;
import cc.carm.plugin.ultrastorehouse.configuration.PluginConfig;
import org.bukkit.Location;
import org.bukkit.World;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.block.BlockBreakEvent;
import org.bukkit.event.entity.EntityDeathEvent;
import org.bukkit.event.entity.EntityPickupItemEvent;
import org.bukkit.inventory.ItemStack;
import java.util.Collection;
import java.util.UUID;
public class CollectListener implements Listener {
@EventHandler(priority = EventPriority.HIGH)
public void onBreak(BlockBreakEvent event) {
if (event.isCancelled() || !event.isDropItems() || !PluginConfig.Collect.BREAK.get()) return;
Player player = event.getPlayer();
if (!Main.getUserManager().isCollectEnabled(player)) return;
Location location = event.getBlock().getLocation();
World world = event.getBlock().getWorld();
Collection<ItemStack> drops;
if (player.getItemInUse() == null) {
drops = event.getBlock().getDrops();
} else {
drops = event.getBlock().getDrops(player.getItemInUse(), player.getPlayer());
}
if (drops.isEmpty()) return;
event.setDropItems(false);
Collection<ItemStack> finalDrops = Main.getBackpackManager().collectItem(player, drops);
finalDrops.forEach(finalDrop -> world.dropItemNaturally(location, finalDrop));
}
@EventHandler(priority = EventPriority.HIGH)
public void onDeath(EntityDeathEvent event) {
if (!PluginConfig.Collect.KILL.get()) return;
Player player = event.getEntity().getKiller();
if (player == null) return;
if (!Main.getUserManager().isCollectEnabled(player)) return;
Collection<ItemStack> finalDrops = Main.getBackpackManager().collectItem(player, event.getDrops());
event.getDrops().clear();
event.getDrops().addAll(finalDrops);
}
@EventHandler(priority = EventPriority.HIGH)
public void onPickup(EntityPickupItemEvent event) {
if (event.isCancelled() || !PluginConfig.Collect.PICKUP.get()) return;
if (!(event.getEntity() instanceof Player)) return;
Player player = (Player) event.getEntity();
if (!Main.getUserManager().isCollectEnabled(player)) return;
// 自己扔出去的东西不计入背包
UUID thrower = event.getItem().getThrower();
if (thrower != null && thrower.equals(player.getUniqueId())) return;
ItemStack item = event.getItem().getItemStack();
if (Main.getBackpackManager().collectItem(player, item)) {
event.setCancelled(true);
event.getItem().remove();
}
}
}
@@ -0,0 +1,59 @@
package cc.carm.plugin.ultrastorehouse.listener;
import cc.carm.plugin.ultrastorehouse.Main;
import cc.carm.plugin.ultrastorehouse.data.UserData;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.player.AsyncPlayerPreLoginEvent;
import org.bukkit.event.player.PlayerLoginEvent;
import org.bukkit.event.player.PlayerQuitEvent;
import java.util.UUID;
public class UserListener implements Listener {
@EventHandler(priority = EventPriority.HIGH)
public void onPreLogin(AsyncPlayerPreLoginEvent event) {
if (event.getLoginResult() != AsyncPlayerPreLoginEvent.Result.ALLOWED) {
return;
}
UUID uuid = event.getUniqueId();
Main.debug("尝试加载玩家 " + event.getName() + " 的数据...");
Main.getUserManager().getDataCache().put(uuid, Main.getUserManager().loadData(uuid));
}
@EventHandler(priority = EventPriority.MONITOR)
public void onPreLoginMonitor(AsyncPlayerPreLoginEvent event) {
if (event.getLoginResult() != AsyncPlayerPreLoginEvent.Result.ALLOWED) {
Main.getUserManager().getDataCache().remove(event.getUniqueId());
}
}
@EventHandler(priority = EventPriority.LOWEST)
public void onPlayerLogin(PlayerLoginEvent e) {
UserData data = Main.getUserManager().getData(e.getPlayer().getUniqueId());
if (data == null) {
e.setResult(PlayerLoginEvent.Result.KICK_OTHER);
e.setKickMessage(Main.getInstance().getName() + " 数据未被正确加载,请重新进入。");
}
}
@EventHandler(priority = EventPriority.MONITOR)
public void onQuit(PlayerQuitEvent event) {
Player player = event.getPlayer();
String playerName = player.getName();
UUID playerUUID = player.getUniqueId();
UserData userData = Main.getUserManager().getData(player);
Main.getScheduler().runAsync(() -> {
try {
userData.save();
Main.debug(" 玩家 " + playerName + " 数据已保存并卸载。");
} catch (Exception ignored) {
}
Main.getUserManager().getDataCache().remove(playerUUID);
});
}
}
@@ -0,0 +1,104 @@
package cc.carm.plugin.ultrastorehouse.manager;
import cc.carm.plugin.ultrastorehouse.Main;
import cc.carm.plugin.ultrastorehouse.configuration.file.FileConfig;
import cc.carm.plugin.ultrastorehouse.configuration.gui.GUIActionConfiguration;
import cc.carm.plugin.ultrastorehouse.configuration.gui.GUIActionType;
import cc.carm.plugin.ultrastorehouse.configuration.gui.GUIConfiguration;
import cc.carm.plugin.ultrastorehouse.util.gui.GUIItem;
import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.Multimap;
import org.bukkit.Material;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.event.inventory.ClickType;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.Nullable;
import java.util.*;
public class ConfigManager {
private static FileConfig config;
private static FileConfig messageConfig;
public static void initConfig() {
ConfigManager.config = new FileConfig(Main.getInstance(), "config.yml");
ConfigManager.messageConfig = new FileConfig(Main.getInstance(), "src/main/resources/messages.yml");
}
public static FileConfig getPluginConfig() {
return config;
}
public static FileConfig getMessageConfig() {
return messageConfig;
}
public static void reload() {
getPluginConfig().reload();
getMessageConfig().reload();
}
public static void saveConfig() {
getPluginConfig().save();
getMessageConfig().save();
}
public static GUIConfiguration readConfiguration(ConfigurationSection section) {
String title = section.getString("title", "");
int liens = section.getInt("lines", 6);
Multimap<GUIItem, Integer> guiItemMap = ArrayListMultimap.create();
ConfigurationSection itemsSection = section.getConfigurationSection("items");
if (itemsSection != null) {
itemsSection.getKeys(false).stream()
.map(key -> readItem(itemsSection.getConfigurationSection(key)))
.filter(Objects::nonNull)
.forEach(entry -> guiItemMap.putAll(entry.getKey(), entry.getValue()));
}
return new GUIConfiguration(title, liens, guiItemMap);
}
@Nullable
private static AbstractMap.SimpleEntry<GUIItem, List<Integer>> readItem(@Nullable ConfigurationSection itemSection) {
if (itemSection == null) return null;
ItemStack icon = itemSection.getItemStack("icon", new ItemStack(Material.STONE));
List<Integer> slots = itemSection.getIntegerList("slots");
int slot = itemSection.getInt("slot", 0);
List<String> actionsString = itemSection.getStringList("actions");
List<GUIActionConfiguration> actions = new ArrayList<>();
for (String actionString : actionsString) {
int prefixStart = actionString.indexOf("[");
int prefixEnd = actionString.indexOf("]");
if (prefixStart < 0 || prefixEnd < 0) continue;
String prefix = actionString.substring(prefixStart + 1, prefixEnd);
ClickType clickType = null;
GUIActionType actionType;
if (prefix.contains(":")) {
String[] args = prefix.split(":");
clickType = readClickType(args[0]);
actionType = GUIActionType.readActionType(args[1]);
} else {
actionType = GUIActionType.readActionType(prefix);
}
if (actionType == null) continue;
actions.add(new GUIActionConfiguration(clickType, actionType, actionString.substring(prefixEnd + 1).trim()));
}
GUIItem item = new GUIItem(icon);
actions.stream().map(GUIActionConfiguration::toClickAction).forEach(item::addClickAction);
return new AbstractMap.SimpleEntry<>(item, slots.size() > 0 ? slots : Collections.singletonList(slot));
}
public static ClickType readClickType(String type) {
return Arrays.stream(ClickType.values())
.filter(click -> click.name().equalsIgnoreCase(type))
.findFirst().orElse(null);
}
}
@@ -0,0 +1,147 @@
package cc.carm.plugin.ultrastorehouse.manager;
import cc.carm.plugin.ultrastorehouse.Main;
import cc.carm.plugin.ultrastorehouse.configuration.depository.DepositoryItem;
import cc.carm.plugin.ultrastorehouse.configuration.depository.ItemDepository;
import cc.carm.plugin.ultrastorehouse.data.UserData;
import com.google.common.collect.HashMultimap;
import org.bukkit.Material;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.*;
import java.util.stream.Collectors;
public class DepositoryManager {
/**
* 记录仓库ID对应的仓库实例
*/
public HashMap<@NotNull String, @NotNull ItemDepository> depositories;
/**
* 用于记录储存每个物品ID所对应的背包ID
*/
public HashMultimap<@NotNull String, @NotNull String> itemMap;
public DepositoryManager() {
this.depositories = new HashMap<>();
this.itemMap = HashMultimap.create();
}
public @NotNull HashMap<@NotNull String, @NotNull ItemDepository> getDepositories() {
return depositories;
}
public boolean hasDepository(@NotNull String depositoryID) {
return getDepositories().containsKey(depositoryID);
}
public boolean hasItem(@NotNull String depositoryID, @NotNull String itemTypeID) {
ItemDepository configuration = getDepository(depositoryID);
if (configuration == null) return false;
return hasItem(configuration, itemTypeID);
}
public boolean hasItem(@NotNull ItemDepository depository, @NotNull String itemTypeID) {
return depository.getItems().containsKey(itemTypeID);
}
public @Nullable ItemDepository getDepository(@NotNull String depositoryID) {
return getDepositories().get(depositoryID);
}
public Set<ItemDepository> getItemDepositories(ItemStack itemStack) {
return getItemDepositories(itemStack.getType(), itemStack.getDurability());
}
public @Nullable Set<ItemDepository> getItemDepositories(Material material, int data) {
return Optional.ofNullable(itemMap.get(getItemTypeID(material, data)))
.map(set -> set.stream().map(this::getDepository).collect(Collectors.toSet()))
.orElse(null);
}
public Set<ItemDepository> getPlayerUsableDepository(Player player, ItemStack itemStack) {
String typeID = getItemTypeID(itemStack);
return getItemDepositories(itemStack).stream().filter(configuration -> {
int currentAmount = Optional.ofNullable(Main.getUserManager().getData(player)
.getItemAmount(configuration.getIdentifier(), typeID)).orElse(0);
int depositoryCapacity = configuration.getCapacity().getPlayerCapacity(player);
return currentAmount + itemStack.getAmount() <= depositoryCapacity;
}).collect(Collectors.toSet());
}
public @NotNull String getItemTypeID(Material material, int data) {
return material.name() + ":" + data;
}
public @NotNull String getItemTypeID(ItemStack itemStack) {
return getItemTypeID(itemStack.getType(), itemStack.getDurability());
}
public Collection<ItemStack> collectItem(Player player, Collection<ItemStack> items) {
if (!Main.getUserManager().isCollectEnabled(player)) return new ArrayList<>();
else return items.stream().filter(item -> collectItem(player, item)).collect(Collectors.toList());
}
public boolean collectItem(Player player, ItemStack item) {
if (!Main.getUserManager().isCollectEnabled(player)) return false;
Set<ItemDepository> usableDepositories = getPlayerUsableDepository(player, item);
if (usableDepositories.size() < 1) return false;
ItemDepository depository = usableDepositories.stream().findFirst().orElse(null);
String typeID = getItemTypeID(item);
UserData data = Main.getUserManager().getData(player);
int itemAmount = item.getAmount();
data.addItemAmount(depository.getIdentifier(), typeID, itemAmount);
return true;
}
/**
* 获得某背包配置中的某件物品单价,最低为0。
*
* @param depositoryID 背包ID
* @param itemTypeID 物品ID
* @return 若为空,则该背包或该物品不存在。
*/
public @Nullable Double getItemPrice(@NotNull String depositoryID, @NotNull String itemTypeID) {
ItemDepository configuration = getDepository(depositoryID);
if (configuration == null) return null;
DepositoryItem item = configuration.getItems().get(itemTypeID);
if (item == null) return null;
return item.getPrice();
}
/**
* 获得某背包配置中的某件物品每日售出限制,最低为0。
*
* @param depositoryID 背包ID
* @param itemTypeID 物品ID
* @return 若为空,则该背包或该物品不存在。
*/
public @Nullable Integer getItemSellLimit(@NotNull String depositoryID, @NotNull String itemTypeID) {
ItemDepository configuration = getDepository(depositoryID);
if (configuration == null) return null;
DepositoryItem item = configuration.getItems().get(itemTypeID);
if (item == null) return null;
return item.getLimit();
}
/**
* 获得某背包配置中的某件物品每日售出限制,最低为0。
*
* @param depository 背包
* @param itemTypeID 物品ID
* @return 若为空,则该背包或该物品不存在。
*/
public @Nullable Integer getItemSellLimit(@NotNull ItemDepository depository, @NotNull String itemTypeID) {
DepositoryItem item = depository.getItems().get(itemTypeID);
if (item == null) return null;
return item.getLimit();
}
}
@@ -0,0 +1,37 @@
package cc.carm.plugin.ultrastorehouse.manager;
import cc.carm.plugin.ultrastorehouse.hooker.VaultHooker;
import org.bukkit.entity.Player;
public class EconomyManager {
VaultHooker hooker;
boolean initialized;
public EconomyManager() {
this.hooker = new VaultHooker();
}
public boolean initialize() {
boolean success = this.hooker.setupEconomy();
this.initialized = success;
return success;
}
public boolean isInitialized() {
return initialized;
}
public VaultHooker getHooker() {
return hooker;
}
public double sell(Player player, double price, int amount) {
if (!isInitialized()) return 0D;
double money = price * amount;
getHooker().addMoney(player, money);
return money;
}
}
@@ -0,0 +1,45 @@
package cc.carm.plugin.ultrastorehouse.manager;
import cc.carm.plugin.ultrastorehouse.Main;
import cc.carm.plugin.ultrastorehouse.data.UserData;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.sql.Date;
import java.util.HashMap;
import java.util.UUID;
@SuppressWarnings("BooleanMethodIsAlwaysInverted")
public class UserManager {
private final HashMap<UUID, UserData> dataCache = new HashMap<>();
public HashMap<UUID, UserData> getDataCache() {
return dataCache;
}
public @Nullable UserData getData(@NotNull UUID userUUID) {
return getDataCache().get(userUUID);
}
public @NotNull UserData getData(@NotNull Player player) {
return getDataCache().get(player.getUniqueId());
}
public @NotNull UserData loadData(@NotNull UUID userUUID) {
try {
return Main.getStorage().loadData(userUUID);
} catch (Exception e) {
Main.error("无法正常加载玩家数据,玩家操作将不会被保存,请检查数据配置!");
Main.error("Could not load user's data, please check the data configuration!");
return new UserData(userUUID, Main.getStorage(), new HashMap<>(), new Date(System.currentTimeMillis()));
}
}
public boolean isCollectEnabled(Player player) {
return player.hasPermission("UltraBackpack.use") &&
player.hasPermission("UltraBackpack.auto") &&
player.hasPermission("UltraBackpack.auto.enable");
}
}
@@ -0,0 +1,20 @@
package cc.carm.plugin.ultrastorehouse.storage;
import cc.carm.plugin.ultrastorehouse.data.UserData;
import org.jetbrains.annotations.NotNull;
import java.util.UUID;
public interface DataStorage {
boolean initialize();
void shutdown();
@NotNull
UserData loadData(@NotNull UUID uuid) throws Exception;
void saveUserData(@NotNull UserData data) throws Exception;
}
@@ -0,0 +1,49 @@
package cc.carm.plugin.ultrastorehouse.storage;
import cc.carm.plugin.ultrastorehouse.Main;
import cc.carm.plugin.ultrastorehouse.configuration.values.ConfigValue;
import cc.carm.plugin.ultrastorehouse.data.UserData;
import org.jetbrains.annotations.NotNull;
import java.io.File;
import java.sql.Date;
import java.util.HashMap;
import java.util.UUID;
public class FileStorage implements DataStorage {
private static final ConfigValue<String> FILE_PATH = new ConfigValue<>(
"storage.file-path", String.class, "data"
);
private File dataContainer;
@Override
public boolean initialize() {
return false;
}
@Override
public void shutdown() {
// 似乎没什么需要做的
}
@Override
public @NotNull UserData loadData(@NotNull UUID uuid) {
long start = System.currentTimeMillis();
Main.debug("正通过 FileStorage 加载 " + uuid + " 的用户数据...");
return new UserData(uuid, this, new HashMap<>(), new Date(System.currentTimeMillis()));
}
@Override
public void saveUserData(@NotNull UserData data) {
long start = System.currentTimeMillis();
Main.debug("正通过 FileStorage 保存 " + data.getUserUUID() + " 的用户数据...");
Main.debug(
"通过 FileStorage 保存 " + data.getUserUUID() + " 的用户数据完成," +
"耗时 " + (System.currentTimeMillis() - start) + "ms。"
);
}
}
@@ -0,0 +1,224 @@
package cc.carm.plugin.ultrastorehouse.storage;
import cc.carm.lib.easysql.EasySQL;
import cc.carm.lib.easysql.api.SQLManager;
import cc.carm.lib.easysql.api.action.query.PreparedQueryAction;
import cc.carm.lib.easysql.api.action.query.SQLQuery;
import cc.carm.plugin.ultrastorehouse.Main;
import cc.carm.plugin.ultrastorehouse.data.DepositoryData;
import cc.carm.plugin.ultrastorehouse.data.ItemData;
import cc.carm.plugin.ultrastorehouse.configuration.PluginConfig;
import cc.carm.plugin.ultrastorehouse.configuration.values.ConfigValue;
import cc.carm.plugin.ultrastorehouse.data.UserData;
import com.google.gson.Gson;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.sql.Date;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
public class MySQLStorage implements DataStorage {
private static final ConfigValue<String> DRIVER_NAME = new ConfigValue<>(
"storage.mysql.driver", String.class, "com.mysql.jdbc.Driver"
);
private static final ConfigValue<String> URL = new ConfigValue<>(
"storage.mysql.url", String.class, "jdbc:mysql://127.0.0.1:3306/minecraft"
);
private static final ConfigValue<String> USERNAME = new ConfigValue<>(
"storage.mysql.username", String.class, "username"
);
private static final ConfigValue<String> PASSWORD = new ConfigValue<>(
"storage.mysql.password", String.class, "password"
);
public enum SQLTables {
USER_DATA("ub_data", new String[]{
"`uuid` VARCHAR(36) NOT NULL PRIMARY KEY", // 用户的UUID
"`data` MEDIUMTEXT NOT NULL",// 背包内具体物品
"`day` DATE NOT NULL", // 记录卖出数量的所在天
});
String name;
String[] columns;
SQLTables(String name, String[] columns) {
this.name = name;
this.columns = columns;
}
public static void createTables(SQLManager sqlManager) throws SQLException {
for (SQLTables value : values()) {
sqlManager.createTable(value.getName())
.setColumns(value.getColumns())
.build().execute();
}
}
public String getName() {
return name;
}
public String[] getColumns() {
return columns;
}
}
public static final Gson GSON = new Gson();
public static final JsonParser PARSER = new JsonParser();
SQLManager sqlManager;
@Override
public boolean initialize() {
try {
Main.log(" 尝试连接到数据库...");
this.sqlManager = EasySQL.createManager(DRIVER_NAME.get(), URL.get(), USERNAME.get(), PASSWORD.get());
this.sqlManager.setDebugMode(PluginConfig.DEBUG.get());
} catch (Exception exception) {
Main.error("无法连接到数据库,请检查配置文件。");
Main.error("Could not connect to the database, please check the configuration.");
exception.printStackTrace();
return false;
}
try {
Main.log(" 创建插件所需表...");
SQLTables.createTables(sqlManager);
} catch (SQLException exception) {
Main.error("无法创建插件所需的表,请检查数据库权限。");
Main.error("Could not create necessary tables, please check the database privileges.");
exception.printStackTrace();
return false;
}
return true;
}
@Override
public void shutdown() {
Main.log(" 关闭数据库连接...");
EasySQL.shutdownManager(getSQLManager());
}
@Override
public @NotNull UserData loadData(@NotNull UUID uuid) throws Exception {
long start = System.currentTimeMillis();
Main.debug("正通过 MySQLStorage 加载 " + uuid + " 的用户数据...");
try (SQLQuery query = createAction(uuid).execute()) {
ResultSet resultSet = query.getResultSet();
Map<String, DepositoryData> dataMap = new HashMap<>();
if (resultSet != null && resultSet.next()) {
String dataJSON = resultSet.getString("data");
Date date = resultSet.getDate("day");
JsonElement dataElement = PARSER.parse(dataJSON);
if (dataElement.isJsonObject()) {
dataElement.getAsJsonObject().entrySet().forEach(entry -> {
String backpackID = entry.getKey();
DepositoryData contentsData = parseContentsData(entry.getValue());
if (contentsData != null) dataMap.put(backpackID, contentsData);
});
}
Main.debug("通过 MySQLStorage 加载 " + uuid + " 的用户数据完成,"
+ "耗时 " + (System.currentTimeMillis() - start) + "ms。");
return new UserData(uuid, this, dataMap, date);
}
Main.debug("当前库内不存在玩家 " + uuid + " 的数据,视作新档。");
return new UserData(uuid, this, new HashMap<>(), new Date(System.currentTimeMillis()));
} catch (Exception exception) {
throw new Exception(exception);
}
}
@Override
public void saveUserData(@NotNull UserData data) throws Exception {
long start = System.currentTimeMillis();
Main.debug("正通过 MySQLStorage 保存 " + data.getUserUUID() + " 的用户数据...");
JsonObject dataObject = new JsonObject();
data.getBackpacks().forEach((id, contents) -> dataObject.add(id, serializeContentsData(contents)));
try {
getSQLManager().createReplace(SQLTables.USER_DATA.getName())
.setColumnNames("uuid", "data", "day")
.setParams(data.getUserUUID(), GSON.toJson(dataObject), data.getDate())
.execute();
} catch (SQLException exception) {
Main.error("在保存玩家 #" + data.getUserUUID() + " 的数据时出现异常。");
Main.error("Error occurred when saving #" + data.getUserUUID() + " data.");
throw new Exception(exception);
}
Main.debug("通过 MySQLStorage 保存 " + data.getUserUUID() + " 的用户数据完成," +
"耗时 " + (System.currentTimeMillis() - start) + "ms。");
}
private SQLManager getSQLManager() {
return sqlManager;
}
private PreparedQueryAction createAction(UUID uuid) {
return getSQLManager().createQuery()
.inTable(SQLTables.USER_DATA.getName())
.addCondition("uuid", uuid.toString())
.setLimit(1).build();
}
private DepositoryData parseContentsData(JsonElement contentsElement) {
return contentsElement.isJsonObject() ? parseContentsData(contentsElement.getAsJsonObject()) : null;
}
private DepositoryData parseContentsData(JsonObject contentsObject) {
Map<String, ItemData> contents = new HashMap<>();
for (Map.Entry<String, JsonElement> entry : contentsObject.entrySet()) {
String itemType = entry.getKey();
ItemData data = parseItemData(entry.getValue());
contents.put(itemType, data);
}
return new DepositoryData(contents);
}
private ItemData parseItemData(JsonElement itemElement) {
return itemElement.isJsonObject() ? parseItemData(itemElement.getAsJsonObject()) : null;
}
private ItemData parseItemData(JsonObject itemObject) {
if (!itemObject.has("amount") || !itemObject.has("sold")) {
return ItemData.emptyItemData();
} else {
return new ItemData(itemObject.get("amount").getAsInt(), itemObject.get("sold").getAsInt());
}
}
@Nullable
private JsonObject serializeContentsData(@Nullable DepositoryData contentsData) {
if (contentsData == null) return null;
JsonObject contentsObject = new JsonObject();
contentsData.getContents().forEach((typeID, item) -> contentsObject.add(typeID, serializeItemData(item)));
return contentsObject;
}
@NotNull
private JsonObject serializeItemData(@NotNull ItemData itemData) {
JsonObject itemObject = new JsonObject();
itemObject.addProperty("amount", itemData.getAmount());
itemObject.addProperty("sold", itemData.getSold());
return itemObject;
}
}
@@ -0,0 +1,79 @@
package cc.carm.plugin.ultrastorehouse.ui;
import cc.carm.plugin.ultrastorehouse.Main;
import cc.carm.plugin.ultrastorehouse.configuration.PluginConfig;
import cc.carm.plugin.ultrastorehouse.configuration.depository.DepositoryItem;
import cc.carm.plugin.ultrastorehouse.configuration.depository.ItemDepository;
import cc.carm.plugin.ultrastorehouse.data.ItemData;
import cc.carm.plugin.ultrastorehouse.data.UserData;
import cc.carm.plugin.ultrastorehouse.util.ItemStackFactory;
import cc.carm.plugin.ultrastorehouse.util.gui.GUI;
import cc.carm.plugin.ultrastorehouse.util.gui.GUIItem;
import org.bukkit.Material;
import org.bukkit.entity.Player;
import org.bukkit.event.inventory.ClickType;
import java.util.List;
import java.util.stream.IntStream;
public class DepositoryGUI extends GUI {
Player player;
UserData userData;
ItemDepository configuration;
public DepositoryGUI(Player player, ItemDepository configuration) {
super(configuration.getGUIConfiguration().getGUIType(), configuration.getGUIConfiguration().getTitle());
this.player = player;
this.userData = Main.getUserManager().getData(player);
this.configuration = configuration;
}
public void setupItems() {
configuration.getGUIConfiguration().setupItems(this);
for (DepositoryItem depositoryItem : configuration.getItems().values()) {
setItem(depositoryItem.getSlot(), new GUIItem(depositoryItem.getDisplayItem()));
}
}
private GUIItem createGUIItem(DepositoryItem item) {
ItemStackFactory factory = new ItemStackFactory(item.getDisplayItem());
ItemData itemData = userData.getItemData(configuration, item);
List<String> additionalLore = PluginConfig.General.ADDITIONAL_LORE.get(player, new Object[]{
item.getName(), itemData.getAmount(), item.getPrice(), itemData.getSold(), item.getLimit()
});
additionalLore.forEach(factory::addLore);
List<String> clickLore = PluginConfig.General.CLICK_LORE.get(player, new Object[]{
item.getName(), itemData.getAmount(), item.getPrice()
});
clickLore.forEach(factory::addLore);
return new GUIItem(factory.toItemStack()) {
@Override
public void onClick(ClickType type) {
if (itemData.getAmount() < 1) return;
if (type == ClickType.LEFT) {
SellItemGUI.open(player, userData, itemData, configuration, item);
} else if (type == ClickType.RIGHT) {
if (hasEmptySlot(player)) {
int pickupAmount = Math.min(itemData.getAmount(), item.getMaterial().getMaxStackSize());
} else {
}
}
}
};
}
private 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,191 @@
package cc.carm.plugin.ultrastorehouse.ui;
import cc.carm.plugin.ultrastorehouse.Main;
import cc.carm.plugin.ultrastorehouse.data.ItemData;
import cc.carm.plugin.ultrastorehouse.util.ItemStackFactory;
import cc.carm.plugin.ultrastorehouse.configuration.PluginConfig;
import cc.carm.plugin.ultrastorehouse.configuration.PluginMessages;
import cc.carm.plugin.ultrastorehouse.configuration.depository.ItemDepository;
import cc.carm.plugin.ultrastorehouse.configuration.depository.DepositoryItem;
import cc.carm.plugin.ultrastorehouse.data.UserData;
import cc.carm.plugin.ultrastorehouse.util.gui.GUI;
import cc.carm.plugin.ultrastorehouse.util.gui.GUIItem;
import cc.carm.plugin.ultrastorehouse.util.gui.GUIType;
import org.bukkit.entity.Player;
import org.bukkit.event.inventory.ClickType;
import org.bukkit.inventory.ItemStack;
import java.util.List;
import static cc.carm.plugin.ultrastorehouse.configuration.PluginConfig.General.SellGUI.Items.*;
public class SellItemGUI extends GUI {
final Player player;
final UserData userData;
final ItemData itemData;
final ItemDepository configuration;
final DepositoryItem item;
ItemStack itemDisplay;
int currentAmount;
public SellItemGUI(Player player, UserData userData, ItemData itemData,
ItemDepository configuration, DepositoryItem item) {
super(GUIType.FOUR_BY_NINE, PluginConfig.General.SellGUI.TITLE.get(player, new String[]{
configuration.getName(), item.getName()
}));
this.player = player;
this.userData = userData;
this.itemData = itemData;
this.configuration = configuration;
this.item = item;
this.itemDisplay = item.getDisplayItem();
load(1);
}
private void load(int amount) {
this.currentAmount = Math.max(1, amount); // 不可小于1
loadIcon();
loadButtons();
}
private void loadIcon() {
ItemStackFactory factory = new ItemStackFactory(this.itemDisplay);
List<String> additionalLore = PluginConfig.General.ADDITIONAL_LORE.get(player, new Object[]{
getItemName(), getRemainAmount(), getItemPrice(), getSoldAmount(), getSellLimit()
});
additionalLore.forEach(factory::addLore);
setItem(4, new GUIItem(factory.toItemStack()));
}
private void loadButtons() {
if (getCurrentAmount() > 1000) setItem(0, getRemoveItem(1000));
if (getCurrentAmount() > 100) setItem(1, getRemoveItem(100));
if (getCurrentAmount() > 10) setItem(2, getRemoveItem(10));
if (getCurrentAmount() > 1) setItem(3, getRemoveItem(1));
if (getAddableAmount() > 1) setItem(5, getAddItem(1));
if (getAddableAmount() > 10) setItem(6, getAddItem(10));
if (getAddableAmount() > 100) setItem(7, getAddItem(100));
if (getAddableAmount() > 1000) setItem(8, getAddItem(1000));
if (getCurrentAmount() >= 1) setItem(getConfirmItem(), 27, 28, 29, 30);
setItem(getCancelItem(), 32, 33, 34, 35);
}
private GUIItem getAddItem(int amount) {
ItemStackFactory factory = new ItemStackFactory(Add.TYPE.get());
factory.setDurability(Add.DATA.get());
factory.setDisplayName(Add.NAME.get(player, new Object[]{
getItemName(), getCurrentAmount()
}));
factory.setLore(Add.LORE.get(player, new Object[]{
getItemName(), getCurrentAmount()
}));
return new GUIItem(factory.toItemStack()) {
@Override
public void onClick(ClickType type) {
load(getCurrentAmount() + amount);
updateView();
}
};
}
private GUIItem getRemoveItem(int amount) {
ItemStackFactory factory = new ItemStackFactory(Remove.TYPE.get());
factory.setDurability(Remove.DATA.get());
factory.setDisplayName(Remove.NAME.get(player, new Object[]{
getItemName(), getCurrentAmount()
}));
factory.setLore(Remove.LORE.get(player, new Object[]{
getItemName(), getCurrentAmount()
}));
return new GUIItem(factory.toItemStack()) {
@Override
public void onClick(ClickType type) {
load(getCurrentAmount() - amount);
updateView();
}
};
}
private GUIItem getConfirmItem() {
ItemStackFactory factory = new ItemStackFactory(Confirm.TYPE.get());
factory.setDurability(Confirm.DATA.get());
factory.setDisplayName(Confirm.NAME.get(player, new Object[]{
getItemName(), getCurrentAmount(), getTotalMoney()
}));
factory.setLore(Confirm.LORE.get(player, new Object[]{
getItemName(), getCurrentAmount(), getTotalMoney()
}));
return new GUIItem(factory.toItemStack()) {
@Override
public void onClick(ClickType type) {
int amount = Math.min(getCurrentAmount(), Math.min(getRemainAmount(), getSellLimit() - getSoldAmount()));
if (amount > 0) {
double money = Main.getEconomyManager().sell(player, getItemPrice(), amount);
PluginMessages.SOLD.sendWithPlaceholders(player, new Object[]{
getItemName(), amount, money
});
}
player.closeInventory();
}
};
}
private GUIItem getCancelItem() {
ItemStackFactory factory = new ItemStackFactory(Cancel.TYPE.get());
factory.setDurability(Cancel.DATA.get());
factory.setDisplayName(Cancel.NAME.get());
factory.setLore(Cancel.LORE.get());
return new GUIItem(factory.toItemStack()) {
@Override
public void onClick(ClickType type) {
player.closeInventory();
}
};
}
private String getItemName() {
return this.item.getName();
}
public int getCurrentAmount() {
return currentAmount;
}
private double getItemPrice() {
return this.item.getPrice();
}
private int getSellLimit() {
return this.item.getLimit();
}
private double getTotalMoney() {
return getCurrentAmount() * getItemPrice();
}
private int getRemainAmount() {
return this.itemData.getAmount();
}
private int getSoldAmount() {
return this.itemData.getSold();
}
private int getAddableAmount() {
return Math.min(getRemainAmount(), getSellLimit() - getSoldAmount()) - getCurrentAmount();
}
public static void open(Player player, UserData userData, ItemData itemData,
ItemDepository configuration, DepositoryItem item) {
if (!Main.getEconomyManager().isInitialized()) return;
SellItemGUI gui = new SellItemGUI(player, userData, itemData, configuration, item);
gui.openGUI(player);
}
}
@@ -0,0 +1,33 @@
package cc.carm.plugin.ultrastorehouse.util;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class ColorParser {
public static String parse(String text) {
text = parseHexColor(text);
return parseColor(text);
}
public static String parseColor(final String text) {
return text.replaceAll("&", "§").replace("§§", "&");
}
public static String parseHexColor(String text) {
Pattern pattern = Pattern.compile("&\\((&?#[0-9a-fA-F]{6})\\)");
Matcher matcher = pattern.matcher(text);
while (matcher.find()) {
String hexColor = text.substring(matcher.start() + 2, matcher.end() - 1);
hexColor = hexColor.replace("&", "");
StringBuilder bukkitColorCode = new StringBuilder('§' + "x");
for (int i = 1; i < hexColor.length(); i++) {
bukkitColorCode.append('§').append(hexColor.charAt(i));
}
text = text.replaceAll("&\\(" + hexColor + "\\)", bukkitColorCode.toString().toLowerCase());
matcher.reset(text);
}
return text;
}
}
@@ -0,0 +1,139 @@
package cc.carm.plugin.ultrastorehouse.util;
import org.bukkit.Material;
import org.bukkit.enchantments.Enchantment;
import org.bukkit.inventory.ItemFlag;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import org.jetbrains.annotations.NotNull;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
public class ItemStackFactory {
ItemStack item;
private ItemStackFactory() {
}
public ItemStackFactory(ItemStack is) {
this.item = is.clone();
}
public ItemStackFactory(Material type) {
this(type, 1);
}
public ItemStackFactory(Material type, int amount) {
this(type, amount, (short) 0);
}
public ItemStackFactory(Material type, int amount, short data) {
this.item = new ItemStack(type, amount, data);
}
public ItemStackFactory(Material type, int amount, int data) {
this(type, amount, (short) data);
}
public ItemStack toItemStack() {
return this.item;
}
public ItemStackFactory setType(Material type) {
this.item.setType(type);
return this;
}
public ItemStackFactory setDurability(int i) {
this.item.setDurability((short) i);
return this;
}
public ItemStackFactory setAmount(int a) {
this.item.setAmount(a);
return this;
}
public ItemStackFactory setDisplayName(@NotNull String name) {
ItemMeta im = this.item.getItemMeta();
if (im != null) {
im.setDisplayName(ColorParser.parse(name));
this.item.setItemMeta(im);
}
return this;
}
public ItemStackFactory setLore(@NotNull List<String> loreList) {
ItemMeta im = this.item.getItemMeta();
if (im != null) {
im.setLore(
loreList.stream()
.map(ColorParser::parse)
.collect(Collectors.toList())
);
this.item.setItemMeta(im);
}
return this;
}
public ItemStackFactory addLore(@NotNull String s) {
ItemMeta im = this.item.getItemMeta();
if (im != null) {
List<String> lore = im.getLore() != null ? im.getLore() : new ArrayList<>();
lore.add(ColorParser.parse(s));
im.setLore(lore);
this.item.setItemMeta(im);
}
return this;
}
public ItemStackFactory addEnchant(@NotNull Enchantment enchant, int level, boolean ignoreLevelRestriction) {
ItemMeta im = this.item.getItemMeta();
if (im != null) {
im.addEnchant(enchant, level, ignoreLevelRestriction);
this.item.setItemMeta(im);
}
return this;
}
public ItemStackFactory removeEnchant(@NotNull Enchantment enchant) {
ItemMeta im = this.item.getItemMeta();
if (im != null) {
im.removeEnchant(enchant);
this.item.setItemMeta(im);
}
return this;
}
public ItemStackFactory addFlag(@NotNull ItemFlag flag) {
ItemMeta im = this.item.getItemMeta();
if (im != null) {
im.addItemFlags(flag);
this.item.setItemMeta(im);
}
return this;
}
public ItemStackFactory removeFlag(@NotNull ItemFlag flag) {
ItemMeta im = this.item.getItemMeta();
if (im != null) {
im.removeItemFlags(flag);
this.item.setItemMeta(im);
}
return this;
}
public ItemStackFactory setUnbreakable(boolean unbreakable) {
ItemMeta im = this.item.getItemMeta();
if (im != null) {
im.setUnbreakable(unbreakable);
this.item.setItemMeta(im);
}
return this;
}
}
@@ -0,0 +1,85 @@
package cc.carm.plugin.ultrastorehouse.util;
import me.clip.placeholderapi.PlaceholderAPI;
import org.bukkit.Bukkit;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.Nullable;
import java.util.*;
public class MessageUtil {
public static boolean hasPlaceholderAPI() {
return Bukkit.getPluginManager().getPlugin("PlaceholderAPI") != null;
}
public static void send(@Nullable CommandSender sender, List<String> messages) {
if (messages == null || messages.isEmpty() || sender == null) return;
for (String s : messages) {
sender.sendMessage(ColorParser.parse(s));
}
}
public static void send(@Nullable CommandSender sender, String... messages) {
send(sender, Arrays.asList(messages));
}
public static void sendWithPlaceholders(CommandSender sender, String... messages) {
sendWithPlaceholders(sender, Arrays.asList(messages));
}
public static void sendWithPlaceholders(@Nullable CommandSender sender, List<String> messages) {
if (messages == null || messages.isEmpty() || sender == null) return;
send(sender, setPlaceholders(sender, messages));
}
public static void sendWithPlaceholders(@Nullable CommandSender sender, List<String> messages, String param, Object value) {
sendWithPlaceholders(sender, messages, new String[]{param}, new Object[]{value});
}
public static void sendWithPlaceholders(@Nullable CommandSender sender, List<String> messages, String[] params, Object[] values) {
sendWithPlaceholders(sender, setCustomParams(messages, params, values));
}
public static List<String> setPlaceholders(@Nullable CommandSender sender, List<String> messages) {
if (messages == null || messages.isEmpty() || sender == null) return messages;
if (hasPlaceholderAPI() && sender instanceof Player) {
return PlaceholderAPI.setPlaceholders((Player) sender, messages);
} else {
return messages;
}
}
public static List<String> setPlaceholders(@Nullable CommandSender sender, List<String> messages, String[] params, Object[] values) {
return setPlaceholders(sender, setCustomParams(messages, params, values));
}
public static List<String> setCustomParams(List<String> messages, String param, Object value) {
return setCustomParams(messages, new String[]{param}, new Object[]{value});
}
public static List<String> setCustomParams(List<String> messages, String[] params, Object[] values) {
if (params.length != values.length) return messages;
HashMap<String, Object> paramsMap = new HashMap<>();
for (int i = 0; i < params.length; i++) {
paramsMap.put(params[i], values[i]);
}
return setCustomParams(messages, paramsMap);
}
public static List<String> setCustomParams(List<String> messages, HashMap<String, Object> params) {
List<String> list = new ArrayList<>();
for (String message : messages) {
String afterMessage = message;
for (Map.Entry<String, Object> entry : params.entrySet()) {
afterMessage = afterMessage.replace(entry.getKey(), entry.getValue().toString());
}
list.add(afterMessage);
}
return list;
}
}
@@ -0,0 +1,351 @@
package cc.carm.plugin.ultrastorehouse.util;
import org.bukkit.Bukkit;
import org.bukkit.plugin.java.JavaPlugin;
import org.bukkit.scheduler.BukkitRunnable;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.Queue;
import java.util.concurrent.Callable;
public class SchedulerUtils {
private final JavaPlugin plugin;
public SchedulerUtils(JavaPlugin plugin) {
this.plugin = plugin;
}
private JavaPlugin getPlugin() {
return plugin;
}
/**
* 在主线程延时执行一个任务。
*
* @param delay 延迟的ticks
* @param runnable 需要执行的任务
*/
public void runLater(long delay, Runnable runnable) {
Bukkit.getScheduler().runTaskLater(getPlugin(), runnable, delay);
}
/**
* 异步延时执行一个任务。
*
* @param delay 延迟的ticks
* @param runnable 需要执行的任务
*/
public void runLaterAsync(long delay, Runnable runnable) {
Bukkit.getScheduler().runTaskLaterAsynchronously(getPlugin(), runnable, delay);
}
/**
* 异步执行一个任务。
*
* @param runnable 需要执行的任务
*/
public void runAsync(Runnable runnable) {
Bukkit.getScheduler().runTaskAsynchronously(getPlugin(), runnable);
}
/**
* 在服务端主线程中执行一个任务
*
* @param runnable 需要执行的任务
*/
public void run(Runnable runnable) {
Bukkit.getScheduler().runTask(getPlugin(), runnable);
}
/**
* 间隔一段时间按顺序异步执行列表中的任务
*
* @param interval 间隔时间
* @param tasks 任务列表
*/
public void runAtIntervalAsync(long interval, Runnable... tasks) {
runAtIntervalAsync(0L, interval, tasks);
}
/**
* 间隔一段时间按顺序执行列表中的任务
*
* @param interval 间隔时间
* @param tasks 任务列表
*/
public void runAtInterval(long interval, Runnable... tasks) {
runAtInterval(0L, interval, tasks);
}
/**
* 间隔一段时间按顺序异步执行列表中的任务
*
* @param delay 延迟时间
* @param interval 间隔时间
* @param tasks 任务列表
*/
public void runAtIntervalAsync(long delay, long interval, Runnable... tasks) {
new BukkitRunnable() {
private int index;
@Override
public void run() {
if (this.index >= tasks.length) {
this.cancel();
return;
}
tasks[index].run();
index++;
}
}.runTaskTimerAsynchronously(getPlugin(), delay, interval);
}
/**
* 间隔一段时间按顺序执行列表中的任务
*
* @param delay 延迟时间
* @param interval 间隔时间
* @param tasks 任务列表
*/
public void runAtInterval(long delay, long interval, Runnable... tasks) {
new BukkitRunnable() {
private int index;
@Override
public void run() {
if (this.index >= tasks.length) {
this.cancel();
return;
}
tasks[index].run();
index++;
}
}.runTaskTimer(getPlugin(), delay, interval);
}
/**
* 重复执行一个任务。
*
* @param repetitions 重复次数
* @param interval 间隔时间
* @param task 任务
* @param onComplete 结束时执行的任务
*/
public void repeat(int repetitions, long interval, Runnable task, Runnable onComplete) {
new BukkitRunnable() {
private int index;
@Override
public void run() {
index++;
if (this.index >= repetitions) {
this.cancel();
if (onComplete == null) {
return;
}
onComplete.run();
return;
}
task.run();
}
}.runTaskTimer(getPlugin(), 0L, interval);
}
/**
* 重复执行一个任务。
*
* @param repetitions 重复次数
* @param interval 间隔时间
* @param task 任务
* @param onComplete 结束时执行的任务
*/
public void repeatAsync(int repetitions, long interval, Runnable task, Runnable onComplete) {
new BukkitRunnable() {
private int index;
@Override
public void run() {
index++;
if (this.index >= repetitions) {
this.cancel();
if (onComplete == null) {
return;
}
onComplete.run();
return;
}
task.run();
}
}.runTaskTimerAsynchronously(getPlugin(), 0L, interval);
}
/**
* 在满足某个条件时,重复执行一个任务。
*
* @param interval 重复间隔时间
* @param predicate 条件
* @param task 任务
* @param onComplete 结束时执行的任务
*/
public void repeatWhile(long interval, Callable<Boolean> predicate, Runnable task, Runnable onComplete) {
new BukkitRunnable() {
@Override
public void run() {
try {
if (!predicate.call()) {
this.cancel();
if (onComplete == null) {
return;
}
onComplete.run();
return;
}
task.run();
} catch (Exception e) {
e.printStackTrace();
}
}
}.runTaskTimer(getPlugin(), 0L, interval);
}
/**
* 在满足某个条件时,重复执行一个任务。
*
* @param interval 重复间隔时间
* @param predicate 条件
* @param task 任务
* @param onComplete 结束时执行的任务
*/
public void repeatWhileAsync(long interval, Callable<Boolean> predicate, Runnable task, Runnable onComplete) {
new BukkitRunnable() {
@Override
public void run() {
try {
if (!predicate.call()) {
this.cancel();
if (onComplete == null) {
return;
}
onComplete.run();
return;
}
task.run();
} catch (Exception e) {
e.printStackTrace();
}
}
}.runTaskTimerAsynchronously(getPlugin(), 0L, interval);
}
public interface Task {
void start(Runnable onComplete);
}
public class TaskBuilder {
private Queue<Task> taskList;
public TaskBuilder() {
this.taskList = new LinkedList<>();
}
public TaskBuilder append(TaskBuilder builder) {
this.taskList.addAll(builder.taskList);
return this;
}
public TaskBuilder appendDelay(long delay) {
this.taskList.add(onComplete -> SchedulerUtils.this.runLater(delay, onComplete));
return this;
}
public TaskBuilder appendTask(Runnable task) {
this.taskList.add(onComplete ->
{
task.run();
onComplete.run();
});
return this;
}
public TaskBuilder appendTask(Task task) {
this.taskList.add(task);
return this;
}
public TaskBuilder appendDelayedTask(long delay, Runnable task) {
this.taskList.add(onComplete -> SchedulerUtils.this.runLater(delay, () ->
{
task.run();
onComplete.run();
}));
return this;
}
public TaskBuilder appendTasks(long delay, long interval, Runnable... tasks) {
this.taskList.add(onComplete ->
{
Runnable[] runnables = Arrays.copyOf(tasks, tasks.length + 1);
runnables[runnables.length - 1] = onComplete;
SchedulerUtils.this.runAtInterval(delay, interval, runnables);
});
return this;
}
public TaskBuilder appendRepeatingTask(int repetitions, long interval, Runnable task) {
this.taskList.add(onComplete -> SchedulerUtils.this.repeat(repetitions, interval, task, onComplete));
return this;
}
public TaskBuilder appendConditionalRepeatingTask(long interval, Callable<Boolean> predicate, Runnable task) {
this.taskList.add(onComplete -> SchedulerUtils.this.repeatWhile(interval, predicate, task, onComplete));
return this;
}
public TaskBuilder waitFor(Callable<Boolean> predicate) {
this.taskList.add(onComplete -> new BukkitRunnable() {
@Override
public void run() {
try {
if (!predicate.call()) {
return;
}
this.cancel();
onComplete.run();
} catch (Exception e) {
e.printStackTrace();
}
}
}.runTaskTimer(getPlugin(), 0L, 1L));
return this;
}
public void runTasks() {
this.startNext();
}
private void startNext() {
Task task = this.taskList.poll();
if (task == null) {
return;
}
task.start(this::startNext);
}
}
}
@@ -0,0 +1,222 @@
package cc.carm.plugin.ultrastorehouse.util.gui;
import cc.carm.plugin.ultrastorehouse.Main;
import cc.carm.plugin.ultrastorehouse.util.ColorParser;
import org.bukkit.Bukkit;
import org.bukkit.Material;
import org.bukkit.entity.HumanEntity;
import org.bukkit.entity.Player;
import org.bukkit.event.inventory.InventoryClickEvent;
import org.bukkit.event.inventory.InventoryDragEvent;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemStack;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.IntStream;
public class GUI {
private static final HashMap<Player, GUI> openedGUIs = new HashMap<>();
GUIType type;
String name;
public GUIItem[] items;
public Inventory inv;
boolean cancelOnTarget = true;
boolean cancelOnSelf = true;
boolean cancelOnOuter = true;
Map<String, Object> flags;
public GUIListener listener;
public GUI(GUIType type, String name) {
this.type = type;
this.name = ColorParser.parse(name);
switch (type) {
case ONE_BY_NINE:
this.items = new GUIItem[9];
break;
case TWO_BY_NINE:
this.items = new GUIItem[18];
break;
case THREE_BY_NINE:
this.items = new GUIItem[27];
break;
case FOUR_BY_NINE:
this.items = new GUIItem[36];
break;
case FIVE_BY_NINE:
this.items = new GUIItem[45];
break;
case SIX_BY_NINE:
this.items = new GUIItem[54];
break;
case CANCEL:
default:
this.items = null;
}
}
public final void setItem(int index, GUIItem item) {
if (item == null) {
this.items[index] = new GUIItem(new ItemStack(Material.AIR));
} else {
this.items[index] = item;
}
}
/**
* 批量添加GUI Item
*
* @param item 物品
* @param index 对应格
*/
public void setItem(GUIItem item, int... index) {
Arrays.stream(index).forEach(i -> setItem(i, item));
}
public void setItem(GUIItem item, int start, int end) {
IntStream.rangeClosed(start, end).forEach(i -> setItem(i, item));
}
public GUIItem getItem(int index) {
return this.items[index];
}
/**
* 更新玩家箱子的视图
*/
public void updateView() {
if (this.inv != null) {
List<HumanEntity> viewers = this.inv.getViewers();
IntStream.range(0, this.items.length).forEach(index -> {
GUIItem item = items[index];
if (item == null) {
inv.setItem(index, new ItemStack(Material.AIR));
} else {
inv.setItem(index, items[index].display);
}
});
for (HumanEntity p : viewers) {
((Player) p).updateInventory();
}
}
}
/**
* 设置是否取消点击GUI内物品的事件
* 如果不取消,玩家可以从GUI中拿取物品。
*
* @param b 是否取消
*/
public void setCancelledIfClickOnTarget(boolean b) {
this.cancelOnTarget = b;
}
/**
* 设置是否取消点击自己背包内物品的事件
* 如果不取消,玩家可以从自己的背包中拿取物品。
*
* @param b 是否取消
*/
public void setCancelledIfClickOnSelf(boolean b) {
this.cancelOnSelf = b;
}
/**
* 设置是否取消点击GUI外的事件
* 如果不取消,玩家可以把物品从GUI或背包中丢出去
*
* @param b 是否取消
*/
public void setCancelledIfClickOnOuter(boolean b) {
this.cancelOnOuter = b;
}
public void addFlag(String flag, Object obj) {
if (this.flags == null) this.flags = new HashMap<>();
this.flags.put(flag, obj);
}
public Object getFlag(String flag) {
if (this.flags == null) return null;
else
return this.flags.get(flag);
}
public void setFlag(String flag, Object obj) {
if (this.flags == null) this.flags = new HashMap<>();
this.flags.replace(flag, obj);
}
public void removeFlag(String flag) {
if (this.flags == null) this.flags = new HashMap<>();
this.flags.remove(flag);
}
public void rawClickListener(InventoryClickEvent event) {
}
public void openGUI(Player player) {
Inventory inv;
if (this.type == GUIType.CANCEL) {
throw new NullPointerException("被取消或不存在的GUI");
}
inv = Bukkit.createInventory(null, this.items.length, this.name);
for (int index = 0; index < this.items.length; index++) {
if (items[index] == null) {
inv.setItem(index, new ItemStack(Material.AIR));
} else {
inv.setItem(index, items[index].display);
}
}
setOpenedGUI(player, this);
this.inv = inv;
player.openInventory(inv);
if (listener == null) {
Main.regListener(listener = new GUIListener(this, player));
}
}
/**
* 拖动GUI内物品时执行的代码
*
* @param event InventoryDragEvent
*/
public void onDrag(InventoryDragEvent event) {
}
/**
* 关闭GUI时执行的代码
*/
public void onClose() {
}
public static void setOpenedGUI(Player player, GUI gui) {
openedGUIs.put(player, gui);
}
public static boolean hasOpenedGUI(Player player) {
return openedGUIs.containsKey(player);
}
public static GUI getOpenedGUI(Player player) {
return openedGUIs.get(player);
}
public static void removeOpenedGUI(Player player) {
openedGUIs.remove(player);
}
}
@@ -0,0 +1,77 @@
package cc.carm.plugin.ultrastorehouse.util.gui;
import org.bukkit.entity.Player;
import org.bukkit.event.inventory.ClickType;
import org.bukkit.event.inventory.InventoryClickEvent;
import org.bukkit.inventory.ItemStack;
import java.util.HashSet;
import java.util.Set;
public class GUIItem {
ItemStack display;
boolean actionActive = true;
public Set<GUIClickAction> actions = new HashSet<>();
public Set<GUIClickAction> actionsIgnoreActive = new HashSet<>();
public GUIItem(ItemStack display) {
this.display = display;
}
public final ItemStack getDisplay() {
return this.display;
}
public final void setDisplay(ItemStack display) {
this.display = display;
}
public final boolean isActionActive() {
return this.actionActive;
}
public final void setActionActive(boolean b) {
actionActive = b;
}
/**
* 玩家点击GUI后执行的代码
*
* @param type 点击的类型
*/
public void onClick(ClickType type) {
}
public void addClickAction(GUIClickAction action) {
actions.add(action);
}
public void addActionIgnoreActive(GUIClickAction action) {
actionsIgnoreActive.add(action);
}
public void rawClickAction(InventoryClickEvent event) {
}
public void realRawClickAction(InventoryClickEvent event) {
}
/**
* 玩家点击GUI后执行的代码
*
* @param player 点击GUI的玩家
*/
public void customAction(Player player) {
}
public abstract static class GUIClickAction {
public abstract void run(ClickType type, Player player);
}
}
@@ -0,0 +1,96 @@
package cc.carm.plugin.ultrastorehouse.util.gui;
import cc.carm.plugin.ultrastorehouse.Main;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.HandlerList;
import org.bukkit.event.Listener;
import org.bukkit.event.inventory.InventoryClickEvent;
import org.bukkit.event.inventory.InventoryCloseEvent;
import org.bukkit.event.inventory.InventoryDragEvent;
public class GUIListener implements Listener {
final GUI currentGUI;
final Player player;
public GUIListener(GUI gui, Player player) {
this.currentGUI = gui;
this.player = player;
}
public GUI getCurrentGUI() {
return currentGUI;
}
@EventHandler
public void onInventoryClickEvent(InventoryClickEvent event) {
if (!(event.getWhoClicked() instanceof Player)) return;
getCurrentGUI().rawClickListener(event);
Player p = (Player) event.getWhoClicked();
if (event.getSlot() != -999) {
try {
if (GUI.getOpenedGUI(p) == getCurrentGUI()
&& event.getClickedInventory() != null
&& event.getClickedInventory().equals(getCurrentGUI().inv)
&& getCurrentGUI().items[event.getSlot()] != null) {
getCurrentGUI().items[event.getSlot()].realRawClickAction(event);
}
} catch (ArrayIndexOutOfBoundsException e) {
Main.error("error cause by GUI(" + getCurrentGUI() + "), name=" + getCurrentGUI().name);
e.printStackTrace();
return;
}
} else if (getCurrentGUI().cancelOnOuter) {
event.setCancelled(true);
}
if (GUI.hasOpenedGUI(p)
&& GUI.getOpenedGUI(p) == getCurrentGUI()
&& event.getClickedInventory() != null) {
if (event.getClickedInventory().equals(getCurrentGUI().inv)) {
if (getCurrentGUI().cancelOnTarget) event.setCancelled(true);
if (event.getSlot() != -999 && getCurrentGUI().items[event.getSlot()] != null) {
GUIItem item = getCurrentGUI().items[event.getSlot()];
if (item.isActionActive()) {
item.onClick(event.getClick());
item.rawClickAction(event);
item.actions.forEach(action -> action.run(event.getClick(), player));
}
item.actionsIgnoreActive.forEach(action -> action.run(event.getClick(), player));
}
} else if (event.getClickedInventory().equals(p.getInventory()) && getCurrentGUI().cancelOnSelf) {
event.setCancelled(true);
}
}
}
@EventHandler
public void onDrag(InventoryDragEvent e) {
if (!(e.getWhoClicked() instanceof Player)) return;
Player p = (Player) e.getWhoClicked();
if (e.getInventory().equals(getCurrentGUI().inv) || e.getInventory().equals(p.getInventory())) {
getCurrentGUI().onDrag(e);
}
}
@EventHandler
public void onInventoryCloseEvent(InventoryCloseEvent event) {
Player p = (Player) event.getPlayer();
if (event.getInventory().equals(getCurrentGUI().inv)) {
HandlerList.unregisterAll(this);
getCurrentGUI().listener = null;
getCurrentGUI().onClose();
GUI.removeOpenedGUI(p);
}
}
}
@@ -0,0 +1,13 @@
package cc.carm.plugin.ultrastorehouse.util.gui;
public enum GUIType {
ONE_BY_NINE,
TWO_BY_NINE,
THREE_BY_NINE,
FOUR_BY_NINE,
FIVE_BY_NINE,
SIX_BY_NINE,
CANCEL
}
+82
View File
@@ -0,0 +1,82 @@
# ${project.parent.name} - ${project.parent.description}
# 项目地址: ${project.parent.url}
# 下载地址: ${project.parent.distributionManagement.downloadUrl}
version: ${project.parent.version}
debug: false
# 存储相关配置
# 注意:存储配置不会通过重载指令生效,如有修改请重新启动服务器。
storage:
# 存储方式,可选 [ file | mysql ]
method: mysql
# 选择 file 存储方式时的存储路径
# 默认为相对路径,相对于插件生成的配置文件夹下的路径
# 支持绝对路径,如 “/var/data/ub/"(linux) 或 "D:\data\ub\"(windows)
# 使用绝对路径时请注意权限问题
file-path: data
# 选择 database 存储方式时的数据库配置
mysql:
# 数据库驱动路径
driver: "com.mysql.jdbc.Driver"
url: "jdbc:mysql://127.0.0.1:3306/<db-name>"
username: "username"
password: "password"
# 玩家收集配置
# 用于决定玩家在哪些情况下的物品会自动放入背包
collect:
pickup: true # 捡取物品
kill: true #杀死动物
break: true #破坏方块
# 通用配置
general:
# 针对每一件物品的额外介绍
# 将添加到背包界面内的物品上,避免重复配置
additional-lore:
- " "
- "&f仓库内数量 &a%(amount)"
- "&f该物品单价 &a%(price)"
- "&f今日可出售 &a%(sold)&8/%(limit)"
# 提示玩家点击行为的介绍
# 将添加到背包界面内的物品上,避免重复配置
click-lore:
- " "
- "&a&l左键点击 &8| &f按量售出该物品"
- "&a&l右键点击 &8| &f取出一组该物品"
# 售出界面的配置
sell-gui:
title: "&8出售 %(item_name)"
items:
add:
type: GREEN_STAINED_GLASS_PANE
name: "&a增加 %(amount) 个"
remove:
type: RED_STAINED_GLASS_PANE
name: "&c减少 %(amount) 个"
confirm:
type: EMERALD
data: 0
name: "&a确认售出"
lore:
- " "
- "&7您将售出 &r%(item_name) &8x &f%(amount)"
- "&7共计获得 &e%(money) &7元作为回报。"
- " "
- "&a&l点击确认售出"
cancel:
type: REDSTONE
data: 0
name: "&c取消售出"
lore:
- " "
- "&c&l点击取消售出"
+8
View File
@@ -0,0 +1,8 @@
item-collected:
- "&f您收集了 &e%(item)&7x%(amount) &f,已自动放入到您的 &6%(depository) &f中。"
item-sold:
- "&f您出售了 &e%(item)&7x%(amount) &f,共赚取 &6%(money) &f元。"
no-space:
- "&f您背包内没有足够的空间取出物品!"
+24
View File
@@ -0,0 +1,24 @@
main: cc.carm.plugin.ultradepository.Main
name: UltraDepository
version: ${project.version}
description: ${project.parent.description}
website: ${project.parent.url}
author: CarmJos
permissions:
"UltraDepository.use":
description: "超级仓库的基本使用权限"
default: true
"UltraDepository.auto":
description: "超级仓库的自动收集权限"
"UltraDepository.auto.enable":
description: "用于判断是否启用了自动收集功能"
"UltraDepository.admin":
description: "超级仓库的管理权限"
default: op