Add 序列化注解 @TSerializeCollection、@TSerializeMap、@TSerializeCustom
This commit is contained in:
		@@ -8,6 +8,8 @@ import java.lang.annotation.Target;
 | 
				
			|||||||
/**
 | 
					/**
 | 
				
			||||||
 * @Author sky
 | 
					 * @Author sky
 | 
				
			||||||
 * @Since 2018-10-05 12:11
 | 
					 * @Since 2018-10-05 12:11
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * 用于标注不需要进行序列化的内容
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
@Target(ElementType.FIELD)
 | 
					@Target(ElementType.FIELD)
 | 
				
			||||||
@Retention(RetentionPolicy.RUNTIME)
 | 
					@Retention(RetentionPolicy.RUNTIME)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -0,0 +1,18 @@
 | 
				
			|||||||
 | 
					package me.skymc.taboolib.common.serialize;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import java.lang.annotation.ElementType;
 | 
				
			||||||
 | 
					import java.lang.annotation.Retention;
 | 
				
			||||||
 | 
					import java.lang.annotation.RetentionPolicy;
 | 
				
			||||||
 | 
					import java.lang.annotation.Target;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @Author sky
 | 
				
			||||||
 | 
					 * @Since 2018-10-05 12:11
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * 用于标识 Collection 类型的字段
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					@Target(ElementType.FIELD)
 | 
				
			||||||
 | 
					@Retention(RetentionPolicy.RUNTIME)
 | 
				
			||||||
 | 
					public @interface TSerializeCollection {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -0,0 +1,18 @@
 | 
				
			|||||||
 | 
					package me.skymc.taboolib.common.serialize;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import java.lang.annotation.ElementType;
 | 
				
			||||||
 | 
					import java.lang.annotation.Retention;
 | 
				
			||||||
 | 
					import java.lang.annotation.RetentionPolicy;
 | 
				
			||||||
 | 
					import java.lang.annotation.Target;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @Author sky
 | 
				
			||||||
 | 
					 * @Since 2018-10-05 12:11
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * 用于标识 TSerializable 类型的字段
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					@Target(ElementType.FIELD)
 | 
				
			||||||
 | 
					@Retention(RetentionPolicy.RUNTIME)
 | 
				
			||||||
 | 
					public @interface TSerializeCustom {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -1,20 +1,18 @@
 | 
				
			|||||||
package me.skymc.taboolib.common.serialize.container;
 | 
					package me.skymc.taboolib.common.serialize;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import java.lang.annotation.ElementType;
 | 
					import java.lang.annotation.ElementType;
 | 
				
			||||||
import java.lang.annotation.Retention;
 | 
					import java.lang.annotation.Retention;
 | 
				
			||||||
import java.lang.annotation.RetentionPolicy;
 | 
					import java.lang.annotation.RetentionPolicy;
 | 
				
			||||||
import java.lang.annotation.Target;
 | 
					import java.lang.annotation.Target;
 | 
				
			||||||
import java.util.HashMap;
 | 
					 | 
				
			||||||
import java.util.Map;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * @Author sky
 | 
					 * @Author sky
 | 
				
			||||||
 * @Since 2018-10-05 12:11
 | 
					 * @Since 2018-10-05 12:11
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * 用于标识 Map 类型的字段
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
@Target(ElementType.FIELD)
 | 
					@Target(ElementType.FIELD)
 | 
				
			||||||
@Retention(RetentionPolicy.RUNTIME)
 | 
					@Retention(RetentionPolicy.RUNTIME)
 | 
				
			||||||
public @interface TSerializeMap {
 | 
					public @interface TSerializeMap {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    Class<? extends Map> type() default HashMap.class;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -1,7 +1,9 @@
 | 
				
			|||||||
package me.skymc.taboolib.common.serialize;
 | 
					package me.skymc.taboolib.common.serialize;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import ch.njol.skript.classes.ConfigurationSerializer;
 | 
					import ch.njol.skript.classes.ConfigurationSerializer;
 | 
				
			||||||
 | 
					import com.google.common.collect.Maps;
 | 
				
			||||||
import com.google.gson.*;
 | 
					import com.google.gson.*;
 | 
				
			||||||
 | 
					import me.skymc.taboolib.common.util.SimpleReflection;
 | 
				
			||||||
import org.bukkit.configuration.InvalidConfigurationException;
 | 
					import org.bukkit.configuration.InvalidConfigurationException;
 | 
				
			||||||
import org.bukkit.configuration.file.YamlConfiguration;
 | 
					import org.bukkit.configuration.file.YamlConfiguration;
 | 
				
			||||||
import org.bukkit.configuration.serialization.ConfigurationSerializable;
 | 
					import org.bukkit.configuration.serialization.ConfigurationSerializable;
 | 
				
			||||||
@@ -19,27 +21,65 @@ import java.util.Optional;
 | 
				
			|||||||
 */
 | 
					 */
 | 
				
			||||||
public class TSerializer {
 | 
					public class TSerializer {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private static Map<String, TSerializerElement> generated = Maps.newHashMap();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public static <T extends ConfigurationSerializable> T read(String value, Class<T> type) {
 | 
					    public static <T extends ConfigurationSerializable> T read(String value, Class<T> type) {
 | 
				
			||||||
        return ConfigurationSerializer.deserializeCS(value, type);
 | 
					        return ConfigurationSerializer.deserializeCS(value, type);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public static TSerializable read(TSerializable serializable, String serializedString) {
 | 
					    public static TSerializable read(TSerializable serializable, String serializedString) {
 | 
				
			||||||
 | 
					        SimpleReflection.checkAndSave(serializable.getClass());
 | 
				
			||||||
        try {
 | 
					        try {
 | 
				
			||||||
            JsonObject jsonObject = (JsonObject) new JsonParser().parse(serializedString);
 | 
					            JsonObject jsonObject = (JsonObject) new JsonParser().parse(serializedString);
 | 
				
			||||||
            if (jsonObject.has("serializeObject")) {
 | 
					            if (jsonObject.has("serializeObject")) {
 | 
				
			||||||
                JsonObject serializeObject = jsonObject.getAsJsonObject("serializeObject");
 | 
					                JsonObject serializeObject = jsonObject.getAsJsonObject("serializeObject");
 | 
				
			||||||
                for (Map.Entry<String, JsonElement> jsonElementEntry : serializeObject.entrySet()) {
 | 
					                for (Map.Entry<String, JsonElement> jsonElementEntry : serializeObject.entrySet()) {
 | 
				
			||||||
                    try {
 | 
					                    try {
 | 
				
			||||||
                        Field declaredField = serializable.getClass().getDeclaredField(jsonElementEntry.getKey());
 | 
					                        Field declaredField = SimpleReflection.getField(serializable.getClass(), jsonElementEntry.getKey());
 | 
				
			||||||
                        declaredField.setAccessible(true);
 | 
					 | 
				
			||||||
                        if (declaredField.isAnnotationPresent(DoNotSerialize.class)) {
 | 
					                        if (declaredField.isAnnotationPresent(DoNotSerialize.class)) {
 | 
				
			||||||
                            continue;
 | 
					                            continue;
 | 
				
			||||||
                        }
 | 
					                        }
 | 
				
			||||||
                        Optional<TSerializerElementGeneral> serializer = Arrays.stream(TSerializerElementGeneral.values()).filter(serializerElements -> serializerElements.getSerializer().matches(declaredField.getType())).findFirst();
 | 
					                        // Serializable
 | 
				
			||||||
                        if (serializer.isPresent()) {
 | 
					                        if (declaredField.isAnnotationPresent(TSerializeCustom.class) && TSerializable.class.isAssignableFrom(declaredField.getType())) {
 | 
				
			||||||
                            declaredField.set(serializable, serializer.get().getSerializer().read(jsonElementEntry.getValue().getAsString()));
 | 
					                            declaredField.set(serializable, generateElement((Class<? extends TSerializable>) declaredField.getType()).read(jsonElementEntry.getValue().getAsString()));
 | 
				
			||||||
                        } else {
 | 
					                        }
 | 
				
			||||||
                            serializable.read(jsonElementEntry.getKey(), jsonElementEntry.getValue().getAsString());
 | 
					                        // List
 | 
				
			||||||
 | 
					                        else if (declaredField.isAnnotationPresent(TSerializeCollection.class) && Collection.class.isAssignableFrom(declaredField.getType())) {
 | 
				
			||||||
 | 
					                            Class listType = SimpleReflection.getListType(declaredField);
 | 
				
			||||||
 | 
					                            if (listType == null) {
 | 
				
			||||||
 | 
					                                serializable.read(jsonElementEntry.getKey(), jsonElementEntry.getValue().getAsString());
 | 
				
			||||||
 | 
					                                continue;
 | 
				
			||||||
 | 
					                            }
 | 
				
			||||||
 | 
					                            TSerializerElementGeneral serializer = Arrays.stream(TSerializerElementGeneral.values()).filter(serializerElements -> serializerElements.getSerializer().matches(listType)).findFirst().orElse(null);
 | 
				
			||||||
 | 
					                            if (serializer == null) {
 | 
				
			||||||
 | 
					                                serializable.read(jsonElementEntry.getKey(), jsonElementEntry.getValue().getAsString());
 | 
				
			||||||
 | 
					                            } else {
 | 
				
			||||||
 | 
					                                readCollection((Collection) declaredField.get(serializable), jsonElementEntry.getValue().getAsString(), checkCustom(listType, serializer));
 | 
				
			||||||
 | 
					                            }
 | 
				
			||||||
 | 
					                        }
 | 
				
			||||||
 | 
					                        // Map
 | 
				
			||||||
 | 
					                        else if (declaredField.isAnnotationPresent(TSerializeMap.class) && Map.class.isAssignableFrom(declaredField.getType())) {
 | 
				
			||||||
 | 
					                            Class[] mapType = SimpleReflection.getMapType(declaredField);
 | 
				
			||||||
 | 
					                            if (mapType == null) {
 | 
				
			||||||
 | 
					                                serializable.read(jsonElementEntry.getKey(), jsonElementEntry.getValue().getAsString());
 | 
				
			||||||
 | 
					                                continue;
 | 
				
			||||||
 | 
					                            }
 | 
				
			||||||
 | 
					                            TSerializerElementGeneral serializerK = Arrays.stream(TSerializerElementGeneral.values()).filter(serializerElements -> serializerElements.getSerializer().matches(mapType[0])).findFirst().orElse(null);
 | 
				
			||||||
 | 
					                            TSerializerElementGeneral serializerV = Arrays.stream(TSerializerElementGeneral.values()).filter(serializerElements -> serializerElements.getSerializer().matches(mapType[1])).findFirst().orElse(null);
 | 
				
			||||||
 | 
					                            if (serializerK == null || serializerV == null) {
 | 
				
			||||||
 | 
					                                serializable.read(jsonElementEntry.getKey(), jsonElementEntry.getValue().getAsString());
 | 
				
			||||||
 | 
					                            } else {
 | 
				
			||||||
 | 
					                                readMap((Map) declaredField.get(serializable), jsonElementEntry.getValue().getAsString(), checkCustom(mapType[0], serializerK), checkCustom(mapType[1], serializerV));
 | 
				
			||||||
 | 
					                            }
 | 
				
			||||||
 | 
					                        }
 | 
				
			||||||
 | 
					                        // 未声明类型
 | 
				
			||||||
 | 
					                        else {
 | 
				
			||||||
 | 
					                            TSerializerElementGeneral serializer = Arrays.stream(TSerializerElementGeneral.values()).filter(serializerElements -> serializerElements.getSerializer().matches(declaredField.getType())).findFirst().orElse(null);
 | 
				
			||||||
 | 
					                            if (serializer == null) {
 | 
				
			||||||
 | 
					                                serializable.read(jsonElementEntry.getKey(), jsonElementEntry.getValue().getAsString());
 | 
				
			||||||
 | 
					                            } else {
 | 
				
			||||||
 | 
					                                declaredField.set(serializable, serializer.getSerializer().read(jsonElementEntry.getValue().getAsString()));
 | 
				
			||||||
 | 
					                            }
 | 
				
			||||||
                        }
 | 
					                        }
 | 
				
			||||||
                    } catch (Throwable t) {
 | 
					                    } catch (Throwable t) {
 | 
				
			||||||
                        t.printStackTrace();
 | 
					                        t.printStackTrace();
 | 
				
			||||||
@@ -57,21 +97,57 @@ public class TSerializer {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public static String write(TSerializable serializable) {
 | 
					    public static String write(TSerializable serializable) {
 | 
				
			||||||
 | 
					        SimpleReflection.checkAndSave(serializable.getClass());
 | 
				
			||||||
        JsonObject jsonObject = new JsonObject();
 | 
					        JsonObject jsonObject = new JsonObject();
 | 
				
			||||||
        JsonObject serializeObject = new JsonObject();
 | 
					        JsonObject serializeObject = new JsonObject();
 | 
				
			||||||
        for (Field declaredField : serializable.getClass().getDeclaredFields()) {
 | 
					        for (Field declaredField : SimpleReflection.getFields(serializable.getClass()).values()) {
 | 
				
			||||||
            try {
 | 
					            try {
 | 
				
			||||||
                if (!declaredField.isAnnotationPresent(DoNotSerialize.class) && !Modifier.isStatic(declaredField.getModifiers())) {
 | 
					                if (!declaredField.isAnnotationPresent(DoNotSerialize.class) && !Modifier.isStatic(declaredField.getModifiers())) {
 | 
				
			||||||
                    declaredField.setAccessible(true);
 | 
					                    Object fieldObject = declaredField.get(serializable);
 | 
				
			||||||
                    Object o = declaredField.get(serializable);
 | 
					                    if (fieldObject == null) {
 | 
				
			||||||
                    if (o == null) {
 | 
					 | 
				
			||||||
                        continue;
 | 
					                        continue;
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                    Optional<TSerializerElementGeneral> serializer = Arrays.stream(TSerializerElementGeneral.values()).filter(serializerElements -> serializerElements.getSerializer().matches(declaredField.getType())).findFirst();
 | 
					                    // Serializable
 | 
				
			||||||
                    if (serializer.isPresent()) {
 | 
					                    if (declaredField.isAnnotationPresent(TSerializeCustom.class) && TSerializable.class.isAssignableFrom(declaredField.getType())) {
 | 
				
			||||||
                        serializeObject.addProperty(declaredField.getName(), serializer.get().getSerializer().write(o));
 | 
					                        serializeObject.addProperty(declaredField.getName(), generateElement((Class<? extends TSerializable>) declaredField.getType()).write(fieldObject));
 | 
				
			||||||
                    } else {
 | 
					                    }
 | 
				
			||||||
                        Optional.ofNullable(serializable.write(declaredField.getName(), o)).ifPresent(value -> serializeObject.addProperty(declaredField.getName(), value));
 | 
					                    // List
 | 
				
			||||||
 | 
					                    else if (declaredField.isAnnotationPresent(TSerializeCollection.class) && Collection.class.isAssignableFrom(declaredField.getType())) {
 | 
				
			||||||
 | 
					                        Class listType = SimpleReflection.getListType(declaredField);
 | 
				
			||||||
 | 
					                        if (listType == null) {
 | 
				
			||||||
 | 
					                            Optional.ofNullable(serializable.write(declaredField.getName(), fieldObject)).ifPresent(value -> serializeObject.addProperty(declaredField.getName(), value));
 | 
				
			||||||
 | 
					                            continue;
 | 
				
			||||||
 | 
					                        }
 | 
				
			||||||
 | 
					                        TSerializerElementGeneral serializer = Arrays.stream(TSerializerElementGeneral.values()).filter(serializerElements -> serializerElements.getSerializer().matches(listType)).findFirst().orElse(null);
 | 
				
			||||||
 | 
					                        if (serializer == null) {
 | 
				
			||||||
 | 
					                            Optional.ofNullable(serializable.write(declaredField.getName(), fieldObject)).ifPresent(value -> serializeObject.addProperty(declaredField.getName(), value));
 | 
				
			||||||
 | 
					                        } else {
 | 
				
			||||||
 | 
					                            serializeObject.addProperty(declaredField.getName(), writeCollection((Collection) fieldObject, checkCustom(listType, serializer)));
 | 
				
			||||||
 | 
					                        }
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                    // Map
 | 
				
			||||||
 | 
					                    else if (declaredField.isAnnotationPresent(TSerializeMap.class) && Map.class.isAssignableFrom(declaredField.getType())) {
 | 
				
			||||||
 | 
					                        Class[] mapType = SimpleReflection.getMapType(declaredField);
 | 
				
			||||||
 | 
					                        if (mapType == null) {
 | 
				
			||||||
 | 
					                            Optional.ofNullable(serializable.write(declaredField.getName(), fieldObject)).ifPresent(value -> serializeObject.addProperty(declaredField.getName(), value));
 | 
				
			||||||
 | 
					                            continue;
 | 
				
			||||||
 | 
					                        }
 | 
				
			||||||
 | 
					                        TSerializerElementGeneral serializerK = Arrays.stream(TSerializerElementGeneral.values()).filter(serializerElements -> serializerElements.getSerializer().matches(mapType[0])).findFirst().orElse(null);
 | 
				
			||||||
 | 
					                        TSerializerElementGeneral serializerV = Arrays.stream(TSerializerElementGeneral.values()).filter(serializerElements -> serializerElements.getSerializer().matches(mapType[1])).findFirst().orElse(null);
 | 
				
			||||||
 | 
					                        if (serializerK == null || serializerV == null) {
 | 
				
			||||||
 | 
					                            Optional.ofNullable(serializable.write(declaredField.getName(), fieldObject)).ifPresent(value -> serializeObject.addProperty(declaredField.getName(), value));
 | 
				
			||||||
 | 
					                        } else {
 | 
				
			||||||
 | 
					                            serializeObject.addProperty(declaredField.getName(), writeMap((Map) fieldObject, checkCustom(mapType[0], serializerK), checkCustom(mapType[1], serializerV)));
 | 
				
			||||||
 | 
					                        }
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                    // 未声明类型
 | 
				
			||||||
 | 
					                    else {
 | 
				
			||||||
 | 
					                        TSerializerElementGeneral serializer = Arrays.stream(TSerializerElementGeneral.values()).filter(serializerElements -> serializerElements.getSerializer().matches(declaredField.getType())).findFirst().orElse(null);
 | 
				
			||||||
 | 
					                        if (serializer == null) {
 | 
				
			||||||
 | 
					                            Optional.ofNullable(serializable.write(declaredField.getName(), fieldObject)).ifPresent(value -> serializeObject.addProperty(declaredField.getName(), value));
 | 
				
			||||||
 | 
					                        } else {
 | 
				
			||||||
 | 
					                            serializeObject.addProperty(declaredField.getName(), serializer.getSerializer().write(fieldObject));
 | 
				
			||||||
 | 
					                        }
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            } catch (Throwable t) {
 | 
					            } catch (Throwable t) {
 | 
				
			||||||
@@ -168,4 +244,33 @@ public class TSerializer {
 | 
				
			|||||||
        Object o = y.get("value");
 | 
					        Object o = y.get("value");
 | 
				
			||||||
        return !c.isInstance(o) ? null : (T) o;
 | 
					        return !c.isInstance(o) ? null : (T) o;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public static TSerializerElement generateElement(Class<? extends TSerializable> serializable) {
 | 
				
			||||||
 | 
					        return generated.computeIfAbsent(serializable.getName(), n -> new TSerializerElement() {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            @Override
 | 
				
			||||||
 | 
					            public Object read(String value) {
 | 
				
			||||||
 | 
					                try {
 | 
				
			||||||
 | 
					                    return serializable.newInstance().read(value);
 | 
				
			||||||
 | 
					                } catch (Throwable t) {
 | 
				
			||||||
 | 
					                    t.printStackTrace();
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                return null;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            @Override
 | 
				
			||||||
 | 
					            public String write(Object value) {
 | 
				
			||||||
 | 
					                return ((TSerializable) value).write();
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            @Override
 | 
				
			||||||
 | 
					            public boolean matches(Class objectClass) {
 | 
				
			||||||
 | 
					                return true;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private static TSerializerElement checkCustom(Class type, TSerializerElementGeneral serializer) {
 | 
				
			||||||
 | 
					        return serializer == TSerializerElementGeneral.CUSTOM ? generateElement(type) : serializer.getSerializer();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -11,5 +11,4 @@ public interface TSerializerElement<T> {
 | 
				
			|||||||
    String write(T value);
 | 
					    String write(T value);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    boolean matches(Class objectClass);
 | 
					    boolean matches(Class objectClass);
 | 
				
			||||||
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -182,7 +182,7 @@ public enum TSerializerElementGeneral {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        @Override
 | 
					        @Override
 | 
				
			||||||
        public boolean matches(Class objectClass) {
 | 
					        public boolean matches(Class objectClass) {
 | 
				
			||||||
            return ItemStack.class.equals(objectClass);
 | 
					            return ItemStack.class.isAssignableFrom(objectClass);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }),
 | 
					    }),
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -200,7 +200,25 @@ public enum TSerializerElementGeneral {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        @Override
 | 
					        @Override
 | 
				
			||||||
        public boolean matches(Class objectClass) {
 | 
					        public boolean matches(Class objectClass) {
 | 
				
			||||||
            return Location.class.equals(objectClass);
 | 
					            return Location.class.isAssignableFrom(objectClass);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }),
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    CUSTOM(new TSerializerElement() {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        @Override
 | 
				
			||||||
 | 
					        public Object read(String value) {
 | 
				
			||||||
 | 
					            return null;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        @Override
 | 
				
			||||||
 | 
					        public String write(Object value) {
 | 
				
			||||||
 | 
					            return null;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        @Override
 | 
				
			||||||
 | 
					        public boolean matches(Class objectClass) {
 | 
				
			||||||
 | 
					            return TSerializable.class.isAssignableFrom(objectClass);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -2,8 +2,9 @@ package me.skymc.taboolib.common.serialize;
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
import com.google.common.collect.ImmutableMap;
 | 
					import com.google.common.collect.ImmutableMap;
 | 
				
			||||||
import com.google.common.collect.Lists;
 | 
					import com.google.common.collect.Lists;
 | 
				
			||||||
 | 
					import com.google.common.collect.Maps;
 | 
				
			||||||
 | 
					import me.skymc.taboolib.string.ArrayUtils;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import java.util.Collection;
 | 
					 | 
				
			||||||
import java.util.List;
 | 
					import java.util.List;
 | 
				
			||||||
import java.util.Map;
 | 
					import java.util.Map;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -15,17 +16,19 @@ public class TSerializerExample {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    public static void main(String[] args) {
 | 
					    public static void main(String[] args) {
 | 
				
			||||||
        // 创建对象
 | 
					        // 创建对象
 | 
				
			||||||
        SimpleData date = new SimpleData();
 | 
					        SimpleData data = new SimpleData();
 | 
				
			||||||
        // 修改参数
 | 
					        // 修改参数
 | 
				
			||||||
        date.number = 100;
 | 
					        data.number = 9999;
 | 
				
			||||||
 | 
					        data.list.addAll(ArrayUtils.asList(111D, 222D));
 | 
				
			||||||
 | 
					        data.map.putAll(ImmutableMap.of("a", "b", "c", "d"));
 | 
				
			||||||
        // 序列化
 | 
					        // 序列化
 | 
				
			||||||
        String value = date.writeBase64();
 | 
					        String value = data.write();
 | 
				
			||||||
        // 打印
 | 
					        // 打印
 | 
				
			||||||
        System.out.println(value);
 | 
					        System.out.println(value);
 | 
				
			||||||
        // 创建新的对象
 | 
					        // 创建新的对象
 | 
				
			||||||
        SimpleData dataCopy = new SimpleData();
 | 
					        SimpleData dataCopy = new SimpleData();
 | 
				
			||||||
        // 反序列化
 | 
					        // 反序列化
 | 
				
			||||||
        dataCopy.readBase64(value);
 | 
					        dataCopy.read(value);
 | 
				
			||||||
        // 打印
 | 
					        // 打印
 | 
				
			||||||
        System.out.println(dataCopy);
 | 
					        System.out.println(dataCopy);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@@ -44,14 +47,13 @@ public class TSerializerExample {
 | 
				
			|||||||
        private int number = 100;
 | 
					        private int number = 100;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        /**
 | 
					        /**
 | 
				
			||||||
         * 特殊类型需要进行手动序列化
 | 
					         * 包含基本类型的容器需要通过标注来完成序列化
 | 
				
			||||||
         * 标注 @TSerializeCollection 或 @TSerializeMap 来进行自动序列化(未完成)
 | 
					 | 
				
			||||||
         */
 | 
					         */
 | 
				
			||||||
//        @TSerializeCollection
 | 
					        @TSerializeCollection
 | 
				
			||||||
        private List<Double> list = Lists.newArrayList(1.0, 2.0, 3.0);
 | 
					        private List<Double> list = Lists.newArrayList();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
//        @TSerializeMap
 | 
					        @TSerializeMap
 | 
				
			||||||
        private Map<String, String> map = ImmutableMap.of("abc", "def");
 | 
					        private Map<String, String> map = Maps.newHashMap();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        /**
 | 
					        /**
 | 
				
			||||||
         * 跳过序列化
 | 
					         * 跳过序列化
 | 
				
			||||||
@@ -59,32 +61,13 @@ public class TSerializerExample {
 | 
				
			|||||||
        @DoNotSerialize
 | 
					        @DoNotSerialize
 | 
				
			||||||
        private String ignoreSerialize = "aaa";
 | 
					        private String ignoreSerialize = "aaa";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        /**
 | 
					 | 
				
			||||||
         * 基本类型不会执行以下两个方法
 | 
					 | 
				
			||||||
         * 由 TSerializer 自动进行序列化和反序列化步骤
 | 
					 | 
				
			||||||
         */
 | 
					 | 
				
			||||||
        @Override
 | 
					 | 
				
			||||||
        public void read(String fieldName, String value) {
 | 
					 | 
				
			||||||
            if (fieldName.equals("list")) {
 | 
					 | 
				
			||||||
                // List 类型可以直接通过 TSerializer 提供的预设方法进行反序列化
 | 
					 | 
				
			||||||
                TSerializer.readCollection(list, value, TSerializerElementGeneral.DOUBLE);
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        @Override
 | 
					 | 
				
			||||||
        public String write(String fieldName, Object value) {
 | 
					 | 
				
			||||||
            if (fieldName.equals("list")) {
 | 
					 | 
				
			||||||
                return TSerializer.writeCollection((Collection) value, TSerializerElementGeneral.DOUBLE);
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            return null;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        @Override
 | 
					        @Override
 | 
				
			||||||
        public String toString() {
 | 
					        public String toString() {
 | 
				
			||||||
            return "SimpleData{" +
 | 
					            return "SimpleData{" +
 | 
				
			||||||
                    "text='" + text + '\'' +
 | 
					                    "text='" + text + '\'' +
 | 
				
			||||||
                    ", number=" + number +
 | 
					                    ", number=" + number +
 | 
				
			||||||
                    ", list=" + list +
 | 
					                    ", list=" + list +
 | 
				
			||||||
 | 
					                    ", map=" + map +
 | 
				
			||||||
                    ", ignoreSerialize='" + ignoreSerialize + '\'' +
 | 
					                    ", ignoreSerialize='" + ignoreSerialize + '\'' +
 | 
				
			||||||
                    '}';
 | 
					                    '}';
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,24 +0,0 @@
 | 
				
			|||||||
package me.skymc.taboolib.common.serialize.container;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import me.skymc.taboolib.common.serialize.TSerializerElement;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import java.lang.annotation.ElementType;
 | 
					 | 
				
			||||||
import java.lang.annotation.Retention;
 | 
					 | 
				
			||||||
import java.lang.annotation.RetentionPolicy;
 | 
					 | 
				
			||||||
import java.lang.annotation.Target;
 | 
					 | 
				
			||||||
import java.util.ArrayList;
 | 
					 | 
				
			||||||
import java.util.Collection;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * @Author sky
 | 
					 | 
				
			||||||
 * @Since 2018-10-05 12:11
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
@Target(ElementType.FIELD)
 | 
					 | 
				
			||||||
@Retention(RetentionPolicy.RUNTIME)
 | 
					 | 
				
			||||||
public @interface TSerializeCollection {
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    Class<? extends Collection> type() default ArrayList.class;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    Class<? extends TSerializerElement> element() default TSerializerElement.class;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@@ -3,6 +3,8 @@ package me.skymc.taboolib.common.util;
 | 
				
			|||||||
import com.google.common.collect.Maps;
 | 
					import com.google.common.collect.Maps;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import java.lang.reflect.Field;
 | 
					import java.lang.reflect.Field;
 | 
				
			||||||
 | 
					import java.lang.reflect.ParameterizedType;
 | 
				
			||||||
 | 
					import java.lang.reflect.Type;
 | 
				
			||||||
import java.util.Arrays;
 | 
					import java.util.Arrays;
 | 
				
			||||||
import java.util.Map;
 | 
					import java.util.Map;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -14,6 +16,24 @@ public class SimpleReflection {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    private static Map<String, Map<String, Field>> fieldCached = Maps.newHashMap();
 | 
					    private static Map<String, Map<String, Field>> fieldCached = Maps.newHashMap();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public static boolean isExists(Class<?> nmsClass) {
 | 
				
			||||||
 | 
					        return fieldCached.containsKey(nmsClass.getName());
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public static Map<String, Field> getFields(Class<?> nmsClass) {
 | 
				
			||||||
 | 
					        return fieldCached.getOrDefault(nmsClass.getName(), Maps.newHashMap());
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public static Field getField(Class<?> nmsClass, String fieldName) {
 | 
				
			||||||
 | 
					        return fieldCached.getOrDefault(nmsClass.getName(), Maps.newHashMap()).get(fieldName);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public static void checkAndSave(Class<?> nmsClass) {
 | 
				
			||||||
 | 
					        if (!isExists(nmsClass)) {
 | 
				
			||||||
 | 
					            saveField(nmsClass);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public static void saveField(Class<?> nmsClass) {
 | 
					    public static void saveField(Class<?> nmsClass) {
 | 
				
			||||||
        try {
 | 
					        try {
 | 
				
			||||||
            Arrays.stream(nmsClass.getDeclaredFields()).forEach(declaredField -> saveField(nmsClass, declaredField.getName()));
 | 
					            Arrays.stream(nmsClass.getDeclaredFields()).forEach(declaredField -> saveField(nmsClass, declaredField.getName()));
 | 
				
			||||||
@@ -82,4 +102,32 @@ public class SimpleReflection {
 | 
				
			|||||||
        return def;
 | 
					        return def;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public static Class getListType(Field field)  {
 | 
				
			||||||
 | 
					        Type genericType = field.getGenericType();
 | 
				
			||||||
 | 
					        try {
 | 
				
			||||||
 | 
					            if (ParameterizedType.class.isAssignableFrom(genericType.getClass())) {
 | 
				
			||||||
 | 
					                for (Type actualTypeArgument : ((ParameterizedType) genericType).getActualTypeArguments()) {
 | 
				
			||||||
 | 
					                    return Class.forName(actualTypeArgument.getTypeName());
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        } catch (Throwable t) {
 | 
				
			||||||
 | 
					            t.printStackTrace();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        return null;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public static Class[] getMapType(Field field)  {
 | 
				
			||||||
 | 
					        Class[] mapType = new Class[2];
 | 
				
			||||||
 | 
					        try {
 | 
				
			||||||
 | 
					            Type genericType = field.getGenericType();
 | 
				
			||||||
 | 
					            if (ParameterizedType.class.isAssignableFrom(genericType.getClass())) {
 | 
				
			||||||
 | 
					                for (Type actualTypeArgument : ((ParameterizedType) genericType).getActualTypeArguments()) {
 | 
				
			||||||
 | 
					                    mapType[mapType[0] == null ? 0 : 1] = Class.forName(actualTypeArgument.getTypeName());
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        } catch (Throwable t) {
 | 
				
			||||||
 | 
					            t.printStackTrace();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        return mapType[1] == null ? null : mapType ;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -14,10 +14,12 @@ public class ClickEvent {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    private ClickType clickType;
 | 
					    private ClickType clickType;
 | 
				
			||||||
    private Event event;
 | 
					    private Event event;
 | 
				
			||||||
 | 
					    private char slot;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public ClickEvent(ClickType clickType, Event event) {
 | 
					    public ClickEvent(ClickType clickType, Event event, char slot) {
 | 
				
			||||||
        this.clickType = clickType;
 | 
					        this.clickType = clickType;
 | 
				
			||||||
        this.event = event;
 | 
					        this.event = event;
 | 
				
			||||||
 | 
					        this.slot = slot;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public InventoryClickEvent castClick() {
 | 
					    public InventoryClickEvent castClick() {
 | 
				
			||||||
@@ -28,6 +30,10 @@ public class ClickEvent {
 | 
				
			|||||||
        return (InventoryDragEvent) event;
 | 
					        return (InventoryDragEvent) event;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public char getSlot() {
 | 
				
			||||||
 | 
					        return slot;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public ClickType getClickType() {
 | 
					    public ClickType getClickType() {
 | 
				
			||||||
        return clickType;
 | 
					        return clickType;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -32,14 +32,14 @@ class ClickListener implements Listener {
 | 
				
			|||||||
            if (((MenuHolder) e.getInventory().getHolder()).getBuilder().isLockHand() && (e.getRawSlot() - e.getInventory().getSize() - 27 == e.getWhoClicked().getInventory().getHeldItemSlot() || (e.getClick() == org.bukkit.event.inventory.ClickType.NUMBER_KEY && e.getHotbarButton() == e.getWhoClicked().getInventory().getHeldItemSlot()))) {
 | 
					            if (((MenuHolder) e.getInventory().getHolder()).getBuilder().isLockHand() && (e.getRawSlot() - e.getInventory().getSize() - 27 == e.getWhoClicked().getInventory().getHeldItemSlot() || (e.getClick() == org.bukkit.event.inventory.ClickType.NUMBER_KEY && e.getHotbarButton() == e.getWhoClicked().getInventory().getHeldItemSlot()))) {
 | 
				
			||||||
                e.setCancelled(true);
 | 
					                e.setCancelled(true);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            Optional.ofNullable(((MenuHolder) e.getInventory().getHolder()).getBuilder().getClickTask()).ifPresent(t -> t.run(new ClickEvent(ClickType.CLICK, e)));
 | 
					            Optional.ofNullable(((MenuHolder) e.getInventory().getHolder()).getBuilder().getClickTask()).ifPresent(t -> t.run(new ClickEvent(ClickType.CLICK, e, ((MenuHolder) e.getInventory().getHolder()).getBuilder().getSlot(e.getRawSlot()))));
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @EventHandler
 | 
					    @EventHandler
 | 
				
			||||||
    public void onDrag(InventoryDragEvent e) {
 | 
					    public void onDrag(InventoryDragEvent e) {
 | 
				
			||||||
        if (e.getInventory().getHolder() instanceof MenuHolder) {
 | 
					        if (e.getInventory().getHolder() instanceof MenuHolder) {
 | 
				
			||||||
            Optional.ofNullable(((MenuHolder) e.getInventory().getHolder()).getBuilder().getClickTask()).ifPresent(t -> t.run(new ClickEvent(ClickType.DRAG, e)));
 | 
					            Optional.ofNullable(((MenuHolder) e.getInventory().getHolder()).getBuilder().getClickTask()).ifPresent(t -> t.run(new ClickEvent(ClickType.DRAG, e, ' ')));
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -86,6 +86,18 @@ public class MenuBuilder {
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
        return inventory;
 | 
					        return inventory;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    public char getSlot(int slot) {
 | 
				
			||||||
 | 
					        for (int i = 0; i < items.length && i < rows; i++) {
 | 
				
			||||||
 | 
					            char[] line = items[i];
 | 
				
			||||||
 | 
					            for (int j = 0; j < line.length && j < 9; j++) {
 | 
				
			||||||
 | 
					                if (i * 9 + j == slot) {
 | 
				
			||||||
 | 
					                    return line[j];
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        return ' ';
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // *********************************
 | 
					    // *********************************
 | 
				
			||||||
    //
 | 
					    //
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user