Added preference command

This commit is contained in:
LOOHP committed 2023-08-30 00:10:47 +01:00
1 parent 8f563d3820
commit 3e482b37b3
10 files changed
+555 -23

No files matched your search

+1 -1
View File
@@ -6,7 +6,7 @@
<groupId>com.loohp</groupId>
<artifactId>ImageFrame</artifactId>
<version>1.7.5.1</version>
<version>1.7.5.2</version>
<packaging>jar</packaging>
<name>ImageFrame</name>
@@ -24,6 +24,8 @@ import com.loohp.imageframe.api.events.ImageMapUpdatedEvent;
import com.loohp.imageframe.migration.ExternalPluginMigration;
import com.loohp.imageframe.migration.PluginMigrationRegistry;
import com.loohp.imageframe.objectholders.BlockPosition;
import com.loohp.imageframe.objectholders.IFPlayer;
import com.loohp.imageframe.objectholders.IFPlayerPreference;
import com.loohp.imageframe.objectholders.ImageMap;
import com.loohp.imageframe.objectholders.ImageMapAccessPermissionType;
import com.loohp.imageframe.objectholders.ItemFrameSelectionManager;
@@ -1179,6 +1181,51 @@ public class Commands implements CommandExecutor, TabCompleter {
sender.sendMessage(ImageFrame.messageNoPermission);
}
return true;
} else if (args[0].equalsIgnoreCase("preference")) {
if (sender.hasPermission("imageframe.preference")) {
if (args.length > 2) {
IFPlayerPreference<?> preference = IFPlayerPreference.valueOf(args[1].toUpperCase());
if (preference == null) {
sender.sendMessage(ImageFrame.messageInvalidUsage);
} else {
IFPlayerPreference.StringDeserializerResult<?> result = preference.getStringDeserializer().apply(args[2]);
if (result.isAccepted()) {
Scheduler.runTaskAsynchronously(ImageFrame.plugin, () -> {
UUID player;
if (args.length > 3) {
if (sender.hasPermission("imageframe.preference.others")) {
player = Bukkit.getOfflinePlayer(args[3]).getUniqueId();
} else {
sender.sendMessage(ImageFrame.messageNoPermission);
return;
}
} else if (sender instanceof Player) {
player = ((Player) sender).getUniqueId();
} else {
sender.sendMessage(ImageFrame.messageNoConsole);
return;
}
Object value = result.getValue();
IFPlayer ifPlayer = ImageFrame.ifPlayerManager.getIFPlayer(player);
ifPlayer.setPreference(preference, value);
try {
ifPlayer.save();
sender.sendMessage(ImageFrame.messagePreferencesUpdate.replace("{Preference}", ImageFrame.getPreferenceTranslatedName(preference)).replace("{Value}", ImageFrame.getPreferenceTranslatedValue(value)));
} catch (Exception e) {
throw new RuntimeException(e);
}
});
} else {
sender.sendMessage(ImageFrame.messageInvalidUsage);
}
}
} else {
sender.sendMessage(ImageFrame.messageInvalidUsage);
}
} else {
sender.sendMessage(ImageFrame.messageNoPermission);
}
return true;
}
sender.sendMessage(ChatColorUtils.translateAlternateColorCodes('&', Bukkit.spigot().getConfig().getString("messages.unknown-command")));
@@ -1248,6 +1295,9 @@ public class Commands implements CommandExecutor, TabCompleter {
if (sender.hasPermission("imageframe.adminmigrate")) {
tab.add("adminmigrate");
}
if (sender.hasPermission("imageframe.preference")) {
tab.add("preference");
}
return tab;
case 1:
if (sender.hasPermission("imageframe.reload")) {
@@ -1345,6 +1395,11 @@ public class Commands implements CommandExecutor, TabCompleter {
tab.add("adminmigrate");
}
}
if (sender.hasPermission("imageframe.preference")) {
if ("preference".startsWith(args[0].toLowerCase())) {
tab.add("preference");
}
}
return tab;
case 2:
if (sender.hasPermission("imageframe.create")) {
@@ -1458,6 +1513,15 @@ public class Commands implements CommandExecutor, TabCompleter {
}
}
}
if (sender.hasPermission("imageframe.preference")) {
if ("preference".equalsIgnoreCase(args[0])) {
for (IFPlayerPreference<?> preference : IFPlayerPreference.values()) {
if (preference.name().toLowerCase().startsWith(args[1].toLowerCase())) {
tab.add(preference.name().toLowerCase());
}
}
}
}
return tab;
case 3:
if (sender.hasPermission("imageframe.create")) {
@@ -1546,6 +1610,14 @@ public class Commands implements CommandExecutor, TabCompleter {
}
}
}
if (sender.hasPermission("imageframe.preference")) {
if ("preference".equalsIgnoreCase(args[0])) {
IFPlayerPreference<?> preference = IFPlayerPreference.valueOf(args[1].toUpperCase());
if (preference != null) {
tab.addAll(preference.getSuggestedValues());
}
}
}
return tab;
case 4:
if (sender.hasPermission("imageframe.create")) {
@@ -1628,6 +1700,15 @@ public class Commands implements CommandExecutor, TabCompleter {
}
}
}
if (sender.hasPermission("imageframe.preference.others")) {
if ("preference".equalsIgnoreCase(args[0])) {
for (Player player : Bukkit.getOnlinePlayers()) {
if (player.getName().toLowerCase().startsWith(args[3].toLowerCase())) {
tab.add(player.getName());
}
}
}
}
return tab;
case 5:
if (sender.hasPermission("imageframe.create")) {
@@ -27,6 +27,8 @@ import com.loohp.imageframe.metrics.Charts;
import com.loohp.imageframe.metrics.Metrics;
import com.loohp.imageframe.objectholders.AnimatedFakeMapManager;
import com.loohp.imageframe.objectholders.CombinedMapItemHandler;
import com.loohp.imageframe.objectholders.IFPlayerManager;
import com.loohp.imageframe.objectholders.IFPlayerPreference;
import com.loohp.imageframe.objectholders.ImageMap;
import com.loohp.imageframe.objectholders.ImageMapAccessPermissionType;
import com.loohp.imageframe.objectholders.ImageMapManager;
@@ -126,6 +128,10 @@ public class ImageFrame extends JavaPlugin {
public static SimpleDateFormat dateFormat;
public static String messagePreferencesUpdate;
public static Map<IFPlayerPreference<?>, String> preferenceNames;
public static Map<String, String> preferencesValues;
public static String mapItemFormat;
public static boolean requireEmptyMaps;
public static int mapMaxSize;
@@ -145,6 +151,7 @@ public class ImageFrame extends JavaPlugin {
public static boolean mapRenderersContextual;
public static ImageMapManager imageMapManager;
public static IFPlayerManager ifPlayerManager;
public static ItemFrameSelectionManager itemFrameSelectionManager;
public static MapMarkerEditManager mapMarkerEditManager;
public static CombinedMapItemHandler combinedMapItemHandler;
@@ -159,6 +166,15 @@ public class ImageFrame extends JavaPlugin {
return restrictImageUrls.stream().anyMatch(each -> normalized.startsWith(each.toLowerCase()));
}
public static String getPreferenceTranslatedName(IFPlayerPreference<?> preference) {
return preferenceNames.getOrDefault(preference, preference.name().toLowerCase());
}
public static String getPreferenceTranslatedValue(Object value) {
String str = String.valueOf(value);
return preferencesValues.getOrDefault(str.toUpperCase(), str);
}
public static int getPlayerCreationLimit(Player player) {
if (player.hasPermission("imageframe.createlimit.unlimited")) {
return -1;
@@ -243,6 +259,7 @@ public class ImageFrame extends JavaPlugin {
getServer().getPluginManager().registerEvents(new Events.ModernEvents(), this);
imageMapManager = new ImageMapManager(new File(getDataFolder(), "data"));
ifPlayerManager = new IFPlayerManager(new File(getDataFolder(), "players"));
itemFrameSelectionManager = new ItemFrameSelectionManager();
mapMarkerEditManager = new MapMarkerEditManager();
combinedMapItemHandler = new CombinedMapItemHandler();
@@ -332,6 +349,18 @@ public class ImageFrame extends JavaPlugin {
dateFormat = new SimpleDateFormat(config.getConfiguration().getString("Messages.DateFormat"));
messagePreferencesUpdate = ChatColorUtils.translateAlternateColorCodes('&', config.getConfiguration().getString("Messages.Preferences.UpdateMessage"));
preferenceNames = new HashMap<>();
for (IFPlayerPreference<?> preference : IFPlayerPreference.values()) {
if (config.getConfiguration().contains("Messages.Preferences.Keys." + preference.name())) {
preferenceNames.put(preference, ChatColorUtils.translateAlternateColorCodes('&', config.getConfiguration().getString("Messages.Preferences.Keys." + preference.name())));
}
}
preferencesValues = new HashMap<>();
for (String key : config.getConfiguration().getConfigurationSection("Messages.Preferences.Values").getKeys(false)) {
preferencesValues.put(key, ChatColorUtils.translateAlternateColorCodes('&', config.getConfiguration().getString("Messages.Preferences.Values." + key)));
}
mapItemFormat = ChatColorUtils.translateAlternateColorCodes('&', config.getConfiguration().getString("Settings.MapItemFormat"));
requireEmptyMaps = config.getConfiguration().getBoolean("Settings.RequireEmptyMaps");
mapMaxSize = config.getConfiguration().getInt("Settings.MaxSize");
@@ -168,32 +168,36 @@ public class AnimatedFakeMapManager implements Listener, Runnable {
}
for (Map.Entry<Player, List<FakeItemUtils.ItemFrameUpdateData>> entry : updateData.entrySet()) {
Player player = entry.getKey();
if (ImageFrame.viaHook && ViaHook.isPlayerLegacy(player)) {
if (!ImageFrame.viaDisableSmoothAnimationForLegacyPlayers) {
List<FakeItemUtils.ItemFrameUpdateData> list = entry.getValue();
for (FakeItemUtils.ItemFrameUpdateData data : list) {
MapUtils.sendImageMap(data.getRealMapId(), data.getMapView(), data.getCurrentPosition(), Collections.singleton(player), true);
if (ImageFrame.ifPlayerManager.getIFPlayer(player.getUniqueId()).getPreference(IFPlayerPreference.VIEW_ANIMATED_MAPS, boolean.class)) {
if (ImageFrame.viaHook && ViaHook.isPlayerLegacy(player)) {
if (!ImageFrame.viaDisableSmoothAnimationForLegacyPlayers) {
List<FakeItemUtils.ItemFrameUpdateData> list = entry.getValue();
for (FakeItemUtils.ItemFrameUpdateData data : list) {
MapUtils.sendImageMap(data.getRealMapId(), data.getMapView(), data.getCurrentPosition(), Collections.singleton(player), true);
}
}
} else {
FakeItemUtils.sendFakeItemChange(player, entry.getValue());
}
} else {
FakeItemUtils.sendFakeItemChange(player, entry.getValue());
}
}
for (Player player : Bukkit.getOnlinePlayers()) {
ItemStack mainhand = player.getEquipment().getItemInMainHand();
ItemStack offhand = player.getEquipment().getItemInOffHand();
MapView mainHandView = MapUtils.getItemMapView(mainhand);
MapView offhandView = MapUtils.getItemMapView(offhand);
if (mainHandView != null) {
ImageMap mainHandMap = ImageFrame.imageMapManager.getFromMapView(mainHandView);
if (mainHandMap != null && mainHandMap.requiresAnimationService()) {
mainHandMap.send(player);
if (ImageFrame.ifPlayerManager.getIFPlayer(player.getUniqueId()).getPreference(IFPlayerPreference.VIEW_ANIMATED_MAPS, boolean.class)) {
ItemStack mainhand = player.getEquipment().getItemInMainHand();
ItemStack offhand = player.getEquipment().getItemInOffHand();
MapView mainHandView = MapUtils.getItemMapView(mainhand);
MapView offhandView = MapUtils.getItemMapView(offhand);
if (mainHandView != null) {
ImageMap mainHandMap = ImageFrame.imageMapManager.getFromMapView(mainHandView);
if (mainHandMap != null && mainHandMap.requiresAnimationService()) {
mainHandMap.send(player);
}
}
}
if (offhandView != null && !offhandView.equals(mainHandView)) {
ImageMap offHandMap = ImageFrame.imageMapManager.getFromMapView(offhandView);
if (offHandMap != null && offHandMap.requiresAnimationService()) {
offHandMap.send(player);
if (offhandView != null && !offhandView.equals(mainHandView)) {
ImageMap offHandMap = ImageFrame.imageMapManager.getFromMapView(offhandView);
if (offHandMap != null && offHandMap.requiresAnimationService()) {
offHandMap.send(player);
}
}
}
}
@@ -0,0 +1,117 @@
/*
* This file is part of ImageFrame.
*
* Copyright (C) 2023. LoohpJames <jamesloohp@gmail.com>
* Copyright (C) 2023. Contributors
*
* 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 <https://www.gnu.org/licenses/>.
*/
package com.loohp.imageframe.objectholders;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import org.bukkit.Bukkit;
import org.bukkit.OfflinePlayer;
import java.io.File;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
public class IFPlayer {
public static final Gson GSON = new GsonBuilder().setPrettyPrinting().serializeNulls().create();
public static IFPlayer create(IFPlayerManager manager, UUID player) throws Exception {
IFPlayer ifPlayer = new IFPlayer(manager, player, Collections.emptyMap());
ifPlayer.save();
return ifPlayer;
}
public static IFPlayer load(IFPlayerManager manager, JsonObject json) {
UUID uuid = UUID.fromString(json.get("uuid").getAsString());
Map<IFPlayerPreference<?>, Object> preferences = new HashMap<>();
JsonObject preferenceJson = json.get("preferences").getAsJsonObject();
for (IFPlayerPreference<?> preference : IFPlayerPreference.values()) {
JsonElement element = preferenceJson.get(preference.getJsonName());
if (element != null) {
preferences.put(preference, preference.getDeserializer().apply(element));
}
}
return new IFPlayer(manager, uuid, preferences);
}
private final IFPlayerManager manager;
private final UUID uuid;
private final Map<IFPlayerPreference<?>, Object> preferences;
private IFPlayer(IFPlayerManager manager, UUID uuid, Map<IFPlayerPreference<?>, ?> preferences) {
this.manager = manager;
this.uuid = uuid;
this.preferences = new ConcurrentHashMap<>(preferences);
}
public OfflinePlayer getLocalPlayer() {
return Bukkit.getOfflinePlayer(uuid);
}
public String getName() {
return getLocalPlayer().getName();
}
public UUID getUniqueId() {
return uuid;
}
public Object getPreference(IFPlayerPreference<?> preference) {
return preferences.computeIfAbsent(preference, k -> preference.getDefaultValue(this));
}
@SuppressWarnings("unchecked")
public <T> T getPreference(IFPlayerPreference<?> preference, Class<T> type) {
return (T) preferences.computeIfAbsent(preference, k -> preference.getDefaultValue(this, type));
}
public void setPreference(IFPlayerPreference<?> preference, Object value) {
preferences.put(preference, value);
}
public void save() throws Exception {
manager.getDataFolder().mkdirs();
File file = new File(manager.getDataFolder(), uuid + ".json");
JsonObject json = new JsonObject();
json.addProperty("uuid", uuid.toString());
JsonObject preferenceJson = new JsonObject();
for (Map.Entry<IFPlayerPreference<?>, Object> entry : preferences.entrySet()) {
IFPlayerPreference<?> preference = entry.getKey();
preferenceJson.add(preference.getJsonName(), preference.getSerializer(Object.class).apply(entry.getValue()));
}
json.add("preferences", preferenceJson);
try (PrintWriter pw = new PrintWriter(new OutputStreamWriter(Files.newOutputStream(file.toPath()), StandardCharsets.UTF_8))) {
pw.println(GSON.toJson(json));
pw.flush();
}
}
}
@@ -0,0 +1,112 @@
/*
* This file is part of ImageFrame.
*
* Copyright (C) 2023. LoohpJames <jamesloohp@gmail.com>
* Copyright (C) 2023. Contributors
*
* 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 <https://www.gnu.org/licenses/>.
*/
package com.loohp.imageframe.objectholders;
import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonObject;
import com.loohp.imageframe.ImageFrame;
import org.bukkit.Bukkit;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.HandlerList;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerJoinEvent;
import org.bukkit.event.player.PlayerQuitEvent;
import java.io.BufferedReader;
import java.io.File;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
public class IFPlayerManager implements AutoCloseable, Listener {
public static final Gson GSON = new GsonBuilder().setPrettyPrinting().serializeNulls().create();
private final File dataFolder;
private final Map<UUID, IFPlayer> loadedPlayers;
private final Set<IFPlayer> persistentLoadedPlayers;
public IFPlayerManager(File dataFolder) {
this.dataFolder = dataFolder;
Cache<UUID, IFPlayer> playersCache = CacheBuilder.newBuilder().weakValues().build();
this.loadedPlayers = playersCache.asMap();
this.persistentLoadedPlayers = ConcurrentHashMap.newKeySet();
Bukkit.getPluginManager().registerEvents(this, ImageFrame.plugin);
}
public File getDataFolder() {
return dataFolder;
}
@Override
public void close() {
HandlerList.unregisterAll(this);
}
@EventHandler(priority = EventPriority.LOWEST)
public void onJoin(PlayerJoinEvent event) {
Scheduler.runTaskAsynchronously(ImageFrame.plugin, () -> persistentLoadedPlayers.add(getIFPlayer(event.getPlayer().getUniqueId())));
}
@EventHandler(priority = EventPriority.MONITOR)
public void onQuit(PlayerQuitEvent event) {
IFPlayer ifPlayer = getIFPlayer(event.getPlayer().getUniqueId());
if (ifPlayer != null) {
Scheduler.runTaskAsynchronously(ImageFrame.plugin, () -> {
try {
ifPlayer.save();
} catch (Exception e) {
e.printStackTrace();
}
persistentLoadedPlayers.remove(ifPlayer);
});
}
}
public IFPlayer getIFPlayer(UUID uuid) {
return loadedPlayers.computeIfAbsent(uuid, k -> {
dataFolder.mkdirs();
File file = new File(dataFolder, uuid + ".json");
if (file.exists()) {
try (BufferedReader reader = new BufferedReader(new InputStreamReader(Files.newInputStream(file.toPath()), StandardCharsets.UTF_8))) {
return IFPlayer.load(this, GSON.fromJson(reader, JsonObject.class));
} catch (Exception e) {
throw new RuntimeException("Unable to load ImageFrame player data from " + file.getAbsolutePath(), e);
}
} else {
try {
return IFPlayer.create(this, uuid);
} catch (Exception e) {
throw new RuntimeException("Unable to create ImageFrame player data for " + uuid, e);
}
}
});
}
}
@@ -0,0 +1,176 @@
/*
* This file is part of ImageFrame.
*
* Copyright (C) 2023. LoohpJames <jamesloohp@gmail.com>
* Copyright (C) 2023. Contributors
*
* 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 <https://www.gnu.org/licenses/>.
*/
package com.loohp.imageframe.objectholders;
import com.google.gson.JsonElement;
import com.google.gson.JsonPrimitive;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Function;
public class IFPlayerPreference<T> {
private static final Map<String, IFPlayerPreference<?>> VALUES = new ConcurrentHashMap<>();
public static final IFPlayerPreference<Boolean> VIEW_ANIMATED_MAPS = new IFPlayerPreference<>("VIEW_ANIMATED_MAPS", "viewAnimatedMaps", boolean.class, Arrays.asList("true", "false"), i -> true, v -> new JsonPrimitive(v), j -> j.getAsBoolean(), s -> StringDeserializerResult.accepted(Boolean.parseBoolean(s)));
static {
register(VIEW_ANIMATED_MAPS);
}
public static void register(IFPlayerPreference<?> preference) {
VALUES.put(preference.name(), preference);
}
public static Collection<IFPlayerPreference<?>> values() {
return Collections.unmodifiableCollection(VALUES.values());
}
public static IFPlayerPreference<?> valueOf(String name) {
return VALUES.get(name);
}
private final String name;
private final String jsonName;
private final Class<T> type;
private final List<String> suggestedValues;
private final Function<IFPlayer, T> defaultValue;
private final Function<T, JsonElement> serializer;
private final Function<JsonElement, T> deserializer;
private final Function<String, StringDeserializerResult<T>> stringDeserializer;
IFPlayerPreference(String name, String jsonName, Class<T> type, List<String> suggestedValues, Function<IFPlayer, T> defaultValue, Function<T, JsonElement> serializer, Function<JsonElement, T> deserializer, Function<String, StringDeserializerResult<T>> stringDeserializer) {
this.name = name;
this.jsonName = jsonName;
this.type = type;
this.suggestedValues = suggestedValues;
this.defaultValue = defaultValue;
this.serializer = serializer;
this.deserializer = deserializer;
this.stringDeserializer = stringDeserializer;
}
public String name() {
return name;
}
public String getJsonName() {
return jsonName;
}
public Class<T> getType() {
return type;
}
public List<String> getSuggestedValues() {
return suggestedValues;
}
public Function<T, JsonElement> getSerializer() {
return serializer;
}
@SuppressWarnings("unchecked")
public <E> Function<E, JsonElement> getSerializer(Class<E> type) {
return (Function<E, JsonElement>) serializer;
}
public Function<JsonElement, T> getDeserializer() {
return deserializer;
}
@SuppressWarnings("unchecked")
public <E> Function<JsonElement, E> getDeserializer(Class<E> type) {
return (Function<JsonElement, E>) deserializer;
}
public Function<String, StringDeserializerResult<T>> getStringDeserializer() {
return stringDeserializer;
}
@SuppressWarnings("unchecked")
public <E> Function<String, StringDeserializerResult<E>> getStringDeserializer(Class<E> type) {
return (Function<String, StringDeserializerResult<E>>) (Function<String, ?>) stringDeserializer;
}
public T getDefaultValue(IFPlayer ifPlayer) {
return defaultValue.apply(ifPlayer);
}
@SuppressWarnings("unchecked")
public <E> E getDefaultValue(IFPlayer ifPlayer, Class<E> type) {
return (E) defaultValue.apply(ifPlayer);
}
@Override
public String toString() {
return name();
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
IFPlayerPreference<?> that = (IFPlayerPreference<?>) o;
return Objects.equals(name, that.name);
}
@Override
public int hashCode() {
return Objects.hash(name);
}
public static class StringDeserializerResult<T> {
public static StringDeserializerResult<?> REJECTED_INSTANCE = new StringDeserializerResult<>(false, null);
@SuppressWarnings("unchecked")
public static <T> StringDeserializerResult<T> rejected() {
return (StringDeserializerResult<T>) REJECTED_INSTANCE;
}
public static <T> StringDeserializerResult<T> accepted(T result) {
return new StringDeserializerResult<>(true, result);
}
private final boolean accepted;
private final T value;
private StringDeserializerResult(boolean accepted, T value) {
this.accepted = accepted;
this.value = value;
}
public boolean isAccepted() {
return accepted;
}
public T getValue() {
return value;
}
}
}
@@ -209,7 +209,7 @@ public class MapMarkerEditManager implements Listener, AutoCloseable {
try {
Map<String, MapCursor> markers = imageMap.getMapMarkers(mapView);
if (!player.hasPermission("imageframe.marker.unlimited") && markers.size() >= ImageFrame.mapMarkerLimit) {
player.sendMessage(ImageFrame.messageMarkersLimitReached.replace("<Limit>", ImageFrame.mapMarkerLimit + ""));
player.sendMessage(ImageFrame.messageMarkersLimitReached.replace("{Limit}", ImageFrame.mapMarkerLimit + ""));
} else {
MapCursor mapCursor = editData.getMapCursor();
markers.put(editData.getName(), mapCursor);
+8 -1
View File
@@ -63,9 +63,16 @@ Messages:
DuplicateName: "&cThere is already a marker with that name!"
NotAMarker: "&cThat is not a valid marker"
NotRenderOnFrameWarning: "&eWarning: This marker type does not render on Item Frames!"
LimitReached: "&cYou can only create <Limit> markers on one map!"
LimitReached: "&cYou can only create {Limit} markers on one map!"
#Date format used where a time based variable is displayed
DateFormat: "dd/MM/yyyy HH:mm:ss zzz"
Preferences:
Keys:
VIEW_ANIMATED_MAPS: "View Animated Maps"
Values:
"TRUE": "&aEnabled"
"FALSE": "&cDisabled"
UpdateMessage: "&ePlayer Preference {Preference}&e has been updated to {Value}&e!"
Settings:
MapItemFormat: "&f{Name} &7({X}, {Y})"
+6
View File
@@ -84,6 +84,12 @@ permissions:
imageframe.adminmigrate:
default: op
description: Allow players to migrate maps from supported plugins to ImageFrame
imageframe.preference:
default: true
description: Allow players to update their player preferences
imageframe.preference.others:
default: op
description: Allow players to update other players' player preferences
imageframe.update:
default: op
description: Allows you receive update messages