diff --git a/README.md b/README.md
index 1716748f..28fdccd7 100644
--- a/README.md
+++ b/README.md
@@ -1,7 +1,7 @@
-# MoonLake [![GitHub version](https://d25lcipzij17d.cloudfront.net/badge.svg?id=gh&type=6&v=1.8-r3&x2=0)](https://github.com/u2g/MoonLake) [![Open Source Love](https://badges.frapsoft.com/os/v1/open-source.svg?v=102)](https://github.com/u2g/MoonLake) [![Open Source Love](https://badges.frapsoft.com/os/gpl/gpl.svg?v=102)](https://github.com/u2g/MoonLake)
+# MoonLake [![GitHub version](https://d25lcipzij17d.cloudfront.net/badge.svg?id=gh&type=6&v=1.8-a4&x2=0)](https://github.com/u2g/MoonLake) [![Open Source Love](https://badges.frapsoft.com/os/v1/open-source.svg?v=102)](https://github.com/u2g/MoonLake) [![Open Source Love](https://badges.frapsoft.com/os/gpl/gpl.svg?v=102)](https://github.com/u2g/MoonLake)
Minecraft MoonLake Core API Plugin
-By Month_Light Ver: 1.8-r3
+By Month_Light Ver: 1.8-a4
## 简介
这个插件提供了大量的 API 功能,实现了一些 Bukkit 无法做到的 NMS 功能
diff --git a/config.yml b/config.yml
index 5b99c8a6..f785cf5b 100644
--- a/config.yml
+++ b/config.yml
@@ -1,14 +1,14 @@
################################
# MoonLake Core API Plugin #
-# By Month_Light Ver: 1.8-r3 #
+# By Month_Light Ver: 1.8-a4 #
################################
# 插件版本号: 此项请勿修改!
-version: '1.8-r3'
+version: '1.8-a4'
# 数据包通道监听器
# 此项可设置是否开启这个功能
# 如果关闭则插件中的一些API功能将无法使用
# 例如: MoonLakePlayerJoinEvent
# PS: 此项是实时监听客户端与服务端的数据包交流
-PacketChannelListener: true
+PacketChannelListener: false
diff --git a/plugin.yml b/plugin.yml
index efb3bbed..90aedba1 100644
--- a/plugin.yml
+++ b/plugin.yml
@@ -1,9 +1,9 @@
name: MoonLake
main: com.minecraft.moonlake.MoonLakePlugin
-version: 1.8-r3
+version: 1.8-a4
prefix: MoonLake
description: Minecraft MoonLake Core API Plugin
website: http://www.mcyszh.com/
author: Month_Light
authors: [Month_Light, MoonLake]
-softdepend: [MoonLakeEconomy, PermissionsEx, Vault]
\ No newline at end of file
+softdepend: [MoonLakeEconomy, PermissionsEx, Vault]
diff --git a/src/com/minecraft/moonlake/MoonLakePlugin.java b/src/com/minecraft/moonlake/MoonLakePlugin.java
index 03e29b78..bd93f508 100644
--- a/src/com/minecraft/moonlake/MoonLakePlugin.java
+++ b/src/com/minecraft/moonlake/MoonLakePlugin.java
@@ -33,7 +33,7 @@
*
*
*
Minecraft MoonLake Core API Plugin
- *
By Month_Light Ver: 1.8-r3
+ *
By Month_Light Ver: 1.8-a4
*
Website: MoonLake Website
*
QQ Group: 377607025 -> Jump
*
@@ -42,7 +42,7 @@
*
* - Bukkit [1.8.x - 1.11.x] ✔ 不完全支持
* - Spigot [1.8.x - 1.11.x] ✔ 完完全全支持
- * - PaperSpigot [1.8.x - 1.11.x]
✔ 完完全全支持
+ * - PaperSpigot [1.8.x - 1.11.x] ✔ 完完全全支持
* - Cauldron | KCauldron [模组服务端] ✘ 完全不支持
*
*
@@ -68,7 +68,7 @@
* 修改操作请您遵守 GPLv3 协议,您必须公开修改过的所有代码!
*
*
- * @version 1.8-r3
+ * @version 1.8-a4
* @author Month_Light
*/
public class MoonLakePlugin extends JavaPlugin implements MoonLake {
diff --git a/src/com/minecraft/moonlake/api/annotation/plugin/CommandAnnotationExpression.java b/src/com/minecraft/moonlake/api/annotation/plugin/CommandAnnotationExpression.java
index 4cccd04f..503fd1ad 100644
--- a/src/com/minecraft/moonlake/api/annotation/plugin/CommandAnnotationExpression.java
+++ b/src/com/minecraft/moonlake/api/annotation/plugin/CommandAnnotationExpression.java
@@ -26,6 +26,7 @@
import java.lang.reflect.Method;
import java.util.HashSet;
import java.util.Set;
+import java.util.logging.Level;
/**
* CommandAnnotationExpression
@@ -49,12 +50,23 @@ public void load(Plugin plugin, Object obj) throws MoonLakeException {
registerCommand(plugin, obj);
}
+ @Override
+ public void load(Plugin plugin, MoonLakeCommand obj) throws MoonLakeException {
+
+ registerCommand(plugin, obj);
+ }
+
@Override
public Set registerCommand(Plugin plugin, Object obj) throws MoonLakeException {
Validate.notNull(plugin, "The plugin object is null.");
Validate.notNull(obj, "The obj object is null.");
+ if(!(obj instanceof MoonLakeCommand)) {
+ // warn new version need implements MoonLakeCommand
+ plugin.getLogger().log(Level.WARNING, "[MoonLake] 警告: 新版本核心插件命令类需要实现 MoonLakeCommand 接口. (请注意更新!)");
+ }
+
Class> clazz = obj.getClass();
Set commands = new HashSet<>();
Set commandCompletionMethods = new HashSet<>();
@@ -98,4 +110,10 @@ public Set registerCommand(Plugin plugin, Object obj) throws M
}
return commands;
}
+
+ @Override
+ public Set registerCommand(Plugin plugin, MoonLakeCommand obj) throws MoonLakeException {
+
+ return registerCommand(plugin, (Object) obj);
+ }
}
diff --git a/src/com/minecraft/moonlake/api/annotation/plugin/command/CommandAnnotation.java b/src/com/minecraft/moonlake/api/annotation/plugin/command/CommandAnnotation.java
index 28b69ef7..b06f6e6d 100644
--- a/src/com/minecraft/moonlake/api/annotation/plugin/command/CommandAnnotation.java
+++ b/src/com/minecraft/moonlake/api/annotation/plugin/command/CommandAnnotation.java
@@ -34,6 +34,32 @@
*/
public interface CommandAnnotation extends PluginAnnotation {
+ /**
+ * 将指定插件的指定对象加载数据
+ *
+ * @param plugin 插件
+ * @param obj 对象
+ * @throws IllegalArgumentException 如果插件对象为 {@code null} 则抛出异常
+ * @throws IllegalArgumentException 如果指定加载对象为 {@code null} 则抛出异常
+ * @throws MoonLakeException 如果加载错误则抛出异常
+ * @see #load(Plugin, MoonLakeCommand)
+ */
+ @Override
+ @Deprecated
+ void load(Plugin plugin, Object obj) throws MoonLakeException;
+
+ /**
+ * 将指定插件的指定对象加载数据
+ *
+ * @param plugin 插件
+ * @param obj 对象命令
+ * @throws IllegalArgumentException 如果插件对象为 {@code null} 则抛出异常
+ * @throws IllegalArgumentException 如果指定加载对象为 {@code null} 则抛出异常
+ * @throws MoonLakeException 如果加载错误则抛出异常
+ * @see #registerCommand(Plugin, MoonLakeCommand)
+ */
+ void load(Plugin plugin, MoonLakeCommand obj) throws MoonLakeException;
+
/**
* 将指定插件的指定对象注册命令
*
@@ -43,6 +69,21 @@ public interface CommandAnnotation extends PluginAnnotation {
* @throws IllegalArgumentException 如果插件对象为 {@code null} 则抛出异常
* @throws IllegalArgumentException 如果指定加载对象为 {@code null} 则抛出异常
* @throws MoonLakeException 如果注册错误则抛出异常
+ * @deprecated @deprecated 已过时, 将于 v2.0 删除. 请使用 {@link #registerCommand(Plugin, MoonLakeCommand)}
+ * @see #registerCommand(Plugin, MoonLakeCommand)
*/
+ @Deprecated
Set registerCommand(Plugin plugin, Object obj) throws MoonLakeException;
+
+ /**
+ * 将指定插件的指定对象注册命令
+ *
+ * @param plugin 插件
+ * @param obj 对象命令
+ * @return 命令
+ * @throws IllegalArgumentException 如果插件对象为 {@code null} 则抛出异常
+ * @throws IllegalArgumentException 如果指定加载对象为 {@code null} 则抛出异常
+ * @throws MoonLakeException 如果注册错误则抛出异常
+ */
+ Set registerCommand(Plugin plugin, MoonLakeCommand obj) throws MoonLakeException;
}
diff --git a/src/com/minecraft/moonlake/api/annotation/plugin/command/MoonLakeCommand.java b/src/com/minecraft/moonlake/api/annotation/plugin/command/MoonLakeCommand.java
new file mode 100644
index 00000000..694d8ded
--- /dev/null
+++ b/src/com/minecraft/moonlake/api/annotation/plugin/command/MoonLakeCommand.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2016 The MoonLake Authors
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+
+package com.minecraft.moonlake.api.annotation.plugin.command;
+
+/**
+ * MoonLakeCommand
+ * 月色之湖命令接口类(详细doc待补充...)
+ *
+ * @version 1.0
+ * @author Month_Light
+ * @see CommandAnnotated
+ */
+public interface MoonLakeCommand {
+}
diff --git a/src/com/minecraft/moonlake/manager/ItemManager.java b/src/com/minecraft/moonlake/manager/ItemManager.java
index afaf44ea..0eafe03d 100644
--- a/src/com/minecraft/moonlake/manager/ItemManager.java
+++ b/src/com/minecraft/moonlake/manager/ItemManager.java
@@ -18,22 +18,30 @@
package com.minecraft.moonlake.manager;
+import com.minecraft.moonlake.MoonLakeAPI;
+import com.minecraft.moonlake.api.item.AttributeModify;
+import com.minecraft.moonlake.api.item.ItemBuilder;
import com.minecraft.moonlake.api.nbt.NBTCompound;
import com.minecraft.moonlake.api.nbt.NBTFactory;
+import com.minecraft.moonlake.data.Conversions;
import com.minecraft.moonlake.data.NBTTagData;
import com.minecraft.moonlake.data.NBTTagDataWrapped;
import com.minecraft.moonlake.exception.MoonLakeException;
+import com.minecraft.moonlake.util.StringUtil;
import com.minecraft.moonlake.validate.Validate;
import org.bukkit.Material;
+import org.bukkit.configuration.ConfigurationSection;
+import org.bukkit.configuration.file.YamlConfiguration;
+import org.bukkit.enchantments.Enchantment;
+import org.bukkit.inventory.ItemFlag;
import org.bukkit.inventory.ItemStack;
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.InputStream;
-import java.io.OutputStream;
+import java.io.*;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.util.Base64;
+import java.util.List;
+import java.util.Set;
import static com.minecraft.moonlake.reflect.Reflect.*;
@@ -454,4 +462,233 @@ public static ItemStack deserialize(String data) {
}
return null;
}
+
+ /** Serialize ItemStack To File */
+ public static File serializeToFile(ItemBuilder builder) {
+
+ Validate.notNull(builder, "The item builder object is null.");
+
+ return serializeToFile(builder.build(true));
+ }
+
+ public static File serializeToFile(ItemStack itemStack) {
+
+ throw new UnsupportedOperationException();
+ }
+ /** Serialize ItemStack To File */
+
+ /**
+ * 将特定 YAML 文件数据反序列化为物品栈对象
+ *
+ * @param path 文件路径
+ * @return 物品栈对象 异常返回 null
+ * @throws IllegalArgumentException 如果路径对象为 {@code null} 则抛出异常
+ * @throws IllegalArgumentException 如果文件对象为 {@code null} 则抛出异常
+ * @throws IllegalArgumentException 如果文件对象不存在或不是文件则抛出异常
+ * @throws IllegalArgumentException 如果文件对象后缀类型名不为 {@code yml} 则抛出异常
+ * @throws MoonLakeException 如果反序列化错误则抛出异常
+ */
+ public static ItemStack deserializeFromFile(String path) {
+
+ Validate.notNull(path, "The file path object is null.");
+
+ return deserializeFromFile(new File(path));
+ }
+
+ /**
+ * 将特定 YAML 文件数据反序列化为物品栈对象
+ *
+ * By Month_Light Ver: 1.0
+ *
+ * @param file 文件
+ * @return 物品栈对象 异常返回 null
+ * @throws IllegalArgumentException 如果文件对象为 {@code null} 则抛出异常
+ * @throws IllegalArgumentException 如果文件对象不存在或不是文件则抛出异常
+ * @throws IllegalArgumentException 如果文件对象后缀类型名不为 {@code yml} 则抛出异常
+ * @throws MoonLakeException 如果反序列化错误则抛出异常
+ */
+ public static ItemStack deserializeFromFile(File file) {
+
+ Validate.notNull(file, "The file object is null.");
+ Validate.isTrue(file.exists() && file.isFile(), "The file not exists or not file.");
+ Validate.isTrue(file.getName().endsWith(".yml"), "The file not is yml suffix.");
+
+ YamlConfiguration yml = YamlConfiguration.loadConfiguration(file);
+ ItemBuilder itemBuilder = null;
+
+ if(!yml.isSet("Type"))
+ throw new MoonLakeException("The yml file not exists 'Type' attribute.");
+
+ String type = yml.getString("Type");
+ Material material = Material.matchMaterial(type);
+
+ if(material == null)
+ throw new MoonLakeException("The yml file 'Type' attribute is unknown material: " + type);
+
+ if(material == Material.AIR)
+ return new ItemStack(Material.AIR);
+
+ // base
+ int data = yml.isSet("Data") ? yml.getInt("Data", 0) : 0;
+ int amount = yml.isSet("Amount") ? yml.getInt("Amount", 1) : 1;
+
+ // init
+ itemBuilder = MoonLakeAPI.newItemBuilder(material, data, amount);
+
+ // displayName
+ String displayName = yml.isSet("DisplayName") ? yml.getString("DisplayName", null) : null;
+
+ if(displayName != null)
+ itemBuilder.setDisplayName(displayName);
+
+ // lore
+ List lore = yml.isSet("Lore") ? yml.getStringList("Lore") : null;
+
+ if(lore != null)
+ itemBuilder.setLore(StringUtil.toColor(lore));
+
+ // enchantment
+ if(yml.isSet("Enchantment")) {
+
+ ConfigurationSection section = yml.getConfigurationSection("Enchantment");
+ Set keys = section != null ? section.getKeys(false) : null;
+
+ if(keys != null && !keys.isEmpty()) {
+
+ for(final String key : keys) {
+
+ Enchantment enchantment = null;
+ int level = yml.getInt("Enchantment." + key);
+
+ if(key.matches("([0-9])+"))
+ enchantment = Enchantment.getById(Conversions.toInt(key));
+ else
+ enchantment = Enchantment.getByName(key.toUpperCase());
+
+ if(enchantment == null)
+ MoonLakeAPI.getMLogger().error("The deserialize from file '" + file.getName() + "' key 'Enchantment' error enchantment: " + key);
+ else
+ itemBuilder.addEnchantment(enchantment, level);
+ }
+ }
+ }
+
+ // hide flag
+ if(yml.isSet("HideFlag")) {
+
+ List list = yml.getStringList("HideFlag");
+
+ if(list != null && !list.isEmpty()) {
+
+ for(final String hideFlag : list) {
+
+ ItemFlag itemFlag = null;
+
+ try {
+
+ itemFlag = ItemFlag.valueOf(hideFlag.toUpperCase());
+ }
+ catch (Exception e) {
+ }
+
+ if(itemFlag == null)
+ MoonLakeAPI.getMLogger().error("The deserialize from file '" + file.getName() + "' key 'HideFlag' error flag: " + hideFlag);
+ else
+ itemBuilder.addFlags(itemFlag);
+ }
+ }
+ }
+
+ // unbreakable
+ if(yml.isSet("Unbreakable")) {
+
+ boolean result = yml.getBoolean("Unbreakable", false);
+
+ if(result)
+ itemBuilder.setUnbreakable(true);
+ }
+
+ // attribute modifiers
+ if(yml.isSet("AttributeModifiers")) {
+
+ ConfigurationSection section = yml.getConfigurationSection("AttributeModifiers");
+ Set keys = section != null ? section.getKeys(false) : null;
+
+ if(keys != null && !keys.isEmpty()) {
+
+ for(final String key : keys) {
+
+ AttributeModify.Type attType = AttributeModify.Type.fromType(key);
+
+ if(attType == null) {
+
+ MoonLakeAPI.getMLogger().error("The deserialize from file '" + file.getName() + "' key 'AttributeModifiers' error type: " + key);
+ continue;
+ }
+ double value = yml.getDouble("AttributeModifiers." + key + ".Value", -1d);
+ boolean percent = yml.getBoolean("AttributeModifiers." + key + ".Percent", false);
+ String slot = yml.getString("AttributeModifiers." + key + ".Slot", null);
+ AttributeModify.Slot slotObj = slot != null ? AttributeModify.Slot.fromType(slot) : AttributeModify.Slot.MAIN_HAND;
+ // add
+ itemBuilder.setAttribute(new AttributeModify(
+ attType,
+ slotObj,
+ percent ? AttributeModify.Operation.ADD_PERCENTAGE : AttributeModify.Operation.ADD_NUMBER,
+ value
+ ));
+ }
+ }
+ }
+
+ // nbt modifiers
+ ItemStack result = itemBuilder.build(true);
+ NBTCompound tag = MoonLakeAPI.getNBTLibrary().read(result);
+
+ // skull owner
+ if(yml.isSet("SkullOwner")) {
+
+ if(material == Material.SKULL_ITEM) {
+
+ String target = yml.getString("SkullOwner", null);
+
+ if(target != null && !target.isEmpty())
+ tag.put("SkullOwner", target);
+ }
+ }
+
+ // age
+ if(yml.isSet("Age")) {
+
+ int age = yml.getInt("Age", 6000);
+
+ if(age != 6000)
+ tag.put("Age", age);
+ }
+
+ // pickup delay
+ if(yml.isSet("PickupDelay")) {
+
+ int pickupDelay = yml.getInt("PickupDelay", -1);
+
+ if(pickupDelay != -1)
+ tag.put("PickupDelay", pickupDelay);
+ }
+
+ // generation
+ /*if(yml.isSet("Generation")) {
+
+ if(material == Material.WRITTEN_BOOK) {
+
+ int value = yml.getInt("Generation", -1);
+
+ if(value != -1)
+ tag.put("generation", value);
+ }
+ }*/
+
+ // write nbt
+ MoonLakeAPI.getNBTLibrary().write(result, tag);
+
+ return result;
+ }
}
diff --git a/src/com/minecraft/moonlake/nms/packet/PacketPlayOutRespawn.java b/src/com/minecraft/moonlake/nms/packet/PacketPlayOutRespawn.java
index cbdeadea..1f6ca047 100644
--- a/src/com/minecraft/moonlake/nms/packet/PacketPlayOutRespawn.java
+++ b/src/com/minecraft/moonlake/nms/packet/PacketPlayOutRespawn.java
@@ -57,10 +57,12 @@ public class PacketPlayOutRespawn extends PacketAbstract {
try {
+ String enumGamemode = getServerVersion().equals("v1_8_R1") || getServerVersionNumber() >= 10 ? "EnumGamemode" : "WorldSettings$EnumGamemode";
+
CLASS_PACKETPLAYOUTRESPAWN = PackageType.MINECRAFT_SERVER.getClass("PacketPlayOutRespawn");
CLASS_WORLDTYPE = PackageType.MINECRAFT_SERVER.getClass("WorldType");
CLASS_ENUMDIFFICULTY = PackageType.MINECRAFT_SERVER.getClass("EnumDifficulty");
- CLASS_ENUMGAMEMODE = PackageType.MINECRAFT_SERVER.getClass("EnumGamemode");
+ CLASS_ENUMGAMEMODE = PackageType.MINECRAFT_SERVER.getClass(enumGamemode);
CLASS_WORLD = PackageType.MINECRAFT_SERVER.getClass("World");
CLASS_WORLDPROVIDER = PackageType.MINECRAFT_SERVER.getClass("WorldProvider");
CLASS_ENTITY = PackageType.MINECRAFT_SERVER.getClass("Entity");