Skip to content

Commit

Permalink
Color maps
Browse files Browse the repository at this point in the history
  • Loading branch information
cerus committed Aug 30, 2022
1 parent 67c2ff4 commit e39911a
Show file tree
Hide file tree
Showing 20 changed files with 848 additions and 26 deletions.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ See [FAQ](#FAQ)
<dependency>
<groupId>dev.cerus.maps</groupId>
<artifactId>common</artifactId>
<version>3.1.0</version>
<version>3.2.0</version>
<scope>provided</scope> <!-- "provided" if the maps plugin is on the server, "compile" if not -->
</dependency>

Expand All @@ -56,7 +56,7 @@ See [FAQ](#FAQ)
<dependency>
<groupId>dev.cerus.maps</groupId>
<artifactId>plugin</artifactId>
<version>3.1.0</version>
<version>3.2.0</version>
<scope>provided</scope>
</dependency>
</dependencies>
Expand Down
2 changes: 1 addition & 1 deletion bukkit-16_R3/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
<parent>
<artifactId>parent</artifactId>
<groupId>dev.cerus.maps</groupId>
<version>3.1.0</version>
<version>3.2.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>

Expand Down
2 changes: 1 addition & 1 deletion bukkit-17_R1/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
<parent>
<artifactId>parent</artifactId>
<groupId>dev.cerus.maps</groupId>
<version>3.1.0</version>
<version>3.2.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>

Expand Down
2 changes: 1 addition & 1 deletion bukkit-18_R1/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
<parent>
<artifactId>parent</artifactId>
<groupId>dev.cerus.maps</groupId>
<version>3.1.0</version>
<version>3.2.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>

Expand Down
2 changes: 1 addition & 1 deletion bukkit-18_R2/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
<parent>
<artifactId>parent</artifactId>
<groupId>dev.cerus.maps</groupId>
<version>3.1.0</version>
<version>3.2.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>

Expand Down
2 changes: 1 addition & 1 deletion bukkit-19_R1/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
<parent>
<artifactId>parent</artifactId>
<groupId>dev.cerus.maps</groupId>
<version>3.1.0</version>
<version>3.2.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>

Expand Down
2 changes: 1 addition & 1 deletion common/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
<parent>
<artifactId>parent</artifactId>
<groupId>dev.cerus.maps</groupId>
<version>3.1.0</version>
<version>3.2.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>

Expand Down
3 changes: 3 additions & 0 deletions common/src/main/java/dev/cerus/maps/api/MapColor.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,10 @@
* Color data pulled from the Minecraft wiki
* <p>
* I tried to name the colors as good as possible but the naming still kind of sucks, I'm sorry
*
* @deprecated Use {@link dev.cerus.maps.api.colormap.ColorMap} and {@link dev.cerus.maps.api.colormap.ColorMaps} instead
*/
@Deprecated
public enum MapColor {

TRANSPARENT_0(0, null),
Expand Down
110 changes: 110 additions & 0 deletions common/src/main/java/dev/cerus/maps/api/colormap/ColorMap.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
package dev.cerus.maps.api.colormap;

import java.util.Arrays;
import java.util.Comparator;
import java.util.Objects;
import java.util.Optional;

/**
* A container for map colors
*/
public class ColorMap {

// Color array, capped at 256 because that's the maximum amount of possible colors at the moment
private final Color[] colors = new Color[256];

public void putColor(final Color color) {
this.colors[this.b2i(color.mapColor)] = color;
}

/**
* Find color by id
*
* @param id Map color id
*
* @return Color or null
*/
public Color fromId(final int id) {
return this.getById(id);
}

/**
* Find color by id
*
* @param id Map color id
*
* @return Color or null
*/
public Color getById(int id) {
id = this.b2i(id);
return (id < 0 || id >= this.colors.length) ? null : this.colors[id];
}

/**
* Find java color by id
*
* @param color Map color id
*
* @return Java color or java color id 0 (or null)
*/
public java.awt.Color mapColorToRgb(final byte color) {
return Optional.ofNullable(this.getById(color)).map(c -> c.javaColor)
.orElse(Optional.ofNullable(getById(0)).map(c -> c.javaColor)
.orElse(null));
}

/**
* Find color by RGB
*
* @param r Red
* @param g Green
* @param b Blue
*
* @return Color or transparent color (0) (or null)
*/
public Color rgbToMapColor(final int r, final int g, final int b) {
return Arrays.stream(this.colors)
.filter(Objects::nonNull)
.filter(color -> color.mapColor() > 3)
.min(Comparator.comparingDouble(value -> this.calcDist(value, r, g, b)))
.orElse(this.getById(0));
}

private double calcDist(final Color clr, final int r, final int g, final int b) {
final java.awt.Color color = clr.javaColor();
return Math.sqrt(Math.pow(r - color.getRed(), 2) + Math.pow(g - color.getGreen(), 2) + Math.pow(b - color.getBlue(), 2));
}

private int b2i(int b) {
if (b < 0) {
b += 256;
}
return b;
}

public Color[] getColors() {
return this.colors;
}

public record Color(byte mapColor, java.awt.Color javaColor) {

@Override
public boolean equals(final Object o) {
if (this == o) {
return true;
}
if (o == null || this.getClass() != o.getClass()) {
return false;
}
final Color color = (Color) o;
return this.mapColor() == color.mapColor() && Objects.equals(this.javaColor(), color.javaColor());
}

@Override
public int hashCode() {
return Objects.hash(this.mapColor(), this.javaColor());
}

}

}
117 changes: 117 additions & 0 deletions common/src/main/java/dev/cerus/maps/api/colormap/ColorMaps.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
package dev.cerus.maps.api.colormap;

import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import java.awt.Color;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.Map;
import org.bukkit.Bukkit;

/**
* Utility class for color maps
*/
public class ColorMaps {

private static final ColorVersion FALLBACK = ColorVersion.MC_1_12;
private static final ColorMap latest = newColorMap(ColorVersion.latest());
private static final ColorMap current = newColorMap(determineVersion());

private ColorMaps() {
}

/**
* Get a color map for the latest Minecraft version
*
* @return Color map for latest version
*/
public static ColorMap latest() {
return latest;
}

/**
* Get a color map for the Minecraft version this server is running
*
* @return Color map for current version
*/
public static ColorMap current() {
return current;
}

/**
* Get a new color map for the specified color version
*
* @param version The version
*
* @return A new color map
*/
public static ColorMap newColorMap(final ColorVersion version) {
final ColorMap colorMap = new ColorMap();
if (version == ColorVersion.latest()) {
// Load colors from jar
try (final InputStream in = ColorMaps.class.getClassLoader().getResourceAsStream("latest_colors.json");
final InputStreamReader reader = new InputStreamReader(in)) {
final JsonObject obj = new JsonParser().parse(reader).getAsJsonObject();
for (final Map.Entry<String, JsonElement> entry : obj.entrySet()) {
final int baseId = Integer.parseInt(entry.getKey());
final JsonObject item = entry.getValue().getAsJsonObject();
final JsonArray colors = item.getAsJsonArray("colors");

int i = 0;
for (final JsonElement element : colors) {
final int colorRaw = element.getAsInt();
colorMap.putColor(new ColorMap.Color(
(byte) (baseId * 4 + i++),
new Color(colorRaw, false)
));
}
}
} catch (final IOException | NullPointerException e) {
System.err.println("Failed to load colors");
}
} else if (latest != null) {
// Copy the colors from the latest color map
for (final ColorMap.Color color : latest.getColors()) {
if (color != null && ((int) color.mapColor()) / 4 <= version.getLastId()) {
colorMap.putColor(color);
}
}
}
return colorMap;
}

/**
* Determine an appropriate color version for this server
*
* @return A color version
*/
public static ColorVersion determineVersion() {
String version = Bukkit.getVersion();
version = version.substring(version.indexOf("MC:") + 4, version.length() - 1).trim();
if (!version.matches("\\d+\\.\\d+(\\.\\d+)")) {
return FALLBACK;
}

final String[] split = version.split("\\.");
final int major = Integer.parseInt(split[0]);
final int minor = Integer.parseInt(split[1]);
if (major != 1) {
// FUTUREEEEE
return FALLBACK;
}
if (minor < 12) {
return ColorVersion.MC_1_8;
} else if (minor < 16) {
return ColorVersion.MC_1_12;
} else if (minor < 17) {
return ColorVersion.MC_1_16;
} else {
return ColorVersion.MC_1_17;
}
}


}
24 changes: 24 additions & 0 deletions common/src/main/java/dev/cerus/maps/api/colormap/ColorVersion.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package dev.cerus.maps.api.colormap;

public enum ColorVersion {

MC_1_8(35),
MC_1_12(51),
MC_1_16(58),
MC_1_17(61);

private final int lastId;

ColorVersion(final int lastId) {
this.lastId = lastId;
}

public static ColorVersion latest() {
return MC_1_17;
}

public int getLastId() {
return this.lastId;
}

}
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package dev.cerus.maps.api.graphics;

import dev.cerus.maps.api.MapColor;
import dev.cerus.maps.api.colormap.ColorMaps;
import java.awt.Color;

/**
Expand Down Expand Up @@ -28,7 +28,8 @@ private ColorCache() {
public static byte rgbToMap(final int r, final int g, final int b) {
final int index = new Color(r, g, b, 0).getRGB();
if (mappedColors[index] == 0) {
mappedColors[index] = (byte) MapColor.rgbToMapColor(r, g, b).getId();
//mappedColors[index] = (byte) MapColor.rgbToMapColor(r, g, b).getId();
mappedColors[index] = ColorMaps.current().rgbToMapColor(r, g, b).mapColor();
}
return mappedColors[index];
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package dev.cerus.maps.api.graphics;

import dev.cerus.maps.api.MapColor;
import dev.cerus.maps.api.colormap.ColorMaps;
import dev.cerus.maps.api.graphics.filter.BoxBlurFilter;
import dev.cerus.maps.api.graphics.filter.Filter;
import dev.cerus.maps.api.graphics.filter.GrayscaleFilter;
Expand Down Expand Up @@ -847,8 +847,10 @@ protected byte calculateComposite(final byte source, final byte dest, final floa
}

return CompositeColorCache.getCompositeOrCompute(source, dest, alpha, () -> {
final Color newColor = MapColor.mapColorToRgb(source);
final Color oldColor = MapColor.mapColorToRgb(dest);
//final Color newColor = MapColor.mapColorToRgb(source);
//final Color oldColor = MapColor.mapColorToRgb(dest);
final Color newColor = ColorMaps.current().mapColorToRgb(source);
final Color oldColor = ColorMaps.current().mapColorToRgb(dest);
final int[] compositedColor = new int[] {
this.composite(newColor.getRed(), oldColor.getRed(), alpha),
this.composite(newColor.getGreen(), oldColor.getGreen(), alpha),
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package dev.cerus.maps.api.graphics.filter;

import dev.cerus.maps.api.MapColor;
import dev.cerus.maps.api.colormap.ColorMaps;
import dev.cerus.maps.api.graphics.ColorCache;
import dev.cerus.maps.api.graphics.MapGraphics;
import java.awt.Color;
Expand Down Expand Up @@ -86,7 +86,8 @@ private int mapToRgb(final byte color) {
throw new KeepOriginalSignal();
}
}
return MapColor.mapColorToRgb(color).getRGB();
//return MapColor.mapColorToRgb(color).getRGB();
return ColorMaps.current().mapColorToRgb(color).getRGB();
}

@Override
Expand Down
Loading

0 comments on commit e39911a

Please sign in to comment.