diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..a12d5ec --- /dev/null +++ b/.travis.yml @@ -0,0 +1,4 @@ +language: java +sudo: false +jdk: oraclejdk8 +install: mvn clean install package \ No newline at end of file diff --git a/README.md b/README.md index ef55dcb..91deb72 100644 --- a/README.md +++ b/README.md @@ -1,19 +1,32 @@ -# MayCore -一个基于BukkitAPI开发的类库 +# May Common Library (MCLib) [![Build status](https://ci.appveyor.com/api/projects/status/fi528yanx76w25qe?svg=true)](https://ci.appveyor.com/project/602723113/may-common-library) [![Build Status](https://travis-ci.org/602723113/May-Common-Library.svg?branch=dev)](https://travis-ci.org/602723113/May-Common-Library) [![Codacy Badge](https://api.codacy.com/project/badge/Grade/e8b69ada84954b13a415981844a7e376)](https://www.codacy.com/app/602723113/May-Common-Library?utm_source=github.com&utm_medium=referral&utm_content=602723113/May-Common-Library&utm_campaign=Badge_Grade) +> A library based on BukkitAPI development, and give developer some useful feature -## 它能为你做些什么? -##### 在MayCore中你可以享受以下内容 -- 简易的构造Title -- 简易的构造ActionBar -- 简易的构造Tellraw -- 简易的构造Book -- [API]简易的使用1.12的新特性Advancement -- 已封装好的BungeeCordAPI -- 封装了许许多多的Util +[Wiki](https://github.com/602723113/May-Common-Library/wiki) +### README Languages +- English +- [Chinese | 中文](https://github.com/602723113/May-Common-Library/blob/dev/README_zh_CN.md) -## 编译 -本项目使用 maven 进行管理 -构建请使用 -''' +### Feature +> In _MCLib_ you can enjoy the following features +- Easy to use NMS +- Easy to use NBT +- Easy to use Tellraw +- Easy to use ServerPing +- Easy to use Book +- Easy to use 1.12 new features **Advancement** +- Easy to use Pager +- Easy to use Reflection +- A lot of Utils +- ... + +### License + - This project follows the MIT protocol + +### Compile +This project uses Maven for management +Construction please use command +``` mvn clean install package -''' +``` + +**Like this project? Why not put it a star** diff --git a/README_zh_CN.md b/README_zh_CN.md new file mode 100644 index 0000000..4d36977 --- /dev/null +++ b/README_zh_CN.md @@ -0,0 +1,28 @@ +# May Common Library (MCLib) [![Build status](https://ci.appveyor.com/api/projects/status/fi528yanx76w25qe?svg=true)](https://ci.appveyor.com/project/602723113/may-common-library) [![Build Status](https://travis-ci.org/602723113/May-Common-Library.svg?branch=dev)](https://travis-ci.org/602723113/May-Common-Library) [![Codacy Badge](https://api.codacy.com/project/badge/Grade/e8b69ada84954b13a415981844a7e376)](https://www.codacy.com/app/602723113/May-Common-Library?utm_source=github.com&utm_medium=referral&utm_content=602723113/May-Common-Library&utm_campaign=Badge_Grade) +> 一个基于BukkitAPI开发的类库 + +[Wiki](https://github.com/602723113/May-Common-Library/wiki) +### 特性 +> 在 _MCLib_ 中你可以享受以下功能 +- 简易使用NMS +- 简易使用NBT +- 简易的使用Tellraw +- 简易的使用ServerPing +- 简易的使用Book +- 简易的使用1.12的新特性Advancement +- 简易的使用分页(Pager) +- 简易的使用反射工具类 +- 封装了许许多多的Util +- ... + +### 协议 + - 本项目遵循 MIT 协议 + +### 编译 +本项目使用 maven 进行管理 +构建请使用 +``` + mvn clean install package +``` + +**喜欢这个项目?不妨给它留个star?** diff --git a/advancement/pom.xml b/advancement/pom.xml new file mode 100644 index 0000000..3e4a0d5 --- /dev/null +++ b/advancement/pom.xml @@ -0,0 +1,16 @@ + + + + May-Common-Library + cc.zoyn.core + 1.0.0 + + 4.0.0 + + advancement + jar + + + \ No newline at end of file diff --git a/src/main/java/cc/zoyn/core/builder/AdvancementBuilder.java b/advancement/src/main/java/cc/zoyn/core/advancement/AdvancementBuilder.java similarity index 98% rename from src/main/java/cc/zoyn/core/builder/AdvancementBuilder.java rename to advancement/src/main/java/cc/zoyn/core/advancement/AdvancementBuilder.java index 0a579ef..33f9a44 100644 --- a/src/main/java/cc/zoyn/core/builder/AdvancementBuilder.java +++ b/advancement/src/main/java/cc/zoyn/core/advancement/AdvancementBuilder.java @@ -1,11 +1,9 @@ -package cc.zoyn.core.builder; +package cc.zoyn.core.advancement; -import cc.zoyn.core.advancement.FrameEnum; import com.google.gson.Gson; import com.google.gson.GsonBuilder; import com.google.gson.JsonElement; import com.google.gson.JsonObject; -import cc.zoyn.core.advancement.BackgroundEnum; import net.md_5.bungee.api.chat.TextComponent; import net.md_5.bungee.chat.ComponentSerializer; import org.bukkit.Bukkit; diff --git a/src/main/java/cc/zoyn/core/advancement/BackgroundEnum.java b/advancement/src/main/java/cc/zoyn/core/advancement/BackgroundEnum.java similarity index 93% rename from src/main/java/cc/zoyn/core/advancement/BackgroundEnum.java rename to advancement/src/main/java/cc/zoyn/core/advancement/BackgroundEnum.java index ba833fa..14cfd60 100644 --- a/src/main/java/cc/zoyn/core/advancement/BackgroundEnum.java +++ b/advancement/src/main/java/cc/zoyn/core/advancement/BackgroundEnum.java @@ -14,7 +14,7 @@ public enum BackgroundEnum { private String name; - private BackgroundEnum(String name) { + BackgroundEnum(String name) { this.name = name; } diff --git a/src/main/java/cc/zoyn/core/builder/ConditionBuilder.java b/advancement/src/main/java/cc/zoyn/core/advancement/ConditionBuilder.java similarity index 95% rename from src/main/java/cc/zoyn/core/builder/ConditionBuilder.java rename to advancement/src/main/java/cc/zoyn/core/advancement/ConditionBuilder.java index 64c3ba8..a9eb379 100644 --- a/src/main/java/cc/zoyn/core/builder/ConditionBuilder.java +++ b/advancement/src/main/java/cc/zoyn/core/advancement/ConditionBuilder.java @@ -1,4 +1,4 @@ -package cc.zoyn.core.builder; +package cc.zoyn.core.advancement; import com.google.gson.JsonElement; import com.google.gson.JsonObject; diff --git a/src/main/java/cc/zoyn/core/builder/CriteriaBuilder.java b/advancement/src/main/java/cc/zoyn/core/advancement/CriteriaBuilder.java similarity index 96% rename from src/main/java/cc/zoyn/core/builder/CriteriaBuilder.java rename to advancement/src/main/java/cc/zoyn/core/advancement/CriteriaBuilder.java index 7442fef..f58f0c1 100644 --- a/src/main/java/cc/zoyn/core/builder/CriteriaBuilder.java +++ b/advancement/src/main/java/cc/zoyn/core/advancement/CriteriaBuilder.java @@ -1,8 +1,7 @@ -package cc.zoyn.core.builder; +package cc.zoyn.core.advancement; import com.google.common.collect.Lists; import com.google.gson.JsonObject; -import cc.zoyn.core.advancement.TriggerEnum; import java.util.List; diff --git a/advancement/src/main/java/cc/zoyn/core/advancement/FrameEnum.java b/advancement/src/main/java/cc/zoyn/core/advancement/FrameEnum.java new file mode 100644 index 0000000..f345e57 --- /dev/null +++ b/advancement/src/main/java/cc/zoyn/core/advancement/FrameEnum.java @@ -0,0 +1,22 @@ +package cc.zoyn.core.advancement; + +/** + * 图标边框枚举 + * + * @author Zoyn + */ +public enum FrameEnum { + /** + * TASK(默认) + */ + TASK(), + /** + * GOAL为更圆的边框标题,其用于完整信标进度 + */ + GOAL(), + /** + * CHALLENGE,其用于杀死所有种类生物的进度 + */ + CHALLENGE() + +} diff --git a/src/main/java/cc/zoyn/core/advancement/TriggerEnum.java b/advancement/src/main/java/cc/zoyn/core/advancement/TriggerEnum.java similarity index 100% rename from src/main/java/cc/zoyn/core/advancement/TriggerEnum.java rename to advancement/src/main/java/cc/zoyn/core/advancement/TriggerEnum.java diff --git a/advancement/src/main/java/cc/zoyn/core/advancement/package-info.java b/advancement/src/main/java/cc/zoyn/core/advancement/package-info.java new file mode 100644 index 0000000..a359f29 --- /dev/null +++ b/advancement/src/main/java/cc/zoyn/core/advancement/package-info.java @@ -0,0 +1,7 @@ +/** + * Wrapper 1.12 version advancement operation + * + * @author Zoyn + * @since 2017-12-09 + */ +package cc.zoyn.core.advancement; \ No newline at end of file diff --git a/book/pom.xml b/book/pom.xml new file mode 100644 index 0000000..13670c3 --- /dev/null +++ b/book/pom.xml @@ -0,0 +1,24 @@ + + + + May-Common-Library + cc.zoyn.core + 1.0.0 + + 4.0.0 + + book + jar + + + + cc.zoyn.core + common + ${project.parent.version} + provided + + + + \ No newline at end of file diff --git a/book/src/main/java/cc/zoyn/core/book/Book.java b/book/src/main/java/cc/zoyn/core/book/Book.java new file mode 100644 index 0000000..7611074 --- /dev/null +++ b/book/src/main/java/cc/zoyn/core/book/Book.java @@ -0,0 +1,36 @@ +package cc.zoyn.core.book; + +import com.google.common.collect.Lists; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import org.bukkit.Material; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.BookMeta; + +import java.util.List; + +/** + * Book - 数据模型 + * + * @author Zoyn + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +public class Book { + + private String author = "Zoyn"; + private String title = "HelloWorld"; + private List pages = Lists.newArrayList(); + + public ItemStack getItem() { + ItemStack book = new ItemStack(Material.WRITTEN_BOOK); + BookMeta meta = (BookMeta) book.getItemMeta(); + meta.setTitle(title); + meta.setAuthor(author); + BookUtils.setPagesAsPage(meta, pages); + book.setItemMeta(meta); + return book; + } +} diff --git a/book/src/main/java/cc/zoyn/core/book/BookUtils.java b/book/src/main/java/cc/zoyn/core/book/BookUtils.java new file mode 100644 index 0000000..d6b173b --- /dev/null +++ b/book/src/main/java/cc/zoyn/core/book/BookUtils.java @@ -0,0 +1,138 @@ +package cc.zoyn.core.book; + +import org.bukkit.Bukkit; +import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.BookMeta; + +import java.lang.reflect.Method; +import java.util.List; +import java.util.stream.Collectors; + +import static cc.zoyn.core.util.NMSUtils.*; +import static cc.zoyn.core.util.reflect.ReflectionUtils.getFieldByFieldName; +import static cc.zoyn.core.util.reflect.ReflectionUtils.getMethod; + +/** + * 书本 - 工具类 + *

+ * 简易的打开一个带有特定json的书 + *

+ * Easy to open a book with the specified json + * + * @author Zoyn + * @since 2017/?/? + */ +public final class BookUtils { + + private static boolean initialised = false; + private static Method getHandle; + private static Method openBook; + + static { + try { + getHandle = getMethod(getOBCClass("CraftPlayer"), "getHandle"); + openBook = getMethod(getNMSClass("EntityPlayer"), "a", getNMSClass("ItemStack"), getNMSClass("EnumHand")); + + initialised = true; + } catch (ReflectiveOperationException e) { + e.printStackTrace(); + Bukkit.getServer().getLogger().warning("Cannot force open book!"); + initialised = false; + } + } + + // Prevent accidental construction + private BookUtils() { + } + + public static boolean isInitialised() { + return initialised; + } + + /** + * 打开一个虚拟的书 + *

+ * open a virtual book + * + * @param item 给定的书 + * @param player 给定的玩家 + * @return return true if open book successfully + */ + public static boolean openBook(Player player, ItemStack item) { + if (!initialised) { + return false; + } + ItemStack held = player.getInventory().getItemInMainHand(); + try { + player.getInventory().setItemInMainHand(item); + sendPacket(item, player); + } catch (ReflectiveOperationException e) { + e.printStackTrace(); + initialised = false; + } + player.getInventory().setItemInMainHand(held); + return initialised; + } + + /** + * 打开一个虚拟的书 + *

+ * open a virtual book + * + * @param player the player + * @param book a {@link Book} object + * @return return true if open book successfully + */ + public static boolean openBook(Player player, Book book) { + return openBook(player, book.getItem()); + } + + /** + * 以JSON格式来设置书的页面 + *

+ * use json to set the book pages + * + * @param metadata book's meta + * @param pages JSON lists + */ + @SuppressWarnings("unchecked") + public static void setBookPagesAsJson(BookMeta metadata, List pages) { + List p; + Object page; + try { + p = (List) getFieldByFieldName(getOBCClass("CraftMetaBook"), "pages").get(metadata); + for (String text : pages) { + page = stringToIChatBaseComponent(text); + p.add(page); + } + } catch (Exception e) { + e.printStackTrace(); + } + } + + /** + * 用{@link Page}来设置书的页面 + *

+ * use {@link Page} to set the book page + * + * @param metadata book's meta + * @param pages {@link Page} lists + */ + @SuppressWarnings("unchecked") + public static void setPagesAsPage(BookMeta metadata, List pages) { + setBookPagesAsJson(metadata, pages.stream() + .map(Page::toJsonString) + .collect(Collectors.toList())); + } + + private static void sendPacket(ItemStack itemStack, Player p) throws ReflectiveOperationException { + Object entityplayer = getHandle.invoke(p); + Class enumHand = getNMSClass("EnumHand"); + Object[] enumArray = new Object[0]; + if (enumHand != null) { + enumArray = enumHand.getEnumConstants(); + } + openBook.invoke(entityplayer, getNMSItem(itemStack), enumArray[0]); + } +} \ No newline at end of file diff --git a/src/main/java/cc/zoyn/core/minecraft/JsonImpl.java b/book/src/main/java/cc/zoyn/core/book/JsonImpl.java similarity index 98% rename from src/main/java/cc/zoyn/core/minecraft/JsonImpl.java rename to book/src/main/java/cc/zoyn/core/book/JsonImpl.java index 698c8f6..54a9c25 100644 --- a/src/main/java/cc/zoyn/core/minecraft/JsonImpl.java +++ b/book/src/main/java/cc/zoyn/core/book/JsonImpl.java @@ -1,4 +1,4 @@ -package cc.zoyn.core.minecraft; +package cc.zoyn.core.book; import cc.zoyn.core.util.JsonBuilderUtils; diff --git a/src/main/java/cc/zoyn/core/dto/Page.java b/book/src/main/java/cc/zoyn/core/book/Page.java similarity index 87% rename from src/main/java/cc/zoyn/core/dto/Page.java rename to book/src/main/java/cc/zoyn/core/book/Page.java index 80871cf..3fc9cd4 100644 --- a/src/main/java/cc/zoyn/core/dto/Page.java +++ b/book/src/main/java/cc/zoyn/core/book/Page.java @@ -1,8 +1,7 @@ -package cc.zoyn.core.dto; +package cc.zoyn.core.book; -import cc.zoyn.core.minecraft.JsonImpl; +import com.google.common.collect.Lists; -import java.util.ArrayList; import java.util.Arrays; import java.util.List; @@ -13,7 +12,7 @@ */ public class Page { - private List jsonParts = new ArrayList(); + private List jsonParts = Lists.newArrayList(); /** * 构造方法 @@ -53,7 +52,7 @@ public Page excuteCommandAndAddHover(String command, String... hover) { * @return {@link Page} */ public Page excuteCommand(String command) { - return onClick("run_command", command); + return onClick(command); } /** @@ -80,7 +79,7 @@ public Page addHover(List texts) { * @return {@link Page} */ public Page addHover(String text) { - return onHover("show_text", text); + return onHover(text); } /** @@ -131,13 +130,12 @@ private JsonImpl latest() { /** * 添加显示操作 * - * @param name 悬浮显示 * @param data 显示内容 * @return {@link Page} */ - private Page onHover(String name, String data) { + private Page onHover(String data) { JsonImpl latest = latest(); - latest.hoverActionName = name; + latest.hoverActionName = "show_text"; latest.hoverActionData = data; return this; } @@ -145,13 +143,12 @@ private Page onHover(String name, String data) { /** * 添加点击操作 * - * @param name 点击名称 * @param data 点击操作 * @return {@link Page} */ - private Page onClick(String name, String data) { + private Page onClick(String data) { JsonImpl latest = latest(); - latest.clickActionName = name; + latest.clickActionName = "run_command"; latest.clickActionData = data; return this; } diff --git a/common/pom.xml b/common/pom.xml new file mode 100644 index 0000000..13e5e83 --- /dev/null +++ b/common/pom.xml @@ -0,0 +1,15 @@ + + + + May-Common-Library + cc.zoyn.core + 1.0.0 + + 4.0.0 + + common + + + \ No newline at end of file diff --git a/common/src/main/java/cc/zoyn/core/Core.java b/common/src/main/java/cc/zoyn/core/Core.java new file mode 100644 index 0000000..4925721 --- /dev/null +++ b/common/src/main/java/cc/zoyn/core/Core.java @@ -0,0 +1,54 @@ +package cc.zoyn.core; + +import cc.zoyn.core.event.PlayerOpenBackpackEvent; +import com.comphenix.protocol.PacketType; +import com.comphenix.protocol.ProtocolLibrary; +import com.comphenix.protocol.events.PacketAdapter; +import com.comphenix.protocol.events.PacketEvent; +import com.comphenix.protocol.wrappers.EnumWrappers; +import org.bukkit.Bukkit; +import org.bukkit.entity.Player; +import org.bukkit.plugin.java.JavaPlugin; + +/** + * Main Class + * + * @author Zoyn + */ +public class Core extends JavaPlugin { + + private static Core instance; + + @Override + public void onEnable() { + instance = this; + + // register channel + Bukkit.getMessenger().registerOutgoingPluginChannel(this, "BungeeCord"); + + // register packet listener + ProtocolLibrary.getProtocolManager().addPacketListener(new PacketAdapter(this, PacketType.Play.Client.CLIENT_COMMAND) { + @Override + public void onPacketReceiving(PacketEvent event) { + Player player = event.getPlayer(); + if (event.getPacket().getClientCommands().read(0) == EnumWrappers.ClientCommand.OPEN_INVENTORY_ACHIEVEMENT) { + // call event + PlayerOpenBackpackEvent openBackpackEvent = new PlayerOpenBackpackEvent(player); + Bukkit.getPluginManager().callEvent(openBackpackEvent); + event.setCancelled(openBackpackEvent.isCancelled()); + } + } + }); + } + + /** + * get Core instance + * + * @return {@link Core} + */ + public static Core getInstance() { + return instance; + } + + +} diff --git a/src/main/java/cc/zoyn/core/builder/ItemStackBuilder.java b/common/src/main/java/cc/zoyn/core/builder/ItemStackBuilder.java similarity index 91% rename from src/main/java/cc/zoyn/core/builder/ItemStackBuilder.java rename to common/src/main/java/cc/zoyn/core/builder/ItemStackBuilder.java index d3f89bc..32cf944 100644 --- a/src/main/java/cc/zoyn/core/builder/ItemStackBuilder.java +++ b/common/src/main/java/cc/zoyn/core/builder/ItemStackBuilder.java @@ -1,12 +1,12 @@ package cc.zoyn.core.builder; -import cc.zoyn.core.util.NBTUtils; import org.bukkit.Material; import org.bukkit.inventory.ItemFlag; import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.meta.ItemMeta; import java.util.Arrays; +import java.util.Collections; import java.util.List; public class ItemStackBuilder { @@ -47,7 +47,7 @@ public ItemStackBuilder setLore(String... lore) { } public ItemStackBuilder clearLore() { - currentMeta.setLore(Arrays.asList()); + currentMeta.setLore(Collections.emptyList()); return this; } @@ -62,7 +62,7 @@ public ItemStackBuilder addHideFlag(ItemFlag... flag) { } public ItemStackBuilder setUnbreakable(boolean unBreakable) { - NBTUtils.setUnbreakable(currentItem, unBreakable); + currentItem.getItemMeta().spigot().setUnbreakable(unBreakable); return this; } diff --git a/common/src/main/java/cc/zoyn/core/builder/package-info.java b/common/src/main/java/cc/zoyn/core/builder/package-info.java new file mode 100644 index 0000000..a4ced26 --- /dev/null +++ b/common/src/main/java/cc/zoyn/core/builder/package-info.java @@ -0,0 +1,7 @@ +/** + * Add some useful Builder + * + * @author Zoyn + * @since 2017-12-09 + */ +package cc.zoyn.core.builder; \ No newline at end of file diff --git a/common/src/main/java/cc/zoyn/core/event/PlayerOpenBackpackEvent.java b/common/src/main/java/cc/zoyn/core/event/PlayerOpenBackpackEvent.java new file mode 100644 index 0000000..db47fac --- /dev/null +++ b/common/src/main/java/cc/zoyn/core/event/PlayerOpenBackpackEvent.java @@ -0,0 +1,43 @@ +package cc.zoyn.core.event; + +import org.bukkit.entity.Player; +import org.bukkit.event.Cancellable; +import org.bukkit.event.HandlerList; +import org.bukkit.event.player.PlayerEvent; + +/** + * 当玩家打开自己的背包时触发本事件 + *

+ * This event fires when the player opens his own backpack + * + * @author Zoyn + * @since 2018-01-07 + */ +public class PlayerOpenBackpackEvent extends PlayerEvent implements Cancellable { + + private static final HandlerList handlers = new HandlerList(); + private boolean cancelled = false; + + public PlayerOpenBackpackEvent(Player who) { + super(who); + } + + @Override + public boolean isCancelled() { + return cancelled; + } + + @Override + public void setCancelled(boolean cancel) { + cancelled = cancel; + } + + @Override + public HandlerList getHandlers() { + return handlers; + } + + public static HandlerList getHandlerList() { + return handlers; + } +} diff --git a/common/src/main/java/cc/zoyn/core/package-info.java b/common/src/main/java/cc/zoyn/core/package-info.java new file mode 100644 index 0000000..3ace757 --- /dev/null +++ b/common/src/main/java/cc/zoyn/core/package-info.java @@ -0,0 +1,7 @@ +/** + * Plugin Main Class + * + * @author Zoyn + * @since 2017-12-09 + */ +package cc.zoyn.core; \ No newline at end of file diff --git a/src/main/java/cc/zoyn/core/util/ActionBarUtils.java b/common/src/main/java/cc/zoyn/core/util/ActionBarUtils.java similarity index 53% rename from src/main/java/cc/zoyn/core/util/ActionBarUtils.java rename to common/src/main/java/cc/zoyn/core/util/ActionBarUtils.java index 20aee9b..9c98915 100644 --- a/src/main/java/cc/zoyn/core/util/ActionBarUtils.java +++ b/common/src/main/java/cc/zoyn/core/util/ActionBarUtils.java @@ -11,36 +11,39 @@ import java.lang.reflect.InvocationTargetException; /** - * ActionBar - 工具类 + * Easy to send an actionbar * * @author Zoyn * @since 2016/?/? */ -public class ActionBarUtils { +public final class ActionBarUtils { + + // Prevent accidental construction + private ActionBarUtils() { + } /** * 给一名玩家发送actionbar + *

+ * send a actionbar to player * - * @param player 玩家 - * @param msg 信息 + * @param player playerObj + * @param msg message */ public static void sendBar(Player player, String msg) { - msg = ChatColor.translateAlternateColorCodes('&', msg); - //获取Pl管理 - ProtocolManager pm = ProtocolLibrary.getProtocolManager(); - PacketContainer packet = pm.createPacket(PacketType.Play.Server.CHAT); - //nms内封包结构为 - /* private IChatBaseComponent a; - * public BaseComponent[] components; //可以不用填 - * private byte b; - */ - //依次写入数据 - packet.getChatComponents().write(0, WrappedChatComponent.fromText(msg)); + String translatedMessage = ChatColor.translateAlternateColorCodes('&', msg); + + //get protocol manager instance + ProtocolManager protocolManager = ProtocolLibrary.getProtocolManager(); + PacketContainer packet = protocolManager.createPacket(PacketType.Play.Server.CHAT); + + //write data + packet.getChatComponents().write(0, WrappedChatComponent.fromText(translatedMessage)); packet.getBytes().write(0, (byte) 2); - //发送数据包 + // send packet try { - pm.sendServerPacket(player, packet, false); + protocolManager.sendServerPacket(player, packet, false); } catch (InvocationTargetException e) { e.printStackTrace(); } diff --git a/common/src/main/java/cc/zoyn/core/util/BasicUtils.java b/common/src/main/java/cc/zoyn/core/util/BasicUtils.java new file mode 100644 index 0000000..b12efbe --- /dev/null +++ b/common/src/main/java/cc/zoyn/core/util/BasicUtils.java @@ -0,0 +1,51 @@ +package cc.zoyn.core.util; + +import com.google.common.collect.Lists; +import org.bukkit.Bukkit; +import org.bukkit.World; +import org.bukkit.entity.Player; + +import java.util.List; +import java.util.UUID; + +/** + * 基础 - 工具类 + * + * @author Zoyn + * @since 2016/12/26 + */ +public final class BasicUtils { + + // Prevent accidental construction + private BasicUtils() { + } + + /** + * Get the server all online players + * + * @return {@link List} + */ + public static List getOnlinePlayers() { + List players = Lists.newArrayList(); + List worlds = Bukkit.getWorlds(); + worlds.forEach(world -> players.addAll(world.getPlayers())); + return players; + } + + /** + * 将玩家名转换为UUID + *

+ * Convert player name to UUID + * + * @param name the player name + * @return {@link UUID}, the name of the corresponding uuid + */ + public UUID translateNameToUUID(String name) { + final Player player = Bukkit.getPlayerExact(name); + if (player != null) { + return player.getUniqueId(); + } else { + return UUID.nameUUIDFromBytes(("OfflinePlayer:" + name).getBytes()); + } + } +} diff --git a/common/src/main/java/cc/zoyn/core/util/BungeeCordUtils.java b/common/src/main/java/cc/zoyn/core/util/BungeeCordUtils.java new file mode 100644 index 0000000..3b1e5f0 --- /dev/null +++ b/common/src/main/java/cc/zoyn/core/util/BungeeCordUtils.java @@ -0,0 +1,96 @@ +package cc.zoyn.core.util; + +import cc.zoyn.core.Core; +import com.google.common.collect.Iterables; +import com.google.common.io.ByteArrayDataOutput; +import com.google.common.io.ByteStreams; +import lombok.Getter; +import org.apache.commons.lang3.Validate; +import org.bukkit.entity.Player; + + +/** + * BungeeCord - 工具类 + * + * @author Zoyn + */ +public final class BungeeCordUtils { + + private static volatile BungeeCordUtils instance; + + // Prevent accidental construction + private BungeeCordUtils() { + } + + public static BungeeCordUtils getInstance() { + if (instance == null) { + synchronized (BungeeCordUtils.class) { + if (instance == null) { + instance = new BungeeCordUtils(); + } + } + } + return instance; + } + + public static void sendData(BungeeCordTagType tagType, String... arguments) { + ByteArrayDataOutput out = ByteStreams.newDataOutput(); + + out.writeUTF(tagType.getText()); + for (String argument : arguments) { + out.writeUTF(argument); + } + + Player player = Iterables.getFirst(BasicUtils.getOnlinePlayers(), null); + Validate.notNull(player).sendPluginMessage(Core.getInstance(), "BungeeCord", out.toByteArray()); + } + + /** + * 将玩家传送至某子服 + * + * @param playerName 名字 + * @param serverName 服务器名 + */ + public static void playerConnectServer(String playerName, String serverName) { + sendData(BungeeCordTagType.CONNECT_OTHER, playerName, serverName); + } + + /** + * 踢出一个玩家 + * + * @param playerName 玩家名 + * @param message 信息 + */ + public static void kickPlayer(String playerName, String message) { + sendData(BungeeCordTagType.KICK_PLAYER, playerName, message); + } + + public static void sendMessageToPlayer(String playerName, String message) { + sendData(BungeeCordTagType.MESSAGE, playerName, message); + } + + + @Getter + public enum BungeeCordTagType { + CONNECT("Connect"), + CONNECT_OTHER("ConnectOther"), + IP("IP"), + PLAYER_COUNT("PlayerCount"), + PLAYER_LIST("PlayerList"), + GET_SERVERS("GetServers"), + MESSAGE("Message"), + KICK_PLAYER("KickPlayer"); + + private String text; + + BungeeCordTagType(String text) { + this.text = text; + } + + @Override + public String toString() { + return text; + } + } + +} diff --git a/common/src/main/java/cc/zoyn/core/util/ConfigurationUtils.java b/common/src/main/java/cc/zoyn/core/util/ConfigurationUtils.java new file mode 100644 index 0000000..624a45c --- /dev/null +++ b/common/src/main/java/cc/zoyn/core/util/ConfigurationUtils.java @@ -0,0 +1,89 @@ +package cc.zoyn.core.util; + +import org.bukkit.configuration.file.FileConfiguration; +import org.bukkit.configuration.file.YamlConfiguration; +import org.yaml.snakeyaml.DumperOptions; + +import java.io.File; +import java.io.IOException; +import java.lang.reflect.Field; + +/** + * 配置文件工具类 + * + * @author Zoyn + * @since 2017-12-17 + */ +public final class ConfigurationUtils { + + // Prevent accidental construction + private ConfigurationUtils() { + } + + /** + * 用路径读取Yml + *
+ * load Yml with the path + * + * @param path 路径 + * @return 那个Yml的FileConfiguration对象 + */ + public static FileConfiguration loadYml(String path) { + return loadYml(new File(path)); + } + + /** + * 保存Yml + *
+ * save a Yml + * + * @param fileConfiguration 该Yml的FileConfiguration对象 + * @param file 文件 + */ + public static void saveYml(FileConfiguration fileConfiguration, File file) { + try { + fileConfiguration.save(file); + } catch (IOException e) { + System.out.println("错误:" + e.toString()); + } + } + + /** + * 读取Yml + *
+ * load Yml with the file + * + * @param file 文件 + * @return YML的FileConfiguration对象 + */ + public static FileConfiguration loadYml(File file) { + if (!file.exists()) { + try { + file.createNewFile(); + } catch (IOException e) { + System.out.println("错误:" + e.toString()); + } + } + FileConfiguration YML = YamlConfiguration.loadConfiguration(file); + DumperOptions yamlOptions = null; + try { + Field f = YamlConfiguration.class.getDeclaredField("yamlOptions"); + f.setAccessible(true); + yamlOptions = new DumperOptions() { + public void setAllowUnicode(boolean allowUnicode) { + super.setAllowUnicode(false); + } + + public void setLineBreak(LineBreak lineBreak) { + super.setLineBreak(LineBreak.getPlatformLineBreak()); + } + }; + yamlOptions.setLineBreak(DumperOptions.LineBreak.getPlatformLineBreak()); + f.set(YML, yamlOptions); + } catch (ReflectiveOperationException ex) { + System.out.println("错误:" + ex.toString()); + } + return YML; + } + +} diff --git a/src/main/java/cc/zoyn/core/util/EntityUtils.java b/common/src/main/java/cc/zoyn/core/util/EntityUtils.java similarity index 56% rename from src/main/java/cc/zoyn/core/util/EntityUtils.java rename to common/src/main/java/cc/zoyn/core/util/EntityUtils.java index 81335b6..9668fb0 100644 --- a/src/main/java/cc/zoyn/core/util/EntityUtils.java +++ b/common/src/main/java/cc/zoyn/core/util/EntityUtils.java @@ -1,30 +1,31 @@ package cc.zoyn.core.util; +import com.google.common.collect.Lists; import org.bukkit.Location; import org.bukkit.block.Block; import org.bukkit.entity.Entity; import org.bukkit.entity.Player; import org.bukkit.util.BlockIterator; -import java.util.ArrayList; import java.util.List; -public class EntityUtils { +public final class EntityUtils { + + // Prevent accidental construction + private EntityUtils() { + } /** * 取目标玩家 + *

+ * get player target * * @param player 玩家 * @return 该玩家的目标玩家 */ public static Player getTargetPlayer(Player player) { - List nearbyE = player.getNearbyEntities(20.0D, 20.0D, 20.0D); - ArrayList nearPlayers = new ArrayList(); - for (Entity e : nearbyE) { - if ((e instanceof Player)) { - nearPlayers.add((Player) e); - } - } + List nearPlayers = getNearbyPlayersList(player.getLocation(), 20D); + Player target = null; BlockIterator bItr = new BlockIterator(player, 20); while (bItr.hasNext()) { @@ -48,37 +49,37 @@ public static Player getTargetPlayer(Player player) { } /** - * 取附近的实体[返回数组] + * 取附近的实体 * * @param loc 坐标 * @param radius 半径 - * @return 实体数组 + * @return return a {@link Entity} array */ public static Entity[] getNearbyEntitiesArrays(Location loc, double radius) { return getNearbyEntitiesList(loc, radius).toArray(new Entity[]{}); } /** - * 取附近的实体[返回List] + * 取附近的实体 * * @param loc 坐标 * @param radius 半径 - * @return 实体集合 + * @return {@link List} */ public static List getNearbyEntitiesList(Location loc, double radius) { int Radius = (int) radius; int chunkRadius = Radius < 16 ? 1 : (Radius - Radius % 16) / 16; - List radiusEntities = new ArrayList(); + List radiusEntities = Lists.newArrayList(); for (int chX = 0 - chunkRadius; chX <= chunkRadius; ++chX) { for (int chZ = 0 - chunkRadius; chZ <= chunkRadius; ++chZ) { int x = (int) loc.getX(); int y = (int) loc.getY(); int z = (int) loc.getZ(); - Entity[] entitys; - int size = (entitys = (new Location(loc.getWorld(), (double) (x + chX * 16), (double) y, + Entity[] entities; + int size = (entities = (new Location(loc.getWorld(), (double) (x + chX * 16), (double) y, (double) (z + chZ * 16))).getChunk().getEntities()).length; for (int i = 0; i < size; i++) { - Entity e = entitys[i]; + Entity e = entities[i]; if (e.getLocation().distance(loc) <= radius && e.getLocation().getBlock() != loc.getBlock()) { radiusEntities.add(e); } @@ -89,36 +90,18 @@ public static List getNearbyEntitiesList(Location loc, double radius) { } /** - * 取附近的玩家 [返回List] + * 取附近的玩家 * * @param loc 坐标 * @param radius 半径 - * @return 玩家集合 + * @return {@link Player} */ public static List getNearbyPlayersList(Location loc, double radius) { - int Radius = (int) radius; - int chunkRadius = Radius < 16 ? 1 : (Radius - Radius % 16) / 16; - List radiusEntities = new ArrayList(); - for (int chX = 0 - chunkRadius; chX <= chunkRadius; ++chX) { - for (int chZ = 0 - chunkRadius; chZ <= chunkRadius; ++chZ) { - int x = (int) loc.getX(); - int y = (int) loc.getY(); - int z = (int) loc.getZ(); - Entity[] entitys; - int size = (entitys = (new Location(loc.getWorld(), (double) (x + chX * 16), (double) y, - (double) (z + chZ * 16))).getChunk().getEntities()).length; - for (int i = 0; i < size; i++) { - Entity e = entitys[i]; - if (e.getLocation().distance(loc) <= radius && e.getLocation().getBlock() != loc.getBlock()) { - radiusEntities.add(e); - } - } - } - } - List players = new ArrayList(); - for (int i = 0; i < radiusEntities.size(); i++) { - if (radiusEntities.get(i) instanceof Player) { - players.add((Player) radiusEntities.get(i)); + List radiusEntities = getNearbyEntitiesList(loc, radius); + List players = Lists.newArrayList(); + for (Entity radiusEntity : radiusEntities) { + if (radiusEntity instanceof Player) { + players.add((Player) radiusEntity); } } return players; diff --git a/src/main/java/cc/zoyn/core/util/FileUtils.java b/common/src/main/java/cc/zoyn/core/util/FileUtils.java similarity index 54% rename from src/main/java/cc/zoyn/core/util/FileUtils.java rename to common/src/main/java/cc/zoyn/core/util/FileUtils.java index b6e4569..11245af 100644 --- a/src/main/java/cc/zoyn/core/util/FileUtils.java +++ b/common/src/main/java/cc/zoyn/core/util/FileUtils.java @@ -1,11 +1,6 @@ package cc.zoyn.core.util; -import org.bukkit.configuration.file.FileConfiguration; -import org.bukkit.configuration.file.YamlConfiguration; -import org.yaml.snakeyaml.DumperOptions; - import java.io.*; -import java.lang.reflect.Field; import java.util.zip.ZipEntry; import java.util.zip.ZipOutputStream; @@ -14,7 +9,11 @@ * * @author Zoyn */ -public class FileUtils { +public final class FileUtils { + + // Prevent accidental construction + private FileUtils() { + } /** * 移动 文件或者文件夹 @@ -40,7 +39,10 @@ public static void deleteFile(String filePath) { } if (file.isDirectory()) { File[] list = file.listFiles(); - + // prevent forEach null + if (list == null) { + return; + } for (File f : list) { deleteFile(f.getAbsolutePath()); } @@ -115,9 +117,14 @@ public static File createZips(String zipFileName, File... files) throws Exceptio e.printStackTrace(); } finally { try { - bo.close(); + if (bo != null) { + bo.close(); + } } finally { - out.close(); // 输出流关闭 + if (out != null) { + // 输出流关闭 + out.close(); + } } } return outFile; @@ -141,43 +148,43 @@ public static File createZip(String zipFileName, File inputFile) throws Exceptio e.printStackTrace(); } finally { try { - bo.close(); + if (bo != null) { + bo.close(); + } } finally { - out.close(); // 输出流关闭 + if (out != null) { + out.close(); // 输出流关闭 + } } } return outFile; } - private static void zip(ZipOutputStream out, File f, String base, BufferedOutputStream bo) throws Exception { // 方法重载 - if (f.isDirectory()) { - File[] fl = f.listFiles(); - if (fl == null || fl.length == 0) { + private static void zip(ZipOutputStream out, File file, String base, BufferedOutputStream bo) throws Exception { // 方法重载 + if (file.isDirectory()) { + File[] files = file.listFiles(); + if (files == null || files.length == 0) { out.putNextEntry(new ZipEntry(base + "/")); // 创建创建一个空的文件夹 } else { - for (int i = 0; i < fl.length; i++) { - zip(out, fl[i], base + "/" + fl[i].getName(), bo); // 递归遍历子文件夹 + for (File fileTemp : files) { + zip(out, fileTemp, base + "/" + fileTemp.getName(), bo); // 递归遍历子文件夹 } } } else { out.putNextEntry(new ZipEntry(base)); // 创建zip压缩进入 base 文件 - System.out.println(base); - BufferedInputStream bi = new BufferedInputStream(new FileInputStream(f)); - try { - write2Out(bi, out); + try (BufferedInputStream in = new BufferedInputStream(new FileInputStream(file))) { + write2Out(in, out); } catch (IOException e) { // Ignore - } finally { - bi.close();// 输入流关闭 } } } private static void write2Out(InputStream input, OutputStream out) throws IOException { byte[] b = new byte[1024]; - int c = 0; + int c; while ((c = input.read(b)) != -1) { out.write(b, 0, c); out.flush(); @@ -185,90 +192,4 @@ private static void write2Out(InputStream input, OutputStream out) throws IOExce out.flush(); } - /** - * 用路径读取Yml - * - * @param path 路径 - * @return 那个Yml的FileConfiguration对象 - */ - public static FileConfiguration loadYml(String path) { - File file = new File(path); - if (!file.exists()) { - try { - file.createNewFile(); - } catch (IOException e) { - System.out.println("错误:" + e.toString()); - } - } - FileConfiguration YML = YamlConfiguration.loadConfiguration(file); - DumperOptions yamlOptions = null; - try { - Field f = YamlConfiguration.class.getDeclaredField("yamlOptions"); - f.setAccessible(true); - yamlOptions = new DumperOptions() { - public void setAllowUnicode(boolean allowUnicode) { - super.setAllowUnicode(false); - } - - public void setLineBreak(DumperOptions.LineBreak lineBreak) { - super.setLineBreak(DumperOptions.LineBreak.getPlatformLineBreak()); - } - }; - yamlOptions.setLineBreak(DumperOptions.LineBreak.getPlatformLineBreak()); - f.set(YML, yamlOptions); - } catch (ReflectiveOperationException ex) { - System.out.println("错误:" + ex.toString()); - } - return YamlConfiguration.loadConfiguration(new File(path)); - } - - /** - * 保存Yml - * - * @param Filec 该Yml的FileConfiguration对象 - * @param file 文件 - */ - public static void saveYml(FileConfiguration Filec, File file) { - try { - Filec.save(file); - } catch (IOException e) { - System.out.println("错误:" + e.toString()); - } - } - - /** - * 读取Yml - * - * @param file 文件 - * @return YML的FileConfiguration对象 - */ - public static FileConfiguration loadYml(File file) { - if (!file.exists()) { - try { - file.createNewFile(); - } catch (IOException e) { - System.out.println("错误:" + e.toString()); - } - } - FileConfiguration YML = YamlConfiguration.loadConfiguration(file); - DumperOptions yamlOptions = null; - try { - Field f = YamlConfiguration.class.getDeclaredField("yamlOptions"); - f.setAccessible(true); - yamlOptions = new DumperOptions() { - public void setAllowUnicode(boolean allowUnicode) { - super.setAllowUnicode(false); - } - - public void setLineBreak(DumperOptions.LineBreak lineBreak) { - super.setLineBreak(DumperOptions.LineBreak.getPlatformLineBreak()); - } - }; - yamlOptions.setLineBreak(DumperOptions.LineBreak.getPlatformLineBreak()); - f.set(YML, yamlOptions); - } catch (ReflectiveOperationException ex) { - System.out.println("错误:" + ex.toString()); - } - return YML; - } } diff --git a/src/main/java/cc/zoyn/core/util/InventoryUtils.java b/common/src/main/java/cc/zoyn/core/util/InventoryUtils.java similarity index 64% rename from src/main/java/cc/zoyn/core/util/InventoryUtils.java rename to common/src/main/java/cc/zoyn/core/util/InventoryUtils.java index 0411e48..d86c5ec 100644 --- a/src/main/java/cc/zoyn/core/util/InventoryUtils.java +++ b/common/src/main/java/cc/zoyn/core/util/InventoryUtils.java @@ -1,32 +1,55 @@ package cc.zoyn.core.util; +import com.google.common.collect.Lists; import org.bukkit.Material; import org.bukkit.entity.Player; import org.bukkit.inventory.Inventory; import org.bukkit.inventory.ItemStack; +import java.util.List; + /** * 物品栏工具类 * * @author Zoyn * @since 2016/?/? */ -public class InventoryUtils { +public final class InventoryUtils { + + // Prevent accidental construction + private InventoryUtils() { + } + + /** + * 检查一个容器是否为空 + * + * @param inventory 给定的容器 + * @return 当容器为空时返回true + */ + public static boolean isEmpty(Inventory inventory) { + List itemStacks = Lists.newArrayList(inventory.getContents()); + for (ItemStack itemStack : itemStacks) { + if (itemStack == null || itemStack.getType().equals(Material.AIR)) { + return false; + } + } + return true; + } /** * 检查玩家是否拥有某物品 * - * @param player 玩家 - * @param is 物品(ItemStack类型) + * @param player 玩家 + * @param itemStack 物品 * @return Boolean */ - public static boolean hasItem(Player player, ItemStack is) { + public static boolean hasItem(Player player, ItemStack itemStack) { Inventory inventory = player.getInventory(); ItemStack[] invItem = inventory.getContents(); - int i = 0; - if (i < invItem.length) { - invItem[i].equals(is); - return true; + for (ItemStack item : invItem) { + if (item.equals(itemStack)) { + return true; + } } return false; } diff --git a/src/main/java/cc/zoyn/core/enchantments/Glow.java b/common/src/main/java/cc/zoyn/core/util/ItemGlowUtils.java similarity index 86% rename from src/main/java/cc/zoyn/core/enchantments/Glow.java rename to common/src/main/java/cc/zoyn/core/util/ItemGlowUtils.java index 4c55104..a86d151 100644 --- a/src/main/java/cc/zoyn/core/enchantments/Glow.java +++ b/common/src/main/java/cc/zoyn/core/util/ItemGlowUtils.java @@ -1,4 +1,4 @@ -package cc.zoyn.core.enchantments; +package cc.zoyn.core.util; import org.bukkit.enchantments.Enchantment; import org.bukkit.enchantments.EnchantmentTarget; @@ -7,16 +7,21 @@ import java.lang.reflect.Field; /** - * 用于给予物品发光属性,无实际作用的一个附魔 + * 用于给予物品发光的特性 * * @author Zoyn */ -public class Glow extends Enchantment { +public class ItemGlowUtils extends Enchantment { + + static { + registerGlow(); + } /** * 注册附魔 */ public static void registerGlow() { + try { Field f = Enchantment.class.getDeclaredField("acceptingNew"); f.setAccessible(true); @@ -26,7 +31,8 @@ public static void registerGlow() { } } - public Glow(int id) { + + public ItemGlowUtils(int id) { super(id); } diff --git a/src/main/java/cc/zoyn/core/util/ItemStackUtils.java b/common/src/main/java/cc/zoyn/core/util/ItemStackUtils.java similarity index 68% rename from src/main/java/cc/zoyn/core/util/ItemStackUtils.java rename to common/src/main/java/cc/zoyn/core/util/ItemStackUtils.java index f331833..eaea5e2 100644 --- a/src/main/java/cc/zoyn/core/util/ItemStackUtils.java +++ b/common/src/main/java/cc/zoyn/core/util/ItemStackUtils.java @@ -1,5 +1,7 @@ package cc.zoyn.core.util; +import com.google.common.collect.Lists; +import org.apache.commons.lang3.Validate; import org.bukkit.ChatColor; import org.bukkit.Material; import org.bukkit.enchantments.Enchantment; @@ -8,11 +10,14 @@ import java.util.ArrayList; import java.util.List; -import java.util.Map; import java.util.Map.Entry; import java.util.Set; -public class ItemStackUtils { +public final class ItemStackUtils { + + // Prevent accidental construction + private ItemStackUtils() { + } /** * 附魔序列化 @@ -23,7 +28,7 @@ public class ItemStackUtils { @SuppressWarnings("deprecation") public static String getEnch(Set> set) { StringBuilder enchs = new StringBuilder(); - for (Map.Entry ench : set) { + for (Entry ench : set) { enchs.append(String.format("{id:%s,lvl:%s},", ench.getKey().getId(), ench.getValue())); } enchs.deleteCharAt(enchs.length() - 1); @@ -53,17 +58,17 @@ public static int getLoreIndex(List lores, String lore) { * * @param is 物品(ItemStack类型) * @param Line 行数 - * @param lore 要设置的Lore + * @param msg 要设置的Lore */ - public static void setLore(ItemStack is, int Line, String lore) { - List lores = new ArrayList(); + public static void setLore(ItemStack is, int Line, String msg) { + List lore = Lists.newArrayList(); if (is == null || is.getType() == Material.AIR) { - throw new NullPointerException(); + return; } if (is.getItemMeta().hasLore()) { - lores.addAll(is.getItemMeta().getLore()); - lores.set((Line - 1), lore.replaceAll("&", "§")); - is.getItemMeta().setLore(lores); + lore.addAll(is.getItemMeta().getLore()); + lore.set((Line - 1), msg.replaceAll("&", "§")); + is.getItemMeta().setLore(lore); is.setItemMeta(is.getItemMeta()); } else { return; @@ -73,28 +78,27 @@ public static void setLore(ItemStack is, int Line, String lore) { /** * 添加Lore * - * @param is 需要设置的物品 - * @param lore 待添加的String + * @param is 需要设置的物品 + * @param msg 待添加的String * @return 该物品的ItemStack对象 */ - public static ItemStack addLore(ItemStack is, String lore) { - if (is != null) { - lore = ChatColor.translateAlternateColorCodes('&', lore); - ItemMeta im = is.getItemMeta(); - if (im.hasLore()) { - List l = im.getLore(); - l.add(lore); - im.setLore(l); - is.setItemMeta(im); - return is; - } - List l = new ArrayList<>(); + public static ItemStack addLore(ItemStack is, String msg) { + Validate.notNull(is); + + String lore = ChatColor.translateAlternateColorCodes('&', msg); + ItemMeta im = is.getItemMeta(); + if (im.hasLore()) { + List l = im.getLore(); l.add(lore); im.setLore(l); is.setItemMeta(im); return is; } - throw new NullPointerException(); + List l = new ArrayList<>(); + l.add(lore); + im.setLore(l); + is.setItemMeta(im); + return is; } /** @@ -106,9 +110,8 @@ public static ItemStack addLore(ItemStack is, String lore) { * @return 该物品的ItemStack */ public static ItemStack replaceLore(ItemStack is, String old, String newString) { - if (is == null) { - throw new NullPointerException(); - } + Validate.notNull(is); + ItemMeta im = is.getItemMeta(); List lore = im.getLore(); if (!lore.contains(old)) { diff --git a/src/main/java/cc/zoyn/core/util/JsonBuilderUtils.java b/common/src/main/java/cc/zoyn/core/util/JsonBuilderUtils.java similarity index 93% rename from src/main/java/cc/zoyn/core/util/JsonBuilderUtils.java rename to common/src/main/java/cc/zoyn/core/util/JsonBuilderUtils.java index de8b37f..09f2941 100644 --- a/src/main/java/cc/zoyn/core/util/JsonBuilderUtils.java +++ b/common/src/main/java/cc/zoyn/core/util/JsonBuilderUtils.java @@ -2,12 +2,11 @@ /** * Json构建 - * - * @author Zoyn */ -public class JsonBuilderUtils { +public final class JsonBuilderUtils { - public static final String[] REPLACEMENT_CHARS; + private static final String[] REPLACEMENT_CHARS; + private StringBuilder json; static { REPLACEMENT_CHARS = new String[128]; @@ -23,8 +22,6 @@ public class JsonBuilderUtils { REPLACEMENT_CHARS['\f'] = "\\f"; } - StringBuilder json; - public JsonBuilderUtils() { json = new StringBuilder(); } diff --git a/src/main/java/cc/zoyn/core/util/MathUtils.java b/common/src/main/java/cc/zoyn/core/util/MathUtils.java similarity index 55% rename from src/main/java/cc/zoyn/core/util/MathUtils.java rename to common/src/main/java/cc/zoyn/core/util/MathUtils.java index a94ee70..52943f8 100644 --- a/src/main/java/cc/zoyn/core/util/MathUtils.java +++ b/common/src/main/java/cc/zoyn/core/util/MathUtils.java @@ -1,17 +1,20 @@ package cc.zoyn.core.util; import org.bukkit.Location; -import org.bukkit.block.Block; import org.bukkit.entity.Player; import org.bukkit.util.Vector; -import java.util.ArrayList; -import java.util.List; +public final class MathUtils { -public class MathUtils { + // Prevent accidental construction + private MathUtils() { + } /** - * 取两坐标点的距离
+ * Get two locations distance + *

+ * 取两坐标点的距离 + *

* 使用空间两点距离公式计算: √(X2 - X1)^2 + (Y2 - Y1)^2 + (Z2 - Z1)^2 * * @param location1 坐标1 @@ -23,6 +26,14 @@ public static double getDistance(Location location1, Location location2) { return Math.sqrt(Math.pow(location1.getX() - location2.getX(), 2) + Math.pow(location1.getY() - location2.getY(), 2) + Math.pow(location1.getZ() - location2.getZ(), 2)); } + /** + * 使一个向量围绕Y轴旋转 + * Make a vector rotate around Y axis + * + * @param v the vector + * @param angle the rotate angle + * @return {@link Vector} + */ public static Vector rotateAroundAxisY(Vector v, double angle) { double cos = Math.cos(angle); double sin = Math.sin(angle); @@ -32,7 +43,7 @@ public static Vector rotateAroundAxisY(Vector v, double angle) { } /** - * 取背后的向量 + * 取坐标后的向量 * * @param loc 坐标 * @return {@link Vector} @@ -43,7 +54,13 @@ public static Vector getBackVector(Location loc) { return new Vector(newX - loc.getX(), 0.0D, newZ - loc.getZ()); } - public static String getCardinalDirection(Player player) { + /** + * get player's direction name + * + * @param player a player instance + * @return the direction name + */ + public static String getDirectionName(Player player) { double rotation = (player.getLocation().getYaw() - 90.0F) % 360.0F; if (rotation < 0.0D) { rotation += 360.0D; @@ -63,39 +80,11 @@ public static String getCardinalDirection(Player player) { /** * 取第一个坐标到第二个坐标的向量 * - * @param first_location 坐标1 - * @param second_location 坐标2 + * @param firstLocation 坐标1 + * @param secondLocation 坐标2 * @return {@link Vector} */ - public static Vector getVector(Location first_location, Location second_location) { - Vector from = new Vector(first_location.getX(), first_location.getY(), first_location.getZ()); - Vector to = new Vector(second_location.getX(), second_location.getY(), second_location.getZ()); - return to.subtract(from); - } - - /** - * 取两点之间的方块List - * - * @param loc1 坐标1 - * @param loc2 坐标2 - * @return 方块集合 - */ - public static List blocksFromTwoPoints(Location loc1, Location loc2) { - ArrayList blocks = new ArrayList(); - int topBlockX = loc1.getBlockX() < loc2.getBlockX() ? loc2.getBlockX() : loc1.getBlockX(); - int bottomBlockX = loc1.getBlockX() > loc2.getBlockX() ? loc2.getBlockX() : loc1.getBlockX(); - int topBlockY = loc1.getBlockY() < loc2.getBlockY() ? loc2.getBlockY() : loc1.getBlockY(); - int bottomBlockY = loc1.getBlockY() > loc2.getBlockY() ? loc2.getBlockY() : loc1.getBlockY(); - int topBlockZ = loc1.getBlockZ() < loc2.getBlockZ() ? loc2.getBlockZ() : loc1.getBlockZ(); - int bottomBlockZ = loc1.getBlockZ() > loc2.getBlockZ() ? loc2.getBlockZ() : loc1.getBlockZ(); - for (int x = bottomBlockX; x <= topBlockX; x++) { - for (int z = bottomBlockZ; z <= topBlockZ; z++) { - for (int y = bottomBlockY; y <= topBlockY; y++) { - Block block = loc1.getWorld().getBlockAt(x, y, z); - blocks.add(block); - } - } - } - return blocks; + public static Vector getVector(Location firstLocation, Location secondLocation) { + return secondLocation.subtract(firstLocation).toVector(); } } diff --git a/common/src/main/java/cc/zoyn/core/util/NMSUtils.java b/common/src/main/java/cc/zoyn/core/util/NMSUtils.java new file mode 100644 index 0000000..9f937fa --- /dev/null +++ b/common/src/main/java/cc/zoyn/core/util/NMSUtils.java @@ -0,0 +1,233 @@ +package cc.zoyn.core.util; + +import cc.zoyn.core.util.reflect.ReflectionUtils; +import org.apache.commons.lang3.Validate; +import org.bukkit.Bukkit; +import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; + +import java.lang.reflect.Field; +import java.lang.reflect.Method; + +import static cc.zoyn.core.util.reflect.ReflectionUtils.*; + +/** + * Easy to use NMS + * + * @author Zoyn + * @since 2017/4/26 + */ +public final class NMSUtils { + + private static String version; + private static Field playerConnectionField; + private static Method sendPacketMethod; + private static Method asNMSCopyMethod; + private static Method asBukkitCopyMethod; + private static Method stringAsIChatBaseComponentMethod; + private static Method craftBukkitEntityPlayerGetHandleMethod; + + // Prevent accidental construction + private NMSUtils() { + } + + static { + // org.bukkit.craftbukkit.vX_XX_RX; + version = Bukkit.getServer().getClass().getPackage().getName().split("\\.")[3]; + + // initial + try { + playerConnectionField = getFieldByFieldName(getNMSClass("EntityPlayer"), "playerConnection"); + sendPacketMethod = getMethod(getNMSClass("PlayerConnection"), "sendPacket", getNMSClass("Packet")); + asNMSCopyMethod = getMethod(getOBCClass("inventory.CraftItemStack"), "asNMSCopy", ItemStack.class); + asBukkitCopyMethod = getMethod(getOBCClass("inventory.CraftItemStack"), "asBukkitCopy", getNMSClass("ItemStack")); + stringAsIChatBaseComponentMethod = getMethod(getNMSClass("IChatBaseComponent$ChatSerializer"), "a", String.class); + craftBukkitEntityPlayerGetHandleMethod = getMethod(getOBCClass("entity.CraftPlayer"), "getHandle"); + } catch (NoSuchMethodException | NoSuchFieldException e) { + e.printStackTrace(); + } + } + + /** + * 取服务器版本 如 v1_10_R1 + *

+ * get the server version, returns a string similar to v1_10_R1 + * + * @return server version + */ + public static String getVersion() { + return version; + } + + /** + * 取 org.bukkit.craftbukkit 包下的类对象 + *

+ * get org.bukkit.craftbukkit's class object + * + * @param className a class's name in the package obc + * @return {@link Class} + */ + public static Class getOBCClass(String className) { + try { + return Class.forName("org.bukkit.craftbukkit." + NMSUtils.getVersion() + "." + className); + } catch (ClassNotFoundException e) { + e.printStackTrace(); + } + return null; + } + + /** + * 将NMSItem转换为BukkitItem + *

+ * Convert NMS Item to Bukkit Item + * + * @param nmsItem the NMSItem Object + * @return {@link Object} + */ + public static Object getBukkitItem(Object nmsItem) { + if (asBukkitCopyMethod == null) { + try { + asNMSCopyMethod = getMethod(getOBCClass("inventory.CraftItemStack"), "asNMSCopy", ItemStack.class); + } catch (Exception e) { + e.printStackTrace(); + } + } + try { + return invokeMethod(asBukkitCopyMethod, null, nmsItem); + } catch (Exception e) { + e.printStackTrace(); + } + return null; + } + + /** + * 取物品的 NMS 对象 + *

+ * get a item's nms object + * + * @param itemStack a itemStack object + * @return {@link Object} + */ + public static Object getNMSItem(ItemStack itemStack) { + Validate.notNull(itemStack); + + if (asNMSCopyMethod == null) { + Class craftItemStack = NMSUtils.getOBCClass("inventory.CraftItemStack"); + System.out.println("CIS: " + craftItemStack); + + try { + // CraftItemStack + asNMSCopyMethod = getMethod(craftItemStack, "asNMSCopy", ItemStack.class); + } catch (Exception e) { + e.printStackTrace(); + } + } + try { + return ReflectionUtils.invokeMethod(asNMSCopyMethod, null, itemStack); + } catch (Exception e) { + e.printStackTrace(); + } + return itemStack; + } + + /** + * 取对应的 NMS 下的类 + *

+ * get net.minecraft.server's class object + * + * @param className a class's name in the package nms + * @return {@link Class} + */ + public static Class getNMSClass(String className) { + try { + return Class.forName("net.minecraft.server." + version + "." + className); + } catch (Exception e) { + System.out.println("错误: " + e.getMessage()); + } + return null; + } + + /** + * 给一名玩家发送 NMS 数据包 + *

+ * send a NMS packet to a player + * + * @param player player object + * @param packet packet object + * @see #getNMSPlayer(Player) + * @see ReflectionUtils#invokeMethod(Method, Object, Object...) + */ + public static void sendPacket(Player player, Object packet) { + Object entityPlayer = getNMSPlayer(player); + + if (playerConnectionField == null) { + try { + playerConnectionField = getFieldByFieldName(getNMSClass("EntityPlayer"), "playerConnection"); + } catch (NoSuchFieldException e) { + e.printStackTrace(); + } + } + + if (sendPacketMethod == null) { + try { + sendPacketMethod = getMethod(getNMSClass("PlayerConnection"), "sendPacket", getNMSClass("Packet")); + } catch (NoSuchMethodException e) { + e.printStackTrace(); + } + } + + try { + // get playerConnection instance + Object playerConnection = playerConnectionField.get(entityPlayer); + // invoke method sendPacket() + invokeMethod(sendPacketMethod, playerConnection, packet); + } catch (Exception e) { + e.printStackTrace(); + } + } + + /** + * 取玩家的 NMS 对象 + *

+ * get a player's nms object + * + * @param player player object + * @return {@link Object} + * @see ReflectionUtils#invokeMethod(Method, Object, Object...) + */ + public static Object getNMSPlayer(Player player) { + try { + return invokeMethod(craftBukkitEntityPlayerGetHandleMethod, player); + } catch (Exception e) { + e.printStackTrace(); + } + return player; + } + + /** + * 将一行文本转换为 IChatBaseComponent 对象 + *

+ * Convert a text to IChatBaseComponent + * + * @param text String object + * @return {@link Object} + * @see ReflectionUtils#getMethod(Class, String, Class[]) + */ + public static Object stringToIChatBaseComponent(String text) { + if (stringAsIChatBaseComponentMethod == null) { + try { + // IChatBaseComponent$ChatSerializer + stringAsIChatBaseComponentMethod = getMethod(getNMSClass("IChatBaseComponent$ChatSerializer"), "a", String.class); + } catch (Exception e) { + e.printStackTrace(); + } + } + + try { + return invokeMethod(stringAsIChatBaseComponentMethod, Validate.notNull(text)); + } catch (Exception e) { + e.printStackTrace(); + return null; + } + } +} diff --git a/src/main/java/cc/zoyn/core/util/NameTagUtils.java b/common/src/main/java/cc/zoyn/core/util/NameTagUtils.java similarity index 93% rename from src/main/java/cc/zoyn/core/util/NameTagUtils.java rename to common/src/main/java/cc/zoyn/core/util/NameTagUtils.java index 2693085..1abc50a 100644 --- a/src/main/java/cc/zoyn/core/util/NameTagUtils.java +++ b/common/src/main/java/cc/zoyn/core/util/NameTagUtils.java @@ -6,7 +6,11 @@ import java.lang.reflect.Field; -public class NameTagUtils { +public final class NameTagUtils { + + // Prevent accidental construction + private NameTagUtils() { + } public static void changeName(String name, Player player) { try { diff --git a/src/main/java/cc/zoyn/core/util/StringUtils.java b/common/src/main/java/cc/zoyn/core/util/StringUtils.java similarity index 63% rename from src/main/java/cc/zoyn/core/util/StringUtils.java rename to common/src/main/java/cc/zoyn/core/util/StringUtils.java index 323e2fb..50cff03 100644 --- a/src/main/java/cc/zoyn/core/util/StringUtils.java +++ b/common/src/main/java/cc/zoyn/core/util/StringUtils.java @@ -2,31 +2,37 @@ import java.util.regex.Pattern; -public class StringUtils { +public final class StringUtils { - public static boolean IsChinese(String str) { + // Prevent accidental construction + private StringUtils() { + } + + /** + * Determine whether a string is Chinese + * + * @param str string object + * @return true mean yes / false mean no + */ + public static boolean isChinese(String str) { Pattern pattern = Pattern.compile("[一-龥]*"); return pattern.matcher(str).matches(); } /** - * 字符串转16进制 - * PU: --> 50553A - * 在线工具:http://www.bejson.com/convert/ox2str/ + * Convert String to Hex String */ public static String convertStringToHex(String str) { char[] chars = str.toCharArray(); - StringBuffer hex = new StringBuffer(); - for (int i = 0; i < chars.length; i++) { - hex.append(Integer.toHexString((int) chars[i])); + StringBuilder hex = new StringBuilder(); + for (char charObj : chars) { + hex.append(Integer.toHexString((int) charObj)); } return hex.toString().toUpperCase(); } /** - * 16进制转换成字符串 - * 50553A --> PU: - * 在线工具:http://www.bejson.com/convert/ox2str/ + * Convert Hex String to String */ public static String convertHexToString(String hex) { diff --git a/common/src/main/java/cc/zoyn/core/util/TabUtils.java b/common/src/main/java/cc/zoyn/core/util/TabUtils.java new file mode 100644 index 0000000..a370db6 --- /dev/null +++ b/common/src/main/java/cc/zoyn/core/util/TabUtils.java @@ -0,0 +1,55 @@ +package cc.zoyn.core.util; + +import com.comphenix.protocol.PacketType; +import com.comphenix.protocol.ProtocolLibrary; +import com.comphenix.protocol.ProtocolManager; +import com.comphenix.protocol.events.PacketContainer; +import com.comphenix.protocol.wrappers.WrappedChatComponent; +import org.apache.commons.lang3.Validate; +import org.bukkit.ChatColor; +import org.bukkit.entity.Player; + +import javax.annotation.Nullable; +import java.lang.reflect.InvocationTargetException; + +public final class TabUtils { + + // Prevent accidental construction + private TabUtils() { + + } + + /** + * 更改一个玩家的Tab列表 + *

+ * change a player's tab + * + * @param player player + * @param head tab's head + * @param foot tab's foot + */ + public static void setTab(@Nullable Player player, @Nullable String head, @Nullable String foot) { + Validate.notNull(player); + + String translatedHead = ""; + String translatedFoot = ""; + if (head != null) { + translatedHead = ChatColor.translateAlternateColorCodes('&', head); + } + if (foot != null) { + translatedFoot = ChatColor.translateAlternateColorCodes('&', foot); + } + + // get ProtocolManager instance + ProtocolManager protocolManager = ProtocolLibrary.getProtocolManager(); + PacketContainer packet = protocolManager.createPacket(PacketType.Play.Server.PLAYER_LIST_HEADER_FOOTER); + packet.getChatComponents() + .write(0, WrappedChatComponent.fromText(translatedHead)) + .write(1, WrappedChatComponent.fromText(translatedFoot)); + try { + protocolManager.sendServerPacket(player, packet); + } catch (InvocationTargetException e) { + e.printStackTrace(); + } + } +} diff --git a/common/src/main/java/cc/zoyn/core/util/TimeUtils.java b/common/src/main/java/cc/zoyn/core/util/TimeUtils.java new file mode 100644 index 0000000..e18644b --- /dev/null +++ b/common/src/main/java/cc/zoyn/core/util/TimeUtils.java @@ -0,0 +1,100 @@ +package cc.zoyn.core.util; + +import org.apache.commons.lang3.Validate; + +import java.text.SimpleDateFormat; +import java.util.Calendar; +import java.util.Date; + +public final class TimeUtils { + + private static final int YEAR = 365 * 24 * 60 * 60; // one year's int data + private static final int MONTH = 30 * 24 * 60 * 60; // one month's int data + private static final int DAY = 24 * 60 * 60; // one day's int data + private static final int HOUR = 60 * 60; // one hour int data + private static final int MINUTE = 60; // one minute int data + private static final String DEFAULT_DATE_FORMAT = "yyyy-MM-dd HH:mm:ss"; + private static final String CHINESE_DATE_FORMAT = "yyyy年MM月dd日 HH:mm:ss"; + + // Prevent accidental construction + private TimeUtils() { + } + + /** + * 根据时间戳获取描述性时间,如3分钟前,1天前 + * + * @param timestamp 时间戳 单位为毫秒 + * @return 时间字符串 + */ + public static String getDescriptionTimeFromTimestamp(long timestamp) { + long currentTime = System.currentTimeMillis(); + long timeGap = (currentTime - timestamp) / 1000;// 与现在时间相差秒数 + String timeStr; + if (timeGap > YEAR) { + timeStr = timeGap / YEAR + "年前"; + } else if (timeGap > MONTH) { + timeStr = timeGap / MONTH + "个月前"; + } else if (timeGap > DAY) {// 1天以上 + timeStr = timeGap / DAY + "天前"; + } else if (timeGap > HOUR) {// 1小时-24小时 + timeStr = timeGap / HOUR + "小时前"; + } else if (timeGap > MINUTE) {// 1分钟-59分钟 + timeStr = timeGap / MINUTE + "分钟前"; + } else {// 1秒钟-59秒钟 + timeStr = "刚刚"; + } + return timeStr; + } + + /** + * 判断今日是否为休假日 + *

+ * check today is week + * + * @return true -> yes / false -> no + */ + public static boolean isWeekDay() { + Calendar calendar = Calendar.getInstance(); + return calendar.get(Calendar.DAY_OF_WEEK) == Calendar.SATURDAY || calendar.get(Calendar.DAY_OF_WEEK) == Calendar.SUNDAY; + } + + /** + * 日期格式化 + *

+ * format a date + * + * @param date dateObj + * @param simpleDataFormat simpleDataFormatObj + * @return formattedDateString + */ + public static String getFormattedDate(Date date, SimpleDateFormat simpleDataFormat) { + return Validate.notNull(simpleDataFormat).format(date); + } + + /** + * 日期格式化,默认日期格式 yyyy-MM-dd + *

+ * format a date, use yyyy-MM-dd + * + * @param date dateObj + * @return formattedDateString + */ + public static String getDefaultFormatDate(Date date) { + return getFormattedDate(date, new SimpleDateFormat(DEFAULT_DATE_FORMAT)); + } + + /** + * 日期格式化,默认日期格式 yyyy年MM月dd日 + *

+ * format a date, use yyyy年MM月dd日 + * + * @param date dateObj + * @return formattedDateString + */ + public static String getChineseDateFormat(Date date) { + return getFormattedDate(date, new SimpleDateFormat(CHINESE_DATE_FORMAT)); + } + + +} + diff --git a/src/main/java/cc/zoyn/core/util/TitleUtils.java b/common/src/main/java/cc/zoyn/core/util/TitleUtils.java similarity index 58% rename from src/main/java/cc/zoyn/core/util/TitleUtils.java rename to common/src/main/java/cc/zoyn/core/util/TitleUtils.java index 341b0e4..61722e9 100644 --- a/src/main/java/cc/zoyn/core/util/TitleUtils.java +++ b/common/src/main/java/cc/zoyn/core/util/TitleUtils.java @@ -7,7 +7,6 @@ import com.comphenix.protocol.wrappers.EnumWrappers; import com.comphenix.protocol.wrappers.WrappedChatComponent; import org.bukkit.ChatColor; -import org.bukkit.Location; import org.bukkit.entity.Player; import java.lang.reflect.InvocationTargetException; @@ -15,12 +14,17 @@ /** * Title工具类 * - * @author Zoyn + * @author Zoyn, D_xiaox * @since 2016/12/26 - * + *

* update 2017/8/05 + * update 2018/8/02 星空(D_xiaox) */ -public class TitleUtils { +public final class TitleUtils { + + // Prevent accidental construction + private TitleUtils() { + } /** * 给一个玩家发送Title信息 1.8+ @@ -32,28 +36,18 @@ public class TitleUtils { * @param title 主标题 * @param subTitle 副标题 */ - public static void sendTitle(Player player, Integer fadeIn, Integer stay, Integer fadeOut, String title, - String subTitle) { - // 获取PL管理 + public static void sendTitle(Player player, Integer fadeIn, Integer stay, Integer fadeOut, String title, String subTitle) { + // get protocol manager instance ProtocolManager pm = ProtocolLibrary.getProtocolManager(); - PacketContainer packet = null; + PacketContainer packet; if (title != null) { - title = ChatColor.translateAlternateColorCodes('&', title); // 支持&颜色代码 - title = title.replaceAll("%player%", player.getName()); - // 创建标题数据包 + String translatedTitle = ChatColor.translateAlternateColorCodes('&', title); + translatedTitle = translatedTitle.replaceAll("%player%", player.getName()); + // create packet packet = pm.createPacket(PacketType.Play.Server.TITLE); - // nms内封包结构为 - /* - * private EnumTitleAction a; private IChatBaseComponent b; private int c; - * private int d; private int e; - */ - // 按顺序往里写入数据 + // write datas packet.getTitleActions().write(0, EnumWrappers.TitleAction.TITLE); // EnumTitleAction - packet.getChatComponents().write(0, WrappedChatComponent.fromText(title)); // 标题内容 - packet.getIntegers() - .write(0, fadeIn) // ---> c - .write(1, stay) // ---> d - .write(2, fadeOut); // ---> e + packet.getChatComponents().write(0, WrappedChatComponent.fromText(translatedTitle)); // 标题内容 try { pm.sendServerPacket(player, packet, false); // 发送数据包 } catch (InvocationTargetException e) { @@ -62,19 +56,31 @@ public static void sendTitle(Player player, Integer fadeIn, Integer stay, Intege } if (subTitle != null) { - subTitle = ChatColor.translateAlternateColorCodes('&', subTitle); // 支持&颜色代码 - subTitle = subTitle.replaceAll("%player%", player.getName()); + String translatedSubTitle = ChatColor.translateAlternateColorCodes('&', subTitle); + translatedSubTitle = translatedSubTitle.replaceAll("%player%", player.getName()); + packet = pm.createPacket(PacketType.Play.Server.TITLE); packet.getTitleActions().write(0, EnumWrappers.TitleAction.SUBTITLE); - packet.getChatComponents().write(0, WrappedChatComponent.fromText(subTitle)); - packet.getIntegers().write(0, fadeIn); - packet.getIntegers().write(1, stay); - packet.getIntegers().write(2, fadeOut); + packet.getChatComponents().write(0, WrappedChatComponent.fromText(translatedSubTitle)); try { pm.sendServerPacket(player, packet, false); } catch (InvocationTargetException e) { e.printStackTrace(); } } + + // 以前无法设置时间, 现在可以了 + packet = pm.createPacket(PacketType.Play.Server.TITLE); + packet.getTitleActions().write(0, EnumWrappers.TitleAction.TIMES); + packet.getIntegers() + .write(0, fadeIn) // ---> c + .write(1, stay) // ---> d + .write(2, fadeOut); // ---> e + try { + pm.sendServerPacket(player, packet, false); + } catch (InvocationTargetException e) { + e.printStackTrace(); + } + } } diff --git a/common/src/main/java/cc/zoyn/core/util/nbt/NBTUtils.java b/common/src/main/java/cc/zoyn/core/util/nbt/NBTUtils.java new file mode 100644 index 0000000..a0920ea --- /dev/null +++ b/common/src/main/java/cc/zoyn/core/util/nbt/NBTUtils.java @@ -0,0 +1,380 @@ +package cc.zoyn.core.util.nbt; + +import cc.zoyn.core.util.NMSUtils; +import cc.zoyn.core.util.reflect.ReflectionUtils; +import org.bukkit.Material; +import org.bukkit.inventory.ItemStack; + +import java.lang.reflect.Constructor; +import java.lang.reflect.Method; +import java.util.List; + +public class NBTUtils { + + private static Class NMS_ITEM_STACK; + private static Class NBT_TAG_LIST; + public static Class NBT_TAG_COMPOUND; + + /* The method of NMSItem */ + private static Method HAS_TAG; + private static Method GET_TAG; + private static Method SET_TAG; + + /* The method of NBTTagCompound */ + private static Method SET_DATA; + private static Method SET_INT; + private static Method SET_STRING; + private static Method SET_SHORT; + private static Method SET_BYTE; + private static Method SET_LONG; + private static Method SET_FLOAT; + private static Method SET_DOUBLE; + private static Method SET_INT_ARRAY; + private static Method SET_BYTE_ARRAY; + private static Method SET_BOOLEAN; + + /* The method of NBTTagList */ + private static Method ADD; + private static Method GET; + private static Method REMOVE; + + // It's public ItemStack(NBTTagCompound nbtTagCompound) + private static Constructor NMS_ITEM_STACK_CONSTRUCTOR_WITH_NBT; + + static { + try { + NMS_ITEM_STACK = NMSUtils.getNMSClass("ItemStack"); + NBT_TAG_COMPOUND = NMSUtils.getNMSClass("NBTTagCompound"); + NBT_TAG_LIST = NMSUtils.getNMSClass("NBTTagList"); + + NMS_ITEM_STACK_CONSTRUCTOR_WITH_NBT = NMS_ITEM_STACK.getConstructor(NBT_TAG_COMPOUND); + + HAS_TAG = ReflectionUtils.getMethod(NMS_ITEM_STACK, "hasTag"); + GET_TAG = ReflectionUtils.getMethod(NMS_ITEM_STACK, "getTag"); + SET_TAG = ReflectionUtils.getMethod(NMS_ITEM_STACK, "setTag", NBT_TAG_COMPOUND); + + SET_INT = ReflectionUtils.getMethod(NBT_TAG_COMPOUND, "setInt", String.class, Integer.TYPE); + SET_STRING = ReflectionUtils.getMethod(NBT_TAG_COMPOUND, "setString", String.class, String.class); + SET_SHORT = ReflectionUtils.getMethod(NBT_TAG_COMPOUND, "setShort", String.class, Short.TYPE); + SET_BYTE = ReflectionUtils.getMethod(NBT_TAG_COMPOUND, "setByte", String.class, Byte.TYPE); + SET_LONG = ReflectionUtils.getMethod(NBT_TAG_COMPOUND, "setInt", String.class, Long.TYPE); + SET_FLOAT = ReflectionUtils.getMethod(NBT_TAG_COMPOUND, "setFloat", String.class, Float.TYPE); + SET_DOUBLE = ReflectionUtils.getMethod(NBT_TAG_COMPOUND, "setDouble", String.class, Double.TYPE); + SET_INT_ARRAY = ReflectionUtils.getMethod(NBT_TAG_COMPOUND, "setIntArray", String.class, int[].class); + SET_BYTE_ARRAY = ReflectionUtils.getMethod(NBT_TAG_COMPOUND, "setByteArray", String.class, byte[].class); + SET_BOOLEAN = ReflectionUtils.getMethod(NBT_TAG_COMPOUND, "setBoolean", String.class, Boolean.TYPE); + SET_DATA = ReflectionUtils.getMethod(NBT_TAG_COMPOUND, "set", String.class, NMSUtils.getNMSClass("NBTBase")); + + ADD = ReflectionUtils.getMethod(NBT_TAG_LIST, "add", NMSUtils.getNMSClass("NBTBase")); + GET = ReflectionUtils.getMethod(NBT_TAG_LIST, "get", Integer.TYPE); + REMOVE = ReflectionUtils.getMethod(NBT_TAG_LIST, "remove", Integer.TYPE); + } catch (Exception e) { + e.printStackTrace(); + } + } + + // Prevent accidental construction + private NBTUtils() { + } + + /** + * Get the item nbt + * + * @param itemStack the ItemStack + * @return {@link TagCompound} + */ + public static TagCompound getItemStackNBT(ItemStack itemStack) { + return new TagCompound(getOriginalItemStackNBT(itemStack)); + } + + /** + * Get the original item nbt + * + * @param itemStack the ItemStack + * @return {@link Object} + */ + public static Object getOriginalItemStackNBT(ItemStack itemStack) { + if (itemStack == null || itemStack.getType().equals(Material.AIR)) { + return null; + } + Object nmsItem = NMSUtils.getNMSItem(itemStack); + Object nbtTag = null; + try { + // check the item has nbttag + if (ReflectionUtils.invokeMethod(HAS_TAG, nmsItem).equals(true)) { + nbtTag = ReflectionUtils.invokeMethod(GET_TAG, nmsItem); + } else { + nbtTag = newNBTTagCompound(); + } + } catch (Exception e) { + e.printStackTrace(); + } + return nbtTag; + } + + /** + * Return an NMSItem with the given nbt + * + * @param nbtTagCompound the nbt + * @return {@link Object} + */ + public static Object newNMSItemStack(Object nbtTagCompound) { + try { + return ReflectionUtils.instantiateObject(NMS_ITEM_STACK_CONSTRUCTOR_WITH_NBT, nbtTagCompound); + } catch (Exception e) { + e.printStackTrace(); + } + return null; + } + + /** + * Return a empty NBTTagCompound + * + * @return {@link Object} + */ + public static Object newNBTTagCompound() { + try { + return ReflectionUtils.instantiateObject(NBT_TAG_COMPOUND.getDeclaredConstructor()); + } catch (Exception e) { + e.printStackTrace(); + } + return null; + } + + /** + * Return a empty NBTTagList + * + * @return {@link Object} + */ + public static Object newNBTTagList() { + try { + return ReflectionUtils.instantiateObject(NBT_TAG_LIST.getDeclaredConstructor()); + } catch (Exception e) { + e.printStackTrace(); + } + return null; + } + + /** + * Set the item nbt, and return the BukkitItem + * + * @param nbtTagCompound the nbt + * @param itemStack the item + * @return {@link ItemStack} + */ + public static ItemStack setItemStackNBT(Object nbtTagCompound, ItemStack itemStack) { + Object nmsItem = NMSUtils.getNMSItem(itemStack); + Object bukkitItem = null; + try { + ReflectionUtils.invokeMethod(SET_TAG, nmsItem, nbtTagCompound); + bukkitItem = NMSUtils.getBukkitItem(nmsItem); + } catch (Exception e) { + e.printStackTrace(); + } + + return (ItemStack) bukkitItem; + } + + /** + * 利用给定的数据来设置nbt + *

+ * Use the given data to set nbt + * + * @param nbtTagCompound the nbt + * @param key the key of json object + * @param value the value of json object + * @throws Exception When the Set method is null, it will throw an excpetion + */ + public static void setTagCompound(Object nbtTagCompound, String key, Object value) throws Exception { + ReflectionUtils.invokeMethod(SET_DATA, nbtTagCompound, key, value); + } + + /** + * 利用给定的数据来设置nbt + *

+ * Use the given data to set nbt + * + * @param nbtTagCompound the nbt + * @param key the key of json object + * @param value the value of json object + * @throws Exception When the Set method is null, it will throw an excpetion + */ + public static void setListTagCompound(Object nbtTagCompound, String key, List value) throws Exception { + Object nbtTagList = newNBTTagList(); + value.forEach(tagCompound -> { + try { + ReflectionUtils.invokeMethod(ADD, nbtTagList, tagCompound.build()); + } catch (Exception e) { + e.printStackTrace(); + } + }); + setTagCompound(nbtTagCompound, key, nbtTagList); + } + + /** + * 利用index来移除一个NBTTagList里的NBTBase数据 + *

+ * Use index to remove NBTBase data from an NBTTagList + * + * @param nbtTagList the nbt tag list + * @param index the index + * @throws Exception When the Remove method is null or the nbtTagList object is not an object of NBTTagList, it will throw an excpetion + */ + public static void removeTagCompound(Object nbtTagList, int index) throws Exception { + ReflectionUtils.invokeMethod(REMOVE, nbtTagList, index); + } + + /** + * 利用index来获取一个NBTTagList里的NBTBase数据 + *

+ * Use index to get NBTBase data from an NBTTagList + * + * @param nbtTagList the nbt tag list + * @param index the index + * @throws Exception When the Get method is null or the nbtTagList object is not an object of NBTTagList, it will throw an excpetion + */ + public static TagCompound getTagCompound(Object nbtTagList, int index) throws Exception { + return new TagCompound(ReflectionUtils.invokeMethod(GET, nbtTagList, index)); + } + + /** + * 利用给定的数据来设置nbt + *

+ * Use the given data to set nbt + * + * @param nbtTagCompound the nbt + * @param key the key of json object + * @param value the value of json object + * @throws Exception When the Set method is null, it will throw an excpetion + */ + public static void setInt(Object nbtTagCompound, String key, int value) throws Exception { + ReflectionUtils.invokeMethod(SET_INT, nbtTagCompound, key, value); + } + + /** + * 利用给定的数据来设置nbt + *

+ * Use the given data to set nbt + * + * @param nbtTagCompound the nbt + * @param key the key of json object + * @param value the value of json object + * @throws Exception When the Set method is null, it will throw an excpetion + */ + public static void setString(Object nbtTagCompound, String key, String value) throws Exception { + ReflectionUtils.invokeMethod(SET_STRING, nbtTagCompound, key, value); + } + + /** + * 利用给定的数据来设置nbt + *

+ * Use the given data to set nbt + * + * @param nbtTagCompound the nbt + * @param key the key of json object + * @param value the value of json object + * @throws Exception When the Set method is null, it will throw an excpetion + */ + public static void setShort(Object nbtTagCompound, String key, short value) throws Exception { + ReflectionUtils.invokeMethod(SET_SHORT, nbtTagCompound, key, value); + } + + /** + * 利用给定的数据来设置nbt + *

+ * Use the given data to set nbt + * + * @param nbtTagCompound the nbt + * @param key the key of json object + * @param value the value of json object + * @throws Exception When the Set method is null, it will throw an excpetion + */ + public static void setByte(Object nbtTagCompound, String key, byte value) throws Exception { + ReflectionUtils.invokeMethod(SET_BYTE, nbtTagCompound, key, value); + } + + /** + * 利用给定的数据来设置nbt + *

+ * Use the given data to set nbt + * + * @param nbtTagCompound the nbt + * @param key the key of json object + * @param value the value of json object + * @throws Exception When the Set method is null, it will throw an excpetion + */ + public static void setLong(Object nbtTagCompound, String key, long value) throws Exception { + ReflectionUtils.invokeMethod(SET_LONG, nbtTagCompound, key, value); + } + + /** + * 利用给定的数据来设置nbt + *

+ * Use the given data to set nbt + * + * @param nbtTagCompound the nbt + * @param key the key of json object + * @param value the value of json object + * @throws Exception When the Set method is null, it will throw an excpetion + */ + public static void setFloat(Object nbtTagCompound, String key, float value) throws Exception { + ReflectionUtils.invokeMethod(SET_FLOAT, nbtTagCompound, key, value); + } + + /** + * 利用给定的数据来设置nbt + *

+ * Use the given data to set nbt + * + * @param nbtTagCompound the nbt + * @param key the key of json object + * @param value the value of json object + * @throws Exception When the Set method is null, it will throw an excpetion + */ + public static void setDouble(Object nbtTagCompound, String key, double value) throws Exception { + ReflectionUtils.invokeMethod(SET_DOUBLE, nbtTagCompound, key, value); + } + + /** + * 利用给定的数据来设置nbt + *

+ * Use the given data to set nbt + * + * @param nbtTagCompound the nbt + * @param key the key of json object + * @param value the value of json object + * @throws Exception When the Set method is null, it will throw an excpetion + */ + public static void setIntArray(Object nbtTagCompound, String key, int[] value) throws Exception { + ReflectionUtils.invokeMethod(SET_INT_ARRAY, nbtTagCompound, key, value); + } + + /** + * 利用给定的数据来设置nbt + *

+ * Use the given data to set nbt + * + * @param nbtTagCompound the nbt + * @param key the key of json object + * @param value the value of json object + * @throws Exception When the Set method is null, it will throw an excpetion + */ + public static void setByteArray(Object nbtTagCompound, String key, byte[] value) throws Exception { + ReflectionUtils.invokeMethod(SET_BYTE_ARRAY, nbtTagCompound, key, value); + } + + /** + * 利用给定的数据来设置nbt + *

+ * Use the given data to set nbt + * + * @param nbtTagCompound the nbt + * @param key the key of json object + * @param value the value of json object + * @throws Exception When the Set method is null, it will throw an excpetion + */ + public static void setBoolean(Object nbtTagCompound, String key, boolean value) throws Exception { + ReflectionUtils.invokeMethod(SET_BOOLEAN, nbtTagCompound, key, value); + } + +} diff --git a/common/src/main/java/cc/zoyn/core/util/nbt/TagCompound.java b/common/src/main/java/cc/zoyn/core/util/nbt/TagCompound.java new file mode 100644 index 0000000..6c2d6dd --- /dev/null +++ b/common/src/main/java/cc/zoyn/core/util/nbt/TagCompound.java @@ -0,0 +1,125 @@ +package cc.zoyn.core.util.nbt; + +import com.google.common.collect.Maps; + +import java.util.List; +import java.util.Map; + +public class TagCompound { + private Object nbtTagCompound; + + private Map data = Maps.newHashMap(); + + public TagCompound() { + this.nbtTagCompound = NBTUtils.newNBTTagCompound(); + } + + public TagCompound(Object nbtTagCompound) { + this.nbtTagCompound = nbtTagCompound; + } + + public Object getNBTTagCompound() { + return nbtTagCompound; + } + + public Map getData() { + return data; + } + + public TagCompound put(String key, Object value) { + data.put(key, value); + return this; + } + + public TagCompound putListCompound(String key, List value) { + data.put(key, value); + return this; + } + + public TagCompound putCompound(String key, TagCompound value) { + data.put(key, value.build()); + return this; + } + + public TagCompound putInt(String key, int value) { + data.put(key, value); + return this; + } + + public TagCompound putString(String key, String value) { + data.put(key, value); + return this; + } + + public TagCompound putShort(String key, short value) { + data.put(key, value); + return this; + } + + public TagCompound putLong(String key, long value) { + data.put(key, value); + return this; + } + + public TagCompound putDouble(String key, double value) { + data.put(key, value); + return this; + } + + public TagCompound putByte(String key, byte value) { + data.put(key, value); + return this; + } + + public TagCompound putBoolean(String key, boolean value) { + data.put(key, value); + return this; + } + + public TagCompound putIntArray(String key, int[] value) { + data.put(key, value); + return this; + } + + public TagCompound putByteArray(String key, byte[] value) { + data.put(key, value); + return this; + } + + public Object build() { + data.forEach((key, value) -> { + try { + if (value.getClass().equals(NBTUtils.NBT_TAG_COMPOUND)) { + NBTUtils.setTagCompound(nbtTagCompound, key, value); + } else if (value instanceof List) { + NBTUtils.setListTagCompound(nbtTagCompound, key, (List) value); + } else if (value instanceof Integer) { + NBTUtils.setInt(nbtTagCompound, key, (int) value); + } else if (value instanceof String) { + NBTUtils.setString(nbtTagCompound, key, (String) value); + } else if (value instanceof Short) { + NBTUtils.setShort(nbtTagCompound, key, (short) value); + } else if (value instanceof Long) { + NBTUtils.setLong(nbtTagCompound, key, (long) value); + } else if (value instanceof Double) { + NBTUtils.setDouble(nbtTagCompound, key, (double) value); + } else if (value instanceof Float) { + NBTUtils.setFloat(nbtTagCompound, key, (float) value); + } else if (value instanceof Byte) { + NBTUtils.setByte(nbtTagCompound, key, (byte) value); + } else if (value instanceof Boolean) { + NBTUtils.setBoolean(nbtTagCompound, key, (boolean) value); + } else if (value instanceof int[]) { + NBTUtils.setIntArray(nbtTagCompound, key, (int[]) value); + } else if (value instanceof byte[]) { + NBTUtils.setByteArray(nbtTagCompound, key, (byte[]) value); + } + } catch (Exception e) { + e.printStackTrace(); + } + }); + return nbtTagCompound; + } + + +} diff --git a/common/src/main/java/cc/zoyn/core/util/package-info.java b/common/src/main/java/cc/zoyn/core/util/package-info.java new file mode 100644 index 0000000..51cded3 --- /dev/null +++ b/common/src/main/java/cc/zoyn/core/util/package-info.java @@ -0,0 +1,7 @@ +/** + * Some useful util + * + * @author Zoyn + * @since 2017-12-09 + */ +package cc.zoyn.core.util; \ No newline at end of file diff --git a/common/src/main/java/cc/zoyn/core/util/page/ListPager.java b/common/src/main/java/cc/zoyn/core/util/page/ListPager.java new file mode 100644 index 0000000..50d47a7 --- /dev/null +++ b/common/src/main/java/cc/zoyn/core/util/page/ListPager.java @@ -0,0 +1,79 @@ +package cc.zoyn.core.util.page; + +import java.util.List; + +/** + * 列表分页工具类 + * + * @author Zoyn + * @since 2018/8/27 + */ +public class ListPager { + + /** + * 放入的列表 + */ + private List list; + /** + * 每页显示的个数 + */ + private int pageSize; + /** + * 所有的元素们 + */ + private int totalCount; + + /** + * 列表分页器 + * + * @param list 列表 + * @param pageSize 每页显示的个数 + */ + public ListPager(List list, int pageSize) { + this.list = list; + this.pageSize = pageSize; + this.totalCount = list.size(); + } + + /** + * 获取分页内容 + * + * @param page 页数 + * @return {@link List} + */ + public List getPage(int page) { + if (page <= 0) { + return getPage(1); + } + + List subList; + if (pageSize >= totalCount) { + subList = list; + } else { + int fromIndex = Math.min(pageSize * (page - 1), totalCount); + int endIndex = Math.min(pageSize * page, totalCount); + + subList = list.subList(fromIndex, endIndex); + } + return subList; + } + + public List getList() { + return list; + } + + public int getPageSize() { + return pageSize; + } + + public ListPager setList(List list) { + this.list = list; + this.totalCount = list.size(); + return this; + } + + public ListPager setPageSize(int pageSize) { + this.pageSize = pageSize; + return this; + } +} diff --git a/common/src/main/java/cc/zoyn/core/util/page/Pagers.java b/common/src/main/java/cc/zoyn/core/util/page/Pagers.java new file mode 100644 index 0000000..dd7d3e5 --- /dev/null +++ b/common/src/main/java/cc/zoyn/core/util/page/Pagers.java @@ -0,0 +1,22 @@ +package cc.zoyn.core.util.page; + +import com.google.common.collect.Lists; + +import java.util.List; + +/** + * 分页工具 + * + * @author Zoyn + */ +public class Pagers { + + public static ListPager newListPager(int pageSize, List list) { + return new ListPager<>(list, pageSize); + } + + public static ListPager newListPager(int pageSize, T... objects) { + return newListPager(pageSize, Lists.newArrayList(objects)); + } + +} diff --git a/common/src/main/java/cc/zoyn/core/util/page/package-info.java b/common/src/main/java/cc/zoyn/core/util/page/package-info.java new file mode 100644 index 0000000..b6aeef0 --- /dev/null +++ b/common/src/main/java/cc/zoyn/core/util/page/package-info.java @@ -0,0 +1,7 @@ +/** + * The utils for partition + * + * @author Zoyn + * @since 2017-12-09 + */ +package cc.zoyn.core.util.page; \ No newline at end of file diff --git a/common/src/main/java/cc/zoyn/core/util/reflect/ConstructorFilter.java b/common/src/main/java/cc/zoyn/core/util/reflect/ConstructorFilter.java new file mode 100644 index 0000000..670a5a7 --- /dev/null +++ b/common/src/main/java/cc/zoyn/core/util/reflect/ConstructorFilter.java @@ -0,0 +1,13 @@ +package cc.zoyn.core.util.reflect; + +import java.lang.reflect.Constructor; + +/** + * @author Zoyn + * @since 2017-12-02 + */ +public interface ConstructorFilter { + + boolean accept(Constructor constructor); + +} diff --git a/common/src/main/java/cc/zoyn/core/util/reflect/FieldFilter.java b/common/src/main/java/cc/zoyn/core/util/reflect/FieldFilter.java new file mode 100644 index 0000000..f1222e1 --- /dev/null +++ b/common/src/main/java/cc/zoyn/core/util/reflect/FieldFilter.java @@ -0,0 +1,13 @@ +package cc.zoyn.core.util.reflect; + +import java.lang.reflect.Field; + +/** + * @author Zoyn + * @since 2017-12-02 + */ +public interface FieldFilter { + + boolean accept(Field field); + +} diff --git a/common/src/main/java/cc/zoyn/core/util/reflect/MethodFilter.java b/common/src/main/java/cc/zoyn/core/util/reflect/MethodFilter.java new file mode 100644 index 0000000..a561e49 --- /dev/null +++ b/common/src/main/java/cc/zoyn/core/util/reflect/MethodFilter.java @@ -0,0 +1,13 @@ +package cc.zoyn.core.util.reflect; + +import java.lang.reflect.Method; + +/** + * @author Zoyn + * @since 2017-12-02 + */ +public interface MethodFilter { + + boolean accept(Method method); + +} diff --git a/common/src/main/java/cc/zoyn/core/util/reflect/ReflectionUtils.java b/common/src/main/java/cc/zoyn/core/util/reflect/ReflectionUtils.java new file mode 100644 index 0000000..8a57325 --- /dev/null +++ b/common/src/main/java/cc/zoyn/core/util/reflect/ReflectionUtils.java @@ -0,0 +1,374 @@ +package cc.zoyn.core.util.reflect; + +import org.apache.commons.lang3.Validate; + +import java.lang.reflect.Constructor; +import java.lang.reflect.Field; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; + +/** + * Easy to reflect + * + * @author Zoyn + * @since 2017-12-02 + */ +public final class ReflectionUtils { + + // Prevent accidental construction + private ReflectionUtils() { + } + + /** + * get field objects by using field names + * + * @param clazz class's object + * @param fieldName field's name + * @return {@link Field} + * @throws NoSuchFieldException If the field with the specified name cannot be found + * @see #hasField(Class, String) + */ + public static Field getFieldByFieldName(Class clazz, String fieldName) throws NoSuchFieldException { + Field field = null; + if (hasField(clazz, fieldName)) { + field = clazz.getField(fieldName); + } + return field; + } + + /** + * @param classPath class's path + * @param fieldName field's name + * @return {@link Field} + * @throws ClassNotFoundException If the class cannot be found + * @throws NoSuchFieldException If the field with the specified name cannot be found + * @see #getFieldByFieldName(Class, String) + */ + public static Field getFieldByFieldName(String classPath, String fieldName) throws ClassNotFoundException, NoSuchFieldException { + return getFieldByFieldName(Class.forName(classPath), fieldName); + } + + + /** + * get a Value field + * + * @param obj object + * @param fieldName field's name + * @return {@link Object} + * @throws IllegalAccessException If the field is accessible + * @see #getFieldByFieldName(Class, String) + */ + public static Object getValueByFieldName(Object obj, String fieldName) throws IllegalAccessException, NoSuchFieldException { + Field field = getFieldByFieldName(obj.getClass(), fieldName); + Object value = null; + + if (field != null) { + if (field.isAccessible()) { + value = field.get(obj); + } else { + field.setAccessible(true); + value = field.get(obj); + field.setAccessible(false); + } + } + return value; + } + + /** + * set a object's Value field + * + * @param obj object + * @param fieldName field's name + * @param value the value to be set + * @throws NoSuchFieldException If the field is missing + */ + public static void setValueByFieldName(Object obj, String fieldName, Object value) throws NoSuchFieldException, IllegalAccessException { + Field field = obj.getClass().getDeclaredField(fieldName); + if (field.isAccessible()) { + field.set(obj, value); + } else { + field.setAccessible(true); + field.set(obj, value); + field.setAccessible(false); + } + } + + /** + * get a class's constructor + * + * @param clazz class's object + * @param parameterTypes parameters + * @return {@link Constructor} + * @throws NoSuchMethodException If the constructor with the specified parameter types cannot be found + * @see #hasConstructor(Class, Class[]) + */ + public static Constructor getConstructor(Class clazz, Class... parameterTypes) throws NoSuchMethodException { + Constructor constructor = null; + if (hasConstructor(clazz, parameterTypes)) { + constructor = clazz.getDeclaredConstructor(parameterTypes); + } + return constructor; + } + + /** + * get a class's constructor + * + * @param classPath class's path + * @param parameterTypes parameters + * @return {@link Constructor} + * @throws ClassNotFoundException If the class cannot be found + * @throws NoSuchMethodException If the constructor with the specified parameter types cannot be found + * @see #getConstructor(Class, Class[]) + */ + public static Constructor getConstructor(String classPath, Class... parameterTypes) throws ClassNotFoundException, NoSuchMethodException { + return getConstructor(Class.forName(classPath), parameterTypes); + } + + + /** + * Constructing an object with a constructor + * + * @param constructor the Constructor + * @param arguments the constructor's arguments + * @return {@link Object} + * @throws IllegalAccessException If the desired constructor cannot be accessed due to certain circumstances + * @throws InvocationTargetException If the desired constructor cannot be invoked + * @throws InstantiationException If you cannot create an instance of the target class due to certain circumstances + */ + public static Object instantiateObject(Constructor constructor, Object... arguments) throws IllegalAccessException, InvocationTargetException, InstantiationException { + return Validate.notNull(constructor).newInstance(arguments); + } + + /** + * get a method in a class + * + * @param clazz class's object + * @param methodName method's name + * @param parameterTypes the method's arguments + * @return {@link Method} + * @throws NoSuchMethodException If the method with the specified parameter types cannot be found + */ + public static Method getMethod(Class clazz, String methodName, Class... parameterTypes) throws NoSuchMethodException { + if (hasMethod(clazz, methodName, parameterTypes)) { + return clazz.getDeclaredMethod(methodName, parameterTypes); + } + return null; + } + + /** + * get a method in a class + * + * @param classPath class's path + * @param methodName method's name + * @param parameterTypes the method's arguments + * @return {@link Method} + * @throws ClassNotFoundException If the class cannot be found + * @throws NoSuchMethodException If the method with the specified parameter types cannot be found + * @see #getMethod(Class, String, Class[]) + */ + public static Method getMethod(String classPath, String methodName, Class... parameterTypes) throws ClassNotFoundException, NoSuchMethodException { + return getMethod(Class.forName(classPath), methodName, parameterTypes); + } + + /** + * Invoke a method + * + * @param method the method object + * @param object the object will be invoke + * @param arguments the method arguments + * @return {@link Object} + * @throws InvocationTargetException If the desired method cannot be invoked + * @throws IllegalAccessException If the desired method cannot be accessed due to certain circumstances + */ + public static Object invokeMethod(Method method, Object object, Object... arguments) throws InvocationTargetException, IllegalAccessException { + Validate.notNull(method); + Object o; + + if (method.isAccessible()) { + o = method.invoke(object, arguments); + } else { + method.setAccessible(true); + o = method.invoke(object, arguments); + method.setAccessible(false); + } + return o; + } + + /** + * Invoke a method + * + * @param methodName the method name + * @param object the object will be invoke + * @param arguments the method arguments + * @return {@link Object} + * @throws InvocationTargetException If the desired method cannot be invoked + * @throws IllegalAccessException If the desired method cannot be accessed due to certain circumstances + */ + public static Object invokeMethod(String methodName, Object object, Object... arguments) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException { + Method method; + Class[] classes = new Class[0]; + for (int i = 0; i < arguments.length; i++) { + classes[i] = arguments[i].getClass(); + } + + method = getMethod(object.getClass(), methodName, classes); + return invokeMethod(method, object, arguments); + } + + /** + * check a class has a specified field + * + * @param clazz class's object + * @param fieldName field's name + * @return return true if the field is exist + */ + public static boolean hasField(Class clazz, String fieldName) { + boolean has; + + try { + Validate.notNull(clazz).getDeclaredField(fieldName); + has = true; + } catch (NoSuchFieldException e) { + has = false; + } + return has; + } + + /** + * check a class has a specified field + * + * @param clazz class's object + * @param filter filter obj + * @return return true if the field is exist + */ + public static boolean hasField(Class clazz, FieldFilter filter) { + Validate.notNull(filter); + + boolean has = false; + Field[] fields = clazz.getDeclaredFields(); + for (Field field : fields) { + if (filter.accept(field)) { + has = true; + break; + } + } + return has; + } + + /** + * check a class has a specified field + * + * @param classPath class's path + * @param fieldName field's name + * @return return true if the field is exist + * @see #hasField(Class, String) + */ + public static boolean hasField(String classPath, String fieldName) throws ClassNotFoundException { + return hasField(Class.forName(classPath), fieldName); + } + + /** + * check a class has a specified constructor + * + * @param clazz class's object + * @param parameterTypes the constructor with the specified parameter types + * @return return true if the constructor is exist + */ + public static boolean hasConstructor(Class clazz, Class... parameterTypes) { + boolean has; + try { + Validate.notNull(clazz).getDeclaredConstructor(parameterTypes); + has = true; + } catch (NoSuchMethodException e) { + has = false; + } + return has; + } + + /** + * check a class has a specified constructor + * + * @param clazz class's object + * @param filter filter obj + * @return return true if the constructor is exist + */ + public static boolean hasConstructor(Class clazz, ConstructorFilter filter) { + Validate.notNull(filter); + + boolean has = false; + Constructor[] constructors = clazz.getDeclaredConstructors(); + for (Constructor constructor : constructors) { + if (filter.accept(constructor)) { + has = true; + break; + } + } + return has; + } + + /** + * check a class has a specified constructor + * + * @param classPath class's path + * @param parameterTypes the constructor with the specified parameter types + * @return return true if the constructor is exist + * @see #hasField(Class, String) + */ + public static boolean hasConstructor(String classPath, Class... parameterTypes) throws ClassNotFoundException { + return hasConstructor(Class.forName(classPath), parameterTypes); + } + + + /** + * check a class has a specified method + * + * @param clazz class's object + * @param methodName method's name + * @param parameterTypes the method with the specified parameter types + * @return return true if the method is exist + */ + public static boolean hasMethod(Class clazz, String methodName, Class... parameterTypes) { + boolean has; + try { + Validate.notNull(clazz).getDeclaredMethod(methodName, parameterTypes); + has = true; + } catch (NoSuchMethodException e) { + has = false; + } + return has; + } + + /** + * check a class has a specified method + * + * @param clazz class's object + * @param filter filter obj + * @return return true if the constructor is exist + */ + public static boolean hasMethod(Class clazz, MethodFilter filter) { + Validate.notNull(filter); + + boolean has = false; + Method[] methods = clazz.getDeclaredMethods(); + for (Method method : methods) { + if (filter.accept(method)) { + has = true; + break; + } + } + return has; + } + + /** + * check a class has a specified method + * + * @param classPath class's path + * @param methodName method's name + * @param parameterTypes the method with the specified parameter types + * @return return true if the constructor is exist + * @see #hasMethod(Class, String, Class[]) + */ + public static boolean hasMethod(String classPath, String methodName, Class... parameterTypes) throws ClassNotFoundException { + return hasMethod(Class.forName(classPath), methodName, parameterTypes); + } +} \ No newline at end of file diff --git a/common/src/main/java/cc/zoyn/core/util/reflect/package-info.java b/common/src/main/java/cc/zoyn/core/util/reflect/package-info.java new file mode 100644 index 0000000..b31ee0c --- /dev/null +++ b/common/src/main/java/cc/zoyn/core/util/reflect/package-info.java @@ -0,0 +1,7 @@ +/** + * The reflection of utils + * + * @author Zoyn + * @since 2017-12-09 + */ +package cc.zoyn.core.util.reflect; \ No newline at end of file diff --git a/src/main/java/cc/zoyn/core/util/BukkitObjectSerializerUtils.java b/common/src/main/java/cc/zoyn/core/util/serializer/BukkitObjectSerializerUtils.java similarity index 82% rename from src/main/java/cc/zoyn/core/util/BukkitObjectSerializerUtils.java rename to common/src/main/java/cc/zoyn/core/util/serializer/BukkitObjectSerializerUtils.java index 6b1fe95..db29fcb 100644 --- a/src/main/java/cc/zoyn/core/util/BukkitObjectSerializerUtils.java +++ b/common/src/main/java/cc/zoyn/core/util/serializer/BukkitObjectSerializerUtils.java @@ -1,4 +1,4 @@ -package cc.zoyn.core.util; +package cc.zoyn.core.util.serializer; import org.bukkit.configuration.serialization.ConfigurationSerializable; import org.bukkit.util.io.BukkitObjectInputStream; @@ -13,7 +13,11 @@ import java.util.List; import java.util.stream.Collectors; -public class BukkitObjectSerializerUtils { +public final class BukkitObjectSerializerUtils { + + // Prevent accidental construction + private BukkitObjectSerializerUtils() { + } /** * 单对象序列化为字符串 @@ -22,7 +26,7 @@ public class BukkitObjectSerializerUtils { * @return 字符串 * @throws IOException */ - public String singleObjectToString(Object object) throws IOException { + public static String singleObjectToString(Object object) throws IOException { byte[] raw = singleObjectToByteArray(object); if (raw != null) { @@ -39,7 +43,7 @@ public String singleObjectToString(Object object) throws IOException { * @return 字节数组 * @throws IOException */ - public byte[] singleObjectToByteArray(Object object) throws IOException { + public static byte[] singleObjectToByteArray(Object object) throws IOException { if (object instanceof ConfigurationSerializable || object instanceof Serializable) { ByteArrayOutputStream buf = new ByteArrayOutputStream(); BukkitObjectOutputStream out = new BukkitObjectOutputStream(buf); @@ -60,7 +64,7 @@ public byte[] singleObjectToByteArray(Object object) throws IOException { * @return 字符串 * @throws IOException */ - public String collectionToString(Collection objects) throws IOException { + public static String collectionToString(Collection objects) throws IOException { byte[] raw = collectionToByteArray(objects); if (raw != null) { @@ -77,7 +81,7 @@ public String collectionToString(Collection objects) throws IOException * @return 字节数组 * @throws IOException */ - public byte[] collectionToByteArray(Collection objects) throws IOException { + public static byte[] collectionToByteArray(Collection objects) throws IOException { ByteArrayOutputStream buf = new ByteArrayOutputStream(); BukkitObjectOutputStream out = new BukkitObjectOutputStream(buf); List compatible = objects.stream() @@ -102,7 +106,7 @@ public byte[] collectionToByteArray(Collection objects) throws IOExcepti * @return 实例对象 * @throws IOException */ - public T singleObjectFromString(String serialized, Class classOfT) throws IOException { + public static T singleObjectFromString(String serialized, Class classOfT) throws IOException { return singleObjectFromByteArray(Base64Coder.decodeLines(serialized), classOfT); } @@ -115,7 +119,7 @@ public T singleObjectFromString(String serialized, Class classOfT) throws * @throws IOException */ @SuppressWarnings("unchecked") - public T singleObjectFromByteArray(byte[] serialized, Class classOfT) throws IOException { + public static T singleObjectFromByteArray(byte[] serialized, Class classOfT) throws IOException { ByteArrayInputStream buf = new ByteArrayInputStream(serialized); BukkitObjectInputStream in = new BukkitObjectInputStream(buf); T object = null; @@ -140,8 +144,7 @@ public T singleObjectFromByteArray(byte[] serialized, Class classOfT) thr * @return 实例对象集合 * @throws IOException */ - public > C collectionFromString(String serialized, Class classOfC, Class classOfT) - throws IOException { + public static > C collectionFromString(String serialized, Class classOfC, Class classOfT) throws IOException { return collectionFromByteArray(Base64Coder.decodeLines(serialized), classOfC, classOfT); } @@ -155,8 +158,7 @@ public > C collectionFromString(String serialized, Cl * @throws IOException */ @SuppressWarnings("unchecked") - public > C collectionFromByteArray(byte[] serialized, Class classOfC, - Class classOfT) throws IOException { + public static > C collectionFromByteArray(byte[] serialized, Class classOfC, Class classOfT) throws IOException { C objects = null; try { diff --git a/src/main/java/cc/zoyn/core/util/EffectsSerializerUtils.java b/common/src/main/java/cc/zoyn/core/util/serializer/EffectsSerializerUtils.java similarity index 86% rename from src/main/java/cc/zoyn/core/util/EffectsSerializerUtils.java rename to common/src/main/java/cc/zoyn/core/util/serializer/EffectsSerializerUtils.java index d6531f1..983e100 100644 --- a/src/main/java/cc/zoyn/core/util/EffectsSerializerUtils.java +++ b/common/src/main/java/cc/zoyn/core/util/serializer/EffectsSerializerUtils.java @@ -1,4 +1,4 @@ -package cc.zoyn.core.util; +package cc.zoyn.core.util.serializer; import com.google.common.collect.Lists; import org.bukkit.potion.PotionEffect; @@ -18,7 +18,11 @@ * @author Zoyn * @since 2017/8/2 */ -public class EffectsSerializerUtils { +public final class EffectsSerializerUtils { + + // Prevent accidental construction + private EffectsSerializerUtils() { + } /** * 将药水效果序列化为Base64数据 @@ -26,11 +30,10 @@ public class EffectsSerializerUtils { * @param paramCollection 药水数据 * @return Base64数据 */ - public static String potionEffectsToBase64(Collection paramCollection) { + public static String toBase64(Collection paramCollection) { try { ByteArrayOutputStream localByteArrayOutputStream = new ByteArrayOutputStream(); - BukkitObjectOutputStream localBukkitObjectOutputStream = new BukkitObjectOutputStream( - localByteArrayOutputStream); + BukkitObjectOutputStream localBukkitObjectOutputStream = new BukkitObjectOutputStream(localByteArrayOutputStream); localBukkitObjectOutputStream.writeInt(paramCollection.toArray().length); for (int i = 0; i < paramCollection.toArray().length; i++) { @@ -49,7 +52,7 @@ public static String potionEffectsToBase64(Collection paramCollect * @param paramString 药水Base64数据 * @return 药水集合 */ - public static Collection potionEffectsFromBase64(String paramString) { + public static Collection fromBase64(String paramString) { try { ByteArrayInputStream localByteArrayInputStream = new ByteArrayInputStream( Base64Coder.decodeLines(paramString)); diff --git a/src/main/java/cc/zoyn/core/util/ItemSerializerUtils.java b/common/src/main/java/cc/zoyn/core/util/serializer/ItemSerializerUtils.java similarity index 91% rename from src/main/java/cc/zoyn/core/util/ItemSerializerUtils.java rename to common/src/main/java/cc/zoyn/core/util/serializer/ItemSerializerUtils.java index 25d763a..6a0615d 100644 --- a/src/main/java/cc/zoyn/core/util/ItemSerializerUtils.java +++ b/common/src/main/java/cc/zoyn/core/util/serializer/ItemSerializerUtils.java @@ -1,5 +1,6 @@ -package cc.zoyn.core.util; +package cc.zoyn.core.util.serializer; +import cc.zoyn.core.util.NMSUtils; import org.bukkit.inventory.ItemStack; import org.yaml.snakeyaml.external.biz.base64Coder.Base64Coder; @@ -14,11 +15,15 @@ * @version 1.1 更新 2017/8/2 更新内容: 修复兼容1.11与1.12的问题 * @since 2017/?/? */ -public class ItemSerializerUtils { +public final class ItemSerializerUtils { private static Method WRITE_NBT; private static Method READ_NBT; + // Prevent accidental construction + private ItemSerializerUtils() { + } + /** * 将物品序列化为Base64数据 * @@ -61,14 +66,14 @@ public static String toBase64(ItemStack[] items) { if (WRITE_NBT == null) { try { WRITE_NBT = NMSUtils.getNMSClass("NBTCompressedStreamTools").getDeclaredMethod("a", - new Class[]{NMSUtils.getNMSClass("NBTBase"), DataOutput.class}); + NMSUtils.getNMSClass("NBTBase"), DataOutput.class); WRITE_NBT.setAccessible(true); } catch (Exception localException1) { throw new IllegalStateException("未找到写入方法", localException1); } } try { - WRITE_NBT.invoke(null, new Object[]{localNBTTagList, localDataOutputStream}); + WRITE_NBT.invoke(null, localNBTTagList, localDataOutputStream); } catch (Exception localException2) { throw new IllegalArgumentException("无法写入" + localNBTTagList + "至" + localDataOutputStream, localException2); } @@ -98,7 +103,7 @@ public static ItemStack[] fromBase64(String paramString) { int subVersion = Integer.valueOf(version.split("_")[1]); /* * 1.11版本及以上删除了createStack方法所以只能使用其构造方法来创建 - */ + */ if (subVersion >= 11) { //构造器 Constructor constructor = NMSUtils.getNMSClass("ItemStack").getConstructor(NMSUtils.getNMSClass("NBTTagCompound")); @@ -131,7 +136,7 @@ private static Object readNbt(DataInput paramDataInput) { if (READ_NBT == null) { try { READ_NBT = NMSUtils.getNMSClass("NBTCompressedStreamTools").getDeclaredMethod("a", - new Class[]{DataInput.class, Integer.TYPE, NMSUtils.getNMSClass("NBTReadLimiter")}); + DataInput.class, Integer.TYPE, NMSUtils.getNMSClass("NBTReadLimiter")); READ_NBT.setAccessible(true); } catch (Exception localException1) { throw new IllegalStateException("未找到方法.", localException1); @@ -139,8 +144,8 @@ private static Object readNbt(DataInput paramDataInput) { } try { Object limiter = NMSUtils.getNMSClass("NBTReadLimiter").getConstructor(Long.TYPE) - .newInstance(9223372036854775807L); - return (Object) READ_NBT.invoke(null, new Object[]{paramDataInput, Integer.valueOf(0), limiter}); + .newInstance(Long.MAX_VALUE); + return READ_NBT.invoke(null, paramDataInput, 0, limiter); } catch (Exception localException2) { throw new IllegalArgumentException("无法从该位置读取数据" + paramDataInput, localException2); } diff --git a/common/src/main/java/cc/zoyn/core/util/serializer/package-info.java b/common/src/main/java/cc/zoyn/core/util/serializer/package-info.java new file mode 100644 index 0000000..14478f4 --- /dev/null +++ b/common/src/main/java/cc/zoyn/core/util/serializer/package-info.java @@ -0,0 +1,6 @@ +/** + * The serialization of utils + * @author Zoyn + * @since 2017-12-09 + */ +package cc.zoyn.core.util.serializer; \ No newline at end of file diff --git a/common/src/main/resources/plugin.yml b/common/src/main/resources/plugin.yml new file mode 100644 index 0000000..e38c6e3 --- /dev/null +++ b/common/src/main/resources/plugin.yml @@ -0,0 +1,6 @@ +name: May-Common-Library +main: cc.zoyn.core.Core +version: 1.0.0 +author: Zoyn +prefix: Core +depend: [ProtocolLib] \ No newline at end of file diff --git a/plugin-release/pom.xml b/plugin-release/pom.xml new file mode 100644 index 0000000..385ae29 --- /dev/null +++ b/plugin-release/pom.xml @@ -0,0 +1,89 @@ + + + + May-Common-Library + cc.zoyn.core + 1.0.0 + + 4.0.0 + + plugin-release + + + + cc.zoyn.core + common + ${project.parent.version} + compile + + + cc.zoyn.core + serverping + ${project.parent.version} + compile + + + cc.zoyn.core + tellraw + ${project.parent.version} + compile + + + cc.zoyn.core + book + ${project.parent.version} + compile + + + cc.zoyn.core + advancement + 1.0.0 + compile + + + + + + + ../common/src/main/resources + true + + + + + org.apache.maven.plugins + maven-jar-plugin + 2.6 + + ${project.parent.artifactId}-${project.parent.version} + + + + org.apache.maven.plugins + maven-shade-plugin + 3.1.0 + + + package + + shade + + + + + cglib + org.spigotmc + com.comphenix.protocol + com.comphenix.executors + + + + + + + + + + \ No newline at end of file diff --git a/pom.xml b/pom.xml index 1b09d44..85e7e6b 100644 --- a/pom.xml +++ b/pom.xml @@ -5,11 +5,20 @@ 4.0.0 cc.zoyn.core - MayCore + May-Common-Library 1.0.0 - jar + pom - MayCore + + tellraw + serverping + common + plugin-release + book + advancement + + + May-Common-Library Zoyn @@ -21,34 +30,23 @@ UTF-8 - - - spigotmc-repo - https://hub.spigotmc.org/nexus/content/groups/public/ - elmakers-repo http://maven.elmakers.com/repository - dmulloy2-repo - http://repo.dmulloy2.net/content/groups/public/ + lss233-minecraft + Lss233's Minecraft Repository + https://lss233.com/artifactory/minecraft - - - org.spigotmc - spigot-api - 1.12.1-R0.1-SNAPSHOT - provided - org.spigotmc spigot - 1.12.1-R0.1-SNAPSHOT + 1.12.2-R0.1-SNAPSHOT @@ -60,14 +58,8 @@ com.comphenix.protocol - ProtocolLib - 4.3.0 - - - - org.apache.commons - commons-lang3 - 3.7 + ProtocolLib-API + 4.3.0-SNAPSHOT @@ -76,56 +68,19 @@ 4.12 test - - - com.zaxxer - HikariCP - 2.7.2 - compile - - clean install - ${project.name}-${project.version} - src/main/java - - org.apache.maven.plugins maven-compiler-plugin - 3.1 + 3.5.1 1.8 1.8 - - - org.apache.maven.plugins - maven-shade-plugin - 3.1.0 - - - package - - shade - - - - - cglib - org.spigotmc - com.comphenix.protocol - com.comphenix.executors - - - - - - - \ No newline at end of file diff --git a/serverping/pom.xml b/serverping/pom.xml new file mode 100644 index 0000000..e196a8e --- /dev/null +++ b/serverping/pom.xml @@ -0,0 +1,23 @@ + + + + May-Common-Library + cc.zoyn.core + 1.0.0 + + 4.0.0 + + serverping + + + + cc.zoyn.core + common + ${project.parent.version} + provided + + + + \ No newline at end of file diff --git a/serverping/src/main/java/cc/zoyn/core/serverping/ServerPing.java b/serverping/src/main/java/cc/zoyn/core/serverping/ServerPing.java new file mode 100644 index 0000000..a658edf --- /dev/null +++ b/serverping/src/main/java/cc/zoyn/core/serverping/ServerPing.java @@ -0,0 +1,104 @@ +package cc.zoyn.core.serverping; + +import jdk.nashorn.api.scripting.ScriptObjectMirror; +import lombok.AllArgsConstructor; +import lombok.Data; + +import javax.script.Invocable; +import java.io.ByteArrayOutputStream; +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.net.InetSocketAddress; +import java.net.Socket; + +import static cc.zoyn.core.serverping.ServerPingUtils.*; + +@Data +@AllArgsConstructor +public class ServerPing { + + private String hostName; + private int port = 25565; + private int timeOut = 2000; + private String charSet = "UTF-8"; + private ServerPingReply reply; + + public ServerPing(String hostName) { + this(hostName, 25565); + } + + public ServerPing(String hostName, int port) { + this(hostName, port, 2000); + } + + public ServerPing(String hostName, int port, int timeOut) { + this.hostName = hostName; + this.port = port; + this.timeOut = timeOut; + } + + public boolean pingServer() { + try (Socket socket = new Socket()) { + socket.connect(new InetSocketAddress(hostName, 25565), 8000); + final DataInputStream in = new DataInputStream(socket.getInputStream()); + final DataOutputStream out = new DataOutputStream(socket.getOutputStream()); + + //> Handshake + ByteArrayOutputStream handshake_bytes = new ByteArrayOutputStream(); + DataOutputStream handshake = new DataOutputStream(handshake_bytes); + + handshake.writeByte(PACKET_HANDSHAKE); + writeVarInt(handshake, PROTOCOL_VERSION); + writeVarInt(handshake, this.hostName.length()); + + handshake.writeBytes(hostName); + handshake.writeShort(getPort()); + writeVarInt(handshake, STATUS_HANDSHAKE); + + writeVarInt(out, handshake_bytes.size()); + out.write(handshake_bytes.toByteArray()); + + //> Status request + out.writeByte(0x01); // Size of packet + out.writeByte(PACKET_STATUSREQUEST); + + //< Status response + readVarInt(in); // Size + int id = readVarInt(in); + int length = readVarInt(in); + byte[] data = new byte[length]; + in.readFully(data); + String json = new String(data, this.charSet); + + // format data + ScriptObjectMirror mirror = (ScriptObjectMirror) ((Invocable) ServerPingUtils.getEngine()).invokeFunction("parse", json); + if (mirror == null) { + return false; + } + ServerPingReply reply = new ServerPingReply(); + + ServerPingReply.Version version = new ServerPingReply.Version((String) mirror.get("version_name"), (int) mirror.get("version_protocol")); + ServerPingReply.Players players = new ServerPingReply.Players((int) mirror.get("players_max"), (int) mirror.get("players_online")); + ServerPingReply.Motd motd = new ServerPingReply.Motd((String) mirror.get("motd_text")); + ServerPingReply.Favicon favicon = new ServerPingReply.Favicon((String) mirror.get("favicon_data")); + + reply.setVersion(version); + reply.setPlayers(players); + reply.setMotd(motd); + reply.setFavicon(favicon); + reply.setOriginalJson(json); + + // Close + handshake.close(); + handshake_bytes.close(); + out.close(); + in.close(); + + setReply(reply); + return true; + } catch (Exception e) { + e.printStackTrace(); + } + return false; + } +} diff --git a/serverping/src/main/java/cc/zoyn/core/serverping/ServerPingReply.java b/serverping/src/main/java/cc/zoyn/core/serverping/ServerPingReply.java new file mode 100644 index 0000000..6353882 --- /dev/null +++ b/serverping/src/main/java/cc/zoyn/core/serverping/ServerPingReply.java @@ -0,0 +1,52 @@ +package cc.zoyn.core.serverping; + +import lombok.*; + +/** + * @author Zoyn + * @since 2017-12-22 + */ +@Data +@AllArgsConstructor +@RequiredArgsConstructor +public class ServerPingReply { + + private Version version; + private Players players; + private Motd motd; + private Favicon favicon; + private String originalJson; + + @ToString + @AllArgsConstructor + public static class Version { + @Getter + private String name; + @Getter + private int protocol; + } + + @ToString + @AllArgsConstructor + public static class Players { + @Getter + private int maxPlayer; + @Getter + private int onlinePlayer; + } + + @ToString + @AllArgsConstructor + public static class Motd { + @Getter + private String text; + } + + @ToString + @AllArgsConstructor + public static class Favicon { + @Getter + private String data; + } + +} diff --git a/serverping/src/main/java/cc/zoyn/core/serverping/ServerPingUtils.java b/serverping/src/main/java/cc/zoyn/core/serverping/ServerPingUtils.java new file mode 100644 index 0000000..96c51f8 --- /dev/null +++ b/serverping/src/main/java/cc/zoyn/core/serverping/ServerPingUtils.java @@ -0,0 +1,136 @@ +package cc.zoyn.core.serverping; + +import javax.script.ScriptEngine; +import javax.script.ScriptEngineManager; +import javax.script.ScriptException; +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; + +/** + * @since 2017-12-22 + */ +public final class ServerPingUtils { + + static byte PACKET_HANDSHAKE = 0x00, PACKET_STATUSREQUEST = 0x00; + static int PROTOCOL_VERSION = 4; + static int STATUS_HANDSHAKE = 1; + private static ScriptEngine engine; + + /* + * MOTD解析脚本 + * + * @author 喵♂呜 + * @editor: Zoyn + */ + static { + ScriptEngineManager manager = new ScriptEngineManager(); + engine = manager.getEngineByName("js"); + try { + engine.eval("function parse(json) {\n" + + " var color = [];\n" + + " color['black'] = '0';\n" + + " color['dark_blue'] = '1';\n" + + " color['dark_green'] = '2';\n" + + " color['dark_aqua'] = '3';\n" + + " color['dark_red'] = '4';\n" + + " color['dark_purple'] = '5';\n" + + " color['gold'] = '6';\n" + + " color['gray'] = '7';\n" + + " color['dark_gray'] = '8';\n" + + " color['blue'] = '9';\n" + + " color['green'] = 'a';\n" + + " color['aqua'] = 'b';\n" + + " color['red'] = 'c';\n" + + " color['light_purple'] = 'd';\n" + + " color['yellow'] = 'e';\n" + + " color['white'] = 'f';\n" + + " var obj = JSON.parse(json);\n" + + " // noinspection JSUnresolvedVariable\n" + + " var motd = obj.description.text;\n" + + " // noinspection JSUnresolvedVariable\n" + + " if (obj.description.extra) {\n" + + " // noinspection JSUnresolvedVariable\n" + + " obj.description.extra.forEach(function (part) {\n" + + " // noinspection JSUnresolvedVariable\n" + + " if (part.obfuscated) {\n" + + " motd += \"§k\";\n" + + " }\n" + + " if (part.bold) {\n" + + " motd += \"§l\";\n" + + " }\n" + + " // noinspection JSUnresolvedVariable\n" + + " if (part.strikethrough) {\n" + + " motd += \"§m\";\n" + + " }\n" + + " // noinspection JSUnresolvedVariable\n" + + " if (part.underline) {\n" + + " motd += \"§n\";\n" + + " }\n" + + " // noinspection JSUnresolvedVariable\n" + + " if (part.italic) {\n" + + " motd += \"§o\";\n" + + " }\n" + + " if (part.reset) {\n" + + " motd += \"§r\";\n" + + " }\n" + + " if (part.color) {\n" + + " motd += '§' + color[part.color];\n" + + " }\n" + + " motd += part.text;\n" + + " })\n" + + " } else if(obj.description.text) {\n" + + " motd = obj.description.text\n" + + " }\n" + + " obj.version_name = obj.version.name;\n" + + " obj.version_protocol = obj.version.protocol;\n" + + " obj.players_max = obj.players.max;\n" + + " obj.players_online = obj.players.online;\n" + + " obj.motd_text = motd;\n" + + " obj.favicon_data = obj.favicon;\n" + + " return obj;\n" + + "}"); + } catch (ScriptException e) { + e.printStackTrace(); + System.out.println("警告! MOTD 解析脚本初始化失败!"); + } + } + + public static ScriptEngine getEngine() { + return engine; + } + + /** + * @author thinkofdeath + * See: https://gist.github.com/thinkofdeath/e975ddee04e9c87faf22 + */ + public static int readVarInt(DataInputStream in) throws IOException { + int i = 0; + int j = 0; + while (true) { + int k = in.readByte(); + i |= (k & 0x7F) << j++ * 7; + if (j > 5) + throw new RuntimeException("VarInt too big"); + if ((k & 0x80) != 128) + break; + } + return i; + } + + /** + * @author thinkofdeath + * See: https://gist.github.com/thinkofdeath/e975ddee04e9c87faf22 + */ + public static void writeVarInt(DataOutputStream out, int paramInt) throws IOException { + while (true) { + if ((paramInt & 0xFFFFFF80) == 0) { + out.writeByte(paramInt); + return; + } + out.writeByte(paramInt & 0x7F | 0x80); + paramInt >>>= 7; + } + } + +} diff --git a/serverping/src/test/java/cc/zoyn/core/ServerPingTest.java b/serverping/src/test/java/cc/zoyn/core/ServerPingTest.java new file mode 100644 index 0000000..540bbed --- /dev/null +++ b/serverping/src/test/java/cc/zoyn/core/ServerPingTest.java @@ -0,0 +1,21 @@ +package cc.zoyn.core; + +import org.junit.Test; + +/** + * @author Zoyn + * @since 2017-12-22 + */ +public class ServerPingTest { + + @Test + public void testServerPing() { +// ServerPing serverPing = new ServerPing("mc.52ko.com"); +// serverPing.pingServer(); + +// ServerPingReply reply = serverPing.getReply(); +// System.out.println(new GsonBuilder().setPrettyPrinting().create().toJson(new JsonParser().parse(reply.getOriginalJson()))); +// Assert.assertTrue(reply.getVersion().getName().contains("1.12")); + } + +} \ No newline at end of file diff --git a/src/main/java/cc/zoyn/core/Core.java b/src/main/java/cc/zoyn/core/Core.java deleted file mode 100644 index f1daaa7..0000000 --- a/src/main/java/cc/zoyn/core/Core.java +++ /dev/null @@ -1,104 +0,0 @@ -package cc.zoyn.core; - -import cc.zoyn.core.command.CommandHandler; -import cc.zoyn.core.listener.TestListener; -import com.comphenix.protocol.PacketType; -import com.comphenix.protocol.ProtocolLibrary; -import com.comphenix.protocol.ProtocolManager; -import com.comphenix.protocol.events.PacketAdapter; -import com.comphenix.protocol.events.PacketContainer; -import com.comphenix.protocol.events.PacketEvent; -import com.comphenix.protocol.wrappers.BlockPosition; -import com.google.common.collect.Lists; -import com.google.common.collect.Maps; -import org.bukkit.Bukkit; -import org.bukkit.World; -import org.bukkit.entity.Player; -import org.bukkit.plugin.Plugin; -import org.bukkit.plugin.java.JavaPlugin; - -import java.util.Arrays; -import java.util.List; -import java.util.Map; - -public class Core extends JavaPlugin { - - private static Core instance; - private ProtocolManager pm; - public static Map map = Maps.newHashMap(); - - public void onEnable() { - instance = this; - - Bukkit.getPluginCommand("core").setExecutor(new CommandHandler()); - Bukkit.getPluginManager().registerEvents(new TestListener(), this); - - saveDefaultConfig(); - pm = ProtocolLibrary.getProtocolManager(); - - pm.addPacketListener( - new PacketAdapter(this, PacketType.Play.Client.UPDATE_SIGN) { - @Override - public void onPacketReceiving(PacketEvent event) { - System.out.println("test"); - PacketContainer packet = event.getPacket(); - Player player = event.getPlayer(); - - BlockPosition cacheBlockPosition = map.get(player.getName()); //缓存中的牌子位置数据 - BlockPosition packetBlockPosition = packet.getBlockPositionModifier().getValues().get(0); //数据包中的牌子位置数据 - - System.out.println(packet.getModifier().getValues().toString()); - - System.out.println(cacheBlockPosition); - System.out.println(packetBlockPosition); - - //NPE检查 - if (cacheBlockPosition == null || packetBlockPosition == null) { - System.out.println("null?"); - return; - } - - if (cacheBlockPosition.equals(packetBlockPosition)) { - System.out.println("123"); - } - } - } - ); - } - - /** - * 以List的方式取服务器插件 - * - * @return 服务器所有插件的集合 - */ - public List getPlugins() { - return Arrays.asList(Bukkit.getPluginManager().getPlugins()); - } - - /** - * 取全部世界的名字 - * - * @return 全部世界名 - */ - public List getWorldsName() { - List names = Lists.newArrayList(); - for (World world : Bukkit.getWorlds()) { - names.add(world.getName()); - } - return names; - } - - /** - * 取Core实例 - * - * @return Core的实例 - */ - public static Core getInstance() { - return instance; - } - - public ProtocolManager getProtocolManager() { - return pm; - } - -} diff --git a/src/main/java/cc/zoyn/core/advancement/FrameEnum.java b/src/main/java/cc/zoyn/core/advancement/FrameEnum.java deleted file mode 100644 index b8f40cb..0000000 --- a/src/main/java/cc/zoyn/core/advancement/FrameEnum.java +++ /dev/null @@ -1,18 +0,0 @@ -package cc.zoyn.core.advancement; - -/** - * 图标边框枚举 - * - * @author Zoyn - */ -public enum FrameEnum { - // TASK(默认) - // GOAL为更圆的边框标题,其用于完整信标进度 - // CHALLENGE,其用于杀死所有种类生物的进度 - TASK(), - GOAL(), - CHALLENGE(); - - private FrameEnum() { - } -} diff --git a/src/main/java/cc/zoyn/core/api/BungeeCordAPI.java b/src/main/java/cc/zoyn/core/api/BungeeCordAPI.java deleted file mode 100644 index 04dc3bf..0000000 --- a/src/main/java/cc/zoyn/core/api/BungeeCordAPI.java +++ /dev/null @@ -1,42 +0,0 @@ -package cc.zoyn.core.api; - -import cc.zoyn.core.util.BungeeCordUtils; - -/** - * 蹦极代理API - * - * @author Zoyn - */ -public class BungeeCordAPI { - - /** - * 踢出一个玩家 - * - * @param playerName 玩家名 - * @param message 信息 - */ - public static void kickPlayer(String playerName, String message) { - BungeeCordUtils.kickPlayer(playerName, message); - } - - /** - * 将玩家传送至某子服 - * - * @param playerName 玩家名 - * @param serverName 服务器名 - */ - public static void playerConnectServer(String playerName, String serverName) { - BungeeCordUtils.playerConnectServer(playerName, serverName); - } - - /** - * 给所有服务器的玩家发送Title - * - * @param title 标题 - * @param subtitle 子标题 - */ - public static void sendTitleToAllServer(String title, String subtitle) { - BungeeCordUtils.sendData("BukkitCoreMessage", title + "%ncyn%" + subtitle); - } - -} diff --git a/src/main/java/cc/zoyn/core/api/CoreAPI.java b/src/main/java/cc/zoyn/core/api/CoreAPI.java deleted file mode 100644 index 00de213..0000000 --- a/src/main/java/cc/zoyn/core/api/CoreAPI.java +++ /dev/null @@ -1,109 +0,0 @@ -package cc.zoyn.core.api; - -import cc.zoyn.core.dto.Tellraw; -import cc.zoyn.core.service.CoreService; -import cc.zoyn.core.service.CoreServiceImpl; -import org.bukkit.Location; -import org.bukkit.entity.Entity; -import org.bukkit.entity.Player; -import org.bukkit.inventory.ItemStack; - -/** - * 核心API - * - * @author Zoyn - */ -public class CoreAPI { - - private static CoreService coreService; - - static { - coreService = new CoreServiceImpl(); - } - - /** - * 给一名玩家发送Tellraw - * - * @param tellraw Tellraw的对象 - * @param player 玩家 - */ - public static void sendTellraw(Tellraw tellraw, Player player) { - coreService.sendTellraw(tellraw, player); - } - - /** - * 创建一个Tellraw对象 - * - * @param message 信息 - * @return {@link Tellraw} - */ - public static Tellraw createTellraw(String message) { - return coreService.createTellraw(message); - } - - /** - * 设置一个物品的无法破坏 - * - * @param is 物品 - * @param unbreakable 无法破坏值[布尔] - */ - public static void setItemUnbreakable(ItemStack is, boolean unbreakable) { - coreService.setItemUnbreakable(is, unbreakable); - } - - /** - * 设置一个物品发光 - * - * @param is 物品 - * @return {@link ItemStack} - */ - public static ItemStack setItemGlow(ItemStack is) { - return coreService.setItemGlow(is); - } - - /** - * 设置玩家的Tab 可以使用\n换行字符 - * - * @param player 玩家 - * @param head Tab首 - * @param foot Tab尾 - */ - public static void setPlayerTab(Player player, String head, String foot) { - coreService.setPlayerTab(player, head, foot); - } - - /** - * 给玩家发送Title - * - * @param player 玩家 - * @param fadeIn 淡入时间 - * @param stay 停留时间 - * @param fadeOut 淡出时间 - * @param title 标题[可用Null] - * @param subtitle 副标题[可用Null] - */ - public static void sendTitle(Player player, Integer fadeIn, Integer stay, Integer fadeOut, String title, String subtitle) { - coreService.sendTitle(player, fadeIn, stay, fadeOut, title, subtitle); - } - - /** - * 给玩家发送一条ActionBar - * - * @param player 玩家 - * @param msg 信息 - */ - public static void sendActionBar(Player player, String msg) { - coreService.sendActionBar(player, msg); - } - - /** - * 取该坐标附近的所有实体 - * - * @param loc 坐标 - * @param radius 半径 - * @return {@link Entity} - */ - public static Entity[] getNearbyEntitiesArrays(Location loc, double radius) { - return coreService.getNearbyEntitiesArrays(loc, radius); - } -} \ No newline at end of file diff --git a/src/main/java/cc/zoyn/core/api/events/PlayerReceiveActionbarEvent.java b/src/main/java/cc/zoyn/core/api/events/PlayerReceiveActionbarEvent.java deleted file mode 100644 index 7fbcda3..0000000 --- a/src/main/java/cc/zoyn/core/api/events/PlayerReceiveActionbarEvent.java +++ /dev/null @@ -1,59 +0,0 @@ -package cc.zoyn.core.api.events; - -import cc.zoyn.core.dto.Actionbar; -import org.bukkit.entity.Player; -import org.bukkit.event.Cancellable; -import org.bukkit.event.Event; -import org.bukkit.event.HandlerList; - -/** - * 玩家接收ActionBar事件 - * - * @author Zoyn - */ -public class PlayerReceiveActionbarEvent extends Event implements Cancellable { - - private Player player; - private Actionbar actionBar; - private static final HandlerList handlers = new HandlerList(); - - public PlayerReceiveActionbarEvent(Player player, Actionbar actionBar) { - this.player = player; - this.actionBar = actionBar; - } - - public Player getPlayer() { - return player; - } - - public void setPlayer(Player player) { - this.player = player; - } - - public Actionbar getActionbar() { - return actionBar; - } - - public void setActionbar(Actionbar actionBar) { - this.actionBar = actionBar; - } - - public HandlerList getHandlers() { - return handlers; - } - - public static HandlerList getHandlerList() { - return handlers; - } - - private boolean cancelled = false; - - public boolean isCancelled() { - return this.cancelled; - } - - public void setCancelled(boolean cancel) { - this.cancelled = cancel; - } - -} diff --git a/src/main/java/cc/zoyn/core/api/events/PlayerReceiveTellrawEvent.java b/src/main/java/cc/zoyn/core/api/events/PlayerReceiveTellrawEvent.java deleted file mode 100644 index a5cab98..0000000 --- a/src/main/java/cc/zoyn/core/api/events/PlayerReceiveTellrawEvent.java +++ /dev/null @@ -1,58 +0,0 @@ -package cc.zoyn.core.api.events; - -import cc.zoyn.core.dto.Tellraw; -import org.bukkit.entity.Player; -import org.bukkit.event.Cancellable; -import org.bukkit.event.Event; -import org.bukkit.event.HandlerList; - -/** - * 玩家接收Tellraw事件 - * - * @author Zoyn - */ -public class PlayerReceiveTellrawEvent extends Event implements Cancellable { - - private Player player; - private Tellraw tellraw; - private static final HandlerList handlers = new HandlerList(); - - public PlayerReceiveTellrawEvent(Player player, Tellraw tellraw) { - this.player = player; - this.tellraw = tellraw; - } - - public Player getPlayer() { - return player; - } - - public void setPlayer(Player player) { - this.player = player; - } - - public Tellraw getTellraw() { - return tellraw; - } - - public void setTellraw(Tellraw tellraw) { - this.tellraw = tellraw; - } - - public HandlerList getHandlers() { - return handlers; - } - - public static HandlerList getHandlerList() { - return handlers; - } - - private boolean cancelled = false; - - public boolean isCancelled() { - return this.cancelled; - } - - public void setCancelled(boolean cancel) { - this.cancelled = cancel; - } -} diff --git a/src/main/java/cc/zoyn/core/api/events/PlayerReceiveTitleEvent.java b/src/main/java/cc/zoyn/core/api/events/PlayerReceiveTitleEvent.java deleted file mode 100644 index ed4ee37..0000000 --- a/src/main/java/cc/zoyn/core/api/events/PlayerReceiveTitleEvent.java +++ /dev/null @@ -1,59 +0,0 @@ -package cc.zoyn.core.api.events; - -import cc.zoyn.core.dto.Title; -import org.bukkit.entity.Player; -import org.bukkit.event.Cancellable; -import org.bukkit.event.Event; -import org.bukkit.event.HandlerList; - -/** - * 玩家接收Title事件 - * - * @author Zoyn - */ -public class PlayerReceiveTitleEvent extends Event implements Cancellable { - - private Player player; - private Title title; - private static final HandlerList handlers = new HandlerList(); - - public PlayerReceiveTitleEvent(Player player, Title title) { - this.player = player; - this.title = title; - } - - public Player getPlayer() { - return player; - } - - public void setPlayer(Player player) { - this.player = player; - } - - public Title getTitle() { - return title; - } - - public void setTitle(Title title) { - this.title = title; - } - - public HandlerList getHandlers() { - return handlers; - } - - public static HandlerList getHandlerList() { - return handlers; - } - - private boolean cancelled = false; - - public boolean isCancelled() { - return this.cancelled; - } - - public void setCancelled(boolean cancel) { - this.cancelled = cancel; - } - -} diff --git a/src/main/java/cc/zoyn/core/command/CommandHandler.java b/src/main/java/cc/zoyn/core/command/CommandHandler.java deleted file mode 100644 index e9b7d64..0000000 --- a/src/main/java/cc/zoyn/core/command/CommandHandler.java +++ /dev/null @@ -1,48 +0,0 @@ -package cc.zoyn.core.command; - -import cc.zoyn.core.command.subcommand.InfoCommand; -import cc.zoyn.core.command.subcommand.ListCommand; -import cc.zoyn.core.util.SubCommand; -import com.google.common.collect.Maps; -import org.bukkit.Bukkit; -import org.bukkit.command.Command; -import org.bukkit.command.CommandExecutor; -import org.bukkit.command.CommandSender; - -import java.util.Map; - -public class CommandHandler implements CommandExecutor { - - private Map subCommandMap = Maps.newHashMap(); - - public CommandHandler() { - registerSubCommand("list", new ListCommand()); - registerSubCommand("info", new InfoCommand()); - } - - public void registerSubCommand(String commandName, SubCommand subCommand) { - if (subCommandMap.containsKey(commandName)) { - Bukkit.getLogger().warning("发现重复注册指令!"); - } - subCommandMap.put(commandName, subCommand); - } - - @Override - public boolean onCommand(CommandSender sender, Command cmd, String label, String[] args) { - if (label.equalsIgnoreCase("core")) { - if (args.length == 0) { - sender.sendMessage("§6========== §3[ §eMayCore §l| §e核心 §3] §6=========="); - sender.sendMessage("§b/core list §7查看插件列表"); - sender.sendMessage("§b/core info §7查看服务器信息"); - return true; - } - SubCommand subCommand = subCommandMap.get(args[0]); - if (subCommand == null) { - sender.sendMessage("§8[§6核心§8] §e>> §c未知指令"); - return true; - } - subCommand.execute(sender, args); - } - return false; - } -} diff --git a/src/main/java/cc/zoyn/core/command/subcommand/InfoCommand.java b/src/main/java/cc/zoyn/core/command/subcommand/InfoCommand.java deleted file mode 100644 index 34ceb9b..0000000 --- a/src/main/java/cc/zoyn/core/command/subcommand/InfoCommand.java +++ /dev/null @@ -1,23 +0,0 @@ -package cc.zoyn.core.command.subcommand; - -import cc.zoyn.core.util.SubCommand; -import org.bukkit.Bukkit; -import org.bukkit.command.CommandSender; - -public class InfoCommand implements SubCommand { - - @Override - public boolean execute(CommandSender sender, String[] args) { - if (!sender.isOp()) { - sender.sendMessage("§b[核心] §e>> §c权限不足"); - return true; - } - sender.sendMessage("§6运行版本§c:§r " + Bukkit.getBukkitVersion() + " | " + Bukkit.getVersion()); - sender.sendMessage("§6当前在线§c:§r " + Bukkit.getOnlinePlayers().size()); - sender.sendMessage("§6最大人数§c:§r " + Bukkit.getMaxPlayers()); - sender.sendMessage("§6封禁玩家§c:§r " + Bukkit.getBannedPlayers().size()); - sender.sendMessage("§6封禁IP数§c:§r " + Bukkit.getIPBans().size()); - - return false; - } -} diff --git a/src/main/java/cc/zoyn/core/command/subcommand/ListCommand.java b/src/main/java/cc/zoyn/core/command/subcommand/ListCommand.java deleted file mode 100644 index f52e5b5..0000000 --- a/src/main/java/cc/zoyn/core/command/subcommand/ListCommand.java +++ /dev/null @@ -1,39 +0,0 @@ -package cc.zoyn.core.command.subcommand; - -import cc.zoyn.core.util.SubCommand; -import cc.zoyn.core.Core; -import org.bukkit.command.CommandSender; -import org.bukkit.plugin.Plugin; - -import java.util.List; - -public class ListCommand implements SubCommand { - - private List plugins = null; - - @Override - public boolean execute(CommandSender sender, String[] args) { - if (plugins == null) { - plugins = Core.getInstance().getPlugins(); - } - sender.sendMessage("§6========== §3[ §aPlugins §6◤ §f" + plugins.size() + " §6◢ §3] §6=========="); - for (int i = 0; i < plugins.size(); i++) { - if (plugins.get(i).isEnabled()) { - String prefix = plugins.get(i).getDescription().getPrefix(); - if (prefix == null) { - sender.sendMessage("§6" + plugins.get(i).getName() + " §7- §a✔ 已加载"); - } else { - sender.sendMessage("§6" + plugins.get(i).getName() + "§7(" + prefix + "§7)" + " §7- §a✔ 已加载"); - } - } else { - String prefix = plugins.get(i).getDescription().getPrefix(); - if (prefix == null) { - sender.sendMessage("§6" + plugins.get(i).getName() + " §7- §c✘ 未加载"); - } else { - sender.sendMessage("§6" + plugins.get(i).getName() + "§7(" + prefix + "§7)" + " §7- §c✘ 未加载"); - } - } - } - return true; - } -} diff --git a/src/main/java/cc/zoyn/core/dto/Actionbar.java b/src/main/java/cc/zoyn/core/dto/Actionbar.java deleted file mode 100644 index a67f2dd..0000000 --- a/src/main/java/cc/zoyn/core/dto/Actionbar.java +++ /dev/null @@ -1,24 +0,0 @@ -package cc.zoyn.core.dto; - -/** - * Actionbar - 数据模型 - * - * @author Zoyn - */ -public class Actionbar { - - private String message; - - public Actionbar(String message) { - this.message = message; - } - - public String getMessage() { - return message; - } - - public void setMessage(String message) { - this.message = message; - } - -} diff --git a/src/main/java/cc/zoyn/core/dto/Book.java b/src/main/java/cc/zoyn/core/dto/Book.java deleted file mode 100644 index 164c72d..0000000 --- a/src/main/java/cc/zoyn/core/dto/Book.java +++ /dev/null @@ -1,67 +0,0 @@ -package cc.zoyn.core.dto; - -import cc.zoyn.core.util.BookUtils; -import org.bukkit.Material; -import org.bukkit.inventory.ItemStack; -import org.bukkit.inventory.meta.BookMeta; - -import java.util.ArrayList; -import java.util.List; - -/** - * Book - 数据模型 - * - * @author Zoyn - */ -public class Book { - - private String author = "notch"; - private String title = "SouthOfSouth"; - private List pages = new ArrayList(); - - @Override - public String toString() { - return "Book [author=" + author + ", title=" + title + ", pages=" + pages + "]"; - } - - public Book(String author, String title, List pages) { - super(); - this.author = author; - this.title = title; - this.pages = pages; - } - - public String getAuthor() { - return author; - } - - public void setAuthor(String author) { - this.author = author; - } - - public String getTitle() { - return title; - } - - public void setTitle(String title) { - this.title = title; - } - - public List getPages() { - return pages; - } - - public void setPages(List pages) { - this.pages = pages; - } - - public ItemStack getItem() { - ItemStack book = new ItemStack(Material.WRITTEN_BOOK); - BookMeta meta = (BookMeta) book.getItemMeta(); - meta.setTitle(title); - meta.setAuthor(author); - BookUtils.setPagesAsPage(meta, pages); - book.setItemMeta(meta); - return book; - } -} diff --git a/src/main/java/cc/zoyn/core/dto/Sign.java b/src/main/java/cc/zoyn/core/dto/Sign.java deleted file mode 100644 index 9e13c9a..0000000 --- a/src/main/java/cc/zoyn/core/dto/Sign.java +++ /dev/null @@ -1,55 +0,0 @@ -package cc.zoyn.core.dto; - -import java.util.List; - -/** - * Sign - 数据传输模型 - * - * @author Zoyn - */ -public class Sign { - - private String[] message = new String[4]; - - public Sign(List texts) { - if (texts.size() > 4) { - for (int i = 0; i < 3; i++) { - String string = message[i]; - message[i] = string; - } - } - message = texts.toArray(new String[]{}); - } - - public Sign(String... texts) { - if (texts.length > 4) { - for (int i = 0; i <= 3; i++) { - String string = texts[i]; - message[i] = string; - } - } - message = texts; - } - - public Sign setTexts(String... texts) { - if (texts.length > 4) { - for (int i = 0; i <= 3; i++) { - String string = texts[i]; - message[i] = string; - } - } - message = texts; - return this; - } - - public boolean isEmpty() { - if (message.length == 0) { - return true; - } - return false; - } - - public String[] getTexts() { - return message; - } -} diff --git a/src/main/java/cc/zoyn/core/dto/SlotTypeEnum.java b/src/main/java/cc/zoyn/core/dto/SlotTypeEnum.java deleted file mode 100644 index 2edd759..0000000 --- a/src/main/java/cc/zoyn/core/dto/SlotTypeEnum.java +++ /dev/null @@ -1,13 +0,0 @@ -package cc.zoyn.core.dto; - -/** - * NBTSlot类型枚举 - * - * @author Zoyn - */ -public enum SlotTypeEnum { - mainhand, offhand, feet, legs, chest, head; - - private SlotTypeEnum() { - } -} diff --git a/src/main/java/cc/zoyn/core/dto/Title.java b/src/main/java/cc/zoyn/core/dto/Title.java deleted file mode 100644 index 118277d..0000000 --- a/src/main/java/cc/zoyn/core/dto/Title.java +++ /dev/null @@ -1,65 +0,0 @@ -package cc.zoyn.core.dto; - -/** - * Title - 数据模型 - * - * @author Zoyn - */ -public class Title { - - private int fadeIn; - private int stay; - private int fadeOut; - private String title; - private String subtitle; - - - public Title(int fadeIn, int stay, int fadeOut, String title, String subtitle) { - this.fadeIn = fadeIn; - this.stay = stay; - this.fadeOut = fadeOut; - this.title = title; - this.subtitle = subtitle; - } - - public int getFadeIn() { - return fadeIn; - } - - public void setFadeIn(int fadeIn) { - this.fadeIn = fadeIn; - } - - public int getStay() { - return stay; - } - - public void setStay(int stay) { - this.stay = stay; - } - - public int getFadeOut() { - return fadeOut; - } - - public void setFadeOut(int fadeOut) { - this.fadeOut = fadeOut; - } - - public String getTitle() { - return title; - } - - public void setTitle(String title) { - this.title = title; - } - - public String getSubtitle() { - return subtitle; - } - - public void setSubtitle(String subtitle) { - this.subtitle = subtitle; - } - -} diff --git a/src/main/java/cc/zoyn/core/listener/TestListener.java b/src/main/java/cc/zoyn/core/listener/TestListener.java deleted file mode 100644 index 08e4307..0000000 --- a/src/main/java/cc/zoyn/core/listener/TestListener.java +++ /dev/null @@ -1,38 +0,0 @@ -package cc.zoyn.core.listener; - - -import com.comphenix.protocol.wrappers.nbt.NbtBase; -import com.comphenix.protocol.wrappers.nbt.NbtCompound; -import com.comphenix.protocol.wrappers.nbt.NbtFactory; -import com.google.common.collect.Lists; -import org.bukkit.event.EventHandler; -import org.bukkit.event.Listener; -import org.bukkit.event.player.AsyncPlayerChatEvent; - -import java.util.List; - -/** - * 测试用Listener - * - * @author Zoyn - * @since 2017-10-03 - */ -public class TestListener implements Listener { - - @EventHandler - public void onChat(AsyncPlayerChatEvent e) { - List> list = Lists.newArrayList(); - list.add(NbtFactory.of("name", "null")); - list.add(NbtFactory.of("Value", "xxx")); - - NbtCompound value = NbtFactory.ofCompound("value"); - NbtCompound array = NbtFactory.ofCompound("value"); - array.put("name", "null"); - array.put("Value", "xxx"); - value.put(array); - - System.out.println(value.getKeys().toString()); - System.out.println(value.toString()); - - } -} diff --git a/src/main/java/cc/zoyn/core/service/CoreService.java b/src/main/java/cc/zoyn/core/service/CoreService.java deleted file mode 100644 index 8174a35..0000000 --- a/src/main/java/cc/zoyn/core/service/CoreService.java +++ /dev/null @@ -1,34 +0,0 @@ -package cc.zoyn.core.service; - -import cc.zoyn.core.dto.Tellraw; -import cc.zoyn.core.dto.Sign; -import org.bukkit.Location; -import org.bukkit.entity.Entity; -import org.bukkit.entity.Player; -import org.bukkit.inventory.ItemStack; - -/** - * Core - 应用层接口 - * - * @author Zoyn - */ -public interface CoreService { - - void sendTellraw(Tellraw tellraw, Player player); - - Tellraw createTellraw(String message); - - void setItemUnbreakable(ItemStack is, boolean unbreakable); - - ItemStack setItemGlow(ItemStack is); - - void setPlayerTab(Player player, String head, String foot); - - void sendTitle(Player player, Integer fadeIn, Integer stay, Integer fadeOut, String title, String subtitle); - - void sendActionBar(Player player, String msg); - - void sendSign(Player player, Sign sign); - - Entity[] getNearbyEntitiesArrays(Location loc, double radius); -} diff --git a/src/main/java/cc/zoyn/core/service/CoreServiceImpl.java b/src/main/java/cc/zoyn/core/service/CoreServiceImpl.java deleted file mode 100644 index 6da2ef3..0000000 --- a/src/main/java/cc/zoyn/core/service/CoreServiceImpl.java +++ /dev/null @@ -1,191 +0,0 @@ -package cc.zoyn.core.service; - -import cc.zoyn.core.Core; -import cc.zoyn.core.api.events.PlayerReceiveActionbarEvent; -import cc.zoyn.core.api.events.PlayerReceiveTellrawEvent; -import cc.zoyn.core.api.events.PlayerReceiveTitleEvent; -import cc.zoyn.core.dto.Actionbar; -import cc.zoyn.core.dto.Sign; -import cc.zoyn.core.dto.Tellraw; -import cc.zoyn.core.dto.Title; -import cc.zoyn.core.enchantments.Glow; -import cc.zoyn.core.util.*; -import com.comphenix.protocol.PacketType; -import com.comphenix.protocol.ProtocolManager; -import com.comphenix.protocol.events.PacketContainer; -import com.comphenix.protocol.wrappers.BlockPosition; -import com.comphenix.protocol.wrappers.WrappedBlockData; -import com.comphenix.protocol.wrappers.nbt.NbtCompound; -import com.comphenix.protocol.wrappers.nbt.NbtFactory; -import org.bukkit.Bukkit; -import org.bukkit.Location; -import org.bukkit.Material; -import org.bukkit.entity.Entity; -import org.bukkit.entity.Player; -import org.bukkit.inventory.ItemStack; -import org.bukkit.inventory.meta.ItemMeta; - -import java.lang.reflect.InvocationTargetException; - -/** - * Core - 接口实现 - * - * @author Zoyn - */ -public class CoreServiceImpl implements CoreService { - - @Override - public void sendTellraw(Tellraw tellraw, Player player) { - if (!player.isOnline()) { - throw new NullPointerException("错误: 玩家不在线!"); - } - if (tellraw == null) { - throw new NullPointerException("错误: Tellraw不能为Null!"); - } - Tellraw tellRaw = tellraw; - PlayerReceiveTellrawEvent event = new PlayerReceiveTellrawEvent(player, tellRaw); - Bukkit.getPluginManager().callEvent(event); - if (event.isCancelled()) { - return; - } - - if (Bukkit.getVersion().contains("Paper") && !Bukkit.isPrimaryThread()) { - Bukkit.getScheduler().runTask( - Core.getInstance(), - () -> Bukkit.dispatchCommand(Bukkit.getConsoleSender(), "tellraw " + player.getName() + " " + tellraw.toJsonString()) - ); - - } else { - Bukkit.dispatchCommand(Bukkit.getConsoleSender(), "tellraw " + player.getName() + " " + tellRaw.toJsonString()); - } - } - - @Override - public Tellraw createTellraw(String message) { - return new Tellraw(message.replaceAll("&", "§")); - } - - @Override - public void setItemUnbreakable(ItemStack is, boolean unbreakable) { - if (is == null) { - throw new NullPointerException("错误: 物品不能为Null!"); - } - NBTUtils.setUnbreakable(is, unbreakable); - } - - @Override - public ItemStack setItemGlow(ItemStack is) { - if (is == null) { - throw new NullPointerException("错误: 物品不能为Null!"); - } - ItemMeta im = is.getItemMeta(); - im.addEnchant(new Glow(255), 1, true); - is.setItemMeta(im); - im = null; - return is; - } - - @Override - public void setPlayerTab(Player player, String head, String foot) { - if (!player.isOnline()) { - throw new NullPointerException("错误: 玩家不在线!"); - } - TabUtils.setTab(player, head.replaceAll("&", "§"), foot.replaceAll("&", "§")); - } - - @Override - public void sendTitle(Player player, Integer fadeIn, Integer stay, Integer fadeOut, String title, String subtitle) { - if (!player.isOnline()) { - throw new NullPointerException("错误: 玩家不在线!"); - } - Title t = new Title(fadeIn, stay, fadeOut, title, subtitle); - PlayerReceiveTitleEvent event = new PlayerReceiveTitleEvent(player, t); - Bukkit.getPluginManager().callEvent(event); - if (event.isCancelled()) { - return; - } - TitleUtils.sendTitle(player, t.getFadeIn(), t.getStay(), t.getFadeOut(), t.getTitle(), t.getSubtitle()); - } - - @Override - public void sendActionBar(Player player, String msg) { - if (!player.isOnline()) { - throw new NullPointerException("错误: 玩家不在线!"); - } - Actionbar action = new Actionbar(msg.replaceAll("&", "§")); - PlayerReceiveActionbarEvent event = new PlayerReceiveActionbarEvent(player, action); - Bukkit.getPluginManager().callEvent(event); - if (event.isCancelled()) { - return; - } - ActionBarUtils.sendBar(player, action.getMessage()); - } - - @Override - public Entity[] getNearbyEntitiesArrays(Location loc, double radius) { - return EntityUtils.getNearbyEntitiesArrays(loc, radius); - } - - @Override - public void sendSign(Player player, Sign sign) { - if (!player.isOnline()) { - throw new NullPointerException("错误: 玩家不在线!"); - } - if (sign == null) { - throw new NullPointerException("错误: Sign不能为Null!"); - } - if (sign.isEmpty()) { - throw new IllegalArgumentException("错误: Sign不能无内容!"); - } - String[] lines = sign.getTexts(); - //获取Pl管理 - ProtocolManager pm = Core.getInstance().getProtocolManager(); - - /* - * private BlockPosition a; ---> 方块位置 - * public IBlockData block; ---> 方块数据 - */ - BlockPosition blockPosition = new BlockPosition(player.getLocation().toVector()); - - PacketContainer blockChange = pm.createPacket(PacketType.Play.Server.BLOCK_CHANGE); - blockChange.getBlockPositionModifier().write(0, blockPosition); - blockChange.getBlockData().write(0, WrappedBlockData.createData(Material.SIGN_POST)); - - try { - pm.sendServerPacket(player, blockChange); - } catch (InvocationTargetException ex) { - ex.printStackTrace(); - } - - PacketContainer updateSign = pm.createPacket(PacketType.Play.Server.TILE_ENTITY_DATA); - updateSign.getBlockPositionModifier().write(0, blockPosition); - updateSign.getIntegers().write(0, 9); - NbtCompound compound = NbtFactory.ofCompound("Sign"); - for (int i = 0; i < lines.length; i++) { - compound.put("Text" + (i + 1), "{\"text\":\"" + lines[i] + "\"}"); - } - updateSign.getNbtModifier().write(0, compound); - - try { - pm.sendServerPacket(player, updateSign); - } catch (InvocationTargetException ex) { - ex.printStackTrace(); - } - - /* - * 1.8以下为OPEN_SIGN_ENTITY - * OpenSignEditor内部字段 - * private BlockPosition a; ---> 方块位置 - */ - PacketContainer open = pm.createPacket(PacketType.Play.Server.OPEN_SIGN_EDITOR); - open.getBlockPositionModifier().write(0, blockPosition); - - try { - pm.sendServerPacket(player, open); - } catch (InvocationTargetException e) { - e.printStackTrace(); - return; - } - Core.map.put(player.getName(), blockPosition); //丢入缓冲区 - } -} diff --git a/src/main/java/cc/zoyn/core/util/BaiduAPIUtils.java b/src/main/java/cc/zoyn/core/util/BaiduAPIUtils.java deleted file mode 100644 index 4c86fe9..0000000 --- a/src/main/java/cc/zoyn/core/util/BaiduAPIUtils.java +++ /dev/null @@ -1,54 +0,0 @@ -package cc.zoyn.core.util; - -import java.io.BufferedReader; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.net.HttpURLConnection; -import java.net.URL; - -/** - * Create By IDEA - * - * @author Zoyn - * @since 2017-09-10 - */ -public class BaiduAPIUtils { - - /** - * 获取IP的信息 - * - * @param ip ip - * @param apiKey 用户的apiKey - * @return 一段JSON字符串 - */ - public static String getIPInformation(String ip, String apiKey) { - BufferedReader reader = null; - String result = null; - StringBuffer sbf = new StringBuffer(); - StringBuilder http = new StringBuilder("http://apis.baidu.com/bdyunfenxi/intelligence/ip?ip="); - http.append(ip); - - try { - URL url = new URL(http.toString()); - HttpURLConnection connection = (HttpURLConnection) url.openConnection(); - // 设置请求方法 - connection.setRequestMethod("GET"); - // 填入apikey - connection.setRequestProperty("apikey", apiKey); - connection.connect(); - - InputStream is = connection.getInputStream(); - reader = new BufferedReader(new InputStreamReader(is, "UTF-8")); - String strRead = null; - while ((strRead = reader.readLine()) != null) { - sbf.append(strRead); - sbf.append("\r\n"); - } - reader.close(); - result = sbf.toString(); - } catch (Exception e) { - e.printStackTrace(); - } - return result; - } -} diff --git a/src/main/java/cc/zoyn/core/util/BasicUtils.java b/src/main/java/cc/zoyn/core/util/BasicUtils.java deleted file mode 100644 index dcdccc3..0000000 --- a/src/main/java/cc/zoyn/core/util/BasicUtils.java +++ /dev/null @@ -1,191 +0,0 @@ -package cc.zoyn.core.util; - -import com.google.common.collect.Lists; -import org.bukkit.Bukkit; -import org.bukkit.World; -import org.bukkit.entity.Player; - -import java.util.List; -import java.util.UUID; - -/** - * 基础 - 工具类 - * - * @author Zoyn - * @since 2016/12/26 - */ -public class BasicUtils { - - /** - * 取服务器版本 - * - * @return 服务器版本 - */ - public static String getServerVersion() { - return Bukkit.getServer().getClass().getPackage().getName().substring(23); - } - - /** - * 给一个玩家发送json数据 - * - * @param player 玩家 - * @param msg JSON数据 - */ - public static void sendJson(Player player, String msg) { - String version = getServerVersion(); - try { - Object icbc = NMSUtils - .getNMSClass(version.equalsIgnoreCase("v1_8_R1") ? "ChatSerializer" - : "IChatBaseComponent$ChatSerializer") - .getMethod("a", new Class[]{String.class}).invoke(null, new Object[]{msg}); - Object ppoc = NMSUtils.getNMSClass("PacketPlayOutChat") - .getConstructor(new Class[]{NMSUtils.getNMSClass("IChatBaseComponent"), Byte.TYPE}) - .newInstance(icbc, Byte.valueOf("1")); - NMSUtils.sendPacket(player, ppoc); - } catch (Exception e) { - System.out.println("错误: " + e.getMessage()); - } - } - - /** - * 转换Unicode - * - * @param ori 字符 - * @return 转换后的字符串 - */ - public static String convertUnicode(String ori) { - int len = ori.length(); - StringBuffer outBuffer = new StringBuffer(len); - int x = 0; - while (true) { - while (true) { - while (x < len) { - char aChar = ori.charAt(x++); - if (aChar == 92) { - aChar = ori.charAt(x++); - if (aChar == 117) { - int value = 0; - for (int i = 0; i < 4; ++i) { - aChar = ori.charAt(x++); - switch (aChar) { - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - value = (value << 4) + aChar - 48; - break; - case ':': - case ';': - case '<': - case '=': - case '>': - case '?': - case '@': - case 'G': - case 'H': - case 'I': - case 'J': - case 'K': - case 'L': - case 'M': - case 'N': - case 'O': - case 'P': - case 'Q': - case 'R': - case 'S': - case 'T': - case 'U': - case 'V': - case 'W': - case 'X': - case 'Y': - case 'Z': - case '[': - case '\\': - case ']': - case '^': - case '_': - case '`': - default: - throw new IllegalArgumentException("Malformed \\uxxxx encoding."); - case 'A': - case 'B': - case 'C': - case 'D': - case 'E': - case 'F': - value = (value << 4) + 10 + aChar - 65; - break; - case 'a': - case 'b': - case 'c': - case 'd': - case 'e': - case 'f': - value = (value << 4) + 10 + aChar - 97; - } - } - outBuffer.append((char) value); - } else { - if (aChar == 116) { - aChar = 9; - } else if (aChar == 114) { - aChar = 13; - } else if (aChar == 110) { - aChar = 10; - } else if (aChar == 102) { - aChar = 12; - } - outBuffer.append(aChar); - } - } else { - outBuffer.append(aChar); - } - } - return outBuffer.toString(); - } - } - } - - /** - * 取服务器在线玩家 - * - * @return 玩家集合 - */ - public static List getOnlinePlayers() { - // 实例化两个List用于存放Player和World - List players = Lists.newArrayList(); - List worlds = Lists.newArrayList(); - worlds.addAll(Bukkit.getWorlds()); - // 遍历所有的世界 - for (int i = 0; i < worlds.size(); i++) { - // 如果第i个世界的玩家是空的则进行下一次循环 - if (worlds.get(i).getPlayers().isEmpty()) { - continue; - } else { - // 不是空的则添加到players集合中 - players.addAll(worlds.get(i).getPlayers()); - } - } - return players; - } - - /** - * 将名字转换为UUID - * - * @param name 名字 - * @return 该名的UUID对象 - */ - public UUID translateNameToUUID(String name) { - UUID uuid = null; - uuid = Bukkit.getPlayer(name).getUniqueId(); - return uuid; - } -} diff --git a/src/main/java/cc/zoyn/core/util/BookUtils.java b/src/main/java/cc/zoyn/core/util/BookUtils.java deleted file mode 100644 index a2b86a4..0000000 --- a/src/main/java/cc/zoyn/core/util/BookUtils.java +++ /dev/null @@ -1,147 +0,0 @@ -package cc.zoyn.core.util; - -import cc.zoyn.core.dto.Book; -import cc.zoyn.core.dto.Page; -import cc.zoyn.core.util.ReflectionUtils.PackageType; -import org.bukkit.Bukkit; -import org.bukkit.entity.Player; -import org.bukkit.inventory.ItemStack; -import org.bukkit.inventory.meta.BookMeta; - -import java.lang.reflect.Method; -import java.util.List; - -/** - * 书本 - 工具类 - * - * @author Zoyn - * @since 2017/?/? - */ -public class BookUtils { - - private static boolean initialised = false; - private static Method getHandle; - private static Method openBook; - - static { - try { - getHandle = ReflectionUtils.getMethod("CraftPlayer", PackageType.CRAFTBUKKIT_ENTITY, "getHandle"); - openBook = ReflectionUtils.getMethod("EntityPlayer", PackageType.MINECRAFT_SERVER, "a", - PackageType.MINECRAFT_SERVER.getClass("ItemStack"), - PackageType.MINECRAFT_SERVER.getClass("EnumHand")); - initialised = true; - } catch (ReflectiveOperationException e) { - e.printStackTrace(); - Bukkit.getServer().getLogger().warning("Cannot force open book!"); - initialised = false; - } - } - - public static boolean isInitialised() { - return initialised; - } - - /** - * 打开一个虚拟的书 - * - * @param item 书 - * @param player 玩家 - * @return 布尔值[true成功/false失败] - */ - public static boolean openBook(Player player, Book book) { - if (!initialised) - return false; - ItemStack held = player.getInventory().getItemInMainHand(); - ItemStack bookItem = book.getItem(); - try { - player.getInventory().setItemInMainHand(bookItem); - sendPacket(bookItem, player); - } catch (ReflectiveOperationException e) { - e.printStackTrace(); - initialised = false; - } - player.getInventory().setItemInMainHand(held); - return initialised; - - } - - /** - * 打开一个虚拟的书 - * - * @param item 书 - * @param player 玩家 - * @return 布尔值[true成功/false失败] - */ - public static boolean openBook(ItemStack item, Player player) { - if (!initialised) - return false; - ItemStack held = player.getInventory().getItemInMainHand(); - try { - player.getInventory().setItemInMainHand(item); - sendPacket(item, player); - } catch (ReflectiveOperationException e) { - e.printStackTrace(); - initialised = false; - } - player.getInventory().setItemInMainHand(held); - return initialised; - } - - private static void sendPacket(ItemStack i, Player p) throws ReflectiveOperationException { - Object entityplayer = getHandle.invoke(p); - Class enumHand = PackageType.MINECRAFT_SERVER.getClass("EnumHand"); - Object[] enumArray = enumHand.getEnumConstants(); - openBook.invoke(entityplayer, getItemStack(i), enumArray[0]); - } - - public static Object getItemStack(ItemStack item) { - try { - Method asNMSCopy = ReflectionUtils.getMethod(PackageType.CRAFTBUKKIT_INVENTORY.getClass("CraftItemStack"), - "asNMSCopy", ItemStack.class); - return asNMSCopy.invoke(PackageType.CRAFTBUKKIT_INVENTORY.getClass("CraftItemStack"), item); - } catch (Exception e) { - e.printStackTrace(); - } - return null; - } - - /** - * 以JSON格式来设置书的页面 - * - * @param metadata 书本的BookMeta - * @param pages 每页的json集合 - */ - @SuppressWarnings("unchecked") - public static void setPagesAsJson(BookMeta metadata, List pages) { - List p; - Object page; - try { - p = (List) ReflectionUtils - .getField(PackageType.CRAFTBUKKIT_INVENTORY.getClass("CraftMetaBook"), true, "pages").get(metadata); - for (String text : pages) { - page = ReflectionUtils.invokeMethod(ReflectionUtils.PackageType.MINECRAFT_SERVER - .getClass("IChatBaseComponent$ChatSerializer").newInstance(), "a", text); - p.add(page); - } - } catch (Exception e) { - e.printStackTrace(); - } - } - - @SuppressWarnings("unchecked") - public static void setPagesAsPage(BookMeta meta, List pagess) { - List p; - Object page; - try { - p = (List) ReflectionUtils - .getField(PackageType.CRAFTBUKKIT_INVENTORY.getClass("CraftMetaBook"), true, "pages").get(meta); - for (Page onePage : pagess) { - page = ReflectionUtils.invokeMethod(ReflectionUtils.PackageType.MINECRAFT_SERVER - .getClass("IChatBaseComponent$ChatSerializer").newInstance(), "a", onePage.toJsonString()); - p.add(page); - } - } catch (Exception e) { - e.printStackTrace(); - } - } -} \ No newline at end of file diff --git a/src/main/java/cc/zoyn/core/util/BungeeCordUtils.java b/src/main/java/cc/zoyn/core/util/BungeeCordUtils.java deleted file mode 100644 index 1f63bb1..0000000 --- a/src/main/java/cc/zoyn/core/util/BungeeCordUtils.java +++ /dev/null @@ -1,86 +0,0 @@ -package cc.zoyn.core.util; - -import com.google.common.collect.Iterables; -import cc.zoyn.core.Core; -import org.bukkit.Bukkit; -import org.bukkit.entity.Player; -import org.bukkit.plugin.messaging.PluginMessageListener; - -import java.io.ByteArrayOutputStream; -import java.io.DataOutputStream; -import java.io.IOException; - -/** - * BungeeCord - 工具类 - * - * @author Zoyn - */ -public class BungeeCordUtils implements PluginMessageListener { - - /** - * 将玩家传送至某子服 - * - * @param name 名字 - * @param serverName 服务器名 - */ - public static void playerConnectServer(String name, String serverName) { - ByteArrayOutputStream byteOut = new ByteArrayOutputStream(); - DataOutputStream dataOut = new DataOutputStream(byteOut); - try { - dataOut.writeUTF("Connect"); - dataOut.writeUTF(name); - dataOut.writeUTF(serverName); - } catch (IOException e) { - System.out.println("错误: " + e.getMessage()); - } - if (Bukkit.getOnlinePlayers() != null) { - Player player = (Player) Iterables.getFirst(Bukkit.getOnlinePlayers(), null); - player.sendPluginMessage(Core.getInstance(), "BungeeCord", byteOut.toByteArray()); - } - } - - /** - * 踢出一个玩家 - * - * @param name 玩家名 - * @param message 信息 - */ - public static void kickPlayer(String name, String message) { - ByteArrayOutputStream byteOut = new ByteArrayOutputStream(); - DataOutputStream dataOut = new DataOutputStream(byteOut); - try { - dataOut.writeUTF("KickPlayer"); - dataOut.writeUTF(name); - dataOut.writeUTF(message); - } catch (IOException e) { - System.out.println("错误: " + e.getMessage()); - } - if (Bukkit.getOnlinePlayers() != null) { - Player player = (Player) Iterables.getFirst(Bukkit.getOnlinePlayers(), null); - player.sendPluginMessage(Core.getInstance(), "BungeeCord", byteOut.toByteArray()); - } - } - - public static void sendData(String tag, String message) { - ByteArrayOutputStream byteOut = new ByteArrayOutputStream(); - DataOutputStream dataOut = new DataOutputStream(byteOut); - try { - dataOut.writeUTF(tag); - dataOut.writeUTF(message); - } catch (IOException e) { - System.out.println("错误: " + e.getMessage()); - } - if (Bukkit.getOnlinePlayers() != null) { - Player player = (Player) Iterables.getFirst(Bukkit.getOnlinePlayers(), null); - player.sendPluginMessage(Core.getInstance(), "BukkitCoreMessage", byteOut.toByteArray()); - } - } - - @Override - public void onPluginMessageReceived(String channel, Player player, byte[] message) { - if (!channel.equals("BukkitCoreMessage")) { - return; - } - } - -} diff --git a/src/main/java/cc/zoyn/core/util/EffectUtils.java b/src/main/java/cc/zoyn/core/util/EffectUtils.java deleted file mode 100644 index 4e8f535..0000000 --- a/src/main/java/cc/zoyn/core/util/EffectUtils.java +++ /dev/null @@ -1,194 +0,0 @@ -package cc.zoyn.core.util; - -import cc.zoyn.core.Core; -import org.bukkit.Bukkit; -import org.bukkit.Effect; -import org.bukkit.Location; -import org.bukkit.entity.ArmorStand; -import org.bukkit.entity.Player; -import org.bukkit.inventory.ItemStack; -import org.bukkit.util.EulerAngle; -import org.bukkit.util.Vector; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; - -public class EffectUtils { - - /** - * 创建三维旋转特效 - * - * @param player 玩家 - * @throws Exception - */ - public void createHelix(Player player) throws Exception { - Location loc = player.getLocation(); - int radius = 2; - for (double y = 0; y <= 50; y += 0.05) { - double x = radius * Math.cos(y); - double z = radius * Math.sin(y); - Object packet = NMSUtils.getNMSClass("PacketPlayOutWorldParticles").newInstance(); - packet = packet.getClass() - .getConstructor(String.class, float.class, float.class, float.class, float.class, float.class, - float.class, float.class, int.class) - .newInstance("fireworksSpark", (float) (loc.getX() + x), (float) (loc.getY() + y), - (float) (loc.getZ() + z), 0, 0, 0, 0, 1); - for (Player online : Bukkit.getOnlinePlayers()) { - Object nmsPlayer = online.getClass().getMethod("getHandle").invoke(online); - Object playerConnection = nmsPlayer.getClass().getDeclaredField("playerConnection").get(nmsPlayer); - playerConnection.getClass().getMethod("sendPacket", NMSUtils.getNMSClass("Packet")) - .invoke(playerConnection, packet); - } - } - } - - private static HashMap, Location> lastLoc = new HashMap, Location>(); - - @SuppressWarnings("deprecation") - public static void callCircle(final Player p, int id, double amount, final int time) { - // 取玩家的坐标 - Location loc = p.getLocation(); - loc.setDirection(new Vector()); - loc.add(0.0D, -1.0D, 0.0D); - // 之后将头向下 - - // 建立一个存放ArmorStand的list - final List list = new ArrayList(); - // 遍历要生成的个数 - for (int i = 0; i < amount; i++) { - // 计算第i个ArmorStand的位置 公式为 ---> i除以全部数量乘以π再乘以2 - double rand = i / amount * 3.141592653589793D * 2.0D; - double dx = Math.cos(rand); - double dz = Math.sin(rand); - ArmorStand as = (ArmorStand) loc.getWorld().spawn(loc.clone().add(dx, 0.0D, dz), ArmorStand.class); - as.setVisible(false); - as.setGravity(false); - as.setHelmet(new ItemStack(id)); - as.setHeadPose(EulerAngle.ZERO.setY(rand)); - list.add(as); - } - - // 添加到 第一次开始执行时的Map - lastLoc.put(list, p.getLocation()); - - // 异步操作 - Bukkit.getScheduler().runTaskTimer(Core.getInstance(), new Runnable() { - // 线程死亡开关 - boolean dead; - // 倒数 - int countDown = 0; - - public void run() { - // 如果线程死亡开启则返回 - if (dead) { - return; - } - // 判断玩家是否在线,并且是活着的 - if ((p.isOnline()) && (!p.isDead()) && (countDown < time)) { - // 倒数器 自加1 - countDown += 1; - // 取玩家 - Vector v = p.getLocation().subtract((Location) lastLoc.get(list)).toVector(); - for (ArmorStand as : list) { - as.teleport(as.getLocation().add(v)); - double rand = 1 / amount * 3.141592653589793D * 2.0D; - double dx = Math.cos(rand); - double dz = Math.sin(rand); - p.playEffect(lastLoc.get(list).clone().add(dx, 0.0D, dz), Effect.HAPPY_VILLAGER, 3); - } - lastLoc.put(list, p.getLocation()); - } else { - for (ArmorStand as : list) { - as.remove(); - } - dead = true; - } - } - }, 1L, 1L); - } - - public static List buildCircle(Location center, int radius, float precision) { - List ret = new ArrayList(); - for (float i = precision; i < 6.283185307179586D; i += precision) { - ret.add(new Location(center.getWorld(), Math.cos(i) * radius + center.getX(), center.getY(), - Math.sin(i) * radius + center.getZ())); - } - return ret; - } - - public static List buildLine(Location loc1, Location loc2) { - List line = new ArrayList(); - int dx = Math.max(loc1.getBlockX(), loc2.getBlockX()) - Math.min(loc1.getBlockX(), loc2.getBlockX()); - int dy = Math.max(loc1.getBlockY(), loc2.getBlockY()) - Math.min(loc1.getBlockY(), loc2.getBlockY()); - int dz = Math.max(loc1.getBlockZ(), loc2.getBlockZ()) - Math.min(loc1.getBlockZ(), loc2.getBlockZ()); - int x1 = loc1.getBlockX(); - int x2 = loc2.getBlockX(); - int y1 = loc1.getBlockY(); - int y2 = loc2.getBlockY(); - int z1 = loc1.getBlockZ(); - int z2 = loc2.getBlockZ(); - int x = 0; - int y = 0; - int z = 0; - int i = 0; - int d = 1; - switch (findHighest(dx, dy, dz)) { - case 1: - i = 0; - d = 1; - if (x1 > x2) { - d = -1; - } - x = loc1.getBlockX(); - do { - i++; - y = y1 + (x - x1) * (y2 - y1) / (x2 - x1); - z = z1 + (x - x1) * (z2 - z1) / (x2 - x1); - line.add(new Location(loc1.getWorld(), x, y, z)); - x += d; - } while (i <= Math.max(x1, x2) - Math.min(x1, x2)); - break; - case 2: - i = 0; - d = 1; - if (y1 > y2) { - d = -1; - } - y = loc1.getBlockY(); - do { - i++; - x = x1 + (y - y1) * (x2 - x1) / (y2 - y1); - z = z1 + (y - y1) * (z2 - z1) / (y2 - y1); - line.add(new Location(loc1.getWorld(), x, y, z)); - y += d; - } while (i <= Math.max(y1, y2) - Math.min(y1, y2)); - break; - case 3: - i = 0; - d = 1; - if (z1 > z2) { - d = -1; - } - z = loc1.getBlockZ(); - do { - i++; - y = y1 + (z - z1) * (y2 - y1) / (z2 - z1); - x = x1 + (z - z1) * (x2 - x1) / (z2 - z1); - line.add(new Location(loc1.getWorld(), x, y, z)); - z += d; - } while (i <= Math.max(z1, z2) - Math.min(z1, z2)); - } - return line; - } - - private static int findHighest(int x, int y, int z) { - if ((x >= y) && (x >= z)) { - return 1; - } - if ((y >= x) && (y >= z)) { - return 2; - } - return 3; - } -} diff --git a/src/main/java/cc/zoyn/core/util/IsNullUtils.java b/src/main/java/cc/zoyn/core/util/IsNullUtils.java deleted file mode 100644 index 9ad062a..0000000 --- a/src/main/java/cc/zoyn/core/util/IsNullUtils.java +++ /dev/null @@ -1,167 +0,0 @@ -package cc.zoyn.core.util; - -import java.io.File; -import java.util.List; -import java.util.Map; - -/** - * 空,非空判断工具 - * - * @author Zoyn - */ -public class IsNullUtils { - - private static boolean flag; //记录判断结果 - - /** - * 判断空 - * 举例 - * null:true - * new Object():false - * 0:true - * List.size() = 0:true - * - * @param object 对象 - * @return true[是]/false[不是] - */ - public static boolean isNull(Object object) { - if (object == null) { - return true; - } - return detect(object, true); - } - - /** - * 判断非空 - *

- * 举例 - * null:false - * new Object():true - * 0.0001:true - * List.size() = 0:false - * - * @param object 对象 - * @return true[是]/false[不是] - */ - public static boolean notNull(Object object) { - if (object == null) { - return false; - } - return detect(object, false); - } - - private static boolean detect(Object object, boolean isDetectNull) { - if (object instanceof Boolean) { - return (boolean) object; - } else if (object instanceof String) { - if (((String) object).equals("")) { - if (isDetectNull) - flag = true; - else - flag = false; - } else { - if (isDetectNull) - flag = false; - else - flag = true; - } - } else if (object instanceof Integer) { - if (((Integer) object) == 0) { - if (isDetectNull) - flag = true; - else - flag = false; - } else { - if (isDetectNull) - flag = false; - else - flag = true; - } - } else if (object instanceof Double) { - if (((Double) object) == 0) { - if (isDetectNull) - flag = true; - else - flag = false; - } else { - if (isDetectNull) - flag = false; - else - flag = true; - } - } else if (object instanceof Float) { - if (((Float) object) == 0) { - if (isDetectNull) - flag = true; - else - flag = false; - } else { - if (isDetectNull) - flag = false; - else - flag = true; - } - } else if (object instanceof List) { - if (((List) object).size() < 1) { - if (isDetectNull) - flag = true; - else - flag = false; - } else { - if (isDetectNull) - flag = false; - else - flag = true; - } - } else if (object instanceof Map) { - if (((Map) object).isEmpty()) { - if (isDetectNull) - flag = true; - else - flag = false; - } else { - if (isDetectNull) - flag = false; - else - flag = true; - } - } else if (object instanceof File) { - if (((File) object).exists()) { - if (isDetectNull) - flag = false; - else - flag = true; - } else { - if (isDetectNull) - flag = true; - else - flag = false; - } - } else if (object instanceof Object[]) { - if (((Object[]) object).length < 1) { - if (isDetectNull) - flag = true; - else - flag = false; - } else { - if (isDetectNull) - flag = false; - else - flag = true; - } - } else { - if (object == null) { - if (isDetectNull) - flag = true; - else - flag = false; - } else { - if (isDetectNull) - flag = false; - else - flag = true; - } - } - return flag; - } -} diff --git a/src/main/java/cc/zoyn/core/util/NBTUtils.java b/src/main/java/cc/zoyn/core/util/NBTUtils.java deleted file mode 100644 index 6eae4ac..0000000 --- a/src/main/java/cc/zoyn/core/util/NBTUtils.java +++ /dev/null @@ -1,203 +0,0 @@ -package cc.zoyn.core.util; - -import cc.zoyn.core.dto.SlotTypeEnum; -import org.bukkit.inventory.ItemStack; - -import java.lang.reflect.Method; - -public class NBTUtils { - - private static Method setTag; - private static Method set; - - static { - try { - setTag = NMSUtils.getNMSClass("ItemStack").getMethod("setTag", NMSUtils.getNMSClass("NBTTagCompound")); - set = NMSUtils.getNMSClass("NBTTagCompound").getMethod("set", new Class[]{String.class, NMSUtils.getNMSClass("NBTBase")}); - } catch (Exception e) { - e.printStackTrace(); - } - } - - // /** - // * 各类属性 - // */ - // private static String attackDamage = "generic.attackDamage"; - // private static String attackSpeed = "generic.attackSpeed"; - // private static String maxHealth = "generic.maxHealth"; - // private static String moveMentSpeed = "generic.movementSpeed"; - // private static String armor = "generic.armor"; - // private static String luck = "generic.luck"; - - public static Object nbtTagString(String str) { - try { - return NMSUtils.getNMSClass("NBTTagString").getConstructor(String.class).newInstance(str); - } catch (Exception e) { - System.out.println("错误: " + e.getMessage()); - } - return null; - } - - public static Object nbtTagInt(int num) { - try { - return NMSUtils.getNMSClass("NBTTagInt").getConstructor(Integer.TYPE).newInstance(num); - } catch (Exception e) { - System.out.println("错误: " + e.getMessage()); - } - return null; - } - - public static Object nbtTagDouble(double num) { - try { - return NMSUtils.getNMSClass("NBTTagDouble").getConstructor(Double.TYPE).newInstance(num); - } catch (Exception e) { - System.out.println("错误: " + e.getMessage()); - } - return null; - } - - public static Object nbtTagByte(byte num) { - try { - return NMSUtils.getNMSClass("NBTTagByte").getConstructor(Byte.TYPE).newInstance(num); - } catch (Exception e) { - System.out.println("错误: " + e.getMessage()); - } - return null; - } - - public static Object nbtTagFloat(float num) { - try { - return NMSUtils.getNMSClass("NBTTagFloat").getConstructor(Float.TYPE).newInstance(num); - } catch (Exception e) { - System.out.println("错误: " + e.getMessage()); - } - return null; - } - - public static Object getItemNBT(ItemStack is) { - Object nmsItem = NMSUtils.getNMSItem(is); - if (nmsItem == null) { - return null; - } - try { - return nmsItem.getClass().getMethod("getTag").invoke(nmsItem) != null - ? nmsItem.getClass().getMethod("getTag").invoke(nmsItem) - : NMSUtils.getNMSClass("NBTTagCompound").newInstance(); - } catch (Exception e) { - System.out.println("错误: " + e.getMessage()); - } - return null; - } - - public static void setUnbreakable(ItemStack is, boolean unbreak) { - Object nmsItem = NMSUtils.getNMSItem(is); - Object itemNbt = getItemNBT(is); - try { - //NPE检查 - if (set == null) { - set = NMSUtils.getNMSClass("NBTTagCompound").getMethod("set", new Class[]{String.class, NMSUtils.getNMSClass("NBTBase")}); - } - set.invoke(itemNbt, new Object[]{"Unbreakable", nbtTagByte((byte) (unbreak ? 1 : 0))}); - - //NPE检查 - if (setTag == null) { - setTag = NMSUtils.getNMSClass("ItemStack").getMethod("setTag", NMSUtils.getNMSClass("NBTTagCompound")); - } - - setTag.invoke(nmsItem, itemNbt); - NMSUtils.getOBCClass("inventory.CraftItemStack").getMethod("asBukkitCopy", NMSUtils.getNMSClass("ItemStack")).invoke(nmsItem, nmsItem); - } catch (Exception e) { - e.printStackTrace(); - } - } - - /** - * 取武器的Attribute数据 - * - * @param is 物品 - * @return NBTTagCompound的实例 - */ - public static Object getAttribute(ItemStack is) { - Object nmsItem = NMSUtils.getNMSItem(is); - // 判断是否有无Tag数据 - try { - if (nmsItem.getClass().getMethod("getTag").invoke(nmsItem) != null) { - return nmsItem.getClass().getMethod("getTag").invoke(nmsItem); - } else { - // 如果没有Tag数据则实例化个NBTTagCompound的实例 - return NMSUtils.getNMSClass("NBTTagCompound").newInstance(); - } - } catch (Exception e) { - System.out.println("错误: " + e.getMessage()); - } - - return null; - } - - // public static ItemStack setUnbreakable(ItemStack is, boolean unbreak) { - // Object nmsItem = NMSUtil.getNMSItem(is); - // Object itemNbt = getItemNBT(is); - // return null; - // } - - /** - * 设置物品伤害 - * - * @param is 物品 - * @param damage 伤害 - * @param slot 位置 - * @return 物品的ItemStack - */ - public static ItemStack setItemDamage(ItemStack is, int damage, SlotTypeEnum slot) { - try { - // 物品的nms对象 - Object nmsItem = is.getClass().getMethod("asNMSCopy", ItemStack.class).invoke(is, is); - // 物品的nbt对象 - Object itemNbt = nmsItem.getClass().getMethod("getTag").invoke(nmsItem) != null - ? nmsItem.getClass().getMethod("getTag").invoke(nmsItem) - : NMSUtils.getNMSClass("NBTTagCompound").newInstance(); - // NbtTagList对象 - Object modifiers = NMSUtils.getNMSClass("NBTTagList").getConstructor().newInstance(); - Object damageTag = NMSUtils.getNMSClass("NBTTagCompound").getConstructor().newInstance(); - // 模块数据构造 - Object attackDamage = NMSUtils.getNMSClass("NBTTagString").getConstructor(String.class) - .newInstance("generic.attackDamage"); - Object name = NMSUtils.getNMSClass("NBTTagString").getConstructor(String.class).newInstance("Damage"); - Object amount = NMSUtils.getNMSClass("NBTTagInt").getConstructor(Integer.TYPE).newInstance(damage); - Object operation = NMSUtils.getNMSClass("NBTTagInt").getConstructor(Integer.TYPE).newInstance(0); - Object uuidLeast = NMSUtils.getNMSClass("NBTTagInt").getConstructor(Integer.TYPE).newInstance(894654); - Object uuidMost = NMSUtils.getNMSClass("NBTTagInt").getConstructor(Integer.TYPE).newInstance(2872); - Object slotTag = NMSUtils.getNMSClass("NBTTagString").getConstructor(String.class) - .newInstance(slot.toString()); - // 模块数据输入 - damageTag.getClass().getMethod("set", new Class[]{String.class, NMSUtils.getNMSClass("NBTBase")}) - .invoke(damageTag, new Object[]{"AttributeName", attackDamage}); - damageTag.getClass().getMethod("set", new Class[]{String.class, NMSUtils.getNMSClass("NBTBase")}) - .invoke(damageTag, new Object[]{"Name", name}); - damageTag.getClass().getMethod("set", new Class[]{String.class, NMSUtils.getNMSClass("NBTBase")}) - .invoke(damageTag, new Object[]{"Amount", amount}); - damageTag.getClass().getMethod("set", new Class[]{String.class, NMSUtils.getNMSClass("NBTBase")}) - .invoke(damageTag, new Object[]{"Operation", operation}); - damageTag.getClass().getMethod("set", new Class[]{String.class, NMSUtils.getNMSClass("NBTBase")}) - .invoke(damageTag, new Object[]{"UUIDLeast", uuidLeast}); - damageTag.getClass().getMethod("set", new Class[]{String.class, NMSUtils.getNMSClass("NBTBase")}) - .invoke(damageTag, new Object[]{"UUIDMost", uuidMost}); - damageTag.getClass().getMethod("set", new Class[]{String.class, NMSUtils.getNMSClass("NBTBase")}) - .invoke(damageTag, new Object[]{"Slot", slotTag}); - // NbtTagList数据导入 - modifiers.getClass().getMethod("add", NMSUtils.getNMSClass("NBTBase")).invoke(modifiers, damageTag); - // 设置该NbtTagList - itemNbt.getClass().getMethod("set", new Class[]{String.class, NMSUtils.getNMSClass("NBTBase")}) - .invoke(itemNbt, new Object[]{"AttributeModifiers", modifiers}); - // 保存nbt数据 - nmsItem.getClass().getMethod("setTag", NMSUtils.getNMSClass("NBTTagCompound")).invoke(nmsItem, itemNbt); - ItemStack bukItem = (ItemStack) is.getClass().getMethod("asBukkitCopy", NMSUtils.getNMSClass("ItemStack")) - .invoke(nmsItem, nmsItem); - return bukItem; - } catch (Exception e) { - System.out.println("错误: " + e.getMessage()); - } - return is; - } - -} diff --git a/src/main/java/cc/zoyn/core/util/NMSUtils.java b/src/main/java/cc/zoyn/core/util/NMSUtils.java deleted file mode 100644 index a895566..0000000 --- a/src/main/java/cc/zoyn/core/util/NMSUtils.java +++ /dev/null @@ -1,154 +0,0 @@ -package cc.zoyn.core.util; - -import org.bukkit.Bukkit; -import org.bukkit.entity.Player; -import org.bukkit.inventory.ItemStack; - -/** - * NMS工具类 - * - * @author Zoyn - * @since 2017/4/26 - */ -public class NMSUtils { - - private static Class chatSerializer; - private static Class enumTitleAction; - private static Class packetPlayOutTitle; - private static Class packetPlayOutChat; - private static String version; - - private NMSUtils() { - } - - ; - - static { - //org.bukkit.craftbukkit.vX_XX_RX; - version = Bukkit.getServer().getClass().getPackage().getName().split("\\.")[3]; - chatSerializer = version.contains("v1_8_R1") ? getNMSClass("ChatSerializer") : getNMSClass("IChatBaseComponent$ChatSerializer"); - enumTitleAction = version.contains("v1_8_R1") ? getNMSClass("EnumTitleAction") : getNMSClass("PacketPlayOutTitle$EnumTitleAction"); - packetPlayOutTitle = getNMSClass("PacketPlayOutTitle"); - packetPlayOutChat = getNMSClass("PacketPlayOutChat"); - } - - /** - * 取PacketPlayOutTitle类 - * - * @return {@link Class} - */ - public static Class getPacketPlayOutTitleClass() { - return packetPlayOutTitle; - } - - /** - * 取PacketPlayOutChat类 - * - * @return {@link Class} - */ - public static Class getPacketPlayOutChatClass() { - return packetPlayOutChat; - } - - /** - * 取EnumTitleAction类 - * - * @return {@link Class} - */ - public static Class getEnumTitleActionClass() { - return enumTitleAction; - } - - /** - * 取chatSerializer类 - * - * @return {@link Class} - */ - public static Class getChatSerializerClass() { - return chatSerializer; - } - - /** - * 取服务器版本 如v1_10_R1 - * - * @return 服务器版本 - */ - public static String getVersion() { - return version; - } - - public static Class getOBCClass(String className) { - try { - return Class.forName("org.bukkit.craftbukkit." + NMSUtils.getVersion() + "." + className); - } catch (ClassNotFoundException e) { - e.printStackTrace(); - } - return null; - } - - /** - * 取物品的NMS对象 - * - * @param is - * @return {@link Object} - */ - public static Object getNMSItem(ItemStack is) { - try { - return NMSUtils.getOBCClass("inventory.CraftItemStack").getMethod("asNMSCopy", ItemStack.class).invoke(is, is); - } catch (Exception e) { - System.out.println("错误: " + e.getMessage()); - } - return null; - } - - /** - * 取对应的NMS下的类 - * - * @param className 类名 - * @return {@link Class} - */ - public static Class getNMSClass(String className) { - try { - return Class.forName("net.minecraft.server." + version + "." + className); - } catch (Exception e) { - System.out.println("错误: " + e.getMessage()); - } - return null; - } - - /** - * 给一名玩家发送NMS数据包 - * - * @param player 玩家 - * @param packet 数据包对象 - */ - public static void sendPacket(Player player, Object packet) { - //取NMS实例 - Object entityPlayer = getNMSPlayer(player); - try { - //取其playerConnection实例 - Object playerConnection = entityPlayer.getClass().getField("playerConnection").get(entityPlayer); - //调用方法sendPacket() - playerConnection.getClass().getMethod("sendPacket", new Class[]{getNMSClass("Packet")}).invoke(playerConnection, packet); - } catch (Exception e) { - System.out.println("错误: " + e.getMessage()); - } - } - - /** - * 取玩家NMS对象也就是EntityPlayer类的实例 - * - * @param player 玩家 - * @return 玩家的NMS对象 - */ - public static Object getNMSPlayer(Player player) { - try { - //取Player的实现类并调用其方法getHandle - Object entityPlayer = player.getClass().getMethod("getHandle").invoke(player); - return entityPlayer; - } catch (Exception e) { - System.out.println("错误: " + e.getMessage()); - } - return player; - } -} diff --git a/src/main/java/cc/zoyn/core/util/NPCUtils.java b/src/main/java/cc/zoyn/core/util/NPCUtils.java deleted file mode 100644 index 338be86..0000000 --- a/src/main/java/cc/zoyn/core/util/NPCUtils.java +++ /dev/null @@ -1,169 +0,0 @@ -package cc.zoyn.core.util; - -import com.comphenix.protocol.PacketType; -import com.comphenix.protocol.ProtocolLibrary; -import com.comphenix.protocol.ProtocolManager; -import com.comphenix.protocol.events.PacketContainer; -import com.comphenix.protocol.wrappers.EnumWrappers.NativeGameMode; -import com.comphenix.protocol.wrappers.EnumWrappers.PlayerInfoAction; -import com.comphenix.protocol.wrappers.PlayerInfoData; -import com.comphenix.protocol.wrappers.WrappedChatComponent; -import com.comphenix.protocol.wrappers.WrappedDataWatcher; -import com.comphenix.protocol.wrappers.WrappedGameProfile; -import com.google.common.collect.Lists; -import com.google.gson.JsonObject; -import com.google.gson.JsonParser; -import com.mojang.authlib.GameProfile; -import com.mojang.authlib.properties.Property; -import cc.zoyn.core.Core; -import net.minecraft.server.v1_12_R1.*; -import net.minecraft.server.v1_12_R1.PacketPlayOutPlayerInfo.EnumPlayerInfoAction; -import org.bukkit.Bukkit; -import org.bukkit.craftbukkit.v1_12_R1.CraftServer; -import org.bukkit.craftbukkit.v1_12_R1.entity.CraftPlayer; -import org.bukkit.entity.Player; - -import java.io.IOException; -import java.io.InputStreamReader; -import java.lang.reflect.InvocationTargetException; -import java.net.URL; -import java.util.List; -import java.util.UUID; - -public class NPCUtils { - - public static String[] getFromName(String name) { - try { - URL url_0 = new URL("https://api.mojang.com/users/profiles/minecraft/" + name); - InputStreamReader reader_0 = new InputStreamReader(url_0.openStream()); - String uuid = new JsonParser().parse(reader_0).getAsJsonObject().get("id").getAsString(); - - URL url_1 = new URL("https://sessionserver.mojang.com/session/minecraft/profile/" + uuid + "?unsigned=false"); - InputStreamReader reader_1 = new InputStreamReader(url_1.openStream()); - JsonObject textureProperty = new JsonParser().parse(reader_1).getAsJsonObject().get("properties").getAsJsonArray().get(0).getAsJsonObject(); - String texture = textureProperty.get("value").getAsString(); - String signature = textureProperty.get("signature").getAsString(); - - return new String[]{texture, signature}; - } catch (IOException e) { - System.err.println("无法从服务器读取皮肤信息!"); - e.printStackTrace(); - return null; - } - } - - - /** - * 增加npc - * - * @param name NPC显示名 - * @param skinName 皮肤名 - * @param x 坐标X - * @param y 坐标Y - * @param z 坐标Z - */ - public static void addNpc(String name, String skinName, double x, double y, double z) { - String[] a = getFromName(skinName); - MinecraftServer server = ((CraftServer) Bukkit.getServer()).getServer(); - GameProfile profile = new GameProfile(UUID.randomUUID(), name); - profile.getProperties().put("textures", new Property("textures", a[0], a[1])); - EntityPlayer npc = new EntityPlayer(server, server.getWorldServer(0), profile, new PlayerInteractManager(server.getWorldServer(0))); - npc.setPosition(x, y, z); - for (Player player : Bukkit.getOnlinePlayers()) { - ((CraftPlayer) player).getHandle().playerConnection.sendPacket(new PacketPlayOutPlayerInfo(EnumPlayerInfoAction.ADD_PLAYER, npc)); - ((CraftPlayer) player).getHandle().playerConnection.sendPacket(new PacketPlayOutNamedEntitySpawn(npc)); - Bukkit.getScheduler().scheduleSyncDelayedTask(Core.getInstance(), new Runnable() { - @Override - public void run() { - ((CraftPlayer) player).getHandle().playerConnection.sendPacket(new PacketPlayOutPlayerInfo(EnumPlayerInfoAction.REMOVE_PLAYER, npc)); - } - }, 5); - } - } - - /** - * 使用ProtocolLib制造NPC - * - * @param name NPC名 - * @param skinName 皮肤名 - * @param x 坐标X - * @param y 坐标Y - * @param z 坐标Z - */ - public static void addNPCUsePL(String name, String skinName, double x, double y, double z) { - //获取皮肤信息 - String[] skin = getFromName(skinName); - //获取Server的nms对象 - MinecraftServer server = ((CraftServer) Bukkit.getServer()).getServer(); - //新建一个NPC的GameProfile - GameProfile profile = new GameProfile(UUID.randomUUID(), name); - //设置皮肤 - profile.getProperties().put("textures", new Property("textures", skin[0], skin[1])); - - //实例化NPC对象 - EntityPlayer npc = new EntityPlayer(server, server.getWorldServer(0), profile, new PlayerInteractManager(server.getWorldServer(0))); - //设置坐标 - npc.setPosition(x, y, z); - - //获取PL管理工具 - ProtocolManager pm = ProtocolLibrary.getProtocolManager(); - - PacketContainer packet = pm.createPacket(PacketType.Play.Server.PLAYER_INFO); - /* - * PlayerInfo - * private EnumPlayerInfoAction a; - * private final List b = Lists.newArrayList(); - */ - //依次写入相关数据 - packet.getPlayerInfoAction().write(0, PlayerInfoAction.ADD_PLAYER); - List datas = Lists.newArrayList(); - datas.add(new PlayerInfoData(WrappedGameProfile.fromHandle(npc.getProfile()), npc.ping, NativeGameMode.CREATIVE, WrappedChatComponent.fromText(name))); - packet.getPlayerInfoDataLists().write(0, datas); - - //已命名实体生成 - PacketContainer packet2 = pm.createPacket(PacketType.Play.Server.NAMED_ENTITY_SPAWN); - /* - * NamedEntitySpawn - * private int a; - * private UUID b; - * private double c; - * private double d; - * private double e; - * private byte f; - * private byte g; - * private DataWatcher h; - * private List> i; - */ - packet2.getIntegers().write(0, npc.getId()); - packet2.getUUIDs().write(0, profile.getId()); - packet2.getDoubles().write(0, npc.locX); - packet2.getDoubles().write(1, npc.locY); - packet2.getDoubles().write(2, npc.locZ); - packet2.getBytes().write(0, (byte) (int) (npc.yaw * 256.0F / 360.0F)); - packet2.getBytes().write(1, (byte) (int) (npc.pitch * 256.0F / 360.0F)); - packet2.getDataWatcherModifier().write(0, WrappedDataWatcher.getEntityWatcher(npc.getBukkitEntity())); - - PacketContainer packet3 = pm.createPacket(PacketType.Play.Server.PLAYER_INFO); - packet3.getPlayerInfoAction().write(0, PlayerInfoAction.REMOVE_PLAYER); - packet3.getPlayerInfoDataLists().write(0, datas); - - for (Player player : Bukkit.getOnlinePlayers()) { - try { - pm.sendServerPacket(player, packet); - pm.sendServerPacket(player, packet2); - } catch (InvocationTargetException e) { - e.printStackTrace(); - } - Bukkit.getScheduler().scheduleSyncDelayedTask(Core.getInstance(), new Runnable() { - @Override - public void run() { - try { - pm.sendServerPacket(player, packet3); - } catch (InvocationTargetException e) { - e.printStackTrace(); - } - } - }, 5); - } - } -} diff --git a/src/main/java/cc/zoyn/core/util/ReflectionUtils.java b/src/main/java/cc/zoyn/core/util/ReflectionUtils.java deleted file mode 100644 index 58c9e3e..0000000 --- a/src/main/java/cc/zoyn/core/util/ReflectionUtils.java +++ /dev/null @@ -1,609 +0,0 @@ -package cc.zoyn.core.util; - -import org.bukkit.Bukkit; - -import java.lang.reflect.Constructor; -import java.lang.reflect.Field; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.util.HashMap; -import java.util.Map; - -/** - * ReflectionUtils - *

- * This class provides useful methods which makes dealing with reflection much easier, especially when working with Bukkit - *

- * You are welcome to use it, modify it and redistribute it under the following conditions: - *

    - *
  • Don't claim this class as your own - *
  • Don't remove this disclaimer - *
- *

- * It would be nice if you provide credit to me if you use this class in a published project - * - * @author DarkBlade12 - * @version 1.1 - */ -public final class ReflectionUtils { - // Prevent accidental construction - private ReflectionUtils() { - } - - /** - * Returns the constructor of a given class with the given parameter types - * - * @param clazz Target class - * @param parameterTypes Parameter types of the desired constructor - * @return The constructor of the target class with the specified parameter types - * @throws NoSuchMethodException If the desired constructor with the specified parameter types cannot be found - * @see DataType - * @see DataType#getPrimitive(Class[]) - * @see DataType#compare(Class[], Class[]) - */ - public static Constructor getConstructor(Class clazz, Class... parameterTypes) throws NoSuchMethodException { - Class[] primitiveTypes = DataType.getPrimitive(parameterTypes); - for (Constructor constructor : clazz.getConstructors()) { - if (!DataType.compare(DataType.getPrimitive(constructor.getParameterTypes()), primitiveTypes)) { - continue; - } - return constructor; - } - throw new NoSuchMethodException("There is no such constructor in this class with the specified parameter types"); - } - - /** - * 返回给予的参数的类的构造方法 - *

- * 原文: Returns the constructor of a desired class with the given parameter types - * - * @param className Name of the desired target class - * @param packageType Package where the desired target class is located - * @param parameterTypes Parameter types of the desired constructor - * @return The constructor of the desired target class with the specified parameter types - * @throws NoSuchMethodException If the desired constructor with the specified parameter types cannot be found - * @throws ClassNotFoundException ClassNotFoundException If the desired target class with the specified name and package cannot be found - * @see #getClass(String, PackageType) - * @see #getConstructor(Class, Class...) - */ - public static Constructor getConstructor(String className, PackageType packageType, Class... parameterTypes) throws NoSuchMethodException, ClassNotFoundException { - return getConstructor(packageType.getClass(className), parameterTypes); - } - - /** - * Returns an instance of a class with the given arguments - * - * @param clazz Target class - * @param arguments Arguments which are used to construct an object of the target class - * @return The instance of the target class with the specified arguments - * @throws InstantiationException If you cannot create an instance of the target class due to certain circumstances - * @throws IllegalAccessException If the desired constructor cannot be accessed due to certain circumstances - * @throws IllegalArgumentException If the types of the arguments do not match the parameter types of the constructor (this should not occur since it searches for a constructor with the types of the arguments) - * @throws InvocationTargetException If the desired constructor cannot be invoked - * @throws NoSuchMethodException If the desired constructor with the specified arguments cannot be found - */ - public static Object instantiateObject(Class clazz, Object... arguments) throws InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException { - return getConstructor(clazz, DataType.getPrimitive(arguments)).newInstance(arguments); - } - - /** - * Returns an instance of a desired class with the given arguments - * - * @param className Name of the desired target class - * @param packageType Package where the desired target class is located - * @param arguments Arguments which are used to construct an object of the desired target class - * @return The instance of the desired target class with the specified arguments - * @throws InstantiationException If you cannot create an instance of the desired target class due to certain circumstances - * @throws IllegalAccessException If the desired constructor cannot be accessed due to certain circumstances - * @throws IllegalArgumentException If the types of the arguments do not match the parameter types of the constructor (this should not occur since it searches for a constructor with the types of the arguments) - * @throws InvocationTargetException If the desired constructor cannot be invoked - * @throws NoSuchMethodException If the desired constructor with the specified arguments cannot be found - * @throws ClassNotFoundException If the desired target class with the specified name and package cannot be found - * @see #getClass(String, PackageType) - * @see #instantiateObject(Class, Object...) - */ - public static Object instantiateObject(String className, PackageType packageType, Object... arguments) throws InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, ClassNotFoundException { - return instantiateObject(packageType.getClass(className), arguments); - } - - /** - * Returns a method of a class with the given parameter types - * - * @param clazz Target class - * @param methodName Name of the desired method - * @param parameterTypes Parameter types of the desired method - * @return The method of the target class with the specified name and parameter types - * @throws NoSuchMethodException If the desired method of the target class with the specified name and parameter types cannot be found - * @see DataType#getPrimitive(Class[]) - * @see DataType#compare(Class[], Class[]) - */ - public static Method getMethod(Class clazz, String methodName, Class... parameterTypes) throws NoSuchMethodException { - Class[] primitiveTypes = DataType.getPrimitive(parameterTypes); - for (Method method : clazz.getMethods()) { - if (!method.getName().equals(methodName) || !DataType.compare(DataType.getPrimitive(method.getParameterTypes()), primitiveTypes)) { - continue; - } - return method; - } - throw new NoSuchMethodException("There is no such method in this class with the specified name and parameter types"); - } - - /** - * Returns a method of a desired class with the given parameter types - * - * @param className Name of the desired target class - * @param packageType Package where the desired target class is located - * @param methodName Name of the desired method - * @param parameterTypes Parameter types of the desired method - * @return The method of the desired target class with the specified name and parameter types - * @throws NoSuchMethodException If the desired method of the desired target class with the specified name and parameter types cannot be found - * @throws ClassNotFoundException If the desired target class with the specified name and package cannot be found - * @see #getClass(String, PackageType) - * @see #getMethod(Class, String, Class...) - */ - public static Method getMethod(String className, PackageType packageType, String methodName, Class... parameterTypes) throws NoSuchMethodException, ClassNotFoundException { - return getMethod(packageType.getClass(className), methodName, parameterTypes); - } - - /** - * Invokes a method on an object with the given arguments - * - * @param instance Target object - * @param methodName Name of the desired method - * @param arguments Arguments which are used to invoke the desired method - * @return The result of invoking the desired method on the target object - * @throws IllegalAccessException If the desired method cannot be accessed due to certain circumstances - * @throws IllegalArgumentException If the types of the arguments do not match the parameter types of the method (this should not occur since it searches for a method with the types of the arguments) - * @throws InvocationTargetException If the desired method cannot be invoked on the target object - * @throws NoSuchMethodException If the desired method of the class of the target object with the specified name and arguments cannot be found - * @see #getMethod(Class, String, Class...) - * @see DataType#getPrimitive(Object[]) - */ - public static Object invokeMethod(Object instance, String methodName, Object... arguments) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException { - return getMethod(instance.getClass(), methodName, DataType.getPrimitive(arguments)).invoke(instance, arguments); - } - - /** - * Invokes a method of the target class on an object with the given arguments - * - * @param instance Target object - * @param clazz Target class - * @param methodName Name of the desired method - * @param arguments Arguments which are used to invoke the desired method - * @return The result of invoking the desired method on the target object - * @throws IllegalAccessException If the desired method cannot be accessed due to certain circumstances - * @throws IllegalArgumentException If the types of the arguments do not match the parameter types of the method (this should not occur since it searches for a method with the types of the arguments) - * @throws InvocationTargetException If the desired method cannot be invoked on the target object - * @throws NoSuchMethodException If the desired method of the target class with the specified name and arguments cannot be found - * @see #getMethod(Class, String, Class...) - * @see DataType#getPrimitive(Object[]) - */ - public static Object invokeMethod(Object instance, Class clazz, String methodName, Object... arguments) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException { - return getMethod(clazz, methodName, DataType.getPrimitive(arguments)).invoke(instance, arguments); - } - - /** - * Invokes a method of a desired class on an object with the given arguments - * - * @param instance Target object - * @param className Name of the desired target class - * @param packageType Package where the desired target class is located - * @param methodName Name of the desired method - * @param arguments Arguments which are used to invoke the desired method - * @return The result of invoking the desired method on the target object - * @throws IllegalAccessException If the desired method cannot be accessed due to certain circumstances - * @throws IllegalArgumentException If the types of the arguments do not match the parameter types of the method (this should not occur since it searches for a method with the types of the arguments) - * @throws InvocationTargetException If the desired method cannot be invoked on the target object - * @throws NoSuchMethodException If the desired method of the desired target class with the specified name and arguments cannot be found - * @throws ClassNotFoundException If the desired target class with the specified name and package cannot be found - * @see #getClass(String, PackageType) - * @see #invokeMethod(Object, Class, String, Object...) - */ - public static Object invokeMethod(Object instance, String className, PackageType packageType, String methodName, Object... arguments) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, ClassNotFoundException { - return invokeMethod(instance, packageType.getClass(className), methodName, arguments); - } - - /** - * Returns a field of the target class with the given name - * - * @param clazz Target class - * @param declared Whether the desired field is declared or not - * @param fieldName Name of the desired field - * @return The field of the target class with the specified name - * @throws NoSuchFieldException If the desired field of the given class cannot be found - * @throws SecurityException If the desired field cannot be made accessible - */ - public static Field getField(Class clazz, boolean declared, String fieldName) throws NoSuchFieldException, SecurityException { - Field field = declared ? clazz.getDeclaredField(fieldName) : clazz.getField(fieldName); - field.setAccessible(true); - return field; - } - - /** - * Returns a field of a desired class with the given name - * - * @param className Name of the desired target class - * @param packageType Package where the desired target class is located - * @param declared Whether the desired field is declared or not - * @param fieldName Name of the desired field - * @return The field of the desired target class with the specified name - * @throws NoSuchFieldException If the desired field of the desired class cannot be found - * @throws SecurityException If the desired field cannot be made accessible - * @throws ClassNotFoundException If the desired target class with the specified name and package cannot be found - * @see #getField(Class, boolean, String) - */ - public static Field getField(String className, PackageType packageType, boolean declared, String fieldName) throws NoSuchFieldException, SecurityException, ClassNotFoundException { - return getField(packageType.getClass(className), declared, fieldName); - } - - /** - * Returns the value of a field of the given class of an object - * - * @param instance Target object - * @param clazz Target class - * @param declared Whether the desired field is declared or not - * @param fieldName Name of the desired field - * @return The value of field of the target object - * @throws IllegalArgumentException If the target object does not feature the desired field - * @throws IllegalAccessException If the desired field cannot be accessed - * @throws NoSuchFieldException If the desired field of the target class cannot be found - * @throws SecurityException If the desired field cannot be made accessible - * @see #getField(Class, boolean, String) - */ - public static Object getValue(Object instance, Class clazz, boolean declared, String fieldName) throws IllegalArgumentException, IllegalAccessException, NoSuchFieldException, SecurityException { - return getField(clazz, declared, fieldName).get(instance); - } - - /** - * Returns the value of a field of a desired class of an object - * - * @param instance Target object - * @param className Name of the desired target class - * @param packageType Package where the desired target class is located - * @param declared Whether the desired field is declared or not - * @param fieldName Name of the desired field - * @return The value of field of the target object - * @throws IllegalArgumentException If the target object does not feature the desired field - * @throws IllegalAccessException If the desired field cannot be accessed - * @throws NoSuchFieldException If the desired field of the desired class cannot be found - * @throws SecurityException If the desired field cannot be made accessible - * @throws ClassNotFoundException If the desired target class with the specified name and package cannot be found - * @see #getValue(Object, Class, boolean, String) - */ - public static Object getValue(Object instance, String className, PackageType packageType, boolean declared, String fieldName) throws IllegalArgumentException, IllegalAccessException, NoSuchFieldException, SecurityException, ClassNotFoundException { - return getValue(instance, packageType.getClass(className), declared, fieldName); - } - - /** - * Returns the value of a field with the given name of an object - * - * @param instance Target object - * @param declared Whether the desired field is declared or not - * @param fieldName Name of the desired field - * @return The value of field of the target object - * @throws IllegalArgumentException If the target object does not feature the desired field (should not occur since it searches for a field with the given name in the class of the object) - * @throws IllegalAccessException If the desired field cannot be accessed - * @throws NoSuchFieldException If the desired field of the target object cannot be found - * @throws SecurityException If the desired field cannot be made accessible - * @see #getValue(Object, Class, boolean, String) - */ - public static Object getValue(Object instance, boolean declared, String fieldName) throws IllegalArgumentException, IllegalAccessException, NoSuchFieldException, SecurityException { - return getValue(instance, instance.getClass(), declared, fieldName); - } - - /** - * Sets the value of a field of the given class of an object - * - * @param instance Target object - * @param clazz Target class - * @param declared Whether the desired field is declared or not - * @param fieldName Name of the desired field - * @param value New value - * @throws IllegalArgumentException If the type of the value does not match the type of the desired field - * @throws IllegalAccessException If the desired field cannot be accessed - * @throws NoSuchFieldException If the desired field of the target class cannot be found - * @throws SecurityException If the desired field cannot be made accessible - * @see #getField(Class, boolean, String) - */ - public static void setValue(Object instance, Class clazz, boolean declared, String fieldName, Object value) throws IllegalArgumentException, IllegalAccessException, NoSuchFieldException, SecurityException { - getField(clazz, declared, fieldName).set(instance, value); - } - - /** - * Sets the value of a field of a desired class of an object - * - * @param instance Target object - * @param className Name of the desired target class - * @param packageType Package where the desired target class is located - * @param declared Whether the desired field is declared or not - * @param fieldName Name of the desired field - * @param value New value - * @throws IllegalArgumentException If the type of the value does not match the type of the desired field - * @throws IllegalAccessException If the desired field cannot be accessed - * @throws NoSuchFieldException If the desired field of the desired class cannot be found - * @throws SecurityException If the desired field cannot be made accessible - * @throws ClassNotFoundException If the desired target class with the specified name and package cannot be found - * @see #setValue(Object, Class, boolean, String, Object) - */ - public static void setValue(Object instance, String className, PackageType packageType, boolean declared, String fieldName, Object value) throws IllegalArgumentException, IllegalAccessException, NoSuchFieldException, SecurityException, ClassNotFoundException { - setValue(instance, packageType.getClass(className), declared, fieldName, value); - } - - /** - * Sets the value of a field with the given name of an object - * - * @param instance Target object - * @param declared Whether the desired field is declared or not - * @param fieldName Name of the desired field - * @param value New value - * @throws IllegalArgumentException If the type of the value does not match the type of the desired field - * @throws IllegalAccessException If the desired field cannot be accessed - * @throws NoSuchFieldException If the desired field of the target object cannot be found - * @throws SecurityException If the desired field cannot be made accessible - * @see #setValue(Object, Class, boolean, String, Object) - */ - public static void setValue(Object instance, boolean declared, String fieldName, Object value) throws IllegalArgumentException, IllegalAccessException, NoSuchFieldException, SecurityException { - setValue(instance, instance.getClass(), declared, fieldName, value); - } - - /** - * Represents an enumeration of dynamic packages of NMS and CraftBukkit - *

- * This class is part of the ReflectionUtils and follows the same usage conditions - * - * @author DarkBlade12 - * @since 1.0 - */ - public enum PackageType { - MINECRAFT_SERVER("net.minecraft.server." + getServerVersion()), - CRAFTBUKKIT("org.bukkit.craftbukkit." + getServerVersion()), - CRAFTBUKKIT_BLOCK(CRAFTBUKKIT, "block"), - CRAFTBUKKIT_CHUNKIO(CRAFTBUKKIT, "chunkio"), - CRAFTBUKKIT_COMMAND(CRAFTBUKKIT, "command"), - CRAFTBUKKIT_CONVERSATIONS(CRAFTBUKKIT, "conversations"), - CRAFTBUKKIT_ENCHANTMENS(CRAFTBUKKIT, "enchantments"), - CRAFTBUKKIT_ENTITY(CRAFTBUKKIT, "entity"), - CRAFTBUKKIT_EVENT(CRAFTBUKKIT, "event"), - CRAFTBUKKIT_GENERATOR(CRAFTBUKKIT, "generator"), - CRAFTBUKKIT_HELP(CRAFTBUKKIT, "help"), - CRAFTBUKKIT_INVENTORY(CRAFTBUKKIT, "inventory"), - CRAFTBUKKIT_MAP(CRAFTBUKKIT, "map"), - CRAFTBUKKIT_METADATA(CRAFTBUKKIT, "metadata"), - CRAFTBUKKIT_POTION(CRAFTBUKKIT, "potion"), - CRAFTBUKKIT_PROJECTILES(CRAFTBUKKIT, "projectiles"), - CRAFTBUKKIT_SCHEDULER(CRAFTBUKKIT, "scheduler"), - CRAFTBUKKIT_SCOREBOARD(CRAFTBUKKIT, "scoreboard"), - CRAFTBUKKIT_UPDATER(CRAFTBUKKIT, "updater"), - CRAFTBUKKIT_UTIL(CRAFTBUKKIT, "util"); - - private final String path; - - /** - * Construct a new package type - * - * @param path Path of the package - */ - private PackageType(String path) { - this.path = path; - } - - /** - * Construct a new package type - * - * @param parent Parent package of the package - * @param path Path of the package - */ - private PackageType(PackageType parent, String path) { - this(parent + "." + path); - } - - /** - * Returns the path of this package type - * - * @return The path - */ - public String getPath() { - return path; - } - - /** - * Returns the class with the given name - * - * @param className Name of the desired class - * @return The class with the specified name - * @throws ClassNotFoundException If the desired class with the specified name and package cannot be found - */ - public Class getClass(String className) throws ClassNotFoundException { - return Class.forName(this + "." + className); - } - - // Override for convenience - @Override - public String toString() { - return path; - } - - /** - * Returns the version of your server - * - * @return The server version - */ - public static String getServerVersion() { - return Bukkit.getServer().getClass().getPackage().getName().substring(23); - } - } - - /** - * Represents an enumeration of Java data types with corresponding classes - *

- * This class is part of the ReflectionUtils and follows the same usage conditions - * - * @author DarkBlade12 - * @since 1.0 - */ - public enum DataType { - BYTE(byte.class, Byte.class), - SHORT(short.class, Short.class), - INTEGER(int.class, Integer.class), - LONG(long.class, Long.class), - CHARACTER(char.class, Character.class), - FLOAT(float.class, Float.class), - DOUBLE(double.class, Double.class), - BOOLEAN(boolean.class, Boolean.class); - - private static final Map, DataType> CLASS_MAP = new HashMap, DataType>(); - private final Class primitive; - private final Class reference; - - // Initialize map for quick class lookup - static { - for (DataType type : values()) { - CLASS_MAP.put(type.primitive, type); - CLASS_MAP.put(type.reference, type); - } - } - - /** - * Construct a new data type - * - * @param primitive Primitive class of this data type - * @param reference Reference class of this data type - */ - private DataType(Class primitive, Class reference) { - this.primitive = primitive; - this.reference = reference; - } - - /** - * Returns the primitive class of this data type - * - * @return The primitive class - */ - public Class getPrimitive() { - return primitive; - } - - /** - * Returns the reference class of this data type - * - * @return The reference class - */ - public Class getReference() { - return reference; - } - - /** - * Returns the data type with the given primitive/reference class - * - * @param clazz Primitive/Reference class of the data type - * @return The data type - */ - public static DataType fromClass(Class clazz) { - return CLASS_MAP.get(clazz); - } - - /** - * Returns the primitive class of the data type with the given reference class - * - * @param clazz Reference class of the data type - * @return The primitive class - */ - public static Class getPrimitive(Class clazz) { - DataType type = fromClass(clazz); - return type == null ? clazz : type.getPrimitive(); - } - - /** - * Returns the reference class of the data type with the given primitive class - * - * @param clazz Primitive class of the data type - * @return The reference class - */ - public static Class getReference(Class clazz) { - DataType type = fromClass(clazz); - return type == null ? clazz : type.getReference(); - } - - /** - * Returns the primitive class array of the given class array - * - * @param classes Given class array - * @return The primitive class array - */ - public static Class[] getPrimitive(Class[] classes) { - int length = classes == null ? 0 : classes.length; - Class[] types = new Class[length]; - for (int index = 0; index < length; index++) { - types[index] = getPrimitive(classes[index]); - } - return types; - } - - /** - * Returns the reference class array of the given class array - * - * @param classes Given class array - * @return The reference class array - */ - public static Class[] getReference(Class[] classes) { - int length = classes == null ? 0 : classes.length; - Class[] types = new Class[length]; - for (int index = 0; index < length; index++) { - types[index] = getReference(classes[index]); - } - return types; - } - - /** - * Returns the primitive class array of the given object array - * - * @param object Given object array - * @return The primitive class array - */ - public static Class[] getPrimitive(Object[] objects) { - int length = objects == null ? 0 : objects.length; - Class[] types = new Class[length]; - for (int index = 0; index < length; index++) { - types[index] = getPrimitive(objects[index].getClass()); - } - return types; - } - - /** - * Returns the reference class array of the given object array - * - * @param object Given object array - * @return The reference class array - */ - public static Class[] getReference(Object[] objects) { - int length = objects == null ? 0 : objects.length; - Class[] types = new Class[length]; - for (int index = 0; index < length; index++) { - types[index] = getReference(objects[index].getClass()); - } - return types; - } - - /** - * Compares two class arrays on equivalence - * - * @param primary Primary class array - * @param secondary Class array which is compared to the primary array - * @return Whether these arrays are equal or not - */ - public static boolean compare(Class[] primary, Class[] secondary) { - if (primary == null || secondary == null || primary.length != secondary.length) { - return false; - } - for (int index = 0; index < primary.length; index++) { - Class primaryClass = primary[index]; - Class secondaryClass = secondary[index]; - if (primaryClass.equals(secondaryClass) || primaryClass.isAssignableFrom(secondaryClass)) { - continue; - } - return false; - } - return true; - } - } -} diff --git a/src/main/java/cc/zoyn/core/util/SkinUtils.java b/src/main/java/cc/zoyn/core/util/SkinUtils.java deleted file mode 100644 index 9f1def7..0000000 --- a/src/main/java/cc/zoyn/core/util/SkinUtils.java +++ /dev/null @@ -1,20 +0,0 @@ -package cc.zoyn.core.util; - -import net.minecraft.server.v1_12_R1.EntityPlayer; -import org.bukkit.craftbukkit.v1_12_R1.entity.CraftPlayer; -import org.bukkit.entity.Player; - -public class SkinUtils { - - public static void changeSkin(Player player, String skinName) { - Object nmsPlayer = NMSUtils.getNMSPlayer(player); - try { - Object gameProfile = nmsPlayer.getClass().getMethod("getProfile").invoke(null); - CraftPlayer cp = (CraftPlayer) player; - EntityPlayer ep = cp.getHandle(); - } catch (Exception e) { - e.printStackTrace(); - } - } -} - diff --git a/src/main/java/cc/zoyn/core/util/SubCommand.java b/src/main/java/cc/zoyn/core/util/SubCommand.java deleted file mode 100644 index a549187..0000000 --- a/src/main/java/cc/zoyn/core/util/SubCommand.java +++ /dev/null @@ -1,9 +0,0 @@ -package cc.zoyn.core.util; - -import org.bukkit.command.CommandSender; - -public interface SubCommand { - - boolean execute(CommandSender sender, String[] args); - -} diff --git a/src/main/java/cc/zoyn/core/util/TabUtils.java b/src/main/java/cc/zoyn/core/util/TabUtils.java deleted file mode 100644 index 290dc83..0000000 --- a/src/main/java/cc/zoyn/core/util/TabUtils.java +++ /dev/null @@ -1,43 +0,0 @@ -package cc.zoyn.core.util; - -import cc.zoyn.core.Core; -import com.comphenix.protocol.PacketType; -import com.comphenix.protocol.ProtocolManager; -import com.comphenix.protocol.events.PacketContainer; -import com.comphenix.protocol.wrappers.WrappedChatComponent; -import org.bukkit.ChatColor; -import org.bukkit.entity.Player; - -import java.lang.reflect.InvocationTargetException; - -public class TabUtils { - - /** - * 更改一个玩家的Tab列表 - * - * @param player 玩家 - * @param head Tab顶部 - * @param foot Tab底部 - */ - public static void setTab(Player player, String head, String foot) { - if (head == null) { - head = ""; - } - head = ChatColor.translateAlternateColorCodes('&', head); - if (foot == null) { - foot = ""; - } - foot = ChatColor.translateAlternateColorCodes('&', foot); - ProtocolManager pm = Core.getInstance().getProtocolManager(); - PacketContainer packet = pm.createPacket(PacketType.Play.Server.PLAYER_LIST_HEADER_FOOTER); - packet.getChatComponents() - .write(0, WrappedChatComponent.fromText(head)) - .write(1, WrappedChatComponent.fromText(foot)) - ; - try { - pm.sendServerPacket(player, packet); - } catch (InvocationTargetException e) { - e.printStackTrace(); - } - } -} diff --git a/src/main/java/cc/zoyn/core/util/TimeUtils.java b/src/main/java/cc/zoyn/core/util/TimeUtils.java deleted file mode 100644 index cb4afa9..0000000 --- a/src/main/java/cc/zoyn/core/util/TimeUtils.java +++ /dev/null @@ -1,180 +0,0 @@ -package cc.zoyn.core.util; - -import java.text.ParseException; -import java.text.SimpleDateFormat; -import java.util.Calendar; -import java.util.Date; - -public class TimeUtils { - - private static final int YEAR = 365 * 24 * 60 * 60;// 年 - private static final int MONTH = 30 * 24 * 60 * 60;// 月 - private static final int DAY = 24 * 60 * 60;// 天 - private static final int HOUR = 60 * 60;// 小时 - private static final int MINUTE = 60;// 分钟 - private static Calendar calendar = Calendar.getInstance(); - - - /** - * 根据时间戳获取描述性时间,如3分钟前,1天前 - * - * @param timestamp 时间戳 单位为毫秒 - * @return 时间字符串 - */ - public static String getDescriptionTimeFromTimestamp(long timestamp) { - long currentTime = System.currentTimeMillis(); - long timeGap = (currentTime - timestamp) / 1000;// 与现在时间相差秒数 - String timeStr; - if (timeGap > YEAR) { - timeStr = timeGap / YEAR + "年前"; - } else if (timeGap > MONTH) { - timeStr = timeGap / MONTH + "个月前"; - } else if (timeGap > DAY) {// 1天以上 - timeStr = timeGap / DAY + "天前"; - } else if (timeGap > HOUR) {// 1小时-24小时 - timeStr = timeGap / HOUR + "小时前"; - } else if (timeGap > MINUTE) {// 1分钟-59分钟 - timeStr = timeGap / MINUTE + "分钟前"; - } else {// 1秒钟-59秒钟 - timeStr = "刚刚"; - } - return timeStr; - } - - /** - * Long型时间格式化 - * - * @param time 时间 - * @param dateFormat 日期格式,如yyyy年MM月dd日 HH:mm:ss - * @return 格式化后的日期字符串 - */ - public static String timeToFormatDate(Long time, String dateFormat) { - SimpleDateFormat format = new SimpleDateFormat(dateFormat); - return format.format(time); - } - - /** - * long型时间转中式日期 - * - * @param time 时间 - * @return - */ - public static String timeToDate(Long time) { - SimpleDateFormat format = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss"); - return format.format(time); - } - - /** - * 得到当前的时间,时间格式yyyy-MM-dd - * - * @return - */ - public static String getCurrentDate() { - SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); - return sdf.format(new Date()); - } - - /** - * 得到当前的时间,自定义时间格式 - * y 年 M 月 d 日 H 时 m 分 s 秒 - * - * @param dateFormat 输出显示的时间格式 - * @return - */ - public static String getCurrentDate(String dateFormat) { - SimpleDateFormat sdf = new SimpleDateFormat(dateFormat); - return sdf.format(new Date()); - } - - /** - * 日期格式化,默认日期格式yyyy-MM-dd - * - * @param date - * @return - */ - public static String getFormatDate(Date date) { - SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); - return sdf.format(date); - } - - /** - * 日期格式化,自定义输出日期格式 - * - * @param date - * @return - */ - public static String getFormatDate(Date date, String dateFormat) { - SimpleDateFormat sdf = new SimpleDateFormat(dateFormat); - return sdf.format(date); - } - - /** - * 返回当前日期的前一个时间日期,amount为正数 当前时间后的时间 为负数 当前时间前的时间 - * 默认日期格式yyyy-MM-dd - * - * @param field 日历字段 - * y 年 M 月 d 日 H 时 m 分 s 秒 - * @param amount 数量 - * @return 一个日期 - */ - public static String getPreDate(String field, int amount) { - calendar.setTime(new Date()); - if (field != null && !field.equals("")) { - if (field.equals("y")) { - calendar.add(Calendar.YEAR, amount); - } else if (field.equals("M")) { - calendar.add(Calendar.MONTH, amount); - } else if (field.equals("d")) { - calendar.add(Calendar.DAY_OF_MONTH, amount); - } else if (field.equals("H")) { - calendar.add(Calendar.HOUR, amount); - } - } else { - return null; - } - return getFormatDate(calendar.getTime()); - } - - /** - * 某一个日期的前一个日期 - * - * @param date,某一个日期 - * @param field 日历字段 - * y 年 M 月 d 日 H 时 m 分 s 秒 - * @param amount 数量 - * @return 一个日期 - */ - public static String getPreDate(Date date, String field, int amount) { - calendar.setTime(date); - if (field != null && !field.equals("")) { - if (field.equals("y")) { - calendar.add(Calendar.YEAR, amount); - } else if (field.equals("M")) { - calendar.add(Calendar.MONTH, amount); - } else if (field.equals("d")) { - calendar.add(Calendar.DAY_OF_MONTH, amount); - } else if (field.equals("H")) { - calendar.add(Calendar.HOUR, amount); - } - } else { - return null; - } - return getFormatDate(calendar.getTime()); - } - - /** - * 某一个时间的前一个时间 - * - * @param date - * @return - * @throws ParseException - */ - public static String getPreDate(String date) throws ParseException { - Date d = new SimpleDateFormat().parse(date); - String preD = getPreDate(d, "d", 1); - Date preDate = new SimpleDateFormat().parse(preD); - SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); - return sdf.format(preDate); - } -} - diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml deleted file mode 100644 index 8636d7f..0000000 --- a/src/main/resources/config.yml +++ /dev/null @@ -1,11 +0,0 @@ -Tab: - Head: "&r &6&l&m一&f&l&m一一一一一一&8 [ &6梦江湖 &8] &f&l&m一一一一一一&6&l&m一\n" - Foot: "\n&6游戏版本 &a1.12" -Title: - FadeIn: 5 - Stay: 20 - FadeOut: 5 - Title: "&a梦江湖" - SubTitle: null -BossBar: "&6&o&l90%原创,详情 /Core List" -ChatRadius: 35.0 \ No newline at end of file diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml deleted file mode 100644 index 901c9c5..0000000 --- a/src/main/resources/plugin.yml +++ /dev/null @@ -1,8 +0,0 @@ -name: MayCore -main: Core -version: 1.0 -author: Zoyn -prefix: 核心 -depend: [ProtocolLib] -commands: - core: \ No newline at end of file diff --git a/tellraw/pom.xml b/tellraw/pom.xml new file mode 100644 index 0000000..1888a81 --- /dev/null +++ b/tellraw/pom.xml @@ -0,0 +1,22 @@ + + + + May-Common-Library + cc.zoyn.core + 1.0.0 + + 4.0.0 + tellraw + + + + cc.zoyn.core + common + ${project.parent.version} + provided + + + + \ No newline at end of file diff --git a/tellraw/src/main/java/cc/zoyn/core/tellraw/ItemSerializer.java b/tellraw/src/main/java/cc/zoyn/core/tellraw/ItemSerializer.java new file mode 100644 index 0000000..083dbd0 --- /dev/null +++ b/tellraw/src/main/java/cc/zoyn/core/tellraw/ItemSerializer.java @@ -0,0 +1,63 @@ +package cc.zoyn.core.tellraw; + +import cc.zoyn.core.util.NMSUtils; +import cc.zoyn.core.util.nbt.NBTUtils; +import cc.zoyn.core.util.reflect.ReflectionUtils; +import org.bukkit.inventory.ItemStack; + +import java.lang.reflect.Method; + +public class ItemSerializer { + + private static Method SAVE_NBT; + private static Method MOJANGSON_TO_NBT; + + static { + try { + SAVE_NBT = ReflectionUtils.getMethod(NMSUtils.getNMSClass("ItemStack"), "save", NMSUtils.getNMSClass("NBTTagCompound")); + MOJANGSON_TO_NBT = ReflectionUtils.getMethod(NMSUtils.getNMSClass("MojangsonParser"), "parse", String.class); + } catch (Exception e) { + e.printStackTrace(); + } + } + + /** + * Create the item mojangson data + * + * @param itemStack the item + * @return {@link String} + */ + public static String getItemStackJson(ItemStack itemStack) { + Object nmsItem = NMSUtils.getNMSItem(itemStack); + Object savedTag = null; + try { + savedTag = ReflectionUtils.invokeMethod(SAVE_NBT, nmsItem, NBTUtils.newNBTTagCompound()); + } catch (Exception e) { + e.printStackTrace(); + } + if (savedTag != null) { + return savedTag.toString(); + } else { + return "null"; + } + } + + /** + * Load a item by using mojangson data + * + * @param mojangson the mojangson data + * @return {@link ItemStack} + */ + public static ItemStack loadItemStackJson(String mojangson) { + ItemStack itemStack = null; + try { + Object nbtTag = ReflectionUtils.invokeMethod(MOJANGSON_TO_NBT, null, mojangson); + Object nmsItem = NBTUtils.newNMSItemStack(nbtTag); + itemStack = (ItemStack) NMSUtils.getBukkitItem(nmsItem); + } catch (Exception e) { + e.printStackTrace(); + } + return itemStack; + } + +} diff --git a/tellraw/src/main/java/cc/zoyn/core/tellraw/JsonImpl.java b/tellraw/src/main/java/cc/zoyn/core/tellraw/JsonImpl.java new file mode 100644 index 0000000..a068db5 --- /dev/null +++ b/tellraw/src/main/java/cc/zoyn/core/tellraw/JsonImpl.java @@ -0,0 +1,80 @@ +package cc.zoyn.core.tellraw; + +import cc.zoyn.core.util.JsonBuilderUtils; + +public class JsonImpl { + + private final static String TEXT_FORMAT = "\"text\":\"%s\""; + private final static String CLICK_FORMAT = "\"clickEvent\":{\"action\":\"%s\",\"value\":\"%s\"}"; + private final static String HOVER_FORMAT = "\"hoverEvent\":{\"action\":\"%s\",\"value\":\"%s\"}"; + private final static String INSERT_FORMAT = " \"insertion\":\"%s\""; + /** + * 消息文本 + */ + public String text; + /** + * 点击操作 + */ + public String clickActionName; + /** + * 点击数据 + */ + public String clickActionData; + /** + * 悬浮操作 + */ + public String hoverActionName; + /** + * 悬浮数据 + */ + public String hoverActionData; + /** + * 插入数据 + */ + public String insertionData; + + @Override + public String toString() { + return "JsonImpl [text=" + text + ", clickActionName=" + clickActionName + ", clickActionData=" + + clickActionData + ", hoverActionName=" + hoverActionName + ", hoverActionData=" + hoverActionData + + ", insertionData=" + insertionData + "]"; + } + + public JsonImpl() { + this(""); + } + + public JsonImpl(String text) { + this.text = text; + } + + /** + * @return 是否有文本 + */ + public boolean hasText() { + return text != null && !text.isEmpty(); + } + + /** + * 写入Json + * + * @param str 流对象 + */ + public void writeJson(StringBuilder str) { + str.append("{"); + str.append(String.format(TEXT_FORMAT, new JsonBuilderUtils(text))); + if (clickActionName != null) { + str.append(","); + str.append(String.format(CLICK_FORMAT, clickActionName, new JsonBuilderUtils(clickActionData))); + } + if (hoverActionName != null) { + str.append(","); + str.append(String.format(HOVER_FORMAT, hoverActionName, new JsonBuilderUtils(hoverActionData))); + } + if (insertionData != null) { + str.append(","); + str.append(String.format(INSERT_FORMAT, new JsonBuilderUtils(insertionData))); + } + str.append("}"); + } +} diff --git a/src/main/java/cc/zoyn/core/dto/Tellraw.java b/tellraw/src/main/java/cc/zoyn/core/tellraw/Tellraw.java similarity index 64% rename from src/main/java/cc/zoyn/core/dto/Tellraw.java rename to tellraw/src/main/java/cc/zoyn/core/tellraw/Tellraw.java index c976d3c..b170075 100644 --- a/src/main/java/cc/zoyn/core/dto/Tellraw.java +++ b/tellraw/src/main/java/cc/zoyn/core/tellraw/Tellraw.java @@ -1,11 +1,13 @@ -package cc.zoyn.core.dto; +package cc.zoyn.core.tellraw; import com.google.common.collect.Lists; -import cc.zoyn.core.minecraft.JsonImpl; +import com.google.common.collect.Maps; +import org.bukkit.Bukkit; import org.bukkit.configuration.serialization.ConfigurationSerializable; +import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; import java.util.Arrays; -import java.util.HashMap; import java.util.List; import java.util.Map; @@ -35,6 +37,65 @@ public Tellraw(Map map) { this.jsonParts = (List) map.get("jsonParts"); } + /** + * 当玩家光标悬停在tellraw上时,它将向玩家显示成就或统计数据 + *

+ * When the player cursor hover the tellraw, it will show a achievement or statistic to player + *

+ * The key can be found at here + * https://minecraft.gamepedia.com/Achievements#List_of_achievements + * https://minecraft.gamepedia.com/Statistics#List_of_general_statistics + *

+ * + * @param value the id of achievement or statistic + * @return {@link Tellraw} + */ + public Tellraw showAchievement(String value) { + onHover("show_achievement", value); + return this; + } + + /** + * 当玩家光标悬停在tellraw上时,它将向玩家显示实体信息 + *

+ * When the player cursor hover the tellraw, it will show a entity information to player + * + * @param name the name + * @param entityType the entity type + * @param id the id + * @return {@link Tellraw} + */ + public Tellraw showEntity(String name, String entityType, String id) { + onHover("show_entity", "{\"id\":\"" + id + "\", \"name\":\"" + name + "\", \"type\":\"" + entityType + "\"}"); + return this; + } + + /** + * 当玩家光标悬停在tellraw上时,它会向玩家显示一个物品 + *

+ * When the player cursor hover the tellraw, it will show a item to player + * + * @param itemStack the item + * @return {@link Tellraw} + */ + public Tellraw showItem(ItemStack itemStack) { + onHover("show_item", ItemSerializer.getItemStackJson(itemStack)); + return this; + } + + /** + * 当玩家点击tellraw时,它会打开一个url并提示玩家 + *

+ * When the player click the tellraw, it will open a url and tips player + * + * @param url the url + * @return {@link Tellraw} + */ + public Tellraw openUrl(String url) { + onClick("open_url", url); + return this; + } + /** * 补全命令[点击后将会自动出现在聊天栏] * @@ -158,15 +219,9 @@ public Tellraw addHover(String... texts) { * @return {@link Tellraw} */ public Tellraw addAnotherTellraw(String text) { - return addAnotherTellraw(new JsonImpl(String.format(text))); + return addAnotherTellraw(new JsonImpl(text)); } - /** - * 结束上一串消息 开始下一串数据[使用一个JsonImpl的实例] - * - * @param part 下一段内容 - * @return {@link Tellraw} - */ private Tellraw addAnotherTellraw(JsonImpl part) { JsonImpl last = latest(); if (!last.hasText()) { @@ -177,6 +232,15 @@ private Tellraw addAnotherTellraw(JsonImpl part) { return this; } + /** + * 给指定玩家发送Tellraw + * + * @param player 给定的玩家 + */ + public void send(Player player) { + Bukkit.dispatchCommand(Bukkit.getConsoleSender(), "tellraw " + player.getName() + " " + toJsonString()); + } + /** * 转换成Json串 * @@ -195,7 +259,7 @@ public String toJsonString() { @Override public Map serialize() { - Map map = new HashMap(); + Map map = Maps.newHashMap(); map.put("jsonParts", this.jsonParts); return map; } diff --git a/tellraw/src/main/java/cc/zoyn/core/tellraw/package-info.java b/tellraw/src/main/java/cc/zoyn/core/tellraw/package-info.java new file mode 100644 index 0000000..5ea5f2b --- /dev/null +++ b/tellraw/src/main/java/cc/zoyn/core/tellraw/package-info.java @@ -0,0 +1,7 @@ +/** + * Wrapper tellraw operation + * + * @author Zoyn + * @since 2017-12-09 + */ +package cc.zoyn.core.tellraw; \ No newline at end of file