diff --git a/README.md b/README.md index 026cd3a..6254f88 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,6 @@ # MapReflectionAPI This API helps developer with viewing images on maps. It supports Spigot 1.12 - 1.19. -It currently has **no** support for GIFs. ## Dependencies: diff --git a/src/main/java/tech/sbdevelopment/mapreflectionapi/api/AbstractMapWrapper.java b/src/main/java/tech/sbdevelopment/mapreflectionapi/api/AbstractMapWrapper.java new file mode 100644 index 0000000..b5ba6a6 --- /dev/null +++ b/src/main/java/tech/sbdevelopment/mapreflectionapi/api/AbstractMapWrapper.java @@ -0,0 +1,38 @@ +/* + * This file is part of MapReflectionAPI. + * Copyright (c) 2022 inventivetalent / SBDevelopment - All Rights Reserved + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package tech.sbdevelopment.mapreflectionapi.api; + +public abstract class AbstractMapWrapper { + /** + * Get the controller of this wrapper + * + * @return The {@link MapController} + */ + public abstract IMapController getController(); + + protected void unwrap() { + getController().cancelSend(); + getController().clearViewers(); + } +} diff --git a/src/main/java/tech/sbdevelopment/mapreflectionapi/api/IMapController.java b/src/main/java/tech/sbdevelopment/mapreflectionapi/api/IMapController.java new file mode 100644 index 0000000..f1f9394 --- /dev/null +++ b/src/main/java/tech/sbdevelopment/mapreflectionapi/api/IMapController.java @@ -0,0 +1,85 @@ +/* + * This file is part of MapReflectionAPI. + * Copyright (c) 2022 inventivetalent / SBDevelopment - All Rights Reserved + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package tech.sbdevelopment.mapreflectionapi.api; + +import org.bukkit.OfflinePlayer; +import org.bukkit.entity.Player; +import org.jetbrains.annotations.NotNull; +import tech.sbdevelopment.mapreflectionapi.api.exceptions.MapLimitExceededException; + +public interface IMapController { + /** + * Add a viewer + * + * @param player {@link Player} to add + */ + void addViewer(Player player) throws MapLimitExceededException; + + /** + * Remove a viewer + * + * @param player {@link OfflinePlayer} to remove + */ + void removeViewer(OfflinePlayer player); + + /** + * Remove all viewers + */ + void clearViewers(); + + /** + * Check if a player is viewing + * + * @param player {@link OfflinePlayer} to check + * @return true if the player is viewing + */ + boolean isViewing(OfflinePlayer player); + + /** + * Update the image + * + * @param content new {@link ArrayImage} content + */ + void update(@NotNull ArrayImage content); + + /** + * Send the content to a player + * + * @param player {@link Player} receiver of the content + */ + void sendContent(Player player); + + /** + * Send the content to a player + * + * @param player {@link Player} receiver of the content + * @param withoutQueue if true, the content will be sent immediately + */ + void sendContent(Player player, boolean withoutQueue); + + /** + * Cancels the 'send events' in the queue + */ + void cancelSend(); +} diff --git a/src/main/java/tech/sbdevelopment/mapreflectionapi/api/MapController.java b/src/main/java/tech/sbdevelopment/mapreflectionapi/api/MapController.java index 9653e3f..2179cd8 100644 --- a/src/main/java/tech/sbdevelopment/mapreflectionapi/api/MapController.java +++ b/src/main/java/tech/sbdevelopment/mapreflectionapi/api/MapController.java @@ -27,36 +27,13 @@ import org.bukkit.OfflinePlayer; import org.bukkit.World; import org.bukkit.entity.ItemFrame; import org.bukkit.entity.Player; -import org.jetbrains.annotations.NotNull; -import tech.sbdevelopment.mapreflectionapi.api.exceptions.MapLimitExceededException; -public interface MapController { +public interface MapController extends IMapController { /** - * Add a viewer - * - * @param player {@link Player} to add + * @deprecated Please use {@link MapWrapper#getContent()} */ - void addViewer(Player player) throws MapLimitExceededException; - - /** - * Remove a viewer - * - * @param player {@link OfflinePlayer} to remove - */ - void removeViewer(OfflinePlayer player); - - /** - * Remove all viewers - */ - void clearViewers(); - - /** - * Check if a player is viewing - * - * @param player {@link OfflinePlayer} to check - * @return true if the player is viewing - */ - boolean isViewing(OfflinePlayer player); + @Deprecated(since = "1.3", forRemoval = true) + ArrayImage getContent(); /** * Get the map ID for a player @@ -66,40 +43,6 @@ public interface MapController { */ int getMapId(OfflinePlayer player); - /** - * Update the image - * - * @param content new {@link ArrayImage} content - */ - void update(@NotNull ArrayImage content); - - /** - * Get the content of the controller - * - * @return The {@link ArrayImage} - */ - ArrayImage getContent(); - - /** - * Send the content to a player - * - * @param player {@link Player} receiver of the content - */ - void sendContent(Player player); - - /** - * Send the content to a player - * - * @param player {@link Player} receiver of the content - * @param withoutQueue if true, the content will be sent immediately - */ - void sendContent(Player player, boolean withoutQueue); - - /** - * Cancels the 'send events' in the queue - */ - void cancelSend(); - /** * Show in a player's inventory * diff --git a/src/main/java/tech/sbdevelopment/mapreflectionapi/api/MapManager.java b/src/main/java/tech/sbdevelopment/mapreflectionapi/api/MapManager.java index 2da997a..9b806d8 100644 --- a/src/main/java/tech/sbdevelopment/mapreflectionapi/api/MapManager.java +++ b/src/main/java/tech/sbdevelopment/mapreflectionapi/api/MapManager.java @@ -37,7 +37,7 @@ import java.util.concurrent.CopyOnWriteArrayList; public class MapManager { protected final Set occupiedIds = new HashSet<>(); - private final List managedMaps = new CopyOnWriteArrayList<>(); + protected final List managedMaps = new CopyOnWriteArrayList<>(); /** * Wrap a {@link BufferedImage} in a {@link MapWrapper} @@ -64,6 +64,52 @@ public class MapManager { return wrapNewImage(image); } + /** + * Wrap a {@link BufferedImage} and split it into multiple maps + * + * @param image The image to wrap + * @param rows Rows of the split (i.e. height) + * @param columns Columns of the split (i.e. width) + * @return The wrapper + */ + public MultiMapWrapper wrapMultiImage(BufferedImage image, int rows, int columns) { + //Don't add to managedMaps, because the MultiMapWrapper will do that for us + return new MultiMapWrapper(image, rows, columns); + } + + /** + * Wrap an {@link ArrayImage} and split it into multiple maps + * + * @param image The image to wrap + * @param rows Rows of the split (i.e. height) + * @param columns Columns of the split (i.e. width) + * @return The wrapper + */ + public MultiMapWrapper wrapMultiImage(ArrayImage image, int rows, int columns) { + //Don't add to managedMaps, because the MultiMapWrapper will do that for us + return new MultiMapWrapper(image, rows, columns); + } + + /** + * Wrap multiple {@link BufferedImage}s + * + * @param images The images to wrap + * @return The wrapper + */ + public MultiMapWrapper wrapMultiImage(BufferedImage[][] images) { + return new MultiMapWrapper(images); + } + + /** + * Wrap multiple {@link ArrayImage}s + * + * @param images The images to wrap + * @return The wrapper + */ + public MultiMapWrapper wrapMultiImage(ArrayImage[][] images) { + return new MultiMapWrapper(images); + } + /** * Wrap a new image * @@ -82,8 +128,7 @@ public class MapManager { * @param wrapper The {@link MapWrapper} to unwrap */ public void unwrapImage(MapWrapper wrapper) { - wrapper.controller.cancelSend(); - wrapper.getController().clearViewers(); + wrapper.unwrap(); managedMaps.remove(wrapper); } diff --git a/src/main/java/tech/sbdevelopment/mapreflectionapi/api/MapWrapper.java b/src/main/java/tech/sbdevelopment/mapreflectionapi/api/MapWrapper.java index a812e93..6b851a8 100644 --- a/src/main/java/tech/sbdevelopment/mapreflectionapi/api/MapWrapper.java +++ b/src/main/java/tech/sbdevelopment/mapreflectionapi/api/MapWrapper.java @@ -38,7 +38,7 @@ import tech.sbdevelopment.mapreflectionapi.utils.ReflectionUtil; import java.util.*; -public class MapWrapper { +public class MapWrapper extends AbstractMapWrapper { private static final String REFERENCE_METADATA = "MAP_WRAPPER_REF"; protected ArrayImage content; @@ -59,7 +59,6 @@ public class MapWrapper { private static final Class craftStackClass = ReflectionUtil.getCraftClass("inventory.CraftItemStack"); private static final Class setSlotPacketClass = ReflectionUtil.getNMSClass("network.protocol.game", "PacketPlayOutSetSlot"); - //private static final Class tagCompoundClass = ReflectionUtil.getNMSClass("nbt", "NBTTagCompound"); private static final Class entityClass = ReflectionUtil.getNMSClass("world.entity", "Entity"); private static final Class dataWatcherClass = ReflectionUtil.getNMSClass("network.syncher", "DataWatcher"); private static final Class entityMetadataPacketClass = ReflectionUtil.getNMSClass("network.protocol.game", "PacketPlayOutEntityMetadata"); @@ -176,7 +175,6 @@ public class MapWrapper { inventoryMenuName = "defaultContainer"; } Object inventoryMenu = ReflectionUtil.getField(ReflectionUtil.getHandle(player), inventoryMenuName); -// int windowId = (int) ReflectionUtil.getField(inventoryMenu, ReflectionUtil.supports(17) ? "j" : "windowId"); ItemStack stack; if (ReflectionUtil.supports(13)) { @@ -353,20 +351,11 @@ public class MapWrapper { } }; - /** - * Get the content that is wrapped - * - * @return The {@link ArrayImage} - */ public ArrayImage getContent() { return content; } - /** - * Get the controller of this wrapper - * - * @return The {@link MapController} - */ + @Override public MapController getController() { return controller; } diff --git a/src/main/java/tech/sbdevelopment/mapreflectionapi/api/MultiMapController.java b/src/main/java/tech/sbdevelopment/mapreflectionapi/api/MultiMapController.java new file mode 100644 index 0000000..a30e166 --- /dev/null +++ b/src/main/java/tech/sbdevelopment/mapreflectionapi/api/MultiMapController.java @@ -0,0 +1,153 @@ +/* + * This file is part of MapReflectionAPI. + * Copyright (c) 2022 inventivetalent / SBDevelopment - All Rights Reserved + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package tech.sbdevelopment.mapreflectionapi.api; + +import org.bukkit.OfflinePlayer; +import org.bukkit.entity.ItemFrame; +import org.bukkit.entity.Player; +import org.jetbrains.annotations.NotNull; +import tech.sbdevelopment.mapreflectionapi.api.exceptions.MapLimitExceededException; + +public interface MultiMapController extends IMapController { + /** + * Add a viewer + * + * @param player {@link Player} to add + */ + void addViewer(Player player) throws MapLimitExceededException; + + /** + * Remove a viewer + * + * @param player {@link OfflinePlayer} to remove + */ + void removeViewer(OfflinePlayer player); + + /** + * Remove all viewers + */ + void clearViewers(); + + /** + * Check if a player is viewing + * + * @param player {@link OfflinePlayer} to check + * @return true if the player is viewing + */ + boolean isViewing(OfflinePlayer player); + + /** + * Update the image + * + * @param content new {@link ArrayImage} content + */ + void update(@NotNull ArrayImage content); + + /** + * Send the content to a player + * + * @param player {@link Player} receiver of the content + */ + void sendContent(Player player); + + /** + * Send the content to a player + * + * @param player {@link Player} receiver of the content + * @param withoutQueue if true, the content will be sent immediately + */ + void sendContent(Player player, boolean withoutQueue); + + /** + * Cancels the 'send events' in the queue + */ + void cancelSend(); + + /** + * Show this {@link MultiMapController} in {@link ItemFrame}s + * + * @param player {@link Player} that will be able to see the maps + * @param entityIdMatrix 2D-Array of entity-IDs of the {@link ItemFrame}s (int[width][height]) + * @see MapController#showInFrame(Player, int) + */ + void showInFrames(Player player, int[][] entityIdMatrix); + + /** + * Show this {@link MultiMapController} in {@link ItemFrame}s + * + * @param player {@link Player} that will be able to see the maps + * @param entityIdMatrix 2D-Array of entity-IDs of the {@link ItemFrame}s (int[width][height]) + * @param callable {@link DebugCallable} which will be called to display debug information, or null + * @see MapController#showInFrame(Player, int, String) + */ + void showInFrames(Player player, int[][] entityIdMatrix, DebugCallable callable); + + /** + * Show this {@link MultiMapController} in {@link ItemFrame}s + * + * @param player {@link Player} that will be able to see the maps + * @param itemFrameMatrix 2D-Array of {@link ItemFrame}s (ItemFrame[width][height]) + * @param force if false, the map will not be shown if there is not Map-Item in the ItemFrames + * @see MapController#showInFrame(Player, ItemFrame, boolean) + */ + void showInFrames(Player player, ItemFrame[][] itemFrameMatrix, boolean force); + + /** + * Show this {@link MultiMapController} in {@link ItemFrame}s + * + * @param player {@link Player} that will be able to see the maps + * @param itemFrameMatrix 2D-Array of {@link ItemFrame}s (ItemFrame[width][height]) + * @see MapController#showInFrame(Player, ItemFrame) + */ + void showInFrames(Player player, ItemFrame[][] itemFrameMatrix); + + /** + * Clear the frames + * + * @param player {@link Player} that will be able to see the cleared frames + * @param entityIdMatrix 2D-Array of entity-IDs of the {@link ItemFrame}s (int[width][height]) + */ + void clearFrames(Player player, int[][] entityIdMatrix); + + /** + * Clear the frames + * + * @param player {@link Player} that will be able to see the cleared frames + * @param itemFrameMatrix 2D-Array of {@link ItemFrame}s (ItemFrame[width][height]) + */ + void clearFrames(Player player, ItemFrame[][] itemFrameMatrix); + + interface DebugCallable { + /** + * Called to get debug information for a frame + * + * @param controller the {@link MapController} + * @param x X-Position of the current frame + * @param y Y-Position of the current frame + * @return {@link String} to show when a player looks at the map, or null + * @see MapController#showInFrame(Player, int, String) + */ + String call(MapController controller, int x, int y); + } +} diff --git a/src/main/java/tech/sbdevelopment/mapreflectionapi/api/MultiMapWrapper.java b/src/main/java/tech/sbdevelopment/mapreflectionapi/api/MultiMapWrapper.java new file mode 100644 index 0000000..e83e732 --- /dev/null +++ b/src/main/java/tech/sbdevelopment/mapreflectionapi/api/MultiMapWrapper.java @@ -0,0 +1,229 @@ +/* + * This file is part of MapReflectionAPI. + * Copyright (c) 2022 inventivetalent / SBDevelopment - All Rights Reserved + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package tech.sbdevelopment.mapreflectionapi.api; + +import org.bukkit.OfflinePlayer; +import org.bukkit.entity.ItemFrame; +import org.bukkit.entity.Player; +import org.jetbrains.annotations.NotNull; +import tech.sbdevelopment.mapreflectionapi.MapReflectionAPI; +import tech.sbdevelopment.mapreflectionapi.api.exceptions.MapLimitExceededException; + +import java.awt.*; +import java.awt.image.BufferedImage; +import java.util.HashSet; +import java.util.Set; +import java.util.UUID; + +public class MultiMapWrapper extends AbstractMapWrapper { + private final MapWrapper[][] wrapperMatrix; + + public MultiMapWrapper(BufferedImage image, int rows, int columns) { + this(splitImage(image, columns, rows)); + } + + public MultiMapWrapper(ArrayImage image, int rows, int columns) { + this(splitImage(image.toBuffered(), columns, rows)); + } + + public MultiMapWrapper(ArrayImage[][] imageMatrix) { + wrapperMatrix = new MapWrapper[imageMatrix.length][imageMatrix[0].length]; + + for (int x = 0; x < imageMatrix.length; x++) { + if (imageMatrix[x].length != imageMatrix[0].length) { + throw new IllegalArgumentException("An image in a MultiMapWrapper is not rectangular!"); + } + + for (int y = 0; y < imageMatrix[x].length; y++) { + wrapperMatrix[x][y] = MapReflectionAPI.getMapManager().wrapImage(imageMatrix[x][y]); + } + } + } + + public MultiMapWrapper(BufferedImage[][] imageMatrix) { + wrapperMatrix = new MapWrapper[imageMatrix.length][imageMatrix[0].length]; + + for (int x = 0; x < imageMatrix.length; x++) { + if (imageMatrix[x].length != imageMatrix[0].length) { + throw new IllegalArgumentException("An image in a MultiMapWrapper is not rectangular!"); + } + + for (int y = 0; y < imageMatrix[x].length; y++) { + wrapperMatrix[x][y] = MapReflectionAPI.getMapManager().wrapImage(imageMatrix[x][y]); + } + } + } + + private final MultiMapController controller = new MultiMapController() { + private final Set viewers = new HashSet<>(); + + @Override + public void addViewer(Player player) throws MapLimitExceededException { + if (!viewers.contains(player.getUniqueId())) { + for (MapWrapper[] mapWrappers : wrapperMatrix) { + for (MapWrapper wrapper : mapWrappers) { + wrapper.getController().addViewer(player); + } + } + viewers.add(player.getUniqueId()); + } + } + + @Override + public void removeViewer(OfflinePlayer player) { + for (MapWrapper[] mapWrappers : wrapperMatrix) { + for (MapWrapper wrapper : mapWrappers) { + wrapper.getController().removeViewer(player); + } + } + viewers.remove(player.getUniqueId()); + } + + @Override + public void clearViewers() { + for (MapWrapper[] mapWrappers : wrapperMatrix) { + for (MapWrapper wrapper : mapWrappers) { + wrapper.getController().clearViewers(); + } + } + viewers.clear(); + } + + @Override + public boolean isViewing(OfflinePlayer player) { + return viewers.contains(player.getUniqueId()); + } + + @Override + public void update(@NotNull ArrayImage content) { + ArrayImage[][] split = splitImage(content.toBuffered(), wrapperMatrix[0].length, wrapperMatrix.length); + for (int x = 0; x < wrapperMatrix.length; x++) { + for (int y = 0; y < wrapperMatrix[x].length; y++) { + wrapperMatrix[x][y].getController().update(split[x][y]); + } + } + } + + @Override + public void sendContent(Player player) { + sendContent(player, false); + } + + @Override + public void sendContent(Player player, boolean withoutQueue) { + for (MapWrapper[] mapWrappers : wrapperMatrix) { + for (MapWrapper wrapper : mapWrappers) { + wrapper.getController().sendContent(player, withoutQueue); + } + } + } + + @Override + public void cancelSend() { + for (MapWrapper[] mapWrappers : wrapperMatrix) { + for (MapWrapper wrapper : mapWrappers) { + wrapper.getController().cancelSend(); + } + } + } + + @Override + public void showInFrames(Player player, int[][] entityIdMatrix) { + for (int x = 0; x < entityIdMatrix.length; x++) { + for (int y = 0; y < entityIdMatrix[x].length; y++) { + wrapperMatrix[y][x].getController().showInFrame(player, entityIdMatrix[x][wrapperMatrix.length - 1 - y]); + } + } + } + + @Override + public void showInFrames(Player player, int[][] entityIdMatrix, DebugCallable callable) { + for (int x = 0; x < entityIdMatrix.length; x++) { + for (int y = 0; y < entityIdMatrix[x].length; y++) { + wrapperMatrix[y][x].getController().showInFrame(player, entityIdMatrix[x][wrapperMatrix.length - 1 - y], callable.call(wrapperMatrix[y][x].getController(), x, y)); + } + } + } + + @Override + public void showInFrames(Player player, ItemFrame[][] itemFrameMatrix, boolean force) { + for (int x = 0; x < itemFrameMatrix.length; x++) { + for (int y = 0; y < itemFrameMatrix[x].length; y++) { + wrapperMatrix[y][x].getController().showInFrame(player, itemFrameMatrix[x][wrapperMatrix.length - 1 - y], force); + } + } + } + + @Override + public void showInFrames(Player player, ItemFrame[][] itemFrameMatrix) { + showInFrames(player, itemFrameMatrix, false); + } + + @Override + public void clearFrames(Player player, int[][] entityIdMatrix) { + for (int x = 0; x < entityIdMatrix.length; x++) { + for (int y = 0; y < entityIdMatrix[x].length; y++) { + wrapperMatrix[y][x].getController().clearFrame(player, entityIdMatrix[x][y]); + } + } + } + + @Override + public void clearFrames(Player player, ItemFrame[][] itemFrameMatrix) { + for (int x = 0; x < itemFrameMatrix.length; x++) { + for (int y = 0; y < itemFrameMatrix[x].length; y++) { + wrapperMatrix[y][x].getController().clearFrame(player, itemFrameMatrix[x][y]); + } + } + } + }; + + /* + * Modified Method from http://kalanir.blogspot.de/2010/02/how-to-split-image-into-chunks-java.html + */ + private static ArrayImage[][] splitImage(final BufferedImage image, final int columns, final int rows) { + int chunkWidth = image.getWidth() / columns; + int chunkHeight = image.getHeight() / rows; + + ArrayImage[][] images = new ArrayImage[rows][columns]; + for (int x = 0; x < rows; x++) { + for (int y = 0; y < columns; y++) { + BufferedImage raw = new BufferedImage(chunkWidth, chunkHeight, image.getType()); + + Graphics2D gr = raw.createGraphics(); + gr.drawImage(image, 0, 0, chunkWidth, chunkHeight, chunkWidth * y, chunkHeight * x, chunkWidth * y + chunkWidth, chunkHeight * x + chunkHeight, null); + gr.dispose(); + + images[x][y] = new ArrayImage(raw); + raw.flush(); + } + } + return images; + } + + @Override + public MultiMapController getController() { + return controller; + } +}