9
0
mirror of https://gitlab.com/SamB440/rpgregions-2.git synced 2025-12-27 10:49:08 +00:00

Correctly serialise ItemStacks using base64

This commit is contained in:
SamB440
2022-01-14 19:58:07 +00:00
parent 7aeeb2fab6
commit 6cc07824c2
7 changed files with 1134 additions and 3 deletions

View File

@@ -0,0 +1,118 @@
/*
* This file is part of helper, licensed under the MIT License.
*
* Copyright (c) lucko (Luck) <luck@lucko.me>
* Copyright (c) contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package me.lucko.helper.gson;
import com.google.gson.JsonElement;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
/**
* An object which can be serialized to JSON.
*
* <p>Classes which implement this interface should also implement a static "deserialize" method,
* accepting {@link JsonElement} as the only parameter.</p>
*/
public interface GsonSerializable {
/**
* Deserializes a JsonElement to a GsonSerializable object.
*
* @param clazz the GsonSerializable class
* @param element the json element to deserialize
* @param <T> the GsonSerializable type
* @return the deserialized object
* @throws IllegalStateException if the clazz does not have a deserialization method
*/
@Nonnull
static <T extends GsonSerializable> T deserialize(@Nonnull Class<T> clazz, @Nonnull JsonElement element) {
Method deserializeMethod = getDeserializeMethod(clazz);
if (deserializeMethod == null) {
throw new IllegalStateException("Class does not have a deserialize method accessible.");
}
try {
//noinspection unchecked
return (T) deserializeMethod.invoke(null, element);
} catch (IllegalAccessException | InvocationTargetException e) {
throw new RuntimeException(e);
}
}
/**
* Deserializes a JsonElement to a GsonSerializable object.
*
* @param clazz the GsonSerializable class
* @param element the json element to deserialize
* @return the deserialized object
* @throws IllegalStateException if the clazz does not have a deserialization method
*/
@Nonnull
static GsonSerializable deserializeRaw(@Nonnull Class<?> clazz, @Nonnull JsonElement element) {
Class<? extends GsonSerializable> typeCastedClass = clazz.asSubclass(GsonSerializable.class);
return deserialize(typeCastedClass, element);
}
/**
* Gets the deserialization method for a given class.
*
* @param clazz the class
* @return the deserialization method, if the class has one
*/
@Nullable
static Method getDeserializeMethod(@Nonnull Class<?> clazz) {
if (!GsonSerializable.class.isAssignableFrom(clazz)) {
return null;
}
Method deserializeMethod;
try {
//noinspection JavaReflectionMemberAccess
deserializeMethod = clazz.getDeclaredMethod("deserialize", JsonElement.class);
deserializeMethod.setAccessible(true);
} catch (Exception e) {
return null;
}
if (!Modifier.isStatic(deserializeMethod.getModifiers())) {
return null;
}
return deserializeMethod;
}
/**
* Serializes the object to JSON
*
* @return a json form of this object
*/
@Nonnull
JsonElement serialize();
}

View File

@@ -0,0 +1,739 @@
/*
* This file is part of helper, licensed under the MIT License.
*
* Copyright (c) lucko (Luck) <luck@lucko.me>
* Copyright (c) contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package me.lucko.helper.gson;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonNull;
import com.google.gson.JsonObject;
import com.google.gson.JsonPrimitive;
import javax.annotation.Nullable;
import java.util.Map;
import java.util.Objects;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.stream.Collector;
import java.util.stream.Stream;
/**
* Builder utilities for creating GSON Objects/Arrays.
*/
public final class JsonBuilder {
/**
* Creates a new object builder
*
* <p>If copy is not true, the passed object will be mutated by the builder methods.</p>
*
* @param object the object to base the new builder upon
* @param copy if the object should be deep copied, or just referenced.
* @return a new builder
*/
public static JsonObjectBuilder object(JsonObject object, boolean copy) {
Objects.requireNonNull(object, "object");
if (copy) {
return object().addAll(object, true);
} else {
return new JsonObjectBuilderImpl(object);
}
}
/**
* Creates a new object builder, without copying the passed object.
*
* <p>Equivalent to calling {@link #object(JsonObject, boolean)} with copy = false.</p>
*
* @param object the object to base the new builder upon
* @return a new builder
*/
public static JsonObjectBuilder object(JsonObject object) {
Objects.requireNonNull(object, "object");
return object(object, false);
}
/**
* Creates a new object builder, with no initial values
*
* @return a new builder
*/
public static JsonObjectBuilder object() {
return object(new JsonObject());
}
/**
* Creates a new array builder
*
* <p>If copy is not true, the passed array will be mutated by the builder methods.</p>
*
* @param array the array to base the new builder upon
* @param copy if the array should be deep copied, or just referenced.
* @return a new builder
*/
public static JsonArrayBuilder array(JsonArray array, boolean copy) {
Objects.requireNonNull(array, "array");
if (copy) {
return array().addAll(array, true);
} else {
return new JsonArrayBuilderImpl(array);
}
}
/**
* Creates a new array builder, without copying the passed array.
*
* <p>Equivalent to calling {@link #array(JsonArray, boolean)} with copy = false.</p>
*
* @param array the array to base the new builder upon
* @return a new builder
*/
public static JsonArrayBuilder array(JsonArray array) {
Objects.requireNonNull(array, "array");
return array(array, false);
}
/**
* Creates a new array builder, with no initial values
*
* @return a new builder
*/
public static JsonArrayBuilder array() {
return array(new JsonArray());
}
/**
* Creates a JsonPrimitive from the given value.
*
* <p>If the value is null, {@link #nullValue()} is returned.</p>
*
* @param value the value
* @return a json primitive for the value
*/
public static JsonElement primitive(@Nullable String value) {
return value == null ? nullValue() : new JsonPrimitive(value);
}
/**
* Creates a JsonPrimitive from the given value.
*
* <p>If the value is null, {@link #nullValue()} is returned.</p>
*
* @param value the value
* @return a json primitive for the value
*/
public static JsonElement primitive(@Nullable Number value) {
return value == null ? nullValue() : new JsonPrimitive(value);
}
/**
* Creates a JsonPrimitive from the given value.
*
* <p>If the value is null, {@link #nullValue()} is returned.</p>
*
* @param value the value
* @return a json primitive for the value
*/
public static JsonElement primitive(@Nullable Boolean value) {
return value == null ? nullValue() : new JsonPrimitive(value);
}
/**
* Creates a JsonPrimitive from the given value.
*
* <p>If the value is null, {@link #nullValue()} is returned.</p>
*
* @param value the value
* @return a json primitive for the value
*/
public static JsonElement primitive(@Nullable Character value) {
return value == null ? nullValue() : new JsonPrimitive(value);
}
/**
* Returns an instance of {@link JsonNull}.
*
* @return a json null instance
*/
public static JsonNull nullValue() {
return JsonNull.INSTANCE;
}
/**
* Creates a JsonPrimitive from the given value.
*
* <p>If the value is null, a {@link NullPointerException} will be thrown.</p>
*
* @param value the value
* @return a json primitive for the value
* @throws NullPointerException if value is null
*/
public static JsonPrimitive primitiveNonNull(String value) {
Objects.requireNonNull(value, "value");
return new JsonPrimitive(value);
}
/**
* Creates a JsonPrimitive from the given value.
*
* <p>If the value is null, a {@link NullPointerException} will be thrown.</p>
*
* @param value the value
* @return a json primitive for the value
* @throws NullPointerException if value is null
*/
public static JsonPrimitive primitiveNonNull(Number value) {
Objects.requireNonNull(value, "value");
return new JsonPrimitive(value);
}
/**
* Creates a JsonPrimitive from the given value.
*
* <p>If the value is null, a {@link NullPointerException} will be thrown.</p>
*
* @param value the value
* @return a json primitive for the value
* @throws NullPointerException if value is null
*/
public static JsonPrimitive primitiveNonNull(Boolean value) {
Objects.requireNonNull(value, "value");
return new JsonPrimitive(value);
}
/**
* Creates a JsonPrimitive from the given value.
*
* <p>If the value is null, a {@link NullPointerException} will be thrown.</p>
*
* @param value the value
* @return a json primitive for the value
* @throws NullPointerException if value is null
*/
public static JsonPrimitive primitiveNonNull(Character value) {
Objects.requireNonNull(value, "value");
return new JsonPrimitive(value);
}
/**
* Returns a collector which forms a JsonObject using the key and value mappers
*
* @param keyMapper the function to map from T to {@link String}
* @param valueMapper the function to map from T to {@link JsonElement}
* @param <T> the type
* @return a new collector
*/
public static <T> Collector<T, JsonObjectBuilder, JsonObject> collectToObject(Function<? super T, String> keyMapper, Function<? super T, JsonElement> valueMapper) {
return Collector.of(
JsonBuilder::object,
(r, t) -> r.add(keyMapper.apply(t), valueMapper.apply(t)),
(l, r) -> l.addAll(r.build()),
JsonObjectBuilder::build
);
}
/**
* Returns a collector which forms a JsonArray using the value mapper
*
* @param valueMapper the function to map from T to {@link JsonElement}
* @param <T> the type
* @return a new collector
*/
public static <T> Collector<T, JsonArrayBuilder, JsonArray> collectToArray(Function<? super T, JsonElement> valueMapper) {
return Collector.of(
JsonBuilder::array,
(r, t) -> r.add(valueMapper.apply(t)),
(l, r) -> l.addAll(r.build()),
JsonArrayBuilder::build
);
}
/**
* Returns a collector which forms a JsonArray from JsonElements
*
* @return a new collector
*/
public static Collector<JsonElement, JsonArrayBuilder, JsonArray> collectToArray() {
return Collector.of(
JsonBuilder::array,
JsonArrayBuilder::add,
(l, r) -> l.addAll(r.build()),
JsonArrayBuilder::build
);
}
/**
* Returns a collector which forms a JsonArray from GsonSerializables
*
* @return a new collector
*/
public static Collector<GsonSerializable, JsonArrayBuilder, JsonArray> collectSerializablesToArray() {
return Collector.of(
JsonBuilder::array,
JsonArrayBuilder::add,
(l, r) -> l.addAll(r.build()),
JsonArrayBuilder::build
);
}
/**
* A {@link JsonObject} builder utility
*/
public interface JsonObjectBuilder extends BiConsumer<String, JsonElement>, Consumer<Map.Entry<String, JsonElement>> {
@Override
default void accept(Map.Entry<String, JsonElement> entry) {
Objects.requireNonNull(entry, "entry");
add(entry.getKey(), entry.getValue());
}
@Override
default void accept(String property, JsonElement value) {
add(property, value);
}
JsonObjectBuilder add(String property, @Nullable JsonElement value, boolean copy);
default JsonObjectBuilder add(String property, @Nullable JsonElement value) {
return add(property, value, false);
}
default JsonObjectBuilder add(String property, @Nullable GsonSerializable serializable) {
return serializable == null ? add(property, nullValue()) : add(property, serializable.serialize());
}
default JsonObjectBuilder add(String property, @Nullable String value) {
return add(property, primitive(value));
}
default JsonObjectBuilder add(String property, @Nullable Number value) {
return add(property, primitive(value));
}
default JsonObjectBuilder add(String property, @Nullable Boolean value) {
return add(property, primitive(value));
}
default JsonObjectBuilder add(String property, @Nullable Character value) {
return add(property, primitive(value));
}
JsonObjectBuilder addIfAbsent(String property, @Nullable JsonElement value, boolean copy);
default JsonObjectBuilder addIfAbsent(String property, @Nullable JsonElement value) {
return addIfAbsent(property, value, false);
}
default JsonObjectBuilder addIfAbsent(String property, @Nullable GsonSerializable serializable) {
return serializable == null ? addIfAbsent(property, nullValue()) : addIfAbsent(property, serializable.serialize());
}
default JsonObjectBuilder addIfAbsent(String property, @Nullable String value) {
return addIfAbsent(property, primitive(value));
}
default JsonObjectBuilder addIfAbsent(String property, @Nullable Number value) {
return addIfAbsent(property, primitive(value));
}
default JsonObjectBuilder addIfAbsent(String property, @Nullable Boolean value) {
return addIfAbsent(property, primitive(value));
}
default JsonObjectBuilder addIfAbsent(String property, @Nullable Character value) {
return addIfAbsent(property, primitive(value));
}
default <T extends JsonElement> JsonObjectBuilder addAll(Iterable<Map.Entry<String, T>> iterable, boolean deepCopy) {
Objects.requireNonNull(iterable, "iterable");
for (Map.Entry<String, T> e : iterable) {
if (e == null || e.getKey() == null) {
continue;
}
add(e.getKey(), e.getValue(), deepCopy);
}
return this;
}
default <T extends JsonElement> JsonObjectBuilder addAll(Iterable<Map.Entry<String, T>> iterable) {
return addAll(iterable, false);
}
default <T extends JsonElement> JsonObjectBuilder addAll(Stream<Map.Entry<String, T>> stream, boolean deepCopy) {
Objects.requireNonNull(stream, "stream");
stream.forEach(e -> {
if (e == null || e.getKey() == null) {
return;
}
add(e.getKey(), e.getValue(), deepCopy);
});
return this;
}
default <T extends JsonElement> JsonObjectBuilder addAll(Stream<Map.Entry<String, T>> stream) {
return addAll(stream, false);
}
default JsonObjectBuilder addAll(JsonObject object, boolean deepCopy) {
Objects.requireNonNull(object, "object");
return addAll(object.entrySet(), deepCopy);
}
default JsonObjectBuilder addAll(JsonObject object) {
return addAll(object, false);
}
default <T extends GsonSerializable> JsonObjectBuilder addAllSerializables(Iterable<Map.Entry<String, T>> iterable) {
Objects.requireNonNull(iterable, "iterable");
for (Map.Entry<String, T> e : iterable) {
if (e == null || e.getKey() == null) {
continue;
}
add(e.getKey(), e.getValue());
}
return this;
}
default JsonObjectBuilder addAllStrings(Iterable<Map.Entry<String, String>> iterable) {
Objects.requireNonNull(iterable, "iterable");
for (Map.Entry<String, String> e : iterable) {
if (e == null || e.getKey() == null) {
continue;
}
add(e.getKey(), e.getValue());
}
return this;
}
default <T extends Number> JsonObjectBuilder addAllNumbers(Iterable<Map.Entry<String, T>> iterable) {
Objects.requireNonNull(iterable, "iterable");
for (Map.Entry<String, T> e : iterable) {
if (e == null || e.getKey() == null) {
continue;
}
add(e.getKey(), e.getValue());
}
return this;
}
default JsonObjectBuilder addAllBooleans(Iterable<Map.Entry<String, Boolean>> iterable) {
Objects.requireNonNull(iterable, "iterable");
for (Map.Entry<String, Boolean> e : iterable) {
if (e == null || e.getKey() == null) {
continue;
}
add(e.getKey(), e.getValue());
}
return this;
}
default JsonObjectBuilder addAllCharacters(Iterable<Map.Entry<String, Character>> iterable) {
Objects.requireNonNull(iterable, "iterable");
for (Map.Entry<String, Character> e : iterable) {
if (e == null || e.getKey() == null) {
continue;
}
add(e.getKey(), e.getValue());
}
return this;
}
default <T extends JsonElement> JsonObjectBuilder addAllIfAbsent(Iterable<Map.Entry<String, T>> iterable, boolean deepCopy) {
Objects.requireNonNull(iterable, "iterable");
for (Map.Entry<String, T> e : iterable) {
if (e == null || e.getKey() == null) {
continue;
}
addIfAbsent(e.getKey(), e.getValue(), deepCopy);
}
return this;
}
default <T extends JsonElement> JsonObjectBuilder addAllIfAbsent(Iterable<Map.Entry<String, T>> iterable) {
return addAllIfAbsent(iterable, false);
}
default <T extends JsonElement> JsonObjectBuilder addAllIfAbsent(Stream<Map.Entry<String, T>> stream, boolean deepCopy) {
Objects.requireNonNull(stream, "stream");
stream.forEach(e -> {
if (e == null || e.getKey() == null) {
return;
}
addIfAbsent(e.getKey(), e.getValue(), deepCopy);
});
return this;
}
default <T extends JsonElement> JsonObjectBuilder addAllIfAbsent(Stream<Map.Entry<String, T>> stream) {
return addAllIfAbsent(stream, false);
}
default JsonObjectBuilder addAllIfAbsent(JsonObject object, boolean deepCopy) {
Objects.requireNonNull(object, "object");
return addAllIfAbsent(object.entrySet(), deepCopy);
}
default JsonObjectBuilder addAllIfAbsent(JsonObject object) {
return addAllIfAbsent(object, false);
}
default <T extends GsonSerializable> JsonObjectBuilder addAllSerializablesIfAbsent(Iterable<Map.Entry<String, T>> iterable) {
Objects.requireNonNull(iterable, "iterable");
for (Map.Entry<String, T> e : iterable) {
if (e == null || e.getKey() == null) {
continue;
}
addIfAbsent(e.getKey(), e.getValue());
}
return this;
}
default JsonObjectBuilder addAllStringsIfAbsent(Iterable<Map.Entry<String, String>> iterable) {
Objects.requireNonNull(iterable, "iterable");
for (Map.Entry<String, String> e : iterable) {
if (e == null || e.getKey() == null) {
continue;
}
addIfAbsent(e.getKey(), e.getValue());
}
return this;
}
default <T extends Number> JsonObjectBuilder addAllNumbersIfAbsent(Iterable<Map.Entry<String, T>> iterable) {
Objects.requireNonNull(iterable, "iterable");
for (Map.Entry<String, T> e : iterable) {
if (e == null || e.getKey() == null) {
continue;
}
addIfAbsent(e.getKey(), e.getValue());
}
return this;
}
default JsonObjectBuilder addAllBooleansIfAbsent(Iterable<Map.Entry<String, Boolean>> iterable) {
Objects.requireNonNull(iterable, "iterable");
for (Map.Entry<String, Boolean> e : iterable) {
if (e == null || e.getKey() == null) {
continue;
}
addIfAbsent(e.getKey(), e.getValue());
}
return this;
}
default JsonObjectBuilder addAllCharactersIfAbsent(Iterable<Map.Entry<String, Character>> iterable) {
Objects.requireNonNull(iterable, "iterable");
for (Map.Entry<String, Character> e : iterable) {
if (e == null || e.getKey() == null) {
continue;
}
addIfAbsent(e.getKey(), e.getValue());
}
return this;
}
JsonObject build();
}
/**
* A {@link JsonArray} builder utility
*/
public interface JsonArrayBuilder extends Consumer<JsonElement> {
@Override
default void accept(JsonElement value) {
add(value);
}
JsonArrayBuilder add(@Nullable JsonElement value, boolean copy);
default JsonArrayBuilder add(@Nullable JsonElement value) {
return add(value, false);
}
default JsonArrayBuilder add(@Nullable GsonSerializable serializable) {
return serializable == null ? add(nullValue()) : add(serializable.serialize());
}
default JsonArrayBuilder add(@Nullable String value) {
return add(primitive(value));
}
default JsonArrayBuilder add(@Nullable Number value) {
return add(primitive(value));
}
default JsonArrayBuilder add(@Nullable Boolean value) {
return add(primitive(value));
}
default JsonArrayBuilder add(@Nullable Character value) {
return add(primitive(value));
}
default <T extends JsonElement> JsonArrayBuilder addAll(Iterable<T> iterable, boolean copy) {
Objects.requireNonNull(iterable, "iterable");
for (T e : iterable) {
add(e, copy);
}
return this;
}
default <T extends JsonElement> JsonArrayBuilder addAll(Iterable<T> iterable) {
return addAll(iterable, false);
}
default <T extends JsonElement> JsonArrayBuilder addAll(Stream<T> stream, boolean copy) {
Objects.requireNonNull(stream, "iterable");
stream.forEach(e -> add(e, copy));
return this;
}
default <T extends JsonElement> JsonArrayBuilder addAll(Stream<T> stream) {
return addAll(stream, false);
}
default <T extends GsonSerializable> JsonArrayBuilder addSerializables(Iterable<T> iterable) {
Objects.requireNonNull(iterable, "iterable");
for (T e : iterable) {
add(e);
}
return this;
}
default JsonArrayBuilder addStrings(Iterable<String> iterable) {
Objects.requireNonNull(iterable, "iterable");
for (String e : iterable) {
add(e);
}
return this;
}
default <T extends Number> JsonArrayBuilder addNumbers(Iterable<T> iterable) {
Objects.requireNonNull(iterable, "iterable");
for (T e : iterable) {
add(e);
}
return this;
}
default JsonArrayBuilder addBooleans(Iterable<Boolean> iterable) {
Objects.requireNonNull(iterable, "iterable");
for (Boolean e : iterable) {
add(e);
}
return this;
}
default JsonArrayBuilder addCharacters(Iterable<Character> iterable) {
Objects.requireNonNull(iterable, "iterable");
for (Character e : iterable) {
add(e);
}
return this;
}
JsonArray build();
}
private static final class JsonObjectBuilderImpl implements JsonObjectBuilder {
private final JsonObject handle;
private JsonObjectBuilderImpl(JsonObject handle) {
this.handle = handle;
}
@Override
public JsonObjectBuilder add(String property, @Nullable JsonElement value, boolean copy) {
Objects.requireNonNull(property, "property");
if (value == null) {
value = nullValue();
}
if (copy && value.isJsonObject()) {
this.handle.add(property, object(value.getAsJsonObject(), true).build());
} else if (copy && value.isJsonArray()) {
this.handle.add(property, array(value.getAsJsonArray(), true).build());
} else {
this.handle.add(property, value);
}
return this;
}
@Override
public JsonObjectBuilder addIfAbsent(String property, @Nullable JsonElement value, boolean copy) {
Objects.requireNonNull(property, "property");
if (this.handle.has(property)) {
return this;
}
return add(property, value, copy);
}
@Override
public JsonObject build() {
return this.handle;
}
}
private static final class JsonArrayBuilderImpl implements JsonArrayBuilder {
private final JsonArray handle;
private JsonArrayBuilderImpl(JsonArray handle) {
this.handle = handle;
}
@Override
public JsonArrayBuilder add(@Nullable JsonElement value, boolean copy) {
if (value == null) {
value = nullValue();
}
if (copy && value.isJsonObject()) {
this.handle.add(object(value.getAsJsonObject(), true).build());
} else if (copy && value.isJsonArray()) {
this.handle.add(array(value.getAsJsonArray(), true).build());
} else {
this.handle.add(value);
}
return this;
}
@Override
public JsonArray build() {
return this.handle;
}
}
private JsonBuilder() {
throw new UnsupportedOperationException("This class cannot be instantiated");
}
}

View File

@@ -0,0 +1,53 @@
/*
* This file is part of helper, licensed under the MIT License.
*
* Copyright (c) lucko (Luck) <luck@lucko.me>
* Copyright (c) contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package me.lucko.helper.serialize;
import org.yaml.snakeyaml.external.biz.base64Coder.Base64Coder;
import java.util.Base64;
class Base64Util {
public static String encode(byte[] buf) {
return Base64.getEncoder().encodeToString(buf);
}
public static byte[] decode(String src) {
try {
return Base64.getDecoder().decode(src);
} catch (IllegalArgumentException e) {
// compat with the previously used base64 encoder
try {
return Base64Coder.decodeLines(src);
} catch (Exception ignored) {
throw e;
}
}
}
private Base64Util() {}
}

View File

@@ -0,0 +1,145 @@
/*
* This file is part of helper, licensed under the MIT License.
*
* Copyright (c) lucko (Luck) <luck@lucko.me>
* Copyright (c) contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package me.lucko.helper.serialize;
import org.bukkit.Bukkit;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemStack;
import org.bukkit.util.io.BukkitObjectInputStream;
import org.bukkit.util.io.BukkitObjectOutputStream;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
public final class InventorySerialization {
public static byte[] encodeItemStack(ItemStack item) {
try (ByteArrayOutputStream outputStream = new ByteArrayOutputStream()) {
try (BukkitObjectOutputStream dataOutput = new BukkitObjectOutputStream(outputStream)) {
dataOutput.writeObject(item);
return outputStream.toByteArray();
}
} catch (IOException e) {
throw new RuntimeException(e);
}
}
public static String encodeItemStackToString(ItemStack item) {
return Base64Util.encode(encodeItemStack(item));
}
public static ItemStack decodeItemStack(byte[] buf) {
try (ByteArrayInputStream inputStream = new ByteArrayInputStream(buf)) {
try (BukkitObjectInputStream dataInput = new BukkitObjectInputStream(inputStream)) {
return (ItemStack) dataInput.readObject();
}
} catch (ClassNotFoundException | IOException e) {
throw new RuntimeException(e);
}
}
public static ItemStack decodeItemStack(String data) {
return decodeItemStack(Base64Util.decode(data));
}
public static byte[] encodeItemStacks(ItemStack[] items) {
try (ByteArrayOutputStream outputStream = new ByteArrayOutputStream()) {
try (BukkitObjectOutputStream dataOutput = new BukkitObjectOutputStream(outputStream)) {
dataOutput.writeInt(items.length);
for (ItemStack item : items) {
dataOutput.writeObject(item);
}
return outputStream.toByteArray();
}
} catch (IOException e) {
throw new RuntimeException(e);
}
}
public static String encodeItemStacksToString(ItemStack[] items) {
return Base64Util.encode(encodeItemStacks(items));
}
public static ItemStack[] decodeItemStacks(byte[] buf) {
try (ByteArrayInputStream inputStream = new ByteArrayInputStream(buf)) {
try (BukkitObjectInputStream dataInput = new BukkitObjectInputStream(inputStream)) {
ItemStack[] items = new ItemStack[dataInput.readInt()];
for (int i = 0; i < items.length; i++) {
items[i] = (ItemStack) dataInput.readObject();
}
return items;
}
} catch (ClassNotFoundException | IOException e) {
throw new RuntimeException(e);
}
}
public static ItemStack[] decodeItemStacks(String data) {
return decodeItemStacks(Base64Util.decode(data));
}
public static byte[] encodeInventory(Inventory inventory) {
try (ByteArrayOutputStream outputStream = new ByteArrayOutputStream()) {
try (BukkitObjectOutputStream dataOutput = new BukkitObjectOutputStream(outputStream)) {
dataOutput.writeInt(inventory.getSize());
for (int i = 0; i < inventory.getSize(); i++) {
dataOutput.writeObject(inventory.getItem(i));
}
return outputStream.toByteArray();
}
} catch (IOException e) {
throw new RuntimeException(e);
}
}
public static String encodeInventoryToString(Inventory inventory) {
return Base64Util.encode(encodeInventory(inventory));
}
public static Inventory decodeInventory(byte[] buf, String title) {
try (ByteArrayInputStream inputStream = new ByteArrayInputStream(buf)) {
try (BukkitObjectInputStream dataInput = new BukkitObjectInputStream(inputStream)) {
Inventory inventory = Bukkit.getServer().createInventory(null, dataInput.readInt(), title);
for (int i = 0; i < inventory.getSize(); i++) {
inventory.setItem(i, (ItemStack) dataInput.readObject());
}
return inventory;
}
} catch (ClassNotFoundException | IOException e) {
throw new RuntimeException(e);
}
}
public static Inventory decodeInventory(String data, String title) {
return decodeInventory(Base64Util.decode(data), title);
}
private InventorySerialization() {
throw new UnsupportedOperationException("This class cannot be instantiated");
}
}

View File

@@ -0,0 +1,70 @@
/*
* This file is part of helper, licensed under the MIT License.
*
* Copyright (c) lucko (Luck) <luck@lucko.me>
* Copyright (c) contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package me.lucko.helper.serialize;
import com.google.common.base.Preconditions;
import com.google.gson.JsonElement;
import com.google.gson.JsonPrimitive;
import me.lucko.helper.gson.JsonBuilder;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemStack;
/**
* Utility methods for converting ItemStacks and Inventories to and from JSON.
*/
public final class Serializers {
public static JsonPrimitive serializeItemstack(ItemStack item) {
return JsonBuilder.primitiveNonNull(InventorySerialization.encodeItemStackToString(item));
}
public static ItemStack deserializeItemstack(JsonElement data) {
Preconditions.checkArgument(data.isJsonPrimitive());
return InventorySerialization.decodeItemStack(data.getAsString());
}
public static JsonPrimitive serializeItemstacks(ItemStack[] items) {
return JsonBuilder.primitiveNonNull(InventorySerialization.encodeItemStacksToString(items));
}
public static JsonPrimitive serializeInventory(Inventory inventory) {
return JsonBuilder.primitiveNonNull(InventorySerialization.encodeInventoryToString(inventory));
}
public static ItemStack[] deserializeItemstacks(JsonElement data) {
Preconditions.checkArgument(data.isJsonPrimitive());
return InventorySerialization.decodeItemStacks(data.getAsString());
}
public static Inventory deserializeInventory(JsonElement data, String title) {
Preconditions.checkArgument(data.isJsonPrimitive());
return InventorySerialization.decodeInventory(data.getAsString(), title);
}
private Serializers() {
throw new UnsupportedOperationException("This class cannot be instantiated");
}
}

View File

@@ -139,7 +139,6 @@ public class RPGRegionsCommand extends BaseCommand {
sender.sendMessage(StringUtils.colour("&aSet name of region '" + region + "' to: " + regionName));
}
@Subcommand("remove")
@CommandPermission("rpgregions.remove")
@CommandCompletion("@regions")

View File

@@ -8,6 +8,8 @@ import com.google.gson.JsonElement;
import com.google.gson.JsonSerializationContext;
import com.google.gson.JsonSerializer;
import com.google.gson.reflect.TypeToken;
import me.lucko.helper.serialize.Serializers;
import net.islandearth.rpgregions.api.RPGRegionsAPI;
import org.bukkit.inventory.ItemStack;
import java.lang.reflect.Type;
@@ -24,11 +26,16 @@ public class ItemStackAdapter implements JsonSerializer<ItemStack>, JsonDeserial
@Override
public ItemStack deserialize(JsonElement jsonElement, Type type,
JsonDeserializationContext context) {
return ItemStack.deserialize(gson.fromJson(jsonElement, new TypeToken<Map<String, Object>>(){}.getType()));
try {
return Serializers.deserializeItemstack(jsonElement);
} catch (Exception e) { // Legacy data, load it as normal, when it's next saved it will be normal.
RPGRegionsAPI.getAPI().getLogger().warning("Trying to migrate legacy ItemStack...");
return ItemStack.deserialize(gson.fromJson(jsonElement, new TypeToken<Map<String, Object>>(){}.getType()));
}
}
@Override
public JsonElement serialize(ItemStack itemStack, Type type, JsonSerializationContext context) {
return gson.toJsonTree(itemStack.serialize());
return Serializers.serializeItemstack(itemStack);
}
}