diff --git a/src/de/steamwar/lobby/LobbySystem.java b/src/de/steamwar/lobby/LobbySystem.java index 3f0badd..0ec117d 100644 --- a/src/de/steamwar/lobby/LobbySystem.java +++ b/src/de/steamwar/lobby/LobbySystem.java @@ -24,7 +24,7 @@ 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.map.CustomMapCommand; import de.steamwar.lobby.team.TeamPlayer; import de.steamwar.message.Message; import org.bukkit.plugin.java.JavaPlugin; @@ -51,6 +51,7 @@ public class LobbySystem extends JavaPlugin { new HologramCommand(); new FlyCommand(); new ModifyCommand(); + new CustomMapCommand(); config = new Config(getConfig()); new PlayerSpawn(); @@ -67,8 +68,6 @@ public class LobbySystem extends JavaPlugin { new AlphaWall(l -> l.getX() < 2977, AlphaWall.REFLECT_X); 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/listener/WorldInteraction.java b/src/de/steamwar/lobby/listener/WorldInteraction.java index 8bef3fc..1dcaa9c 100644 --- a/src/de/steamwar/lobby/listener/WorldInteraction.java +++ b/src/de/steamwar/lobby/listener/WorldInteraction.java @@ -22,20 +22,41 @@ package de.steamwar.lobby.listener; import de.steamwar.lobby.command.ModifyCommand; import org.bukkit.Material; import org.bukkit.entity.HumanEntity; +import org.bukkit.entity.ItemFrame; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; import org.bukkit.event.block.Action; import org.bukkit.event.block.BlockBreakEvent; import org.bukkit.event.block.BlockPhysicsEvent; import org.bukkit.event.block.BlockPlaceEvent; +import org.bukkit.event.entity.EntityDamageByEntityEvent; import org.bukkit.event.entity.EntityDamageEvent; import org.bukkit.event.entity.FoodLevelChangeEvent; import org.bukkit.event.hanging.HangingBreakByEntityEvent; +import org.bukkit.event.hanging.HangingBreakEvent; import org.bukkit.event.player.PlayerInteractEvent; +import org.bukkit.event.server.MapInitializeEvent; import org.bukkit.util.Vector; public class WorldInteraction extends BasicListener { + @EventHandler + public void onEntityDamageByEntity(EntityDamageByEntityEvent event) { + if (!(event.getDamager() instanceof Player)) { + return; + } + if(!ModifyCommand.modifying((Player) event.getDamager())) { + event.setCancelled(true); + return; + } + if (!(event.getEntity() instanceof ItemFrame)) { + return; + } + ItemFrame itemFrame = (ItemFrame) event.getEntity(); + ((Player) event.getDamager()).getInventory().addItem(itemFrame.getItem()); + itemFrame.setItem(null); + } + @EventHandler public void handleEntityDamage(EntityDamageEvent event) { event.setCancelled(true); @@ -75,6 +96,7 @@ public class WorldInteraction extends BasicListener { @EventHandler public void onBlockPhysics(BlockPhysicsEvent event) { + System.out.println(event); event.setCancelled(true); } } diff --git a/src/de/steamwar/lobby/map/CustomMap.java b/src/de/steamwar/lobby/map/CustomMap.java index 24bc598..6bf8536 100644 --- a/src/de/steamwar/lobby/map/CustomMap.java +++ b/src/de/steamwar/lobby/map/CustomMap.java @@ -19,44 +19,22 @@ package de.steamwar.lobby.map; +import net.minecraft.server.v1_15_R1.WorldMap; +import org.bukkit.Bukkit; +import org.bukkit.Material; +import org.bukkit.craftbukkit.v1_15_R1.map.CraftMapView; +import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.MapMeta; 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; +import java.lang.reflect.Field; 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) { + public CustomMap(Player player, BufferedImage image) { if (image.getWidth() % 128 != 0) { throw new IllegalArgumentException("Image width must be a multiple of 128"); } @@ -65,125 +43,68 @@ public class CustomMap { } 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); + 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()); } - 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 (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()); } } - - 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); + 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.colors[sx + sy * 128] = color; + } + } + 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); } } - - 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 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 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 int clamp(int value) { + return Math.max(0, Math.min(255, value)); } - 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; - } + private static Color getNearest(Color color) { + return MapPalette.getColor(MapPalette.matchColor(color)); } } diff --git a/src/de/steamwar/lobby/map/CustomMapCommand.java b/src/de/steamwar/lobby/map/CustomMapCommand.java new file mode 100644 index 0000000..c2d6f6a --- /dev/null +++ b/src/de/steamwar/lobby/map/CustomMapCommand.java @@ -0,0 +1,80 @@ +/* + * 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.GuardChecker; +import de.steamwar.command.GuardResult; +import de.steamwar.command.SWCommand; +import de.steamwar.command.TypeMapper; +import de.steamwar.sql.SteamwarUser; +import de.steamwar.sql.UserGroup; +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(@Guard Player p, File file) { + if (SteamwarUser.get(p).getUserGroup() != UserGroup.Developer) { + return; + } + if (!file.exists()) { + p.sendMessage("§cDiese Datei existiert nicht!"); + return; + } + new CustomMap(p, ImageIO.read(file)); + } + + @ClassGuard(value = Player.class, local = true) + public GuardChecker getGuardChecker() { + return (commandSender, guardCheckType, strings, s) -> { + Player player = (Player) commandSender; + if (SteamwarUser.get(player).getUserGroup() == UserGroup.Developer) { + return GuardResult.ALLOWED; + } + return GuardResult.DENIED; + }; + } + + @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/MapColors.png b/src/de/steamwar/lobby/map/MapColors.png deleted file mode 100644 index 5e44d49..0000000 Binary files a/src/de/steamwar/lobby/map/MapColors.png and /dev/null differ diff --git a/src/de/steamwar/lobby/map/wgsbanner13.png b/src/de/steamwar/lobby/map/wgsbanner13.png deleted file mode 100644 index 749948e..0000000 Binary files a/src/de/steamwar/lobby/map/wgsbanner13.png and /dev/null differ