mirror of
https://github.com/zDevelopers/ImageOnMap.git
synced 2024-09-28 06:27:38 +02:00
Implemented the map item limit (global and per-player).
* NEW: Implemented the per-player map limit. * NEW: Implemented the global map limit. * NEW: The map manager can now raise exceptions for some requests. * NEW: The configuration can now have deprecated field names. These fields are automatically migrated if present in the config file. * NEW: The configuration now writes default values when loading the plugin. * BUG: Fixed configuration loading. * BUG: Fixed player store loading's thread-safety. * OPT: Cleaned up map loading events initialisation.
This commit is contained in:
parent
27f836977f
commit
b87dfdf231
@ -80,13 +80,13 @@ public final class ImageOnMap extends JavaPlugin
|
||||
}
|
||||
|
||||
//Init all the things !
|
||||
PluginConfiguration.init(this);
|
||||
MetricsLite.startMetrics();
|
||||
ImageIOExecutor.start();
|
||||
ImageRendererExecutor.start();
|
||||
MapManager.init();
|
||||
Commands.init(this);
|
||||
getServer().getPluginManager().registerEvents(new MapInitEvent(), this);
|
||||
MapInitEvent.init();
|
||||
MapInitEvent.init(this);
|
||||
MapItemManager.init();
|
||||
}
|
||||
|
||||
|
@ -19,21 +19,24 @@
|
||||
package fr.moribus.imageonmap;
|
||||
|
||||
import org.bukkit.configuration.file.FileConfiguration;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
|
||||
public enum PluginConfiguration
|
||||
{
|
||||
//Configuration field Names, with default values
|
||||
COLLECT_DATA("collect-data", true),
|
||||
MAP_GLOBAL_LIMIT("map-global-limit", 0),
|
||||
MAP_PLAYER_LIMIT("map-player-limit", 0);
|
||||
MAP_GLOBAL_LIMIT("map-global-limit", 0, "Limit-map-by-server"),
|
||||
MAP_PLAYER_LIMIT("map-player-limit", 0, "Limit-map-by-player");
|
||||
|
||||
private final String fieldName;
|
||||
private final Object defaultValue;
|
||||
private final String[] deprecatedNames;
|
||||
|
||||
private PluginConfiguration(String fieldName, Object defaultValue)
|
||||
private PluginConfiguration(String fieldName, Object defaultValue, String ... deprecatedNames)
|
||||
{
|
||||
this.fieldName = fieldName;
|
||||
this.defaultValue = defaultValue;
|
||||
this.deprecatedNames = deprecatedNames;
|
||||
}
|
||||
|
||||
public Object get()
|
||||
@ -46,9 +49,9 @@ public enum PluginConfiguration
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
public boolean isDefaultValue()
|
||||
public boolean isDefined()
|
||||
{
|
||||
return get().equals(defaultValue);
|
||||
return getConfig().contains(fieldName);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -72,8 +75,51 @@ public enum PluginConfiguration
|
||||
return getConfig().getBoolean(fieldName, (Boolean)defaultValue);
|
||||
}
|
||||
|
||||
private boolean init()
|
||||
{
|
||||
boolean affected = false;
|
||||
|
||||
if(!isDefined())
|
||||
{
|
||||
getConfig().set(fieldName, defaultValue);
|
||||
affected = true;
|
||||
}
|
||||
|
||||
for(String deprecatedName : deprecatedNames)
|
||||
{
|
||||
if(getConfig().contains(deprecatedName))
|
||||
{
|
||||
getConfig().set(fieldName, getConfig().get(deprecatedName));
|
||||
getConfig().set(deprecatedName, null);
|
||||
affected = true;
|
||||
}
|
||||
}
|
||||
return affected;
|
||||
}
|
||||
|
||||
/* ===== Static API ===== */
|
||||
|
||||
static private Plugin plugin;
|
||||
static public FileConfiguration getConfig()
|
||||
{
|
||||
return ImageOnMap.getPlugin().getConfig();
|
||||
return plugin.getConfig();
|
||||
}
|
||||
|
||||
static public void init(Plugin plugin)
|
||||
{
|
||||
PluginConfiguration.plugin = plugin;
|
||||
loadDefaultValues();
|
||||
}
|
||||
|
||||
static private void loadDefaultValues()
|
||||
{
|
||||
boolean affected = false;
|
||||
|
||||
for(PluginConfiguration configField : PluginConfiguration.values())
|
||||
{
|
||||
if(configField.init()) affected = true;
|
||||
}
|
||||
|
||||
if(affected) plugin.saveConfig();
|
||||
}
|
||||
}
|
||||
|
@ -18,6 +18,8 @@
|
||||
|
||||
package fr.moribus.imageonmap.commands;
|
||||
|
||||
import fr.moribus.imageonmap.PluginLogger;
|
||||
|
||||
public class CommandException extends Exception
|
||||
{
|
||||
public enum Reason
|
||||
@ -63,6 +65,7 @@ public class CommandException extends Exception
|
||||
case SENDER_NOT_AUTHORIZED:
|
||||
return "You do not have the permission to use this command.";
|
||||
default:
|
||||
PluginLogger.LogWarning("Unknown CommandException caught", this);
|
||||
return "An unknown error suddenly happened.";
|
||||
}
|
||||
}
|
||||
|
@ -18,9 +18,11 @@
|
||||
|
||||
package fr.moribus.imageonmap.commands.maptool;
|
||||
|
||||
import fr.moribus.imageonmap.PluginLogger;
|
||||
import fr.moribus.imageonmap.commands.*;
|
||||
import fr.moribus.imageonmap.map.ImageMap;
|
||||
import fr.moribus.imageonmap.map.MapManager;
|
||||
import fr.moribus.imageonmap.map.MapManagerException;
|
||||
import java.util.List;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
@ -39,8 +41,16 @@ public class DeleteNoConfirmCommand extends Command
|
||||
Player player = playerSender();
|
||||
ImageMap map = getMapFromArgs();
|
||||
MapManager.clear(player.getInventory(), map);
|
||||
MapManager.deleteMap(map);
|
||||
info("Map successfully deleted.");
|
||||
try
|
||||
{
|
||||
MapManager.deleteMap(map);
|
||||
info("Map successfully deleted.");
|
||||
}
|
||||
catch (MapManagerException ex)
|
||||
{
|
||||
PluginLogger.LogWarning("A non-existent map was requested to be deleted", ex);
|
||||
warning("This map does not exist.");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -86,6 +86,7 @@ public class ImageRendererExecutor extends Worker
|
||||
|
||||
static private ImageMap RenderSingle(final BufferedImage image, final UUID playerUUID) throws Throwable
|
||||
{
|
||||
MapManager.checkMapLimit(1, playerUUID);
|
||||
Future<Short> futureMapID = instance.submitToMainThread(new Callable<Short>()
|
||||
{
|
||||
@Override
|
||||
@ -118,7 +119,8 @@ public class ImageRendererExecutor extends Worker
|
||||
{
|
||||
final PosterImage poster = new PosterImage(image);
|
||||
final int mapCount = poster.getImagesCount();
|
||||
|
||||
|
||||
MapManager.checkMapLimit(mapCount, playerUUID);
|
||||
final Future<short[]> futureMapsIds = instance.submitToMainThread(new Callable<short[]>()
|
||||
{
|
||||
@Override
|
||||
|
@ -32,11 +32,14 @@ import org.bukkit.event.player.PlayerItemHeldEvent;
|
||||
import org.bukkit.event.world.ChunkLoadEvent;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.map.MapView;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
|
||||
public class MapInitEvent implements Listener
|
||||
{
|
||||
static public void init()
|
||||
static public void init(Plugin plugin)
|
||||
{
|
||||
plugin.getServer().getPluginManager().registerEvents(new MapInitEvent(), plugin);
|
||||
|
||||
for(World world : Bukkit.getWorlds())
|
||||
{
|
||||
for(ItemFrame frame : world.getEntitiesByClass(ItemFrame.class))
|
||||
|
@ -66,6 +66,7 @@ public abstract class ImageMap implements ConfigurationSerializable
|
||||
|
||||
public abstract short[] getMapsIDs();
|
||||
public abstract boolean managesMap(short mapID);
|
||||
public abstract int getMapCount();
|
||||
|
||||
public boolean managesMap(ItemStack item)
|
||||
{
|
||||
|
@ -19,8 +19,10 @@
|
||||
package fr.moribus.imageonmap.map;
|
||||
|
||||
import fr.moribus.imageonmap.ImageOnMap;
|
||||
import fr.moribus.imageonmap.PluginConfiguration;
|
||||
import fr.moribus.imageonmap.image.ImageIOExecutor;
|
||||
import fr.moribus.imageonmap.image.PosterImage;
|
||||
import fr.moribus.imageonmap.map.MapManagerException.Reason;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
@ -72,14 +74,14 @@ abstract public class MapManager
|
||||
return false;
|
||||
}
|
||||
|
||||
static public ImageMap createMap(UUID playerUUID, short mapID)
|
||||
static public ImageMap createMap(UUID playerUUID, short mapID) throws MapManagerException
|
||||
{
|
||||
ImageMap newMap = new SingleMap(playerUUID, mapID);
|
||||
addMap(newMap);
|
||||
return newMap;
|
||||
}
|
||||
|
||||
static public ImageMap createMap(PosterImage image, UUID playerUUID, short[] mapsIDs)
|
||||
static public ImageMap createMap(PosterImage image, UUID playerUUID, short[] mapsIDs) throws MapManagerException
|
||||
{
|
||||
ImageMap newMap;
|
||||
if(image.getImagesCount() == 1)
|
||||
@ -104,15 +106,15 @@ abstract public class MapManager
|
||||
return mapsIds;
|
||||
}
|
||||
|
||||
static public void addMap(ImageMap map)
|
||||
static public void addMap(ImageMap map) throws MapManagerException
|
||||
{
|
||||
getPlayerMapStore(map.getUserUUID()).addMap(map);
|
||||
}
|
||||
|
||||
static public void deleteMap(ImageMap map)
|
||||
static public void deleteMap(ImageMap map) throws MapManagerException
|
||||
{
|
||||
ImageIOExecutor.deleteImage(map);
|
||||
getPlayerMapStore(map.getUserUUID()).deleteMap(map);
|
||||
ImageIOExecutor.deleteImage(map);
|
||||
}
|
||||
|
||||
static public void notifyModification(UUID playerUUID)
|
||||
@ -170,14 +172,48 @@ abstract public class MapManager
|
||||
}
|
||||
}
|
||||
|
||||
static public void checkMapLimit(ImageMap map) throws MapManagerException
|
||||
{
|
||||
checkMapLimit(map.getMapCount(), map.getUserUUID());
|
||||
}
|
||||
|
||||
static public void checkMapLimit(int newMapsCount, UUID userUUID) throws MapManagerException
|
||||
{
|
||||
int limit = PluginConfiguration.MAP_GLOBAL_LIMIT.getInteger();
|
||||
if(limit > 0)
|
||||
{
|
||||
if(getMapCount() + newMapsCount > limit)
|
||||
throw new MapManagerException(Reason.MAXIMUM_SERVER_MAPS_EXCEEDED);
|
||||
}
|
||||
getPlayerMapStore(userUUID).checkMapLimit(newMapsCount);
|
||||
}
|
||||
|
||||
static public int getMapCount()
|
||||
{
|
||||
int mapCount = 0;
|
||||
synchronized(playerMaps)
|
||||
{
|
||||
for(PlayerMapStore tStore : playerMaps)
|
||||
{
|
||||
mapCount += tStore.getMapCount();
|
||||
}
|
||||
}
|
||||
return mapCount;
|
||||
}
|
||||
|
||||
static private PlayerMapStore getPlayerMapStore(UUID playerUUID)
|
||||
{
|
||||
PlayerMapStore store = getExistingPlayerMapStore(playerUUID);
|
||||
if(store == null)
|
||||
PlayerMapStore store;
|
||||
synchronized(playerMaps)
|
||||
{
|
||||
store = new PlayerMapStore(playerUUID);
|
||||
synchronized(playerMaps){playerMaps.add(store);}
|
||||
store.load();
|
||||
store = getExistingPlayerMapStore(playerUUID);
|
||||
if(store == null)
|
||||
{
|
||||
store = new PlayerMapStore(playerUUID);
|
||||
|
||||
playerMaps.add(store);
|
||||
store.load();
|
||||
}
|
||||
}
|
||||
return store;
|
||||
}
|
||||
|
@ -0,0 +1,53 @@
|
||||
/*
|
||||
* 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.map;
|
||||
|
||||
import java.text.MessageFormat;
|
||||
|
||||
public class MapManagerException extends Exception
|
||||
{
|
||||
public enum Reason
|
||||
{
|
||||
MAXIMUM_PLAYER_MAPS_EXCEEDED("You have too many maps (maximum : {0})."),
|
||||
MAXIMUM_SERVER_MAPS_EXCEEDED("The server ImageOnMap limit has been reached."),
|
||||
IMAGEMAP_DOES_NOT_EXIST("The given map does not exist.");
|
||||
|
||||
private final String reasonString;
|
||||
private Reason(String reasonString)
|
||||
{
|
||||
this.reasonString = reasonString;
|
||||
}
|
||||
|
||||
public String getReasonString(Object ...arguments)
|
||||
{
|
||||
return MessageFormat.format(reasonString, arguments);
|
||||
}
|
||||
}
|
||||
|
||||
private final Reason reason;
|
||||
|
||||
public MapManagerException(Reason reason, Object ...arguments)
|
||||
{
|
||||
super(reason.getReasonString(arguments));
|
||||
this.reason = reason;
|
||||
}
|
||||
|
||||
public Reason getReason() { return reason; }
|
||||
|
||||
}
|
@ -19,7 +19,9 @@
|
||||
package fr.moribus.imageonmap.map;
|
||||
|
||||
import fr.moribus.imageonmap.ImageOnMap;
|
||||
import fr.moribus.imageonmap.PluginConfiguration;
|
||||
import fr.moribus.imageonmap.PluginLogger;
|
||||
import fr.moribus.imageonmap.map.MapManagerException.Reason;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
@ -39,6 +41,7 @@ public class PlayerMapStore implements ConfigurationSerializable
|
||||
private final UUID playerUUID;
|
||||
private final ArrayList<ImageMap> mapList = new ArrayList<ImageMap>();
|
||||
private boolean modified = false;
|
||||
private int mapCount = 0;
|
||||
|
||||
public PlayerMapStore(UUID playerUUID)
|
||||
{
|
||||
@ -63,18 +66,34 @@ public class PlayerMapStore implements ConfigurationSerializable
|
||||
return false;
|
||||
}
|
||||
|
||||
public synchronized void addMap(ImageMap map)
|
||||
public synchronized void addMap(ImageMap map) throws MapManagerException
|
||||
{
|
||||
mapList.add(map);
|
||||
checkMapLimit(map);
|
||||
_addMap(map);
|
||||
notifyModification();
|
||||
}
|
||||
|
||||
public synchronized void deleteMap(ImageMap map)
|
||||
private void _addMap(ImageMap map)
|
||||
{
|
||||
mapList.remove(map);
|
||||
mapList.add(map);
|
||||
mapCount += map.getMapCount();
|
||||
}
|
||||
|
||||
public synchronized void deleteMap(ImageMap map) throws MapManagerException
|
||||
{
|
||||
_removeMap(map);
|
||||
notifyModification();
|
||||
}
|
||||
|
||||
private void _removeMap(ImageMap map) throws MapManagerException
|
||||
{
|
||||
if(!mapList.remove(map))
|
||||
{
|
||||
throw new MapManagerException(Reason.IMAGEMAP_DOES_NOT_EXIST);
|
||||
}
|
||||
mapCount -= map.getMapCount();
|
||||
}
|
||||
|
||||
public synchronized boolean mapExists(String id)
|
||||
{
|
||||
for(ImageMap map : mapList)
|
||||
@ -113,6 +132,20 @@ public class PlayerMapStore implements ConfigurationSerializable
|
||||
return null;
|
||||
}
|
||||
|
||||
public void checkMapLimit(ImageMap map) throws MapManagerException
|
||||
{
|
||||
checkMapLimit(map.getMapCount());
|
||||
}
|
||||
|
||||
public void checkMapLimit(int newMapsCount) throws MapManagerException
|
||||
{
|
||||
int limit = PluginConfiguration.MAP_PLAYER_LIMIT.getInteger();
|
||||
if(limit <= 0) return;
|
||||
|
||||
if(getMapCount() + newMapsCount > limit)
|
||||
throw new MapManagerException(Reason.MAXIMUM_PLAYER_MAPS_EXCEEDED, limit);
|
||||
}
|
||||
|
||||
/* ===== Getters & Setters ===== */
|
||||
|
||||
public UUID getUUID()
|
||||
@ -130,6 +163,11 @@ public class PlayerMapStore implements ConfigurationSerializable
|
||||
this.modified = true;
|
||||
}
|
||||
|
||||
public synchronized int getMapCount()
|
||||
{
|
||||
return this.mapCount;
|
||||
}
|
||||
|
||||
/* ****** Serializing ***** */
|
||||
|
||||
@Override
|
||||
@ -159,13 +197,20 @@ public class PlayerMapStore implements ConfigurationSerializable
|
||||
try
|
||||
{
|
||||
ImageMap newMap = ImageMap.fromConfig(tMap, playerUUID);
|
||||
synchronized(this) {mapList.add(newMap);}
|
||||
synchronized(this) {_addMap(newMap);}
|
||||
}
|
||||
catch(InvalidConfigurationException ex)
|
||||
{
|
||||
PluginLogger.LogWarning("Could not load map data : " + ex.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
try { checkMapLimit(0); }
|
||||
catch(MapManagerException ex)
|
||||
{
|
||||
PluginLogger.LogWarning("Map limit exceeded for player " + playerUUID.toString() +
|
||||
" (" + mapList.size() + " maps loaded).");
|
||||
}
|
||||
}
|
||||
|
||||
/* ****** Configuration Files management ***** */
|
||||
|
@ -101,4 +101,10 @@ public class PosterMap extends ImageMap
|
||||
return (i / columnCount) + 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMapCount()
|
||||
{
|
||||
return mapsIDs.length;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -44,6 +44,12 @@ public class SingleMap extends ImageMap
|
||||
return this.mapID == mapID;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMapCount()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* ====== Serialization methods ====== */
|
||||
|
||||
public SingleMap(Map<String, Object> map, UUID userUUID) throws InvalidConfigurationException
|
||||
|
Loading…
Reference in New Issue
Block a user