From c7c49b43b21fb89a96d1d934fb747a9a821f1d0b Mon Sep 17 00:00:00 2001 From: yoyosource Date: Wed, 17 Jul 2024 21:13:24 +0200 Subject: [PATCH] Updating CustomMap --- src/de/steamwar/lobby/LobbySystem.java | 6 +- src/de/steamwar/lobby/map/CustomMap.java | 392 ++++++++++++++---- .../steamwar/lobby/map/CustomMapCommand.java | 73 ---- src/de/steamwar/lobby/map/CustomMapNew.java | 354 ---------------- 4 files changed, 321 insertions(+), 504 deletions(-) delete mode 100644 src/de/steamwar/lobby/map/CustomMapCommand.java delete mode 100644 src/de/steamwar/lobby/map/CustomMapNew.java diff --git a/src/de/steamwar/lobby/LobbySystem.java b/src/de/steamwar/lobby/LobbySystem.java index aab6a57..4d198d4 100644 --- a/src/de/steamwar/lobby/LobbySystem.java +++ b/src/de/steamwar/lobby/LobbySystem.java @@ -27,8 +27,7 @@ import de.steamwar.lobby.command.PortalCommand; import de.steamwar.lobby.jumpandrun.JumpAndRun; import de.steamwar.lobby.jumpandrun.JumpAndRunCommand; import de.steamwar.lobby.listener.*; -import de.steamwar.lobby.map.CustomMapCommand; -import de.steamwar.lobby.map.CustomMapNew; +import de.steamwar.lobby.map.CustomMap; import de.steamwar.lobby.particle.ParticleListener; import de.steamwar.lobby.special.advent.AdventsCalendar; import de.steamwar.lobby.team.TeamPlayer; @@ -54,7 +53,7 @@ public class LobbySystem extends JavaPlugin { entityServer = new REntityServer(); debugEntityServer = new REntityServer(); - CustomMapNew.init(); + CustomMap.init(); Fightserver.init(); new Portals(); @@ -62,7 +61,6 @@ public class LobbySystem extends JavaPlugin { new HologramCommand(); new FlyCommand(); new ModifyCommand(); - new CustomMapCommand(); new JumpAndRun(); new JumpAndRunCommand(); diff --git a/src/de/steamwar/lobby/map/CustomMap.java b/src/de/steamwar/lobby/map/CustomMap.java index 0e9885e..4e7d859 100644 --- a/src/de/steamwar/lobby/map/CustomMap.java +++ b/src/de/steamwar/lobby/map/CustomMap.java @@ -1,110 +1,356 @@ /* - * This file is a part of the SteamWar software. + * This file is a part of the SteamWar software. * - * Copyright (C) 2022 SteamWar.de-Serverteam + * Copyright (C) 2024 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 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. + * 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 . + * 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 net.minecraft.world.level.saveddata.maps.WorldMap; +import de.steamwar.lobby.LobbySystem; import org.bukkit.Bukkit; import org.bukkit.Material; -import org.bukkit.craftbukkit.v1_20_R1.map.CraftMapView; +import org.bukkit.entity.Entity; +import org.bukkit.entity.ItemFrame; import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.world.ChunkLoadEvent; import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.meta.MapMeta; +import org.bukkit.map.MapCanvas; import org.bukkit.map.MapPalette; +import org.bukkit.map.MapRenderer; +import org.bukkit.map.MapView; +import org.bukkit.util.Vector; +import javax.imageio.ImageIO; import java.awt.*; import java.awt.image.BufferedImage; -import java.lang.reflect.Field; +import java.awt.image.WritableRaster; +import java.io.File; +import java.io.IOException; +import java.util.*; -public class CustomMap { +public class CustomMap implements Listener { - public CustomMap(Player player, 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"); + public static void init() { + } + + private static final CustomMap LEFT = new CustomMap(new File(System.getProperty("user.home") + "/lobbyBanner/left.png"), + new Vector(2346, 48, 1297), new Vector(2345, 48, 1297), new Vector(2344, 48, 1297), new Vector(2343, 48, 1297), new Vector(2342, 48, 1297), new Vector(2341, 48, 1297), new Vector(2340, 48, 1297), + new Vector(2346, 47, 1297), new Vector(2345, 47, 1297), new Vector(2344, 47, 1297), new Vector(2343, 47, 1297), new Vector(2342, 47, 1297), new Vector(2341, 47, 1297), new Vector(2340, 47, 1297), + new Vector(2346, 46, 1297), new Vector(2345, 46, 1297), new Vector(2344, 46, 1297), new Vector(2343, 46, 1297), new Vector(2342, 46, 1297), new Vector(2341, 46, 1297), new Vector(2340, 46, 1297), + new Vector(2346, 45, 1297), new Vector(2345, 45, 1297), new Vector(2344, 45, 1297), new Vector(2343, 45, 1297), new Vector(2342, 45, 1297), new Vector(2341, 45, 1297), new Vector(2340, 45, 1297) + ); + + private static final CustomMap RIGHT = new CustomMap(new File(System.getProperty("user.home") + "/lobbyBanner/right.png"), + new Vector(2330, 48, 1297), new Vector(2329, 48, 1297), new Vector(2328, 48, 1297), new Vector(2327, 48, 1297), new Vector(2326, 48, 1297), new Vector(2325, 48, 1297), new Vector(2324, 48, 1297), + new Vector(2330, 47, 1297), new Vector(2329, 47, 1297), new Vector(2328, 47, 1297), new Vector(2327, 47, 1297), new Vector(2326, 47, 1297), new Vector(2325, 47, 1297), new Vector(2324, 47, 1297), + new Vector(2330, 46, 1297), new Vector(2329, 46, 1297), new Vector(2328, 46, 1297), new Vector(2327, 46, 1297), new Vector(2326, 46, 1297), new Vector(2325, 46, 1297), new Vector(2324, 46, 1297), + new Vector(2330, 45, 1297), new Vector(2329, 45, 1297), new Vector(2328, 45, 1297), new Vector(2327, 45, 1297), new Vector(2326, 45, 1297), new Vector(2325, 45, 1297), new Vector(2324, 45, 1297) + ); + + private File mapFile; + private Map itemFrameIndex = new HashMap<>(); + private ItemFrame[] itemFrames; + private long lastModified = Long.MAX_VALUE; + + public CustomMap(File mapFile, Vector... itemFrames) { + this.mapFile = mapFile; + this.itemFrames = new ItemFrame[itemFrames.length]; + for (int i = 0; i < itemFrames.length; i++) { + itemFrameIndex.put(itemFrames[i], i); } - BufferedImage bufferedImage = new BufferedImage(image.getWidth(), image.getHeight(), BufferedImage.TYPE_INT_RGB); - for (int y = 0; y < image.getHeight(); y++) { - for (int x = 0; x < image.getWidth(); x++) { - Color oldPixel = new Color(image.getRGB(x, y)); - Color newPixel = getNearest(oldPixel); - bufferedImage.setRGB(x, y, newPixel.getRGB()); - int quantErrorRed = oldPixel.getRed() - newPixel.getRed(); - int quantErrorGreen = oldPixel.getGreen() - newPixel.getGreen(); - int quantErrorBlue = oldPixel.getBlue() - newPixel.getBlue(); - if (x < image.getWidth() - 1) { - image.setRGB(x + 1, y, updateViaQuantError(new Color(image.getRGB(x + 1, y)), quantErrorRed, quantErrorGreen, quantErrorBlue, 7 / 16.0).getRGB()); - } - if (x > 0) { - image.setRGB(x - 1, y, updateViaQuantError(new Color(image.getRGB(x - 1, y)), quantErrorRed, quantErrorGreen, quantErrorBlue, 3 / 16.0).getRGB()); - } - if (y < image.getHeight() - 1) { - image.setRGB(x, y + 1, updateViaQuantError(new Color(image.getRGB(x, y + 1)), quantErrorRed, quantErrorGreen, quantErrorBlue, 5 / 16.0).getRGB()); - if (x < image.getWidth() - 1) { - image.setRGB(x + 1, y + 1, updateViaQuantError(new Color(image.getRGB(x + 1, y + 1)), quantErrorRed, quantErrorGreen, quantErrorBlue, 1 / 16.0).getRGB()); + Bukkit.getScheduler().runTaskTimer(LobbySystem.getPlugin(), () -> { + long modified = mapFile.lastModified(); + if (modified > lastModified) { + lastModified = modified; + System.out.println("Updating Banner: " + mapFile.getName()); + Bukkit.getScheduler().runTaskAsynchronously(LobbySystem.getPlugin(), () -> { + try { + run(); + } catch (IOException e) { + // Ignore } - } + }); } - } + }, 200L, 200L); + Bukkit.getPluginManager().registerEvents(this, LobbySystem.getPlugin()); + } - 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); - CraftMapView craftMapView = (CraftMapView) Bukkit.createMap(player.getWorld()); - try { - Field field = CraftMapView.class.getDeclaredField("worldMap"); - field.setAccessible(true); - WorldMap worldMap = (WorldMap) field.get(craftMapView); - for (int sx = 0; sx < 128; sx++) { - for (int sy = 0; sy < 128; sy++) { - byte color = MapPalette.matchColor(new Color(subImage.getRGB(sx, sy))); - worldMap.g[sx + sy * 128] = color; + @EventHandler + public void onChunkLoad(ChunkLoadEvent event) { + for (Entity entity : event.getChunk().getEntities()) { + if (!(entity instanceof ItemFrame)) continue; + ItemFrame itemFrame = (ItemFrame) entity; + ItemStack itemStack = itemFrame.getItem(); + if (itemStack.getType() != Material.FILLED_MAP) continue; + Vector vector = itemFrame.getLocation().getBlock().getLocation().toVector(); + if (itemFrameIndex.containsKey(vector)) { + if (itemFrames[itemFrameIndex.get(vector)] != null) continue; + itemFrames[itemFrameIndex.get(vector)] = itemFrame; + lastModified = 0; + MapView mapView = ((MapMeta) itemFrame.getItem().getItemMeta()).getMapView(); + new ArrayList<>(mapView.getRenderers()).forEach(mapView::removeRenderer); + mapView.addRenderer(new MapRenderer() { + @Override + public void render(MapView map, MapCanvas canvas, Player player) { + for (int x = 0; x < 128; x++) { + for (int y = 0; y < 128; y++) { + canvas.setPixel(x, y, (byte) 32); + } } } - craftMapView.setLocked(true); - } catch (IllegalAccessException | NoSuchFieldException e) { - throw new SecurityException(e.getMessage(), e); - } - ItemStack itemStack = new ItemStack(Material.FILLED_MAP, 1); - MapMeta mapMeta = (MapMeta) itemStack.getItemMeta(); - mapMeta.setMapView(craftMapView); - itemStack.setItemMeta(mapMeta); - player.getInventory().addItem(itemStack); + }); } } } - private Color updateViaQuantError(Color color, int quantErrorRed, int quantErrorGreen, int quantErrorBlue, double multiplier) { - int newRed = (int) (color.getRed() + quantErrorRed * multiplier); - int newGreen = (int) (color.getGreen() + quantErrorGreen * multiplier); - int newBlue = (int) (color.getBlue() + quantErrorBlue * multiplier); - return new Color(clamp(newRed), clamp(newGreen), clamp(newBlue)); + private void run() throws IOException { + BufferedImage bufferedImage = ImageIO.read(mapFile); + + Set[] patches = new Set[256]; + for (int patch = 0; patch < patches.length; patch++) { + patches[patch] = new HashSet<>(); + } + + for (int y = 0; y < bufferedImage.getHeight(); y++) { + for (int x = 0; x < bufferedImage.getWidth(); x++) { + Color color = new Color(bufferedImage.getRGB(x, y)); + double red = color.getRed() / 255.0; + double green = color.getGreen() / 255.0; + double blue = color.getBlue() / 255.0; + double luminance = Math.sqrt(0.299 * red * red + 0.587 * green * green + 0.114 * blue * blue); + luminance *= 255; + patches[(int) luminance].add(new Point(x, y)); + } + } + + for (int patch = 0; patch < patches.length; patch++) { + Set points = patches[patch]; + if (points.isEmpty()) continue; + BufferedImage patchImage = new BufferedImage(bufferedImage.getWidth(), bufferedImage.getHeight(), BufferedImage.TYPE_INT_ARGB); + points.forEach(point -> { + patchImage.setRGB(point.getX(), point.getY(), bufferedImage.getRGB(point.getX(), point.getY())); + }); + floodFill(patchImage); + dither(patchImage); + points.forEach(point -> { + bufferedImage.setRGB(point.getX(), point.getY(), patchImage.getRGB(point.getX(), point.getY())); + }); + } + + for (int y = 0; y < bufferedImage.getHeight(); y += 128) { + for (int x = 0; x < bufferedImage.getWidth(); x += 128) { + ItemFrame itemFrame = itemFrames[y / 128 * 7 + x / 128]; + if (itemFrame == null) continue; + int finalX = x; + int finalY = y; + Bukkit.getScheduler().runTaskLater(LobbySystem.getPlugin(), () -> { + ItemStack itemStack = itemFrame.getItem(); + MapMeta mapMeta = (MapMeta) itemStack.getItemMeta(); + MapView mapView = mapMeta.getMapView(); + new ArrayList<>(mapView.getRenderers()).forEach(mapView::removeRenderer); + mapView.addRenderer(new MapRenderer() { + @Override + public void render(MapView map, MapCanvas canvas, Player player) { + for (int dy = 0; dy < 128; dy++) { + for (int dx = 0; dx < 128; dx++) { + int ax = dx + finalX; + int ay = dy + finalY; + Color color = new Color(bufferedImage.getRGB(ax, ay)); + canvas.setPixel(dx, dy, ColorInit.getColorByte(color.getRed(), color.getGreen(), color.getBlue())); + } + } + } + }); + + mapMeta.setMapView(mapView); + itemStack.setItemMeta(mapMeta); + itemFrame.setItem(itemStack); + }, 1); + } + } } - private int clamp(int value) { - return Math.max(0, Math.min(255, value)); + private static void floodFill(BufferedImage bufferedImage) { + WritableRaster alpha = bufferedImage.getAlphaRaster(); + int[] data = alpha.getPixels(0, 0, bufferedImage.getWidth(), bufferedImage.getHeight(), new int[bufferedImage.getWidth() * bufferedImage.getHeight()]); + for (int i = 0; i < 5; i++) { + Set changes = new HashSet<>(); + for (int y = 0; y < bufferedImage.getHeight(); y++) { + for (int x = 0; x < bufferedImage.getWidth(); x++) { + if (data[y * bufferedImage.getWidth() + x] == 0) continue; + int color = bufferedImage.getRGB(x, y); + if (x > 0 && data[y * bufferedImage.getWidth() + x - 1] == 0) { + bufferedImage.setRGB(x - 1, y, color); + changes.add(new Point(x - 1, y)); + } + if (x < bufferedImage.getWidth() - 1 && data[y * bufferedImage.getWidth() + x + 1] == 0) { + bufferedImage.setRGB(x + 1, y, color); + changes.add(new Point(x + 1, y)); + } + if (y > 0 && data[(y - 1) * bufferedImage.getWidth() + x] == 0) { + bufferedImage.setRGB(x, y - 1, color); + changes.add(new Point(x, y - 1)); + } + if (y < bufferedImage.getHeight() - 1 && data[(y + 1) * bufferedImage.getWidth() + x] == 0) { + bufferedImage.setRGB(x, y + 1, color); + changes.add(new Point(x, y + 1)); + } + } + } + if (changes.isEmpty()) return; + changes.forEach(point -> { + data[point.getY() * bufferedImage.getWidth() + point.getX()] = 255; + }); + } } - private static Color getNearest(Color color) { - return MapPalette.getColor(MapPalette.matchColor(color)); + private static BufferedImage dither(BufferedImage image) { + final double multiplier1 = 7 / 48.0; + final double multiplier2 = 3 / 48.0; + final double multiplier3 = 5 / 48.0; + final double multiplier4 = 1 / 48.0; + WritableRaster alphaRaster = image.getAlphaRaster(); + WritableRaster raster = image.getRaster(); + int numBands = raster.getNumBands(); + int[] pixels = raster.getPixels(0, 0, image.getWidth(), image.getHeight(), new int[image.getWidth() * image.getHeight() * numBands]); + + int width = image.getWidth(); + int height = image.getHeight(); + + for (int y = 0; y < height; y++) { + for (int x = 0; x < width; x++) { + if (alphaRaster.getPixel(x, y, new int[1])[0] == 0) continue; + + int red = pixels[(y * width + x) * numBands]; + int i2 = (y * width + x) * numBands + 1; + int green = pixels[i2]; + int i3 = (y * width + x) * numBands + 2; + int blue = pixels[i3]; + Color nearest = MapPalette.getColor(ColorInit.getColorByte(red, green, blue)); + + pixels[(y * width + x) * numBands] = nearest.getRed(); + pixels[i2] = nearest.getGreen(); + pixels[i3] = nearest.getBlue(); + + int quantErrorRed = red - nearest.getRed(); + int quantErrorGreen = green - nearest.getGreen(); + int quantErrorBlue = blue - nearest.getBlue(); + + int mr1 = (int) (quantErrorRed * multiplier1); + int mg1 = (int) (quantErrorGreen * multiplier1); + int mb1 = (int) (quantErrorBlue * multiplier1); + + int mr2 = (int) (quantErrorRed * multiplier2); + int mg2 = (int) (quantErrorGreen * multiplier2); + int mb2 = (int) (quantErrorBlue * multiplier2); + + int mr3 = (int) (quantErrorRed * multiplier3); + int mg3 = (int) (quantErrorGreen * multiplier3); + int mb3 = (int) (quantErrorBlue * multiplier3); + + int mr4 = (int) (quantErrorRed * multiplier4); + int mg4 = (int) (quantErrorGreen * multiplier4); + int mb4 = (int) (quantErrorBlue * multiplier4); + + if (x < width - 1) { + int i = (y * width + x + 1) * numBands; + pixels[i] = clamp(pixels[i] + mr1); + pixels[i + 1] = clamp(pixels[i + 1] + mg1); + pixels[i + 2] = clamp(pixels[i + 2] + mb1); + } + + if (x < width - 2) { + int i = (y * width + x + 2) * numBands; + pixels[i] = clamp(pixels[i] + mr3); + pixels[i + 1] = clamp(pixels[i + 1] + mg3); + pixels[i + 2] = clamp(pixels[i + 2] + mb3); + } + + if (y < height - 1) { + if (x > 1) { + int i = ((y + 1) * width + x - 2) * numBands; + pixels[i] = clamp(pixels[i] + mr2); + pixels[i + 1] = clamp(pixels[i + 1] + mg2); + pixels[i + 2] = clamp(pixels[i + 2] + mb2); + } + if (x > 0) { + int i = ((y + 1) * width + x - 1) * numBands; + pixels[i] = clamp(pixels[i] + mr3); + pixels[i + 1] = clamp(pixels[i + 1] + mg3); + pixels[i + 2] = clamp(pixels[i + 2] + mb3); + } + if (x < width - 1) { + int i = ((y + 1) * width + x + 1) * numBands; + pixels[i] = clamp(pixels[i] + mr3); + pixels[i + 1] = clamp(pixels[i + 1] + mg3); + pixels[i + 2] = clamp(pixels[i + 2] + mb3); + } + if (x < width - 2) { + int i = ((y + 1) * width + x + 2) * numBands; + pixels[i] = clamp(pixels[i] + mr2); + pixels[i + 1] = clamp(pixels[i + 1] + mg2); + pixels[i + 2] = clamp(pixels[i + 2] + mb2); + } + int i = (y * width + x) * numBands; + pixels[i] = clamp(pixels[i] + mr1); + pixels[i + 1] = clamp(pixels[i + 1] + mg1); + pixels[i + 2] = clamp(pixels[i + 2] + mb1); + } + + if (y < height - 2) { + if (x > 1) { + int i = ((y + 2) * width + x - 2) * numBands; + pixels[i] = clamp(pixels[i] + mr4); + pixels[i + 1] = clamp(pixels[i + 1] + mg4); + pixels[i + 2] = clamp(pixels[i + 2] + mb4); + } + if (x > 0) { + int i = ((y + 2) * width + x - 1) * numBands; + pixels[i] = clamp(pixels[i] + mr2); + pixels[i + 1] = clamp(pixels[i + 1] + mg2); + pixels[i + 2] = clamp(pixels[i + 2] + mb2); + } + if (x < width - 1) { + int i = ((y + 2) * width + x + 1) * numBands; + pixels[i] = clamp(pixels[i] + mr2); + pixels[i + 1] = clamp(pixels[i + 1] + mg2); + pixels[i + 2] = clamp(pixels[i + 2] + mb2); + } + if (x < width - 2) { + int i = ((y + 2) * width + x + 2) * numBands; + pixels[i] = clamp(pixels[i] + mr4); + pixels[i + 1] = clamp(pixels[i + 1] + mg4); + pixels[i + 2] = clamp(pixels[i + 2] + mb4); + } + int i = (y * width + x) * numBands; + pixels[i] = clamp(pixels[i] + mr3); + pixels[i + 1] = clamp(pixels[i + 1] + mg3); + pixels[i + 2] = clamp(pixels[i + 2] + mb3); + } + } + } + raster.setPixels(0, 0, width, height, pixels); + return image; + } + + private static int clamp(int value) { + return Math.max(0, Math.min(value, 255)); } } diff --git a/src/de/steamwar/lobby/map/CustomMapCommand.java b/src/de/steamwar/lobby/map/CustomMapCommand.java deleted file mode 100644 index c0489d9..0000000 --- a/src/de/steamwar/lobby/map/CustomMapCommand.java +++ /dev/null @@ -1,73 +0,0 @@ -/* - * 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 de.steamwar.command.SWCommand; -import de.steamwar.command.TypeMapper; -import de.steamwar.command.TypeValidator; -import de.steamwar.sql.SteamwarUser; -import de.steamwar.sql.UserPerm; -import lombok.SneakyThrows; -import org.bukkit.command.CommandSender; -import org.bukkit.entity.Player; - -import javax.imageio.ImageIO; -import java.io.File; -import java.util.List; - -public class CustomMapCommand extends SWCommand { - - public CustomMapCommand() { - super("map"); - } - - @Register - @SneakyThrows - public void render(@Validator Player p, File file) { - if (!SteamwarUser.get(p.getUniqueId()).hasPerm(UserPerm.ADMINISTRATION)) { - return; - } - if (!file.exists()) { - p.sendMessage("§cDiese Datei existiert nicht!"); - return; - } - new CustomMap(p, ImageIO.read(file)); - } - - @ClassValidator(value = Player.class, local = true) - public TypeValidator getGuardChecker() { - return (commandSender, player, messageSender) -> SteamwarUser.get(player.getUniqueId()).hasPerm(UserPerm.ADMINISTRATION); - } - - @ClassMapper(value = File.class, local = true) - public TypeMapper getTypeMapper() { - return new TypeMapper() { - @Override - public List tabCompletes(CommandSender commandSender, String[] strings, String s) { - return null; - } - - @Override - public File map(CommandSender commandSender, String[] previousArguments, String s) { - return new File(s); - } - }; - } -} diff --git a/src/de/steamwar/lobby/map/CustomMapNew.java b/src/de/steamwar/lobby/map/CustomMapNew.java deleted file mode 100644 index c9703b4..0000000 --- a/src/de/steamwar/lobby/map/CustomMapNew.java +++ /dev/null @@ -1,354 +0,0 @@ -/* - * This file is a part of the SteamWar software. - * - * Copyright (C) 2024 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 de.steamwar.lobby.LobbySystem; -import net.minecraft.world.level.saveddata.maps.WorldMap; -import org.bukkit.Bukkit; -import org.bukkit.Material; -import org.bukkit.World; -import org.bukkit.craftbukkit.v1_20_R1.map.CraftMapView; -import org.bukkit.entity.ItemFrame; -import org.bukkit.inventory.ItemStack; -import org.bukkit.inventory.meta.MapMeta; -import org.bukkit.map.MapPalette; -import org.bukkit.util.Vector; - -import javax.imageio.ImageIO; -import java.awt.*; -import java.awt.image.BufferedImage; -import java.awt.image.WritableRaster; -import java.io.File; -import java.io.IOException; -import java.lang.reflect.Field; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Map; -import java.util.Set; - -public class CustomMapNew { - - public static void init() { - } - - private static final World WORLD = Bukkit.getWorlds().get(0); - - private static final CustomMapNew LEFT = new CustomMapNew(new File(System.getProperty("user.home") + "/lobbyBanner/left.png"), - new Vector(2346, 48, 1297), new Vector(2345, 48, 1297), new Vector(2344, 48, 1297), new Vector(2343, 48, 1297), new Vector(2342, 48, 1297), new Vector(2341, 48, 1297), new Vector(2340, 48, 1297), - new Vector(2346, 47, 1297), new Vector(2345, 47, 1297), new Vector(2344, 47, 1297), new Vector(2343, 47, 1297), new Vector(2342, 47, 1297), new Vector(2341, 47, 1297), new Vector(2340, 47, 1297), - new Vector(2346, 46, 1297), new Vector(2345, 46, 1297), new Vector(2344, 46, 1297), new Vector(2343, 46, 1297), new Vector(2342, 46, 1297), new Vector(2341, 46, 1297), new Vector(2340, 46, 1297), - new Vector(2346, 45, 1297), new Vector(2345, 45, 1297), new Vector(2344, 45, 1297), new Vector(2343, 45, 1297), new Vector(2342, 45, 1297), new Vector(2341, 45, 1297), new Vector(2340, 45, 1297) - ); - - private File mapFile; - private ItemFrame[] itemFrames = null; - - public CustomMapNew(File mapFile, Vector... itemFrames) { - this.mapFile = mapFile; - - Bukkit.getScheduler().runTaskTimer(LobbySystem.getPlugin(), () -> { - long lastModified = 0; - while (true) { - try { - Thread.sleep(10000); - } catch (InterruptedException e) { - Thread.currentThread().interrupt(); - } - if (this.itemFrames == null) { - loadItemFrames(itemFrames); - continue; - } - - long modified = mapFile.lastModified(); - System.out.println(lastModified + " " + modified); - if (modified > lastModified) { - lastModified = modified; - System.out.println("Updating Banner: " + mapFile.getName()); - Bukkit.getScheduler().runTaskAsynchronously(LobbySystem.getPlugin(), () -> { - try { - run(); - } catch (IOException e) { - // Ignore - } - }); - } - } - }, 200L, 200L); - } - - private void loadItemFrames(Vector... itemFrames) { - for (int i = 0; i < itemFrames.length; i++) { - itemFrames[i] = itemFrames[i].toLocation(WORLD).getBlock().getLocation().toVector(); - } - Map worldMaps = new HashMap<>(); - WORLD.getEntitiesByClass(ItemFrame.class).forEach(itemFrame -> { - ItemStack itemStack = itemFrame.getItem(); - System.out.println(itemFrame.getLocation().getBlock() + ": " + itemFrame + " " + itemStack); - if (itemStack.getType() != Material.FILLED_MAP) return; - worldMaps.put(itemFrame.getLocation().getBlock().getLocation().toVector(), itemFrame); - }); - - ItemFrame[] frames = new ItemFrame[itemFrames.length]; - for (int i = 0; i < frames.length; i++) { - if (worldMaps.get(itemFrames[i]) == null) { - System.out.println("ItemFrame at location " + itemFrames[i] + " is missing!"); - return; - } - frames[i] = worldMaps.get(itemFrames[i]); - } - this.itemFrames = frames; - } - - private void run() throws IOException { - BufferedImage bufferedImage = ImageIO.read(mapFile); - - Set[] patches = new Set[256]; - for (int patch = 0; patch < patches.length; patch++) { - patches[patch] = new HashSet<>(); - } - - for (int y = 0; y < bufferedImage.getHeight(); y++) { - for (int x = 0; x < bufferedImage.getWidth(); x++) { - Color color = new Color(bufferedImage.getRGB(x, y)); - double red = color.getRed() / 255.0; - double green = color.getGreen() / 255.0; - double blue = color.getBlue() / 255.0; - double luminance = Math.sqrt(0.299 * red * red + 0.587 * green * green + 0.114 * blue * blue); - luminance *= 255; - patches[(int) luminance].add(new Point(x, y)); - } - } - - for (int patch = 0; patch < patches.length; patch++) { - Set points = patches[patch]; - if (points.isEmpty()) continue; - BufferedImage patchImage = new BufferedImage(bufferedImage.getWidth(), bufferedImage.getHeight(), BufferedImage.TYPE_INT_ARGB); - points.forEach(point -> { - patchImage.setRGB(point.getX(), point.getY(), bufferedImage.getRGB(point.getX(), point.getY())); - }); - floodFill(patchImage); - dither(patchImage); - points.forEach(point -> { - bufferedImage.setRGB(point.getX(), point.getY(), patchImage.getRGB(point.getX(), point.getY())); - }); - } - - for (int y = 0; y < bufferedImage.getHeight() / 128; y += 128) { - for (int x = 0; x < bufferedImage.getWidth() / 128; x += 128) { - ItemFrame itemFrame = itemFrames[y / 128 * 7 + x / 128]; - int finalX = x; - int finalY = y; - Bukkit.getScheduler().runTaskLater(LobbySystem.getPlugin(), () -> { - ItemStack itemStack = itemFrame.getItem(); - MapMeta mapMeta = (MapMeta) itemStack.getItemMeta(); - CraftMapView mapView = (CraftMapView) mapMeta.getMapView(); - - try { - Field field = CraftMapView.class.getDeclaredField("worldMap"); - field.setAccessible(true); - WorldMap worldMap = (WorldMap) field.get(mapView); - - for (int dy = 0; dy < 128; dy++) { - for (int dx = 0; dx < 128; dx++) { - int ax = dx + finalX; - int ay = dy + finalY; - Color color = new Color(bufferedImage.getRGB(ax, ay)); - worldMap.g[dx + dy * 128] = ColorInit.getColorByte(color.getRed(), color.getGreen(), color.getBlue()); - } - } - } catch (IllegalAccessException | NoSuchFieldException e) { - throw new SecurityException(e.getMessage(), e); - } - - mapMeta.setMapView(mapView); - itemStack.setItemMeta(mapMeta); - itemFrame.setItem(itemStack); - }, 1); - } - } - } - - private static void floodFill(BufferedImage bufferedImage) { - WritableRaster alpha = bufferedImage.getAlphaRaster(); - int[] data = alpha.getPixels(0, 0, bufferedImage.getWidth(), bufferedImage.getHeight(), new int[bufferedImage.getWidth() * bufferedImage.getHeight()]); - for (int i = 0; i < 5; i++) { - Set changes = new HashSet<>(); - for (int y = 0; y < bufferedImage.getHeight(); y++) { - for (int x = 0; x < bufferedImage.getWidth(); x++) { - if (data[y * bufferedImage.getWidth() + x] == 0) continue; - int color = bufferedImage.getRGB(x, y); - if (x > 0 && data[y * bufferedImage.getWidth() + x - 1] == 0) { - bufferedImage.setRGB(x - 1, y, color); - changes.add(new Point(x - 1, y)); - } - if (x < bufferedImage.getWidth() - 1 && data[y * bufferedImage.getWidth() + x + 1] == 0) { - bufferedImage.setRGB(x + 1, y, color); - changes.add(new Point(x + 1, y)); - } - if (y > 0 && data[(y - 1) * bufferedImage.getWidth() + x] == 0) { - bufferedImage.setRGB(x, y - 1, color); - changes.add(new Point(x, y - 1)); - } - if (y < bufferedImage.getHeight() - 1 && data[(y + 1) * bufferedImage.getWidth() + x] == 0) { - bufferedImage.setRGB(x, y + 1, color); - changes.add(new Point(x, y + 1)); - } - } - } - if (changes.isEmpty()) return; - changes.forEach(point -> { - data[point.getY() * bufferedImage.getWidth() + point.getX()] = 255; - }); - } - } - - private static BufferedImage dither(BufferedImage image) { - final double multiplier1 = 7 / 48.0; - final double multiplier2 = 3 / 48.0; - final double multiplier3 = 5 / 48.0; - final double multiplier4 = 1 / 48.0; - WritableRaster alphaRaster = image.getAlphaRaster(); - WritableRaster raster = image.getRaster(); - int numBands = raster.getNumBands(); - int[] pixels = raster.getPixels(0, 0, image.getWidth(), image.getHeight(), new int[image.getWidth() * image.getHeight() * numBands]); - - int width = image.getWidth(); - int height = image.getHeight(); - - for (int y = 0; y < height; y++) { - for (int x = 0; x < width; x++) { - if (alphaRaster.getPixel(x, y, new int[1])[0] == 0) continue; - - int red = pixels[(y * width + x) * numBands]; - int i2 = (y * width + x) * numBands + 1; - int green = pixels[i2]; - int i3 = (y * width + x) * numBands + 2; - int blue = pixels[i3]; - Color nearest = MapPalette.getColor(ColorInit.getColorByte(red, green, blue)); - - pixels[(y * width + x) * numBands] = nearest.getRed(); - pixels[i2] = nearest.getGreen(); - pixels[i3] = nearest.getBlue(); - - int quantErrorRed = red - nearest.getRed(); - int quantErrorGreen = green - nearest.getGreen(); - int quantErrorBlue = blue - nearest.getBlue(); - - int mr1 = (int) (quantErrorRed * multiplier1); - int mg1 = (int) (quantErrorGreen * multiplier1); - int mb1 = (int) (quantErrorBlue * multiplier1); - - int mr2 = (int) (quantErrorRed * multiplier2); - int mg2 = (int) (quantErrorGreen * multiplier2); - int mb2 = (int) (quantErrorBlue * multiplier2); - - int mr3 = (int) (quantErrorRed * multiplier3); - int mg3 = (int) (quantErrorGreen * multiplier3); - int mb3 = (int) (quantErrorBlue * multiplier3); - - int mr4 = (int) (quantErrorRed * multiplier4); - int mg4 = (int) (quantErrorGreen * multiplier4); - int mb4 = (int) (quantErrorBlue * multiplier4); - - if (x < width - 1) { - int i = (y * width + x + 1) * numBands; - pixels[i] = clamp(pixels[i] + mr1); - pixels[i + 1] = clamp(pixels[i + 1] + mg1); - pixels[i + 2] = clamp(pixels[i + 2] + mb1); - } - - if (x < width - 2) { - int i = (y * width + x + 2) * numBands; - pixels[i] = clamp(pixels[i] + mr3); - pixels[i + 1] = clamp(pixels[i + 1] + mg3); - pixels[i + 2] = clamp(pixels[i + 2] + mb3); - } - - if (y < height - 1) { - if (x > 1) { - int i = ((y + 1) * width + x - 2) * numBands; - pixels[i] = clamp(pixels[i] + mr2); - pixels[i + 1] = clamp(pixels[i + 1] + mg2); - pixels[i + 2] = clamp(pixels[i + 2] + mb2); - } - if (x > 0) { - int i = ((y + 1) * width + x - 1) * numBands; - pixels[i] = clamp(pixels[i] + mr3); - pixels[i + 1] = clamp(pixels[i + 1] + mg3); - pixels[i + 2] = clamp(pixels[i + 2] + mb3); - } - if (x < width - 1) { - int i = ((y + 1) * width + x + 1) * numBands; - pixels[i] = clamp(pixels[i] + mr3); - pixels[i + 1] = clamp(pixels[i + 1] + mg3); - pixels[i + 2] = clamp(pixels[i + 2] + mb3); - } - if (x < width - 2) { - int i = ((y + 1) * width + x + 2) * numBands; - pixels[i] = clamp(pixels[i] + mr2); - pixels[i + 1] = clamp(pixels[i + 1] + mg2); - pixels[i + 2] = clamp(pixels[i + 2] + mb2); - } - int i = (y * width + x) * numBands; - pixels[i] = clamp(pixels[i] + mr1); - pixels[i + 1] = clamp(pixels[i + 1] + mg1); - pixels[i + 2] = clamp(pixels[i + 2] + mb1); - } - - if (y < height - 2) { - if (x > 1) { - int i = ((y + 2) * width + x - 2) * numBands; - pixels[i] = clamp(pixels[i] + mr4); - pixels[i + 1] = clamp(pixels[i + 1] + mg4); - pixels[i + 2] = clamp(pixels[i + 2] + mb4); - } - if (x > 0) { - int i = ((y + 2) * width + x - 1) * numBands; - pixels[i] = clamp(pixels[i] + mr2); - pixels[i + 1] = clamp(pixels[i + 1] + mg2); - pixels[i + 2] = clamp(pixels[i + 2] + mb2); - } - if (x < width - 1) { - int i = ((y + 2) * width + x + 1) * numBands; - pixels[i] = clamp(pixels[i] + mr2); - pixels[i + 1] = clamp(pixels[i + 1] + mg2); - pixels[i + 2] = clamp(pixels[i + 2] + mb2); - } - if (x < width - 2) { - int i = ((y + 2) * width + x + 2) * numBands; - pixels[i] = clamp(pixels[i] + mr4); - pixels[i + 1] = clamp(pixels[i + 1] + mg4); - pixels[i + 2] = clamp(pixels[i + 2] + mb4); - } - int i = (y * width + x) * numBands; - pixels[i] = clamp(pixels[i] + mr3); - pixels[i + 1] = clamp(pixels[i + 1] + mg3); - pixels[i + 2] = clamp(pixels[i + 2] + mb3); - } - } - } - raster.setPixels(0, 0, width, height, pixels); - return image; - } - - private static int clamp(int value) { - return Math.max(0, Math.min(value, 255)); - } -}