diff --git a/.idea/modules.xml b/.idea/modules.xml index 89e9515..0fe66a1 100644 --- a/.idea/modules.xml +++ b/.idea/modules.xml @@ -3,6 +3,7 @@ + \ No newline at end of file diff --git a/.idea/modules/PixelPic.main.iml b/.idea/modules/PixelPic.main.iml index bbeeb3e..746f1fd 100644 --- a/.idea/modules/PixelPic.main.iml +++ b/.idea/modules/PixelPic.main.iml @@ -11,4 +11,8 @@ + + + + \ No newline at end of file diff --git a/.idea/modules/eu.mhsl.minecraft.pixelpic.PixelPic.main.iml b/.idea/modules/eu.mhsl.minecraft.pixelpic.PixelPic.main.iml new file mode 100644 index 0000000..bbeeb3e --- /dev/null +++ b/.idea/modules/eu.mhsl.minecraft.pixelpic.PixelPic.main.iml @@ -0,0 +1,14 @@ + + + + + + + PAPER + ADVENTURE + + 1 + + + + \ No newline at end of file diff --git a/src/main/java/eu/mhsl/minecraft/pixelpic/ImageMapRenderer.java b/src/main/java/eu/mhsl/minecraft/pixelpic/ImageMapRenderer.java index 3461005..d8ec8c3 100644 --- a/src/main/java/eu/mhsl/minecraft/pixelpic/ImageMapRenderer.java +++ b/src/main/java/eu/mhsl/minecraft/pixelpic/ImageMapRenderer.java @@ -1,6 +1,5 @@ package eu.mhsl.minecraft.pixelpic; -import org.bukkit.Bukkit; import org.bukkit.entity.Player; import org.bukkit.map.MapCanvas; import org.bukkit.map.MapRenderer; @@ -10,23 +9,19 @@ import org.jetbrains.annotations.NotNull; import java.awt.image.BufferedImage; public class ImageMapRenderer extends MapRenderer { - public final int IMAGE_SIZE = 128; - - private BufferedImage image; - private final int x; - private final int y; + public static final int IMAGE_SIZE = 128; + private final BufferedImage image; + private boolean alreadyRendered = false; public ImageMapRenderer(BufferedImage image) { this(image, 0, 0); } public ImageMapRenderer(BufferedImage image, int x, int y) { - this.x = x; - this.y = y; - recalculateInput(image); + this.image = recalculateInput(image, x, y); } - public void recalculateInput(BufferedImage input) { + public static BufferedImage recalculateInput(BufferedImage input, int x, int y) { if (x * IMAGE_SIZE > input.getWidth() || y * IMAGE_SIZE > input.getHeight()) throw new RuntimeException(String.format("Input image mus match a multiple of x and y with %d", IMAGE_SIZE)); @@ -37,14 +32,15 @@ public class ImageMapRenderer extends MapRenderer { int y2 = (int) (double) Math.min(input.getHeight(), ((y + 1) * IMAGE_SIZE)); if (x2 - x1 <= 0 || y2 - y1 <= 0) - return; + throw new RuntimeException("Invalid Image dimensions!"); - this.image = input.getSubimage(x1, y1, x2 - x1, y2 - y1); + return input.getSubimage(x1, y1, x2 - x1, y2 - y1); } @Override public void render(@NotNull MapView map, @NotNull MapCanvas canvas, @NotNull Player player) { - if(image == null) return; - Bukkit.getScheduler().runTaskLater(Main.getInstance(), () -> canvas.drawImage(0, 0, image), 2L); + if(this.alreadyRendered) return; + canvas.drawImage(0, 0, this.image); + this.alreadyRendered = true; } } diff --git a/src/main/java/eu/mhsl/minecraft/pixelpic/Main.java b/src/main/java/eu/mhsl/minecraft/pixelpic/Main.java index 25beb2a..b757bc8 100644 --- a/src/main/java/eu/mhsl/minecraft/pixelpic/Main.java +++ b/src/main/java/eu/mhsl/minecraft/pixelpic/Main.java @@ -1,120 +1,83 @@ package eu.mhsl.minecraft.pixelpic; +import eu.mhsl.minecraft.pixelpic.commands.PixelPicCommand; import eu.mhsl.minecraft.pixelpic.render.render.DefaultScreenRenderer; import eu.mhsl.minecraft.pixelpic.render.render.Renderer; -import eu.mhsl.minecraft.pixelpic.render.render.Resolution; -import net.kyori.adventure.text.Component; import org.bukkit.Bukkit; -import org.bukkit.Material; -import org.bukkit.entity.Player; -import org.bukkit.inventory.ItemStack; -import org.bukkit.inventory.meta.MapMeta; -import org.bukkit.map.MapView; import org.bukkit.plugin.java.JavaPlugin; -import javax.imageio.ImageIO; -import java.awt.image.BufferedImage; -import java.io.File; - public final class Main extends JavaPlugin { private static Main instance; private Renderer screenRenderer; @Override public void onEnable() { - this.instance = this; - this.screenRenderer = new DefaultScreenRenderer(); - Bukkit.getPluginCommand("test").setExecutor((sender, command, label, args) -> { - if(!(sender instanceof Player player)) return false; - - Resolution.Pixels pixels = Resolution.Pixels._128P; - Resolution.AspectRatio aspectRatio = Resolution.AspectRatio._1_1; - Resolution resolution = new Resolution(pixels, aspectRatio); - BufferedImage image = screenRenderer.render((Player) sender, resolution); - Bukkit.broadcast(Component.text(image.toString())); - - File file = new File(getDataFolder(), "Bild" + ".png"); - try { - getDataFolder().mkdir(); - ImageIO.write(image, "png", file); - } catch (Exception e) { - return true; - } - - ItemStack map = new ItemStack(Material.FILLED_MAP, 1); - MapMeta meta = (MapMeta) map.getItemMeta(); - - MapView mapView = Bukkit.createMap(Bukkit.getWorlds().getFirst()); - mapView.addRenderer(new ImageMapRenderer(image)); - - meta.setMapView(mapView); - map.setItemMeta(meta); - - player.getInventory().addItem(map); - player.updateInventory(); - - return true; - }); - - Bukkit.getPluginCommand("test2").setExecutor((sender, command, label, args) -> { - if(!(sender instanceof Player player)) return false; - Bukkit.broadcast(Component.text("HI")); - - Resolution.Pixels pixels = Resolution.Pixels._256P; - Resolution.AspectRatio aspectRatio = Resolution.AspectRatio._1_1; - Resolution resolution = new Resolution(pixels, aspectRatio); - BufferedImage image = screenRenderer.render((Player) sender, resolution); - Bukkit.broadcast(Component.text(image.toString())); - - File file = new File(getDataFolder(), "Bild" + ".png"); - try { - getDataFolder().mkdir(); - ImageIO.write(image, "png", file); - } catch (Exception e) { - return true; - } - - ItemStack map = new ItemStack(Material.FILLED_MAP, 1); - MapMeta meta = (MapMeta) map.getItemMeta(); - MapView mapView = Bukkit.createMap(Bukkit.getWorlds().getFirst()); - mapView.addRenderer(new ImageMapRenderer(image, 0, 0)); - meta.setMapView(mapView); - map.setItemMeta(meta); - player.getInventory().addItem(map); - - ItemStack map2 = new ItemStack(Material.FILLED_MAP, 1); - MapMeta meta1 = (MapMeta) map2.getItemMeta(); - MapView mapView4 = Bukkit.createMap(Bukkit.getWorlds().getFirst()); - mapView4.addRenderer(new ImageMapRenderer(image, 1, 0)); - meta1.setMapView(mapView4); - map2.setItemMeta(meta1); - player.getInventory().addItem(map2); - - ItemStack map3 = new ItemStack(Material.FILLED_MAP, 1); - MapMeta meta2 = (MapMeta) map3.getItemMeta(); - MapView mapView3 = Bukkit.createMap(Bukkit.getWorlds().getFirst()); - mapView3.addRenderer(new ImageMapRenderer(image, 0, 1)); - meta2.setMapView(mapView3); - map3.setItemMeta(meta2); - player.getInventory().addItem(map3); - - ItemStack map4 = new ItemStack(Material.FILLED_MAP, 1); - MapMeta meta3 = (MapMeta) map4.getItemMeta(); - MapView mapView2 = Bukkit.createMap(Bukkit.getWorlds().getFirst()); - mapView2.addRenderer(new ImageMapRenderer(image, 1, 1)); - meta3.setMapView(mapView2); - map4.setItemMeta(meta3); - player.getInventory().addItem(map4); - - player.updateInventory(); - - return true; - }); + instance = this; + Bukkit.getPluginCommand("pixelPic").setExecutor(new PixelPicCommand()); +// +// Bukkit.getPluginCommand("test2").setExecutor((sender, command, label, args) -> { +// if(!(sender instanceof Player player)) return false; +// Bukkit.broadcast(Component.text("HI")); +// +// Resolution.Pixels pixels = Resolution.Pixels._256P; +// Resolution.AspectRatio aspectRatio = Resolution.AspectRatio._1_1; +// Resolution resolution = new Resolution(pixels, aspectRatio); +// BufferedImage image = screenRenderer.render((Player) sender, resolution); +// Bukkit.broadcast(Component.text(image.toString())); +// +// File file = new File(getDataFolder(), "Bild" + ".png"); +// try { +// getDataFolder().mkdir(); +// ImageIO.write(image, "png", file); +// } catch (Exception e) { +// return true; +// } +// +// ItemStack map = new ItemStack(Material.FILLED_MAP, 1); +// MapMeta meta = (MapMeta) map.getItemMeta(); +// MapView mapView = Bukkit.createMap(Bukkit.getWorlds().getFirst()); +// mapView.addRenderer(new ImageMapRenderer(image, 0, 0)); +// meta.setMapView(mapView); +// map.setItemMeta(meta); +// player.getInventory().addItem(map); +// +// ItemStack map2 = new ItemStack(Material.FILLED_MAP, 1); +// MapMeta meta1 = (MapMeta) map2.getItemMeta(); +// MapView mapView4 = Bukkit.createMap(Bukkit.getWorlds().getFirst()); +// mapView4.addRenderer(new ImageMapRenderer(image, 1, 0)); +// meta1.setMapView(mapView4); +// map2.setItemMeta(meta1); +// player.getInventory().addItem(map2); +// +// ItemStack map3 = new ItemStack(Material.FILLED_MAP, 1); +// MapMeta meta2 = (MapMeta) map3.getItemMeta(); +// MapView mapView3 = Bukkit.createMap(Bukkit.getWorlds().getFirst()); +// mapView3.addRenderer(new ImageMapRenderer(image, 0, 1)); +// meta2.setMapView(mapView3); +// map3.setItemMeta(meta2); +// player.getInventory().addItem(map3); +// +// ItemStack map4 = new ItemStack(Material.FILLED_MAP, 1); +// MapMeta meta3 = (MapMeta) map4.getItemMeta(); +// MapView mapView2 = Bukkit.createMap(Bukkit.getWorlds().getFirst()); +// mapView2.addRenderer(new ImageMapRenderer(image, 1, 1)); +// meta3.setMapView(mapView2); +// map4.setItemMeta(meta3); +// player.getInventory().addItem(map4); +// +// player.updateInventory(); +// +// return true; +// }); } @Override public void onDisable() { - // Plugin shutdown logic + } + + public Renderer getScreenRenderer() { + if(this.screenRenderer == null) this.screenRenderer = new DefaultScreenRenderer(); + return this.screenRenderer; } public static Main getInstance() { diff --git a/src/main/java/eu/mhsl/minecraft/pixelpic/commands/PixelPicCommand.java b/src/main/java/eu/mhsl/minecraft/pixelpic/commands/PixelPicCommand.java new file mode 100644 index 0000000..75b6e55 --- /dev/null +++ b/src/main/java/eu/mhsl/minecraft/pixelpic/commands/PixelPicCommand.java @@ -0,0 +1,56 @@ +package eu.mhsl.minecraft.pixelpic.commands; + +import eu.mhsl.minecraft.pixelpic.ImageMapRenderer; +import eu.mhsl.minecraft.pixelpic.Main; +import eu.mhsl.minecraft.pixelpic.render.render.Resolution; +import org.bukkit.Bukkit; +import org.bukkit.Material; +import org.bukkit.command.Command; +import org.bukkit.command.CommandExecutor; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.MapMeta; +import org.bukkit.map.MapView; +import org.jetbrains.annotations.NotNull; + +import javax.imageio.ImageIO; +import java.awt.image.BufferedImage; +import java.io.File; + +public class PixelPicCommand implements CommandExecutor { + @Override + public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String @NotNull [] args) { + if(!(sender instanceof Player player)) + throw new IllegalStateException("Dieser Command kann nur von einem Spieler ausgeführt werden!"); + + Resolution.Pixels pixels = Resolution.Pixels._128P; + Resolution.AspectRatio aspectRatio = Resolution.AspectRatio._1_1; + Resolution resolution = new Resolution(pixels, aspectRatio); + + BufferedImage image = Main.getInstance().getScreenRenderer().render(player, resolution); + + File file = new File(Main.getInstance().getDataFolder(), "Bild" + ".png"); + try { + Main.getInstance().getDataFolder().mkdir(); + ImageIO.write(image, "png", file); + } catch (Exception e) { + return true; + } + + ItemStack map = new ItemStack(Material.FILLED_MAP, 1); + MapMeta meta = (MapMeta) map.getItemMeta(); + + MapView mapView = Bukkit.createMap(Bukkit.getWorlds().getFirst()); + mapView.getRenderers().forEach(mapView::removeRenderer); + mapView.addRenderer(new ImageMapRenderer(image)); + + meta.setMapView(mapView); + map.setItemMeta(meta); + + player.getInventory().addItem(map); + player.updateInventory(); + + return true; + } +} diff --git a/src/main/java/eu/mhsl/minecraft/pixelpic/render/raytrace/DefaultRaytracer.java b/src/main/java/eu/mhsl/minecraft/pixelpic/render/raytrace/DefaultRaytracer.java index 134a9f5..d47a75e 100644 --- a/src/main/java/eu/mhsl/minecraft/pixelpic/render/raytrace/DefaultRaytracer.java +++ b/src/main/java/eu/mhsl/minecraft/pixelpic/render/raytrace/DefaultRaytracer.java @@ -15,14 +15,20 @@ import org.bukkit.block.data.BlockData; import org.bukkit.util.Vector; public class DefaultRaytracer implements Raytracer { - - private static final int MAX_DISTANCE = 300; - private static final int REFLECTION_DEPTH = 10; + private final int maxDistance; + private final int reflectionDepth; private final ModelRegistry textureRegistry; private Block reflectedBlock; public DefaultRaytracer() { + this(300, 10); + } + + public DefaultRaytracer(int maxDistance, int reflectionDepth) { + this.maxDistance = maxDistance; + this.reflectionDepth = reflectionDepth; + this.textureRegistry = new DefaultModelRegistry(); this.textureRegistry.initialize(); @@ -31,7 +37,7 @@ public class DefaultRaytracer implements Raytracer { @Override public int trace(World world, Vector point, Vector direction) { - return trace(world, point, direction, REFLECTION_DEPTH); + return trace(world, point, direction, reflectionDepth); } private int trace(World world, Vector point, Vector direction, int reflectionDepth) { @@ -52,19 +58,10 @@ public class DefaultRaytracer implements Raytracer { Material occlusionMaterial = null; BlockData occlusionData = null; - for (int i = 0; i < MAX_DISTANCE; i++) { - if (!iterator.hasNext()) { - break; - } - + for (int i = 0; i < maxDistance; i++) { + if (!iterator.hasNext()) break; Block block = iterator.next(); - if (block == null) { - continue; - } - - if (reflectedBlock != null && reflectedBlock.equals(block)) { - continue; - } + if (reflectedBlock != null && reflectedBlock.equals(block)) continue; reflectedBlock = null; Material material = block.getType(); @@ -75,20 +72,30 @@ public class DefaultRaytracer implements Raytracer { } Model textureModel = textureRegistry.getModel(block); - Intersection currentIntersection = Intersection.of(MathUtil.toVector(iterator.getIntersectionFace()), - i == 0 ? point : iterator.getIntersectionPoint(), direction); + Intersection currentIntersection = Intersection.of( + MathUtil.toVector(iterator.getIntersectionFace()), + i == 0 ? point : iterator.getIntersectionPoint(), + direction + ); Intersection newIntersection = textureModel.intersect(block, currentIntersection); - if (newIntersection == null) { - continue; - } + if (newIntersection == null) continue; int color = newIntersection.getColor(); if (!reflected && textureModel.getReflectionFactor() > 0 && reflectionDepth > 0 && (color >> 24) != 0) { reflectedBlock = block; - reflectionColor = trace(world, newIntersection.getPoint(), MathUtil.reflectVector(point, direction, - newIntersection.getPoint(), newIntersection.getNormal()), reflectionDepth - 1); + reflectionColor = trace( + world, + newIntersection.getPoint(), + MathUtil.reflectVector( + point, + direction, + newIntersection.getPoint(), + newIntersection.getNormal() + ), + reflectionDepth - 1 + ); reflectionFactor = textureModel.getReflectionFactor(); reflected = true; } @@ -102,9 +109,7 @@ public class DefaultRaytracer implements Raytracer { if (textureModel.isOccluding()) { BlockData data = block.getBlockData(); - if (material == occlusionMaterial && data.equals(occlusionData)) { - continue; - } + if (material == occlusionMaterial && data.equals(occlusionData)) continue; occlusionMaterial = material; occlusionData = data; @@ -113,13 +118,8 @@ public class DefaultRaytracer implements Raytracer { occlusionData = null; } - if (transparencyStart != null && textureModel.getTransparencyFactor() > 0) { - continue; - } - - if ((color >> 24) == 0) { - continue; - } + if (transparencyStart != null && textureModel.getTransparencyFactor() > 0) continue; + if ((color >> 24) == 0) continue; baseColor = color; finalIntersection = newIntersection.getPoint(); @@ -127,13 +127,22 @@ public class DefaultRaytracer implements Raytracer { } if (transparencyStart != null) { - baseColor = MathUtil.weightedColorSum(baseColor, transparencyColor, transparencyFactor, (1 + baseColor = MathUtil.weightedColorSum( + baseColor, + transparencyColor, + transparencyFactor, + (1 - transparencyFactor) * (1 + transparencyStart.distance(finalIntersection == null ? transparencyStart : finalIntersection) / 5.0)); } if (reflected) { - baseColor = MathUtil.weightedColorSum(baseColor, reflectionColor, 1 - reflectionFactor, reflectionFactor); + baseColor = MathUtil.weightedColorSum( + baseColor, + reflectionColor, + 1 - reflectionFactor, + reflectionFactor + ); } return baseColor & 0xFFFFFF; diff --git a/src/main/java/eu/mhsl/minecraft/pixelpic/render/util/BlockRaytracer.java b/src/main/java/eu/mhsl/minecraft/pixelpic/render/util/BlockRaytracer.java index fbfe63e..e8ca4ab 100644 --- a/src/main/java/eu/mhsl/minecraft/pixelpic/render/util/BlockRaytracer.java +++ b/src/main/java/eu/mhsl/minecraft/pixelpic/render/util/BlockRaytracer.java @@ -5,6 +5,7 @@ import org.bukkit.block.Block; import org.bukkit.block.BlockFace; import org.bukkit.util.BlockIterator; import org.bukkit.util.Vector; +import org.jetbrains.annotations.NotNull; public class BlockRaytracer extends BlockIterator { @@ -32,14 +33,16 @@ public class BlockRaytracer extends BlockIterator { public Vector getIntersectionPoint() { BlockFace lastFace = getIntersectionFace(); Vector planeNormal = new Vector(lastFace.getModX(), lastFace.getModY(), lastFace.getModZ()); - Vector planePoint = lastBlock.getLocation().add(0.5, 0.5, 0.5).toVector() - .add(planeNormal.clone().multiply(0.5)); + Vector planePoint = lastBlock.getLocation() + .add(0.5, 0.5, 0.5) + .toVector() + .add(planeNormal.clone().multiply(0.5)); return MathUtil.getLinePlaneIntersection(position, direction, planePoint, planeNormal, true); } @Override - public Block next() { + public @NotNull Block next() { Block currentBlock = super.next(); currentFace = lastBlock == null ? BlockFace.SELF : currentBlock.getFace(lastBlock); diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml index afd0bad..c617946 100644 --- a/src/main/resources/plugin.yml +++ b/src/main/resources/plugin.yml @@ -3,5 +3,6 @@ version: '1.0-SNAPSHOT' main: eu.mhsl.minecraft.pixelpic.Main api-version: '1.21' commands: - test: - test2: \ No newline at end of file + pixelPic: + permission: "pixelpic.use" + usage: "pixelpic take"