aboutsummaryrefslogtreecommitdiff
path: root/src/main/java/de/cowtipper/cowlection/util
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/java/de/cowtipper/cowlection/util')
-rw-r--r--src/main/java/de/cowtipper/cowlection/util/GsonUtils.java89
-rw-r--r--src/main/java/de/cowtipper/cowlection/util/ImageUtils.java132
-rw-r--r--src/main/java/de/cowtipper/cowlection/util/MooChatComponent.java21
3 files changed, 232 insertions, 10 deletions
diff --git a/src/main/java/de/cowtipper/cowlection/util/GsonUtils.java b/src/main/java/de/cowtipper/cowlection/util/GsonUtils.java
index c0b2735..e97a88d 100644
--- a/src/main/java/de/cowtipper/cowlection/util/GsonUtils.java
+++ b/src/main/java/de/cowtipper/cowlection/util/GsonUtils.java
@@ -3,14 +3,19 @@ package de.cowtipper.cowlection.util;
import com.google.gson.*;
import com.mojang.util.UUIDTypeAdapter;
import de.cowtipper.cowlection.data.HyPlayerData;
-import net.minecraft.nbt.NBTBase;
-import net.minecraft.nbt.NBTTagCompound;
-import net.minecraft.nbt.NBTTagList;
-import net.minecraft.nbt.NBTTagString;
+import net.minecraft.nbt.*;
import net.minecraftforge.common.util.Constants;
+import org.apache.commons.codec.binary.Base64;
import java.io.Reader;
import java.lang.reflect.Type;
+import java.time.DateTimeException;
+import java.time.Instant;
+import java.time.ZoneOffset;
+import java.time.ZonedDateTime;
+import java.time.format.DateTimeFormatter;
+import java.util.Map;
+import java.util.TreeMap;
import java.util.UUID;
public final class GsonUtils {
@@ -29,13 +34,51 @@ public final class GsonUtils {
}
public static String toJson(Object object) {
+ return toJson(object, false);
+ }
+
+ public static String toJson(Object object, boolean sort) {
if (object instanceof NBTBase) {
- return gsonPrettyPrinter.toJson(nbtToJson((NBTBase) object));
+ JsonElement jsonElement = nbtToJson((NBTBase) object);
+ if (sort && (jsonElement instanceof JsonObject || jsonElement instanceof JsonArray)) {
+ jsonElement = sortJsonElement(jsonElement);
+ }
+ return gsonPrettyPrinter.toJson(jsonElement);
} else {
return gson.toJson(object);
}
}
+ private static JsonElement sortJsonElement(JsonElement jsonElement) {
+ if (jsonElement instanceof JsonArray) {
+ // sort each element of array
+ JsonArray sortedJsonArray = new JsonArray();
+ for (JsonElement arrayElement : (JsonArray) jsonElement) {
+ sortedJsonArray.add(sortJsonElement(arrayElement));
+ }
+ return sortedJsonArray;
+ } else if (jsonElement instanceof JsonObject) {
+ // sort json by key
+ TreeMap<String, JsonElement> sortedJsonObject = new TreeMap<>(String::compareToIgnoreCase);
+ for (Map.Entry<String, JsonElement> jsonEntry : ((JsonObject) jsonElement).entrySet()) {
+ JsonElement sortedJsonElement = jsonEntry.getValue();
+ if (sortedJsonElement instanceof JsonObject) {
+ sortedJsonElement = sortJsonElement(sortedJsonElement);
+ }
+ sortedJsonObject.put(jsonEntry.getKey(), sortedJsonElement);
+ }
+ // overwrite jsonElement with json sorted by key alphabetically
+ JsonObject sortedJsonElement = new JsonObject();
+ for (Map.Entry<String, JsonElement> jsonEntrySorted : sortedJsonObject.entrySet()) {
+ sortedJsonElement.add(jsonEntrySorted.getKey(), jsonEntrySorted.getValue());
+ }
+ return sortedJsonElement;
+ } else {
+ // neither array, nor object: return original element
+ return jsonElement;
+ }
+ }
+
private static JsonElement nbtToJson(NBTBase nbtElement) {
if (nbtElement instanceof NBTBase.NBTPrimitive) {
NBTBase.NBTPrimitive nbtNumber = (NBTBase.NBTPrimitive) nbtElement;
@@ -56,7 +99,34 @@ public final class GsonUtils {
return new JsonObject();
}
} else if (nbtElement instanceof NBTTagString) {
- return new JsonPrimitive(((NBTTagString) nbtElement).getString());
+ String str = ((NBTTagString) nbtElement).getString();
+ if (str.length() > 100 && (str.startsWith("eyJ") || str.startsWith("ewo")) && Base64.isBase64(str)) {
+ // base64 decode NBTTagStrings starting with {" or {\n
+ try {
+ JsonElement base64DecodedJson = new JsonParser().parse(new String(Base64.decodeBase64(str)));
+ if (base64DecodedJson.isJsonObject()) {
+ JsonObject jsonObject = base64DecodedJson.getAsJsonObject();
+ JsonElement timestamp = jsonObject.get("timestamp");
+ if (timestamp != null) {
+ // convert unix timestamp to human-readable dates
+ try {
+ ZonedDateTime utcDateTime = ZonedDateTime.ofInstant(Instant.ofEpochMilli(timestamp.getAsLong()), ZoneOffset.UTC);
+ ZonedDateTime localDateTime = utcDateTime.withZoneSameInstant(ZoneOffset.systemDefault());
+ String zoneOffset = localDateTime.getOffset().toString();
+
+ DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss O");
+ jsonObject.add("timeInUTC", new JsonPrimitive(utcDateTime.format(dateTimeFormatter)));
+ jsonObject.add("timeInLocalZone (UTC" + ("Z".equals(zoneOffset) ? "" : zoneOffset) + ")", new JsonPrimitive(localDateTime.format(dateTimeFormatter)));
+ } catch (DateTimeException | NumberFormatException ignored) {
+ }
+ }
+ }
+ return base64DecodedJson;
+ } catch (JsonParseException ignored) {
+ // failed to parse as json; leaving original string unmodified
+ }
+ }
+ return new JsonPrimitive(str);
} else if (nbtElement instanceof NBTTagList) {
NBTTagList nbtList = (NBTTagList) nbtElement;
JsonArray jsonArray = new JsonArray();
@@ -64,6 +134,13 @@ public final class GsonUtils {
jsonArray.add(nbtToJson(nbtList.get(tagId)));
}
return jsonArray;
+ } else if (nbtElement instanceof NBTTagIntArray) {
+ int[] intArray = ((NBTTagIntArray) nbtElement).getIntArray();
+ JsonArray jsonArray = new JsonArray();
+ for (int number : intArray) {
+ jsonArray.add(new JsonPrimitive(number));
+ }
+ return jsonArray;
} else if (nbtElement instanceof NBTTagCompound) {
NBTTagCompound nbtCompound = (NBTTagCompound) nbtElement;
JsonObject jsonObject = new JsonObject();
diff --git a/src/main/java/de/cowtipper/cowlection/util/ImageUtils.java b/src/main/java/de/cowtipper/cowlection/util/ImageUtils.java
index 69ee561..1d6820f 100644
--- a/src/main/java/de/cowtipper/cowlection/util/ImageUtils.java
+++ b/src/main/java/de/cowtipper/cowlection/util/ImageUtils.java
@@ -1,12 +1,20 @@
package de.cowtipper.cowlection.util;
import com.mojang.authlib.minecraft.MinecraftProfileTexture;
+import de.cowtipper.cowlection.Cowlection;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.ThreadDownloadImageData;
import net.minecraft.util.ResourceLocation;
+import net.minecraft.world.storage.MapData;
import net.minecraftforge.fml.relauncher.ReflectionHelper;
+import javax.imageio.ImageIO;
+import java.awt.*;
import java.awt.image.BufferedImage;
+import java.io.File;
+import java.io.IOException;
+import java.time.LocalDateTime;
+import java.time.format.DateTimeFormatter;
public class ImageUtils {
public static int getTierFromTexture(String minionSkinId) {
@@ -62,4 +70,128 @@ public class ImageUtils {
return ordinal();
}
}
+
+ private static final Color[] MAP_COLORS;
+
+ static {
+ // base colors: https://minecraft.gamepedia.com/Map_item_format?oldid=778280#Base_colors
+ MAP_COLORS = new Color[36];
+ MAP_COLORS[0] = new Color(0, 0, 0, 0);
+ MAP_COLORS[1] = new Color(125, 176, 55, 255);
+ MAP_COLORS[2] = new Color(244, 230, 161, 255);
+ MAP_COLORS[3] = new Color(197, 197, 197, 255);
+ MAP_COLORS[4] = new Color(252, 0, 0, 255);
+ MAP_COLORS[5] = new Color(158, 158, 252, 255);
+ MAP_COLORS[6] = new Color(165, 165, 165, 255);
+ MAP_COLORS[7] = new Color(0, 123, 0, 255);
+ MAP_COLORS[8] = new Color(252, 252, 252, 255);
+ MAP_COLORS[9] = new Color(162, 166, 182, 255);
+ MAP_COLORS[10] = new Color(149, 108, 76, 255);
+ MAP_COLORS[11] = new Color(111, 111, 111, 255);
+ MAP_COLORS[12] = new Color(63, 63, 252, 255);
+ MAP_COLORS[13] = new Color(141, 118, 71, 255);
+ MAP_COLORS[14] = new Color(252, 249, 242, 255);
+ MAP_COLORS[15] = new Color(213, 125, 50, 255);
+ MAP_COLORS[16] = new Color(176, 75, 213, 255);
+ MAP_COLORS[17] = new Color(101, 151, 213, 255);
+ MAP_COLORS[18] = new Color(226, 226, 50, 255);
+ MAP_COLORS[19] = new Color(125, 202, 25, 255);
+ MAP_COLORS[20] = new Color(239, 125, 163, 255);
+ MAP_COLORS[21] = new Color(75, 75, 75, 255);
+ MAP_COLORS[22] = new Color(151, 151, 151, 255);
+ MAP_COLORS[23] = new Color(75, 125, 151, 255);
+ MAP_COLORS[24] = new Color(125, 62, 176, 255);
+ MAP_COLORS[25] = new Color(50, 75, 176, 255);
+ MAP_COLORS[26] = new Color(101, 75, 50, 255);
+ MAP_COLORS[27] = new Color(101, 125, 50, 255);
+ MAP_COLORS[28] = new Color(151, 50, 50, 255);
+ MAP_COLORS[29] = new Color(25, 25, 25, 255);
+ MAP_COLORS[30] = new Color(247, 235, 76, 255);
+ MAP_COLORS[31] = new Color(91, 216, 210, 255);
+ MAP_COLORS[32] = new Color(73, 129, 252, 255);
+ MAP_COLORS[33] = new Color(0, 214, 57, 255);
+ MAP_COLORS[34] = new Color(127, 85, 48, 255);
+ MAP_COLORS[35] = new Color(111, 2, 0, 255);
+ }
+
+ public static File saveMapToFile(MapData mapData) {
+ int size = 128;
+ BufferedImage image = new BufferedImage(size, size, BufferedImage.TYPE_INT_ARGB);
+
+ int x = 0;
+ int y = 0;
+ for (int i = 0; i < mapData.colors.length; i++) {
+ Color pixelColor = colorIdToColor(mapData.colors[i]);
+ image.setRGB(x, y, pixelColor.getRGB());
+ ++x;
+ if (x >= size) {
+ // new line
+ ++y;
+ x = 0;
+ }
+ }
+ try {
+ File cowlectionImagePath = new File(Minecraft.getMinecraft().mcDataDir, "cowlection_images");
+ if (!cowlectionImagePath.exists() && !cowlectionImagePath.mkdirs()) {
+ // dir didn't exist and couldn't be created
+ return null;
+ }
+ File imageFile = getTimestampedPngFileForDirectory(cowlectionImagePath, "map");
+ ImageIO.write(image, "png", imageFile);
+ return imageFile.getCanonicalFile();
+ } catch (IOException e) {
+ // couldn't save map image
+ e.printStackTrace();
+ return null;
+ }
+ }
+
+ private static Color colorIdToColor(byte rawId) {
+ int id = rawId & 255;
+ int baseId = id / 4;
+ int shadeId = id & 3;
+
+ if (baseId >= MAP_COLORS.length) {
+ Cowlection.getInstance().getLogger().warn("Unknown base color id " + baseId + " (id=" + id + ")");
+ return new Color(0xf700d5);
+ }
+
+ Color c = MAP_COLORS[baseId];
+ int shadeMul;
+ switch (shadeId) {
+ case 0:
+ shadeMul = 180;
+ break;
+ case 1:
+ shadeMul = 220;
+ break;
+ case 2:
+ shadeMul = 255;
+ break;
+ case 3:
+ shadeMul = 135;
+ break;
+ default:
+ shadeMul = 180;
+ Cowlection.getInstance().getLogger().warn("Unknown shade id " + shadeId + " (raw: " + id + ")");
+ c = new Color(0xf700d5);
+ }
+ return new Color((shadeMul * c.getRed()) / 255, (shadeMul * c.getGreen()) / 255, (shadeMul * c.getBlue()) / 255, c.getAlpha());
+ }
+
+ /**
+ * Based on ScreenShotHelper#getTimestampedPNGFileForDirectory
+ */
+ private static File getTimestampedPngFileForDirectory(File directory, String prefix) {
+ String currentDateTime = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd_HH.mm.ss"));
+ int i = 1;
+
+ while (true) {
+ File timestampedFile = new File(directory, prefix + "_" + currentDateTime + (i == 1 ? "" : "_" + i) + ".png");
+ if (!timestampedFile.exists()) {
+ return timestampedFile;
+ }
+ ++i;
+ }
+ }
}
diff --git a/src/main/java/de/cowtipper/cowlection/util/MooChatComponent.java b/src/main/java/de/cowtipper/cowlection/util/MooChatComponent.java
index 95415d3..856cbb3 100644
--- a/src/main/java/de/cowtipper/cowlection/util/MooChatComponent.java
+++ b/src/main/java/de/cowtipper/cowlection/util/MooChatComponent.java
@@ -6,6 +6,9 @@ import net.minecraft.util.ChatComponentText;
import net.minecraft.util.EnumChatFormatting;
import net.minecraft.util.IChatComponent;
+import java.io.File;
+
+@SuppressWarnings("unused")
public class MooChatComponent extends ChatComponentText {
public MooChatComponent(String msg) {
super(msg);
@@ -127,13 +130,11 @@ public class MooChatComponent extends ChatComponentText {
}
public MooChatComponent setUrl(String url) {
- setUrl(url, new KeyValueTooltipComponent("Click to visit", url));
- return this;
+ return setUrl(url, new KeyValueTooltipComponent("Click to visit", url));
}
public MooChatComponent setUrl(String url, String hover) {
- setUrl(url, new MooChatComponent(hover).yellow());
- return this;
+ return setUrl(url, new MooChatComponent(hover).yellow());
}
public MooChatComponent setUrl(String url, IChatComponent hover) {
@@ -142,6 +143,12 @@ public class MooChatComponent extends ChatComponentText {
return this;
}
+ public MooChatComponent setOpenFile(File filePath) {
+ setChatStyle(getChatStyle().setChatClickEvent(new ClickEvent(ClickEvent.Action.OPEN_FILE, filePath.getAbsolutePath())));
+ setHover(new MooChatComponent(filePath.isFile() ? "Open " + filePath.getName() : "Open folder: " + filePath.toString()).yellow());
+ return this;
+ }
+
public MooChatComponent setSuggestCommand(String command) {
setSuggestCommand(command, true);
return this;
@@ -155,6 +162,12 @@ public class MooChatComponent extends ChatComponentText {
return this;
}
+ @Override
+ public MooChatComponent appendSibling(IChatComponent component) {
+ super.appendSibling(component);
+ return this;
+ }
+
/**
* Appends the given component in a new line, without inheriting formatting of previous siblings.
*