├── .gitignore ├── .settings ├── .gitignore ├── org.eclipse.core.resources.prefs ├── org.eclipse.jdt.ui.prefs └── org.eclipse.m2e.core.prefs ├── LICENSE ├── README.md ├── bukkit ├── .classpath ├── .gitignore ├── .project ├── .settings │ ├── org.eclipse.core.resources.prefs │ ├── org.eclipse.jdt.core.prefs │ └── org.eclipse.jdt.ui.prefs ├── bin │ ├── .project │ └── pom.xml ├── pom.xml └── src │ └── main │ ├── java │ └── com │ │ └── blzeecraft │ │ └── virtualmenu │ │ └── bukkit │ │ ├── BukkitCommandHandler.java │ │ ├── BukkitPlatform.java │ │ ├── MenuType.java │ │ ├── PlaceholderAPIAdapter.java │ │ ├── ReflectUtils.java │ │ ├── VirtualMenuPlugin.java │ │ ├── WrapConsoleBukkit.java │ │ ├── WrapItemBukkit.java │ │ ├── WrapPlayerBukkit.java │ │ ├── WrapSchedulerBukkit.java │ │ ├── conf │ │ ├── EconomyPlugins.java │ │ ├── Settings.java │ │ └── package-info.java │ │ ├── economy │ │ ├── GemsEconomyHook.java │ │ ├── IEconomyHook.java │ │ ├── PlayerPointsHook.java │ │ ├── VaultHook.java │ │ └── package-info.java │ │ ├── hook │ │ └── package-info.java │ │ ├── item │ │ ├── BukkitItemBuilder.java │ │ ├── ItemUtils.java │ │ ├── NBTUtils.java │ │ ├── XMaterial.java │ │ └── package-info.java │ │ ├── package-info.java │ │ ├── packet │ │ ├── PacketDebugHandler.java │ │ ├── PacketListener.java │ │ ├── PacketPlayInCloseWindow.java │ │ ├── PacketPlayInWindowClick1_7.java │ │ ├── PacketPlayInWindowClick1_8.java │ │ ├── PacketPlayOutCloseWindow.java │ │ ├── PacketPlayOutSetSlot.java │ │ ├── PacketPlayOutWIndowOpen1_14.java │ │ ├── PacketPlayOutWindowItems1_11.java │ │ ├── PacketPlayOutWindowItems1_7.java │ │ ├── PacketPlayOutWindowOpen1_7.java │ │ ├── PacketPlayOutWindowOpen1_8.java │ │ ├── ProtocolLibAdapter.java │ │ └── package-info.java │ │ └── title │ │ ├── Constants.java │ │ ├── ITitleAPI.java │ │ ├── TitleAPI.java │ │ ├── TitleBukkit.java │ │ ├── TitleLegacy.java │ │ └── TitlePacket.java │ └── resources │ ├── config.yml │ └── plugin.yml ├── common ├── .gitignore ├── .settings │ ├── org.eclipse.core.resources.prefs │ ├── org.eclipse.jdt.core.prefs │ └── org.eclipse.m2e.core.prefs ├── pom.xml └── src │ └── main │ ├── java │ └── com │ │ └── blzeecraft │ │ └── virtualmenu │ │ └── core │ │ ├── Command.java │ │ ├── IPlatformAdapter.java │ │ ├── IWrappedObject.java │ │ ├── PluginExecption.java │ │ ├── ThreadSafe.java │ │ ├── VirtualMenu.java │ │ ├── VirtualMenuUtils.java │ │ ├── action │ │ ├── Action.java │ │ ├── ActionUtils.java │ │ ├── IAction.java │ │ ├── IScope.java │ │ ├── MultiAction.java │ │ ├── event │ │ │ ├── IconActionEvent.java │ │ │ ├── MenuActionEvent.java │ │ │ ├── MenuEvent.java │ │ │ └── package-info.java │ │ ├── extension │ │ │ ├── ActionActionbar.java │ │ │ ├── ActionBungeeCord.java │ │ │ ├── ActionCloseMenu.java │ │ │ ├── ActionCommand.java │ │ │ ├── ActionConsoleCommand.java │ │ │ ├── ActionOpCommand.java │ │ │ ├── ActionOpenMenu.java │ │ │ ├── ActionSound.java │ │ │ ├── ActionTell.java │ │ │ ├── ActionTitle.java │ │ │ └── package-info.java │ │ └── package-info.java │ │ ├── command │ │ ├── Callstack.java │ │ ├── CommandHandler.java │ │ ├── CommandMeta.java │ │ ├── IllegalCommandArgumentException.java │ │ ├── PlayerOnly.java │ │ ├── RequirePermission.java │ │ ├── SubCommandBase.java │ │ ├── Usage.java │ │ ├── extension │ │ │ ├── CommandList.java │ │ │ ├── CommandOpenMenu.java │ │ │ ├── CommandReload.java │ │ │ └── package-info.java │ │ └── package-info.java │ │ ├── condition │ │ ├── Condition.java │ │ ├── ConditionUtils.java │ │ ├── ICondition.java │ │ ├── MultiCondition.java │ │ ├── extension │ │ │ ├── ConditionEconomy.java │ │ │ ├── ConditionLevel.java │ │ │ ├── ConditionPermission.java │ │ │ └── package-info.java │ │ └── package-info.java │ │ ├── conf │ │ ├── ConfSerializable.java │ │ ├── InvalidConfigException.java │ │ ├── ObjectConvertException.java │ │ ├── OptionalMapper.java │ │ ├── StringSerializable.java │ │ ├── convert │ │ │ ├── ConvertFunctions.java │ │ │ ├── FuncDouble.java │ │ │ ├── FuncInteger.java │ │ │ ├── FuncList.java │ │ │ ├── FuncLong.java │ │ │ ├── FuncMap.java │ │ │ ├── FuncOptional.java │ │ │ ├── FuncOptionalDouble.java │ │ │ ├── FuncOptionalInt.java │ │ │ ├── FuncOptionalLong.java │ │ │ ├── FuncS2ObjectMap.java │ │ │ ├── FuncS2StringMap.java │ │ │ ├── FuncString.java │ │ │ ├── FuncSubConf.java │ │ │ └── package-info.java │ │ ├── file │ │ │ ├── FileMapFactory.java │ │ │ ├── IFileFormat.java │ │ │ ├── JsonFile.java │ │ │ ├── UnsupportedFileException.java │ │ │ ├── YamlFile.java │ │ │ └── package-info.java │ │ ├── line │ │ │ ├── InvalidLineCommandException.java │ │ │ ├── InvalidLineFormatException.java │ │ │ ├── LineConfigObject.java │ │ │ ├── LineConfigParser.java │ │ │ ├── MissingRequiredObjectException.java │ │ │ ├── ResolvedLineConfig.java │ │ │ └── package-info.java │ │ ├── menu │ │ │ ├── ConfMenuFactory.java │ │ │ ├── MenuManager.java │ │ │ └── package-info.java │ │ ├── package-info.java │ │ └── transition │ │ │ ├── ChestCommandsAdapter.java │ │ │ ├── ChestCommandsConf.java │ │ │ ├── IllegalFieldException.java │ │ │ ├── ObjectType.java │ │ │ ├── StandardConf.java │ │ │ ├── SubConf.java │ │ │ └── package-info.java │ │ ├── icon │ │ ├── DynamicIcon.java │ │ ├── EmptyIcon.java │ │ ├── Icon.java │ │ ├── IconBuilder.java │ │ ├── MultiIcon.java │ │ ├── SimpleIcon.java │ │ └── package-info.java │ │ ├── item │ │ ├── AbstractItem.java │ │ ├── AbstractItemBuilder.java │ │ └── package-info.java │ │ ├── logger │ │ ├── LogFormatter.java │ │ ├── LogNode.java │ │ ├── LoggerObject.java │ │ ├── PluginLogger.java │ │ └── package-info.java │ │ ├── menu │ │ ├── AbstractPacketMenu.java │ │ ├── ClickEvent.java │ │ ├── ClickType.java │ │ ├── EventHandler.java │ │ ├── EventType.java │ │ ├── IMenuType.java │ │ ├── IPacketMenu.java │ │ ├── PacketMenu.java │ │ ├── PacketMenuBuilder.java │ │ └── package-info.java │ │ ├── packet │ │ ├── AbstractPacket.java │ │ ├── AbstractPacketInCloseWindow.java │ │ ├── AbstractPacketInWindowClick.java │ │ ├── AbstractPacketOutCloseWindow.java │ │ ├── AbstractPacketOutSetSlot.java │ │ ├── AbstractPacketOutWindowItems.java │ │ ├── AbstractPacketOutWindowOpen.java │ │ ├── AbstractWindowPacket.java │ │ ├── ClickMode.java │ │ ├── IPacketAdapter.java │ │ ├── PacketHandler.java │ │ ├── PacketMenuClickEvent.java │ │ ├── PacketMenuCloseEvent.java │ │ ├── PacketMenuEvent.java │ │ └── package-info.java │ │ ├── schedule │ │ ├── AbstractTask.java │ │ ├── IScheduler.java │ │ └── package-info.java │ │ ├── user │ │ ├── IUser.java │ │ ├── UserManager.java │ │ ├── UserSession.java │ │ └── package-info.java │ │ └── variable │ │ ├── EmptyVariableAdapter.java │ │ ├── IVariableAdapter.java │ │ ├── UpdatePeriod.java │ │ ├── VariableUpdater.java │ │ └── package-info.java │ └── resources │ ├── example.yml │ └── exampleCC.yml ├── jar ├── pom.xml └── target │ ├── classes │ └── LICENSE │ └── maven-archiver │ └── pom.properties ├── pom.xml └── resources └── example.yml /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled class file 2 | *.class 3 | 4 | # Log file 5 | *.log 6 | 7 | # BlueJ files 8 | *.ctxt 9 | 10 | # Mobile Tools for Java (J2ME) 11 | .mtj.tmp/ 12 | 13 | # Package Files # 14 | *.jar 15 | *.war 16 | *.nar 17 | *.ear 18 | *.zip 19 | *.tar.gz 20 | *.rar 21 | 22 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml 23 | hs_err_pid* 24 | /bin/ 25 | /.classpath 26 | /.project 27 | /target/ 28 | -------------------------------------------------------------------------------- /.settings/.gitignore: -------------------------------------------------------------------------------- 1 | /org.eclipse.jdt.core.prefs 2 | -------------------------------------------------------------------------------- /.settings/org.eclipse.core.resources.prefs: -------------------------------------------------------------------------------- 1 | eclipse.preferences.version=1 2 | encoding/=UTF-8 3 | separateDerivedEncodings=true 4 | -------------------------------------------------------------------------------- /.settings/org.eclipse.m2e.core.prefs: -------------------------------------------------------------------------------- 1 | activeProfiles= 2 | eclipse.preferences.version=1 3 | resolveWorkspaceProjects=true 4 | version=1 5 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # VirtualMenu v2 Bukkit, Sponge, Nukkit 2 | 3 | 这个插件允许你在Minecraft服务器中创建自定义的菜单,类似ChestCommands和TrMenu,但这个插件基于 Packet 的拦截和发送而不是 BukkitAPI,这样可以保证安全性,同时可以方便地移植到其他平台。本插件旨在提供安全,简单,高效的自定义菜单。 4 | __目前v2仍然在开发中,请勿在生产环境使用__ 5 | 从v1到v2可能还需要一些时间,尽管目前v2 Bukkit平台版已经基本可以用了,但目前没有经过大量测试,所以生产环境请使用旧的版本(0.0.X)。 6 | https://www.mcbbs.net/thread-894621-1-1.html 7 | *** 8 | 9 | 10 | ## 插件统计 11 | https://bstats.org/plugin/bukkit/VirtualMenu/5355 12 | *** 13 | 14 | 15 | ## 相比于v1 16 | v2 几乎重写了整个插件,把与服务端无关的代码分离出来,同时采用了表达能力更强的配置方式 17 | *** 18 | 19 | 20 | ## TODO 21 | - [ ] 平台支持 22 | - [x] Bukkit 23 | - [ ] Sponge 24 | - [ ] Nukkit 25 | - [ ] Bukkit 26 | - [x] Vault 27 | - [x] GemEconomy 28 | - [x] PlayerPoints 29 | - [x] NBT Support 30 | - [x] PlaceholderAPI 31 | - [ ] CommandPrompter 32 | - [ ] 核心功能 33 | - [x] 变量支持 34 | - [ ] 自定义动画 35 | - [x] ChestCommands 菜单加载 36 | - [ ] ChestCommands 自动转换 37 | - [ ] GUI 菜单编辑器 38 | - [ ] 更多的自带命令 39 | - [ ] 精确的错误提示(进行中,不完全) 40 | *** 41 | 42 | ## 授权 43 | __GPL-3.0__ 44 | *** 45 | 46 | ## 如何构建 47 | 你需要jdk8和maven来构建这个插件 48 | ``` 49 | git clone https://github.com/ColorsWind/VirtualMenu.git 50 | mvn clean install 51 | ``` 52 | *** 53 | 54 | 55 | ## 下载 56 | https://github.com/ColorsWind/VirtualMenu/releases 57 | -------------------------------------------------------------------------------- /bukkit/.classpath: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /bukkit/.gitignore: -------------------------------------------------------------------------------- 1 | /target/ 2 | -------------------------------------------------------------------------------- /bukkit/.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | virtualmenu-bukkit 4 | 5 | 6 | 7 | 8 | 9 | org.eclipse.jdt.core.javabuilder 10 | 11 | 12 | 13 | 14 | org.eclipse.m2e.core.maven2Builder 15 | 16 | 17 | 18 | 19 | 20 | org.eclipse.jdt.core.javanature 21 | org.eclipse.m2e.core.maven2Nature 22 | 23 | 24 | -------------------------------------------------------------------------------- /bukkit/.settings/org.eclipse.core.resources.prefs: -------------------------------------------------------------------------------- 1 | eclipse.preferences.version=1 2 | encoding//src/main/java=UTF-8 3 | encoding//src/main/resources=UTF-8 4 | encoding//src/test/java=UTF-8 5 | encoding//src/test/resources=UTF-8 6 | encoding/=UTF-8 7 | -------------------------------------------------------------------------------- /bukkit/.settings/org.eclipse.jdt.core.prefs: -------------------------------------------------------------------------------- 1 | eclipse.preferences.version=1 2 | org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8 3 | org.eclipse.jdt.core.compiler.compliance=1.8 4 | org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures=disabled 5 | org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning 6 | org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=ignore 7 | org.eclipse.jdt.core.compiler.release=disabled 8 | org.eclipse.jdt.core.compiler.source=1.8 9 | -------------------------------------------------------------------------------- /bukkit/bin/.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | virtualmenu-bukkit 4 | 5 | 6 | 7 | 8 | 9 | org.eclipse.jdt.core.javabuilder 10 | 11 | 12 | 13 | 14 | org.eclipse.m2e.core.maven2Builder 15 | 16 | 17 | 18 | 19 | 20 | org.eclipse.jdt.core.javanature 21 | org.eclipse.m2e.core.maven2Nature 22 | 23 | 24 | -------------------------------------------------------------------------------- /bukkit/bin/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | com.blzeecraft.virtualmenu 7 | virtualmenu-parent 8 | 1.0.0-SNAPSHOT 9 | 10 | 4.0.0 11 | 12 | virtualmenu-bukkit 13 | 14 | 15 | 16 | 17 | 18 | org.spigotmc 19 | spigot-api 20 | 1.13.2-R0.1-SNAPSHOT 21 | provided 22 | 23 | 24 | 25 | 26 | net.milkbowl.vault 27 | VaultAPI 28 | 1.7 29 | provided 30 | 31 | 32 | 33 | 34 | com.comphenix.protocol 35 | ProtocolLib 36 | 4.5.0 37 | provided 38 | 39 | 40 | 41 | 42 | com.meowj 43 | LangUtils 44 | 1.9 45 | provided 46 | 47 | 48 | 49 | 50 | me.clip 51 | placeholderapi 52 | 2.9.2 53 | jar 54 | provided 55 | 56 | 57 | 58 | 59 | org.black_ixx 60 | PlayerPoints 61 | 2.1.3 62 | jar 63 | provided 64 | 65 | 66 | -------------------------------------------------------------------------------- /bukkit/src/main/java/com/blzeecraft/virtualmenu/bukkit/BukkitCommandHandler.java: -------------------------------------------------------------------------------- 1 | package com.blzeecraft.virtualmenu.bukkit; 2 | 3 | import java.util.Optional; 4 | 5 | import org.bukkit.command.Command; 6 | import org.bukkit.command.CommandExecutor; 7 | import org.bukkit.command.CommandSender; 8 | import org.bukkit.entity.Player; 9 | 10 | import com.blzeecraft.virtualmenu.core.command.CommandHandler; 11 | import com.blzeecraft.virtualmenu.core.user.IUser; 12 | 13 | public class BukkitCommandHandler implements CommandExecutor { 14 | private final BukkitPlatform platform; 15 | 16 | public BukkitCommandHandler(VirtualMenuPlugin plugin) { 17 | this.platform = plugin.getPlatformAdapter(); 18 | } 19 | 20 | @Override 21 | public boolean onCommand(CommandSender sender, Command command, String label, String[] args) { 22 | if (sender instanceof Player) { 23 | Optional> optUser = platform.getUserExact((Player)sender); 24 | if (optUser.isPresent()) { 25 | return CommandHandler.process(optUser.get(), label, args); 26 | } 27 | } 28 | return CommandHandler.process(platform.getConsole(), label, args); 29 | } 30 | 31 | } 32 | -------------------------------------------------------------------------------- /bukkit/src/main/java/com/blzeecraft/virtualmenu/bukkit/PlaceholderAPIAdapter.java: -------------------------------------------------------------------------------- 1 | package com.blzeecraft.virtualmenu.bukkit; 2 | 3 | import java.util.List; 4 | 5 | import com.blzeecraft.virtualmenu.core.user.IUser; 6 | import com.blzeecraft.virtualmenu.core.variable.IVariableAdapter; 7 | 8 | import me.clip.placeholderapi.PlaceholderAPI; 9 | 10 | public class PlaceholderAPIAdapter implements IVariableAdapter { 11 | 12 | @Override 13 | public String replace(IUser user, String line) { 14 | return PlaceholderAPI.setPlaceholders(((WrapPlayerBukkit)user).getHandle(), line); 15 | } 16 | 17 | @Override 18 | public List replace(IUser user, List lines) { 19 | return PlaceholderAPI.setPlaceholders(((WrapPlayerBukkit)user).getHandle(), lines); 20 | } 21 | 22 | @Override 23 | public boolean containsVariable(String line) { 24 | if (line == null) { 25 | return false; 26 | } 27 | return PlaceholderAPI.containsPlaceholders(line); 28 | } 29 | 30 | @Override 31 | public boolean containsVariable(List lines) { 32 | if (lines == null) { 33 | return false; 34 | } 35 | return lines.stream().anyMatch(PlaceholderAPI::containsPlaceholders); 36 | } 37 | 38 | } 39 | -------------------------------------------------------------------------------- /bukkit/src/main/java/com/blzeecraft/virtualmenu/bukkit/ReflectUtils.java: -------------------------------------------------------------------------------- 1 | package com.blzeecraft.virtualmenu.bukkit; 2 | 3 | import java.lang.reflect.InvocationTargetException; 4 | import java.lang.reflect.Method; 5 | 6 | import org.bukkit.Bukkit; 7 | import org.bukkit.Material; 8 | import org.bukkit.entity.Player; 9 | import org.bukkit.inventory.ItemStack; 10 | import org.bukkit.inventory.PlayerInventory; 11 | 12 | import com.meowj.langutils.lang.LanguageHelper; 13 | 14 | import lombok.AccessLevel; 15 | import lombok.NoArgsConstructor; 16 | 17 | @NoArgsConstructor(access = AccessLevel.PRIVATE) 18 | public class ReflectUtils { 19 | 20 | public static String getNMSVersion() { 21 | return Bukkit.getServer().getClass().getPackage().getName().substring(23); 22 | } 23 | 24 | public static Class getNMSClass(String name) throws Exception { 25 | return Class.forName("net.minecraft.server." + getNMSVersion() + "." + name); 26 | } 27 | 28 | public static Material getMaterial(int id) { 29 | try { 30 | Method m = Material.class.getMethod("getMaterial", int.class); 31 | Material type = (Material) m.invoke(null, id); 32 | if (type != null) { 33 | return type; 34 | } 35 | } catch (NoSuchMethodException e) { 36 | } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) { 37 | e.printStackTrace(); 38 | } 39 | throw new IllegalArgumentException(); 40 | } 41 | 42 | public static ItemStack getItemInHand(Player p, boolean b) { 43 | try { 44 | String name = b ? "getItemInMainHand" : "getItemInOffHand"; 45 | PlayerInventory inv = p.getInventory(); 46 | Class clazz = inv.getClass(); 47 | Method method = null; 48 | try { 49 | method = clazz.getMethod(name); 50 | } catch (NoSuchMethodException e) { 51 | method = clazz.getMethod("getItemInHand"); 52 | } 53 | return (ItemStack) method.invoke(inv); 54 | } catch (Exception e) { 55 | e.printStackTrace(); 56 | } 57 | return new ItemStack(Material.AIR); 58 | } 59 | 60 | 61 | public static ItemStack asNMSCopy(ItemStack original) { 62 | try { 63 | Class clazz = Class 64 | .forName(Bukkit.getServer().getClass().getPackage().getName() + ".inventory.CraftItemStack"); 65 | Method method = clazz.getMethod("asCraftCopy", ItemStack.class); 66 | return (ItemStack) method.invoke(null, original); 67 | } catch (Exception e) { 68 | e.printStackTrace(); 69 | } 70 | return original; 71 | } 72 | 73 | public static String getItemName(ItemStack item) { 74 | if (item == null) { 75 | return "null"; 76 | } 77 | // 使用LangUtils获取物品名称 78 | try { 79 | Class.forName("com.meowj.langutils.lang.LanguageHelper"); 80 | return LanguageHelper.getItemName(item, "zh_CN"); 81 | } catch (ClassNotFoundException e) { 82 | } 83 | try { 84 | ItemStack.class.getMethod("getI18NDisplayName", new Class[0]); 85 | return item.getI18NDisplayName(); 86 | } catch (NoSuchMethodException | SecurityException e) { 87 | } 88 | return item.getType().name(); 89 | } 90 | 91 | } 92 | -------------------------------------------------------------------------------- /bukkit/src/main/java/com/blzeecraft/virtualmenu/bukkit/WrapItemBukkit.java: -------------------------------------------------------------------------------- 1 | package com.blzeecraft.virtualmenu.bukkit; 2 | 3 | import java.util.Arrays; 4 | import java.util.HashSet; 5 | import java.util.List; 6 | import java.util.Set; 7 | 8 | import org.bukkit.Material; 9 | import org.bukkit.inventory.ItemStack; 10 | import org.bukkit.inventory.meta.ItemMeta; 11 | 12 | import com.blzeecraft.virtualmenu.bukkit.item.BukkitItemBuilder; 13 | import com.blzeecraft.virtualmenu.bukkit.item.ItemUtils; 14 | import com.blzeecraft.virtualmenu.core.item.AbstractItem; 15 | 16 | import lombok.ToString; 17 | 18 | @ToString 19 | public class WrapItemBukkit extends AbstractItem { 20 | public static final Set EMPTY_TYPE = new HashSet<>( 21 | Arrays.asList("AIR", "CAVE_AIR", "VOID_AIR", "LEGACY_AIR")); 22 | public static final WrapItemBukkit EMPTY_ITEM = new WrapItemBukkit(new ItemStack(Material.AIR), ""); 23 | protected final ItemStack item; 24 | 25 | public WrapItemBukkit(ItemStack item, String nbt) { 26 | super(item, item.getType().name(), item.getAmount(), ItemUtils.getDisplayname(item), ItemUtils.getLore(item), 27 | nbt); 28 | this.item = item; 29 | } 30 | 31 | public WrapItemBukkit(ItemStack item) { 32 | super(item, item.getType().name(), item.getAmount(), ItemUtils.getDisplayname(item), ItemUtils.getLore(item)); 33 | this.item = item; 34 | } 35 | 36 | @Override 37 | public BukkitItemBuilder builder() { 38 | return new BukkitItemBuilder(this); 39 | } 40 | 41 | @Override 42 | public boolean isEmpty() { 43 | return EMPTY_TYPE.contains(item.getType().name()); 44 | } 45 | 46 | @Override 47 | public ItemStack getHandle() { 48 | return item.clone(); 49 | } 50 | 51 | @Override 52 | public WrapItemBukkit updateMeta(String newName, List newLore) { 53 | ItemStack newItem = this.item.clone(); 54 | ItemMeta meta = newItem.getItemMeta(); 55 | if (meta != null) { 56 | meta.setDisplayName(newName); 57 | meta.setLore(newLore); 58 | newItem.setItemMeta(meta); 59 | } 60 | return new WrapItemBukkit(newItem); 61 | } 62 | 63 | } 64 | -------------------------------------------------------------------------------- /bukkit/src/main/java/com/blzeecraft/virtualmenu/bukkit/WrapSchedulerBukkit.java: -------------------------------------------------------------------------------- 1 | package com.blzeecraft.virtualmenu.bukkit; 2 | 3 | import org.bukkit.Bukkit; 4 | import org.bukkit.scheduler.BukkitScheduler; 5 | import org.bukkit.scheduler.BukkitTask; 6 | 7 | import com.blzeecraft.virtualmenu.core.schedule.AbstractTask; 8 | import com.blzeecraft.virtualmenu.core.schedule.IScheduler; 9 | 10 | import lombok.RequiredArgsConstructor; 11 | import lombok.ToString; 12 | 13 | @RequiredArgsConstructor 14 | @ToString 15 | public class WrapSchedulerBukkit implements IScheduler { 16 | protected final VirtualMenuPlugin plugin; 17 | protected final BukkitScheduler scheduler = Bukkit.getScheduler(); 18 | 19 | @Override 20 | public AbstractTask runTaskLater(Runnable task, long delay) { 21 | return new WrapTaskBukkit(scheduler.runTaskLater(plugin, task, delay)); 22 | } 23 | 24 | @Override 25 | public AbstractTask runTaskTimer(Runnable task, long delay, long period) { 26 | return new WrapTaskBukkit(scheduler.runTaskTimer(plugin, task, delay, period)); 27 | } 28 | 29 | @Override 30 | public AbstractTask runTaskGuaranteePrimaryThread(Runnable task) { 31 | if (Bukkit.isPrimaryThread()) { 32 | task.run(); 33 | return new SyncTask(task); 34 | } else { 35 | return new WrapTaskBukkit(scheduler.runTask(plugin, task)); 36 | } 37 | } 38 | 39 | @Override 40 | public AbstractTask runTaskAsync(Runnable task) { 41 | return new WrapTaskBukkit(scheduler.runTaskAsynchronously(plugin, task)); 42 | } 43 | 44 | class WrapTaskBukkit extends AbstractTask { 45 | 46 | public WrapTaskBukkit(BukkitTask handle) { 47 | super(handle); 48 | } 49 | 50 | @Override 51 | public boolean isRunning() { 52 | return handle.isCancelled(); 53 | } 54 | 55 | @Override 56 | public boolean isAsync() { 57 | return !handle.isSync(); 58 | } 59 | 60 | @Override 61 | public void cancel() { 62 | handle.cancel(); 63 | } 64 | } 65 | 66 | class SyncTask extends AbstractTask { 67 | 68 | public SyncTask(Runnable handle) { 69 | super(handle); 70 | } 71 | 72 | @Override 73 | public boolean isRunning() { 74 | return false; 75 | } 76 | 77 | @Override 78 | public boolean isAsync() { 79 | return false; 80 | } 81 | 82 | @Override 83 | public void cancel() { 84 | } 85 | 86 | } 87 | 88 | 89 | 90 | } 91 | -------------------------------------------------------------------------------- /bukkit/src/main/java/com/blzeecraft/virtualmenu/bukkit/conf/EconomyPlugins.java: -------------------------------------------------------------------------------- 1 | package com.blzeecraft.virtualmenu.bukkit.conf; 2 | 3 | import java.util.Arrays; 4 | import java.util.HashMap; 5 | import java.util.HashSet; 6 | import java.util.Map; 7 | import java.util.Optional; 8 | import java.util.Set; 9 | import java.util.function.Supplier; 10 | 11 | import org.bukkit.configuration.ConfigurationSection; 12 | 13 | import com.blzeecraft.virtualmenu.bukkit.economy.IEconomyHook; 14 | import com.blzeecraft.virtualmenu.bukkit.economy.VaultHook; 15 | 16 | import lombok.Getter; 17 | import lombok.Setter; 18 | import lombok.ToString; 19 | 20 | import com.blzeecraft.virtualmenu.bukkit.economy.PlayerPointsHook; 21 | import com.blzeecraft.virtualmenu.bukkit.economy.GemsEconomyHook; 22 | @Getter 23 | @ToString 24 | public enum EconomyPlugins { 25 | 26 | VAULT("Vault", VaultHook::new), PLAYER_POINTS("PlayerPoints", PlayerPointsHook::new), 27 | GEMS_ECONOMY("GemsEconomy", GemsEconomyHook::new); 28 | 29 | private final String name; 30 | private final Supplier supplier; 31 | 32 | @Setter 33 | private IEconomyHook instance; 34 | private Set currency; 35 | 36 | private EconomyPlugins(String name, Supplier supplier) { 37 | this.name = name; 38 | this.supplier = supplier; 39 | } 40 | 41 | public boolean isEnable() { 42 | return instance != null; 43 | } 44 | 45 | public void readIsEnable(ConfigurationSection sect) { 46 | if (sect.getBoolean(name)) { 47 | IEconomyHook hook = supplier.get(); 48 | if (hook.isPluginInstall() && hook.register()) { 49 | instance = hook; 50 | } 51 | } 52 | } 53 | 54 | public void readCurrency(ConfigurationSection sect) { 55 | if ("*".equals(sect.getString(name))) { 56 | currency = null; 57 | } else { 58 | currency = new HashSet<>(sect.getStringList(name)); 59 | } 60 | } 61 | 62 | private static Map mapCurrency = new HashMap<>(); 63 | private static Optional defaultEconomy = Optional.empty(); 64 | 65 | public static void rebuildMapping() { 66 | defaultEconomy = Arrays.stream(values()).filter(type -> type.currency == null).findFirst() 67 | .map(EconomyPlugins::getInstance); 68 | mapCurrency = Arrays.stream(values()).filter(EconomyPlugins::isEnable).filter(type -> type.currency != null).flatMap(type -> { 69 | return type.currency.stream().map(currencyName -> { 70 | Map map = new HashMap<>(1); 71 | map.put(currencyName, type.instance); 72 | return map; 73 | }); 74 | }).reduce(new HashMap<>(), (map1, map2) -> { 75 | map1.putAll(map2); 76 | return map1; 77 | }); 78 | } 79 | 80 | public static Optional getHandlerByCurrency(String currency) { 81 | IEconomyHook econHook = mapCurrency.get(currency); 82 | if (econHook == null) { 83 | return defaultEconomy; 84 | } 85 | return Optional.of(econHook); 86 | } 87 | 88 | } 89 | -------------------------------------------------------------------------------- /bukkit/src/main/java/com/blzeecraft/virtualmenu/bukkit/conf/Settings.java: -------------------------------------------------------------------------------- 1 | package com.blzeecraft.virtualmenu.bukkit.conf; 2 | 3 | import java.io.File; 4 | import java.util.Arrays; 5 | 6 | import org.bukkit.configuration.ConfigurationSection; 7 | import org.bukkit.configuration.file.FileConfiguration; 8 | import org.bukkit.configuration.file.YamlConfiguration; 9 | 10 | import com.blzeecraft.virtualmenu.bukkit.VirtualMenuPlugin; 11 | 12 | public class Settings { 13 | 14 | public static boolean useXMaterial = true; 15 | public static boolean supportNBT = true; 16 | public static boolean hookPlaceholderAPI = true; 17 | 18 | public static void read(VirtualMenuPlugin plugin) { 19 | File file = new File(plugin.getDataFolder(), "config.yml"); 20 | FileConfiguration config = YamlConfiguration.loadConfiguration(file); 21 | useXMaterial = config.getBoolean("UseXMaterial", true); 22 | supportNBT = config.getBoolean("SupportNBT", true); 23 | hookPlaceholderAPI = config.getBoolean("HookPlaceholderAPI", true); 24 | ConfigurationSection hookSect = config.getConfigurationSection("EconomyHook"); 25 | ConfigurationSection currencySect = config.getConfigurationSection("MultiCurrency"); 26 | Arrays.stream(EconomyPlugins.values()).forEach(type -> { 27 | type.readIsEnable(hookSect); 28 | type.readCurrency(currencySect); 29 | }); 30 | EconomyPlugins.rebuildMapping(); 31 | } 32 | 33 | } 34 | -------------------------------------------------------------------------------- /bukkit/src/main/java/com/blzeecraft/virtualmenu/bukkit/conf/package-info.java: -------------------------------------------------------------------------------- 1 | package com.blzeecraft.virtualmenu.bukkit.conf; -------------------------------------------------------------------------------- /bukkit/src/main/java/com/blzeecraft/virtualmenu/bukkit/economy/GemsEconomyHook.java: -------------------------------------------------------------------------------- 1 | package com.blzeecraft.virtualmenu.bukkit.economy; 2 | 3 | import java.util.OptionalDouble; 4 | 5 | import org.bukkit.Bukkit; 6 | import org.bukkit.entity.Player; 7 | import org.bukkit.plugin.java.JavaPlugin; 8 | 9 | import me.xanium.gemseconomy.GemsEconomy; 10 | import me.xanium.gemseconomy.economy.Account; 11 | import me.xanium.gemseconomy.economy.AccountManager; 12 | import me.xanium.gemseconomy.economy.Currency; 13 | 14 | public class GemsEconomyHook implements IEconomyHook { 15 | 16 | @Override 17 | public boolean isPluginInstall() { 18 | return Bukkit.getPluginManager().isPluginEnabled("GemsEconomy"); 19 | } 20 | 21 | @Override 22 | public boolean register() { 23 | if (JavaPlugin.getPlugin(GemsEconomy.class) == null) { 24 | return false; 25 | } 26 | try { 27 | Class.forName("me.xanium.gemseconomy.economy.AccountManager"); 28 | } catch (ClassNotFoundException e) { 29 | return false; 30 | } 31 | return true; 32 | 33 | } 34 | 35 | @Override 36 | public void unRegister() { 37 | } 38 | 39 | @Override 40 | public OptionalDouble getBanlance(Player player, String currency) { 41 | Currency c = AccountManager.getCurrency(currency); 42 | if (c == null) { 43 | return OptionalDouble.empty(); 44 | } 45 | Account acc = AccountManager.getAccount(player); 46 | if (acc == null) { 47 | return OptionalDouble.empty(); 48 | } 49 | return OptionalDouble.of(acc.getBalance(c)); 50 | } 51 | 52 | @Override 53 | public boolean deposit(Player player, String currency, double amount) { 54 | Currency c = AccountManager.getCurrency(currency); 55 | if (c == null) { 56 | return false; 57 | } 58 | Account acc = AccountManager.getAccount(player); 59 | if (acc == null) { 60 | return false; 61 | } 62 | return acc.deposit(c, amount); 63 | } 64 | 65 | @Override 66 | public boolean withdraw(Player player, String currency, double amount) { 67 | Currency c = AccountManager.getCurrency(currency); 68 | if (c == null) { 69 | return false; 70 | } 71 | Account acc = AccountManager.getAccount(player); 72 | if (acc == null) { 73 | return false; 74 | } 75 | return acc.withdraw(c, amount); 76 | } 77 | 78 | } 79 | -------------------------------------------------------------------------------- /bukkit/src/main/java/com/blzeecraft/virtualmenu/bukkit/economy/IEconomyHook.java: -------------------------------------------------------------------------------- 1 | package com.blzeecraft.virtualmenu.bukkit.economy; 2 | 3 | import java.util.OptionalDouble; 4 | 5 | import org.bukkit.entity.Player; 6 | 7 | public interface IEconomyHook { 8 | 9 | boolean isPluginInstall(); 10 | 11 | boolean register(); 12 | 13 | void unRegister(); 14 | 15 | OptionalDouble getBanlance(Player player, String currency); 16 | 17 | boolean deposit(Player player, String currency, double amount); 18 | 19 | boolean withdraw(Player player, String currency, double amount); 20 | 21 | } 22 | -------------------------------------------------------------------------------- /bukkit/src/main/java/com/blzeecraft/virtualmenu/bukkit/economy/PlayerPointsHook.java: -------------------------------------------------------------------------------- 1 | package com.blzeecraft.virtualmenu.bukkit.economy; 2 | 3 | import java.util.OptionalDouble; 4 | 5 | import org.black_ixx.playerpoints.PlayerPoints; 6 | import org.black_ixx.playerpoints.PlayerPointsAPI; 7 | import org.bukkit.Bukkit; 8 | import org.bukkit.entity.Player; 9 | import org.bukkit.plugin.java.JavaPlugin; 10 | 11 | public class PlayerPointsHook implements IEconomyHook { 12 | private PlayerPointsAPI api; 13 | 14 | @Override 15 | public boolean isPluginInstall() { 16 | return Bukkit.getPluginManager().isPluginEnabled("PlayerPoints"); 17 | } 18 | 19 | @Override 20 | public boolean register() { 21 | PlayerPoints playerPoints = JavaPlugin.getPlugin(PlayerPoints.class); 22 | if (playerPoints == null) { 23 | return false; 24 | } 25 | api = playerPoints.getAPI(); 26 | return true; 27 | } 28 | 29 | @Override 30 | public void unRegister() { 31 | api = null; 32 | } 33 | 34 | @Override 35 | public OptionalDouble getBanlance(Player player, String currency) { 36 | return OptionalDouble.of(api.look(player.getUniqueId())); 37 | } 38 | 39 | @Override 40 | /** 41 | * 由于 PlayerPoints 只支持整数, 所有包含小数的请求都会拒绝. 42 | */ 43 | public boolean deposit(Player player, String currency, double amount) { 44 | if (!isInteger(amount)) { 45 | return false; 46 | } 47 | return api.give(player.getUniqueId(), (int) amount); 48 | } 49 | 50 | @Override 51 | /** 52 | * 由于 PlayerPoints 只支持整数, 所有包含小数的请求都会拒绝. 53 | */ 54 | public boolean withdraw(Player player, String currency, double amount) { 55 | if (!isInteger(amount)) { 56 | return false; 57 | } 58 | return api.take(player.getUniqueId(), (int) amount); 59 | } 60 | 61 | public static final double ACCURACY = 1E-5; 62 | 63 | /** 64 | * 判断double是否为整数 65 | */ 66 | public static boolean isInteger(double d) { 67 | return d - Math.floor(d) < ACCURACY; 68 | } 69 | 70 | } 71 | -------------------------------------------------------------------------------- /bukkit/src/main/java/com/blzeecraft/virtualmenu/bukkit/economy/VaultHook.java: -------------------------------------------------------------------------------- 1 | package com.blzeecraft.virtualmenu.bukkit.economy; 2 | 3 | import java.util.OptionalDouble; 4 | 5 | import org.bukkit.Bukkit; 6 | import org.bukkit.entity.Player; 7 | import org.bukkit.plugin.RegisteredServiceProvider; 8 | 9 | import net.milkbowl.vault.economy.Economy; 10 | import net.milkbowl.vault.economy.EconomyResponse; 11 | 12 | public class VaultHook implements IEconomyHook { 13 | private Economy econ = null; 14 | 15 | @Override 16 | public boolean isPluginInstall() { 17 | return Bukkit.getPluginManager().isPluginEnabled("Vault"); 18 | } 19 | 20 | @Override 21 | public boolean register() { 22 | RegisteredServiceProvider rsp = Bukkit.getServicesManager().getRegistration(Economy.class); 23 | if (rsp == null) { 24 | return false; 25 | } 26 | econ = rsp.getProvider(); 27 | return econ != null; 28 | } 29 | 30 | @Override 31 | public void unRegister() { 32 | econ = null; 33 | } 34 | 35 | @Override 36 | public OptionalDouble getBanlance(Player player, String currency) { 37 | return OptionalDouble.of(econ.getBalance(player)); 38 | } 39 | 40 | @Override 41 | public boolean deposit(Player player, String currency, double amount) { 42 | EconomyResponse respone = econ.depositPlayer(player, amount); 43 | return respone.transactionSuccess(); 44 | } 45 | 46 | @Override 47 | public boolean withdraw(Player player, String currency, double amount) { 48 | EconomyResponse respone = econ.withdrawPlayer(player, amount); 49 | return respone.transactionSuccess(); 50 | } 51 | 52 | } 53 | -------------------------------------------------------------------------------- /bukkit/src/main/java/com/blzeecraft/virtualmenu/bukkit/economy/package-info.java: -------------------------------------------------------------------------------- 1 | package com.blzeecraft.virtualmenu.bukkit.economy; -------------------------------------------------------------------------------- /bukkit/src/main/java/com/blzeecraft/virtualmenu/bukkit/hook/package-info.java: -------------------------------------------------------------------------------- 1 | package com.blzeecraft.virtualmenu.bukkit.hook; -------------------------------------------------------------------------------- /bukkit/src/main/java/com/blzeecraft/virtualmenu/bukkit/item/ItemUtils.java: -------------------------------------------------------------------------------- 1 | package com.blzeecraft.virtualmenu.bukkit.item; 2 | 3 | import java.lang.reflect.InvocationTargetException; 4 | import java.lang.reflect.Method; 5 | import java.util.Arrays; 6 | import java.util.List; 7 | import java.util.Optional; 8 | 9 | import org.bukkit.Bukkit; 10 | import org.bukkit.Material; 11 | import org.bukkit.inventory.ItemStack; 12 | import org.bukkit.inventory.meta.ItemMeta; 13 | 14 | import com.meowj.langutils.lang.LanguageHelper; 15 | 16 | public class ItemUtils { 17 | 18 | public static String getDisplayname(ItemStack item) { 19 | if (item == null) { 20 | return null; 21 | } 22 | ItemMeta meta = item.getItemMeta(); 23 | if (meta == null) { 24 | return null; 25 | } 26 | return meta.getDisplayName(); 27 | } 28 | 29 | public static List getLore(ItemStack item) { 30 | if (item == null) { 31 | return null; 32 | } 33 | ItemMeta meta = item.getItemMeta(); 34 | if (meta == null) { 35 | return null; 36 | } 37 | return meta.getLore(); 38 | } 39 | 40 | public static ItemStack setDisplayname(ItemStack item, String displayname) { 41 | ItemMeta meta = item.getItemMeta(); 42 | meta.setDisplayName(displayname); 43 | item.setItemMeta(meta); 44 | return item; 45 | } 46 | 47 | public static ItemStack setLore(ItemStack item, String... lore) { 48 | ItemMeta meta = item.getItemMeta(); 49 | meta.setLore(Arrays.asList(lore)); 50 | item.setItemMeta(meta); 51 | return item; 52 | } 53 | 54 | public static ItemStack asNMSCopy(ItemStack original) { 55 | try { 56 | Class clazz = Class 57 | .forName(Bukkit.getServer().getClass().getPackage().getName() + ".inventory.CraftItemStack"); 58 | Method method = clazz.getMethod("asCraftCopy", ItemStack.class); 59 | return (ItemStack) method.invoke(null, original); 60 | } catch (Exception e) { 61 | e.printStackTrace(); 62 | } 63 | return original; 64 | } 65 | 66 | 67 | public static Optional getMaterial(int id) throws NoSuchMethodException { 68 | try { 69 | Method m = Material.class.getMethod("getMaterial", int.class); 70 | return Optional.ofNullable((Material) m.invoke(null, id)); 71 | } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) { 72 | e.printStackTrace(); 73 | } 74 | return Optional.empty(); 75 | } 76 | 77 | public static Optional getMaterial(String id){ 78 | return Optional.ofNullable(Material.getMaterial(id)); 79 | } 80 | 81 | public static String getItemName(ItemStack item) { 82 | if (item == null) { 83 | return "null"; 84 | } 85 | // 使用LangUtils获取物品名称 86 | try { 87 | Class.forName("com.meowj.langutils.lang.LanguageHelper"); 88 | return LanguageHelper.getItemName(item, "zh_CN"); 89 | } catch (ClassNotFoundException e) { 90 | } 91 | try { 92 | ItemStack.class.getMethod("getI18NDisplayName", new Class[0]); 93 | return item.getI18NDisplayName(); 94 | } catch (NoSuchMethodException | SecurityException e) { 95 | } 96 | return item.getType().name(); 97 | } 98 | 99 | } 100 | -------------------------------------------------------------------------------- /bukkit/src/main/java/com/blzeecraft/virtualmenu/bukkit/item/NBTUtils.java: -------------------------------------------------------------------------------- 1 | package com.blzeecraft.virtualmenu.bukkit.item; 2 | 3 | import java.io.IOException; 4 | 5 | import org.bukkit.inventory.ItemStack; 6 | 7 | import com.blzeecraft.virtualmenu.bukkit.conf.Settings; 8 | import com.comphenix.protocol.wrappers.nbt.NbtCompound; 9 | import com.comphenix.protocol.wrappers.nbt.NbtFactory; 10 | import com.comphenix.protocol.wrappers.nbt.NbtWrapper; 11 | import com.comphenix.protocol.wrappers.nbt.io.NbtTextSerializer; 12 | 13 | import lombok.AccessLevel; 14 | import lombok.NoArgsConstructor; 15 | 16 | @NoArgsConstructor(access = AccessLevel.PRIVATE) 17 | public class NBTUtils { 18 | 19 | public static String itemNBTtoText(ItemStack item) { 20 | if (Settings.supportNBT) { 21 | NbtWrapper wrapper = NbtFactory.fromItemTag(item); 22 | return NbtTextSerializer.DEFAULT.serialize(wrapper); 23 | } else { 24 | return "unsupport"; 25 | } 26 | 27 | } 28 | 29 | public static ItemStack setItemNBT(ItemStack original, String text) throws IOException { 30 | NbtWrapper wrapper = NbtTextSerializer.DEFAULT.deserialize(text); 31 | NbtCompound compound = NbtFactory.asCompound(wrapper); 32 | original = checkClass(original); 33 | NbtFactory.setItemTag(original, compound); 34 | return original; 35 | } 36 | 37 | public static ItemStack checkClass(ItemStack item) { 38 | if (item.getClass() == ItemStack.class) { 39 | return ItemUtils.asNMSCopy(item); 40 | } 41 | return item; 42 | } 43 | 44 | public static boolean isVaidNBT(String text) { 45 | return Settings.supportNBT && text != null && !text.isEmpty() && !"unsupport".equalsIgnoreCase(text); 46 | } 47 | 48 | } 49 | -------------------------------------------------------------------------------- /bukkit/src/main/java/com/blzeecraft/virtualmenu/bukkit/item/package-info.java: -------------------------------------------------------------------------------- 1 | package com.blzeecraft.virtualmenu.bukkit.item; -------------------------------------------------------------------------------- /bukkit/src/main/java/com/blzeecraft/virtualmenu/bukkit/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * @author colors_wind 3 | * @date 2020-02-18 4 | * 5 | */ 6 | package com.blzeecraft.virtualmenu.bukkit; -------------------------------------------------------------------------------- /bukkit/src/main/java/com/blzeecraft/virtualmenu/bukkit/packet/PacketDebugHandler.java: -------------------------------------------------------------------------------- 1 | package com.blzeecraft.virtualmenu.bukkit.packet; 2 | 3 | import com.blzeecraft.virtualmenu.bukkit.BukkitPlatform; 4 | import com.blzeecraft.virtualmenu.bukkit.VirtualMenuPlugin; 5 | import com.blzeecraft.virtualmenu.core.logger.PluginLogger; 6 | import com.comphenix.protocol.PacketType; 7 | import com.comphenix.protocol.events.ListenerPriority; 8 | import com.comphenix.protocol.events.PacketAdapter; 9 | import com.comphenix.protocol.events.PacketEvent; 10 | 11 | public class PacketDebugHandler extends PacketAdapter { 12 | @SuppressWarnings("unused") 13 | private final BukkitPlatform platform; 14 | 15 | public PacketDebugHandler(VirtualMenuPlugin plugin) { 16 | super(plugin, ListenerPriority.MONITOR, 17 | PacketType.Play.Server.OPEN_WINDOW, PacketType.Play.Server.WINDOW_ITEMS, PacketType.Play.Client.CLOSE_WINDOW, PacketType.Play.Server.SET_SLOT); 18 | this.platform = plugin.getPlatformAdapter(); 19 | } 20 | 21 | @Override 22 | public void onPacketReceiving(PacketEvent e) { 23 | System.out.println("Receiving packet:" + e.getPacketType() + " from: " + e.getPlayer().getName()); 24 | PluginLogger.debugPacket(e.getPacket().getHandle()); 25 | } 26 | 27 | @Override 28 | public void onPacketSending(PacketEvent e) { 29 | System.out.println("Send packet:" + e.getPacketType() + " target: " + e.getPlayer().getName()); 30 | PluginLogger.debugPacket(e.getPacket().getHandle()); 31 | } 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | } 41 | -------------------------------------------------------------------------------- /bukkit/src/main/java/com/blzeecraft/virtualmenu/bukkit/packet/PacketListener.java: -------------------------------------------------------------------------------- 1 | package com.blzeecraft.virtualmenu.bukkit.packet; 2 | 3 | import org.bukkit.event.EventHandler; 4 | import org.bukkit.event.Listener; 5 | import org.bukkit.event.player.PlayerQuitEvent; 6 | 7 | import com.blzeecraft.virtualmenu.bukkit.BukkitPlatform; 8 | import com.blzeecraft.virtualmenu.bukkit.VirtualMenuPlugin; 9 | import com.blzeecraft.virtualmenu.core.packet.PacketHandler; 10 | import com.blzeecraft.virtualmenu.core.user.IUser; 11 | import com.blzeecraft.virtualmenu.core.user.UserManager; 12 | import com.comphenix.protocol.PacketType; 13 | import com.comphenix.protocol.events.ListenerPriority; 14 | import com.comphenix.protocol.events.PacketAdapter; 15 | import com.comphenix.protocol.events.PacketEvent; 16 | 17 | import lombok.val; 18 | 19 | public class PacketListener extends PacketAdapter implements Listener { 20 | private final BukkitPlatform platform; 21 | private final ProtocolLibAdapter packetAdapter; 22 | 23 | public PacketListener(VirtualMenuPlugin plugin, ProtocolLibAdapter packetAdapter) { 24 | super(plugin, ListenerPriority.MONITOR, PacketType.Play.Client.CLOSE_WINDOW, 25 | PacketType.Play.Client.WINDOW_CLICK, PacketType.Play.Server.WINDOW_ITEMS, 26 | PacketType.Play.Server.SET_SLOT); 27 | this.platform = plugin.getPlatformAdapter(); 28 | this.packetAdapter = packetAdapter; 29 | } 30 | 31 | @Override 32 | public void onPacketReceiving(PacketEvent e) { 33 | platform.getUserExact(e.getPlayer()).flatMap(IUser::getCurrentSession).ifPresent(session -> { 34 | val packetType = e.getPacketType(); 35 | val packet = e.getPacket(); 36 | final boolean cancel; 37 | if (packetType == PacketType.Play.Client.CLOSE_WINDOW) { 38 | cancel = PacketHandler.handleClientPacket(session, packetAdapter.mapToCloseWindow(packet)); 39 | } else if (packetType == PacketType.Play.Client.WINDOW_CLICK) { 40 | cancel = PacketHandler.handleClientPacket(session, packetAdapter.mapToWindowClick(packet)); 41 | } else { 42 | return; 43 | } 44 | if (cancel) { 45 | e.setReadOnly(false); 46 | e.setCancelled(true); 47 | } 48 | }); 49 | 50 | } 51 | 52 | @Override 53 | public void onPacketSending(PacketEvent e) { 54 | platform.getUserExact(e.getPlayer()).flatMap(IUser::getCurrentSession).ifPresent(session -> { 55 | val packetType = e.getPacketType(); 56 | val packet = e.getPacket(); 57 | final boolean cancel; 58 | if (packetType == PacketType.Play.Server.WINDOW_ITEMS) { 59 | cancel = PacketHandler.handleServerPacket(session, packetAdapter.mapToWindowItems(packet)); 60 | } else if (packetType == PacketType.Play.Client.WINDOW_CLICK) { 61 | cancel = PacketHandler.handleServerPacket(session, packetAdapter.mapToSetSlot(packet)); 62 | } else { 63 | return; 64 | } 65 | if (cancel) { 66 | e.setReadOnly(false); 67 | e.setCancelled(true); 68 | } 69 | }); 70 | } 71 | 72 | @EventHandler 73 | public void handle(PlayerQuitEvent e) { 74 | platform.getUserExact(e.getPlayer()).flatMap(IUser::getCurrentSession) 75 | .ifPresent(UserManager::handleClosePacketMenu); 76 | } 77 | 78 | } 79 | -------------------------------------------------------------------------------- /bukkit/src/main/java/com/blzeecraft/virtualmenu/bukkit/packet/PacketPlayInCloseWindow.java: -------------------------------------------------------------------------------- 1 | package com.blzeecraft.virtualmenu.bukkit.packet; 2 | 3 | import com.blzeecraft.virtualmenu.core.packet.AbstractPacketInCloseWindow; 4 | import com.comphenix.protocol.events.PacketContainer; 5 | 6 | public class PacketPlayInCloseWindow extends AbstractPacketInCloseWindow { 7 | protected final PacketContainer packet = super.packet; // 避免强制准换 8 | 9 | public PacketPlayInCloseWindow(PacketContainer packet) { 10 | super(packet); 11 | } 12 | 13 | @Override 14 | public void setWindowId(int windowId) { 15 | packet.getIntegers().write(0, windowId); 16 | } 17 | 18 | @Override 19 | public int getWindowId() { 20 | return packet.getIntegers().read(0); 21 | } 22 | 23 | } 24 | -------------------------------------------------------------------------------- /bukkit/src/main/java/com/blzeecraft/virtualmenu/bukkit/packet/PacketPlayInWindowClick1_7.java: -------------------------------------------------------------------------------- 1 | package com.blzeecraft.virtualmenu.bukkit.packet; 2 | 3 | import org.bukkit.inventory.ItemStack; 4 | 5 | import com.blzeecraft.virtualmenu.bukkit.WrapItemBukkit; 6 | import com.blzeecraft.virtualmenu.core.item.AbstractItem; 7 | import com.blzeecraft.virtualmenu.core.packet.AbstractPacketInWindowClick; 8 | import com.blzeecraft.virtualmenu.core.packet.ClickMode; 9 | import com.comphenix.protocol.events.PacketContainer; 10 | 11 | public class PacketPlayInWindowClick1_7 extends AbstractPacketInWindowClick { 12 | 13 | public PacketPlayInWindowClick1_7(PacketContainer handle) { 14 | super(handle); 15 | } 16 | 17 | @Override 18 | public void setRawSlot(int slot) { 19 | packet.getIntegers().write(1, slot); 20 | } 21 | 22 | @Override 23 | public int getRawSlot() { 24 | return packet.getIntegers().read(1); 25 | } 26 | 27 | @Override 28 | public void setClickMode(ClickMode mode) { 29 | packet.getIntegers().write(3, mode.ordinal()); 30 | } 31 | 32 | @Override 33 | public ClickMode getClickMode() { 34 | return ClickMode.values()[packet.getIntegers().read(3)]; 35 | } 36 | 37 | @Override 38 | public void setButton(int button) { 39 | packet.getIntegers().write(2, button); 40 | } 41 | 42 | @Override 43 | public int getButton() { 44 | return packet.getIntegers().read(2); 45 | } 46 | 47 | @Override 48 | public void setClickedItem(AbstractItem item) { 49 | ItemStack clickedItem = (ItemStack) item.getHandle(); 50 | packet.getItemModifier().write(0, clickedItem); 51 | } 52 | 53 | @Override 54 | public AbstractItem getClickedItem() { 55 | ItemStack clickedItem = packet.getItemModifier().read(0); 56 | return new WrapItemBukkit(clickedItem); 57 | } 58 | 59 | @Override 60 | public void setWindowId(int windowId) { 61 | packet.getIntegers().write(0, windowId); 62 | } 63 | 64 | @Override 65 | public int getWindowId() { 66 | return packet.getIntegers().read(0); 67 | } 68 | 69 | } 70 | -------------------------------------------------------------------------------- /bukkit/src/main/java/com/blzeecraft/virtualmenu/bukkit/packet/PacketPlayInWindowClick1_8.java: -------------------------------------------------------------------------------- 1 | package com.blzeecraft.virtualmenu.bukkit.packet; 2 | 3 | import org.bukkit.inventory.ItemStack; 4 | 5 | import com.blzeecraft.virtualmenu.bukkit.WrapItemBukkit; 6 | import com.blzeecraft.virtualmenu.core.item.AbstractItem; 7 | import com.blzeecraft.virtualmenu.core.packet.AbstractPacketInWindowClick; 8 | import com.blzeecraft.virtualmenu.core.packet.ClickMode; 9 | import com.comphenix.protocol.events.PacketContainer; 10 | 11 | public class PacketPlayInWindowClick1_8 extends AbstractPacketInWindowClick { 12 | 13 | public PacketPlayInWindowClick1_8(PacketContainer handle) { 14 | super(handle); 15 | } 16 | 17 | @Override 18 | public void setRawSlot(int slot) { 19 | packet.getIntegers().write(1, slot); 20 | } 21 | 22 | @Override 23 | public int getRawSlot() { 24 | return packet.getIntegers().read(1); 25 | } 26 | 27 | @Override 28 | public void setClickMode(ClickMode mode) { 29 | packet.getEnumModifier(ClickMode.class, 5).write(0, mode); 30 | } 31 | 32 | @Override 33 | public ClickMode getClickMode() { 34 | return packet.getEnumModifier(ClickMode.class, 5).read(0); 35 | } 36 | 37 | @Override 38 | public void setButton(int button) { 39 | packet.getIntegers().write(2, button); 40 | } 41 | 42 | @Override 43 | public int getButton() { 44 | return packet.getIntegers().read(2); 45 | } 46 | 47 | @Override 48 | public void setClickedItem(AbstractItem item) { 49 | ItemStack clickedItem = (ItemStack) item.getHandle(); 50 | packet.getItemModifier().write(0, clickedItem); 51 | } 52 | 53 | @Override 54 | public AbstractItem getClickedItem() { 55 | ItemStack clickedItem = packet.getItemModifier().read(0); 56 | return new WrapItemBukkit(clickedItem); 57 | } 58 | 59 | @Override 60 | public void setWindowId(int windowId) { 61 | packet.getIntegers().write(0, windowId); 62 | } 63 | 64 | @Override 65 | public int getWindowId() { 66 | return packet.getIntegers().read(0); 67 | } 68 | 69 | } 70 | -------------------------------------------------------------------------------- /bukkit/src/main/java/com/blzeecraft/virtualmenu/bukkit/packet/PacketPlayOutCloseWindow.java: -------------------------------------------------------------------------------- 1 | package com.blzeecraft.virtualmenu.bukkit.packet; 2 | 3 | import com.blzeecraft.virtualmenu.core.packet.AbstractPacketOutCloseWindow; 4 | import com.comphenix.protocol.PacketType; 5 | import com.comphenix.protocol.events.PacketContainer; 6 | 7 | public class PacketPlayOutCloseWindow extends AbstractPacketOutCloseWindow { 8 | protected final PacketContainer packet = super.packet; // 避免强制准换 9 | 10 | public PacketPlayOutCloseWindow() { 11 | super(new PacketContainer(PacketType.Play.Server.CLOSE_WINDOW)); 12 | } 13 | 14 | @Override 15 | public void setWindowId(int windowId) { 16 | packet.getIntegers().write(0, windowId); 17 | } 18 | 19 | @Override 20 | public int getWindowId() { 21 | return packet.getIntegers().read(0); 22 | } 23 | 24 | } 25 | -------------------------------------------------------------------------------- /bukkit/src/main/java/com/blzeecraft/virtualmenu/bukkit/packet/PacketPlayOutSetSlot.java: -------------------------------------------------------------------------------- 1 | package com.blzeecraft.virtualmenu.bukkit.packet; 2 | 3 | import org.bukkit.inventory.ItemStack; 4 | 5 | import com.blzeecraft.virtualmenu.bukkit.WrapItemBukkit; 6 | import com.blzeecraft.virtualmenu.core.item.AbstractItem; 7 | import com.blzeecraft.virtualmenu.core.packet.AbstractPacketOutSetSlot; 8 | import com.comphenix.protocol.PacketType; 9 | import com.comphenix.protocol.events.PacketContainer; 10 | 11 | public class PacketPlayOutSetSlot extends AbstractPacketOutSetSlot { 12 | protected final PacketContainer packet = super.packet; // 避免强制准换 13 | 14 | public PacketPlayOutSetSlot() { 15 | this(new PacketContainer(PacketType.Play.Server.SET_SLOT)); 16 | } 17 | 18 | public PacketPlayOutSetSlot(PacketContainer packet) { 19 | super(packet); 20 | } 21 | 22 | @Override 23 | public void setSlot(int slot) { 24 | packet.getIntegers().write(1, slot); 25 | } 26 | 27 | @Override 28 | public int getSlot() { 29 | return packet.getIntegers().read(1); 30 | } 31 | 32 | @Override 33 | public void setItem(AbstractItem item) { 34 | this.setRawItem(item.getHandle()); 35 | } 36 | 37 | @Override 38 | public AbstractItem getItem() { 39 | return new WrapItemBukkit(packet.getItemModifier().read(0)); 40 | } 41 | 42 | @Override 43 | public void setWindowId(int windowId) { 44 | packet.getIntegers().write(0, windowId); 45 | 46 | } 47 | 48 | @Override 49 | public int getWindowId() { 50 | return packet.getIntegers().read(0); 51 | } 52 | 53 | @Override 54 | public void setRawItem(Object item) { 55 | packet.getItemModifier().write(0, (ItemStack) item); 56 | } 57 | 58 | @Override 59 | public ItemStack getRawItem() { 60 | return packet.getItemModifier().read(0); 61 | } 62 | 63 | } 64 | -------------------------------------------------------------------------------- /bukkit/src/main/java/com/blzeecraft/virtualmenu/bukkit/packet/PacketPlayOutWIndowOpen1_14.java: -------------------------------------------------------------------------------- 1 | package com.blzeecraft.virtualmenu.bukkit.packet; 2 | 3 | import com.blzeecraft.virtualmenu.bukkit.MenuType; 4 | import com.blzeecraft.virtualmenu.core.menu.IMenuType; 5 | import com.blzeecraft.virtualmenu.core.packet.AbstractPacketOutWindowOpen; 6 | import com.comphenix.protocol.PacketType; 7 | import com.comphenix.protocol.events.PacketContainer; 8 | import com.comphenix.protocol.wrappers.WrappedChatComponent; 9 | 10 | public class PacketPlayOutWIndowOpen1_14 extends AbstractPacketOutWindowOpen { 11 | protected final PacketContainer packet = super.packet; // 避免强制准换 12 | 13 | public PacketPlayOutWIndowOpen1_14() { 14 | super(new PacketContainer(PacketType.Play.Server.OPEN_WINDOW)); 15 | 16 | } 17 | 18 | @Override 19 | public void setTitle(String title) { 20 | WrappedChatComponent component = WrappedChatComponent.fromText(title); 21 | packet.getChatComponents().write(0, component); 22 | } 23 | 24 | @Override 25 | public String getTitle() { 26 | return packet.getChatComponents().read(0).toString(); 27 | } 28 | 29 | @Override 30 | public void setMenuType(IMenuType menuType) { 31 | packet.getIntegers().write(1, menuType.getIndex()); 32 | } 33 | 34 | @Override 35 | public IMenuType getMenuType() { 36 | int index = packet.getIntegers().read(1); 37 | return MenuType.values()[index]; 38 | } 39 | 40 | @Override 41 | public void setWindowId(int windowId) { 42 | packet.getSpecificModifier(boolean.class).write(0, true); 43 | packet.getIntegers().write(0, windowId); 44 | } 45 | 46 | @Override 47 | public int getWindowId() { 48 | return packet.getIntegers().read(0); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /bukkit/src/main/java/com/blzeecraft/virtualmenu/bukkit/packet/PacketPlayOutWindowItems1_11.java: -------------------------------------------------------------------------------- 1 | package com.blzeecraft.virtualmenu.bukkit.packet; 2 | 3 | import java.util.Arrays; 4 | import java.util.List; 5 | import java.util.stream.Collectors; 6 | 7 | import org.bukkit.Material; 8 | import org.bukkit.inventory.ItemStack; 9 | 10 | import com.blzeecraft.virtualmenu.bukkit.BukkitPlatform; 11 | import com.blzeecraft.virtualmenu.bukkit.WrapItemBukkit; 12 | import com.blzeecraft.virtualmenu.core.item.AbstractItem; 13 | import com.blzeecraft.virtualmenu.core.packet.AbstractPacketOutWindowItems; 14 | import com.comphenix.protocol.PacketType; 15 | import com.comphenix.protocol.events.PacketContainer; 16 | 17 | public class PacketPlayOutWindowItems1_11 extends AbstractPacketOutWindowItems { 18 | public static final ItemStack EMPTY_ITEM = new ItemStack(Material.AIR); 19 | protected final PacketContainer packet = super.packet; // 避免强制准换 20 | 21 | public PacketPlayOutWindowItems1_11() { 22 | this(new PacketContainer(PacketType.Play.Server.WINDOW_ITEMS)); 23 | } 24 | 25 | public PacketPlayOutWindowItems1_11(PacketContainer packet) { 26 | super(packet); 27 | } 28 | 29 | @Override 30 | public void setItems(AbstractItem[] items) { 31 | List itemList = Arrays.stream(items).map(item -> item == null ? EMPTY_ITEM : (ItemStack)item.getHandle()).collect(Collectors.toList()); 32 | packet.getItemListModifier().write(0, itemList); 33 | } 34 | 35 | 36 | @Override 37 | public AbstractItem[] getItems() { 38 | List itemList = packet.getItemListModifier().read(0); 39 | return itemList.stream().map(WrapItemBukkit::new).collect(Collectors.toList()) 40 | .toArray(new WrapItemBukkit[itemList.size()]); 41 | } 42 | 43 | @Override 44 | public void setWindowId(int windowId) { 45 | packet.getIntegers().write(0, windowId); 46 | } 47 | 48 | @Override 49 | public int getWindowId() { 50 | return packet.getIntegers().read(0); 51 | } 52 | 53 | @Override 54 | public void setRawItems(Object[] items) { 55 | packet.getItemListModifier().write(0, Arrays.asList(BukkitPlatform.castItemArray(items))); 56 | } 57 | 58 | @Override 59 | public ItemStack[] getRawItems() { 60 | List items = packet.getItemListModifier().read(0); 61 | return items.toArray(new ItemStack[items.size()]); 62 | } 63 | 64 | } 65 | -------------------------------------------------------------------------------- /bukkit/src/main/java/com/blzeecraft/virtualmenu/bukkit/packet/PacketPlayOutWindowItems1_7.java: -------------------------------------------------------------------------------- 1 | package com.blzeecraft.virtualmenu.bukkit.packet; 2 | 3 | import java.util.Arrays; 4 | import java.util.stream.Collectors; 5 | 6 | import org.bukkit.Material; 7 | import org.bukkit.inventory.ItemStack; 8 | 9 | import com.blzeecraft.virtualmenu.bukkit.BukkitPlatform; 10 | import com.blzeecraft.virtualmenu.bukkit.WrapItemBukkit; 11 | import com.blzeecraft.virtualmenu.core.item.AbstractItem; 12 | import com.blzeecraft.virtualmenu.core.packet.AbstractPacketOutWindowItems; 13 | import com.comphenix.protocol.PacketType; 14 | import com.comphenix.protocol.events.PacketContainer; 15 | 16 | public class PacketPlayOutWindowItems1_7 extends AbstractPacketOutWindowItems { 17 | public static final ItemStack EMPTY_ITEM = new ItemStack(Material.AIR); 18 | protected final PacketContainer packet = super.packet; // 避免强制准换 19 | 20 | public PacketPlayOutWindowItems1_7() { 21 | this(new PacketContainer(PacketType.Play.Server.WINDOW_ITEMS)); 22 | } 23 | 24 | public PacketPlayOutWindowItems1_7(PacketContainer packet) { 25 | super(packet); 26 | } 27 | 28 | @Override 29 | public void setItems(AbstractItem[] items) { 30 | int size = items.length; 31 | ItemStack[] itemArray = new ItemStack[size]; 32 | for (int i = 0; i < size; i++) { 33 | itemArray[i] = items[i] == null ? EMPTY_ITEM : (ItemStack) items[i].getHandle(); 34 | } 35 | packet.getItemArrayModifier().write(0, itemArray); 36 | } 37 | 38 | @Override 39 | public AbstractItem[] getItems() { 40 | ItemStack[] itemArray = getRawItems(); 41 | return Arrays.stream(itemArray).map(WrapItemBukkit::new).collect(Collectors.toList()) 42 | .toArray(new WrapItemBukkit[itemArray.length]); 43 | } 44 | 45 | @Override 46 | public void setWindowId(int windowId) { 47 | packet.getIntegers().write(0, windowId); 48 | } 49 | 50 | @Override 51 | public int getWindowId() { 52 | return packet.getIntegers().read(0); 53 | } 54 | 55 | @Override 56 | public void setRawItems(Object[] items) { 57 | packet.getItemArrayModifier().write(0, BukkitPlatform.castItemArray(items)); 58 | } 59 | 60 | @Override 61 | public ItemStack[] getRawItems() { 62 | return packet.getItemArrayModifier().read(0); 63 | } 64 | 65 | } 66 | -------------------------------------------------------------------------------- /bukkit/src/main/java/com/blzeecraft/virtualmenu/bukkit/packet/PacketPlayOutWindowOpen1_7.java: -------------------------------------------------------------------------------- 1 | package com.blzeecraft.virtualmenu.bukkit.packet; 2 | 3 | import java.util.Arrays; 4 | import java.util.NoSuchElementException; 5 | 6 | import com.blzeecraft.virtualmenu.bukkit.MenuType; 7 | import com.blzeecraft.virtualmenu.core.menu.IMenuType; 8 | import com.blzeecraft.virtualmenu.core.packet.AbstractPacketOutWindowOpen; 9 | import com.comphenix.protocol.PacketType; 10 | import com.comphenix.protocol.events.PacketContainer; 11 | 12 | public class PacketPlayOutWindowOpen1_7 extends AbstractPacketOutWindowOpen { 13 | protected final PacketContainer packet = super.packet; // 避免强制准换 14 | 15 | public PacketPlayOutWindowOpen1_7() { 16 | super(new PacketContainer(PacketType.Play.Server.OPEN_WINDOW)); 17 | } 18 | 19 | @Override 20 | public void setTitle(String title) { 21 | packet.getStrings().write(0, title); 22 | } 23 | 24 | @Override 25 | public String getTitle() { 26 | return packet.getStrings().read(0); 27 | } 28 | 29 | @Override 30 | public void setMenuType(IMenuType menuType) { 31 | packet.getIntegers().write(1, Math.max(0, menuType.getLegacyIndex())); 32 | packet.getIntegers().write(2, menuType.getSize()); 33 | 34 | } 35 | 36 | @Override 37 | public IMenuType getMenuType() throws NoSuchElementException { 38 | int legacyIndex = packet.getIntegers().read(1); 39 | int size = packet.getIntegers().read(2); 40 | return Arrays.stream(MenuType.values()).filter(type -> type.getLegacyIndex() == legacyIndex) 41 | .filter(type -> type.getSize() == size).findAny().get(); 42 | } 43 | 44 | @Override 45 | public void setWindowId(int windowId) { 46 | packet.getSpecificModifier(boolean.class).write(0, true); 47 | packet.getIntegers().write(0, windowId); 48 | } 49 | 50 | @Override 51 | public int getWindowId() { 52 | return packet.getIntegers().read(0); 53 | } 54 | 55 | } 56 | -------------------------------------------------------------------------------- /bukkit/src/main/java/com/blzeecraft/virtualmenu/bukkit/packet/PacketPlayOutWindowOpen1_8.java: -------------------------------------------------------------------------------- 1 | package com.blzeecraft.virtualmenu.bukkit.packet; 2 | 3 | import java.util.Arrays; 4 | import java.util.NoSuchElementException; 5 | 6 | import com.blzeecraft.virtualmenu.bukkit.MenuType; 7 | import com.blzeecraft.virtualmenu.core.menu.IMenuType; 8 | import com.blzeecraft.virtualmenu.core.packet.AbstractPacketOutWindowOpen; 9 | import com.comphenix.protocol.PacketType; 10 | import com.comphenix.protocol.events.PacketContainer; 11 | import com.comphenix.protocol.wrappers.WrappedChatComponent; 12 | 13 | public class PacketPlayOutWindowOpen1_8 extends AbstractPacketOutWindowOpen { 14 | protected final PacketContainer packet = super.packet; // 避免强制准换 15 | 16 | public PacketPlayOutWindowOpen1_8() { 17 | super(new PacketContainer(PacketType.Play.Server.OPEN_WINDOW)); 18 | } 19 | 20 | @Override 21 | public void setTitle(String title) { 22 | WrappedChatComponent component = WrappedChatComponent.fromText(title); 23 | packet.getChatComponents().write(0, component); 24 | } 25 | 26 | @Override 27 | public String getTitle() { 28 | return packet.getChatComponents().read(0).toString(); 29 | } 30 | 31 | @Override 32 | public void setMenuType(IMenuType menuType) { 33 | packet.getStrings().write(0, menuType.getMinecraftKey()); 34 | packet.getIntegers().write(1, menuType.getSize()); 35 | 36 | } 37 | 38 | @Override 39 | public IMenuType getMenuType() throws NoSuchElementException { 40 | String minecraftKey = packet.getStrings().read(0); 41 | int size = packet.getIntegers().read(1); 42 | return Arrays.stream(MenuType.values()).filter(type -> type.getMinecraftKey().equalsIgnoreCase(minecraftKey)).filter(type -> type.getSize() == size).findAny().get(); 43 | } 44 | 45 | @Override 46 | public void setWindowId(int windowId) { 47 | packet.getIntegers().write(0, windowId); 48 | } 49 | 50 | @Override 51 | public int getWindowId() { 52 | return packet.getIntegers().read(0); 53 | } 54 | 55 | } 56 | -------------------------------------------------------------------------------- /bukkit/src/main/java/com/blzeecraft/virtualmenu/bukkit/packet/package-info.java: -------------------------------------------------------------------------------- 1 | package com.blzeecraft.virtualmenu.bukkit.packet; -------------------------------------------------------------------------------- /bukkit/src/main/java/com/blzeecraft/virtualmenu/bukkit/title/Constants.java: -------------------------------------------------------------------------------- 1 | package com.blzeecraft.virtualmenu.bukkit.title; 2 | 3 | public class Constants { 4 | 5 | public static int TITLE_STAY = 7; 6 | public static int TITLE_FADE = 3; 7 | 8 | } 9 | -------------------------------------------------------------------------------- /bukkit/src/main/java/com/blzeecraft/virtualmenu/bukkit/title/ITitleAPI.java: -------------------------------------------------------------------------------- 1 | package com.blzeecraft.virtualmenu.bukkit.title; 2 | 3 | import org.bukkit.entity.Player; 4 | 5 | public interface ITitleAPI { 6 | 7 | void sendTitle(Player p, String title, String subtitle, int fadeIn, int stay, int fadeOut); 8 | 9 | void sendActionBar(Player p, String msg); 10 | 11 | void sendHeaderAndFooter(Player p, String head, String foot); 12 | 13 | } 14 | -------------------------------------------------------------------------------- /bukkit/src/main/java/com/blzeecraft/virtualmenu/bukkit/title/TitleAPI.java: -------------------------------------------------------------------------------- 1 | package com.blzeecraft.virtualmenu.bukkit.title; 2 | 3 | import org.bukkit.GameMode; 4 | import org.bukkit.entity.Player; 5 | 6 | 7 | 8 | public class TitleAPI { 9 | public static final ITitleAPI API = getAPI(); 10 | 11 | public static ITitleAPI getAPI() { 12 | // 较高版本的Bukkit已经自带了sendActionbar等方法 13 | try { 14 | Player.class.getMethod("sendActionBar", String.class); 15 | return new TitleBukkit(); 16 | } catch (Exception e) { 17 | } 18 | // 较老版本的Bukkit使用ProtocolLib 19 | try { 20 | GameMode.class.getField("SPECTATOR"); 21 | return new TitlePacket(); 22 | } catch (Exception e) { 23 | } 24 | // 版本在1.7.10或以下的使用sendMessage代替 25 | return new TitleLegacy(); 26 | } 27 | 28 | 29 | public static void sendTitle(Player player, String title, String subtitle) { 30 | API.sendTitle(player, title, subtitle, 31 | Constants.TITLE_FADE, Constants.TITLE_STAY, Constants.TITLE_FADE); 32 | } 33 | 34 | public static void sendTitle(Player player, String title, String subtitle, 35 | int fadeIn, int stay, int fadeOut) { 36 | API.sendTitle(player, title, subtitle, fadeIn, stay, fadeOut); 37 | } 38 | 39 | 40 | 41 | public static void sendActionBar(Player p, String msg) { 42 | API.sendActionBar(p, msg); 43 | } 44 | 45 | 46 | 47 | public static void sendHeaderAndFooter(Player p, String head, String foot) { 48 | API.sendHeaderAndFooter(p, head, foot); 49 | } 50 | 51 | } 52 | -------------------------------------------------------------------------------- /bukkit/src/main/java/com/blzeecraft/virtualmenu/bukkit/title/TitleBukkit.java: -------------------------------------------------------------------------------- 1 | package com.blzeecraft.virtualmenu.bukkit.title; 2 | 3 | import org.bukkit.entity.Player; 4 | 5 | import net.md_5.bungee.api.chat.TextComponent; 6 | 7 | public class TitleBukkit implements ITitleAPI { 8 | 9 | @Override 10 | public void sendTitle(Player p, String title, String subtitle, int fadeIn, int stay, int fadeOut) { 11 | p.sendTitle(title, subtitle, fadeIn, stay, fadeOut); 12 | 13 | } 14 | 15 | @Override 16 | public void sendActionBar(Player p, String msg) { 17 | p.sendActionBar(msg); 18 | 19 | } 20 | 21 | @Override 22 | public void sendHeaderAndFooter(Player p, String head, String foot) { 23 | p.setPlayerListHeaderFooter(TextComponent.fromLegacyText(head), TextComponent.fromLegacyText(foot)); 24 | 25 | } 26 | 27 | } 28 | -------------------------------------------------------------------------------- /bukkit/src/main/java/com/blzeecraft/virtualmenu/bukkit/title/TitleLegacy.java: -------------------------------------------------------------------------------- 1 | package com.blzeecraft.virtualmenu.bukkit.title; 2 | 3 | import org.bukkit.entity.Player; 4 | 5 | public class TitleLegacy implements ITitleAPI { 6 | 7 | @Override 8 | public void sendTitle(Player p, String title, String subtitle, int fadeIn, int stay, int fadeOut) { 9 | p.sendMessage(title + "|" + subtitle); 10 | } 11 | 12 | @Override 13 | public void sendActionBar(Player p, String msg) { 14 | p.sendMessage(msg); 15 | 16 | } 17 | 18 | @Override 19 | public void sendHeaderAndFooter(Player p, String head, String foot) { 20 | p.sendMessage(head + "|" + foot); 21 | 22 | } 23 | 24 | } 25 | -------------------------------------------------------------------------------- /bukkit/src/main/java/com/blzeecraft/virtualmenu/bukkit/title/TitlePacket.java: -------------------------------------------------------------------------------- 1 | package com.blzeecraft.virtualmenu.bukkit.title; 2 | 3 | import java.lang.reflect.InvocationTargetException; 4 | 5 | import org.bukkit.entity.Player; 6 | 7 | import com.comphenix.protocol.ProtocolLibrary; 8 | import com.comphenix.protocol.ProtocolManager; 9 | import com.comphenix.protocol.PacketType.Play.Server; 10 | import com.comphenix.protocol.events.PacketContainer; 11 | import com.comphenix.protocol.reflect.StructureModifier; 12 | import com.comphenix.protocol.wrappers.WrappedChatComponent; 13 | import com.comphenix.protocol.wrappers.EnumWrappers.TitleAction; 14 | 15 | public class TitlePacket implements ITitleAPI { 16 | 17 | public static ProtocolManager manager = ProtocolLibrary.getProtocolManager(); 18 | 19 | 20 | @Override 21 | public void sendTitle(Player player, String title, String subtitle, int fadeIn, int stay, int fadeOut) { 22 | try { 23 | PacketContainer packet = manager.createPacket(Server.TITLE); 24 | packet.getTitleActions().write(0, TitleAction.TITLE); 25 | packet.getChatComponents().write(0, WrappedChatComponent.fromText(title)); 26 | StructureModifier modify = packet.getIntegers(); 27 | modify.write(0, fadeIn); 28 | modify.write(1, stay); 29 | modify.write(2, fadeOut); 30 | if (subtitle == null) { 31 | try { 32 | manager.sendServerPacket(player, packet); 33 | } catch (InvocationTargetException e) { 34 | e.printStackTrace(); 35 | } 36 | } else { 37 | PacketContainer packetSub = manager.createPacket(Server.TITLE); 38 | packetSub.getTitleActions().write(0, TitleAction.SUBTITLE); 39 | packetSub.getChatComponents().write(0, WrappedChatComponent.fromText(subtitle)); 40 | StructureModifier modifySub = packet.getIntegers(); 41 | modifySub.write(0, fadeIn); 42 | modifySub.write(1, stay); 43 | modifySub.write(2, fadeOut); 44 | try { 45 | manager.sendServerPacket(player, packet); 46 | manager.sendServerPacket(player, packetSub); 47 | } catch (InvocationTargetException e) { 48 | e.printStackTrace(); 49 | } 50 | } 51 | } catch (IllegalArgumentException e) { 52 | player.sendMessage(title + "|" + subtitle); 53 | } 54 | 55 | } 56 | 57 | @Override 58 | public void sendActionBar(Player p, String msg) { 59 | PacketContainer packet = manager 60 | .createPacket(Server.CHAT); 61 | packet.getChatComponents().write(0, WrappedChatComponent.fromText(msg)); 62 | packet.getBytes().write(0, (byte) 2); 63 | try { 64 | manager.sendServerPacket(p, packet); 65 | } catch (InvocationTargetException e) { 66 | e.printStackTrace(); 67 | } 68 | 69 | } 70 | 71 | @Override 72 | public void sendHeaderAndFooter(Player p, String head, String foot) { 73 | PacketContainer packet = manager 74 | .createPacket(Server.PLAYER_LIST_HEADER_FOOTER); 75 | StructureModifier modify = packet.getChatComponents(); 76 | modify.write(0, WrappedChatComponent.fromText(head)); 77 | modify.write(2, WrappedChatComponent.fromText(foot)); 78 | try { 79 | manager.sendServerPacket(p, packet); 80 | } catch (InvocationTargetException e) { 81 | e.printStackTrace(); 82 | } 83 | 84 | } 85 | 86 | } 87 | -------------------------------------------------------------------------------- /bukkit/src/main/resources/config.yml: -------------------------------------------------------------------------------- 1 | # 支持的经济系统设置 2 | EconomyHook: 3 | # 是否使用 Vault 接口 4 | Vault: true 5 | # 是否使用 PlayerPoints 接口 6 | PlayerPoints: true 7 | # 是否使用 GemsEconomy 接口 8 | GemsEconomy: true 9 | # 多货币体系, 这里为每个接口绑定货币, 可使用 '*' 代表所有货币. 10 | # e.g 消费1000金钱 -> 不满足任何绑定 -> 使用Vault 接口 11 | # 消费1000点券 -> 满足PlayerPoints绑定 -> 使用 PP 接口 12 | # esp 如果不满足任何绑定且没有配置 '*', 插件将默认: 动作不执行, 条件不满足. 13 | MultiCurrency: 14 | Vault: '*' 15 | PlayerPoints: [点券] 16 | # GemsEconomy 支持多货币, 所以 VirtualMenu 会将货币名称传递给 GE. 17 | GemsEconomy: [铜币, 银币, 金币] 18 | # 是否启用NBT支持, 启用可支持NBT, 但某些特殊的服务端可能会出现问题. 19 | SupportNBT: true 20 | # 是否使用XMaterial提供物品类型高级匹配功能, 如果是MOD服建议关闭. 21 | UseXMaterial: true 22 | # 是否使用 PlaceholderAPI 支持菜单变量, 插件本身不提供任何变量, 如果需要变量请安装papi. 23 | HookPlaceholderAPI: true 24 | 25 | -------------------------------------------------------------------------------- /bukkit/src/main/resources/plugin.yml: -------------------------------------------------------------------------------- 1 | name: VirtualMenu 2 | main: com.blzeecraft.virtualmenu.bukkit.VirtualMenuPlugin 3 | version: maven-version 4 | softdepend: [PlaceHolderAPI, PlayerPoints, Vault, LangUtils, GemsEconomy] 5 | depend: [ProtocolLib] 6 | api-version: 1.13 7 | commands: 8 | virtualmenu: 9 | description: Main command for VirtualMenu. 10 | usage: / 11 | aliases: [vm] 12 | permission: virtualmenu.admin 13 | 14 | permissions: 15 | virtualmenu.admin: 16 | description: Gives access to all virtualmenu commands 17 | default: op 18 | children: 19 | virtualmenu.open.self: false 20 | virtualmenu.open.others: false 21 | virtualmenu.reload: false -------------------------------------------------------------------------------- /common/.gitignore: -------------------------------------------------------------------------------- 1 | /target/ 2 | /.classpath 3 | /.project 4 | -------------------------------------------------------------------------------- /common/.settings/org.eclipse.core.resources.prefs: -------------------------------------------------------------------------------- 1 | eclipse.preferences.version=1 2 | encoding//src/main/java=UTF-8 3 | encoding//src/main/resources=UTF-8 4 | encoding//src/test/java=UTF-8 5 | encoding//src/test/resources=UTF-8 6 | encoding/=UTF-8 7 | -------------------------------------------------------------------------------- /common/.settings/org.eclipse.jdt.core.prefs: -------------------------------------------------------------------------------- 1 | eclipse.preferences.version=1 2 | org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8 3 | org.eclipse.jdt.core.compiler.compliance=1.8 4 | org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures=disabled 5 | org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning 6 | org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=ignore 7 | org.eclipse.jdt.core.compiler.release=disabled 8 | org.eclipse.jdt.core.compiler.source=1.8 9 | -------------------------------------------------------------------------------- /common/.settings/org.eclipse.m2e.core.prefs: -------------------------------------------------------------------------------- 1 | activeProfiles= 2 | eclipse.preferences.version=1 3 | resolveWorkspaceProjects=true 4 | version=1 5 | -------------------------------------------------------------------------------- /common/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | com.blzeecraft.virtualmenu 7 | virtualmenu-parent 8 | 2.0.0-SNAPSHOT 9 | 10 | 4.0.0 11 | 12 | virtualmenu-common 13 | 14 | -------------------------------------------------------------------------------- /common/src/main/java/com/blzeecraft/virtualmenu/core/Command.java: -------------------------------------------------------------------------------- 1 | package com.blzeecraft.virtualmenu.core; 2 | 3 | import java.util.Optional; 4 | 5 | import com.blzeecraft.virtualmenu.core.action.IAction; 6 | import com.blzeecraft.virtualmenu.core.action.event.MenuEvent; 7 | import com.blzeecraft.virtualmenu.core.condition.ICondition; 8 | import com.blzeecraft.virtualmenu.core.conf.StringSerializable; 9 | import com.blzeecraft.virtualmenu.core.conf.line.LineConfigObject; 10 | import com.blzeecraft.virtualmenu.core.conf.line.ResolvedLineConfig; 11 | import com.blzeecraft.virtualmenu.core.logger.LogNode; 12 | 13 | public abstract class Command extends LineConfigObject implements ICondition, IAction, StringSerializable { 14 | 15 | public Command(LogNode node, ResolvedLineConfig rlc) { 16 | super(node, rlc); 17 | } 18 | 19 | public Command(LogNode node) { 20 | this(node, new ResolvedLineConfig()); 21 | } 22 | 23 | @Override 24 | public void accept(MenuEvent event) { 25 | apply(event); 26 | } 27 | 28 | @Override 29 | public abstract Optional apply(MenuEvent event); 30 | 31 | public abstract String getKey(); 32 | 33 | 34 | @Override 35 | public String serialize() { 36 | return new StringBuilder(this.getKey()).append(this.rlc.toString()).toString(); 37 | } 38 | 39 | @Override 40 | public String[] seriablizeAll() { 41 | return new String[] {serialize()}; 42 | } 43 | 44 | } 45 | -------------------------------------------------------------------------------- /common/src/main/java/com/blzeecraft/virtualmenu/core/IPlatformAdapter.java: -------------------------------------------------------------------------------- 1 | package com.blzeecraft.virtualmenu.core; 2 | 3 | import java.io.File; 4 | import java.util.Collection; 5 | import java.util.Optional; 6 | import java.util.logging.Logger; 7 | 8 | import com.blzeecraft.virtualmenu.core.item.AbstractItem; 9 | import com.blzeecraft.virtualmenu.core.item.AbstractItemBuilder; 10 | import com.blzeecraft.virtualmenu.core.menu.IMenuType; 11 | import com.blzeecraft.virtualmenu.core.schedule.IScheduler; 12 | import com.blzeecraft.virtualmenu.core.user.IUser; 13 | import com.blzeecraft.virtualmenu.core.variable.IVariableAdapter; 14 | 15 | /** 16 | * 服务端平台适配器 17 | * @author colors_wind 18 | * 19 | */ 20 | public interface IPlatformAdapter { 21 | 22 | /** 23 | * 获取插件的数据目录. 24 | * @return 数据目录 25 | */ 26 | File getDataFolder(); 27 | 28 | /** 29 | * 获取当前在线的所有玩家(不包括控制台). 30 | * @return 在线的玩家 31 | */ 32 | Collection> getUsersOnline(); 33 | 34 | /** 35 | * 通过用户名获取在线的玩家. 36 | * @param name 37 | * @return 玩家,如果找不到玩家,返回 {@link Optional#empty()}. 38 | */ 39 | Optional> getUser(String name); 40 | 41 | /** 42 | * 通过玩家名称精确地获取在线的玩家. 43 | * @param name 玩家名称 44 | * @return 玩家,如果找不到玩家,返回 {@link Optional#empty()}. 45 | */ 46 | Optional> getUserExact(String name); 47 | 48 | /** 49 | * 获取控制台对象 50 | * @return 51 | */ 52 | IUser getConsole(); 53 | 54 | /** 55 | * 获取 Item(Material = AIR). 56 | * @param 57 | * @return Item 58 | */ 59 | AbstractItem emptyItem(); 60 | 61 | /** 62 | * 创建一个新的 ItemBuilder. 63 | * @return ItemBuilder 64 | */ 65 | AbstractItemBuilder createItemBuilder(); 66 | 67 | /** 68 | * 通过菜单类型的名称获取 MenuType. 69 | * @param name 70 | * @return MenuType, 如果找不到返回 {@link Optional#empty()}. 71 | */ 72 | Optional getMenuType(String name); 73 | 74 | /** 75 | * 获取所有可用的 MenuType. 76 | * @return 可用的 MenuType. 77 | */ 78 | IMenuType[] getMenuTypes(); 79 | 80 | /** 81 | * 获取任务调度器 Scheduler. 82 | * @return Scheduler 83 | */ 84 | IScheduler getScheduler(); 85 | 86 | 87 | /** 88 | * 获取适配器的版本. 89 | * @return 版本 90 | */ 91 | String getVersion(); 92 | 93 | /** 94 | * 获取日志输出器. 95 | * @return 日志输出器 96 | */ 97 | default Logger getLogger() { 98 | return Logger.getLogger("VirtualMenu"); 99 | } 100 | 101 | /** 102 | * 获取变量适配器. 103 | * @return 104 | */ 105 | IVariableAdapter getVariableAdapter(); 106 | 107 | 108 | 109 | } 110 | -------------------------------------------------------------------------------- /common/src/main/java/com/blzeecraft/virtualmenu/core/IWrappedObject.java: -------------------------------------------------------------------------------- 1 | package com.blzeecraft.virtualmenu.core; 2 | 3 | /** 4 | * 对不同平台的实例进行包装 5 | * @author colors_wind 6 | * 7 | * @param 相应的类型 8 | */ 9 | public interface IWrappedObject { 10 | 11 | T getHandle(); 12 | 13 | } 14 | -------------------------------------------------------------------------------- /common/src/main/java/com/blzeecraft/virtualmenu/core/PluginExecption.java: -------------------------------------------------------------------------------- 1 | package com.blzeecraft.virtualmenu.core; 2 | 3 | import com.blzeecraft.virtualmenu.core.logger.LogNode; 4 | import com.blzeecraft.virtualmenu.core.logger.PluginLogger; 5 | 6 | /** 7 | * 代表 VirtualMenu 产生的异常. 8 | * @author colors_wind 9 | * 10 | */ 11 | public class PluginExecption extends RuntimeException { 12 | 13 | /** 14 | * 15 | */ 16 | private static final long serialVersionUID = 8516136571412240395L; 17 | 18 | 19 | public PluginExecption() { 20 | super(); 21 | } 22 | 23 | 24 | public PluginExecption(String message, Throwable cause) { 25 | super(message, cause); 26 | } 27 | 28 | 29 | public PluginExecption(String message) { 30 | super(message); 31 | } 32 | 33 | 34 | public PluginExecption(Throwable cause) { 35 | super(cause); 36 | } 37 | 38 | 39 | public void printStackTrace(LogNode node) { 40 | PluginLogger.severe(node, "捕获到异常: " + this.getClass().getSimpleName()); 41 | this.printStackTrace(); 42 | } 43 | 44 | 45 | 46 | 47 | } 48 | -------------------------------------------------------------------------------- /common/src/main/java/com/blzeecraft/virtualmenu/core/ThreadSafe.java: -------------------------------------------------------------------------------- 1 | package com.blzeecraft.virtualmenu.core; 2 | 3 | import static java.lang.annotation.ElementType.METHOD; 4 | import static java.lang.annotation.ElementType.TYPE; 5 | import static java.lang.annotation.RetentionPolicy.RUNTIME; 6 | 7 | import java.lang.annotation.Retention; 8 | import java.lang.annotation.Target; 9 | 10 | /** 11 | * 用来标记一个类或者一个方法是线程安全的. 12 | * @author colors_wind 13 | * 14 | */ 15 | @Retention(RUNTIME) 16 | @Target({ TYPE, METHOD }) 17 | public @interface ThreadSafe { 18 | 19 | } 20 | -------------------------------------------------------------------------------- /common/src/main/java/com/blzeecraft/virtualmenu/core/VirtualMenuUtils.java: -------------------------------------------------------------------------------- 1 | package com.blzeecraft.virtualmenu.core; 2 | 3 | import java.io.BufferedInputStream; 4 | import java.io.File; 5 | import java.io.FileOutputStream; 6 | import java.io.InputStream; 7 | import java.net.URL; 8 | import java.net.URLConnection; 9 | 10 | import lombok.SneakyThrows; 11 | import lombok.val; 12 | 13 | public class VirtualMenuUtils { 14 | 15 | @SneakyThrows 16 | public static InputStream getResource(String name) { 17 | URL url = VirtualMenuUtils.class.getClassLoader().getResource(name); 18 | if (url == null) { 19 | return null; 20 | } 21 | URLConnection connection = url.openConnection(); 22 | connection.setUseCaches(false); 23 | return connection.getInputStream(); 24 | } 25 | 26 | @SneakyThrows 27 | public static boolean saveResouce(String name, File target) { 28 | if (!target.exists()) { 29 | BufferedInputStream in = new BufferedInputStream(getResource(name)); 30 | FileOutputStream out = new FileOutputStream(target); 31 | byte[] buff = new byte[1024]; 32 | int len; 33 | while ((len = in.read(buff)) != -1) { 34 | out.write(buff, 0, len); 35 | } 36 | out.flush(); 37 | out.close(); 38 | in.close(); 39 | } 40 | return true; 41 | } 42 | 43 | public static void generateResources(File dataFolder) { 44 | ensureFolder(new File(dataFolder, "logs")); 45 | val menuFolder = new File(dataFolder, "menu"); 46 | ensureFolder(menuFolder); 47 | val menuExample = new File(menuFolder, "example.yml"); 48 | saveResouce("example.yml", menuExample); 49 | val ccFolder = new File(dataFolder, "chestcommands"); 50 | ensureFolder(ccFolder); 51 | val ccExample = new File(ccFolder, "exampleCC.yml"); 52 | saveResouce("exampleCC.yml", ccExample); 53 | } 54 | 55 | public static boolean ensureFolder(File folder) { 56 | if (!folder.exists()) { 57 | folder.mkdirs(); 58 | return false; 59 | } 60 | return true; 61 | } 62 | 63 | } 64 | -------------------------------------------------------------------------------- /common/src/main/java/com/blzeecraft/virtualmenu/core/action/Action.java: -------------------------------------------------------------------------------- 1 | package com.blzeecraft.virtualmenu.core.action; 2 | 3 | import java.util.EnumSet; 4 | import java.util.Optional; 5 | import java.util.Set; 6 | 7 | import com.blzeecraft.virtualmenu.core.Command; 8 | import com.blzeecraft.virtualmenu.core.action.event.IconActionEvent; 9 | import com.blzeecraft.virtualmenu.core.action.event.MenuActionEvent; 10 | import com.blzeecraft.virtualmenu.core.action.event.MenuEvent; 11 | import com.blzeecraft.virtualmenu.core.conf.StringSerializable; 12 | import com.blzeecraft.virtualmenu.core.conf.line.ResolvedLineConfig; 13 | import com.blzeecraft.virtualmenu.core.logger.LogNode; 14 | import com.blzeecraft.virtualmenu.core.logger.PluginLogger; 15 | import com.blzeecraft.virtualmenu.core.menu.ClickType; 16 | import com.blzeecraft.virtualmenu.core.user.IUser; 17 | 18 | /** 19 | * 这个类代表一个动作.这个类是不可变的. 20 | *

21 | * 动作可以是一个命令,也可以是诸如发送actionbar这样的其他操作. 22 | *

23 | * 动作是由 {@link MenuActionEvent} 或 {@link IconActionEvent} 触发的, 24 | *

25 | * 两者分别对应菜单配置中events和icon下的action. 26 | * 27 | * @author colors_wind 28 | * @date 2020-02-10 29 | */ 30 | public abstract class Action extends Command implements IAction, StringSerializable { 31 | 32 | protected final Set types; 33 | 34 | public Action(LogNode node, ResolvedLineConfig rlc) { 35 | super(node, rlc); 36 | this.types = rlc.getAsOptEnumSet("click", ClickType.class).orElse(EnumSet.allOf(ClickType.class)); 37 | } 38 | 39 | public Action(LogNode node) { 40 | super(node); 41 | this.types = EnumSet.allOf(ClickType.class); 42 | } 43 | 44 | 45 | 46 | @Override 47 | public final Optional apply(MenuEvent event) { 48 | accept(event); 49 | return Optional.empty(); 50 | } 51 | 52 | @Override 53 | public final void accept(MenuEvent event) { 54 | if (types.contains(event.getClickType())) { 55 | try { 56 | execute(event.getUser()); 57 | } catch (Exception e) { 58 | PluginLogger.warning(node, "处理菜单事件时发生严重异常."); 59 | e.printStackTrace(); 60 | } 61 | } 62 | } 63 | 64 | @Override 65 | public LogNode getLogNode() { 66 | return node; 67 | } 68 | 69 | public abstract void execute(IUser user); 70 | 71 | } 72 | -------------------------------------------------------------------------------- /common/src/main/java/com/blzeecraft/virtualmenu/core/action/ActionUtils.java: -------------------------------------------------------------------------------- 1 | package com.blzeecraft.virtualmenu.core.action; 2 | 3 | import java.util.List; 4 | import java.util.stream.Collectors; 5 | import java.util.stream.IntStream; 6 | 7 | import com.blzeecraft.virtualmenu.core.action.event.IconActionEvent; 8 | import com.blzeecraft.virtualmenu.core.condition.ICondition; 9 | import com.blzeecraft.virtualmenu.core.conf.InvalidConfigException; 10 | import com.blzeecraft.virtualmenu.core.conf.line.LineConfigParser; 11 | import com.blzeecraft.virtualmenu.core.logger.LogNode; 12 | import com.blzeecraft.virtualmenu.core.logger.PluginLogger; 13 | 14 | import lombok.val; 15 | 16 | /** 17 | * 动作的工具类 18 | * 19 | * @author colors_wind 20 | * @date 2020-02-10 21 | */ 22 | public class ActionUtils { 23 | 24 | /** 25 | * 空的动作, 对任何 {@link IconActionEvent} 都不会执行任何操作 26 | */ 27 | public static IAction EMPTY_ACTION = e -> { 28 | }; 29 | 30 | /** 31 | * 解析动作, 该方法一定会返回一个可用的结果 32 | * 33 | * @param node 条件所属的日志节点 34 | * @param line 待解析的字符串 35 | * @return 解析结果 36 | */ 37 | public static IAction parse(LogNode node, String line) { 38 | try { 39 | return LineConfigParser.parseFull(node, line, Action.class); 40 | } catch (InvalidConfigException e) { 41 | PluginLogger.warning(node, line); 42 | } 43 | PluginLogger.severe(node, "解析动作时发送严重错误, 已跳过该行."); 44 | return EMPTY_ACTION; 45 | } 46 | 47 | /** 48 | * 解析动作, 该方法一定会返回一个可用的结果 49 | * 50 | * @param node 条件所属的日志节点 51 | * @param line 待解析的字符串列表 52 | * @return 解析结果 53 | */ 54 | public static IAction parse(LogNode node, List lines) { 55 | List actions = IntStream.range(0, lines.size()).mapToObj(i -> { 56 | val subNode = node.sub("L" + (i + 1)); 57 | val action = parse(subNode, lines.get(i)); 58 | return action; 59 | }).filter(action -> action != EMPTY_ACTION).map(Action.class::cast).collect(Collectors.toList()); 60 | return actions.size() == 0 ? EMPTY_ACTION : actions.size() == 1 ? actions.get(0) : new MultiAction(actions); 61 | } 62 | 63 | public static IAction wrap(IAction action, ICondition condition) { 64 | return event -> { 65 | if (condition.test(event)) 66 | action.accept(event); 67 | }; 68 | } 69 | 70 | } 71 | -------------------------------------------------------------------------------- /common/src/main/java/com/blzeecraft/virtualmenu/core/action/IAction.java: -------------------------------------------------------------------------------- 1 | package com.blzeecraft.virtualmenu.core.action; 2 | 3 | import java.util.function.Consumer; 4 | 5 | import com.blzeecraft.virtualmenu.core.action.event.MenuEvent; 6 | 7 | /** 8 | * 代表动作 9 | * @author colors_wind 10 | * @date 2020-02-11 11 | */ 12 | public interface IAction extends Consumer { 13 | 14 | } 15 | -------------------------------------------------------------------------------- /common/src/main/java/com/blzeecraft/virtualmenu/core/action/IScope.java: -------------------------------------------------------------------------------- 1 | package com.blzeecraft.virtualmenu.core.action; 2 | 3 | import com.blzeecraft.virtualmenu.core.menu.ClickType; 4 | 5 | public interface IScope { 6 | 7 | default ClickType[] scope() { 8 | return ClickType.values(); 9 | } 10 | 11 | } 12 | -------------------------------------------------------------------------------- /common/src/main/java/com/blzeecraft/virtualmenu/core/action/MultiAction.java: -------------------------------------------------------------------------------- 1 | package com.blzeecraft.virtualmenu.core.action; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | import com.blzeecraft.virtualmenu.core.Command; 7 | import com.blzeecraft.virtualmenu.core.action.event.MenuEvent; 8 | import com.blzeecraft.virtualmenu.core.conf.StringSerializable; 9 | 10 | import lombok.val; 11 | 12 | /** 13 | * 用于包装多个动作, 这个类是不可变的. 14 | * 15 | * @author colors_wind 16 | * @date 2020-02-07 17 | */ 18 | public class MultiAction implements IAction, StringSerializable { 19 | 20 | protected final List actions; 21 | 22 | public MultiAction(List actions) { 23 | this.actions = new ArrayList<>(actions); 24 | } 25 | 26 | @Override 27 | public void accept(MenuEvent e) { 28 | for(val action : actions) { 29 | action.accept(e); 30 | } 31 | } 32 | 33 | @Override 34 | public String[] seriablizeAll() { 35 | return actions.stream().map(Command::serialize).toArray(String[]::new); 36 | } 37 | 38 | @Override 39 | public String serialize() { 40 | throw new UnsupportedOperationException(); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /common/src/main/java/com/blzeecraft/virtualmenu/core/action/event/IconActionEvent.java: -------------------------------------------------------------------------------- 1 | package com.blzeecraft.virtualmenu.core.action.event; 2 | 3 | import com.blzeecraft.virtualmenu.core.item.AbstractItem; 4 | import com.blzeecraft.virtualmenu.core.menu.ClickType; 5 | import com.blzeecraft.virtualmenu.core.user.UserSession; 6 | 7 | import lombok.Getter; 8 | import lombok.ToString; 9 | 10 | 11 | /** 12 | * 代表一个玩家点击菜单中的物品的事件 13 | * @author colors_wind 14 | * 15 | */ 16 | @Getter 17 | @ToString(callSuper=true) 18 | public class IconActionEvent extends MenuEvent { 19 | 20 | protected final ClickType type; 21 | protected final int rawSlot; 22 | protected final int slot; 23 | protected final AbstractItem current; 24 | 25 | 26 | public IconActionEvent(UserSession session, ClickType type, int rawSlot, int slot, 27 | AbstractItem current) { 28 | super(session); 29 | this.type = type; 30 | this.rawSlot = rawSlot; 31 | this.slot = slot; 32 | this.current = current; 33 | } 34 | 35 | @Override 36 | public ClickType getClickType() { 37 | return type; 38 | } 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | } 47 | -------------------------------------------------------------------------------- /common/src/main/java/com/blzeecraft/virtualmenu/core/action/event/MenuActionEvent.java: -------------------------------------------------------------------------------- 1 | package com.blzeecraft.virtualmenu.core.action.event; 2 | 3 | import com.blzeecraft.virtualmenu.core.menu.EventType; 4 | import com.blzeecraft.virtualmenu.core.user.UserSession; 5 | 6 | import lombok.Getter; 7 | import lombok.ToString; 8 | 9 | @Getter 10 | @ToString(callSuper=true) 11 | public class MenuActionEvent extends MenuEvent { 12 | protected final EventType eventType; 13 | 14 | public MenuActionEvent(UserSession session, EventType eventType) { 15 | super(session); 16 | this.eventType = eventType; 17 | } 18 | 19 | } 20 | -------------------------------------------------------------------------------- /common/src/main/java/com/blzeecraft/virtualmenu/core/action/event/MenuEvent.java: -------------------------------------------------------------------------------- 1 | package com.blzeecraft.virtualmenu.core.action.event; 2 | 3 | import com.blzeecraft.virtualmenu.core.menu.ClickType; 4 | import com.blzeecraft.virtualmenu.core.menu.IPacketMenu; 5 | import com.blzeecraft.virtualmenu.core.user.IUser; 6 | import com.blzeecraft.virtualmenu.core.user.UserSession; 7 | 8 | import lombok.AllArgsConstructor; 9 | import lombok.Getter; 10 | import lombok.ToString; 11 | 12 | /** 13 | * @author colors_wind 14 | * @date 2020-02-10 15 | */ 16 | @AllArgsConstructor 17 | @ToString 18 | @Getter 19 | public class MenuEvent { 20 | 21 | protected final UserSession session; 22 | 23 | 24 | public ClickType getClickType() { 25 | return ClickType.UNKNOWN; 26 | } 27 | 28 | public IUser getUser() { 29 | return session.getUser(); 30 | } 31 | 32 | public IPacketMenu getMenu() { 33 | return session.getMenu(); 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /common/src/main/java/com/blzeecraft/virtualmenu/core/action/event/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 包含触发 Action 执行的 Event 类. 3 | * @author colors_wind 4 | * @date 2020-02-14 5 | */ 6 | package com.blzeecraft.virtualmenu.core.action.event; -------------------------------------------------------------------------------- /common/src/main/java/com/blzeecraft/virtualmenu/core/action/extension/ActionActionbar.java: -------------------------------------------------------------------------------- 1 | package com.blzeecraft.virtualmenu.core.action.extension; 2 | 3 | import com.blzeecraft.virtualmenu.core.action.Action; 4 | import com.blzeecraft.virtualmenu.core.conf.line.ResolvedLineConfig; 5 | import com.blzeecraft.virtualmenu.core.logger.LogNode; 6 | import com.blzeecraft.virtualmenu.core.user.IUser; 7 | 8 | import lombok.ToString; 9 | 10 | @ToString 11 | public class ActionActionbar extends Action { 12 | protected final String message; 13 | 14 | public ActionActionbar(LogNode node, ResolvedLineConfig rlc) { 15 | super(node, rlc); 16 | this.message = rlc.getAsString("s"); 17 | } 18 | 19 | @Override 20 | public void execute(IUser user) { 21 | user.sendActionbar(message); 22 | 23 | } 24 | 25 | @Override 26 | public String getKey() { 27 | return "actionbar"; 28 | } 29 | 30 | } 31 | -------------------------------------------------------------------------------- /common/src/main/java/com/blzeecraft/virtualmenu/core/action/extension/ActionBungeeCord.java: -------------------------------------------------------------------------------- 1 | package com.blzeecraft.virtualmenu.core.action.extension; 2 | 3 | import java.io.ByteArrayOutputStream; 4 | import java.io.DataOutputStream; 5 | import java.io.IOException; 6 | 7 | import com.blzeecraft.virtualmenu.core.VirtualMenu; 8 | import com.blzeecraft.virtualmenu.core.action.Action; 9 | import com.blzeecraft.virtualmenu.core.conf.line.ResolvedLineConfig; 10 | import com.blzeecraft.virtualmenu.core.logger.LogNode; 11 | import com.blzeecraft.virtualmenu.core.user.IUser; 12 | 13 | import lombok.ToString; 14 | 15 | @ToString 16 | public class ActionBungeeCord extends Action { 17 | public static final String KEY = "server"; 18 | protected final String toServer; 19 | 20 | 21 | public ActionBungeeCord(LogNode node, ResolvedLineConfig rlc) { 22 | super(node, rlc); 23 | this.toServer = rlc.getAsString("server"); 24 | } 25 | 26 | @Override 27 | public void execute(IUser user) { 28 | VirtualMenu.getScheduler().runTaskAsync(() -> { 29 | ByteArrayOutputStream byteArray = new ByteArrayOutputStream(); 30 | DataOutputStream out = new DataOutputStream(byteArray); 31 | try { 32 | out.writeUTF("Connect"); 33 | out.writeUTF(toServer); 34 | } catch (IOException e) { 35 | e.printStackTrace(); 36 | } 37 | user.sendPluginMessage("BungeeCord", byteArray.toByteArray()); 38 | }); 39 | } 40 | 41 | @Override 42 | public String getKey() { 43 | return KEY; 44 | } 45 | 46 | public static String remap(String value) { 47 | return KEY + new ResolvedLineConfig("server", value).toString(); 48 | } 49 | 50 | } 51 | -------------------------------------------------------------------------------- /common/src/main/java/com/blzeecraft/virtualmenu/core/action/extension/ActionCloseMenu.java: -------------------------------------------------------------------------------- 1 | package com.blzeecraft.virtualmenu.core.action.extension; 2 | 3 | 4 | import com.blzeecraft.virtualmenu.core.action.Action; 5 | import com.blzeecraft.virtualmenu.core.conf.line.ResolvedLineConfig; 6 | import com.blzeecraft.virtualmenu.core.logger.LogNode; 7 | import com.blzeecraft.virtualmenu.core.user.IUser; 8 | import com.blzeecraft.virtualmenu.core.user.UserManager; 9 | 10 | import lombok.ToString; 11 | 12 | @ToString 13 | public class ActionCloseMenu extends Action { 14 | 15 | public ActionCloseMenu(LogNode node, ResolvedLineConfig rlc) { 16 | super(node, rlc); 17 | } 18 | 19 | @Override 20 | public void execute(IUser user) { 21 | UserManager.closeAllMenu(); 22 | } 23 | 24 | @Override 25 | public String getKey() { 26 | return "close"; 27 | } 28 | 29 | 30 | 31 | } 32 | -------------------------------------------------------------------------------- /common/src/main/java/com/blzeecraft/virtualmenu/core/action/extension/ActionCommand.java: -------------------------------------------------------------------------------- 1 | package com.blzeecraft.virtualmenu.core.action.extension; 2 | 3 | 4 | import com.blzeecraft.virtualmenu.core.action.Action; 5 | import com.blzeecraft.virtualmenu.core.conf.line.ResolvedLineConfig; 6 | import com.blzeecraft.virtualmenu.core.logger.LogNode; 7 | import com.blzeecraft.virtualmenu.core.user.IUser; 8 | 9 | import lombok.ToString; 10 | 11 | @ToString 12 | public class ActionCommand extends Action { 13 | public static final String KEY = "command"; 14 | protected final String command; 15 | 16 | public ActionCommand(LogNode node, ResolvedLineConfig rlc) { 17 | super(node, rlc); 18 | this.command = rlc.getAsString("command"); 19 | } 20 | 21 | @Override 22 | public void execute(IUser user) { 23 | user.performCommand(command.replace("", user.getName())); 24 | } 25 | 26 | @Override 27 | public String getKey() { 28 | return KEY; 29 | } 30 | 31 | public static String remap(String s) { 32 | return KEY + new ResolvedLineConfig("command", s).toString(); 33 | } 34 | 35 | 36 | 37 | } 38 | -------------------------------------------------------------------------------- /common/src/main/java/com/blzeecraft/virtualmenu/core/action/extension/ActionConsoleCommand.java: -------------------------------------------------------------------------------- 1 | package com.blzeecraft.virtualmenu.core.action.extension; 2 | 3 | import com.blzeecraft.virtualmenu.core.VirtualMenu; 4 | import com.blzeecraft.virtualmenu.core.action.Action; 5 | import com.blzeecraft.virtualmenu.core.conf.line.ResolvedLineConfig; 6 | import com.blzeecraft.virtualmenu.core.logger.LogNode; 7 | import com.blzeecraft.virtualmenu.core.user.IUser; 8 | 9 | import lombok.ToString; 10 | 11 | @ToString 12 | public class ActionConsoleCommand extends Action { 13 | public static final String KEY = "console"; 14 | protected final String command; 15 | 16 | public ActionConsoleCommand(LogNode node, ResolvedLineConfig rlc) { 17 | super(node, rlc); 18 | this.command = rlc.getAsString("command"); 19 | } 20 | 21 | @Override 22 | public void execute(IUser user) { 23 | VirtualMenu.getConsole().performCommand(command.replace("", user.getName())); 24 | } 25 | 26 | @Override 27 | public String getKey() { 28 | return KEY; 29 | } 30 | 31 | public static String remap(String value) { 32 | return KEY + new ResolvedLineConfig("command", value).toString(); 33 | } 34 | 35 | 36 | 37 | 38 | } 39 | -------------------------------------------------------------------------------- /common/src/main/java/com/blzeecraft/virtualmenu/core/action/extension/ActionOpCommand.java: -------------------------------------------------------------------------------- 1 | package com.blzeecraft.virtualmenu.core.action.extension; 2 | 3 | import com.blzeecraft.virtualmenu.core.action.Action; 4 | import com.blzeecraft.virtualmenu.core.conf.line.ResolvedLineConfig; 5 | import com.blzeecraft.virtualmenu.core.logger.LogNode; 6 | import com.blzeecraft.virtualmenu.core.user.IUser; 7 | 8 | import lombok.ToString; 9 | 10 | @ToString 11 | public class ActionOpCommand extends Action { 12 | public static final String KEY = "op"; 13 | protected final String command; 14 | 15 | public ActionOpCommand(LogNode node, ResolvedLineConfig rlc) { 16 | super(node, rlc); 17 | this.command = rlc.getAsString("command"); 18 | } 19 | 20 | @Override 21 | public void execute(IUser user) { 22 | user.performCommand(command.replace("", user.getName())); 23 | } 24 | 25 | @Override 26 | public String getKey() { 27 | return "op"; 28 | } 29 | 30 | public static String remap(String value) { 31 | return KEY + new ResolvedLineConfig("command", value).toString(); 32 | } 33 | 34 | 35 | 36 | 37 | 38 | } 39 | -------------------------------------------------------------------------------- /common/src/main/java/com/blzeecraft/virtualmenu/core/action/extension/ActionOpenMenu.java: -------------------------------------------------------------------------------- 1 | package com.blzeecraft.virtualmenu.core.action.extension; 2 | 3 | import com.blzeecraft.virtualmenu.core.action.Action; 4 | import com.blzeecraft.virtualmenu.core.conf.line.ResolvedLineConfig; 5 | import com.blzeecraft.virtualmenu.core.conf.menu.MenuManager; 6 | import com.blzeecraft.virtualmenu.core.logger.LogNode; 7 | import com.blzeecraft.virtualmenu.core.user.IUser; 8 | 9 | import lombok.val; 10 | 11 | public class ActionOpenMenu extends Action { 12 | public static final String KEY = "open"; 13 | protected final String menu; 14 | 15 | public ActionOpenMenu(LogNode node, ResolvedLineConfig rlc) { 16 | super(node, rlc); 17 | this.menu = rlc.getAsString("menu"); 18 | } 19 | 20 | @Override 21 | public void execute(IUser user) { 22 | val opt = MenuManager.getMenu(menu); 23 | if (opt.isPresent()) { 24 | user.openPacketMenu(opt.get()); 25 | } else { 26 | user.sendMessage("找不到菜单: " + menu); 27 | } 28 | } 29 | 30 | @Override 31 | public String getKey() { 32 | return KEY; 33 | } 34 | 35 | public static String remap(String value) { 36 | return KEY + new ResolvedLineConfig("menu", value).toString(); 37 | } 38 | 39 | 40 | 41 | 42 | 43 | 44 | } 45 | -------------------------------------------------------------------------------- /common/src/main/java/com/blzeecraft/virtualmenu/core/action/extension/ActionSound.java: -------------------------------------------------------------------------------- 1 | package com.blzeecraft.virtualmenu.core.action.extension; 2 | 3 | import java.util.LinkedHashMap; 4 | import java.util.StringTokenizer; 5 | 6 | import com.blzeecraft.virtualmenu.core.action.Action; 7 | import com.blzeecraft.virtualmenu.core.conf.line.ResolvedLineConfig; 8 | import com.blzeecraft.virtualmenu.core.logger.LogNode; 9 | import com.blzeecraft.virtualmenu.core.user.IUser; 10 | 11 | import lombok.ToString; 12 | import lombok.val; 13 | 14 | @ToString 15 | public class ActionSound extends Action { 16 | public static final String KEY = "sound"; 17 | protected final String sound; 18 | protected final float volume; 19 | protected final float pitch; 20 | 21 | public ActionSound(LogNode node, ResolvedLineConfig rlc) { 22 | super(node, rlc); 23 | this.sound = rlc.getAsString("sound"); 24 | this.volume = (float) rlc.getAsOptDouble("volume").orElse(1D); 25 | this.pitch = (float) rlc.getAsOptDouble("pitch").orElse(0D); 26 | } 27 | 28 | @Override 29 | public void execute(IUser user) { 30 | user.playSound(sound, volume, pitch); 31 | 32 | } 33 | 34 | @Override 35 | public String getKey() { 36 | return KEY; 37 | } 38 | 39 | public static String remap(String value) { 40 | val map = new LinkedHashMap(); 41 | val str = new StringTokenizer(value, ","); 42 | map.put("sound", str.nextToken()); 43 | if (str.hasMoreElements()) { 44 | map.put("volume", str.nextToken()); 45 | } 46 | if (str.hasMoreElements()) { 47 | map.put("pitch", str.nextToken()); 48 | } 49 | return KEY + new ResolvedLineConfig(map).toString(); 50 | } 51 | 52 | } 53 | -------------------------------------------------------------------------------- /common/src/main/java/com/blzeecraft/virtualmenu/core/action/extension/ActionTell.java: -------------------------------------------------------------------------------- 1 | package com.blzeecraft.virtualmenu.core.action.extension; 2 | 3 | import com.blzeecraft.virtualmenu.core.action.Action; 4 | import com.blzeecraft.virtualmenu.core.conf.line.ResolvedLineConfig; 5 | import com.blzeecraft.virtualmenu.core.logger.LogNode; 6 | import com.blzeecraft.virtualmenu.core.user.IUser; 7 | 8 | import lombok.ToString; 9 | 10 | @ToString 11 | public class ActionTell extends Action { 12 | public static final String KEY = "tell"; 13 | protected final String message; 14 | 15 | public ActionTell(LogNode node, ResolvedLineConfig rlc) { 16 | super(node, rlc); 17 | this.message = rlc.getAsString("s"); 18 | } 19 | 20 | @Override 21 | public void execute(IUser user) { 22 | user.sendMessage(message.replace("", user.getName())); 23 | } 24 | 25 | @Override 26 | public String getKey() { 27 | return KEY; 28 | } 29 | 30 | public static String remap(String value) { 31 | return KEY + new ResolvedLineConfig("tell", value).toString(); 32 | } 33 | 34 | 35 | 36 | } 37 | -------------------------------------------------------------------------------- /common/src/main/java/com/blzeecraft/virtualmenu/core/action/extension/ActionTitle.java: -------------------------------------------------------------------------------- 1 | package com.blzeecraft.virtualmenu.core.action.extension; 2 | 3 | import com.blzeecraft.virtualmenu.core.action.Action; 4 | import com.blzeecraft.virtualmenu.core.conf.line.ResolvedLineConfig; 5 | import com.blzeecraft.virtualmenu.core.logger.LogNode; 6 | import com.blzeecraft.virtualmenu.core.user.IUser; 7 | 8 | import lombok.ToString; 9 | 10 | @ToString 11 | public class ActionTitle extends Action { 12 | protected final String title; 13 | protected final String subtitle; 14 | protected final int fadeIn; 15 | protected final int stay; 16 | protected final int fadeOut; 17 | 18 | public ActionTitle(LogNode node, ResolvedLineConfig rlc) { 19 | super(node, rlc); 20 | this.title = rlc.getAsString("title"); 21 | this.subtitle = rlc.getAsOptString("subtitle").orElse(""); 22 | this.fadeIn = rlc.getAsOptInt("fadeIn").orElse(3); 23 | this.stay = rlc.getAsOptInt("stay").orElse(7); 24 | this.fadeOut = rlc.getAsOptInt("fadeOut").orElse(3); 25 | } 26 | 27 | @Override 28 | public void execute(IUser user) { 29 | user.sendTitle(title, subtitle, fadeIn, stay, fadeOut); 30 | } 31 | 32 | @Override 33 | public String getKey() { 34 | return "title"; 35 | } 36 | 37 | 38 | 39 | 40 | } 41 | -------------------------------------------------------------------------------- /common/src/main/java/com/blzeecraft/virtualmenu/core/action/extension/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 包含一些平台通用的动作实现. 这个包里的类需要在 {@link LineConfigParser} 注册. 3 | * @author colors_wind 4 | * @date 2020/1/24 5 | */ 6 | package com.blzeecraft.virtualmenu.core.action.extension; 7 | 8 | import com.blzeecraft.virtualmenu.core.conf.line.LineConfigParser; -------------------------------------------------------------------------------- /common/src/main/java/com/blzeecraft/virtualmenu/core/action/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 玩家点击菜单后执行动作相关类 3 | */ 4 | package com.blzeecraft.virtualmenu.core.action; -------------------------------------------------------------------------------- /common/src/main/java/com/blzeecraft/virtualmenu/core/command/Callstack.java: -------------------------------------------------------------------------------- 1 | package com.blzeecraft.virtualmenu.core.command; 2 | 3 | import com.blzeecraft.virtualmenu.core.user.IUser; 4 | 5 | import lombok.AllArgsConstructor; 6 | import lombok.Getter; 7 | import lombok.ToString; 8 | 9 | @AllArgsConstructor 10 | @ToString 11 | @Getter 12 | public final class Callstack { 13 | 14 | private final IUser sender; 15 | private final String[] args; 16 | 17 | 18 | } 19 | -------------------------------------------------------------------------------- /common/src/main/java/com/blzeecraft/virtualmenu/core/command/IllegalCommandArgumentException.java: -------------------------------------------------------------------------------- 1 | package com.blzeecraft.virtualmenu.core.command; 2 | 3 | /** 4 | * 表示解析命令参数时出现异常. 5 | * @author colors_wind 6 | * @date 2020-02-15 7 | */ 8 | public class IllegalCommandArgumentException extends RuntimeException { 9 | 10 | /** 11 | * 12 | */ 13 | private static final long serialVersionUID = 1265652245261882178L; 14 | 15 | public IllegalCommandArgumentException(String message, Throwable cause) { 16 | super(message, cause); 17 | } 18 | 19 | public IllegalCommandArgumentException(String message) { 20 | super(message); 21 | } 22 | 23 | public String format(int index, String argument) { 24 | return this.getMessage().replace("%index%", String.valueOf(index)).replace("%arg%", argument); 25 | } 26 | 27 | } 28 | -------------------------------------------------------------------------------- /common/src/main/java/com/blzeecraft/virtualmenu/core/command/PlayerOnly.java: -------------------------------------------------------------------------------- 1 | package com.blzeecraft.virtualmenu.core.command; 2 | 3 | import static java.lang.annotation.ElementType.METHOD; 4 | import static java.lang.annotation.RetentionPolicy.RUNTIME; 5 | 6 | import java.lang.annotation.Retention; 7 | import java.lang.annotation.Target; 8 | 9 | /** 10 | * 用于标记子命令只能由玩家发出. 11 | * @author colors_wind 12 | * @date 2020-02-14 13 | */ 14 | @Retention(RUNTIME) 15 | @Target(METHOD) 16 | public @interface PlayerOnly {} 17 | -------------------------------------------------------------------------------- /common/src/main/java/com/blzeecraft/virtualmenu/core/command/RequirePermission.java: -------------------------------------------------------------------------------- 1 | package com.blzeecraft.virtualmenu.core.command; 2 | 3 | import static java.lang.annotation.ElementType.METHOD; 4 | import static java.lang.annotation.RetentionPolicy.RUNTIME; 5 | 6 | import java.lang.annotation.Retention; 7 | import java.lang.annotation.Target; 8 | 9 | @Retention(RUNTIME) 10 | @Target(METHOD) 11 | public @interface RequirePermission { 12 | 13 | String value() default ""; 14 | 15 | } 16 | -------------------------------------------------------------------------------- /common/src/main/java/com/blzeecraft/virtualmenu/core/command/SubCommandBase.java: -------------------------------------------------------------------------------- 1 | package com.blzeecraft.virtualmenu.core.command; 2 | 3 | import com.blzeecraft.virtualmenu.core.menu.IPacketMenu; 4 | import com.blzeecraft.virtualmenu.core.user.IUser; 5 | 6 | import lombok.Getter; 7 | 8 | public abstract class SubCommandBase { 9 | public static final Class[] ACCEPT_ARGS = new Class[] { Integer.class, Long.class, Double.class, String.class, 10 | IUser.class, IPacketMenu.class, int.class, long.class, double.class }; 11 | 12 | @Getter 13 | protected String[] name; 14 | 15 | public SubCommandBase(String[] name) { 16 | this.name = name; 17 | } 18 | 19 | } 20 | -------------------------------------------------------------------------------- /common/src/main/java/com/blzeecraft/virtualmenu/core/command/Usage.java: -------------------------------------------------------------------------------- 1 | package com.blzeecraft.virtualmenu.core.command; 2 | 3 | import static java.lang.annotation.ElementType.METHOD; 4 | import static java.lang.annotation.RetentionPolicy.RUNTIME; 5 | 6 | import java.lang.annotation.Retention; 7 | import java.lang.annotation.Target; 8 | 9 | /** 10 | * 用于标记子命令使用帮助. 11 | * @author colors_wind 12 | * @date 2020-02-14 13 | */ 14 | @Retention(RUNTIME) 15 | @Target(METHOD) 16 | public @interface Usage { 17 | /** 18 | * 获取命令帮助. 19 | * @return 命令帮助, 若不手动指定则隐藏该命令帮助. 20 | */ 21 | String value() default ""; 22 | 23 | } 24 | -------------------------------------------------------------------------------- /common/src/main/java/com/blzeecraft/virtualmenu/core/command/extension/CommandList.java: -------------------------------------------------------------------------------- 1 | package com.blzeecraft.virtualmenu.core.command.extension; 2 | 3 | import com.blzeecraft.virtualmenu.core.command.Callstack; 4 | import com.blzeecraft.virtualmenu.core.command.SubCommandBase; 5 | import com.blzeecraft.virtualmenu.core.command.Usage; 6 | import com.blzeecraft.virtualmenu.core.conf.menu.MenuManager; 7 | import com.blzeecraft.virtualmenu.core.user.IUser; 8 | 9 | public class CommandList extends SubCommandBase { 10 | 11 | public CommandList() { 12 | super(new String[] { "list" }); 13 | } 14 | 15 | @Usage("§alist §c-§a 列出可用的菜单") 16 | public boolean listMenu(Callstack stack) { 17 | IUser sender = stack.getSender(); 18 | sender.sendMessageWithPrefix("§a可用的菜单列表: "); 19 | MenuManager.getMenusName() 20 | .forEach(name -> sender.sendMessage(new StringBuilder("§c- §e").append(name).toString())); 21 | return true; 22 | } 23 | 24 | } 25 | -------------------------------------------------------------------------------- /common/src/main/java/com/blzeecraft/virtualmenu/core/command/extension/CommandOpenMenu.java: -------------------------------------------------------------------------------- 1 | package com.blzeecraft.virtualmenu.core.command.extension; 2 | 3 | import com.blzeecraft.virtualmenu.core.command.Callstack; 4 | import com.blzeecraft.virtualmenu.core.command.PlayerOnly; 5 | import com.blzeecraft.virtualmenu.core.command.RequirePermission; 6 | import com.blzeecraft.virtualmenu.core.command.SubCommandBase; 7 | import com.blzeecraft.virtualmenu.core.command.Usage; 8 | import com.blzeecraft.virtualmenu.core.menu.IPacketMenu; 9 | import com.blzeecraft.virtualmenu.core.user.IUser; 10 | 11 | public class CommandOpenMenu extends SubCommandBase { 12 | 13 | public CommandOpenMenu() { 14 | super(new String[] {"open"}); 15 | } 16 | 17 | 18 | @PlayerOnly 19 | @RequirePermission("virtualmenu.open.self") 20 | @Usage("§aopen §c-§a [menu] 为打开菜单") 21 | public boolean openMenu(Callstack stack, IPacketMenu menu) { 22 | IUser sender = stack.getSender(); 23 | sender.openPacketMenu(menu); 24 | sender.sendMessageWithPrefix("§a成功为自己打开菜单 ", stack.getArgs()[1], "."); 25 | return true; 26 | } 27 | 28 | @RequirePermission("virtualmenu.open.others") 29 | @Usage 30 | public boolean openMenu(Callstack stack, IPacketMenu menu, IUser user) { 31 | IUser sender = stack.getSender(); 32 | sender.sendMessageWithPrefix("§a成功为 ", user.getName() ," 打开菜单 ", stack.getArgs()[1], "."); 33 | user.openPacketMenu(menu); 34 | return true; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /common/src/main/java/com/blzeecraft/virtualmenu/core/command/extension/CommandReload.java: -------------------------------------------------------------------------------- 1 | package com.blzeecraft.virtualmenu.core.command.extension; 2 | 3 | import com.blzeecraft.virtualmenu.core.command.Callstack; 4 | import com.blzeecraft.virtualmenu.core.command.RequirePermission; 5 | import com.blzeecraft.virtualmenu.core.command.SubCommandBase; 6 | import com.blzeecraft.virtualmenu.core.command.Usage; 7 | import com.blzeecraft.virtualmenu.core.conf.menu.MenuManager; 8 | import com.blzeecraft.virtualmenu.core.user.IUser; 9 | import com.blzeecraft.virtualmenu.core.user.UserManager; 10 | 11 | public class CommandReload extends SubCommandBase { 12 | 13 | public CommandReload() { 14 | super(new String[] { "reload" }); 15 | } 16 | 17 | @RequirePermission("virtualmenu.reload") 18 | @Usage("§areload §c-§a 重载配置文件和菜单") 19 | public void readPlugin(Callstack stack) { 20 | IUser user = stack.getSender(); 21 | UserManager.closeAllMenu(); 22 | MenuManager.reloadMenu(); 23 | user.sendMessageWithPrefix("§a成功重载配置文件和菜单."); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /common/src/main/java/com/blzeecraft/virtualmenu/core/command/extension/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 包含插件的子命令实现. 3 | * @author colors_wind 4 | * @date 2020-02-14 5 | */ 6 | package com.blzeecraft.virtualmenu.core.command.extension; -------------------------------------------------------------------------------- /common/src/main/java/com/blzeecraft/virtualmenu/core/command/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 包含插件命令相关类. 3 | * @author colors_wind 4 | * @date 2020-02-14 5 | */ 6 | package com.blzeecraft.virtualmenu.core.command; -------------------------------------------------------------------------------- /common/src/main/java/com/blzeecraft/virtualmenu/core/condition/Condition.java: -------------------------------------------------------------------------------- 1 | package com.blzeecraft.virtualmenu.core.condition; 2 | 3 | import java.util.EnumSet; 4 | import java.util.Optional; 5 | import java.util.Set; 6 | 7 | import com.blzeecraft.virtualmenu.core.Command; 8 | import com.blzeecraft.virtualmenu.core.action.event.MenuEvent; 9 | import com.blzeecraft.virtualmenu.core.conf.line.ResolvedLineConfig; 10 | import com.blzeecraft.virtualmenu.core.logger.LogNode; 11 | import com.blzeecraft.virtualmenu.core.logger.PluginLogger; 12 | import com.blzeecraft.virtualmenu.core.menu.ClickType; 13 | 14 | /** 15 | * 这个类代表一个条件.这个类是不可变的.

16 | * 条件是诸如玩家等级,拥有的权限,持有的金钱等.

17 | * 条件分为两种:view-condition和click-condition,都在icon下配置.

18 | * 检查条件时不推荐对玩家进行有副作用的操作(如检查玩家金钱时扣除金钱), 19 | * 若条件在click-condition中设置:条件可能不只一个,任何一个条件不满足都不会继续执行, 20 | * 若条件在view-condition中设置:插件不能保证view-condition中条件被检查的次数. 21 | * 22 | * @see ICondition 23 | * @author colors_wind 24 | * @date 2020-02-10 25 | */ 26 | public abstract class Condition extends Command { 27 | 28 | protected final String message; 29 | protected final Set types; 30 | 31 | public Condition(LogNode node, ResolvedLineConfig rlc) { 32 | super(node, rlc); 33 | this.message = rlc.getAsOptString("msg").orElse(""); 34 | this.types = rlc.getAsOptEnumSet("click", ClickType.class).orElse(EnumSet.allOf(ClickType.class)); 35 | } 36 | 37 | public Condition(LogNode node) { 38 | super(node); 39 | this.message = ""; 40 | this.types = EnumSet.allOf(ClickType.class); 41 | } 42 | 43 | @Override 44 | public LogNode getLogNode() { 45 | return node; 46 | } 47 | 48 | @Override 49 | public final Optional apply(MenuEvent event) { 50 | if (types.contains(event.getClickType())) { 51 | return Optional.of(message); 52 | } 53 | try { 54 | return check(event); 55 | } catch (Exception ex) { 56 | ex.printStackTrace(); 57 | PluginLogger.warning(node, "检查条件时发生严重错误, 该条件检查不通过."); 58 | } 59 | return Optional.of("发送严重错误, 请联系管理员."); 60 | } 61 | 62 | public abstract Optional check(MenuEvent event); 63 | 64 | @Override 65 | public boolean test(MenuEvent event) { 66 | return !this.apply(event).isPresent(); 67 | } 68 | 69 | 70 | 71 | 72 | 73 | 74 | } 75 | -------------------------------------------------------------------------------- /common/src/main/java/com/blzeecraft/virtualmenu/core/condition/ConditionUtils.java: -------------------------------------------------------------------------------- 1 | package com.blzeecraft.virtualmenu.core.condition; 2 | 3 | import java.util.List; 4 | import java.util.Optional; 5 | import java.util.stream.Collectors; 6 | import java.util.stream.IntStream; 7 | 8 | import com.blzeecraft.virtualmenu.core.conf.InvalidConfigException; 9 | import com.blzeecraft.virtualmenu.core.conf.line.LineConfigParser; 10 | import com.blzeecraft.virtualmenu.core.logger.LogNode; 11 | import com.blzeecraft.virtualmenu.core.logger.PluginLogger; 12 | 13 | import lombok.val; 14 | 15 | /** 16 | * 条件的工具类 17 | * @author colors_wind 18 | * 19 | */ 20 | public class ConditionUtils { 21 | 22 | /** 23 | * 空的条件, 对任何 {@link IconActionEvent} 都返回 {@link Optional#empty()} 24 | */ 25 | public static final ICondition EMPTY_CONDITION = e -> Optional.empty(); 26 | 27 | /** 28 | * 解析条件, 该方法一定会返回一个可用的结果 29 | * 30 | * @param node 条件所属的 LogNode 31 | * @param line 待解析的字符串 32 | * @return 解析结果 33 | */ 34 | public static ICondition parse(LogNode node, String line) { 35 | try { 36 | return LineConfigParser.parseFull(node, line, Condition.class); 37 | } catch (InvalidConfigException e) { 38 | PluginLogger.warning(node, line); 39 | } 40 | PluginLogger.severe(node, "解析条件时发送严重错误, 已跳过该行."); 41 | return EMPTY_CONDITION; 42 | } 43 | 44 | /** 45 | * 解析条件, 该方法一定会返回一个可用的结果. 46 | * 47 | * @param node 条件所属的日志节点 48 | * @param line 待解析的字符串列表 49 | * @return 解析结果, 如果没有任何结果, 返回 {@link #EMPTY_CONDITION} 50 | */ 51 | public static ICondition parse(LogNode node, List lines) { 52 | List condtions = IntStream.range(0, lines.size()).mapToObj(i -> { 53 | val subNode = node.sub("L" + (i + 1)); 54 | val condition = parse(subNode, lines.get(i)); 55 | return condition; 56 | }).filter(action -> action != EMPTY_CONDITION).map(Condition.class::cast).collect(Collectors.toList()); 57 | return condtions.size() == 0 ? EMPTY_CONDITION : condtions.size() == 1 ? condtions.get(0) : new MultiCondition(condtions); 58 | } 59 | 60 | } 61 | -------------------------------------------------------------------------------- /common/src/main/java/com/blzeecraft/virtualmenu/core/condition/ICondition.java: -------------------------------------------------------------------------------- 1 | package com.blzeecraft.virtualmenu.core.condition; 2 | 3 | import java.util.Optional; 4 | import java.util.function.Function; 5 | import java.util.function.Predicate; 6 | 7 | import com.blzeecraft.virtualmenu.core.action.IScope; 8 | import com.blzeecraft.virtualmenu.core.action.event.MenuEvent; 9 | 10 | /** 11 | * 代表条件 12 | * 13 | * @author colors_wind 14 | * @date 2020-02-11 15 | */ 16 | public interface ICondition 17 | extends Function>, Predicate, IScope { 18 | 19 | /** 20 | * 检查事件是否满足条件, 这个方法通常会在检查view-condition时被调用. 21 | *

22 | * 通常情况下, 这个方法不需要手动实现, 只需要实现 {@link #apply(MenuEvent)} 即可. 23 | * 24 | * @see #apply(MenuEvent) 25 | * @param event 待测事件 26 | * @return true 如果满足条件, 否则返回 false. 27 | */ 28 | @Override 29 | default boolean test(MenuEvent event) { 30 | return !this.apply(event).isPresent(); 31 | } 32 | 33 | /** 34 | * 检查事件是否满足条件, 这个方法通常会在检查click-condition时被调用. 35 | * 36 | * 37 | * @param event 待测事件 38 | * @return {@link Optional#empty()} 如果满足条件, 否则返回非空 {@link Optional}, 这种情况下可用 39 | * {@link Optional#get()} 获取不满足条件的原因. 40 | */ 41 | @Override 42 | Optional apply(MenuEvent event); 43 | 44 | 45 | } 46 | -------------------------------------------------------------------------------- /common/src/main/java/com/blzeecraft/virtualmenu/core/condition/MultiCondition.java: -------------------------------------------------------------------------------- 1 | package com.blzeecraft.virtualmenu.core.condition; 2 | 3 | import java.util.ArrayList; 4 | import java.util.Collections; 5 | import java.util.List; 6 | import java.util.Optional; 7 | 8 | import com.blzeecraft.virtualmenu.core.Command; 9 | import com.blzeecraft.virtualmenu.core.action.event.MenuEvent; 10 | import com.blzeecraft.virtualmenu.core.conf.StringSerializable; 11 | 12 | import lombok.val; 13 | 14 | /** 15 | * 用于包装多个条件, 这个类是不可变的. 16 | * 17 | * @author colors_wind 18 | * @date 2020-02-07 19 | */ 20 | public class MultiCondition implements ICondition, StringSerializable { 21 | 22 | protected final List conditions; 23 | 24 | /** 25 | * 包装多个条件, 条件的顺序会被保留. 26 | * @param conditions 多个条件 27 | */ 28 | public MultiCondition(List conditions) { 29 | this.conditions = new ArrayList<>(conditions); 30 | } 31 | 32 | /** 33 | * 按原顺序检查条件. 34 | * @see #MultiCondition(List) 35 | */ 36 | @Override 37 | public Optional apply(MenuEvent e) { 38 | for(val condition : conditions) { 39 | val opt = condition.apply(e); 40 | if (opt.isPresent()) { 41 | return opt; 42 | } 43 | } 44 | return Optional.empty(); 45 | } 46 | 47 | /** 48 | * 获取包装的多个条件. 49 | * @return 多个条件的视图, 且这个视图是不可变的. 50 | */ 51 | public List getConditions() { 52 | return Collections.unmodifiableList(conditions); 53 | } 54 | 55 | @Override 56 | public String[] seriablizeAll() { 57 | return conditions.stream().map(Command::serialize).toArray(String[]::new); 58 | } 59 | 60 | @Override 61 | public String serialize() { 62 | throw new UnsupportedOperationException(); 63 | } 64 | 65 | 66 | 67 | 68 | 69 | 70 | } 71 | -------------------------------------------------------------------------------- /common/src/main/java/com/blzeecraft/virtualmenu/core/condition/extension/ConditionEconomy.java: -------------------------------------------------------------------------------- 1 | package com.blzeecraft.virtualmenu.core.condition.extension; 2 | 3 | import java.util.Optional; 4 | 5 | import com.blzeecraft.virtualmenu.core.action.event.MenuEvent; 6 | import com.blzeecraft.virtualmenu.core.condition.Condition; 7 | import com.blzeecraft.virtualmenu.core.conf.line.ResolvedLineConfig; 8 | import com.blzeecraft.virtualmenu.core.logger.LogNode; 9 | 10 | import lombok.ToString; 11 | import lombok.val; 12 | 13 | /** 14 | * 关于玩家经济的条件 15 | * @author colors_wind 16 | * 17 | */ 18 | @ToString 19 | public class ConditionEconomy extends Condition { 20 | protected final double amount; 21 | protected final String currency; 22 | protected final boolean take; 23 | 24 | public ConditionEconomy(LogNode node, ResolvedLineConfig rlc) { 25 | super(node, rlc); 26 | this.amount = rlc.getAsInt("amount"); 27 | this.currency = rlc.getAsOptString("currency").orElse(""); 28 | this.take = rlc.getAsOptBoolean("take").orElse(Boolean.FALSE).booleanValue(); 29 | } 30 | 31 | @Override 32 | public Optional check(MenuEvent e) { 33 | val user = e.getUser(); 34 | if(take) { 35 | return user.withdraw(currency, amount) ? Optional.empty() : Optional.of(message); 36 | } 37 | val opt = user.getBanlance(currency); 38 | if (opt.isPresent() && opt.getAsDouble() > amount) { 39 | return Optional.empty(); 40 | } 41 | return Optional.of(message); 42 | } 43 | 44 | @Override 45 | public String getKey() { 46 | return "money"; 47 | } 48 | 49 | 50 | 51 | 52 | 53 | } 54 | -------------------------------------------------------------------------------- /common/src/main/java/com/blzeecraft/virtualmenu/core/condition/extension/ConditionLevel.java: -------------------------------------------------------------------------------- 1 | package com.blzeecraft.virtualmenu.core.condition.extension; 2 | 3 | import java.util.Optional; 4 | 5 | import com.blzeecraft.virtualmenu.core.action.event.MenuEvent; 6 | import com.blzeecraft.virtualmenu.core.condition.Condition; 7 | import com.blzeecraft.virtualmenu.core.conf.line.ResolvedLineConfig; 8 | import com.blzeecraft.virtualmenu.core.logger.LogNode; 9 | import lombok.ToString; 10 | import lombok.val; 11 | 12 | /** 13 | * 关于玩家等级的条件 14 | * @author colors_wind 15 | * 16 | */ 17 | @ToString 18 | public class ConditionLevel extends Condition { 19 | protected final int level; 20 | protected final boolean take; 21 | 22 | public ConditionLevel(LogNode node, ResolvedLineConfig rlc) { 23 | super(node, rlc); 24 | this.level = rlc.getAsInt("level"); 25 | this.take = rlc.getAsOptBoolean("take").orElse(Boolean.FALSE).booleanValue(); 26 | 27 | } 28 | 29 | @Override 30 | public Optional check(MenuEvent e) { 31 | val user = e.getUser(); 32 | int newLevel = user.getLevel() - level; 33 | if (newLevel < 0) { 34 | return Optional.of(message); 35 | } 36 | if (take) { 37 | user.setLevel(newLevel); 38 | } 39 | return Optional.empty(); 40 | } 41 | 42 | @Override 43 | public String getKey() { 44 | return "level"; 45 | } 46 | 47 | 48 | } 49 | -------------------------------------------------------------------------------- /common/src/main/java/com/blzeecraft/virtualmenu/core/condition/extension/ConditionPermission.java: -------------------------------------------------------------------------------- 1 | package com.blzeecraft.virtualmenu.core.condition.extension; 2 | 3 | import java.util.Optional; 4 | 5 | import com.blzeecraft.virtualmenu.core.action.event.MenuEvent; 6 | import com.blzeecraft.virtualmenu.core.condition.Condition; 7 | import com.blzeecraft.virtualmenu.core.conf.line.ResolvedLineConfig; 8 | import com.blzeecraft.virtualmenu.core.logger.LogNode; 9 | 10 | import lombok.ToString; 11 | 12 | /** 13 | * 关于玩家权限的条件 14 | * @author colors_wind 15 | * 16 | */ 17 | @ToString 18 | public class ConditionPermission extends Condition { 19 | 20 | protected final String permission; 21 | 22 | public ConditionPermission(LogNode node, ResolvedLineConfig rlc) { 23 | super(node, rlc); 24 | this.permission = rlc.getAsString("perm"); 25 | 26 | } 27 | 28 | @Override 29 | public Optional check(MenuEvent e) { 30 | return e.getUser().hasPermission(permission) ? Optional.empty() : Optional.of(message); 31 | } 32 | 33 | @Override 34 | public String getKey() { 35 | return "permission"; 36 | } 37 | 38 | 39 | } 40 | -------------------------------------------------------------------------------- /common/src/main/java/com/blzeecraft/virtualmenu/core/condition/extension/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 包含一些平台通用的条件实现. 这个包里的类需要在 {@link LineConfigParser} 注册. 3 | * @author colors_wind 4 | * @date 2020/1/24 5 | */ 6 | package com.blzeecraft.virtualmenu.core.condition.extension; 7 | 8 | import com.blzeecraft.virtualmenu.core.conf.line.LineConfigParser; -------------------------------------------------------------------------------- /common/src/main/java/com/blzeecraft/virtualmenu/core/condition/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 有关菜单条件的类 3 | */ 4 | package com.blzeecraft.virtualmenu.core.condition; -------------------------------------------------------------------------------- /common/src/main/java/com/blzeecraft/virtualmenu/core/conf/ConfSerializable.java: -------------------------------------------------------------------------------- 1 | package com.blzeecraft.virtualmenu.core.conf; 2 | 3 | import java.lang.reflect.Array; 4 | 5 | import com.blzeecraft.virtualmenu.core.conf.transition.SubConf; 6 | 7 | /** 8 | * 代表这个类是可序列化成 {@link SubConf} 的子类的. 9 | * @author colors_wind 10 | * 11 | * @param 12 | */ 13 | public interface ConfSerializable { 14 | 15 | T serialize(); 16 | 17 | default T[] seriablizeAll() { 18 | T obj = serialize(); 19 | @SuppressWarnings("unchecked") 20 | T[] array = (T[]) Array.newInstance(obj.getClass(), 1); 21 | array[0] = obj; 22 | return array; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /common/src/main/java/com/blzeecraft/virtualmenu/core/conf/InvalidConfigException.java: -------------------------------------------------------------------------------- 1 | package com.blzeecraft.virtualmenu.core.conf; 2 | 3 | /** 4 | * 表示尝试加载无效的配置时出现的异常. 例如一个配置文件不满足 YAML 的语法要求. 5 | * 6 | * @author colors_wind 7 | * 8 | */ 9 | public class InvalidConfigException extends RuntimeException { 10 | 11 | /** 12 | * 13 | */ 14 | private static final long serialVersionUID = 2348281412323397238L; 15 | 16 | public InvalidConfigException() { 17 | super(); 18 | } 19 | 20 | public InvalidConfigException(String message, Throwable cause, boolean enableSuppression, 21 | boolean writableStackTrace) { 22 | super(message, cause, enableSuppression, writableStackTrace); 23 | } 24 | 25 | public InvalidConfigException(String message, Throwable cause) { 26 | super(message, cause); 27 | } 28 | 29 | public InvalidConfigException(String message) { 30 | super(message); 31 | } 32 | 33 | public InvalidConfigException(Throwable cause) { 34 | super(cause); 35 | } 36 | 37 | } 38 | -------------------------------------------------------------------------------- /common/src/main/java/com/blzeecraft/virtualmenu/core/conf/ObjectConvertException.java: -------------------------------------------------------------------------------- 1 | package com.blzeecraft.virtualmenu.core.conf; 2 | 3 | import com.blzeecraft.virtualmenu.core.PluginExecption; 4 | 5 | /** 6 | * 表示不同类型元素转换时发生的异常. 如尝试将 "string" 转换成 Integer时. 7 | * 8 | * @author colors_wind 9 | * 10 | */ 11 | public class ObjectConvertException extends PluginExecption { 12 | 13 | /** 14 | * 15 | */ 16 | private static final long serialVersionUID = -7796906226004776337L; 17 | 18 | public ObjectConvertException() { 19 | super(); 20 | } 21 | 22 | public ObjectConvertException(String message, Throwable cause) { 23 | super(message, cause); 24 | } 25 | 26 | public ObjectConvertException(String message) { 27 | super(message); 28 | } 29 | 30 | public ObjectConvertException(Throwable cause) { 31 | super(cause); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /common/src/main/java/com/blzeecraft/virtualmenu/core/conf/OptionalMapper.java: -------------------------------------------------------------------------------- 1 | package com.blzeecraft.virtualmenu.core.conf; 2 | 3 | import java.util.Arrays; 4 | import java.util.HashSet; 5 | import java.util.OptionalDouble; 6 | import java.util.OptionalInt; 7 | import java.util.OptionalLong; 8 | import java.util.Set; 9 | import java.util.function.Function; 10 | 11 | import lombok.Getter; 12 | import lombok.ToString; 13 | 14 | /** 15 | * 用于给 Optional 拆包. 16 | * 17 | * @author colors_wind 18 | * 19 | */ 20 | 21 | @ToString 22 | @Getter 23 | public class OptionalMapper { 24 | 25 | public static final Set> SUPPORT_TYPE = new HashSet<>( 26 | Arrays.asList(String.class, Integer.class, Long.class, Double.class, OptionalInt.class, OptionalLong.class, OptionalDouble.class)); 27 | public static final Function MAPPER_INT = opt -> { 28 | if (opt.isPresent()) { 29 | return opt.getAsInt(); 30 | } 31 | return null; 32 | }; 33 | public static final Function MAPPER_LONG = opt -> { 34 | if (opt.isPresent()) { 35 | return opt.getAsLong(); 36 | } 37 | return null; 38 | }; 39 | public static final Function MAPPER_DOUBLE = opt -> { 40 | if (opt.isPresent()) { 41 | return opt.getAsDouble(); 42 | } 43 | return null; 44 | }; 45 | 46 | private final Object value; 47 | 48 | public OptionalMapper(Object value) { 49 | this.value = value; 50 | } 51 | 52 | public Object apply() { 53 | Class clazz = value.getClass(); 54 | if (clazz == OptionalInt.class) { 55 | return MAPPER_INT.apply((OptionalInt) value); 56 | } else if (clazz == OptionalLong.class) { 57 | return MAPPER_LONG.apply((OptionalLong) value); 58 | } else if (clazz == OptionalDouble.class) { 59 | return MAPPER_DOUBLE.apply((OptionalDouble) value); 60 | } 61 | return value; 62 | } 63 | 64 | } 65 | -------------------------------------------------------------------------------- /common/src/main/java/com/blzeecraft/virtualmenu/core/conf/StringSerializable.java: -------------------------------------------------------------------------------- 1 | package com.blzeecraft.virtualmenu.core.conf; 2 | 3 | /** 4 | * 代表这个类可以被序列化成 {@link String}. 5 | * @author colors_wind 6 | * 7 | */ 8 | public interface StringSerializable { 9 | 10 | String serialize(); 11 | 12 | default String[] seriablizeAll() { 13 | return new String[] {serialize()}; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /common/src/main/java/com/blzeecraft/virtualmenu/core/conf/convert/FuncDouble.java: -------------------------------------------------------------------------------- 1 | package com.blzeecraft.virtualmenu.core.conf.convert; 2 | 3 | import java.util.function.Function; 4 | 5 | import lombok.NonNull; 6 | 7 | public class FuncDouble implements Function { 8 | 9 | @Override 10 | @NonNull 11 | public Double apply(@NonNull Object obj) { 12 | return Double.valueOf(obj.toString()); 13 | } 14 | 15 | } 16 | -------------------------------------------------------------------------------- /common/src/main/java/com/blzeecraft/virtualmenu/core/conf/convert/FuncInteger.java: -------------------------------------------------------------------------------- 1 | package com.blzeecraft.virtualmenu.core.conf.convert; 2 | 3 | import java.util.function.Function; 4 | 5 | import lombok.NonNull; 6 | 7 | public class FuncInteger implements Function { 8 | 9 | @Override 10 | @NonNull 11 | public Integer apply(@NonNull Object obj) { 12 | return Integer.valueOf(obj.toString()); 13 | } 14 | 15 | } 16 | -------------------------------------------------------------------------------- /common/src/main/java/com/blzeecraft/virtualmenu/core/conf/convert/FuncList.java: -------------------------------------------------------------------------------- 1 | package com.blzeecraft.virtualmenu.core.conf.convert; 2 | 3 | import java.util.ArrayList; 4 | import java.util.Collections; 5 | import java.util.List; 6 | import java.util.function.BiFunction; 7 | import java.util.stream.Collectors; 8 | 9 | import com.blzeecraft.virtualmenu.core.conf.ObjectConvertException; 10 | 11 | import lombok.NonNull; 12 | import lombok.val; 13 | import lombok.var; 14 | 15 | public class FuncList implements BiFunction, List> { 16 | 17 | @Override 18 | public List apply(Object obj, @NonNull Class type) { 19 | if (obj == null) { 20 | return Collections.emptyList(); 21 | } 22 | if (type == String.class) { 23 | return asStringList(obj); 24 | } else if (obj instanceof List){ 25 | val list = (List) obj; 26 | return list.stream().map(element -> ConvertFunctions.convertObject(element, type)).collect(Collectors.toList()); 27 | } 28 | throw new ObjectConvertException("无法将" + obj + "转换为类型 " + type + "."); 29 | } 30 | 31 | 32 | @SuppressWarnings("unchecked") 33 | private List asStringList(Object obj) { 34 | if (obj instanceof List) { 35 | return (List)obj; 36 | } 37 | // 以";"分隔, 支持转义"\;" 38 | val list = new ArrayList(); 39 | val chars = obj.toString().toCharArray(); 40 | var cache = new StringBuilder(); 41 | var escape = false; 42 | // 循环处理所有字符 43 | for (char c : chars) { 44 | if (escape) { 45 | escape = false; 46 | cache.append(c); 47 | } else if ('\\' == c) { 48 | escape = true; 49 | } else if (';' == c) { 50 | list.add(cache.toString()); 51 | cache = new StringBuilder(); 52 | } else { 53 | cache.append(c); 54 | } 55 | } 56 | // 处理最后一项 57 | if (cache.length() != 0) { 58 | list.add(cache.toString()); 59 | } 60 | return list; 61 | } 62 | 63 | } 64 | -------------------------------------------------------------------------------- /common/src/main/java/com/blzeecraft/virtualmenu/core/conf/convert/FuncLong.java: -------------------------------------------------------------------------------- 1 | package com.blzeecraft.virtualmenu.core.conf.convert; 2 | 3 | import java.util.function.Function; 4 | 5 | import lombok.NonNull; 6 | 7 | public class FuncLong implements Function { 8 | 9 | @Override 10 | @NonNull 11 | public Long apply(@NonNull Object obj) { 12 | return Long.valueOf(obj.toString()); 13 | } 14 | 15 | } 16 | -------------------------------------------------------------------------------- /common/src/main/java/com/blzeecraft/virtualmenu/core/conf/convert/FuncMap.java: -------------------------------------------------------------------------------- 1 | package com.blzeecraft.virtualmenu.core.conf.convert; 2 | 3 | import java.util.Collections; 4 | import java.util.Map; 5 | import java.util.function.BiFunction; 6 | 7 | import lombok.NonNull; 8 | 9 | 10 | 11 | public class FuncMap implements BiFunction, Class, Map> { 12 | 13 | @Override 14 | @NonNull 15 | public Map apply(Map map, @NonNull Class type) { 16 | if (map == null) { 17 | return Collections.emptyMap(); 18 | } 19 | map.replaceAll((k, v) -> ConvertFunctions.convertObject(v, type)); 20 | return map; 21 | } 22 | 23 | 24 | 25 | 26 | } 27 | -------------------------------------------------------------------------------- /common/src/main/java/com/blzeecraft/virtualmenu/core/conf/convert/FuncOptional.java: -------------------------------------------------------------------------------- 1 | package com.blzeecraft.virtualmenu.core.conf.convert; 2 | 3 | import java.util.Optional; 4 | import java.util.function.BiFunction; 5 | 6 | import lombok.NonNull; 7 | 8 | public class FuncOptional implements BiFunction, Optional> { 9 | 10 | @Override 11 | @NonNull 12 | public Optional apply(Object obj, @NonNull Class type) { 13 | return Optional.ofNullable(obj).map(element -> ConvertFunctions.convertObject(obj, type)); 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /common/src/main/java/com/blzeecraft/virtualmenu/core/conf/convert/FuncOptionalDouble.java: -------------------------------------------------------------------------------- 1 | package com.blzeecraft.virtualmenu.core.conf.convert; 2 | 3 | import java.util.OptionalDouble; 4 | import java.util.function.Function; 5 | 6 | 7 | public class FuncOptionalDouble implements Function { 8 | 9 | @Override 10 | public OptionalDouble apply(Object obj) { 11 | if (obj == null) { 12 | return OptionalDouble.empty(); 13 | } 14 | try { 15 | return OptionalDouble.of(Double.parseDouble(obj.toString())); 16 | } catch (NumberFormatException e) { 17 | } 18 | return OptionalDouble.empty(); 19 | } 20 | 21 | } 22 | -------------------------------------------------------------------------------- /common/src/main/java/com/blzeecraft/virtualmenu/core/conf/convert/FuncOptionalInt.java: -------------------------------------------------------------------------------- 1 | package com.blzeecraft.virtualmenu.core.conf.convert; 2 | 3 | import java.util.OptionalInt; 4 | import java.util.function.Function; 5 | 6 | 7 | public class FuncOptionalInt implements Function { 8 | 9 | @Override 10 | public OptionalInt apply(Object obj) { 11 | if (obj == null) { 12 | return OptionalInt.empty(); 13 | } 14 | try { 15 | return OptionalInt.of(Integer.parseInt(obj.toString())); 16 | } catch (NumberFormatException e) { 17 | } 18 | return OptionalInt.empty(); 19 | } 20 | 21 | } 22 | -------------------------------------------------------------------------------- /common/src/main/java/com/blzeecraft/virtualmenu/core/conf/convert/FuncOptionalLong.java: -------------------------------------------------------------------------------- 1 | package com.blzeecraft.virtualmenu.core.conf.convert; 2 | 3 | import java.util.OptionalLong; 4 | import java.util.function.Function; 5 | 6 | 7 | public class FuncOptionalLong implements Function { 8 | 9 | @Override 10 | public OptionalLong apply(Object obj) { 11 | if (obj == null) { 12 | return OptionalLong.empty(); 13 | } 14 | try { 15 | return OptionalLong.of(Long.parseLong(obj.toString())); 16 | } catch (NumberFormatException e) { 17 | } 18 | return OptionalLong.empty(); 19 | } 20 | 21 | 22 | } 23 | -------------------------------------------------------------------------------- /common/src/main/java/com/blzeecraft/virtualmenu/core/conf/convert/FuncS2ObjectMap.java: -------------------------------------------------------------------------------- 1 | package com.blzeecraft.virtualmenu.core.conf.convert; 2 | 3 | import java.util.LinkedHashMap; 4 | import java.util.Map; 5 | import java.util.Map.Entry; 6 | import java.util.function.Function; 7 | import java.util.stream.Collectors; 8 | 9 | public class FuncS2ObjectMap implements Function> { 10 | 11 | @Override 12 | public Map apply(Object obj) { 13 | if (obj != null && obj instanceof Map) { 14 | return ((Map) obj).entrySet().stream() 15 | .collect(Collectors.toMap(en -> en.getKey().toString(), Entry::getValue)); 16 | } 17 | return new LinkedHashMap<>(); 18 | } 19 | 20 | } 21 | -------------------------------------------------------------------------------- /common/src/main/java/com/blzeecraft/virtualmenu/core/conf/convert/FuncS2StringMap.java: -------------------------------------------------------------------------------- 1 | package com.blzeecraft.virtualmenu.core.conf.convert; 2 | 3 | import java.util.LinkedHashMap; 4 | import java.util.Map; 5 | import java.util.function.Function; 6 | import java.util.stream.Collectors; 7 | 8 | 9 | public class FuncS2StringMap implements Function> { 10 | 11 | @Override 12 | public Map apply(Object obj) { 13 | if (obj == null && obj instanceof Map) { 14 | return ((Map) obj).entrySet().stream() 15 | .collect(Collectors.toMap(en -> en.getKey().toString(), en -> en.getValue().toString())); 16 | } 17 | return new LinkedHashMap<>(); 18 | } 19 | 20 | } -------------------------------------------------------------------------------- /common/src/main/java/com/blzeecraft/virtualmenu/core/conf/convert/FuncString.java: -------------------------------------------------------------------------------- 1 | package com.blzeecraft.virtualmenu.core.conf.convert; 2 | 3 | import java.util.function.Function; 4 | 5 | import lombok.NonNull; 6 | 7 | public class FuncString implements Function { 8 | 9 | @Override 10 | @NonNull 11 | public String apply(@NonNull Object obj) { 12 | return obj.toString(); 13 | } 14 | 15 | } 16 | -------------------------------------------------------------------------------- /common/src/main/java/com/blzeecraft/virtualmenu/core/conf/convert/FuncSubConf.java: -------------------------------------------------------------------------------- 1 | package com.blzeecraft.virtualmenu.core.conf.convert; 2 | 3 | import java.lang.reflect.Field; 4 | import java.util.List; 5 | import java.util.Map; 6 | import java.util.Optional; 7 | import java.util.function.BiFunction; 8 | 9 | import com.blzeecraft.virtualmenu.core.conf.ObjectConvertException; 10 | import com.blzeecraft.virtualmenu.core.conf.transition.SubConf; 11 | import com.blzeecraft.virtualmenu.core.logger.LogNode; 12 | import com.blzeecraft.virtualmenu.core.logger.PluginLogger; 13 | 14 | import lombok.NonNull; 15 | import lombok.val; 16 | 17 | public class FuncSubConf implements BiFunction, Map, SubConf> { 18 | public static final LogNode LOG_NODE = LogNode.of("MapToSubConf"); 19 | 20 | @Override 21 | @NonNull 22 | public SubConf apply(@NonNull Class clazz, @NonNull Map map) { 23 | val instance = initalize(clazz).orElseThrow(ObjectConvertException::new); 24 | for(val field : clazz.getFields()) { 25 | val fieldName = toFieldName(field.getName()); 26 | val dataValue = map.get(fieldName); 27 | processField(instance, field, dataValue); 28 | } 29 | return instance; 30 | } 31 | 32 | public void processField(SubConf instance, Field field, Object dataValue) { 33 | try { 34 | val fieldType = field.getType(); 35 | if (fieldType == Optional.class || fieldType == List.class) { 36 | val actually = ConvertFunctions.getGerericType(field, 0); 37 | val obj = ConvertFunctions.convertObject(dataValue, fieldType, actually); 38 | field.set(instance, obj); 39 | } else if (fieldType == Map.class){ 40 | val actually = ConvertFunctions.getGerericType(field, 1); 41 | val obj = ConvertFunctions.convertObject(dataValue, fieldType, actually); 42 | field.set(instance, obj); 43 | } else { 44 | val obj = ConvertFunctions.convertObject(dataValue, fieldType); 45 | field.set(instance, obj); 46 | } 47 | } catch (Exception e) { 48 | PluginLogger.severe(LOG_NODE, "处理字段 " + field.getDeclaringClass().getSimpleName() + "." + field.getName() + " 时出现异常."); 49 | throw new ObjectConvertException(e); 50 | } 51 | } 52 | 53 | private Optional initalize(@NonNull Class clazz) { 54 | try { 55 | return Optional.of(clazz.newInstance()); 56 | } catch (Exception e) { 57 | e.printStackTrace(); 58 | } 59 | return Optional.empty(); 60 | } 61 | 62 | 63 | 64 | public String toFieldName(String key) { 65 | return key.replace('-', '_'); 66 | } 67 | 68 | } 69 | -------------------------------------------------------------------------------- /common/src/main/java/com/blzeecraft/virtualmenu/core/conf/convert/package-info.java: -------------------------------------------------------------------------------- 1 | package com.blzeecraft.virtualmenu.core.conf.convert; -------------------------------------------------------------------------------- /common/src/main/java/com/blzeecraft/virtualmenu/core/conf/file/IFileFormat.java: -------------------------------------------------------------------------------- 1 | package com.blzeecraft.virtualmenu.core.conf.file; 2 | 3 | import java.io.File; 4 | import java.io.FileWriter; 5 | import java.io.IOException; 6 | import java.io.Reader; 7 | import java.io.Writer; 8 | import java.util.Map; 9 | 10 | import com.blzeecraft.virtualmenu.core.logger.LogNode; 11 | 12 | import lombok.val; 13 | 14 | public interface IFileFormat { 15 | 16 | String[] supportTypes(); 17 | 18 | Map read(LogNode node, Reader reader) throws IOException; 19 | 20 | default Map read(LogNode node, File file) throws IOException { 21 | Reader reader = FileMapFactory.inputFromFile(file); 22 | val result = read(node, reader); 23 | reader.close(); 24 | return result; 25 | } 26 | 27 | void write(LogNode node, Writer writer, Map map) throws IOException; 28 | 29 | default void write(LogNode node, File file, Map map) throws IOException { 30 | Writer writer = new FileWriter(file); 31 | write(node, writer, map); 32 | writer.close(); 33 | } 34 | 35 | 36 | default String name() { 37 | return this.getClass().getSimpleName(); 38 | } 39 | 40 | } 41 | -------------------------------------------------------------------------------- /common/src/main/java/com/blzeecraft/virtualmenu/core/conf/file/JsonFile.java: -------------------------------------------------------------------------------- 1 | package com.blzeecraft.virtualmenu.core.conf.file; 2 | 3 | import java.io.IOException; 4 | import java.io.Reader; 5 | import java.io.Writer; 6 | import java.util.Map; 7 | 8 | import com.blzeecraft.virtualmenu.core.logger.LogNode; 9 | import com.google.gson.Gson; 10 | 11 | public class JsonFile implements IFileFormat { 12 | 13 | @Override 14 | public String[] supportTypes() { 15 | return new String[] {"json"}; 16 | } 17 | 18 | @SuppressWarnings("unchecked") 19 | @Override 20 | public Map read(LogNode node, Reader reader) throws IOException { 21 | Gson gson = new Gson(); 22 | Map map = gson.fromJson(reader, Map.class); 23 | return map; 24 | } 25 | 26 | 27 | 28 | @Override 29 | public void write(LogNode node, Writer writer, Map map) throws IOException { 30 | Gson gson = new Gson(); 31 | gson.toJson(map, Map.class, writer); 32 | } 33 | 34 | 35 | 36 | } 37 | -------------------------------------------------------------------------------- /common/src/main/java/com/blzeecraft/virtualmenu/core/conf/file/UnsupportedFileException.java: -------------------------------------------------------------------------------- 1 | package com.blzeecraft.virtualmenu.core.conf.file; 2 | 3 | import com.blzeecraft.virtualmenu.core.PluginExecption; 4 | 5 | public class UnsupportedFileException extends PluginExecption { 6 | 7 | /** 8 | * 9 | */ 10 | private static final long serialVersionUID = 4254045899401824563L; 11 | 12 | public UnsupportedFileException(String type) { 13 | super("文件类型 ." + type +" 不被支持"); 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /common/src/main/java/com/blzeecraft/virtualmenu/core/conf/file/YamlFile.java: -------------------------------------------------------------------------------- 1 | package com.blzeecraft.virtualmenu.core.conf.file; 2 | 3 | import java.io.IOException; 4 | import java.io.Reader; 5 | import java.io.Writer; 6 | import java.util.Map; 7 | 8 | import org.yaml.snakeyaml.Yaml; 9 | 10 | import com.blzeecraft.virtualmenu.core.logger.LogNode; 11 | 12 | public class YamlFile implements IFileFormat { 13 | 14 | @Override 15 | public String[] supportTypes() { 16 | return new String[] {"yml", "yaml"}; 17 | } 18 | 19 | @Override 20 | public Map read(LogNode node, Reader reader) throws IOException { 21 | Yaml yaml = new Yaml(); 22 | Map map = yaml.load(reader); 23 | return map; 24 | } 25 | 26 | @Override 27 | public void write(LogNode node, Writer writer, Map map) throws IOException { 28 | Yaml yaml = new Yaml(); 29 | String yamlString = yaml.dumpAsMap(map); 30 | writer.append(yamlString); 31 | } 32 | 33 | } 34 | -------------------------------------------------------------------------------- /common/src/main/java/com/blzeecraft/virtualmenu/core/conf/file/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * File -> Map 3 | * @author colors_wind 4 | * @date 2020-01-29 5 | */ 6 | package com.blzeecraft.virtualmenu.core.conf.file; -------------------------------------------------------------------------------- /common/src/main/java/com/blzeecraft/virtualmenu/core/conf/line/InvalidLineCommandException.java: -------------------------------------------------------------------------------- 1 | package com.blzeecraft.virtualmenu.core.conf.line; 2 | 3 | import com.blzeecraft.virtualmenu.core.conf.ObjectConvertException; 4 | 5 | /** 6 | * 表示解析单行配置(LineConfig)时命令名不存在的异常. 7 | * @author colors_wind 8 | * 9 | */ 10 | public class InvalidLineCommandException extends ObjectConvertException { 11 | 12 | /** 13 | * 14 | */ 15 | private static final long serialVersionUID = 8773893646529653864L; 16 | 17 | 18 | public InvalidLineCommandException() { 19 | super(); 20 | } 21 | 22 | public InvalidLineCommandException(String message, Throwable cause) { 23 | super(message, cause); 24 | } 25 | 26 | public InvalidLineCommandException(String message) { 27 | super(message); 28 | } 29 | 30 | public InvalidLineCommandException(Throwable cause) { 31 | super(cause); 32 | } 33 | 34 | 35 | 36 | } 37 | -------------------------------------------------------------------------------- /common/src/main/java/com/blzeecraft/virtualmenu/core/conf/line/InvalidLineFormatException.java: -------------------------------------------------------------------------------- 1 | package com.blzeecraft.virtualmenu.core.conf.line; 2 | 3 | import com.blzeecraft.virtualmenu.core.conf.ObjectConvertException; 4 | 5 | /** 6 | * 表示尝试解析一个单行配置(LineConfig)发现语法错误抛出的异常. 7 | * @author colors_wind 8 | */ 9 | public class InvalidLineFormatException extends ObjectConvertException { 10 | 11 | /** 12 | * 13 | */ 14 | private static final long serialVersionUID = 5048239003927412635L; 15 | 16 | public InvalidLineFormatException() { 17 | super(); 18 | } 19 | 20 | public InvalidLineFormatException(String message, Throwable cause) { 21 | super(message, cause); 22 | } 23 | 24 | public InvalidLineFormatException(String message) { 25 | super(message); 26 | } 27 | 28 | public InvalidLineFormatException(Throwable cause) { 29 | super(cause); 30 | } 31 | 32 | 33 | 34 | 35 | 36 | } 37 | -------------------------------------------------------------------------------- /common/src/main/java/com/blzeecraft/virtualmenu/core/conf/line/LineConfigObject.java: -------------------------------------------------------------------------------- 1 | package com.blzeecraft.virtualmenu.core.conf.line; 2 | 3 | import java.util.LinkedHashMap; 4 | 5 | import com.blzeecraft.virtualmenu.core.logger.LogNode; 6 | import com.blzeecraft.virtualmenu.core.logger.LoggerObject; 7 | 8 | /** 9 | * 代表一个由解析的配置映射得到的对象 10 | * @author colors_wind 11 | * 12 | */ 13 | public abstract class LineConfigObject implements LoggerObject { 14 | 15 | protected final LogNode node; 16 | protected final ResolvedLineConfig rlc; 17 | 18 | 19 | public LineConfigObject(LogNode node, ResolvedLineConfig rlc) { 20 | this.rlc = rlc; 21 | this.node = node; 22 | } 23 | 24 | public LineConfigObject(LogNode node) { 25 | this(node, new ResolvedLineConfig(new LinkedHashMap<>())); 26 | } 27 | 28 | @Override 29 | public LogNode getLogNode() { 30 | return node; 31 | } 32 | 33 | } 34 | -------------------------------------------------------------------------------- /common/src/main/java/com/blzeecraft/virtualmenu/core/conf/line/MissingRequiredObjectException.java: -------------------------------------------------------------------------------- 1 | package com.blzeecraft.virtualmenu.core.conf.line; 2 | 3 | import com.blzeecraft.virtualmenu.core.conf.InvalidConfigException; 4 | 5 | /** 6 | * 表示解析配置文件时检查发现带读取的必须元素不存在时抛出的异常. 7 | * @author colors_wind 8 | * 9 | */ 10 | public class MissingRequiredObjectException extends InvalidConfigException { 11 | 12 | 13 | /** 14 | * 15 | */ 16 | private static final long serialVersionUID = 6365124405281241184L; 17 | 18 | public MissingRequiredObjectException() { 19 | super(); 20 | } 21 | 22 | public MissingRequiredObjectException(String message, Throwable cause) { 23 | super(message, cause); 24 | } 25 | 26 | public MissingRequiredObjectException(String message) { 27 | super(message); 28 | } 29 | 30 | public MissingRequiredObjectException(Throwable cause) { 31 | super(cause); 32 | } 33 | 34 | } 35 | -------------------------------------------------------------------------------- /common/src/main/java/com/blzeecraft/virtualmenu/core/conf/line/package-info.java: -------------------------------------------------------------------------------- 1 | package com.blzeecraft.virtualmenu.core.conf.line; -------------------------------------------------------------------------------- /common/src/main/java/com/blzeecraft/virtualmenu/core/conf/menu/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * conf -> menu 3 | * @author colors_wind 4 | * @date 2020-02-03 5 | */ 6 | package com.blzeecraft.virtualmenu.core.conf.menu; -------------------------------------------------------------------------------- /common/src/main/java/com/blzeecraft/virtualmenu/core/conf/package-info.java: -------------------------------------------------------------------------------- 1 | package com.blzeecraft.virtualmenu.core.conf; -------------------------------------------------------------------------------- /common/src/main/java/com/blzeecraft/virtualmenu/core/conf/transition/IllegalFieldException.java: -------------------------------------------------------------------------------- 1 | package com.blzeecraft.virtualmenu.core.conf.transition; 2 | 3 | import com.blzeecraft.virtualmenu.core.PluginExecption; 4 | 5 | /** 6 | * 表示负责序列化/反序列化的类字段不合法 7 | * 8 | * @author colors_wind 9 | * 10 | */ 11 | public class IllegalFieldException extends PluginExecption { 12 | 13 | /** 14 | * 15 | */ 16 | private static final long serialVersionUID = 1386394777530647500L; 17 | 18 | public IllegalFieldException() { 19 | super(); 20 | } 21 | 22 | public IllegalFieldException(String message, Throwable cause) { 23 | super(message, cause); 24 | } 25 | 26 | public IllegalFieldException(String message) { 27 | super(message); 28 | } 29 | 30 | public IllegalFieldException(Throwable cause) { 31 | super(cause); 32 | } 33 | 34 | } 35 | -------------------------------------------------------------------------------- /common/src/main/java/com/blzeecraft/virtualmenu/core/conf/transition/ObjectType.java: -------------------------------------------------------------------------------- 1 | package com.blzeecraft.virtualmenu.core.conf.transition; 2 | 3 | import static java.lang.annotation.ElementType.FIELD; 4 | import static java.lang.annotation.RetentionPolicy.RUNTIME; 5 | 6 | import java.lang.annotation.Retention; 7 | import java.lang.annotation.Target; 8 | 9 | @Retention(RUNTIME) 10 | @Target(FIELD) 11 | public @interface ObjectType { 12 | 13 | Class value(); 14 | 15 | } 16 | -------------------------------------------------------------------------------- /common/src/main/java/com/blzeecraft/virtualmenu/core/conf/transition/StandardConf.java: -------------------------------------------------------------------------------- 1 | package com.blzeecraft.virtualmenu.core.conf.transition; 2 | 3 | import java.util.List; 4 | import java.util.Map; 5 | import java.util.Optional; 6 | import java.util.OptionalInt; 7 | 8 | import lombok.ToString; 9 | 10 | /** 11 | * 表示文件读取得到的数据,是 {@link File} 到 {@link PacketMenu} 的中间类型}} 12 | * 该类型用于储存文件中未解析的结构化数据 13 | * @author colors_wind 14 | * 15 | */ 16 | @ToString 17 | public class StandardConf extends SubConf { 18 | 19 | public GlobalConf global; 20 | @ToString public static class GlobalConf extends SubConf { 21 | public String title; 22 | public String type; 23 | public Optional refresh; 24 | public List bound; 25 | } 26 | 27 | @ObjectType(EventConf.class) 28 | public Map events; 29 | @ToString public static class EventConf extends SubConf { 30 | public List condition; 31 | public List action; 32 | } 33 | 34 | @ObjectType(IconConf.class) 35 | public Map icons; 36 | @ToString public static class IconConf extends SubConf { 37 | public Optional name; 38 | public String id; 39 | public OptionalInt amount; 40 | public Optional nbt; 41 | public List lore; 42 | public List action; 43 | public List view_condition; 44 | public List click_condition; 45 | public OptionalInt priority; 46 | public OptionalInt postion_x; 47 | public OptionalInt postion_y; 48 | public OptionalInt slot; 49 | 50 | } 51 | 52 | } 53 | -------------------------------------------------------------------------------- /common/src/main/java/com/blzeecraft/virtualmenu/core/conf/transition/SubConf.java: -------------------------------------------------------------------------------- 1 | package com.blzeecraft.virtualmenu.core.conf.transition; 2 | 3 | import java.util.LinkedHashMap; 4 | import java.util.List; 5 | import java.util.Map; 6 | import java.util.Optional; 7 | import java.util.OptionalDouble; 8 | import java.util.OptionalInt; 9 | import java.util.OptionalLong; 10 | import java.util.stream.Collectors; 11 | 12 | import lombok.NonNull; 13 | import lombok.SneakyThrows; 14 | import lombok.val; 15 | 16 | /** 17 | * 用于标记 {@link StandardConf} 中子类型 18 | * @author colors_wind 19 | * 20 | */ 21 | public class SubConf { 22 | 23 | 24 | @NonNull 25 | @SneakyThrows 26 | public Map serialize() { 27 | val map = new LinkedHashMap(); 28 | for(val field : this.getClass().getFields()) { 29 | val value = field.get(this); 30 | val key = field.getName().replace('_', '-'); 31 | if (value == null) { 32 | map.put(key, null); 33 | } else if (value instanceof List) { 34 | map.put(key, unWrapList(value)); 35 | } else if (value instanceof Map) { 36 | map.put(key, unWrapMap(value)); 37 | } else if (value instanceof Optional) { 38 | map.put(key, unWrapOptional(value)); 39 | } else if (value instanceof SubConf) { 40 | map.put(key, ((SubConf) value).serialize()); 41 | } else { 42 | map.put(key, unWrapObject(value)); 43 | } 44 | } 45 | return map; 46 | } 47 | 48 | public List unWrapList(Object value) { 49 | return ((List)value).stream().map(this::unWrapObject).collect(Collectors.toList()); 50 | } 51 | 52 | public Map unWrapMap(Object value) { 53 | val map = new LinkedHashMap(); 54 | ((Map)value).forEach((k,v) -> map.put((String) k, unWrapObject(v))); 55 | return map; 56 | } 57 | 58 | public Object unWrapOptional(Object value) { 59 | return ((Optional)value).map(this::unWrapObject).orElse(null); 60 | } 61 | 62 | public Object unWrapObject(Object obj) { 63 | if (obj instanceof OptionalInt) { 64 | if (((OptionalInt) obj).isPresent()) { 65 | return ((OptionalInt) obj).getAsInt(); 66 | } 67 | } else if (obj instanceof OptionalLong) { 68 | if (((OptionalLong) obj).isPresent()) { 69 | return ((OptionalLong) obj).getAsLong(); 70 | } 71 | } else if (obj instanceof OptionalDouble) { 72 | if (((OptionalDouble) obj).isPresent()) { 73 | return ((OptionalDouble) obj).getAsDouble(); 74 | } 75 | } else if (obj instanceof SubConf) { 76 | return ((SubConf) obj).serialize(); 77 | } 78 | return obj; 79 | } 80 | 81 | } 82 | -------------------------------------------------------------------------------- /common/src/main/java/com/blzeecraft/virtualmenu/core/conf/transition/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Map-> StandardConf 3 | * @author colors_wind 4 | * @date 2020-01-29 5 | */ 6 | package com.blzeecraft.virtualmenu.core.conf.transition; -------------------------------------------------------------------------------- /common/src/main/java/com/blzeecraft/virtualmenu/core/icon/DynamicIcon.java: -------------------------------------------------------------------------------- 1 | package com.blzeecraft.virtualmenu.core.icon; 2 | 3 | import java.util.Collections; 4 | import java.util.List; 5 | import java.util.Optional; 6 | import java.util.function.Consumer; 7 | import java.util.function.Function; 8 | import java.util.function.Predicate; 9 | 10 | import com.blzeecraft.virtualmenu.core.VirtualMenu; 11 | import com.blzeecraft.virtualmenu.core.action.IAction; 12 | import com.blzeecraft.virtualmenu.core.action.event.MenuEvent; 13 | import com.blzeecraft.virtualmenu.core.condition.ICondition; 14 | import com.blzeecraft.virtualmenu.core.item.AbstractItem; 15 | import com.blzeecraft.virtualmenu.core.logger.LogNode; 16 | import com.blzeecraft.virtualmenu.core.user.IUser; 17 | import com.blzeecraft.virtualmenu.core.user.UserSession; 18 | 19 | import lombok.ToString; 20 | import lombok.val; 21 | 22 | /** 23 | * 动态 {@link Icon}, 这个类是不可变的 24 | * 25 | * @author colors_wind 26 | * 27 | */ 28 | @ToString(callSuper = true) 29 | public class DynamicIcon extends SimpleIcon { 30 | public static final Function, String> EMPTY_NAME = u -> null; 31 | public static final Function, List> EMPTY_LORE = u -> Collections.emptyList(); 32 | 33 | protected final Function, String> name; 34 | protected final Function, List> lore; 35 | 36 | public DynamicIcon(LogNode node, int priority, AbstractItem cache, Function> clickCondition, Predicate viewCondition, 37 | Consumer command, Function, String> name, Function, List> lore) { 38 | super(node, priority, cache, clickCondition, viewCondition, command); 39 | this.name = name; 40 | this.lore = lore; 41 | } 42 | 43 | public DynamicIcon(LogNode node, int priority, AbstractItem cache, ICondition clickCondition, ICondition viewCondition, 44 | IAction command, Function, String> name, Function, List> lore) { 45 | super(node, priority, cache, clickCondition, viewCondition, command); 46 | this.name = name; 47 | this.lore = lore; 48 | } 49 | 50 | public DynamicIcon(LogNode node, AbstractItem cache, ICondition clickCondition, ICondition viewCondition, IAction command, 51 | Function, String> name, Function, List> lore) { 52 | this(node, 0, cache, clickCondition, viewCondition, command, name, lore); 53 | } 54 | 55 | 56 | 57 | public AbstractItem refreshItem(UserSession session) { 58 | if (canView(session)) { 59 | return refreshUncheck(session); 60 | } 61 | return VirtualMenu.emptyItem(); 62 | 63 | } 64 | 65 | protected AbstractItem refreshUncheck(UserSession session) { 66 | val builder = this.cache.builder(); 67 | val user = session.getUser(); 68 | builder.name(name.apply(user)); 69 | builder.lore(lore.apply(user)); 70 | val item = builder.build(this.getLogNode()); 71 | return item; 72 | } 73 | 74 | @Override 75 | public AbstractItem view(UserSession session) { 76 | val user = session.getUser(); 77 | val newName = name.apply(user); 78 | val newLore = lore.apply(user); 79 | return this.cache.updateMeta(newName, newLore); 80 | } 81 | 82 | 83 | 84 | 85 | } 86 | -------------------------------------------------------------------------------- /common/src/main/java/com/blzeecraft/virtualmenu/core/icon/EmptyIcon.java: -------------------------------------------------------------------------------- 1 | package com.blzeecraft.virtualmenu.core.icon; 2 | 3 | import java.util.Optional; 4 | 5 | import com.blzeecraft.virtualmenu.core.VirtualMenu; 6 | import com.blzeecraft.virtualmenu.core.action.event.IconActionEvent; 7 | import com.blzeecraft.virtualmenu.core.item.AbstractItem; 8 | import com.blzeecraft.virtualmenu.core.user.UserSession; 9 | 10 | /** 11 | * 表示一个空的 Icon. 12 | * @author colors_wind 13 | * @date 2020-02-13 14 | */ 15 | public final class EmptyIcon implements Icon { 16 | public static final Icon INSTANCE = new EmptyIcon(); 17 | 18 | @Override 19 | public AbstractItem view(UserSession session) { 20 | return VirtualMenu.emptyItem(); 21 | } 22 | 23 | @Override 24 | public boolean canView(UserSession session) { 25 | return false; 26 | } 27 | 28 | @Override 29 | public Optional canClick(IconActionEvent e) { 30 | return Optional.of("找不到可见的Icon."); 31 | } 32 | 33 | @Override 34 | public int getPriority() { 35 | return 0; 36 | } 37 | 38 | @Override 39 | public void accept(IconActionEvent e) {} 40 | 41 | 42 | @Override 43 | public int hashCode() { 44 | return 0; 45 | } 46 | 47 | @Override 48 | public boolean equals(Object obj) { 49 | if (obj != null && obj.getClass() == this.getClass()) { 50 | return true; 51 | } 52 | return false; 53 | } 54 | 55 | @Override 56 | public boolean isEmpty() { 57 | return true; 58 | } 59 | 60 | } 61 | -------------------------------------------------------------------------------- /common/src/main/java/com/blzeecraft/virtualmenu/core/icon/Icon.java: -------------------------------------------------------------------------------- 1 | package com.blzeecraft.virtualmenu.core.icon; 2 | 3 | import java.util.Optional; 4 | import java.util.function.Consumer; 5 | 6 | import com.blzeecraft.virtualmenu.core.user.UserManager; 7 | import com.blzeecraft.virtualmenu.core.user.UserSession; 8 | import com.blzeecraft.virtualmenu.core.icon.EmptyIcon; 9 | import com.blzeecraft.virtualmenu.core.VirtualMenu; 10 | import com.blzeecraft.virtualmenu.core.action.event.IconActionEvent; 11 | import com.blzeecraft.virtualmenu.core.item.AbstractItem; 12 | import com.blzeecraft.virtualmenu.core.logger.LogNode; 13 | 14 | /** 15 | * 代表菜单中的一个图标, 单个图标可以为不同的玩家显示不同的物品. 16 | * Icon 不应该修改 {@link UserSession} 中的字段. 17 | * 所有对 UserSession 的中修改应该由 {@link UserManager} 进行. 18 | * @author colors_wind 19 | * 20 | */ 21 | public interface Icon extends Comparable, Consumer { 22 | 23 | /** 24 | * 获取玩家显示的物品. 25 | * @param session 26 | * @return 如果不显示任何物品, 返回 {@link VirtualMenu#emptyItem()} 否则返回应显示的物品 27 | */ 28 | AbstractItem view(UserSession session); 29 | 30 | 31 | /** 32 | * 检查玩家是否能查看这个 Icon. 33 | * @param session UserSession 34 | * @return 如果可以看见返回 {@code true}, 否则返回 {@code false}. 35 | */ 36 | boolean canView(UserSession session); 37 | 38 | /** 39 | * 检查玩家是否能点击这个{@link Icon} 40 | * @param e 点击的事件 41 | * @return 如果允许玩家点击,返回 {@link Optional#empty} 否则返回拒绝的信息 42 | */ 43 | Optional canClick(IconActionEvent e); 44 | 45 | /** 46 | * 获取这个{@link Icon}显示的优先级 47 | * @return 优先级 48 | */ 49 | int getPriority(); 50 | 51 | void accept(IconActionEvent e); 52 | 53 | @Override 54 | default int compareTo(Icon o) { 55 | return Integer.compare(this.getPriority(), o.getPriority()); 56 | } 57 | 58 | /** 59 | * 该 Icon 是否为 {@link EmptyIcon} 60 | * @return {@code true} 如果这里 Icon 为 {@link EmptyIcon}, 否则返回 {@code false}. 61 | */ 62 | default boolean isEmpty() { 63 | return false; 64 | } 65 | 66 | /** 67 | * 获取该 Icon 对应的 LogNode. 68 | * @return 对应的 LogNode. 69 | */ 70 | default LogNode getLogNode() { 71 | return LogNode.of("#Icon"); 72 | } 73 | 74 | 75 | 76 | 77 | 78 | } 79 | -------------------------------------------------------------------------------- /common/src/main/java/com/blzeecraft/virtualmenu/core/icon/IconBuilder.java: -------------------------------------------------------------------------------- 1 | package com.blzeecraft.virtualmenu.core.icon; 2 | 3 | import java.util.List; 4 | import java.util.Optional; 5 | import java.util.function.Consumer; 6 | import java.util.function.Function; 7 | import java.util.function.Predicate; 8 | 9 | import com.blzeecraft.virtualmenu.core.VirtualMenu; 10 | import com.blzeecraft.virtualmenu.core.action.event.MenuEvent; 11 | import com.blzeecraft.virtualmenu.core.item.AbstractItem; 12 | import com.blzeecraft.virtualmenu.core.logger.LogNode; 13 | import com.blzeecraft.virtualmenu.core.user.IUser; 14 | 15 | import lombok.val; 16 | 17 | public class IconBuilder { 18 | 19 | private int priority; 20 | private AbstractItem item; 21 | private Function> clickCondition; 22 | private Predicate viewCondition; 23 | private Consumer command; 24 | 25 | public IconBuilder priority(int priority) { 26 | this.priority = priority; 27 | return this; 28 | } 29 | public IconBuilder item(AbstractItem item) { 30 | this.item = item; 31 | return this; 32 | } 33 | public IconBuilder clickCondition(Function> clickCondition) { 34 | this.clickCondition = clickCondition; 35 | return this; 36 | } 37 | public IconBuilder viewCondition(Predicate viewCondition) { 38 | this.viewCondition = viewCondition; 39 | return this; 40 | } 41 | public IconBuilder command(Consumer command) { 42 | this.command = command; 43 | return this; 44 | } 45 | 46 | public Icon build(LogNode node) { 47 | val variables = VirtualMenu.getVariableAdapter(); 48 | if (variables.containsVariable(item.getName()) || variables.containsVariable(item.getLore())) { 49 | Function, String> name; 50 | // displayname 51 | if (variables.containsVariable(item.getName())) { 52 | name = user -> variables.replace(user, item.getName()); 53 | } else { 54 | name = user -> item.getName(); 55 | } 56 | // lore 57 | Function, List> lore; 58 | if (variables.containsVariable(item.getLore())) { 59 | lore = user -> variables.replace(user, item.getLore()); 60 | } else { 61 | lore = user -> item.getLore(); 62 | } 63 | return new DynamicIcon(node, priority, item, clickCondition, viewCondition, command, name, lore); 64 | } else { 65 | return new SimpleIcon(node, priority, item, clickCondition, viewCondition, command); 66 | } 67 | } 68 | 69 | 70 | 71 | } 72 | -------------------------------------------------------------------------------- /common/src/main/java/com/blzeecraft/virtualmenu/core/icon/MultiIcon.java: -------------------------------------------------------------------------------- 1 | package com.blzeecraft.virtualmenu.core.icon; 2 | 3 | import java.util.Arrays; 4 | import java.util.Collections; 5 | import java.util.List; 6 | import java.util.Optional; 7 | import java.util.stream.Collectors; 8 | import java.util.stream.Stream; 9 | 10 | import com.blzeecraft.virtualmenu.core.action.event.IconActionEvent; 11 | import com.blzeecraft.virtualmenu.core.conf.ConfSerializable; 12 | import com.blzeecraft.virtualmenu.core.conf.transition.StandardConf.IconConf; 13 | import com.blzeecraft.virtualmenu.core.item.AbstractItem; 14 | import com.blzeecraft.virtualmenu.core.user.UserSession; 15 | 16 | import lombok.Getter; 17 | import lombok.ToString; 18 | import lombok.val; 19 | 20 | /** 21 | * 多个 {@link Icon} 复合,用于支持优先级显示,这个类是不可变的. 22 | * 23 | * @author colors_wind 24 | * 25 | */ 26 | @ToString 27 | public class MultiIcon implements Icon, ConfSerializable { 28 | @Getter 29 | protected final List storeIconList; 30 | 31 | public MultiIcon(List icons) { 32 | // copy 33 | this(icons.toArray(new Icon[icons.size()])); 34 | } 35 | 36 | public MultiIcon(Icon... icons) { 37 | val sort = Arrays.asList(icons); 38 | Collections.sort(sort); 39 | Collections.reverse(sort); 40 | this.storeIconList = sort; 41 | } 42 | 43 | @Override 44 | public AbstractItem view(UserSession session) { 45 | return viewIcon(session).view(session); 46 | } 47 | 48 | @Override 49 | public boolean canView(UserSession session) { 50 | return view(session).isEmpty(); 51 | } 52 | 53 | @Override 54 | public Optional canClick(IconActionEvent e) { 55 | return viewIcon(e.getSession()).canClick(e); 56 | } 57 | 58 | @Override 59 | public void accept(IconActionEvent e) { 60 | viewIcon(e.getSession()).accept(e); 61 | } 62 | 63 | public Icon viewIcon(UserSession session) { 64 | return storeIconList.stream().filter(icon -> icon.canView(session)).findFirst().orElse(EmptyIcon.INSTANCE); 65 | } 66 | 67 | @Override 68 | public int getPriority() { 69 | return 0; 70 | } 71 | 72 | public static MultiIcon of(Icon... icons) { 73 | List flatMapIcons = Arrays.stream(icons).flatMap(icon -> { 74 | if (icon instanceof MultiIcon) { 75 | return ((MultiIcon) icon).storeIconList.stream(); 76 | } else { 77 | return Stream.of(icon); 78 | } 79 | }).collect(Collectors.toList()); 80 | return new MultiIcon(flatMapIcons); 81 | } 82 | 83 | @Override 84 | public IconConf serialize() { 85 | throw new UnsupportedOperationException(); 86 | } 87 | 88 | @Override 89 | public IconConf[] seriablizeAll() { 90 | return storeIconList.stream().filter(ConfSerializable.class::isInstance).map(ConfSerializable.class::cast) 91 | .map(ConfSerializable::serialize).map(IconConf.class::cast).toArray(IconConf[]::new); 92 | } 93 | 94 | } 95 | -------------------------------------------------------------------------------- /common/src/main/java/com/blzeecraft/virtualmenu/core/icon/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 和 {@link Icon} 相关的类 3 | */ 4 | package com.blzeecraft.virtualmenu.core.icon; 5 | -------------------------------------------------------------------------------- /common/src/main/java/com/blzeecraft/virtualmenu/core/item/AbstractItem.java: -------------------------------------------------------------------------------- 1 | package com.blzeecraft.virtualmenu.core.item; 2 | 3 | import java.util.Collections; 4 | import java.util.List; 5 | import java.util.Objects; 6 | import java.util.Optional; 7 | import java.util.OptionalInt; 8 | 9 | import com.blzeecraft.virtualmenu.core.IWrappedObject; 10 | import com.blzeecraft.virtualmenu.core.conf.transition.StandardConf.IconConf; 11 | 12 | import lombok.Data; 13 | 14 | /** 15 | * 用于对物品进行包装, 这个类的不可变的. 16 | * @author colors_wind 17 | * 18 | * @param 19 | */ 20 | @Data 21 | public abstract class AbstractItem implements IWrappedObject { 22 | protected final T handle; 23 | 24 | protected final String id; 25 | protected final int amount; 26 | protected final String name; 27 | protected final List lore; 28 | protected final String nbt; 29 | 30 | //protected final String[] copyOfLore; 31 | 32 | protected AbstractItem(T handle, String id, int amount, String name, List lore, String nbt) { 33 | this.handle = Objects.requireNonNull(handle); 34 | this.id = id; 35 | this.amount = amount; 36 | this.name = name; 37 | this.lore = lore == null ? Collections.emptyList() : Collections.unmodifiableList(lore); 38 | this.nbt = nbt; 39 | //this.copyOfLore = lore.toArray(new String[lore.size()]); 40 | } 41 | 42 | protected AbstractItem(T handle, String id, int amount, String name, List lore) { 43 | this(handle, id, amount, name, lore, null); 44 | } 45 | 46 | public void applyConf(IconConf conf) { 47 | conf.id = this.id; 48 | conf.amount = OptionalInt.of(amount); 49 | conf.name = Optional.ofNullable(name); 50 | conf.lore = lore; 51 | conf.nbt = Optional.ofNullable(nbt); 52 | } 53 | 54 | public abstract AbstractItemBuilder builder(); 55 | 56 | 57 | public abstract boolean isEmpty(); 58 | 59 | public abstract AbstractItem updateMeta(String newName, List newLore); 60 | 61 | 62 | } 63 | -------------------------------------------------------------------------------- /common/src/main/java/com/blzeecraft/virtualmenu/core/item/AbstractItemBuilder.java: -------------------------------------------------------------------------------- 1 | package com.blzeecraft.virtualmenu.core.item; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | import com.blzeecraft.virtualmenu.core.logger.LogNode; 7 | 8 | import lombok.NonNull; 9 | 10 | /** 11 | * 封装的物品构造器 12 | * @author colors_wind 13 | * 14 | * @param 15 | */ 16 | public abstract class AbstractItemBuilder { 17 | 18 | protected String id; 19 | protected int amount; 20 | protected String name; 21 | protected List lore; 22 | protected String nbt; 23 | 24 | public AbstractItemBuilder() {} 25 | 26 | public AbstractItemBuilder(AbstractItem item) { 27 | this.id = item.id; 28 | this.amount = item.amount; 29 | this.name = item.name; 30 | this.lore = item.lore; 31 | this.nbt = item.nbt; 32 | } 33 | 34 | @NonNull 35 | public AbstractItemBuilder(String id) { 36 | this.id = id; 37 | } 38 | 39 | public AbstractItemBuilder id(String id) { 40 | this.id = id; 41 | return this; 42 | } 43 | 44 | @NonNull 45 | public AbstractItemBuilder name(String name) { 46 | this.name = name; 47 | return this; 48 | } 49 | 50 | @NonNull 51 | public AbstractItemBuilder lore(List lore) { 52 | this.lore = lore; 53 | return this; 54 | } 55 | 56 | @NonNull 57 | public AbstractItemBuilder addLore(String... lore) { 58 | if (this.lore == null) { 59 | this.lore = new ArrayList<>(); 60 | } 61 | for(int i=0;i amount(int amount) { 68 | this.amount = amount; 69 | return this; 70 | } 71 | 72 | public AbstractItemBuilder removeLore(int index) throws IndexOutOfBoundsException { 73 | lore.remove(index); 74 | return this; 75 | } 76 | 77 | @NonNull 78 | public AbstractItemBuilder nbt(String nbt) { 79 | this.nbt = nbt; 80 | return this; 81 | } 82 | 83 | public abstract AbstractItem build(LogNode node); 84 | 85 | 86 | } 87 | -------------------------------------------------------------------------------- /common/src/main/java/com/blzeecraft/virtualmenu/core/item/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 与物品相关的类 3 | */ 4 | package com.blzeecraft.virtualmenu.core.item; -------------------------------------------------------------------------------- /common/src/main/java/com/blzeecraft/virtualmenu/core/logger/LogFormatter.java: -------------------------------------------------------------------------------- 1 | package com.blzeecraft.virtualmenu.core.logger; 2 | 3 | import java.util.Arrays; 4 | import java.util.List; 5 | import java.util.Map; 6 | import java.util.Objects; 7 | 8 | public class LogFormatter { 9 | 10 | public static String toString(Object o) { 11 | if (o == null) { 12 | return "null"; 13 | } else if (o instanceof Integer) { 14 | return toStringInt((Integer) o); 15 | } else if (o instanceof Long) { 16 | return toStringLong((Long) o); 17 | } else if (o instanceof Object[]) { 18 | return toStringArray((Object[]) o); 19 | } else if (o instanceof Map) { 20 | return toStringMap((Map) o); 21 | } else if (o instanceof List) { 22 | return toStringList((List) o); 23 | } else { 24 | return o.toString(); 25 | } 26 | } 27 | 28 | public static String toStringObject(Object o) { 29 | return Objects.toString(o); 30 | } 31 | 32 | public static String toStringInt(Integer i) { 33 | return i.toString(); 34 | } 35 | 36 | public static String toStringLong(Long l) { 37 | return l.toString(); 38 | } 39 | 40 | public static String toStringArray(Object[] array) { 41 | return Arrays.toString(array); 42 | } 43 | 44 | public static String toStringMap(Map map) { 45 | return map.toString(); 46 | } 47 | 48 | public static String toStringList(List list) { 49 | return list.toString(); 50 | } 51 | 52 | 53 | 54 | } 55 | -------------------------------------------------------------------------------- /common/src/main/java/com/blzeecraft/virtualmenu/core/logger/LogNode.java: -------------------------------------------------------------------------------- 1 | package com.blzeecraft.virtualmenu.core.logger; 2 | 3 | import lombok.EqualsAndHashCode; 4 | import lombok.NonNull; 5 | import lombok.ToString; 6 | 7 | /** 8 | * 代表一个日志节点, 这个类是不可变的 9 | * @author colors_wind 10 | * 11 | */ 12 | @ToString 13 | @EqualsAndHashCode 14 | public final class LogNode { 15 | public static final String SPLIT = ">"; 16 | public static final String LIST_SUFFIX = "!"; 17 | public static final LogNode ROOT = new LogNode(""); 18 | 19 | 20 | // 上级LogNode 21 | private final LogNode parent; 22 | // 当前LogNode的名称 23 | @NonNull private final String name; 24 | // 格式化输出的缓存 25 | @NonNull private final String cache; 26 | 27 | 28 | @NonNull 29 | private LogNode(String root) { 30 | this.name = root; 31 | this.parent = null; 32 | this.cache = root; 33 | } 34 | 35 | @NonNull 36 | private LogNode(LogNode parent, String name) { 37 | this.parent = parent; 38 | this.name = name; 39 | this.cache = new StringBuilder(parent.cache).append(SPLIT).append(name).toString(); 40 | } 41 | 42 | /** 43 | * @return 上级LogNode 44 | */ 45 | public LogNode parent() { 46 | if (isRoot()) { 47 | throw new ArrayIndexOutOfBoundsException("根 LogNode 没有上级 LogNode"); 48 | } 49 | return parent; 50 | } 51 | 52 | public boolean isRoot() { 53 | return parent == null; 54 | } 55 | 56 | public LogNode sub(String name) { 57 | return new LogNode(this, name); 58 | } 59 | 60 | public String getPrefix() { 61 | return cache; 62 | } 63 | 64 | public LogNode list() { 65 | return new LogNode(parent, name + LIST_SUFFIX); 66 | } 67 | 68 | /** 69 | * 创建根LogNode 70 | * @param root 根名称 71 | */ 72 | public static LogNode of(String name) { 73 | return new LogNode(name); 74 | } 75 | 76 | } 77 | -------------------------------------------------------------------------------- /common/src/main/java/com/blzeecraft/virtualmenu/core/logger/LoggerObject.java: -------------------------------------------------------------------------------- 1 | package com.blzeecraft.virtualmenu.core.logger; 2 | 3 | /** 4 | * 代表对象可作为日志产生者 5 | * @author colors_wind 6 | * 7 | */ 8 | public interface LoggerObject { 9 | 10 | LogNode getLogNode(); 11 | 12 | } 13 | -------------------------------------------------------------------------------- /common/src/main/java/com/blzeecraft/virtualmenu/core/logger/PluginLogger.java: -------------------------------------------------------------------------------- 1 | package com.blzeecraft.virtualmenu.core.logger; 2 | 3 | import java.io.File; 4 | import java.text.SimpleDateFormat; 5 | import java.util.Arrays; 6 | import java.util.Date; 7 | import java.util.logging.FileHandler; 8 | import java.util.logging.Level; 9 | import java.util.logging.Logger; 10 | 11 | import com.blzeecraft.virtualmenu.core.VirtualMenu; 12 | 13 | import lombok.NonNull; 14 | import lombok.SneakyThrows; 15 | import lombok.val; 16 | import lombok.experimental.UtilityClass; 17 | 18 | /** 19 | * 插件日志的工厂类 20 | * @author colors_wind 21 | * 22 | */ 23 | @NonNull 24 | @UtilityClass 25 | public class PluginLogger { 26 | 27 | private static Logger logger = Logger.getLogger("VirtualMenu"); 28 | static { 29 | // minecraft的Logger不会输出INFO以下的信息 30 | logger.setFilter(record -> { 31 | if (record.getLevel().intValue() <= Level.INFO.intValue()) { 32 | record.setLevel(Level.INFO); 33 | } 34 | return true; 35 | }); 36 | } 37 | 38 | @SneakyThrows 39 | public static void setup() { 40 | logger = VirtualMenu.getLogger(); 41 | Date d = new Date(); 42 | SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd"); 43 | File logFolder = new File(VirtualMenu.getDataFolder(), "logs"); 44 | if (!logFolder.exists()) { 45 | logFolder.mkdirs(); 46 | } 47 | File file = new File(logFolder, format.format(d) + ".txt"); 48 | val handler = new FileHandler(file.getPath()); 49 | logger.addHandler(handler); 50 | } 51 | 52 | public static void info(LogNode node, String msg) { 53 | logger.info(join(node, msg)); 54 | } 55 | 56 | private static String join(LogNode node, String msg) { 57 | return new StringBuilder(node.getPrefix()).append(" ").append(msg).toString(); 58 | } 59 | 60 | public static void fine(LogNode node, String msg) { 61 | logger.fine(join(node, msg)); 62 | } 63 | 64 | public static void finest(LogNode node, String msg) { 65 | logger.finest(join(node, msg)); 66 | } 67 | 68 | public static void severe(LogNode node, String msg) { 69 | logger.severe(join(node, msg)); 70 | } 71 | 72 | 73 | public static void warning(LogNode node, String msg) { 74 | logger.warning(join(node, msg)); 75 | } 76 | 77 | public static void log(LogNode node, Level level, String msg) { 78 | logger.log(level, join(node, msg)); 79 | } 80 | 81 | 82 | public static void debugPacket(Object packet) { 83 | 84 | Class clazz = packet.getClass(); 85 | System.out.print(clazz.getSimpleName()); 86 | Arrays.stream(clazz.getDeclaredFields()).forEach(field -> { 87 | field.setAccessible(true); 88 | StringBuilder sb = new StringBuilder(); 89 | sb.append(field.getType().getName()); 90 | sb.append(" "); 91 | sb.append(field.getName()); 92 | sb.append(" = "); 93 | try { 94 | Object obj = field.get(packet); 95 | sb.append(LogFormatter.toString(obj)); 96 | } catch (Exception e) { 97 | e.printStackTrace(); 98 | } 99 | System.out.println(sb.toString()); 100 | }); 101 | } 102 | 103 | } 104 | -------------------------------------------------------------------------------- /common/src/main/java/com/blzeecraft/virtualmenu/core/logger/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 和插件日志相关的类 3 | */ 4 | package com.blzeecraft.virtualmenu.core.logger; -------------------------------------------------------------------------------- /common/src/main/java/com/blzeecraft/virtualmenu/core/menu/ClickEvent.java: -------------------------------------------------------------------------------- 1 | package com.blzeecraft.virtualmenu.core.menu; 2 | 3 | import com.blzeecraft.virtualmenu.core.item.AbstractItem; 4 | import com.blzeecraft.virtualmenu.core.user.IUser; 5 | 6 | import lombok.Data; 7 | 8 | /** 9 | * 代表一个玩家点击菜单中的物品的事件 10 | * @author colors_wind 11 | * 12 | */ 13 | @Data 14 | public class ClickEvent { 15 | 16 | 17 | private final IUser user; 18 | private final ClickType type; 19 | private final int rawSlot; 20 | private final int slot; 21 | private final AbstractItem current; 22 | /** 23 | * 仅当玩家点击玩家背包的菜单这个选项才有效 24 | * 如果该选项为true,将会阻止玩家移动背包的物品 25 | */ 26 | private boolean cancel = true; 27 | 28 | 29 | 30 | 31 | 32 | } 33 | -------------------------------------------------------------------------------- /common/src/main/java/com/blzeecraft/virtualmenu/core/menu/ClickType.java: -------------------------------------------------------------------------------- 1 | package com.blzeecraft.virtualmenu.core.menu; 2 | 3 | /** 4 | * 玩家点击菜单的方式 5 | * @author colors_wind 6 | * 7 | */ 8 | public enum ClickType { 9 | LEFT, SHIFT_LEFT, RIGHT, SHIFT_RIGHT, WINDOW_BORDER_LEFT, WINDOW_BORDER_RIGHT, MIDDLE, NUMBER_KEY, DOUBLE_CLICK, DROP, CONTROL_DROP, CREATIVE, UNKNOWN; 10 | 11 | public boolean isKeyboardClick() { 12 | return this == NUMBER_KEY || this == DROP || this == CONTROL_DROP; 13 | } 14 | 15 | public boolean isCreativeAction() { 16 | return this == MIDDLE || this == CREATIVE; 17 | } 18 | 19 | public boolean isRightClick() { 20 | return this == RIGHT || this == SHIFT_RIGHT; 21 | } 22 | 23 | public boolean isLeftClick() { 24 | return this == LEFT || this == SHIFT_LEFT || this == DOUBLE_CLICK || this == CREATIVE; 25 | } 26 | 27 | public boolean isShiftClick() { 28 | return this == SHIFT_LEFT || this == SHIFT_RIGHT || this == CONTROL_DROP; 29 | } 30 | 31 | public boolean isBorderClick() { 32 | return this == WINDOW_BORDER_LEFT || this == WINDOW_BORDER_RIGHT; 33 | } 34 | } -------------------------------------------------------------------------------- /common/src/main/java/com/blzeecraft/virtualmenu/core/menu/EventHandler.java: -------------------------------------------------------------------------------- 1 | package com.blzeecraft.virtualmenu.core.menu; 2 | 3 | import java.util.Arrays; 4 | import java.util.function.Consumer; 5 | 6 | import com.blzeecraft.virtualmenu.core.action.IAction; 7 | import com.blzeecraft.virtualmenu.core.action.event.IconActionEvent; 8 | import com.blzeecraft.virtualmenu.core.condition.ICondition; 9 | import com.blzeecraft.virtualmenu.core.conf.ConfSerializable; 10 | import com.blzeecraft.virtualmenu.core.conf.StringSerializable; 11 | import com.blzeecraft.virtualmenu.core.conf.transition.StandardConf.EventConf; 12 | 13 | import lombok.AllArgsConstructor; 14 | 15 | @AllArgsConstructor 16 | public class EventHandler implements Consumer , ConfSerializable { 17 | protected final ICondition condition; 18 | protected final IAction action; 19 | 20 | 21 | @Override 22 | public void accept(IconActionEvent e) { 23 | if (condition.test(e)) { 24 | action.accept(e); 25 | } 26 | 27 | } 28 | 29 | 30 | @Override 31 | public EventConf serialize() { 32 | EventConf conf = new EventConf(); 33 | if (condition instanceof StringSerializable) { 34 | conf.condition = Arrays.asList(((StringSerializable) condition).seriablizeAll()); 35 | } 36 | if (action instanceof StringSerializable) { 37 | conf.action = Arrays.asList(((StringSerializable) action).seriablizeAll()); 38 | } 39 | return conf; 40 | } 41 | 42 | 43 | @Override 44 | public EventConf[] seriablizeAll() { 45 | return new EventConf[] {serialize()}; 46 | } 47 | 48 | } 49 | -------------------------------------------------------------------------------- /common/src/main/java/com/blzeecraft/virtualmenu/core/menu/EventType.java: -------------------------------------------------------------------------------- 1 | package com.blzeecraft.virtualmenu.core.menu; 2 | 3 | public enum EventType { 4 | 5 | OPEN_MENU, CLOSE_MENU, RIGHT_BORDER_CLICK, LEFT_BORDER_CLICK; 6 | 7 | } 8 | -------------------------------------------------------------------------------- /common/src/main/java/com/blzeecraft/virtualmenu/core/menu/IMenuType.java: -------------------------------------------------------------------------------- 1 | package com.blzeecraft.virtualmenu.core.menu; 2 | 3 | /** 4 | * 菜单类型的接口 5 | * @author colors_wind 6 | * 7 | */ 8 | public interface IMenuType { 9 | 10 | int getIndex(); 11 | 12 | String getType(); 13 | 14 | default int getLegacyIndex() { 15 | throw new UnsupportedOperationException(); 16 | } 17 | 18 | default String getMinecraftKey() { 19 | throw new UnsupportedOperationException(); 20 | } 21 | 22 | int getSize(); 23 | 24 | boolean isItemMenu(); 25 | 26 | 27 | 28 | } 29 | -------------------------------------------------------------------------------- /common/src/main/java/com/blzeecraft/virtualmenu/core/menu/PacketMenu.java: -------------------------------------------------------------------------------- 1 | package com.blzeecraft.virtualmenu.core.menu; 2 | 3 | import java.util.Map; 4 | import java.util.function.Consumer; 5 | 6 | import com.blzeecraft.virtualmenu.core.action.event.MenuEvent; 7 | import com.blzeecraft.virtualmenu.core.icon.Icon; 8 | import com.blzeecraft.virtualmenu.core.logger.LogNode; 9 | import com.blzeecraft.virtualmenu.core.logger.LoggerObject; 10 | import com.blzeecraft.virtualmenu.core.variable.UpdatePeriod; 11 | 12 | public class PacketMenu extends AbstractPacketMenu implements LoggerObject { 13 | protected final LogNode node; 14 | 15 | 16 | public PacketMenu(LogNode node, UpdatePeriod delay, String title, IMenuType type, Icon[] icons, 17 | Map> menuAction) { 18 | super(delay, title, type, icons, menuAction); 19 | this.node = node; 20 | } 21 | 22 | @Override 23 | public int getWindowId() { 24 | return 127; 25 | } 26 | 27 | @Override 28 | public LogNode getLogNode() { 29 | return node; 30 | } 31 | 32 | 33 | 34 | 35 | 36 | 37 | } 38 | -------------------------------------------------------------------------------- /common/src/main/java/com/blzeecraft/virtualmenu/core/menu/PacketMenuBuilder.java: -------------------------------------------------------------------------------- 1 | package com.blzeecraft.virtualmenu.core.menu; 2 | 3 | import java.util.Arrays; 4 | import java.util.EnumMap; 5 | import java.util.Map; 6 | import java.util.function.Consumer; 7 | import java.util.stream.IntStream; 8 | 9 | import com.blzeecraft.virtualmenu.core.action.ActionUtils; 10 | import com.blzeecraft.virtualmenu.core.action.event.MenuEvent; 11 | import com.blzeecraft.virtualmenu.core.icon.EmptyIcon; 12 | import com.blzeecraft.virtualmenu.core.icon.Icon; 13 | import com.blzeecraft.virtualmenu.core.logger.LogNode; 14 | import com.blzeecraft.virtualmenu.core.variable.UpdatePeriod; 15 | 16 | import lombok.NonNull; 17 | 18 | public class PacketMenuBuilder { 19 | 20 | protected final LogNode node; 21 | 22 | protected IMenuType type; 23 | protected Icon[] icons; 24 | protected Map> menuAction; 25 | protected UpdatePeriod updateDelay; 26 | protected String title; 27 | 28 | public PacketMenuBuilder(LogNode node) { 29 | this.node = node; 30 | this.icons = new Icon[0]; 31 | this.menuAction = new EnumMap<>(EventType.class); 32 | 33 | } 34 | 35 | public PacketMenuBuilder type(@NonNull IMenuType type) { 36 | this.type = type; 37 | this.icons = new Icon[type.getSize()]; 38 | return this; 39 | } 40 | 41 | public PacketMenuBuilder title(@NonNull String title) { 42 | this.title = title; 43 | return this; 44 | } 45 | 46 | public PacketMenuBuilder refresh(UpdatePeriod delay) { 47 | this.updateDelay = delay; 48 | return this; 49 | } 50 | 51 | public PacketMenuBuilder setIcon(int slot, Icon icon) { 52 | if (slot < icons.length) { 53 | icons[slot] = icon; 54 | return this; 55 | } 56 | throw new IllegalArgumentException("尝试访问菜单不存在的icon的位置, length=" + icons.length + " slot=" + slot); 57 | } 58 | 59 | public PacketMenuBuilder icon(Icon[] icons) { 60 | this.icons = icons; 61 | return this; 62 | } 63 | 64 | public PacketMenuBuilder addIcon(Icon icon) { 65 | for (int i = 0; i < icons.length; i++) { 66 | if (icons[i] == null) { 67 | icons[i] = icon; 68 | return this; 69 | } 70 | } 71 | throw new IllegalArgumentException("该菜单已满,无法继续添加icon"); 72 | } 73 | 74 | public PacketMenuBuilder addEventHandler(@NonNull EventType type, @NonNull Consumer handler) { 75 | menuAction.put(type, handler); 76 | return this; 77 | } 78 | 79 | public PacketMenu build() { 80 | // fill 81 | if (icons.length != type.getSize()) { 82 | this.icons = new Icon[type.getSize()]; 83 | System.arraycopy(icons, 0, this.icons, 0, this.icons.length); 84 | } 85 | IntStream.range(0, this.type.getSize()).forEach(i -> { 86 | if (this.icons[i] == null) { 87 | icons[i] = EmptyIcon.INSTANCE; 88 | } 89 | }); 90 | Arrays.stream(EventType.values()).forEach(eventType -> menuAction.putIfAbsent(eventType, ActionUtils.EMPTY_ACTION)); 91 | return new PacketMenu(node, updateDelay, title, type, icons, menuAction); 92 | } 93 | 94 | } 95 | -------------------------------------------------------------------------------- /common/src/main/java/com/blzeecraft/virtualmenu/core/menu/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 和菜单相关的类 3 | */ 4 | package com.blzeecraft.virtualmenu.core.menu; -------------------------------------------------------------------------------- /common/src/main/java/com/blzeecraft/virtualmenu/core/packet/AbstractPacket.java: -------------------------------------------------------------------------------- 1 | package com.blzeecraft.virtualmenu.core.packet; 2 | 3 | import com.blzeecraft.virtualmenu.core.IWrappedObject; 4 | 5 | import lombok.AccessLevel; 6 | import lombok.AllArgsConstructor; 7 | import lombok.ToString; 8 | 9 | /** 10 | * 代表一个 Packet. 11 | * 12 | * @param 被封装的关于Window的 Packet 的类型 13 | * @author colors_wind 14 | * @date 2020-02-12 15 | */ 16 | @ToString 17 | @AllArgsConstructor(access = AccessLevel.PROTECTED) 18 | public abstract class AbstractPacket implements IWrappedObject { 19 | protected final T packet; 20 | 21 | 22 | @Override 23 | public T getHandle() { 24 | return packet; 25 | } 26 | 27 | } 28 | -------------------------------------------------------------------------------- /common/src/main/java/com/blzeecraft/virtualmenu/core/packet/AbstractPacketInCloseWindow.java: -------------------------------------------------------------------------------- 1 | package com.blzeecraft.virtualmenu.core.packet; 2 | 3 | import lombok.Getter; 4 | import lombok.ToString; 5 | 6 | /** 7 | * 代表玩家关闭菜单时客户端发送给服务端的 Packet. 8 | * @author colors_wind 9 | * 10 | */ 11 | @Getter 12 | @ToString(callSuper = true) 13 | public abstract class AbstractPacketInCloseWindow extends AbstractWindowPacket { 14 | 15 | public AbstractPacketInCloseWindow(T packet) { 16 | super(packet); 17 | } 18 | 19 | 20 | } 21 | -------------------------------------------------------------------------------- /common/src/main/java/com/blzeecraft/virtualmenu/core/packet/AbstractPacketInWindowClick.java: -------------------------------------------------------------------------------- 1 | package com.blzeecraft.virtualmenu.core.packet; 2 | 3 | 4 | import com.blzeecraft.virtualmenu.core.item.AbstractItem; 5 | import com.blzeecraft.virtualmenu.core.menu.ClickType; 6 | 7 | import lombok.ToString; 8 | 9 | /** 10 | * 代表玩家点击菜单时客户端发送给服务端的 Packet. 11 | * @author colors_wind 12 | * 13 | */ 14 | @ToString(callSuper = true) 15 | public abstract class AbstractPacketInWindowClick extends AbstractWindowPacket { 16 | 17 | 18 | public AbstractPacketInWindowClick(T handle) { 19 | super(handle); 20 | } 21 | 22 | public abstract void setRawSlot(int slot); 23 | public abstract int getRawSlot(); 24 | 25 | public abstract void setClickMode(ClickMode mode); 26 | public abstract ClickMode getClickMode(); 27 | 28 | public abstract void setButton(int button); 29 | public abstract int getButton(); 30 | 31 | public abstract void setClickedItem(AbstractItem item); 32 | public abstract AbstractItem getClickedItem(); 33 | 34 | public ClickType getClickType(){ 35 | int button = getButton(); 36 | //maybe you need to check slot before invoke this method 37 | int slot = getRawSlot(); 38 | switch(getClickMode()) { 39 | case PICKUP: 40 | if (button == 0) { 41 | return ClickType.LEFT; 42 | } else if (button == 1) { 43 | return ClickType.RIGHT; 44 | } 45 | break; 46 | case QUICK_MOVE: 47 | if (button == 0) { 48 | return ClickType.SHIFT_LEFT; 49 | } else if (button == 1) { 50 | return ClickType.SHIFT_RIGHT; 51 | } 52 | break; 53 | case SWAP: 54 | return ClickType.NUMBER_KEY; 55 | case CLONE: 56 | return ClickType.MIDDLE; 57 | case THROW: 58 | if (slot >= 0) { 59 | if (button == 0) { 60 | return ClickType.DROP; 61 | } else if (button == 1) { 62 | return ClickType.CONTROL_DROP; 63 | } 64 | } else if (slot == -999) { 65 | if (button == 0) { 66 | return ClickType.WINDOW_BORDER_LEFT; 67 | } else if (button == 1) { 68 | return ClickType.WINDOW_BORDER_RIGHT; 69 | } 70 | } 71 | break; 72 | case QUICK_CRAFT: 73 | if (slot >= 0) { 74 | if (button == 1) { 75 | return ClickType.LEFT; 76 | } else if (button == 5) { 77 | return ClickType.RIGHT; 78 | } 79 | } else if (slot == -999) { 80 | switch(button) { 81 | case 0: 82 | case 1: 83 | case 2: 84 | return ClickType.LEFT; 85 | case 4: 86 | case 5: 87 | case 6: 88 | return ClickType.RIGHT; 89 | case 8: 90 | case 9: 91 | case 10: 92 | return ClickType.MIDDLE; 93 | } 94 | } 95 | case PICKUP_ALL: 96 | return ClickType.DOUBLE_CLICK; 97 | } 98 | return ClickType.UNKNOWN; 99 | } 100 | 101 | } 102 | -------------------------------------------------------------------------------- /common/src/main/java/com/blzeecraft/virtualmenu/core/packet/AbstractPacketOutCloseWindow.java: -------------------------------------------------------------------------------- 1 | package com.blzeecraft.virtualmenu.core.packet; 2 | 3 | import lombok.Getter; 4 | import lombok.ToString; 5 | 6 | /** 7 | * 代表使玩家关闭菜单时服务端发送给客户端的 Packet. 8 | * 9 | * @author colors_wind 10 | * 11 | */ 12 | @Getter 13 | @ToString(callSuper = true) 14 | public abstract class AbstractPacketOutCloseWindow extends AbstractWindowPacket { 15 | 16 | public AbstractPacketOutCloseWindow(T packet) { 17 | super(packet); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /common/src/main/java/com/blzeecraft/virtualmenu/core/packet/AbstractPacketOutSetSlot.java: -------------------------------------------------------------------------------- 1 | package com.blzeecraft.virtualmenu.core.packet; 2 | 3 | import com.blzeecraft.virtualmenu.core.item.AbstractItem; 4 | 5 | import lombok.ToString; 6 | 7 | /** 8 | * 代表设置菜单单个 Slot 时服务端发送给客户端的 Packet. 9 | * 10 | * @author colors_wind 11 | * 12 | */ 13 | 14 | @ToString(callSuper = true) 15 | public abstract class AbstractPacketOutSetSlot extends AbstractWindowPacket { 16 | 17 | public AbstractPacketOutSetSlot(T handle) { 18 | super(handle); 19 | } 20 | 21 | public abstract void setSlot(int slot); 22 | 23 | public abstract int getSlot(); 24 | 25 | public abstract void setItem(AbstractItem item); 26 | 27 | public abstract AbstractItem getItem(); 28 | 29 | public abstract void setRawItem(Object item); 30 | 31 | public abstract Object getRawItem(); 32 | 33 | } 34 | -------------------------------------------------------------------------------- /common/src/main/java/com/blzeecraft/virtualmenu/core/packet/AbstractPacketOutWindowItems.java: -------------------------------------------------------------------------------- 1 | package com.blzeecraft.virtualmenu.core.packet; 2 | 3 | import com.blzeecraft.virtualmenu.core.item.AbstractItem; 4 | 5 | import lombok.ToString; 6 | 7 | /** 8 | * 代表更新菜单 Slot 时服务端发送给客户端的 Packet. 9 | * @author colors_wind 10 | * 11 | */ 12 | @ToString(callSuper = true) 13 | public abstract class AbstractPacketOutWindowItems extends AbstractWindowPacket { 14 | 15 | public AbstractPacketOutWindowItems(T handle) { 16 | super(handle); 17 | } 18 | 19 | public abstract void setItems(AbstractItem[] items); 20 | 21 | public abstract void setRawItems(Object[] items); 22 | 23 | public abstract AbstractItem[] getItems(); 24 | 25 | public abstract Object[] getRawItems(); 26 | 27 | } 28 | -------------------------------------------------------------------------------- /common/src/main/java/com/blzeecraft/virtualmenu/core/packet/AbstractPacketOutWindowOpen.java: -------------------------------------------------------------------------------- 1 | package com.blzeecraft.virtualmenu.core.packet; 2 | 3 | import com.blzeecraft.virtualmenu.core.menu.IMenuType; 4 | 5 | import lombok.ToString; 6 | 7 | /** 8 | * 代表使玩家打开菜单时服务端发给客户端的 Packet. 9 | * 10 | * @author colors_wind 11 | * 12 | */ 13 | @ToString(callSuper = true) 14 | public abstract class AbstractPacketOutWindowOpen extends AbstractWindowPacket { 15 | 16 | public AbstractPacketOutWindowOpen(T handle) { 17 | super(handle); 18 | } 19 | 20 | public abstract void setTitle(String title); 21 | 22 | public abstract String getTitle(); 23 | 24 | public abstract void setMenuType(IMenuType menuType); 25 | 26 | public abstract IMenuType getMenuType(); 27 | 28 | } 29 | -------------------------------------------------------------------------------- /common/src/main/java/com/blzeecraft/virtualmenu/core/packet/AbstractWindowPacket.java: -------------------------------------------------------------------------------- 1 | package com.blzeecraft.virtualmenu.core.packet; 2 | 3 | import lombok.ToString; 4 | 5 | /** 6 | * 代表一个有关window的 Packet. 7 | * 8 | * @author colors_wind 9 | */ 10 | @ToString 11 | public abstract class AbstractWindowPacket extends AbstractPacket { 12 | 13 | protected AbstractWindowPacket(T packet) { 14 | super(packet); 15 | } 16 | 17 | public abstract void setWindowId(int windowId); 18 | 19 | public abstract int getWindowId(); 20 | 21 | 22 | 23 | } 24 | -------------------------------------------------------------------------------- /common/src/main/java/com/blzeecraft/virtualmenu/core/packet/ClickMode.java: -------------------------------------------------------------------------------- 1 | package com.blzeecraft.virtualmenu.core.packet; 2 | 3 | /** 4 | * 玩家点击菜单中物品的方式, 该枚举仅用于解析数据包. 5 | * @author colors_wind 6 | * 7 | */ 8 | public enum ClickMode { 9 | PICKUP, 10 | QUICK_MOVE, 11 | SWAP, 12 | CLONE, 13 | THROW, 14 | QUICK_CRAFT, 15 | PICKUP_ALL; 16 | } 17 | 18 | -------------------------------------------------------------------------------- /common/src/main/java/com/blzeecraft/virtualmenu/core/packet/IPacketAdapter.java: -------------------------------------------------------------------------------- 1 | package com.blzeecraft.virtualmenu.core.packet; 2 | 3 | import java.lang.reflect.InvocationTargetException; 4 | 5 | import com.blzeecraft.virtualmenu.core.VirtualMenu; 6 | import com.blzeecraft.virtualmenu.core.logger.PluginLogger; 7 | import com.blzeecraft.virtualmenu.core.user.IUser; 8 | import com.blzeecraft.virtualmenu.core.user.UserManager; 9 | 10 | /** 11 | * Packet 适配器, 用于处理发送 Packet 逻辑. 12 | * 接收 Packet 的方法没有在这里声明, 需要调用 {@link UserManager} 的方法进行处理. 13 | * @author colors_wind 14 | * @see {@link UserManager#handleEvent(PacketMenuClickEvent)} 15 | * @see {@link UserManager#handleEvent(PacketMenuCloseEvent)} 16 | * 17 | */ 18 | public interface IPacketAdapter { 19 | 20 | 21 | AbstractPacketOutCloseWindow createPacketCloseWindow(); 22 | 23 | AbstractPacketOutWindowOpen createPacketWindowOpen(); 24 | 25 | AbstractPacketOutSetSlot createPacketSetSlot(); 26 | 27 | AbstractPacketOutWindowItems createPacketWindowItems(); 28 | 29 | void sendServerPacket(IUser user, AbstractWindowPacket packet) throws InvocationTargetException; 30 | 31 | 32 | default void sendServerPacketWrap(IUser user, AbstractWindowPacket packet) { 33 | VirtualMenu.getScheduler().runTaskGuaranteePrimaryThread(() -> { 34 | try { 35 | sendServerPacket(user, packet); 36 | } catch (InvocationTargetException e) { 37 | PluginLogger.warning(UserManager.LOG_NODE, "尝试向玩家发送 Packet 时出现异常."); 38 | } 39 | }); 40 | } 41 | 42 | default void sendServerPacketWrap(IUser user, AbstractWindowPacket packet1, AbstractWindowPacket packet2) { 43 | VirtualMenu.getScheduler().runTaskGuaranteePrimaryThread(() -> { 44 | try { 45 | sendServerPacket(user, packet1); 46 | sendServerPacket(user, packet2); 47 | } catch (InvocationTargetException e) { 48 | PluginLogger.warning(UserManager.LOG_NODE, "尝试向玩家发送 Packet 时出现异常."); 49 | } 50 | }); 51 | 52 | } 53 | 54 | String getVersion(); 55 | 56 | } 57 | -------------------------------------------------------------------------------- /common/src/main/java/com/blzeecraft/virtualmenu/core/packet/PacketMenuClickEvent.java: -------------------------------------------------------------------------------- 1 | package com.blzeecraft.virtualmenu.core.packet; 2 | 3 | import com.blzeecraft.virtualmenu.core.action.event.IconActionEvent; 4 | import com.blzeecraft.virtualmenu.core.user.IUser; 5 | import com.blzeecraft.virtualmenu.core.user.UserSession; 6 | 7 | import lombok.Getter; 8 | import lombok.ToString; 9 | 10 | /** 11 | * 代表 {@link IUser} 点击菜单的事件. 12 | * @author colors_wind 13 | * @date 2020-02-10 14 | */ 15 | @Getter 16 | @ToString(callSuper = true) 17 | public class PacketMenuClickEvent extends PacketMenuEvent { 18 | 19 | protected final IconActionEvent iconEvent; 20 | 21 | public PacketMenuClickEvent(UserSession session, IconActionEvent event) { 22 | super(session); 23 | this.iconEvent = event; 24 | } 25 | 26 | 27 | 28 | 29 | 30 | } 31 | -------------------------------------------------------------------------------- /common/src/main/java/com/blzeecraft/virtualmenu/core/packet/PacketMenuCloseEvent.java: -------------------------------------------------------------------------------- 1 | package com.blzeecraft.virtualmenu.core.packet; 2 | 3 | import com.blzeecraft.virtualmenu.core.user.IUser; 4 | import com.blzeecraft.virtualmenu.core.user.UserSession; 5 | 6 | import lombok.Getter; 7 | import lombok.ToString; 8 | 9 | /** 10 | * 代表 {@link IUser} 关闭菜单的事件. 11 | * 即使是因为退出游戏而关闭菜单,也应该触发这个事件. 12 | * 13 | * @see {@link #isQuitGame()} 14 | * @author colors_wind 15 | * @date 2020-02-10 16 | */ 17 | @Getter 18 | @ToString(callSuper = true) 19 | public class PacketMenuCloseEvent extends PacketMenuEvent { 20 | protected final boolean quitGame; 21 | 22 | public PacketMenuCloseEvent(UserSession session, boolean quitGame) { 23 | super(session); 24 | this.quitGame = quitGame; 25 | } 26 | 27 | 28 | } 29 | -------------------------------------------------------------------------------- /common/src/main/java/com/blzeecraft/virtualmenu/core/packet/PacketMenuEvent.java: -------------------------------------------------------------------------------- 1 | package com.blzeecraft.virtualmenu.core.packet; 2 | 3 | import com.blzeecraft.virtualmenu.core.user.IUser; 4 | import com.blzeecraft.virtualmenu.core.user.UserSession; 5 | 6 | import lombok.Getter; 7 | import lombok.RequiredArgsConstructor; 8 | import lombok.ToString; 9 | 10 | /** 11 | * 代表一个由 {@link IUser} 触发的菜单事件. 12 | * @author colors_wind 13 | * @date 2020-02-10 14 | */ 15 | @Getter 16 | @ToString 17 | @RequiredArgsConstructor 18 | public abstract class PacketMenuEvent { 19 | protected final UserSession session; 20 | 21 | 22 | 23 | 24 | } 25 | -------------------------------------------------------------------------------- /common/src/main/java/com/blzeecraft/virtualmenu/core/packet/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 和 Packet 相关的类 3 | */ 4 | package com.blzeecraft.virtualmenu.core.packet; -------------------------------------------------------------------------------- /common/src/main/java/com/blzeecraft/virtualmenu/core/schedule/AbstractTask.java: -------------------------------------------------------------------------------- 1 | package com.blzeecraft.virtualmenu.core.schedule; 2 | 3 | import com.blzeecraft.virtualmenu.core.IWrappedObject; 4 | 5 | public abstract class AbstractTask implements IWrappedObject { 6 | 7 | protected final T handle; 8 | 9 | public AbstractTask(T handle) { 10 | this.handle = handle; 11 | } 12 | 13 | @Override 14 | public T getHandle() { 15 | return handle; 16 | } 17 | 18 | public abstract boolean isRunning(); 19 | 20 | public abstract boolean isAsync(); 21 | 22 | public abstract void cancel(); 23 | 24 | } 25 | -------------------------------------------------------------------------------- /common/src/main/java/com/blzeecraft/virtualmenu/core/schedule/IScheduler.java: -------------------------------------------------------------------------------- 1 | package com.blzeecraft.virtualmenu.core.schedule; 2 | 3 | public interface IScheduler { 4 | 5 | AbstractTask runTaskLater(Runnable task, long delay); 6 | 7 | AbstractTask runTaskGuaranteePrimaryThread(Runnable task); 8 | 9 | AbstractTask runTaskAsync(Runnable task); 10 | 11 | AbstractTask runTaskTimer(Runnable task, long delay, long period); 12 | 13 | } 14 | -------------------------------------------------------------------------------- /common/src/main/java/com/blzeecraft/virtualmenu/core/schedule/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 有关计划任务相关类. 3 | */ 4 | package com.blzeecraft.virtualmenu.core.schedule; -------------------------------------------------------------------------------- /common/src/main/java/com/blzeecraft/virtualmenu/core/user/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 包含有关用户,控制台相关的类. 3 | * @author colors_wind 4 | * @date 2020-02-14 5 | */ 6 | package com.blzeecraft.virtualmenu.core.user; -------------------------------------------------------------------------------- /common/src/main/java/com/blzeecraft/virtualmenu/core/variable/EmptyVariableAdapter.java: -------------------------------------------------------------------------------- 1 | package com.blzeecraft.virtualmenu.core.variable; 2 | 3 | import java.util.List; 4 | 5 | import com.blzeecraft.virtualmenu.core.user.IUser; 6 | 7 | public class EmptyVariableAdapter implements IVariableAdapter { 8 | 9 | @Override 10 | public String replace(IUser user, String line) { 11 | return line; 12 | } 13 | 14 | @Override 15 | public List replace(IUser user, List lines) { 16 | return lines; 17 | } 18 | 19 | @Override 20 | public boolean containsVariable(String line) { 21 | return false; 22 | } 23 | 24 | @Override 25 | public boolean containsVariable(List lines) { 26 | return false; 27 | } 28 | 29 | } 30 | -------------------------------------------------------------------------------- /common/src/main/java/com/blzeecraft/virtualmenu/core/variable/IVariableAdapter.java: -------------------------------------------------------------------------------- 1 | package com.blzeecraft.virtualmenu.core.variable; 2 | 3 | import java.util.List; 4 | 5 | import com.blzeecraft.virtualmenu.core.user.IUser; 6 | 7 | public interface IVariableAdapter { 8 | 9 | /** 10 | * 更新变量 11 | * @param user 12 | * @param line 13 | * @return 14 | */ 15 | String replace(IUser user, String line); 16 | 17 | /** 18 | * 更新变量 19 | * @param user 20 | * @param lines 21 | * @return 22 | */ 23 | List replace(IUser user, List lines); 24 | 25 | /** 26 | * 判断是否包含变量 27 | * @param line 28 | * @return 29 | */ 30 | boolean containsVariable(String line); 31 | 32 | /** 33 | * 判断是否包含变量 34 | * @param line 35 | * @return 36 | */ 37 | boolean containsVariable(List lines); 38 | } 39 | -------------------------------------------------------------------------------- /common/src/main/java/com/blzeecraft/virtualmenu/core/variable/UpdatePeriod.java: -------------------------------------------------------------------------------- 1 | package com.blzeecraft.virtualmenu.core.variable; 2 | 3 | import java.util.Arrays; 4 | import java.util.Optional; 5 | 6 | import lombok.Getter; 7 | import lombok.ToString; 8 | 9 | /** 10 | * 用于标记 {@link com.blzeecraft.virtualmenu.icon.Icon} 变量的更新间隔. 11 | * 12 | * @author colors_wind 13 | * @date 2020-02-10 14 | */ 15 | @ToString 16 | public enum UpdatePeriod { 17 | 18 | FAST(5L), NORMAL(10L), SLOW(20L), VERY_SLOT(50L), NEVER(-1L); 19 | 20 | @Getter 21 | private final long period; 22 | 23 | private UpdatePeriod(long period) { 24 | this.period = period; 25 | } 26 | 27 | public boolean autoUpdate() { 28 | return this.period > 0; 29 | } 30 | 31 | public static Optional get(String refresh) { 32 | try { 33 | return Optional.of(valueOf(refresh)); 34 | } catch (IllegalArgumentException | NullPointerException e) { 35 | } 36 | return Optional.empty(); 37 | } 38 | 39 | 40 | public static Optional saftyGet(int refresh) { 41 | if (refresh <= 0) { 42 | return Optional.of(NEVER); 43 | } 44 | return Arrays.stream(values()).filter(ud -> ud.period <= refresh).findFirst(); 45 | } 46 | 47 | public static String typesToString() { 48 | return Arrays.stream(values()) 49 | .map(updateDelay -> new StringBuilder(updateDelay.name()).append("(") 50 | .append((String.format("%.2f", ((double) updateDelay.period) / 20))).append("s)").toString()) 51 | .reduce((s1, s2) -> String.join(", ", s1, s2)).orElse("null"); 52 | } 53 | 54 | } 55 | -------------------------------------------------------------------------------- /common/src/main/java/com/blzeecraft/virtualmenu/core/variable/VariableUpdater.java: -------------------------------------------------------------------------------- 1 | package com.blzeecraft.virtualmenu.core.variable; 2 | 3 | import java.lang.reflect.InvocationTargetException; 4 | import java.util.Arrays; 5 | import java.util.EnumMap; 6 | import java.util.HashSet; 7 | import java.util.Map; 8 | import java.util.Set; 9 | 10 | import com.blzeecraft.virtualmenu.core.VirtualMenu; 11 | import com.blzeecraft.virtualmenu.core.logger.LogNode; 12 | import com.blzeecraft.virtualmenu.core.logger.PluginLogger; 13 | import com.blzeecraft.virtualmenu.core.menu.IPacketMenu; 14 | import com.blzeecraft.virtualmenu.core.packet.IPacketAdapter; 15 | import com.blzeecraft.virtualmenu.core.schedule.AbstractTask; 16 | import com.blzeecraft.virtualmenu.core.user.UserSession; 17 | 18 | import lombok.val; 19 | 20 | public class VariableUpdater implements Runnable { 21 | public static LogNode LOG_NODE = LogNode.of("#VariableUpdater"); 22 | private final UpdatePeriod delay; 23 | private final Set sessions; 24 | private final IPacketAdapter packetAdapter; 25 | private AbstractTask task; 26 | 27 | public VariableUpdater(UpdatePeriod delay) { 28 | this.delay = delay; 29 | sessions = new HashSet<>(); 30 | this.packetAdapter = VirtualMenu.getPacketAdapter(); 31 | } 32 | 33 | @Override 34 | public void run() { 35 | for (val session : sessions) { 36 | IPacketMenu menu = session.getMenu(); 37 | Object[] rawItems = menu.viewRawItems(session); 38 | session.updateCachePacketMenuRawItems(rawItems); 39 | val packet = session.createPacketWindowItemsForMenu(); 40 | try { 41 | packetAdapter.sendServerPacket(session.getUser(), packet); 42 | } catch (InvocationTargetException e) { 43 | PluginLogger.warning(LOG_NODE, "发送更新菜单 Item 的 Packet 错误."); 44 | e.printStackTrace(); 45 | } 46 | } 47 | } 48 | 49 | public VariableUpdater start() { 50 | task = VirtualMenu.getScheduler().runTaskTimer(this, delay.getPeriod() / 2, delay.getPeriod()); 51 | return this; 52 | } 53 | 54 | public void stop() { 55 | if (task != null && task.isRunning()) { 56 | task.cancel(); 57 | } 58 | } 59 | 60 | 61 | public static Map UPDATER_MAP = new EnumMap<>(UpdatePeriod.class); 62 | 63 | public static void startUpdate() { 64 | if (UPDATER_MAP.size() != 0) { 65 | PluginLogger.warning(LOG_NODE, "刷新菜单任务已经开始. 无法重复开始."); 66 | throw new IllegalArgumentException(); 67 | } 68 | Arrays.stream(UpdatePeriod.values()).filter(updateDelay -> updateDelay.getPeriod() > 0).forEach(delay -> { 69 | val updater = new VariableUpdater(delay).start(); 70 | UPDATER_MAP.put(delay, updater); 71 | }); 72 | } 73 | 74 | public static void stopUpdate() { 75 | if (UPDATER_MAP.size() == 0) { 76 | PluginLogger.warning(LOG_NODE, "刷新菜单任务未开始. 不能停止."); 77 | throw new IllegalArgumentException(); 78 | } 79 | UPDATER_MAP.values().forEach(VariableUpdater::stop); 80 | UPDATER_MAP.clear(); 81 | } 82 | 83 | public static void addUpdateTask(UserSession session) { 84 | val menu = session.getMenu(); 85 | UPDATER_MAP.get(menu.getUpdateDelay()).sessions.add(session); 86 | } 87 | 88 | public static void removeUpdateTask(UserSession session) { 89 | val menu = session.getMenu(); 90 | UPDATER_MAP.get(menu.getUpdateDelay()).sessions.remove(session); 91 | } 92 | 93 | 94 | } 95 | -------------------------------------------------------------------------------- /common/src/main/java/com/blzeecraft/virtualmenu/core/variable/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 包含插件变量相关的类 3 | */ 4 | package com.blzeecraft.virtualmenu.core.variable; -------------------------------------------------------------------------------- /common/src/main/resources/example.yml: -------------------------------------------------------------------------------- 1 | # 菜单全局设置 2 | global: 3 | # 【必须】菜单名称 4 | title: '&9&lVirtualMenu测试菜单' 5 | 6 | # 【必须】菜单的类型 7 | # 推荐使用只有储存功能的GUI类型,如 8 | # GENERIC_9X1,GENERIC_9X2,GENERIC_9X3,GENERIC_9X4 9 | # GENERIC_9X5,GENERIC_9X6,GENERIC_3X3,HOPPER(5*1) 10 | # 特殊类型不推荐使用(但也许可以正常工作) 11 | # https://hub.spigotmc.org/javadocs/bukkit/org/bukkit/event/inventory/InventoryType.html 12 | type: GENERIC_9X1 13 | 14 | # 【可选】刷新变量间隔,单位是tick 15 | # 此选项与动态菜单无关 16 | refresh: NORMAL 17 | 18 | # 【可选】菜单绑定设置 19 | bound: 20 | - bounditem{id=NETHER_STAR,action=RIGHT_SHIFT-DROP_ITEM} 21 | - boundcommand{command=mc,inject=true,listen=true} 22 | 23 | # 有关整个菜单的事件 24 | events: 25 | # 【可选】左击菜单的边界外 26 | # 支持condition和action标签,下同 27 | LEFT_BORDER_CLICK: 28 | condition: [] 29 | action: 30 | - tell{s=点击左击边界外\,关闭菜单} 31 | - close 32 | 33 | 34 | # 【可选】右击菜单的边界外 35 | RIGHT_BORDER_CLICK: 36 | action: 37 | - tell{s=点击右击边界外\,关闭菜单} 38 | - close 39 | 40 | 41 | # 【可选】玩家打开菜单 42 | # 支持condition和action标签,下同 43 | # 注:下面给予经验的使玩家可以看到slot3的物品 44 | OPEN_MENU: 45 | action: 46 | - 'console{command=minecraft:xp 20L }' 47 | - tell{s=打开菜单(此项可在events.open配置)} 48 | 49 | 50 | # 【可选】玩家关闭菜单时 51 | CLOSE_MENU: 52 | action: 53 | - console{command=say 玩家关闭了菜单(此项可在events.close配置)} 54 | 55 | 56 | # 下面是菜单里单个物品的设置 57 | icons: 58 | slot0: 59 | name: '&a&l物品格式示例' 60 | id: 'LEATHER_CHESTPLATE:12' 61 | lore: 62 | - '化繁为简,displayname和lore直接设置' 63 | - '其他itemmeta用序列化后的nbt表示' 64 | - 'displayname和lore会覆盖nbt的设置' 65 | amount: 1 66 | nbt: "CgAACgAHZGlzcGxheQMABWNvbG9yADNMsgAA\r\n" 67 | slot: 0 68 | 69 | slot1: 70 | name: '&c&l物品位置示例' 71 | id: 'ENCHANTED_BOOK:0' 72 | lore: 73 | - '同时支持x,y坐标的定位方式(仅限于箱子菜单)' 74 | - '和slot的定位方式,slot会覆盖x,y的设置' 75 | - '以下两种定位方式的等价的' 76 | position-x: 2 77 | position-y: 1 78 | slot: 1 79 | 80 | slot2: 81 | name: '&d&l动作触发实例' 82 | id: SAND 83 | condition: 84 | - 'checkpermission{perm=virtualmenu.admin,msg=权限不足\,你不能左击这个图标,click=RIGHT-SHIFT_RIGHT}' 85 | - 'checkeconomy{amount=1,take=true,msg=最少必须有一块钱才能点击这个图标}' 86 | action: 87 | - 'tell{s=左击,click=LEFT}' 88 | - 'tell{s=右击,click=RIGHT}' 89 | - 'tell{s=SHIFT左击,click=SHIFT_LEFT}' 90 | - 'tell{s=SHIFT右击,click=SHIFT_RIGHT}' 91 | lore: 92 | - '条件和动作都会从上到下依次执行' 93 | - '所有条件必须都满足才会开始执行动作' 94 | - 'click=?标签用于检查的点击方式' 95 | slot: 2 96 | 97 | slot3-1: 98 | name: '&b&l多图标覆盖实例-1' 99 | id: ICE 100 | amount: 1 101 | view-condition: 102 | - 'checklevel{level=10,take=false}' 103 | priority: 10 104 | lore: 105 | - '你能看到这个图标说明你的等级区间10-999' 106 | slot: 3 107 | 108 | slot3-2: 109 | name: '&b&l多标签覆盖实例-2' 110 | id: ICE 111 | amount: 64 112 | view-condition: 113 | - 'checklevel{level=10,take=false}' 114 | priority: 1000 115 | lore: 116 | - '你能看到这个图标说明你的等级在1000级以上' 117 | slot: 3 118 | 119 | slot4: 120 | name: '&6&l变量实例' 121 | id: 'ARROW:0' 122 | amount: 1 123 | lore: 124 | - '是否AFK: %essentials_afk%' 125 | - '如果不能正常显示,请检查' 126 | - '1.确保按照了PlaceHolderAPI和' 127 | - 'Essentials(因为papi的附件需要)' 128 | - '2.输入/papi ecloud download essentials下载papi的附件' 129 | - '3.将菜单文件PLACEHOLDERAPI改成true' 130 | - '4.输入/vm reload 重载插件' 131 | variable: 132 | - PlaceholderAPI 133 | slot: 4 -------------------------------------------------------------------------------- /jar/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | com.blzeecraft.virtualmenu 7 | virtualmenu-parent 8 | 2.0.0-SNAPSHOT 9 | 10 | 4.0.0 11 | 12 | virtualmenu-jar 13 | 14 | 15 | VirtualMenu-${project.version} 16 | clean install 17 | 18 | 19 | . 20 | false 21 | ../ 22 | 23 | LICENSE 24 | 25 | 26 | 27 | 28 | 29 | org.apache.maven.plugins 30 | maven-shade-plugin 31 | 2.4.3 32 | 33 | false 34 | false 35 | 36 | 37 | 38 | package 39 | 40 | shade 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | com.blzeecraft.virtualmenu 51 | virtualmenu-common 52 | ${project.parent.version} 53 | 54 | 55 | com.blzeecraft.virtualmenu 56 | virtualmenu-bukkit 57 | ${project.parent.version} 58 | 59 | 60 | 61 | -------------------------------------------------------------------------------- /jar/target/maven-archiver/pom.properties: -------------------------------------------------------------------------------- 1 | #Generated by Maven 2 | #Fri Feb 28 17:53:08 CST 2020 3 | version=1.0.0-SNAPSHOT 4 | groupId=com.blzeecraft.virtualmenu 5 | artifactId=virtualmenu-jar 6 | --------------------------------------------------------------------------------