First (and dirty) implementation for Splatter maps. Still WIP.

* NEW: Added splatter maps.
* NEW: Shift-left clicking on a poster map in a frames removes the
  complete map.
* NEW: Placing a splatter map on the bottom-left of an item frame wall
  places the entire map.
* NEW: Map GUIs now give splatter maps instead of all the separate map
  parts.
This commit is contained in:
Adrien Prokopowicz 2016-04-15 17:16:09 +02:00
parent a285d782be
commit 3bfa1266ad
6 changed files with 321 additions and 50 deletions

View File

@ -24,9 +24,11 @@ import fr.moribus.imageonmap.map.MapManager;
import fr.moribus.imageonmap.map.PosterMap; import fr.moribus.imageonmap.map.PosterMap;
import fr.moribus.imageonmap.map.SingleMap; import fr.moribus.imageonmap.map.SingleMap;
import fr.moribus.imageonmap.ui.MapItemManager; import fr.moribus.imageonmap.ui.MapItemManager;
import fr.moribus.imageonmap.ui.SplatterMapManager;
import fr.zcraft.zlib.components.gui.ExplorerGui; import fr.zcraft.zlib.components.gui.ExplorerGui;
import fr.zcraft.zlib.components.gui.Gui; import fr.zcraft.zlib.components.gui.Gui;
import fr.zcraft.zlib.components.gui.GuiUtils; import fr.zcraft.zlib.components.gui.GuiUtils;
import fr.zcraft.zlib.tools.items.ItemStackBuilder;
import org.bukkit.ChatColor; import org.bukkit.ChatColor;
import org.bukkit.Material; import org.bukkit.Material;
import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.ItemStack;
@ -95,6 +97,10 @@ public class MapListGui extends ExplorerGui<ImageMap>
{ {
return MapItemManager.createMapItem(map.getMapsIDs()[0], map.getName()); return MapItemManager.createMapItem(map.getMapsIDs()[0], map.getName());
} }
else if(map instanceof PosterMap)
{
return SplatterMapManager.makeSplatterMap((PosterMap) map);
}
MapItemManager.give(getPlayer(), map); MapItemManager.give(getPlayer(), map);
return null; return null;
@ -133,38 +139,27 @@ public class MapListGui extends ExplorerGui<ImageMap>
double percentageUsed = mapPartLeft < 0 ? 0 : ((double) mapPartCount) / ((double) (mapPartCount + mapPartLeft)) * 100; double percentageUsed = mapPartLeft < 0 ? 0 : ((double) mapPartCount) / ((double) (mapPartCount + mapPartLeft)) * 100;
ItemStackBuilder statistics = new ItemStackBuilder(Material.ENCHANTED_BOOK)
ItemStack statistics = new ItemStack(Material.ENCHANTED_BOOK); .title(ChatColor.BLUE, "Usage statistics")
ItemMeta meta = statistics.getItemMeta(); .lore( "",
meta.setDisplayName(ChatColor.BLUE + "Usage statistics");
meta.setLore(Arrays.asList(
"",
getStatisticText("Images rendered", imagesCount), getStatisticText("Images rendered", imagesCount),
getStatisticText("Minecraft maps used", mapPartCount) getStatisticText("Minecraft maps used", mapPartCount));
));
if(mapPartLeft >= 0) if(mapPartLeft >= 0)
{ {
List<String> lore = meta.getLore(); statistics.lore("", ChatColor.BLUE + "Minecraft maps limits");
lore.add(""); statistics.lore("",
lore.add(ChatColor.BLUE + "Minecraft maps limits"); getStatisticText("Server-wide limit", mapGlobalLimit, true),
getStatisticText("Per-player limit", mapPersonalLimit, true))
lore.add(""); .lore("",
lore.add(getStatisticText("Server-wide limit", mapGlobalLimit, true)); getStatisticText("Current consumption", ((int) Math.rint(percentageUsed)) + " %"),
lore.add(getStatisticText("Per-player limit", mapPersonalLimit, true)); getStatisticText("Maps left", mapPartLeft));
lore.add("");
lore.add(getStatisticText("Current consumption", ((int) Math.rint(percentageUsed)) + " %"));
lore.add(getStatisticText("Maps left", mapPartLeft));
meta.setLore(lore);
} }
GuiUtils.hideItemAttributes(meta); statistics.hideAttributes();
statistics.setItemMeta(meta);
action("", getSize() - 5, statistics); action("", getSize() - 5, statistics);
} }

View File

@ -202,6 +202,8 @@ abstract public class MapManager
*/ */
static public ImageMap getMap(ItemStack item) static public ImageMap getMap(ItemStack item)
{ {
if(item == null) return null;
if(item.getType() != Material.MAP) return null;
return getMap(item.getDurability()); return getMap(item.getDurability());
} }

View File

@ -117,6 +117,11 @@ public class PosterMap extends ImageMap
return (i / columnCount) + 1; return (i / columnCount) + 1;
} }
public int getIndexAt(int col, int row)
{
return columnCount * row + col;
}
/** /**
* Returns the map id at the given column and line. * Returns the map id at the given column and line.
* *
@ -128,7 +133,20 @@ public class PosterMap extends ImageMap
*/ */
public short getMapIdAt(int col, int row) public short getMapIdAt(int col, int row)
{ {
return mapsIDs[getColumnCount() * col + row]; return mapsIDs[getColumnCount() * row + col];
}
public short getMapIdAtReverseY(int index)
{
int col = index % (columnCount);
int row = index / (rowCount - 1);
System.out.println(col + " : " + row + " (" + index);
return getMapIdAt(col, rowCount - row - 1);
}
public short getMapIdAt(int index)
{
return mapsIDs[index];
} }
public boolean hasColumnData() public boolean hasColumnData()

View File

@ -22,16 +22,14 @@ import fr.moribus.imageonmap.map.ImageMap;
import fr.moribus.imageonmap.map.MapManager; import fr.moribus.imageonmap.map.MapManager;
import fr.moribus.imageonmap.map.PosterMap; import fr.moribus.imageonmap.map.PosterMap;
import fr.moribus.imageonmap.map.SingleMap; import fr.moribus.imageonmap.map.SingleMap;
import fr.zcraft.zlib.components.gui.GuiUtils;
import fr.zcraft.zlib.core.ZLib; import fr.zcraft.zlib.core.ZLib;
import fr.zcraft.zlib.tools.items.ItemStackBuilder;
import fr.zcraft.zlib.tools.items.ItemUtils; import fr.zcraft.zlib.tools.items.ItemUtils;
import org.bukkit.ChatColor;
import org.bukkit.Material; import org.bukkit.Material;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.bukkit.event.Listener; import org.bukkit.event.Listener;
import org.bukkit.inventory.Inventory; import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import java.util.ArrayDeque; import java.util.ArrayDeque;
import java.util.HashMap; import java.util.HashMap;
@ -146,14 +144,11 @@ public class MapItemManager implements Listener
static public ItemStack createMapItem(short mapID, String text) static public ItemStack createMapItem(short mapID, String text)
{ {
ItemStack itemMap = new ItemStack(Material.MAP, 1, mapID); return new ItemStackBuilder(Material.MAP)
.data(mapID)
ItemMeta meta = itemMap.getItemMeta(); .title(text)
meta.setDisplayName(ChatColor.RESET + text); .hideAttributes()
GuiUtils.hideItemAttributes(meta); .item();
itemMap.setItemMeta(meta);
return itemMap;
} }
/** /**
@ -225,21 +220,37 @@ public class MapItemManager implements Listener
if(frame.getItem().getType() != Material.AIR) return; if(frame.getItem().getType() != Material.AIR) return;
if(!MapManager.managesMap(player.getItemInHand())) return; if(!MapManager.managesMap(player.getItemInHand())) return;
if(SplatterMapManager.hasSplatterAttributes(player.getItemInHand()))
event.setCancelled(true); {
SplatterMapManager.placeSplatterMap(frame, player);
}
else
{
ItemStack is = new ItemStack(Material.MAP, 1, player.getItemInHand().getDurability()); ItemStack is = new ItemStack(Material.MAP, 1, player.getItemInHand().getDurability());
frame.setItem(is); frame.setItem(is);
}
event.setCancelled(true);
ItemUtils.consumeItem(player); ItemUtils.consumeItem(player);
} }
static private void onItemFrameRemove(ItemFrame frame, Player player) static private void onItemFrameRemove(ItemFrame frame, Player player, EntityDamageByEntityEvent event)
{ {
ItemStack item = frame.getItem(); ItemStack item = frame.getItem();
if(frame.getItem().getType() != Material.MAP) return; if(frame.getItem().getType() != Material.MAP) return;
if(!MapManager.managesMap(frame.getItem())) return;
if(player.isSneaking())
{
if(SplatterMapManager.removeSplatterMap(frame))
{
event.setCancelled(true);
return;
}
}
if(!MapManager.managesMap(frame.getItem())) return;
frame.setItem(ItemUtils.setDisplayName(item, getMapTitle(item))); frame.setItem(ItemUtils.setDisplayName(item, getMapTitle(item)));
} }
@EventHandler @EventHandler
@ -248,7 +259,7 @@ public class MapItemManager implements Listener
if(!(event.getEntity() instanceof ItemFrame)) return; if(!(event.getEntity() instanceof ItemFrame)) return;
if(!(event.getDamager() instanceof Player)) return; if(!(event.getDamager() instanceof Player)) return;
onItemFrameRemove((ItemFrame)event.getEntity(), (Player)event.getDamager()); onItemFrameRemove((ItemFrame)event.getEntity(), (Player)event.getDamager(), event);
} }
@EventHandler @EventHandler

View File

@ -0,0 +1,142 @@
/*
* Copyright (C) 2013 Moribus
* Copyright (C) 2015 ProkopyL <prokopylmc@gmail.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package fr.moribus.imageonmap.ui;
import fr.moribus.imageonmap.map.PosterMap;
import fr.zcraft.zlib.tools.world.FlatLocation;
import fr.zcraft.zlib.tools.world.WorldUtils;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.block.BlockFace;
import org.bukkit.entity.Entity;
import org.bukkit.entity.ItemFrame;
import org.bukkit.inventory.ItemStack;
public class PosterWall
{
public FlatLocation loc1;
public FlatLocation loc2;
public ItemFrame[] frames;
public boolean isValid()
{
ItemFrame curFrame;
FlatLocation bottomLeft = FlatLocation.minMerged(loc1, loc2);
FlatLocation loc = bottomLeft.clone();
int distX = FlatLocation.flatBlockDistanceX(loc1, loc2);
int distY = FlatLocation.flatBlockDistanceY(loc1, loc2);
frames = new ItemFrame[distX * distY];
for(int x = 0; x < distX; x++)
{
for(int y = 0; y < distY; y++)
{
curFrame = getEmptyFrameAt(loc, loc.getFacing());
if(curFrame == null) return false;
frames[y * distX + x] = curFrame;
loc.add(0, 1);
}
loc.add(1, 0);
loc.setY(bottomLeft.getY());
}
return true;
}
public void expand()
{
}
static public ItemFrame[] getMatchingMapFrames(PosterMap map, FlatLocation location, short mapId)
{
int mapIndex = map.getIndex(mapId);
int x = map.getColumnAt(mapIndex), y = map.getRowAt(mapIndex);
return getMatchingMapFrames(map, location.clone().add(-x + 1, y - 1));
}
static public ItemFrame[] getMatchingMapFrames(PosterMap map, FlatLocation location)
{
ItemFrame[] frames = new ItemFrame[map.getMapCount()];
FlatLocation loc = location.clone();
for(int y = 0; y < map.getRowCount(); ++y)
{
for(int x = 0; x < map.getColumnCount(); ++x)
{
//Location newLocation = WorldUtils.addToLocation(topLeftLocation, x, -y, facing);
System.out.println("Checking : " + loc);
int mapIndex = map.getIndexAt(x, y);
ItemFrame frame = getMapFrameAt(loc, map.getMapIdAt(mapIndex));
if(frame == null) return null;
frames[mapIndex] = frame;
loc.add(1, 0);
}
loc.setX(location.getX());
loc.setZ(location.getZ());
loc.add(0, -1);
}
return frames;
}
static public ItemFrame getMapFrameAt(FlatLocation location, short mapId)
{
Entity entities[] = location.getChunk().getEntities();
for(Entity entity : entities)
{
if(!(entity instanceof ItemFrame)) continue;
if(!WorldUtils.blockEquals(location, entity.getLocation())) continue;
ItemFrame frame = (ItemFrame) entity;
if(frame.getFacing() != location.getFacing()) continue;
ItemStack item = frame.getItem();
if(item.getType() != Material.MAP) continue;
if(item.getDurability() != mapId) continue;
return frame;
}
return null;
}
static public ItemFrame getEmptyFrameAt(Location location, BlockFace facing)
{
Entity entities[] = location.getChunk().getEntities();
for(Entity entity : entities)
{
if(!(entity instanceof ItemFrame)) continue;
if(!WorldUtils.blockEquals(location, entity.getLocation())) continue;
ItemFrame frame = (ItemFrame) entity;
if(frame.getFacing() != facing) continue;
ItemStack item = frame.getItem();
if(item.getType() != Material.AIR) continue;
return frame;
}
return null;
}
}

View File

@ -0,0 +1,103 @@
/*
* Copyright (C) 2013 Moribus
* Copyright (C) 2015 ProkopyL <prokopylmc@gmail.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package fr.moribus.imageonmap.ui;
import fr.moribus.imageonmap.map.ImageMap;
import fr.moribus.imageonmap.map.MapManager;
import fr.moribus.imageonmap.map.PosterMap;
import fr.zcraft.zlib.tools.items.GlowEffect;
import fr.zcraft.zlib.tools.items.ItemStackBuilder;
import fr.zcraft.zlib.tools.world.FlatLocation;
import org.bukkit.ChatColor;
import org.bukkit.Material;
import org.bukkit.entity.ItemFrame;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
abstract public class SplatterMapManager
{
private SplatterMapManager() {}
static public ItemStack makeSplatterMap(PosterMap map)
{
return new ItemStackBuilder(Material.MAP)
.data(map.getMapIdAt(0))
.title(ChatColor.GOLD, map.getName())
.loreLine(ChatColor.GOLD, "Splatter Map")
.glow()
.hideAttributes()
.item();
}
static public boolean hasSplatterAttributes(ItemStack itemStack)
{
return GlowEffect.hasGlow(itemStack);
}
static public boolean isSplatterMap(ItemStack itemStack)
{
return hasSplatterAttributes(itemStack) && MapManager.managesMap(itemStack);
}
static public boolean placeSplatterMap(ItemFrame startFrame, Player player)
{
ImageMap map = MapManager.getMap(player.getItemInHand());
if(map == null || !(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();
wall.loc1 = startLocation;
wall.loc2 = endLocation;
if(!wall.isValid())
{
player.sendMessage(ChatColor.RED + "There is not enough space to place this map (" + poster.getColumnCount() + "x" + poster.getRowCount() + ")");
return false;
}
int i = 0;
for(ItemFrame frame : wall.frames)
{
frame.setItem(new ItemStack(Material.MAP, 1, poster.getMapIdAtReverseY(i)));
++i;
}
return true;
}
static public boolean removeSplatterMap(ItemFrame startFrame)
{
ImageMap map = MapManager.getMap(startFrame.getItem());
if(map == null || !(map instanceof PosterMap)) return false;
PosterMap poster = (PosterMap) map;
FlatLocation loc = new FlatLocation(startFrame.getLocation(), startFrame.getFacing());
ItemFrame[] matchingFrames = PosterWall.getMatchingMapFrames(poster, loc, startFrame.getItem().getDurability());
if(matchingFrames == null) return false;
for(ItemFrame frame : matchingFrames)
{
frame.setItem(null);
}
return true;
}
}