mirror of
https://github.com/WiIIiam278/HuskSync.git
synced 2025-12-27 18:49:11 +00:00
Echest, invsee
This commit is contained in:
@@ -6,10 +6,7 @@ import dev.dejvokep.boostedyaml.settings.dumper.DumperSettings;
|
||||
import dev.dejvokep.boostedyaml.settings.general.GeneralSettings;
|
||||
import dev.dejvokep.boostedyaml.settings.loader.LoaderSettings;
|
||||
import dev.dejvokep.boostedyaml.settings.updater.UpdaterSettings;
|
||||
import net.william278.husksync.command.BukkitCommand;
|
||||
import net.william278.husksync.command.CommandBase;
|
||||
import net.william278.husksync.command.HuskSyncCommand;
|
||||
import net.william278.husksync.command.Permission;
|
||||
import net.william278.husksync.command.*;
|
||||
import net.william278.husksync.config.Locales;
|
||||
import net.william278.husksync.config.Settings;
|
||||
import net.william278.husksync.data.CompressedDataAdapter;
|
||||
@@ -17,6 +14,7 @@ import net.william278.husksync.data.DataAdapter;
|
||||
import net.william278.husksync.data.JsonDataAdapter;
|
||||
import net.william278.husksync.database.Database;
|
||||
import net.william278.husksync.database.MySqlDatabase;
|
||||
import net.william278.husksync.editor.DataEditor;
|
||||
import net.william278.husksync.listener.BukkitEventListener;
|
||||
import net.william278.husksync.listener.EventListener;
|
||||
import net.william278.husksync.player.BukkitPlayer;
|
||||
@@ -51,6 +49,8 @@ public class BukkitHuskSync extends JavaPlugin implements HuskSync {
|
||||
|
||||
private DataAdapter dataAdapter;
|
||||
|
||||
private DataEditor dataEditor;
|
||||
|
||||
private Settings settings;
|
||||
|
||||
private Locales locales;
|
||||
@@ -97,6 +97,7 @@ public class BukkitHuskSync extends JavaPlugin implements HuskSync {
|
||||
return loadedSettings;
|
||||
}).join();
|
||||
}).thenApply(succeeded -> {
|
||||
// Prepare data adapter
|
||||
if (succeeded) {
|
||||
if (settings.getBooleanValue(Settings.ConfigOption.SYNCHRONIZATION_COMPRESS_DATA)) {
|
||||
dataAdapter = new CompressedDataAdapter();
|
||||
@@ -105,6 +106,12 @@ public class BukkitHuskSync extends JavaPlugin implements HuskSync {
|
||||
}
|
||||
}
|
||||
return succeeded;
|
||||
}).thenApply(succeeded -> {
|
||||
// Prepare data editor
|
||||
if (succeeded) {
|
||||
dataEditor = new DataEditor();
|
||||
}
|
||||
return succeeded;
|
||||
}).thenApply(succeeded -> {
|
||||
// Establish connection to the database
|
||||
this.database = new MySqlDatabase(settings, resourceReader, logger, dataAdapter);
|
||||
@@ -160,11 +167,10 @@ public class BukkitHuskSync extends JavaPlugin implements HuskSync {
|
||||
})));
|
||||
|
||||
// Register commands
|
||||
final CommandBase[] commands = new CommandBase[]{new HuskSyncCommand(this)};
|
||||
for (CommandBase commandBase : commands) {
|
||||
final PluginCommand pluginCommand = getCommand(commandBase.command);
|
||||
for (final BukkitCommandType bukkitCommandType : BukkitCommandType.values()) {
|
||||
final PluginCommand pluginCommand = getCommand(bukkitCommandType.commandBase.command);
|
||||
if (pluginCommand != null) {
|
||||
new BukkitCommand(commandBase, this).register(pluginCommand);
|
||||
new BukkitCommand(bukkitCommandType.commandBase, this).register(pluginCommand);
|
||||
}
|
||||
}
|
||||
getLoggingAdapter().log(Level.INFO, "Successfully registered permissions & commands");
|
||||
@@ -226,6 +232,11 @@ public class BukkitHuskSync extends JavaPlugin implements HuskSync {
|
||||
return dataAdapter;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull DataEditor getDataEditor() {
|
||||
return dataEditor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Settings getSettings() {
|
||||
return settings;
|
||||
|
||||
@@ -67,4 +67,5 @@ public class BukkitCommand implements CommandExecutor, TabExecutor {
|
||||
}
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
package net.william278.husksync.command;
|
||||
|
||||
import net.william278.husksync.BukkitHuskSync;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* Commands available on the Bukkit HuskSync implementation
|
||||
*/
|
||||
public enum BukkitCommandType {
|
||||
HUSKSYNC_COMMAND(new HuskSyncCommand(BukkitHuskSync.getInstance())),
|
||||
HUSKSYNC_INVSEE(new InvseeCommand(BukkitHuskSync.getInstance())),
|
||||
HUSKSYNC_ECHEST(new EchestCommand(BukkitHuskSync.getInstance()));
|
||||
|
||||
public final CommandBase commandBase;
|
||||
|
||||
BukkitCommandType(@NotNull CommandBase commandBase) {
|
||||
this.commandBase = commandBase;
|
||||
}
|
||||
}
|
||||
@@ -21,7 +21,7 @@ public class BukkitSerializer {
|
||||
* @param inventoryContents The contents of the inventory
|
||||
* @return The serialized inventory contents
|
||||
*/
|
||||
public static CompletableFuture<String> serializeInventory(ItemStack[] inventoryContents) {
|
||||
public static CompletableFuture<String> serializeInventory(ItemStack[] inventoryContents) throws DataDeserializationException {
|
||||
return CompletableFuture.supplyAsync(() -> {
|
||||
// Return an empty string if there is no inventory item data to serialize
|
||||
if (inventoryContents.length == 0) {
|
||||
@@ -54,7 +54,7 @@ public class BukkitSerializer {
|
||||
* @param inventoryData The serialized {@link ItemStack[]} array
|
||||
* @return The inventory contents as an array of {@link ItemStack}s
|
||||
*/
|
||||
public static CompletableFuture<ItemStack[]> deserializeInventory(String inventoryData) {
|
||||
public static CompletableFuture<ItemStack[]> deserializeInventory(String inventoryData) throws DataDeserializationException {
|
||||
return CompletableFuture.supplyAsync(() -> {
|
||||
// Return empty array if there is no inventory data (set the player as having an empty inventory)
|
||||
if (inventoryData.isEmpty()) {
|
||||
@@ -89,6 +89,7 @@ public class BukkitSerializer {
|
||||
* @param item The {@link ItemStack} to serialize
|
||||
* @return The serialized {@link ItemStack}
|
||||
*/
|
||||
@Nullable
|
||||
private static Map<String, Object> serializeItemStack(ItemStack item) {
|
||||
return item != null ? item.serialize() : null;
|
||||
}
|
||||
@@ -100,6 +101,7 @@ public class BukkitSerializer {
|
||||
* @return The deserialized {@link ItemStack}
|
||||
*/
|
||||
@SuppressWarnings("unchecked") // Ignore the "Unchecked cast" warning
|
||||
@Nullable
|
||||
private static ItemStack deserializeItemStack(Object serializedItemStack) {
|
||||
return serializedItemStack != null ? ItemStack.deserialize((Map<String, Object>) serializedItemStack) : null;
|
||||
}
|
||||
@@ -110,7 +112,7 @@ public class BukkitSerializer {
|
||||
* @param potionEffects The potion effect array
|
||||
* @return The serialized potion effects
|
||||
*/
|
||||
public static CompletableFuture<String> serializePotionEffects(PotionEffect[] potionEffects) {
|
||||
public static CompletableFuture<String> serializePotionEffects(PotionEffect[] potionEffects) throws DataDeserializationException {
|
||||
return CompletableFuture.supplyAsync(() -> {
|
||||
// Return an empty string if there are no effects to serialize
|
||||
if (potionEffects.length == 0) {
|
||||
@@ -143,7 +145,7 @@ public class BukkitSerializer {
|
||||
* @param potionEffectData The serialized {@link PotionEffect[]} array
|
||||
* @return The {@link PotionEffect}s
|
||||
*/
|
||||
public static CompletableFuture<PotionEffect[]> deserializePotionEffects(String potionEffectData) {
|
||||
public static CompletableFuture<PotionEffect[]> deserializePotionEffects(String potionEffectData) throws DataDeserializationException {
|
||||
return CompletableFuture.supplyAsync(() -> {
|
||||
// Return empty array if there is no potion effect data (don't apply any effects to the player)
|
||||
if (potionEffectData.isEmpty()) {
|
||||
|
||||
@@ -1,15 +1,29 @@
|
||||
package net.william278.husksync.listener;
|
||||
|
||||
import net.william278.husksync.BukkitHuskSync;
|
||||
import net.william278.husksync.data.BukkitSerializer;
|
||||
import net.william278.husksync.data.DataDeserializationException;
|
||||
import net.william278.husksync.data.InventoryData;
|
||||
import net.william278.husksync.player.BukkitPlayer;
|
||||
import net.william278.husksync.player.OnlineUser;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.EventPriority;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.block.BlockBreakEvent;
|
||||
import org.bukkit.event.block.BlockPlaceEvent;
|
||||
import org.bukkit.event.entity.EntityPickupItemEvent;
|
||||
import org.bukkit.event.inventory.InventoryCloseEvent;
|
||||
import org.bukkit.event.inventory.InventoryOpenEvent;
|
||||
import org.bukkit.event.player.PlayerDropItemEvent;
|
||||
import org.bukkit.event.player.PlayerInteractEvent;
|
||||
import org.bukkit.event.player.PlayerJoinEvent;
|
||||
import org.bukkit.event.player.PlayerQuitEvent;
|
||||
import org.bukkit.event.world.WorldSaveEvent;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.logging.Level;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class BukkitEventListener extends EventListener implements Listener {
|
||||
@@ -36,11 +50,60 @@ public class BukkitEventListener extends EventListener implements Listener {
|
||||
.collect(Collectors.toList()));
|
||||
}
|
||||
|
||||
/*@EventHandler(ignoreCancelled = true)
|
||||
public void onGenericPlayerEvent(@NotNull PlayerEvent event) {
|
||||
if (event instanceof Cancellable) {
|
||||
((Cancellable) event).setCancelled(cancelPlayerEvent(BukkitPlayer.adapt(event.getPlayer())));
|
||||
@EventHandler(ignoreCancelled = true)
|
||||
public void onInventoryClose(@NotNull InventoryCloseEvent event) {
|
||||
if (event.getPlayer() instanceof Player player) {
|
||||
final OnlineUser user = BukkitPlayer.adapt(player);
|
||||
if (huskSync.getDataEditor().isEditingInventoryData(user)) {
|
||||
try {
|
||||
BukkitSerializer.serializeInventory(event.getInventory().getContents()).thenAccept(
|
||||
serializedInventory -> super.handleMenuClose(user, new InventoryData(serializedInventory)));
|
||||
} catch (DataDeserializationException e) {
|
||||
huskSync.getLoggingAdapter().log(Level.SEVERE,
|
||||
"Failed to serialize inventory data during menu close", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}*/
|
||||
}
|
||||
|
||||
/*
|
||||
* Events to cancel if the player has not been set yet
|
||||
*/
|
||||
|
||||
@EventHandler(priority = EventPriority.HIGHEST)
|
||||
public void onDropItem(@NotNull PlayerDropItemEvent event) {
|
||||
event.setCancelled(cancelPlayerEvent(BukkitPlayer.adapt(event.getPlayer())));
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.HIGHEST)
|
||||
public void onPickupItem(@NotNull EntityPickupItemEvent event) {
|
||||
if (event.getEntity() instanceof Player player) {
|
||||
event.setCancelled(cancelPlayerEvent(BukkitPlayer.adapt(player)));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.HIGHEST)
|
||||
public void onPlayerInteract(@NotNull PlayerInteractEvent event) {
|
||||
event.setCancelled(cancelPlayerEvent(BukkitPlayer.adapt(event.getPlayer())));
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.HIGHEST)
|
||||
public void onBlockPlace(@NotNull BlockPlaceEvent event) {
|
||||
event.setCancelled(cancelPlayerEvent(BukkitPlayer.adapt(event.getPlayer())));
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.HIGHEST)
|
||||
public void onBlockBreak(@NotNull BlockBreakEvent event) {
|
||||
event.setCancelled(cancelPlayerEvent(BukkitPlayer.adapt(event.getPlayer())));
|
||||
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.HIGHEST)
|
||||
public void onInventoryOpen(@NotNull InventoryOpenEvent event) {
|
||||
if (event.getPlayer() instanceof Player player) {
|
||||
event.setCancelled(cancelPlayerEvent(BukkitPlayer.adapt(player)));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -2,8 +2,10 @@ package net.william278.husksync.player;
|
||||
|
||||
import de.themoep.minedown.MineDown;
|
||||
import net.md_5.bungee.api.ChatMessageType;
|
||||
import net.md_5.bungee.api.chat.BaseComponent;
|
||||
import net.william278.husksync.BukkitHuskSync;
|
||||
import net.william278.husksync.data.*;
|
||||
import net.william278.husksync.editor.InventoryEditorMenu;
|
||||
import org.apache.commons.lang.ArrayUtils;
|
||||
import org.bukkit.*;
|
||||
import org.bukkit.advancement.Advancement;
|
||||
@@ -12,6 +14,7 @@ import org.bukkit.attribute.Attribute;
|
||||
import org.bukkit.entity.EntityType;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.player.PlayerTeleportEvent;
|
||||
import org.bukkit.inventory.Inventory;
|
||||
import org.bukkit.persistence.PersistentDataContainer;
|
||||
import org.bukkit.persistence.PersistentDataType;
|
||||
import org.bukkit.potion.PotionEffect;
|
||||
@@ -423,6 +426,20 @@ public class BukkitPlayer extends OnlineUser {
|
||||
return player.hasPermission(node);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void showMenu(@NotNull InventoryEditorMenu menu) {
|
||||
BukkitSerializer.deserializeInventory(menu.inventoryData.serializedInventory).thenAccept(inventoryContents -> {
|
||||
final Inventory inventory = Bukkit.createInventory(player, menu.slotCount,
|
||||
BaseComponent.toLegacyText(menu.menuTitle.toComponent()));
|
||||
inventory.setContents(inventoryContents);
|
||||
Bukkit.getScheduler().runTask(BukkitHuskSync.getInstance(), () -> {
|
||||
player.closeInventory();
|
||||
player.openInventory(inventory);
|
||||
});
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendActionBar(@NotNull MineDown mineDown) {
|
||||
player.spigot().sendMessage(ChatMessageType.ACTION_BAR, mineDown.toComponent());
|
||||
|
||||
@@ -3,6 +3,7 @@ package net.william278.husksync;
|
||||
import net.william278.husksync.config.Locales;
|
||||
import net.william278.husksync.config.Settings;
|
||||
import net.william278.husksync.data.DataAdapter;
|
||||
import net.william278.husksync.editor.DataEditor;
|
||||
import net.william278.husksync.database.Database;
|
||||
import net.william278.husksync.player.OnlineUser;
|
||||
import net.william278.husksync.redis.RedisManager;
|
||||
@@ -26,6 +27,8 @@ public interface HuskSync {
|
||||
|
||||
@NotNull DataAdapter getDataAdapter();
|
||||
|
||||
@NotNull DataEditor getDataEditor();
|
||||
|
||||
@NotNull Settings getSettings();
|
||||
|
||||
@NotNull Locales getLocales();
|
||||
|
||||
@@ -0,0 +1,63 @@
|
||||
package net.william278.husksync.command;
|
||||
|
||||
import net.william278.husksync.HuskSync;
|
||||
import net.william278.husksync.data.UserData;
|
||||
import net.william278.husksync.data.VersionedUserData;
|
||||
import net.william278.husksync.editor.InventoryEditorMenu;
|
||||
import net.william278.husksync.player.OnlineUser;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
|
||||
public class EchestCommand extends CommandBase {
|
||||
|
||||
public EchestCommand(@NotNull HuskSync implementor) {
|
||||
super("echest", Permission.COMMAND_VIEW_INVENTORIES, implementor, "openechest");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onExecute(@NotNull OnlineUser player, @NotNull String[] args) {
|
||||
if (args.length == 0 || args.length > 2) {
|
||||
plugin.getLocales().getLocale("error_invalid_syntax", "/echest <player>")
|
||||
.ifPresent(player::sendMessage);
|
||||
return;
|
||||
}
|
||||
plugin.getDatabase().getUserByName(args[0].toLowerCase()).thenAcceptAsync(optionalUser -> {
|
||||
optionalUser.ifPresentOrElse(user -> {
|
||||
List<VersionedUserData> userData = plugin.getDatabase().getUserData(user).join();
|
||||
Optional<VersionedUserData> dataToView;
|
||||
if (args.length == 2) {
|
||||
try {
|
||||
final UUID version = UUID.fromString(args[1]);
|
||||
dataToView = userData.stream().filter(data -> data.versionUUID().equals(version)).findFirst();
|
||||
} catch (IllegalArgumentException e) {
|
||||
plugin.getLocales().getLocale("error_invalid_syntax",
|
||||
"/echest <player> [version_uuid]").ifPresent(player::sendMessage);
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
dataToView = userData.stream().sorted().findFirst();
|
||||
}
|
||||
dataToView.ifPresentOrElse(versionedUserData -> {
|
||||
final UserData data = versionedUserData.userData();
|
||||
final InventoryEditorMenu menu = InventoryEditorMenu.createEnderChestMenu(
|
||||
data.getEnderChestData(), user, player);
|
||||
plugin.getLocales().getLocale("viewing_ender_chest_of", user.username)
|
||||
.ifPresent(player::sendMessage);
|
||||
plugin.getDataEditor().openInventoryMenu(player, menu).thenAcceptAsync(inventoryDataOnClose -> {
|
||||
final UserData updatedUserData = new UserData(data.getStatusData(),
|
||||
data.getInventoryData(), menu.canEdit ? inventoryDataOnClose : data.getEnderChestData(),
|
||||
data.getPotionEffectData(), data.getAdvancementData(),
|
||||
data.getStatisticData(), data.getLocationData(),
|
||||
data.getPersistentDataContainerData());
|
||||
plugin.getDatabase().setUserData(user, updatedUserData).join();
|
||||
});
|
||||
}, () -> plugin.getLocales().getLocale(args.length == 2 ? "error_invalid_version_uuid"
|
||||
: "error_no_data_to_display").ifPresent(player::sendMessage));
|
||||
}, () -> plugin.getLocales().getLocale("error_invalid_player").ifPresent(player::sendMessage));
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
package net.william278.husksync.command;
|
||||
|
||||
import net.william278.husksync.HuskSync;
|
||||
import net.william278.husksync.data.UserData;
|
||||
import net.william278.husksync.data.VersionedUserData;
|
||||
import net.william278.husksync.editor.InventoryEditorMenu;
|
||||
import net.william278.husksync.player.OnlineUser;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
|
||||
public class InvseeCommand extends CommandBase {
|
||||
|
||||
public InvseeCommand(@NotNull HuskSync implementor) {
|
||||
super("invsee", Permission.COMMAND_VIEW_INVENTORIES, implementor, "openinv");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onExecute(@NotNull OnlineUser player, @NotNull String[] args) {
|
||||
if (args.length == 0 || args.length > 2) {
|
||||
plugin.getLocales().getLocale("error_invalid_syntax", "/invsee <player>")
|
||||
.ifPresent(player::sendMessage);
|
||||
return;
|
||||
}
|
||||
plugin.getDatabase().getUserByName(args[0].toLowerCase()).thenAcceptAsync(optionalUser -> {
|
||||
optionalUser.ifPresentOrElse(user -> {
|
||||
List<VersionedUserData> userData = plugin.getDatabase().getUserData(user).join();
|
||||
Optional<VersionedUserData> dataToView;
|
||||
if (args.length == 2) {
|
||||
try {
|
||||
final UUID version = UUID.fromString(args[1]);
|
||||
dataToView = userData.stream().filter(data -> data.versionUUID().equals(version)).findFirst();
|
||||
} catch (IllegalArgumentException e) {
|
||||
plugin.getLocales().getLocale("error_invalid_syntax",
|
||||
"/invsee <player> [version_uuid]").ifPresent(player::sendMessage);
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
dataToView = userData.stream().sorted().findFirst();
|
||||
}
|
||||
dataToView.ifPresentOrElse(versionedUserData -> {
|
||||
final UserData data = versionedUserData.userData();
|
||||
final InventoryEditorMenu menu = InventoryEditorMenu.createInventoryMenu(
|
||||
data.getInventoryData(), user, player);
|
||||
plugin.getLocales().getLocale("viewing_inventory_of", user.username)
|
||||
.ifPresent(player::sendMessage);
|
||||
plugin.getDataEditor().openInventoryMenu(player, menu).thenAcceptAsync(inventoryDataOnClose -> {
|
||||
final UserData updatedUserData = new UserData(data.getStatusData(),
|
||||
menu.canEdit ? inventoryDataOnClose : data.getInventoryData(),
|
||||
data.getEnderChestData(), data.getPotionEffectData(), data.getAdvancementData(),
|
||||
data.getStatisticData(), data.getLocationData(),
|
||||
data.getPersistentDataContainerData());
|
||||
plugin.getDatabase().setUserData(user, updatedUserData).join();
|
||||
});
|
||||
}, () -> plugin.getLocales().getLocale(args.length == 2 ? "error_invalid_version_uuid"
|
||||
: "error_no_data_to_display").ifPresent(player::sendMessage));
|
||||
}, () -> plugin.getLocales().getLocale("error_invalid_player").ifPresent(player::sendMessage));
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,90 @@
|
||||
package net.william278.husksync.editor;
|
||||
|
||||
import net.william278.husksync.config.Locales;
|
||||
import net.william278.husksync.data.InventoryData;
|
||||
import net.william278.husksync.data.VersionedUserData;
|
||||
import net.william278.husksync.player.OnlineUser;
|
||||
import net.william278.husksync.player.User;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
/**
|
||||
* Provides methods for displaying and editing user data
|
||||
*/
|
||||
public class DataEditor {
|
||||
|
||||
/**
|
||||
* Map of currently open inventory and ender chest data editors
|
||||
*/
|
||||
@NotNull
|
||||
protected final HashMap<UUID, InventoryEditorMenu> openInventoryMenus;
|
||||
|
||||
public DataEditor() {
|
||||
this.openInventoryMenus = new HashMap<>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Open an inventory or ender chest editor menu
|
||||
*
|
||||
* @param user The online user to open the editor for
|
||||
* @param inventoryEditorMenu The {@link InventoryEditorMenu} to open
|
||||
* @return The inventory editor menu
|
||||
* @see InventoryEditorMenu#createInventoryMenu(InventoryData, User, OnlineUser)
|
||||
* @see InventoryEditorMenu#createEnderChestMenu(InventoryData, User, OnlineUser)
|
||||
*/
|
||||
public CompletableFuture<InventoryData> openInventoryMenu(@NotNull OnlineUser user,
|
||||
@NotNull InventoryEditorMenu inventoryEditorMenu) {
|
||||
this.openInventoryMenus.put(user.uuid, inventoryEditorMenu);
|
||||
return inventoryEditorMenu.showInventory(user);
|
||||
}
|
||||
|
||||
/**
|
||||
* Close an inventory or ender chest editor menu
|
||||
*
|
||||
* @param user The online user to close the editor for
|
||||
* @param inventoryData the {@link InventoryData} contained within the menu at the time of closing
|
||||
*/
|
||||
public void closeInventoryMenu(@NotNull OnlineUser user, @NotNull InventoryData inventoryData) {
|
||||
if (this.openInventoryMenus.containsKey(user.uuid)) {
|
||||
this.openInventoryMenus.get(user.uuid).closeInventory(inventoryData);
|
||||
}
|
||||
this.openInventoryMenus.remove(user.uuid);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether edits to the inventory or ender chest menu are allowed
|
||||
*
|
||||
* @param user The online user with an inventory open to check
|
||||
* @return {@code true} if edits to the inventory or ender chest menu are allowed; {@code false} otherwise, including if they don't have an inventory open
|
||||
*/
|
||||
public boolean cancelInventoryEdit(@NotNull OnlineUser user) {
|
||||
if (this.openInventoryMenus.containsKey(user.uuid)) {
|
||||
return !this.openInventoryMenus.get(user.uuid).canEdit;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Display a chat message detailing information about {@link VersionedUserData}
|
||||
*
|
||||
* @param user The online user to display the message to
|
||||
* @param userData The {@link VersionedUserData} to display information about
|
||||
* @param dataOwner The {@link User} who owns the {@link VersionedUserData}
|
||||
*/
|
||||
public void displayDataOverview(@NotNull OnlineUser user, @NotNull VersionedUserData userData,
|
||||
@NotNull User dataOwner) {
|
||||
//todo
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the user has an inventory editor menu open
|
||||
* @param user {@link OnlineUser} to check
|
||||
* @return {@code true} if the user has an inventory editor open; {@code false} otherwise
|
||||
*/
|
||||
public boolean isEditingInventoryData(@NotNull OnlineUser user) {
|
||||
return this.openInventoryMenus.containsKey(user.uuid);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
package net.william278.husksync.editor;
|
||||
|
||||
import de.themoep.minedown.MineDown;
|
||||
import net.william278.husksync.command.Permission;
|
||||
import net.william278.husksync.data.InventoryData;
|
||||
import net.william278.husksync.player.OnlineUser;
|
||||
import net.william278.husksync.player.User;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
public class InventoryEditorMenu {
|
||||
|
||||
public final InventoryData inventoryData;
|
||||
public final int slotCount;
|
||||
public final MineDown menuTitle;
|
||||
public final boolean canEdit;
|
||||
|
||||
private CompletableFuture<InventoryData> inventoryDataCompletableFuture;
|
||||
|
||||
private InventoryEditorMenu(@NotNull InventoryData inventoryData, int slotCount,
|
||||
@NotNull MineDown menuTitle, boolean canEdit) {
|
||||
this.inventoryData = inventoryData;
|
||||
this.menuTitle = menuTitle;
|
||||
this.slotCount = slotCount;
|
||||
this.canEdit = canEdit;
|
||||
}
|
||||
|
||||
public CompletableFuture<InventoryData> showInventory(@NotNull OnlineUser user) {
|
||||
inventoryDataCompletableFuture = new CompletableFuture<>();
|
||||
user.showMenu(this);
|
||||
return inventoryDataCompletableFuture;
|
||||
}
|
||||
|
||||
public void closeInventory(@NotNull InventoryData inventoryData) {
|
||||
inventoryDataCompletableFuture.completeAsync(() -> inventoryData);
|
||||
}
|
||||
|
||||
public static InventoryEditorMenu createInventoryMenu(@NotNull InventoryData inventoryData, @NotNull User dataOwner,
|
||||
@NotNull OnlineUser viewer) {
|
||||
return new InventoryEditorMenu(inventoryData, 45,
|
||||
new MineDown(dataOwner.username + "'s Inventory"),
|
||||
viewer.hasPermission(Permission.COMMAND_EDIT_INVENTORIES.node));
|
||||
}
|
||||
|
||||
public static InventoryEditorMenu createEnderChestMenu(@NotNull InventoryData inventoryData, @NotNull User dataOwner,
|
||||
@NotNull OnlineUser viewer) {
|
||||
return new InventoryEditorMenu(inventoryData, 27,
|
||||
new MineDown(dataOwner.username + "'s Ender Chest"),
|
||||
viewer.hasPermission(Permission.COMMAND_EDIT_ENDER_CHESTS.node));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -2,6 +2,7 @@ package net.william278.husksync.listener;
|
||||
|
||||
import net.william278.husksync.HuskSync;
|
||||
import net.william278.husksync.config.Settings;
|
||||
import net.william278.husksync.data.InventoryData;
|
||||
import net.william278.husksync.player.OnlineUser;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
@@ -19,7 +20,7 @@ public abstract class EventListener {
|
||||
/**
|
||||
* The plugin instance
|
||||
*/
|
||||
private final HuskSync huskSync;
|
||||
protected final HuskSync huskSync;
|
||||
|
||||
/**
|
||||
* Set of UUIDs current awaiting item synchronization. Events will be cancelled for these users
|
||||
@@ -84,6 +85,7 @@ public abstract class EventListener {
|
||||
}
|
||||
|
||||
public final void handlePlayerQuit(@NotNull OnlineUser user) {
|
||||
// Players quitting have their data manually saved by the plugin disable hook
|
||||
if (disabling) {
|
||||
return;
|
||||
}
|
||||
@@ -110,8 +112,22 @@ public abstract class EventListener {
|
||||
huskSync.getRedisManager().close();
|
||||
}
|
||||
|
||||
public final void handleMenuClose(@NotNull OnlineUser user, @NotNull InventoryData menuInventory) {
|
||||
if (disabling) {
|
||||
return;
|
||||
}
|
||||
huskSync.getDataEditor().closeInventoryMenu(user, menuInventory);
|
||||
}
|
||||
|
||||
public final boolean cancelMenuClick(@NotNull OnlineUser user) {
|
||||
if (disabling) {
|
||||
return true;
|
||||
}
|
||||
return huskSync.getDataEditor().cancelInventoryEdit(user);
|
||||
}
|
||||
|
||||
public final boolean cancelPlayerEvent(@NotNull OnlineUser user) {
|
||||
return usersAwaitingSync.contains(user.uuid);
|
||||
return disabling || usersAwaitingSync.contains(user.uuid);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ package net.william278.husksync.player;
|
||||
import de.themoep.minedown.MineDown;
|
||||
import net.william278.husksync.config.Settings;
|
||||
import net.william278.husksync.data.*;
|
||||
import net.william278.husksync.editor.InventoryEditorMenu;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.List;
|
||||
@@ -236,6 +237,13 @@ public abstract class OnlineUser extends User {
|
||||
*/
|
||||
public abstract boolean hasPermission(@NotNull String node);
|
||||
|
||||
/**
|
||||
* Show the player a {@link InventoryEditorMenu} GUI
|
||||
*
|
||||
* @param menu The {@link InventoryEditorMenu} interface to show
|
||||
*/
|
||||
public abstract void showMenu(@NotNull InventoryEditorMenu menu);
|
||||
|
||||
/**
|
||||
* Get the player's current {@link UserData}
|
||||
*
|
||||
|
||||
@@ -3,7 +3,7 @@ viewing_inventory_of: '[Viewing the inventory of](#00fb9a) [%1%](#00fb9a bold)'
|
||||
viewing_ender_chest_of: '[Viewing the ender chest of](#00fb9a) [%1%](#00fb9a bold)'
|
||||
reload_complete: '[HuskSync](#00fb9a bold) [| Reloaded config and message files.](#00fb9a)'
|
||||
error_invalid_syntax: '[Error:](#ff3300) [Incorrect syntax. Usage: %1%](#ff7e5e)'
|
||||
error_invalid_player: '[Error:](#ff3300) [Could not find that player](#ff7e5e)'
|
||||
error_invalid_player: '[Error:](#ff3300) [Could not find that player.](#ff7e5e)'
|
||||
error_no_permission: '[Error:](#ff3300) [You do not have permission to execute this command](#ff7e5e)'
|
||||
error_cannot_view_inventory_online: '[Error:](#ff3300) [You can''t access the inventory of an online player through HuskSync](#ff7e5e)'
|
||||
error_cannot_view_ender_chest_online: '[Error:](#ff3300) [You can''t access the ender chest of an online player through HuskSync](#ff7e5e)'
|
||||
@@ -11,4 +11,7 @@ error_cannot_view_own_inventory: '[Error:](#ff3300) [You can''t access your own
|
||||
error_cannot_view_own_ender_chest: '[Error:](#ff3300) [You can''t access your own ender chest!](#ff7e5e)'
|
||||
error_console_command_only: '[Error:](#ff3300) [That command can only be run through the %1% console](#ff7e5e)'
|
||||
error_no_servers_proxied: '[Error:](#ff3300) [Failed to process operation; no servers are online that have HuskSync installed. Please ensure HuskSync is installed on both the Proxy server and all servers you wish to synchronise data between.](#ff7e5e)'
|
||||
error_invalid_cluster: '[Error:](#ff3300) [Please specify the ID of a valid cluster.](#ff7e5e)'
|
||||
error_invalid_cluster: '[Error:](#ff3300) [Please specify the ID of a valid cluster.](#ff7e5e)'
|
||||
|
||||
error_no_data_to_display: '[Error:](#ff3300) [Could not find any user data to display.](#ff7e5e)'
|
||||
error_invalid_version_uuid: '[Error:](#ff3300) [Could not find any user data for that version UUID.](#ff7e5e)'
|
||||
Reference in New Issue
Block a user