Uh oh!
There was an error while loading. Please reload this page.
- Notifications
You must be signed in to change notification settings - Fork 5
Add support for Stringified NBT objects#92
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Uh oh!
There was an error while loading. Please reload this page.
Changes from all commits
ad30a236e68cc1c722a73587bba972fc01273ac136de99c9f7af764a810deb44fc75f9450810938c1ea8fae716905ae866c6b71aeFile filter
Filter by extension
Conversations
Uh oh!
There was an error while loading. Please reload this page.
Jump to
Uh oh!
There was an error while loading. Please reload this page.
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,66 @@ | ||
| /* | ||
| * Copyright (c) 2020-2021 DumbDogDiner <dumbdogdiner.com>. All rights reserved. | ||
| * Licensed under the MIT license, see LICENSE for more information... | ||
| */ | ||
| package com.dumbdogdiner.stickyapi.common.nbt; | ||
| import com.google.gson.JsonElement; | ||
| import com.google.gson.JsonPrimitive; | ||
| import org.jetbrains.annotations.NotNull; | ||
| /** | ||
| * A convenience class for converting booleans from {@link JsonPrimitive}s, and for easily creating | ||
| */ | ||
| public class NbtBooleanTag extends NbtPrimitiveTag<Boolean> { | ||
| private final boolean bool; | ||
| public NbtBooleanTag(boolean bool) { | ||
| this.bool = bool; | ||
| } | ||
| /** | ||
| * Converts a {@link JsonPrimitive} of a boolean to a new {@link NbtBooleanTag} | ||
| * It is recommended to make sure the primitive is a boolean first | ||
| * | ||
| * @param primitive The incoming {@link JsonPrimitive} to be converted, must be a boolean type! | ||
| * @return A new tag with tbe boolean value of the primitive | ||
| * @throws ClassCastException if the primitive is not a boolean | ||
| * @see JsonPrimitive#isBoolean() | ||
| */ | ||
| public static @NotNull NbtBooleanTag fromPrimitive(@NotNull JsonPrimitive primitive) throws ClassCastException { | ||
| return new NbtBooleanTag(primitive.getAsBoolean()); | ||
| } | ||
| // As much as I hate the object form... we have to because generics | ||
| @Override | ||
| public @NotNull Boolean asPrimitive() { | ||
| return bool; | ||
| } | ||
| @Override | ||
| public @NotNull JsonElement toJson() { | ||
| return new JsonPrimitive(bool); | ||
| } | ||
| @Override | ||
| public @NotNull String toNbtString() { | ||
| return bool ? NbtNumberTag.TRUE.toNbtString() : NbtNumberTag.FALSE.toNbtString(); | ||
| } | ||
| @Override | ||
| public boolean equals(Object other) { | ||
| if (other instanceof NbtBooleanTag) { | ||
| return ((NbtBooleanTag) other).asPrimitive() == bool; | ||
| } else if (other instanceof NbtNumberTag) { | ||
| return (!((NbtNumberTag) other).asPrimitive().equals(0)) == bool; | ||
| } else { | ||
| return false; | ||
| } | ||
| } | ||
| @Override | ||
| public int hashCode() { | ||
| return Boolean.hashCode(bool); | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,117 @@ | ||
| /* | ||
| * Copyright (c) 2020-2021 DumbDogDiner <dumbdogdiner.com>. All rights reserved. | ||
| * Licensed under the MIT license, see LICENSE for more information... | ||
| */ | ||
| package com.dumbdogdiner.stickyapi.common.nbt; | ||
| import com.google.gson.JsonElement; | ||
| import com.google.gson.JsonObject; | ||
| import org.jetbrains.annotations.NotNull; | ||
| import java.util.HashMap; | ||
| import java.util.Map; | ||
| import java.util.StringJoiner; | ||
| /** | ||
| * A wrapper tag that allows working with Compound NBT tags as maps! | ||
| */ | ||
| public class NbtCompoundTag extends HashMap<String, NbtTag> implements NbtTag { | ||
| /** | ||
| * Creates a new {@link NbtCompoundTag} from an existing {@link Map} | ||
| * {@inheritDoc} | ||
| */ | ||
| public NbtCompoundTag(Map<String, NbtTag> map) { | ||
| super(map); | ||
| } | ||
| /** | ||
| * Create a new, blank {@link NbtCompoundTag} | ||
| * | ||
| * {@inheritDoc} | ||
| */ | ||
| public NbtCompoundTag() { | ||
| super(); | ||
| } | ||
| /** | ||
| * Create a new {@link NbtCompoundTag} with an existing key and tag (useful for 1-element compound tags!) | ||
| * @param key The key to set | ||
| * @param tag The tag to assign | ||
| */ | ||
| public NbtCompoundTag(String key, NbtTag tag){ | ||
| super(); | ||
| put(key, tag); | ||
| } | ||
| /** | ||
| * Constructs a new {@link NbtCompoundTag} from a given {@link JsonObject} | ||
| */ | ||
| public static NbtCompoundTag fromJsonObject(JsonObject object){ | ||
| NbtCompoundTag tag = new NbtCompoundTag(); | ||
| for(String elementName : object.keySet()){ | ||
| tag.put(elementName, NbtJsonAdapter.fromJson(object.get(elementName))); | ||
| } | ||
| return tag; | ||
| } | ||
| @Override | ||
| public @NotNull JsonElement toJson() { | ||
| JsonObject object = new JsonObject(); | ||
| forEach((name, nbtTag) -> { | ||
| if(nbtTag instanceof NbtPrimitiveTag){ | ||
| Object primitive = ((NbtPrimitiveTag<?>) nbtTag).asPrimitive(); | ||
| if(primitive instanceof NbtNumberTag){ | ||
| object.addProperty(name, ((NbtNumberTag) primitive).asPrimitive()); | ||
| } else if(primitive instanceof NbtBooleanTag){ | ||
| object.addProperty(name, ((NbtBooleanTag) primitive).asPrimitive()); | ||
| } else if(primitive instanceof NbtStringTag){ | ||
| object.addProperty(name, ((NbtStringTag) primitive).asPrimitive()); | ||
| } | ||
| } else { | ||
| object.add(name, nbtTag.toJson()); | ||
| } | ||
| }); | ||
| return object; | ||
| } | ||
| @Override | ||
| public @NotNull String toNbtString() { | ||
| StringJoiner stringNbt = new StringJoiner(",", "{", "}"); | ||
| forEach((name, nbtTag) -> { | ||
| StringJoiner element = new StringJoiner(":"); | ||
| element.add(name); | ||
| element.add(nbtTag.toNbtString()); | ||
| stringNbt.add(element.toString()); | ||
| }); | ||
| return stringNbt.toString(); | ||
| } | ||
| /** | ||
| * Convenience method to add a number directly to the compound tag with a given key | ||
| * @return The original number | ||
| */ | ||
| public @NotNull Number put(@NotNull String key, @NotNull Number n) { | ||
| put(key, new NbtNumberTag(n)); | ||
| return n; | ||
| } | ||
| /** | ||
| * Convenience method to add a boolean directly to the compound tag with a given key | ||
| * @return The original boolean | ||
| */ | ||
| public boolean put(@NotNull String key, boolean b) { | ||
| put(key, new NbtBooleanTag(b)); | ||
| return b; | ||
| } | ||
| /** | ||
| * Convenience method to add a String directly to the compound tag with a given key | ||
| * @return The original String | ||
| */ | ||
| public String put(@NotNull String key, @NotNull String s){ | ||
| put(key, new NbtStringTag(s)); | ||
| return s; | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,49 @@ | ||
| /* | ||
| * Copyright (c) 2020-2021 DumbDogDiner <dumbdogdiner.com>. All rights reserved. | ||
| * Licensed under the MIT license, see LICENSE for more information... | ||
| */ | ||
| package com.dumbdogdiner.stickyapi.common.nbt; | ||
| import com.google.gson.JsonElement; | ||
| import com.google.gson.JsonPrimitive; | ||
| import lombok.experimental.UtilityClass; | ||
| import org.jetbrains.annotations.NotNull; | ||
| import java.text.MessageFormat; | ||
| /** | ||
| * Utility class for easy creation of the appropriate {@link NbtTag} from an existing {@link JsonElement} | ||
| */ | ||
| @UtilityClass | ||
| public final class NbtJsonAdapter { | ||
jcxldn marked this conversation as resolved.
Uh oh!There was an error while loading. Please reload this page. | ||
| /** | ||
| * Creates the appropriate tag from a given {@link JsonElement}, but never creates a {@link NbtJsonTag} | ||
| * @param element The incoming {@link JsonElement} to convert | ||
| * @return the new {@link NbtTag} | ||
| */ | ||
| public static NbtTag fromJson(@NotNull JsonElement element) { | ||
| if(element.isJsonArray()){ | ||
| return NbtListTag.fromJsonArray(element.getAsJsonArray()); | ||
| } else if(element.isJsonObject()){ | ||
| return NbtCompoundTag.fromJsonObject(element.getAsJsonObject()); | ||
| } else if (element.isJsonPrimitive()) { | ||
| // TODO: Rewrite to look cleaner? | ||
| // https://github.com/DumbDogDiner/StickyAPI/pull/92/files#r575639999 | ||
| JsonPrimitive primitive = element.getAsJsonPrimitive(); | ||
| if(primitive.isBoolean()){ | ||
| return NbtBooleanTag.fromPrimitive(primitive); | ||
| } else if(primitive.isNumber()){ | ||
| return NbtNumberTag.fromPrimitive(primitive); | ||
| } else if(primitive.isString()){ | ||
| return NbtStringTag.fromPrimitive(primitive); | ||
| } else { | ||
| throw new UnsupportedOperationException("Illegal type of NBT primitive"); | ||
| } | ||
| } else if(element.isJsonNull()) { | ||
| return null; | ||
| } else { | ||
| throw new UnsupportedOperationException(MessageFormat.format("This type of JSONElement is unsupported ({0})", element.getClass().getName())); | ||
| } | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,60 @@ | ||
| /* | ||
| * Copyright (c) 2020-2021 DumbDogDiner <dumbdogdiner.com>. All rights reserved. | ||
| * Licensed under the MIT license, see LICENSE for more information... | ||
| */ | ||
| package com.dumbdogdiner.stickyapi.common.nbt; | ||
| import com.google.gson.Gson; | ||
| import com.google.gson.GsonBuilder; | ||
| import com.google.gson.JsonElement; | ||
| import org.jetbrains.annotations.NotNull; | ||
| /** | ||
| * A special type of {@link NbtTag} that converts an arbitrary {@link JsonElement} into an appropriately escaped string as NBT | ||
| */ | ||
| public class NbtJsonTag implements NbtTag{ | ||
jcxldn marked this conversation as resolved.
Uh oh!There was an error while loading. Please reload this page. | ||
| private final @NotNull JsonElement element; | ||
| private static final Gson G = new GsonBuilder() | ||
| // Make sure things aren't weirdly escaped, may need to turn this back on | ||
| .disableHtmlEscaping() | ||
| .create(); | ||
| public NbtJsonTag(@NotNull JsonElement element) { | ||
| this.element = element; | ||
| } | ||
| /** | ||
| * {@inheritDoc} | ||
| */ | ||
| @Override | ||
| public @NotNull JsonElement toJson() { | ||
| return element; | ||
| } | ||
| /** | ||
| * {@inheritDoc} | ||
| */ | ||
| @Override | ||
| public @NotNull String toNbtString() { | ||
| return '\'' + G.toJson(element) | ||
| // Because minecraft json is a hack on a hack..... | ||
| // And sometimes the NBT is just json that gets quoted | ||
| .replaceAll("(?<!\\\\)[']", "\\\\'") // Escape single quotes | ||
| // FIXME: do we need to escape double quotes too?? In theory we don't as long as we are using a single quote style! | ||
| .replace("\n", "\\n") // Replace new lines with escaped versions | ||
| .replaceAll("\\+n", "\\\\n") // Fix formatting of any escaped new lines already in there | ||
| +'\''; | ||
| } | ||
| @Override | ||
| public boolean equals(Object other) { | ||
| return ((other instanceof NbtJsonTag || other instanceof NbtStringTag) | ||
| && toNbtString().equals(((NbtTag) other).toNbtString())); | ||
| } | ||
| @Override | ||
| public int hashCode() { | ||
| return element.hashCode(); | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,83 @@ | ||
| /* | ||
| * Copyright (c) 2020-2021 DumbDogDiner <dumbdogdiner.com>. All rights reserved. | ||
| * Licensed under the MIT license, see LICENSE for more information... | ||
| */ | ||
| package com.dumbdogdiner.stickyapi.common.nbt; | ||
| import com.google.gson.JsonArray; | ||
| import com.google.gson.JsonElement; | ||
| import org.jetbrains.annotations.NotNull; | ||
| import java.util.ArrayList; | ||
| import java.util.Arrays; | ||
| import java.util.StringJoiner; | ||
| /** | ||
| * A wrapper class that allows the construction of or conversion (from JSON) of NBT List Tags | ||
| */ | ||
| public class NbtListTag extends ArrayList<NbtTag> implements NbtTag { | ||
jcxldn marked this conversation as resolved.
Uh oh!There was an error while loading. Please reload this page. | ||
| /** | ||
| * Generates a new, empty {@link NbtListTag} | ||
| * {@inheritDoc} | ||
| */ | ||
| public NbtListTag() { | ||
| super(); | ||
| } | ||
| /** | ||
| * Generate a new {@link NbtListTag} with elements from an existing array or individual objects | ||
| */ | ||
| public NbtListTag(NbtTag ... tags){ | ||
| super(Arrays.asList(tags)); | ||
| } | ||
| /** | ||
| * Converts a JSON array into an NBT List tag of the native types | ||
| * @param arr The Json Array to convert | ||
| * @return the new {@link NbtListTag} | ||
| */ | ||
| public static NbtListTag fromJsonArray(JsonArray arr){ | ||
| NbtListTag listTag = new NbtListTag(); | ||
| for(JsonElement jse : arr){ | ||
| listTag.add(NbtJsonAdapter.fromJson(jse)); | ||
| } | ||
| return listTag; | ||
| } | ||
| /** | ||
| * Creates an NBT tag that is a list of stringified JSON elements from source array | ||
| * @param arr Source JSON array to convert | ||
| * @return The newly converted NBT list tag | ||
| */ | ||
| public static NbtListTag fromJsonArrayQuoted(JsonArray arr){ | ||
| NbtListTag listTag = new NbtListTag(); | ||
| for(JsonElement jse : arr){ | ||
| listTag.add(new NbtJsonTag(jse)); | ||
| } | ||
| return listTag; | ||
| } | ||
| @Override | ||
| public @NotNull JsonElement toJson() { | ||
| JsonArray array = new JsonArray(); | ||
| for(NbtTag tag : this){ | ||
| array.add(tag.toJson()); | ||
| } | ||
| return array; | ||
| } | ||
| @Override | ||
| public @NotNull String toNbtString() { | ||
| StringJoiner joiner = new StringJoiner(",", "[", "]"); | ||
| forEach(nbtTag -> joiner.add(nbtTag.toNbtString())); | ||
| return joiner.toString(); | ||
| } | ||
| /** | ||
| * Creates a {@link NbtStringTag} of escaped NBT as a string | ||
| */ | ||
| public NbtStringTag toNbtStringTag() { | ||
| return new NbtStringTag(toNbtString(), true); | ||
| } | ||
| } | ||
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.