Added preference command
This commit is contained in:
1 parent
8f563d3820
commit
3e482b37b3
10 files changed
+555
-23
No files matched your search
@@ -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);
|
||||
|
||||
@@ -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})"
|
||||
|
||||
@@ -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
|
||||
Reference in new issue
Block a user