1.13 + 1.14 compatibility: the beginning.

- The plugin should be compatible with 1.13+. Compatibility with 1.12- has been dropped; use old versions for them.
- Map IDs are integer instead of shorts now, as the maps limits has been dropped by Minecraft.
- ImageOnMap items are now green to differentiate them. Map parts are lime.
- Removed glow on maps, as zLib's glow effect is not compatible with 1.13+.
This commit is contained in:
Amaury Carrade 2019-10-26 14:26:12 +02:00
parent 4653008e5a
commit fd483d6088
21 changed files with 260 additions and 179 deletions

10
pom.xml
View File

@ -3,13 +3,13 @@
<modelVersion>4.0.0</modelVersion>
<groupId>fr.moribus</groupId>
<artifactId>ImageOnMap</artifactId>
<version>3.1</version>
<version>4.0</version>
<packaging>jar</packaging>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.7</maven.compiler.source>
<maven.compiler.target>1.7</maven.compiler.target>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
</properties>
<build>
@ -46,7 +46,7 @@
<repositories>
<repository>
<id>spigot-repo</id>
<url>https://hub.spigotmc.org/nexus/content/groups/public/</url>
<url>https://hub.spigotmc.org/nexus/content/repositories/snapshots/</url>
</repository>
<repository>
<id>zDevelopers</id>
@ -58,7 +58,7 @@
<dependency>
<groupId>org.bukkit</groupId>
<artifactId>bukkit</artifactId>
<version>1.8.3-R0.1-SNAPSHOT</version>
<version>1.13.2-R0.1-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>fr.zcraft</groupId>

View File

@ -18,13 +18,7 @@
package fr.moribus.imageonmap;
import fr.moribus.imageonmap.commands.maptool.DeleteCommand;
import fr.moribus.imageonmap.commands.maptool.ExploreCommand;
import fr.moribus.imageonmap.commands.maptool.GetCommand;
import fr.moribus.imageonmap.commands.maptool.GetRemainingCommand;
import fr.moribus.imageonmap.commands.maptool.ListCommand;
import fr.moribus.imageonmap.commands.maptool.MigrateCommand;
import fr.moribus.imageonmap.commands.maptool.NewCommand;
import fr.moribus.imageonmap.commands.maptool.*;
import fr.moribus.imageonmap.image.ImageIOExecutor;
import fr.moribus.imageonmap.image.ImageRendererExecutor;
import fr.moribus.imageonmap.image.MapInitEvent;
@ -64,7 +58,7 @@ public final class ImageOnMap extends ZPlugin
public File getImagesDirectory() {return imagesDirectory;}
public File getMapsDirectory() {return mapsDirectory;}
public File getImageFile(short mapID)
public File getImageFile(int mapID)
{
return new File(imagesDirectory, "map"+mapID+".png");
}
@ -79,7 +73,7 @@ public final class ImageOnMap extends ZPlugin
imagesDirectory = checkPluginDirectory(imagesDirectory, V3Migrator.getOldImagesDirectory(this));
checkPluginDirectory(mapsDirectory);
}
catch(IOException ex)
catch(final IOException ex)
{
PluginLogger.error("FATAL: " + ex.getMessage());
this.setEnabled(false);

View File

@ -74,7 +74,7 @@ public class ListCommand extends IoMCommand
.then(map.getId())
.color(ChatColor.WHITE)
.command(GetCommand.class, map.getId())
.hover(new ItemStackBuilder(Material.MAP)
.hover(new ItemStackBuilder(Material.FILLED_MAP)
.title(ChatColor.GREEN + "" + ChatColor.BOLD + map.getName())
.lore(ChatColor.GRAY + map.getId() + ", " + size)
.lore("")

View File

@ -29,13 +29,9 @@ import fr.zcraft.zlib.components.i18n.I;
import fr.zcraft.zlib.tools.PluginLogger;
import fr.zcraft.zlib.tools.items.ItemStackBuilder;
import org.bukkit.ChatColor;
import org.bukkit.DyeColor;
import org.bukkit.Material;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import org.bukkit.material.Dye;
import java.util.Arrays;
import java.util.Random;
@ -106,7 +102,7 @@ public class ConfirmDeleteMapGui extends ActionGui
/* ** Item representation of the image being deleted ** */
action("", 13, new ItemStackBuilder(Material.EMPTY_MAP)
action("", 13, new ItemStackBuilder(Material.FILLED_MAP)
/// The title of the map deletion item
.title(I.t(getPlayerLocale(), "{red}You're about to destroy this map..."))
/// The end, in the lore, of a title starting with You're about to destroy this map....
@ -134,32 +130,21 @@ public class ConfirmDeleteMapGui extends ActionGui
private ItemStack createDeleteSubButton()
{
// Orange? Nooo. In the real world this is red. True story.
return createSubButton(DyeColor.ORANGE, ChatColor.RED + "Delete the map", DELETE_MESSAGES);
return createSubButton(Material.RED_STAINED_GLASS_PANE, ChatColor.RED + "Delete the map", DELETE_MESSAGES);
}
private ItemStack createCancelSubButton()
{
// YES. Purple = lime. BECAUSE. Just accept it.
return createSubButton(DyeColor.PURPLE, ChatColor.GREEN + "Cancel", CANCEL_MESSAGES);
return createSubButton(Material.LIME_STAINED_GLASS_PANE, ChatColor.GREEN + "Cancel", CANCEL_MESSAGES);
}
private ItemStack createSubButton(DyeColor color, String title, String[] messages)
private ItemStack createSubButton(Material color, String title, String[] messages)
{
Dye pane = new Dye(Material.STAINED_GLASS_PANE);
pane.setColor(color);
ItemStack subButton = pane.toItemStack(1);
ItemMeta meta = subButton.getItemMeta();
meta.setDisplayName(title);
meta.setLore(Arrays.asList(
"",
ChatColor.GRAY + messages[random.nextInt(messages.length)]
));
subButton.setItemMeta(meta);
return subButton;
return new ItemStackBuilder(color)
.title(title)
.loreSeparator()
.longLore(ChatColor.GRAY + messages[random.nextInt(messages.length)])
.item();
}
@GuiAction ("cancel")

View File

@ -35,7 +35,7 @@ import org.bukkit.Material;
import org.bukkit.inventory.ItemStack;
public class MapDetailGui extends ExplorerGui<Short>
public class MapDetailGui extends ExplorerGui<Integer>
{
private final ImageMap map;
@ -47,7 +47,7 @@ public class MapDetailGui extends ExplorerGui<Short>
@Override
protected ItemStack getViewItem(int x, int y)
{
final Material partMaterial = y % 2 == x % 2 ? Material.EMPTY_MAP : Material.PAPER;
final Material partMaterial = y % 2 == x % 2 ? Material.MAP : Material.PAPER;
final ItemStackBuilder builder = new ItemStackBuilder(partMaterial)
.title(I.t(getPlayerLocale(), "{green}Map part"))
@ -61,10 +61,10 @@ public class MapDetailGui extends ExplorerGui<Short>
}
@Override
protected ItemStack getViewItem(Short mapId)
protected ItemStack getViewItem(Integer mapId)
{
final int index = ((PosterMap) map).getIndex(mapId);
final Material partMaterial = index % 2 == 0 ? Material.EMPTY_MAP : Material.PAPER;
final Material partMaterial = index % 2 == 0 ? Material.MAP : Material.PAPER;
final ItemStackBuilder builder = new ItemStackBuilder(partMaterial)
.title(I.t(getPlayerLocale(), "{green}Map part"))
@ -95,7 +95,7 @@ public class MapDetailGui extends ExplorerGui<Short>
}
@Override
protected ItemStack getPickedUpItem(Short mapId)
protected ItemStack getPickedUpItem(Integer mapId)
{
if (!Permissions.GET.grantedTo(getPlayer()))
return null;
@ -149,7 +149,7 @@ public class MapDetailGui extends ExplorerGui<Short>
if (canRename)
{
action("rename", renameSlot, new ItemStackBuilder(Material.BOOK_AND_QUILL)
action("rename", renameSlot, new ItemStackBuilder(Material.WRITABLE_BOOK)
.title(I.t(getPlayerLocale(), "{blue}Rename this image"))
.longLore(I.t(getPlayerLocale(), "{gray}Click here to rename this image; this is used for your own organization."))
);

View File

@ -29,8 +29,10 @@ import fr.zcraft.zlib.components.gui.ExplorerGui;
import fr.zcraft.zlib.components.gui.Gui;
import fr.zcraft.zlib.components.i18n.I;
import fr.zcraft.zlib.tools.items.ItemStackBuilder;
import org.bukkit.Color;
import org.bukkit.Material;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.MapMeta;
public class MapListGui extends ExplorerGui<ImageMap>
@ -58,34 +60,41 @@ public class MapListGui extends ExplorerGui<ImageMap>
mapDescription = I.t(getPlayerLocale(), "{white}Poster map ({0} parts)", poster.getMapCount());
}
}
ItemStackBuilder builder = new ItemStackBuilder(Material.MAP)
ItemStackBuilder builder = new ItemStackBuilder(Material.FILLED_MAP)
/// Displayed title of a map on the list GUI
.title(I.t(getPlayerLocale(), "{green}{bold}{0}", map.getName()))
.title(I.tl(getPlayerLocale(), "{green}{bold}{0}", map.getName()))
.lore(mapDescription)
.loreLine()
/// Map ID displayed in the tooltip of a map on the list GUI
.lore(I.t(getPlayerLocale(), "{gray}Map ID: {0}", map.getId()))
.lore(I.tl(getPlayerLocale(), "{gray}Map ID: {0}", map.getId()))
.loreLine();
if (Permissions.GET.grantedTo(getPlayer()))
builder.lore(I.t(getPlayerLocale(), "{gray}» {white}Left-click{gray} to get this map"));
builder.lore(I.tl(getPlayerLocale(), "{gray}» {white}Left-click{gray} to get this map"));
builder.lore(I.t(getPlayerLocale(), "{gray}» {white}Right-click{gray} for details and options"));
builder.lore(I.tl(getPlayerLocale(), "{gray}» {white}Right-click{gray} for details and options"));
return builder.item();
final ItemStack mapItem = builder.item();
final MapMeta meta = (MapMeta) mapItem.getItemMeta();
meta.setColor(Color.GREEN);
mapItem.setItemMeta(meta);
return mapItem;
}
@Override
protected ItemStack getEmptyViewItem()
{
ItemStackBuilder builder = new ItemStackBuilder(Material.BARRIER)
.title(I.t(getPlayerLocale(), "{red}You don't have any map."));
.title(I.tl(getPlayerLocale(), "{red}You don't have any map."));
if (Permissions.NEW.grantedTo(getPlayer()))
builder.longLore(I.t(getPlayerLocale(), "{gray}Get started by creating a new one using {white}/tomap <URL> [resize]{gray}!"));
builder.longLore(I.tl(getPlayerLocale(), "{gray}Get started by creating a new one using {white}/tomap <URL> [resize]{gray}!"));
else
builder.longLore(I.t(getPlayerLocale(), "{gray}Unfortunately, you are not allowed to create one."));
builder.longLore(I.tl(getPlayerLocale(), "{gray}Unfortunately, you are not allowed to create one."));
return builder.item();
}
@ -104,7 +113,7 @@ public class MapListGui extends ExplorerGui<ImageMap>
if (map instanceof SingleMap)
{
return MapItemManager.createMapItem(map.getMapsIDs()[0], map.getName());
return MapItemManager.createMapItem(map.getMapsIDs()[0], map.getName(), false);
}
else if (map instanceof PosterMap)
{
@ -128,7 +137,7 @@ public class MapListGui extends ExplorerGui<ImageMap>
setData(maps);
/// The maps list GUI title
setTitle(I.t(getPlayerLocale(), "{black}Your maps {reset}({0})", maps.length));
setTitle(I.tl(getPlayerLocale(), "{black}Your maps {reset}({0})", maps.length));
setKeepHorizontalScrollingSpace(true);

View File

@ -60,12 +60,12 @@ public class ImageIOExecutor extends Worker
});
}
static public void saveImage(short mapID, BufferedImage image)
static public void saveImage(int mapID, BufferedImage image)
{
saveImage(ImageOnMap.getPlugin().getImageFile(mapID), image);
}
static public void saveImage(short[] mapsIDs, PosterImage image)
static public void saveImage(int[] mapsIDs, PosterImage image)
{
for(int i = 0, c = mapsIDs.length; i < c; i++)
{
@ -75,7 +75,7 @@ public class ImageIOExecutor extends Worker
static public void deleteImage(ImageMap map)
{
short[] mapsIDs = map.getMapsIDs();
int[] mapsIDs = map.getMapsIDs();
for(int i = 0, c = mapsIDs.length; i < c; i++)
{
deleteImage(ImageOnMap.getPlugin().getImageFile(mapsIDs[i]));

View File

@ -77,16 +77,16 @@ public class ImageRendererExecutor extends Worker
static private ImageMap renderSingle(final BufferedImage image, final UUID playerUUID) throws Throwable
{
MapManager.checkMapLimit(1, playerUUID);
final Future<Short> futureMapID = submitToMainThread(new Callable<Short>()
final Future<Integer> futureMapID = submitToMainThread(new Callable<Integer>()
{
@Override
public Short call() throws Exception
public Integer call() throws Exception
{
return MapManager.getNewMapsIds(1)[0];
}
});
final short mapID = futureMapID.get();
final int mapID = futureMapID.get();
ImageIOExecutor.saveImage(mapID, image);
submitToMainThread(new Callable<Void>()
@ -108,10 +108,10 @@ public class ImageRendererExecutor extends Worker
final int mapCount = poster.getImagesCount();
MapManager.checkMapLimit(mapCount, playerUUID);
final Future<short[]> futureMapsIds = submitToMainThread(new Callable<short[]>()
final Future<int[]> futureMapsIds = submitToMainThread(new Callable<int[]>()
{
@Override
public short[] call() throws Exception
public int[] call() throws Exception
{
return MapManager.getNewMapsIds(mapCount);
}
@ -119,7 +119,7 @@ public class ImageRendererExecutor extends Worker
poster.splitImages();
final short[] mapsIDs = futureMapsIds.get();
final int[] mapsIDs = futureMapsIds.get();
ImageIOExecutor.saveImage(mapsIDs, poster);

View File

@ -19,25 +19,26 @@
package fr.moribus.imageonmap.image;
import fr.moribus.imageonmap.ImageOnMap;
import fr.moribus.imageonmap.map.MapManager;
import fr.zcraft.zlib.core.ZLib;
import java.io.File;
import org.bukkit.Bukkit;
import org.bukkit.Material;
import org.bukkit.World;
import org.bukkit.entity.Entity;
import org.bukkit.entity.HumanEntity;
import org.bukkit.entity.ItemFrame;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.entity.EntityPickupItemEvent;
import org.bukkit.event.inventory.InventoryClickEvent;
import org.bukkit.event.player.PlayerInteractEntityEvent;
import org.bukkit.event.player.PlayerItemHeldEvent;
import org.bukkit.event.player.PlayerPickupItemEvent;
import org.bukkit.event.world.ChunkLoadEvent;
import org.bukkit.inventory.ItemStack;
import org.bukkit.map.MapView;
import java.io.File;
public class MapInitEvent implements Listener
{
static public void init()
@ -54,7 +55,7 @@ public class MapInitEvent implements Listener
for(Player player : Bukkit.getOnlinePlayers())
{
initMap(player.getItemInHand());
initMap(player.getInventory().getItemInMainHand());
}
}
@ -78,10 +79,10 @@ public class MapInitEvent implements Listener
}
@EventHandler
public void onPlayerPickup(PlayerPickupItemEvent event)
public void onPlayerPickup(EntityPickupItemEvent event)
{
ItemStack item = event.getItem().getItemStack();
initMap(item);
if (!(event.getEntity() instanceof HumanEntity)) return;
initMap(event.getItem().getItemStack());
}
@EventHandler
@ -99,15 +100,15 @@ public class MapInitEvent implements Listener
static public void initMap(ItemStack item)
{
if (item != null && item.getType() == Material.MAP)
if (item != null && item.getType() == Material.FILLED_MAP)
{
initMap(item.getDurability());
initMap(MapManager.getMapIdFromItemStack(item));
}
}
static public void initMap(short id)
static public void initMap(int id)
{
initMap(Bukkit.getMap(id));
initMap(Bukkit.getServer().getMap(id));
}
static public void initMap(MapView map)

View File

@ -19,13 +19,14 @@
package fr.moribus.imageonmap.image;
import fr.zcraft.zlib.tools.PluginLogger;
import java.awt.image.BufferedImage;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import org.bukkit.map.MapCanvas;
import org.bukkit.map.MapRenderer;
import org.bukkit.map.MapView;
import java.awt.image.BufferedImage;
public class Renderer extends MapRenderer
{
static public boolean isHandled(MapView map)
@ -38,7 +39,7 @@ public class Renderer extends MapRenderer
return false;
}
static public void installRenderer(PosterImage image, short[] mapsIds)
static public void installRenderer(PosterImage image, int[] mapsIds)
{
for(int i = 0; i < mapsIds.length; i++)
{
@ -46,12 +47,12 @@ public class Renderer extends MapRenderer
}
}
static public void installRenderer(BufferedImage image, short mapID)
static public void installRenderer(BufferedImage image, int mapID)
{
MapView map = Bukkit.getMap(mapID);
if(map == null)
{
PluginLogger.warning("Could not install renderer for map {0} : the Minecraft map does not exist", mapID);
PluginLogger.warning("Could not install renderer for map {0}: the Minecraft map does not exist", mapID);
}
else
{

View File

@ -68,15 +68,15 @@ public abstract class ImageMap implements ConfigurationSerializable
}
public abstract short[] getMapsIDs();
public abstract boolean managesMap(short mapID);
public abstract int[] getMapsIDs();
public abstract boolean managesMap(int mapID);
public abstract int getMapCount();
public boolean managesMap(ItemStack item)
{
if(item == null) return false;
if(item.getType() != Material.MAP) return false;
return managesMap(item.getDurability());
if(item.getType() != Material.FILLED_MAP) return false;
return managesMap(MapManager.getMapIdFromItemStack(item));
}
public boolean give(Player player)

View File

@ -28,6 +28,8 @@ import org.bukkit.Bukkit;
import org.bukkit.Material;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import org.bukkit.inventory.meta.MapMeta;
import org.bukkit.scheduler.BukkitTask;
import java.io.File;
@ -53,7 +55,7 @@ abstract public class MapManager
if(autosaveTask != null) autosaveTask.cancel();
}
static public boolean managesMap(short mapID)
static public boolean managesMap(int mapID)
{
synchronized(playerMaps)
{
@ -68,7 +70,7 @@ abstract public class MapManager
static public boolean managesMap(ItemStack item)
{
if(item == null) return false;
if(item.getType() != Material.MAP) return false;
if(item.getType() != Material.FILLED_MAP) return false;
synchronized(playerMaps)
{
@ -80,14 +82,14 @@ abstract public class MapManager
return false;
}
static public ImageMap createMap(UUID playerUUID, short mapID) throws MapManagerException
static public ImageMap createMap(UUID playerUUID, int mapID) throws MapManagerException
{
ImageMap newMap = new SingleMap(playerUUID, mapID);
addMap(newMap);
return newMap;
}
static public ImageMap createMap(PosterImage image, UUID playerUUID, short[] mapsIDs) throws MapManagerException
static public ImageMap createMap(PosterImage image, UUID playerUUID, int[] mapsIDs) throws MapManagerException
{
ImageMap newMap;
if(image.getImagesCount() == 1)
@ -102,15 +104,28 @@ abstract public class MapManager
return newMap;
}
static public short[] getNewMapsIds(int amount)
static public int[] getNewMapsIds(int amount)
{
short[] mapsIds = new short[amount];
int[] mapsIds = new int[amount];
for(int i = 0; i < amount; i++)
{
mapsIds[i] = Bukkit.createMap(Bukkit.getWorlds().get(0)).getId();
}
return mapsIds;
}
/**
* Returns the map ID from an ItemStack
* @param item The item stack
* @return The map ID, or 0 if invalid.
*/
static public int getMapIdFromItemStack(final ItemStack item)
{
final ItemMeta meta = item.getItemMeta();
if (!(meta instanceof MapMeta)) return 0;
return ((MapMeta) meta).hasMapId() ? ((MapMeta) meta).getMapId() : 0;
}
static public void addMap(ImageMap map) throws MapManagerException
{
@ -173,7 +188,7 @@ abstract public class MapManager
* @param mapId The ID of the Minecraft map.
* @return The {@link ImageMap}.
*/
static public ImageMap getMap(short mapId)
static public ImageMap getMap(int mapId)
{
synchronized(playerMaps)
{
@ -204,8 +219,8 @@ abstract public class MapManager
static public ImageMap getMap(ItemStack item)
{
if(item == null) return null;
if(item.getType() != Material.MAP) return null;
return getMap(item.getDurability());
if(item.getType() != Material.FILLED_MAP) return null;
return getMap(getMapIdFromItemStack(item));
}
static public void clear(Inventory inventory)
@ -312,7 +327,7 @@ abstract public class MapManager
* @param mapId the map ID.
* @return true if the given map ID is valid and exists in the current save, false otherwise.
*/
static public boolean mapIdExists(short mapId)
static public boolean mapIdExists(int mapId)
{
try
{

View File

@ -50,7 +50,7 @@ public class PlayerMapStore implements ConfigurationSerializable
this.playerUUID = playerUUID;
}
public synchronized boolean managesMap(short mapID)
public synchronized boolean managesMap(int mapID)
{
for(ImageMap map : mapList)
{
@ -62,7 +62,7 @@ public class PlayerMapStore implements ConfigurationSerializable
public synchronized boolean managesMap(ItemStack item)
{
if(item == null) return false;
if(item.getType() != Material.MAP) return false;
if(item.getType() != Material.FILLED_MAP) return false;
for(ImageMap map : mapList)
{

View File

@ -26,11 +26,11 @@ import java.util.UUID;
public class PosterMap extends ImageMap
{
protected final short[] mapsIDs;
protected final int[] mapsIDs;
protected final int columnCount;
protected final int rowCount;
public PosterMap(UUID userUUID, short[] mapsIDs, String id, String name, int columnCount, int rowCount)
public PosterMap(UUID userUUID, int[] mapsIDs, String id, String name, int columnCount, int rowCount)
{
super(userUUID, Type.POSTER, id, name);
this.mapsIDs = mapsIDs;
@ -38,19 +38,19 @@ public class PosterMap extends ImageMap
this.rowCount = Math.max(rowCount, 0);
}
public PosterMap(UUID userUUID, short[] mapsIDs, int columnCount, int rowCount)
public PosterMap(UUID userUUID, int[] mapsIDs, int columnCount, int rowCount)
{
this(userUUID, mapsIDs, null, null, columnCount, rowCount);
}
@Override
public short[] getMapsIDs()
public int[] getMapsIDs()
{
return mapsIDs;
}
@Override
public boolean managesMap(short mapID)
public boolean managesMap(int mapID)
{
for(int i = 0; i < mapsIDs.length; i++)
{
@ -70,10 +70,10 @@ public class PosterMap extends ImageMap
rowCount = getFieldValue(map, "rows");
List<Integer> idList = getFieldValue(map, "mapsIDs");
mapsIDs = new short[idList.size()];
mapsIDs = new int[idList.size()];
for(int i = 0, c = idList.size(); i < c; i++)
{
mapsIDs[i] = (short) ((int) idList.get(i));
mapsIDs[i] = (int) idList.get(i);
}
}
@ -131,19 +131,19 @@ public class PosterMap extends ImageMap
*
* @throws ArrayIndexOutOfBoundsException if the given coordinates are too big (out of the poster).
*/
public short getMapIdAt(int x, int y)
public int getMapIdAt(int x, int y)
{
return mapsIDs[y * columnCount + x];
}
public short getMapIdAtReverseY(int index)
public int getMapIdAtReverseY(int index)
{
int x = index % (columnCount);
int y = index / (columnCount);
return getMapIdAt(x, rowCount - y - 1);
}
public short getMapIdAt(int index)
public int getMapIdAt(int index)
{
return mapsIDs[index];
}
@ -159,7 +159,7 @@ public class PosterMap extends ImageMap
return mapsIDs.length;
}
public int getIndex(short mapID)
public int getIndex(int mapID)
{
for(int i = 0; i < mapsIDs.length; i++)
{

View File

@ -18,33 +18,34 @@
package fr.moribus.imageonmap.map;
import org.bukkit.configuration.InvalidConfigurationException;
import java.util.Map;
import java.util.UUID;
import org.bukkit.configuration.InvalidConfigurationException;
public class SingleMap extends ImageMap
{
protected final short mapID;
protected final int mapID;
public SingleMap(UUID ownerUUID, short mapID, String id, String name)
public SingleMap(UUID ownerUUID, int mapID, String id, String name)
{
super(ownerUUID, Type.SINGLE, id, name);
this.mapID = mapID;
}
public SingleMap(UUID ownerUUID, short mapID)
public SingleMap(UUID ownerUUID, int mapID)
{
this(ownerUUID, mapID, null, null);
}
@Override
public short[] getMapsIDs()
public int[] getMapsIDs()
{
return new short[]{mapID};
return new int[]{mapID};
}
@Override
public boolean managesMap(short mapID)
public boolean managesMap(int mapID)
{
return this.mapID == mapID;
}
@ -60,8 +61,7 @@ public class SingleMap extends ImageMap
public SingleMap(Map<String, Object> map, UUID userUUID) throws InvalidConfigurationException
{
super(map, userUUID, Type.SINGLE);
int _mapID = getFieldValue(map, "mapID");
mapID = (short) _mapID;//Meh
mapID = getFieldValue(map, "mapID");
}
@Override

View File

@ -21,12 +21,14 @@ package fr.moribus.imageonmap.migration;
import fr.moribus.imageonmap.map.ImageMap;
import fr.moribus.imageonmap.map.MapManager;
import fr.moribus.imageonmap.map.PosterMap;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import org.bukkit.configuration.Configuration;
import org.bukkit.configuration.InvalidConfigurationException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.UUID;
class OldSavedPoster
{
private final String userName;
@ -78,7 +80,11 @@ class OldSavedPoster
public ImageMap toImageMap(UUID userUUID)
{
return new PosterMap(userUUID, mapsIds, null, "poster", 0, 0);
// Converts the maps IDs to int as MC 1.13.2+ uses integer ids
final int[] mapsIdsInt = new int[mapsIds.length];
Arrays.setAll(mapsIdsInt, i -> mapsIds[i]);
return new PosterMap(userUUID, mapsIdsInt, null, "poster", 0, 0);
}
public void serialize(Configuration configuration)

View File

@ -23,6 +23,8 @@ import fr.moribus.imageonmap.map.MapManager;
import fr.zcraft.zlib.components.i18n.I;
import fr.zcraft.zlib.tools.PluginLogger;
import fr.zcraft.zlib.tools.mojang.UUIDFetcher;
import org.apache.commons.lang.ArrayUtils;
import org.apache.commons.lang.StringUtils;
import org.bukkit.configuration.InvalidConfigurationException;
import org.bukkit.configuration.file.FileConfiguration;
import org.bukkit.configuration.file.YamlConfiguration;
@ -37,14 +39,8 @@ import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Map;
import java.util.UUID;
import org.apache.commons.lang.ArrayUtils;
import org.apache.commons.lang.StringUtils;
import java.util.*;
import java.util.stream.Collectors;
/**
* This class represents and executes the ImageOnMap v3.x migration process
@ -427,7 +423,7 @@ public class V3Migrator implements Runnable
ArrayDeque<OldSavedMap> remainingMaps = new ArrayDeque<>();
ArrayDeque<OldSavedPoster> remainingPosters = new ArrayDeque<>();
ArrayDeque<Short> missingMapIds = new ArrayDeque<>();
ArrayDeque<Integer> missingMapIds = new ArrayDeque<>();
UUID playerUUID;
OldSavedMap map;
@ -441,7 +437,7 @@ public class V3Migrator implements Runnable
}
else if(!map.isMapValid())
{
missingMapIds.add(map.getMapId());
missingMapIds.add((int) map.getMapId());
}
else
{
@ -461,7 +457,7 @@ public class V3Migrator implements Runnable
}
else if(!poster.isMapValid())
{
missingMapIds.addAll(Arrays.asList(ArrayUtils.toObject(poster.getMapsIds())));
missingMapIds.addAll(Arrays.stream(ArrayUtils.toObject(poster.getMapsIds())).map(id -> (int) id).collect(Collectors.toList()));
}
else
{

View File

@ -22,10 +22,14 @@ import fr.moribus.imageonmap.map.ImageMap;
import fr.moribus.imageonmap.map.MapManager;
import fr.moribus.imageonmap.map.PosterMap;
import fr.moribus.imageonmap.map.SingleMap;
import fr.zcraft.zlib.components.attributes.Attributes;
import fr.zcraft.zlib.components.i18n.I;
import fr.zcraft.zlib.core.ZLib;
import fr.zcraft.zlib.tools.PluginLogger;
import fr.zcraft.zlib.tools.items.ItemStackBuilder;
import fr.zcraft.zlib.tools.items.ItemUtils;
import fr.zcraft.zlib.tools.reflection.NMSException;
import org.bukkit.Color;
import org.bukkit.GameMode;
import org.bukkit.Material;
import org.bukkit.entity.ItemFrame;
@ -37,6 +41,7 @@ import org.bukkit.event.entity.EntityDamageByEntityEvent;
import org.bukkit.event.player.PlayerInteractEntityEvent;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.MapMeta;
import java.util.ArrayDeque;
import java.util.HashMap;
@ -114,54 +119,77 @@ public class MapItemManager implements Listener
return givenItemsCount;
}
static private boolean give(Player player, ItemStack item)
static private boolean give(final Player player, final ItemStack item)
{
if(player.getInventory().firstEmpty() <= -1)
final int freeSlot = player.getInventory().firstEmpty();
if (freeSlot != -1)
{
getCache(player).add(item);
return true;
player.getInventory().setItem(freeSlot, item);
// If this is a splatter map, we have to re-add the splatter attribute, because
// for some reason, the `addItem` or `setItem` methods removes the attribute in
// Minecraft 1.14+, breaking the auto-deploy feature.
if (SplatterMapManager.hasSplatterAttributes(item))
{
try
{
Attributes.set(player.getInventory().getItem(freeSlot), new SplatterMapManager.Attribute());
}
catch (NMSException e)
{
PluginLogger.error("Unable to add back attribute to splatter map");
}
}
return false;
}
else
{
player.getInventory().addItem(item);
return false;
ItemUtils.drop(player.getLocation(), item);
return true;
}
}
static public ItemStack createMapItem(SingleMap map)
{
return createMapItem(map.getMapsIDs()[0], map.getName());
return createMapItem(map.getMapsIDs()[0], map.getName(), false);
}
static public ItemStack createMapItem(PosterMap map, int index)
{
/// The name of a map item given to a player, if splatter maps are not used. 0 = map name; 1 = index.
return createMapItem(map.getMapIdAt(index), getMapTitle(map, index));
return createMapItem(map.getMapIdAt(index), getMapTitle(map, index), true);
}
static public ItemStack createMapItem(PosterMap map, int x, int y)
{
/// The name of a map item given to a player, if splatter maps are not used. 0 = map name; 1 = row; 2 = column.
return createMapItem(map.getMapIdAt(x, y), getMapTitle(map, y, x));
return createMapItem(map.getMapIdAt(x, y), getMapTitle(map, y, x), true);
}
static public String getMapTitle(PosterMap map, int row, int column)
{
/// The name of a map item given to a player, if splatter maps are not used. 0 = map name; 1 = row; 2 = column.
return I.t("{0} (row {1}, column {2})", map.getName(), row + 1, column + 1);
}
static public String getMapTitle(PosterMap map, int index)
{
/// The name of a map item given to a player, if splatter maps are not used. 0 = map name; 1 = index.
return I.t("{0} (part {1})", map.getName(), index + 1);
}
static public ItemStack createMapItem(short mapID, String text)
static public ItemStack createMapItem(int mapID, String text, boolean isMapPart)
{
return new ItemStackBuilder(Material.MAP)
.data(mapID)
final ItemStack mapItem = new ItemStackBuilder(Material.FILLED_MAP)
.title(text)
.hideAttributes()
.item();
final MapMeta meta = (MapMeta) mapItem.getItemMeta();
meta.setMapId(mapID);
meta.setColor(isMapPart ? Color.LIME : Color.GREEN);
mapItem.setItemMeta(meta);
return mapItem;
}
/**
@ -188,7 +216,7 @@ public class MapItemManager implements Listener
throw new ArrayIndexOutOfBoundsException(); // Coherence
}
return MapItemManager.createMapItem(map.getMapsIDs()[0], map.getName());
return createMapItem(map.getMapsIDs()[0], map.getName(), false);
}
}
@ -218,7 +246,7 @@ public class MapItemManager implements Listener
else
{
PosterMap poster = (PosterMap) map;
int index = poster.getIndex(item.getDurability());
int index = poster.getIndex(MapManager.getMapIdFromItemStack(item));
if(poster.hasColumnData())
return getMapTitle(poster, poster.getRowAt(index), poster.getColumnAt(index));
@ -228,19 +256,20 @@ public class MapItemManager implements Listener
static private void onItemFramePlace(ItemFrame frame, Player player, PlayerInteractEntityEvent event)
{
final ItemStack mapItem = player.getInventory().getItemInMainHand();
if(frame.getItem().getType() != Material.AIR) return;
if(!MapManager.managesMap(player.getItemInHand())) return;
if(!MapManager.managesMap(mapItem)) return;
event.setCancelled(true);
if(SplatterMapManager.hasSplatterAttributes(player.getItemInHand()))
if(SplatterMapManager.hasSplatterAttributes(mapItem))
{
if(!SplatterMapManager.placeSplatterMap(frame, player))
return;
}
else
{
ItemStack is = new ItemStack(Material.MAP, 1, player.getItemInHand().getDurability());
frame.setItem(is);
frame.setItem(player.getInventory().getItemInMainHand());
}
ItemUtils.consumeItem(player);
@ -249,7 +278,7 @@ public class MapItemManager implements Listener
static private void onItemFrameRemove(ItemFrame frame, Player player, EntityDamageByEntityEvent event)
{
ItemStack item = frame.getItem();
if(frame.getItem().getType() != Material.MAP) return;
if(frame.getItem().getType() != Material.FILLED_MAP) return;
if(player.isSneaking())
{
@ -274,22 +303,19 @@ public class MapItemManager implements Listener
}
@EventHandler(priority = EventPriority.HIGHEST)
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
static public void onEntityDamage(EntityDamageByEntityEvent event)
{
if(event.isCancelled()) return;
if(!(event.getEntity() instanceof ItemFrame)) return;
if(!(event.getDamager() instanceof Player)) return;
onItemFrameRemove((ItemFrame)event.getEntity(), (Player)event.getDamager(), event);
}
@EventHandler(priority = EventPriority.HIGHEST)
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
static public void onEntityInteract(PlayerInteractEntityEvent event)
{
if(event.isCancelled()) return;
if(!(event.getRightClicked() instanceof ItemFrame)) return;
onItemFramePlace((ItemFrame)event.getRightClicked(), event.getPlayer(), event);
}
}

View File

@ -70,7 +70,7 @@ public class PosterWall
}
static public ItemFrame[] getMatchingMapFrames(PosterMap map, FlatLocation location, short mapId)
static public ItemFrame[] getMatchingMapFrames(PosterMap map, FlatLocation location, int mapId)
{
int mapIndex = map.getIndex(mapId);
int x = map.getColumnAt(mapIndex), y = map.getRowAt(mapIndex);
@ -111,7 +111,7 @@ public class PosterWall
ItemFrame frame = (ItemFrame) entity;
if(frame.getFacing() != location.getFacing()) continue;
ItemStack item = frame.getItem();
if(item.getType() != Material.MAP) continue;
if(item.getType() != Material.FILLED_MAP) continue;
if(!map.managesMap(item)) continue;
return frame;
}

View File

@ -18,21 +18,28 @@
package fr.moribus.imageonmap.ui;
import com.google.common.collect.ImmutableMap;
import fr.moribus.imageonmap.image.MapInitEvent;
import fr.moribus.imageonmap.map.ImageMap;
import fr.moribus.imageonmap.map.MapManager;
import fr.moribus.imageonmap.map.PosterMap;
import fr.zcraft.zlib.components.gui.GuiUtils;
import fr.zcraft.zlib.components.attributes.Attributes;
import fr.zcraft.zlib.components.i18n.I;
import fr.zcraft.zlib.tools.items.GlowEffect;
import fr.zcraft.zlib.components.nbt.NBTException;
import fr.zcraft.zlib.tools.PluginLogger;
import fr.zcraft.zlib.tools.items.ItemStackBuilder;
import fr.zcraft.zlib.tools.reflection.NMSException;
import fr.zcraft.zlib.tools.world.FlatLocation;
import org.bukkit.ChatColor;
import org.bukkit.Color;
import org.bukkit.Material;
import org.bukkit.entity.ItemFrame;
import org.bukkit.entity.Player;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.MapMeta;
import java.util.UUID;
abstract public class SplatterMapManager
{
@ -40,8 +47,7 @@ abstract public class SplatterMapManager
static public ItemStack makeSplatterMap(PosterMap map)
{
return new ItemStackBuilder(Material.MAP)
.data(map.getMapIdAt(0))
final ItemStack splatter = new ItemStackBuilder(Material.FILLED_MAP)
.title(ChatColor.GOLD, map.getName()).title(ChatColor.DARK_GRAY, " - ").title(ChatColor.GRAY, I.t("Splatter Map"))
.loreLine(ChatColor.GRAY, map.getId())
.loreLine()
@ -52,17 +58,32 @@ abstract public class SplatterMapManager
.loreLine()
/// Title in a splatter map tooltip
.loreLine(ChatColor.BLUE, I.t("How to use this?"))
.lore(GuiUtils.generateLore(ChatColor.GRAY + I.t("Place empty item frames on a wall, enough to host the whole map. Then, right-click on the bottom-left frame with this map.")))
.longLore(ChatColor.GRAY + I.t("Place empty item frames on a wall, enough to host the whole map. Then, right-click on the bottom-left frame with this map."))
.loreLine()
.lore(GuiUtils.generateLore(ChatColor.GRAY + I.t("Shift-click one of the placed maps to remove the whole poster in one shot.")))
.glow()
.longLore(ChatColor.GRAY + I.t("Shift-click one of the placed maps to remove the whole poster in one shot."))
.hideAttributes()
.item();
.craftItem();
final MapMeta meta = (MapMeta) splatter.getItemMeta();
meta.setMapId(map.getMapIdAt(0));
meta.setColor(Color.GREEN);
splatter.setItemMeta(meta);
try
{
Attributes.set(splatter, new Attribute());
}
catch (NBTException | NMSException e)
{
PluginLogger.error("Unable to set Splatter Map attribute on item", e);
}
return splatter;
}
static public boolean hasSplatterAttributes(ItemStack itemStack)
{
return GlowEffect.hasGlow(itemStack);
return Attribute.hasAttribute(itemStack);
}
static public boolean isSplatterMap(ItemStack itemStack)
@ -86,10 +107,11 @@ abstract public class SplatterMapManager
static public boolean placeSplatterMap(ItemFrame startFrame, Player player)
{
ImageMap map = MapManager.getMap(player.getItemInHand());
if(map == null || !(map instanceof PosterMap)) return false;
ImageMap map = MapManager.getMap(player.getInventory().getItemInMainHand());
if(!(map instanceof PosterMap)) return false;
PosterMap poster = (PosterMap) map;
FlatLocation startLocation = new FlatLocation(startFrame.getLocation(), startFrame.getFacing());
FlatLocation endLocation = startLocation.clone().add(poster.getColumnCount(), poster.getRowCount());
PosterWall wall = new PosterWall();
@ -106,8 +128,8 @@ abstract public class SplatterMapManager
int i = 0;
for(ItemFrame frame : wall.frames)
{
short id = poster.getMapIdAtReverseY(i);
frame.setItem(new ItemStack(Material.MAP, 1, id));
int id = poster.getMapIdAtReverseY(i);
frame.setItem(new ItemStackBuilder(Material.FILLED_MAP).nbt(ImmutableMap.of("map", id)).craftItem());
MapInitEvent.initMap(id);
++i;
}
@ -117,12 +139,12 @@ abstract public class SplatterMapManager
static public PosterMap removeSplatterMap(ItemFrame startFrame)
{
ImageMap map = MapManager.getMap(startFrame.getItem());
if(map == null || !(map instanceof PosterMap)) return null;
final ImageMap map = MapManager.getMap(startFrame.getItem());
if(!(map instanceof PosterMap)) return null;
PosterMap poster = (PosterMap) map;
if(!poster.hasColumnData()) return null;
FlatLocation loc = new FlatLocation(startFrame.getLocation(), startFrame.getFacing());
ItemFrame[] matchingFrames = PosterWall.getMatchingMapFrames(poster, loc, startFrame.getItem().getDurability());
ItemFrame[] matchingFrames = PosterWall.getMatchingMapFrames(poster, loc, MapManager.getMapIdFromItemStack(startFrame.getItem()));
if(matchingFrames == null) return null;
for(ItemFrame frame : matchingFrames)
@ -132,4 +154,29 @@ abstract public class SplatterMapManager
return poster;
}
static public class Attribute extends fr.zcraft.zlib.components.attributes.Attribute
{
static public final UUID SPLATTER_MAP_UUID = UUID.fromString("260ae1b3-4b24-40a0-a30d-67ad84b7bdb2");
Attribute()
{
setUUID(SPLATTER_MAP_UUID);
setCustomData("splatter-map");
}
static boolean hasAttribute(final ItemStack item)
{
try
{
return Attributes.get(item, SPLATTER_MAP_UUID) != null;
}
catch (NMSException | NBTException ex)
{
PluginLogger.warning("Error while retrieving SplatterMap Attribute data", ex);
return false;
}
}
}
}

View File

@ -1,6 +1,7 @@
name: ImageOnMap
main: fr.moribus.imageonmap.ImageOnMap
version: 3.1
version: "4.0"
api-version: "1.13"
commands:
tomap: