Yatopia/patches/api/0011-Optimise-Bukkit-s-MapPalette.patch
Ivan Pekov f1ed22d699
In its best "broken" state
color lighting still isn't right. I've returned the getDistance calls to the double one, as it is more acruate.
there is some improvement from changing the getDistance calls tho.
2020-12-27 10:57:55 +02:00

153 lines
6.4 KiB
Diff

From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: epserv <admin@epserv.ru>
Date: Mon, 21 Dec 2020 23:12:15 +0500
Subject: [PATCH] Optimise Bukkit's MapPalette
diff --git a/src/main/java/org/bukkit/map/MapPalette.java b/src/main/java/org/bukkit/map/MapPalette.java
index 95fe3f4d081053a6cf484e4ef07b474f2dc2ab02..839a833ed4efe2de9c08c31697d20fb4e18f0f78 100644
--- a/src/main/java/org/bukkit/map/MapPalette.java
+++ b/src/main/java/org/bukkit/map/MapPalette.java
@@ -23,6 +23,8 @@ public final class MapPalette {
}
private static double getDistance(@NotNull Color c1, @NotNull Color c2) {
+ // Yatopia start - faster method
+ /*
double rmean = (c1.getRed() + c2.getRed()) / 2.0;
double r = c1.getRed() - c2.getRed();
double g = c1.getGreen() - c2.getGreen();
@@ -31,6 +33,17 @@ public final class MapPalette {
double weightG = 4.0;
double weightB = 2 + (255 - rmean) / 256.0;
return weightR * r * r + weightG * g * g + weightB * b * b;
+ */
+ if (c1.getRGB() == c2.getRGB()) { // check if colors are same
+ return 0;
+ }
+ int r = c1.getRed() - c2.getRed(),
+ g = c1.getGreen() - c2.getGreen(),
+ b = c1.getBlue() - c2.getBlue();
+ // (x1 - x2)^2 + (y1 - y2)^2 + (z1 - z2)^2 formula
+ // but with colors. red is x, green is y, blue is z
+ return Math.sqrt(r * r + g * g + b * b);
+ // Yatopia end
}
@NotNull
@@ -95,6 +108,51 @@ public final class MapPalette {
c(60, 31, 43), c(74, 37, 53), c(86, 44, 62), c(45, 23, 32),
c(14, 127, 93), c(17, 155, 114), c(20, 180, 133), c(10, 95, 70)
};
+ // Yatopia start
+ @NotNull
+ private static final int[] modifiers = {180, 220, 255, 135}; // vanilla color modifiers
+ @NotNull
+ static Color[] vanillaColors; // vanilla colors
+ @NotNull
+ static Color[][] doubleColors; // two-dimensional array where doubleColors[index] is an array of possible modifications of vanillaColors[index]
+ @NotNull
+ static int[] rgbColors; // an array of rgb values of each color
+
+ static {
+ // getting an array of rgb values of each color
+ rgbColors = java.util.Arrays.stream(colors).mapToInt(Color::getRGB).toArray();
+
+ try {
+ Class<?> materialMapColorClass = MapPalette.class.getClassLoader().loadClass("net.minecraft.server.MaterialMapColor");
+ Object[] vanillaColorObjects = (Object[]) java.util.Arrays.stream(materialMapColorClass.getFields()).filter(f -> f.getType().isArray() && f.getType().getComponentType().equals(materialMapColorClass)).findAny().get().get(null);
+ // get MaterialMapColor.rgb instance field
+ java.lang.reflect.Field rgbField = materialMapColorClass.getDeclaredField("rgb");
+ rgbField.setAccessible(true);
+ // get vanilla colors array as java.awt.Color instances array
+ vanillaColors = java.util.Arrays.stream(vanillaColorObjects).filter(java.util.Objects::nonNull).mapToInt(objColor -> {
+ try {
+ return rgbField.getInt(materialMapColorClass.cast(objColor));
+ } catch (Exception ex) {
+ throw new RuntimeException(ex);
+ }
+ }).mapToObj(Color::new).toArray(Color[]::new);
+ // get two-dimensional array where doubleColors[index] is an array of possible modifications of vanillaColors[index]
+ doubleColors = new Color[vanillaColors.length][modifiers.length];
+ for (int i = 0; i < vanillaColors.length; i++) {
+ Color vanillaColor = vanillaColors[i];
+ for (int j = 0; j < modifiers.length; j++) {
+ int modifier = modifiers[j];
+ int mr = (vanillaColor.getRed() * modifier) / 255;
+ int mg = (vanillaColor.getGreen() * modifier) / 255;
+ int mb = (vanillaColor.getBlue() * modifier) / 255;
+ doubleColors[i][j] = c(mr, mg, mb);
+ }
+ }
+ } catch (Exception ex) {
+ throw new RuntimeException(ex);
+ }
+ }
+ // Yatopia end
// Interface
/**
@@ -238,6 +296,8 @@ public final class MapPalette {
int index = 0;
double best = -1;
+ // Yatopia start - foreach a maximum of 62 colors instead of 236 per pixel
+ /*
for (int i = 4; i < colors.length; i++) {
double distance = getDistance(color, colors[i]);
if (distance < best || best == -1) {
@@ -245,9 +305,43 @@ public final class MapPalette {
index = i;
}
}
+ */
+ for (int i = 0; i < vanillaColors.length; i++) {
+ double distance = getDistance(color, vanillaColors[i]);
+ if (distance == 0) {
+ index = i;
+ best = 0;
+ break;
+ }
+ if (distance < best || best == -1) {
+ best = distance;
+ index = i;
+ }
+ }
+
+ if (best == 0) {
+ index = com.google.common.primitives.Ints.indexOf(rgbColors, vanillaColors[index].getRGB());
+ return (byte) (index < 128 ? index : index - 256);
+ }
+
+ Color[] modColors = doubleColors[index];
+ best = -1;
+ for (int i = 0; i < modColors.length; i++) {
+ double distance = getDistance(color, modColors[i]);
+ if (distance == 0) {
+ index = i;
+ break;
+ }
+ if (distance < best || best == -1) {
+ best = distance;
+ index = i;
+ }
+ }
+ index = com.google.common.primitives.Ints.indexOf(rgbColors, modColors[index].getRGB());
+ // Yatopia end
// Minecraft has 143 colors, some of which have negative byte representations
- return (byte) (index < 128 ? index : -129 + (index - 127));
+ return (byte) (index < 128 ? index : index - 256); // Yatopia
}
/**
@@ -260,7 +354,7 @@ public final class MapPalette {
@Deprecated
@NotNull
public static Color getColor(byte index) {
- if ((index > -21 && index < 0) || index > 127) {
+ if (index > -21 && index < 0) { // Yatopia
throw new IndexOutOfBoundsException();
} else {
// Minecraft has 143 colors, some of which have negative byte representations