diff --git a/src/de/steamwar/lobby/LobbySystem.java b/src/de/steamwar/lobby/LobbySystem.java
index 9ebcd3a..3f0badd 100644
--- a/src/de/steamwar/lobby/LobbySystem.java
+++ b/src/de/steamwar/lobby/LobbySystem.java
@@ -19,11 +19,12 @@
package de.steamwar.lobby;
-import de.steamwar.lobby.command.ModifyCommand;
import de.steamwar.lobby.command.FlyCommand;
import de.steamwar.lobby.command.HologramCommand;
+import de.steamwar.lobby.command.ModifyCommand;
import de.steamwar.lobby.command.PortalCommand;
import de.steamwar.lobby.listener.*;
+import de.steamwar.lobby.map.CustomMap;
import de.steamwar.lobby.team.TeamPlayer;
import de.steamwar.message.Message;
import org.bukkit.plugin.java.JavaPlugin;
@@ -67,6 +68,7 @@ public class LobbySystem extends JavaPlugin {
new AlphaWall(l -> l.getZ() > 892, AlphaWall.REFLECT_Z);
new AlphaWall(l -> l.getZ() < 1794, AlphaWall.REFLECT_Z);
+ CustomMap.init();
}
@Override
diff --git a/src/de/steamwar/lobby/map/CustomMap.java b/src/de/steamwar/lobby/map/CustomMap.java
new file mode 100644
index 0000000..24bc598
--- /dev/null
+++ b/src/de/steamwar/lobby/map/CustomMap.java
@@ -0,0 +1,189 @@
+/*
+ * This file is a part of the SteamWar software.
+ *
+ * Copyright (C) 2022 SteamWar.de-Serverteam
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+package de.steamwar.lobby.map;
+
+import org.bukkit.map.MapPalette;
+
+import javax.imageio.ImageIO;
+import java.awt.*;
+import java.awt.image.BufferedImage;
+import java.io.File;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.stream.Collectors;
+
+public class CustomMap {
+
+ private static List colorList = new ArrayList<>();
+
+ private static Color c(int r, int g, int b) {
+ return new Color(r, g, b);
+ }
+
+ static {
+ try {
+ BufferedImage bufferedImage = ImageIO.read(CustomMap.class.getResourceAsStream("MapColors.png"));
+ for (int x = 0; x < bufferedImage.getWidth(); x += 16) {
+ for (int y = 0; y < bufferedImage.getHeight(); y += 16) {
+ colorList.add(new Color(bufferedImage.getRGB(x, y)));
+ }
+ }
+ new CustomMap(ImageIO.read(CustomMap.class.getResourceAsStream("wgsbanner13.png")));
+ } catch (Exception e) {
+ throw new SecurityException(e.getMessage(), e);
+ }
+ }
+
+ public static void init() {
+ }
+
+ private List tileImages = new ArrayList<>();
+
+ public CustomMap(BufferedImage image) {
+ if (image.getWidth() % 128 != 0) {
+ throw new IllegalArgumentException("Image width must be a multiple of 128");
+ }
+ if (image.getHeight() % 128 != 0) {
+ throw new IllegalArgumentException("Image height must be a multiple of 128");
+ }
+
+ BufferedImage bufferedImage = new BufferedImage(image.getWidth(), image.getHeight(), BufferedImage.TYPE_INT_RGB);
+ for (int x = 0; x < image.getWidth(); x++) {
+ for (int y = 0; y < image.getHeight(); y++) {
+ Color color = new Color(image.getRGB(x, y));
+ Color nearest = getNearest(color, false);
+ if (nearest == null) {
+ throw new IllegalArgumentException("Image contains invalid color: " + color);
+ }
+ bufferedImage.setRGB(x, y, nearest.getRGB());
+ }
+ }
+ for (int x = 1; x < bufferedImage.getWidth() - 1; x++) {
+ for (int y = 1; y < bufferedImage.getHeight() - 1; y++) {
+ Color toMatch = new Color(image.getRGB(x, y));
+ List current = new ArrayList<>();
+ current.add(new Color(bufferedImage.getRGB(x, y - 1)));
+ current.add(new Color(bufferedImage.getRGB(x - 1, y)));
+ current.add(new Color(bufferedImage.getRGB(x, y)));
+ current.add(new Color(bufferedImage.getRGB(x + 1, y)));
+ current.add(new Color(bufferedImage.getRGB(x, y + 1)));
+
+ List currentNearest = current.stream().map(c -> getNearest(c, true)).collect(Collectors.toList());
+
+ double min = Double.MAX_VALUE;
+ List minNearest = null;
+ for (int i = 0; i < 1 << current.size(); i++) {
+ List currentAverage = new ArrayList<>();
+ for (int j = 0; j < current.size(); j++) {
+ if ((i & (1 << j)) == 0) {
+ currentAverage.add(current.get(j));
+ } else {
+ currentAverage.add(currentNearest.get(j));
+ }
+ }
+ Color average = getAverage(currentAverage);
+ double distance = colorDistance(average, toMatch);
+ if (distance < min) {
+ min = distance;
+ minNearest = currentAverage;
+ }
+ }
+
+ if (minNearest == null) {
+ continue;
+ }
+ bufferedImage.setRGB(x, y - 1, minNearest.get(0).getRGB());
+ bufferedImage.setRGB(x - 1, y, minNearest.get(1).getRGB());
+ bufferedImage.setRGB(x, y, minNearest.get(2).getRGB());
+ bufferedImage.setRGB(x + 1, y, minNearest.get(3).getRGB());
+ bufferedImage.setRGB(x, y + 1, minNearest.get(4).getRGB());
+ }
+ }
+
+ for (int x = 0; x < bufferedImage.getWidth(); x += 128) {
+ for (int y = 0; y < bufferedImage.getHeight(); y += 128) {
+ BufferedImage subImage = bufferedImage.getSubimage(x, y, 128, 128);
+ TileImage tileImage = new TileImage(subImage, x / 128, y / 128);
+ tileImages.add(tileImage);
+ }
+ }
+
+ try {
+ ImageIO.write(bufferedImage, "png", new File("/home/minecraft/server/NeueLobby/Lobby/map.png"));
+ } catch (Exception e) {
+ throw new SecurityException(e.getMessage(), e);
+ }
+ }
+
+ private static Color getAverage(List colors) {
+ int r = 0;
+ int g = 0;
+ int b = 0;
+ for (Color color : colors) {
+ r += color.getRed();
+ g += color.getGreen();
+ b += color.getBlue();
+ }
+ return new Color(r / colors.size(), g / colors.size(), b / colors.size());
+ }
+
+ private static Color getNearest(Color color, boolean notSame) {
+ if (!notSame) {
+ return MapPalette.getColor(MapPalette.matchColor(color));
+ }
+
+ double min = Double.MAX_VALUE;
+ Color nearest = null;
+ for (Color c : colorList) {
+ double distance = colorDistance(color, c);
+ if (c.equals(color)) {
+ continue;
+ }
+ if (distance < min) {
+ min = distance;
+ nearest = c;
+ }
+ }
+ return nearest;
+ }
+
+ private static double colorDistance(Color c1, Color c2) {
+ double rmean = (double)(c1.getRed() + c2.getRed()) / 2.0D;
+ double r = (double)(c1.getRed() - c2.getRed());
+ double g = (double)(c1.getGreen() - c2.getGreen());
+ int b = c1.getBlue() - c2.getBlue();
+ double weightR = 2.0D + rmean / 256.0D;
+ double weightG = 4.0D;
+ double weightB = 2.0D + (255.0D - rmean) / 256.0D;
+ return weightR * r * r + weightG * g * g + weightB * (double)b * (double)b;
+ }
+
+ private static class TileImage {
+ private BufferedImage image;
+ private int tileX;
+ private int tileY;
+
+ public TileImage(BufferedImage image, int tileX, int tileY) {
+ this.image = image;
+ this.tileX = tileX;
+ this.tileY = tileY;
+ }
+ }
+}
diff --git a/src/de/steamwar/lobby/map/MapColors.png b/src/de/steamwar/lobby/map/MapColors.png
new file mode 100644
index 0000000..5e44d49
Binary files /dev/null and b/src/de/steamwar/lobby/map/MapColors.png differ