Skip to content

Commit

Permalink
Added /is admin data to interact with persistent data of players or…
Browse files Browse the repository at this point in the history
… islands
  • Loading branch information
OmerBenGera committed Aug 6, 2022
1 parent e122819 commit a9d02d1
Show file tree
Hide file tree
Showing 23 changed files with 610 additions and 4 deletions.
Expand Up @@ -10,4 +10,15 @@ public interface IPersistentDataHolder {
*/
PersistentDataContainer getPersistentDataContainer();

/**
* Check if the persistent data container is empty.
*/
boolean isPersistentDataContainerEmpty();

/**
* When saving data into the container, it's not immediately saved to database.
* Call this method to save the persistent data container into database.
*/
void savePersistentDataContainer();

}
@@ -1,6 +1,7 @@
package com.bgsoftware.superiorskyblock.api.persistence;

import javax.annotation.Nullable;
import java.util.function.BiConsumer;

public interface PersistentDataContainer {

Expand Down Expand Up @@ -117,6 +118,13 @@ public interface PersistentDataContainer {
*/
int size();

/**
* Iterate through all the data of the container.
*
* @param action The action to perform for each key and value pair.
*/
void forEach(BiConsumer<String, Object> action);

/**
* Get the serialized contents of the container as a bytes array.
* The format of the serialized data may be different depending on the implementation of the container.
Expand Down
Expand Up @@ -25,6 +25,7 @@ public void loadDefaultCommands() {
registerCommand(new CmdAdminClose(), false);
registerCommand(new CmdAdminCmdAll(), false);
registerCommand(new CmdAdminCount(), false);
registerCommand(new CmdAdminData(), false);
registerCommand(new CmdAdminDebug(), false);
registerCommand(new CmdAdminDelWarp(), false);
registerCommand(new CmdAdminDemote(), false);
Expand Down
@@ -0,0 +1,291 @@
package com.bgsoftware.superiorskyblock.commands.admin;

import com.bgsoftware.superiorskyblock.SuperiorSkyblockPlugin;
import com.bgsoftware.superiorskyblock.api.objects.Pair;
import com.bgsoftware.superiorskyblock.api.persistence.IPersistentDataHolder;
import com.bgsoftware.superiorskyblock.api.persistence.PersistentDataContainer;
import com.bgsoftware.superiorskyblock.api.persistence.PersistentDataType;
import com.bgsoftware.superiorskyblock.commands.CommandTabCompletes;
import com.bgsoftware.superiorskyblock.commands.ISuperiorCommand;
import com.bgsoftware.superiorskyblock.commands.arguments.CommandArguments;
import com.bgsoftware.superiorskyblock.commands.arguments.IslandArgument;
import com.bgsoftware.superiorskyblock.core.messages.Message;
import com.bgsoftware.superiorskyblock.core.serialization.impl.PersistentDataSerializer;
import com.bgsoftware.superiorskyblock.player.PlayerLocales;
import com.google.common.collect.ImmutableMap;
import org.bukkit.command.CommandSender;

import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Locale;
import java.util.Map;

public class CmdAdminData implements ISuperiorCommand {

private static final Map<String, SubCommand> subCommands = new ImmutableMap.Builder<String, SubCommand>()
.put("set", new SetSubCommand())
.put("get", new GetSubCommand())
.put("remove", new RemoveSubCommand())
.build();

@Override
public List<String> getAliases() {
return Collections.singletonList("data");
}

@Override
public String getPermission() {
return "superior.admin.data";
}

@Override
public String getUsage(java.util.Locale locale) {
return "admin data <get/set/remove> <player/island> <" +
Message.COMMAND_ARGUMENT_PLAYER_NAME.getMessage(locale) + "/" +
Message.COMMAND_ARGUMENT_ISLAND_NAME.getMessage(locale) + ">";
}

@Override
public String getDescription(java.util.Locale locale) {
return Message.COMMAND_DESCRIPTION_ADMIN_DATA.getMessage(locale);
}

@Override
public int getMinArgs() {
return 5;
}

@Override
public int getMaxArgs() {
return Integer.MAX_VALUE;
}

@Override
public boolean canBeExecutedByConsole() {
return true;
}

@Override
public void execute(SuperiorSkyblockPlugin plugin, CommandSender sender, String[] args) {
SubCommand subCommand = subCommands.get(args[2].toLowerCase(Locale.ENGLISH));

if (subCommand == null) {
Message.COMMAND_USAGE.send(sender, plugin.getCommands().getLabel() + " " + getUsage(PlayerLocales.getLocale(sender)));
return;
}

if (args.length < subCommand.getMinArgs() || args.length > subCommand.getMaxArgs()) {
Locale senderLocale = PlayerLocales.getLocale(sender);
Message.COMMAND_USAGE.send(sender, plugin.getCommands().getLabel() + " " + getUsage(senderLocale) + subCommand.getUsage(senderLocale));
return;
}

IPersistentDataHolder persistentDataHolder;

if (args[3].equalsIgnoreCase("island")) {
IslandArgument arguments = CommandArguments.getIsland(plugin, sender, args[4]);
persistentDataHolder = arguments.getIsland();
} else if (args[3].equalsIgnoreCase("player")) {
persistentDataHolder = CommandArguments.getPlayer(plugin, sender, args[4]);
} else {
Locale senderLocale = PlayerLocales.getLocale(sender);
Message.COMMAND_USAGE.send(sender, plugin.getCommands().getLabel() + " " + getUsage(senderLocale) + subCommand.getUsage(senderLocale));
return;
}

if (persistentDataHolder != null)
subCommand.execute(plugin, sender, persistentDataHolder, args);
}

@Override
public List<String> tabComplete(SuperiorSkyblockPlugin plugin, CommandSender sender, String[] args) {
switch (args.length) {
case 3:
return CommandTabCompletes.getCustomComplete(args[2], "get", "set", "remove");
case 4: {
SubCommand subCommand = subCommands.get(args[2].toLowerCase(Locale.ENGLISH));
return subCommand == null ? Collections.emptyList() :
CommandTabCompletes.getCustomComplete(args[3], "island", "player");
}
case 5: {
SubCommand subCommand = subCommands.get(args[2].toLowerCase(Locale.ENGLISH));
return subCommand == null ? Collections.emptyList() : args[3].equalsIgnoreCase("island") ?
CommandTabCompletes.getOnlinePlayersWithIslands(plugin, args[4], false, null) :
CommandTabCompletes.getOnlinePlayers(plugin, args[4], false);
}
default: {
return Collections.emptyList();
}
}
}

interface SubCommand {

String getUsage(Locale locale);

int getMinArgs();

int getMaxArgs();

void execute(SuperiorSkyblockPlugin plugin, CommandSender sender, IPersistentDataHolder persistentDataHolder,
String[] args);

}

private static class GetSubCommand implements SubCommand {

@Override
public String getUsage(Locale locale) {
return " [" + Message.COMMAND_ARGUMENT_PATH.getMessage(locale) + "]";
}

@Override
public int getMinArgs() {
return 5;
}

@Override
public int getMaxArgs() {
return 6;
}

@Override
public void execute(SuperiorSkyblockPlugin plugin, CommandSender sender, IPersistentDataHolder persistentDataHolder, String[] args) {
if (persistentDataHolder.isPersistentDataContainerEmpty()) {
Message.PERSISTENT_DATA_EMPTY.send(sender);
return;
}

Locale locale = PlayerLocales.getLocale(sender);

PersistentDataSerializer serializer = new PersistentDataSerializer(locale);

PersistentDataContainer dataContainer = persistentDataHolder.getPersistentDataContainer();

String serializedValue;

if (args.length == 6) {
if (!dataContainer.has(args[5])) {
Message.PERSISTENT_DATA_EMPTY.send(sender);
return;
}

serializedValue = serializer.serialize(dataContainer.get(args[5]));
} else {
if (dataContainer.isEmpty()) {
Message.PERSISTENT_DATA_EMPTY.send(sender);
return;
}

StringBuilder dataMessageBuilder = new StringBuilder();

dataContainer.forEach((key, value) -> {
String valueSerialized = serializer.serialize(value);

if (valueSerialized.isEmpty())
return;

if (dataMessageBuilder.length() != 0)
dataMessageBuilder.append(Message.PERSISTENT_DATA_SHOW_SPACER.getMessage(locale));

dataMessageBuilder.append(Message.PERSISTENT_DATA_SHOW_PATH.getMessage(locale, key)).append(valueSerialized);
});

if (dataMessageBuilder.length() < 2) {
Message.PERSISTENT_DATA_EMPTY.send(sender);
return;
}

serializedValue = dataMessageBuilder.toString();
}

Message.PERSISTENT_DATA_SHOW.send(sender, args[4], serializedValue);
}

}

private static class SetSubCommand implements SubCommand {

@Override
public String getUsage(Locale locale) {
return " <path> <value...>";
}

@Override
public int getMinArgs() {
return 7;
}

@Override
public int getMaxArgs() {
return Integer.MAX_VALUE;
}

@Override
public void execute(SuperiorSkyblockPlugin plugin, CommandSender sender, IPersistentDataHolder persistentDataHolder, String[] args) {
PersistentDataContainer dataContainer = persistentDataHolder.getPersistentDataContainer();

PersistentDataSerializer serializer = new PersistentDataSerializer(PlayerLocales.getLocale(sender));

String path = args[5];

// noinspection unchecked
Pair<Object, PersistentDataType<Object>> value = (Pair<Object, PersistentDataType<Object>>)
serializer.deserialize(String.join(" ", Arrays.copyOfRange(args, 6, args.length)));

assert value != null;

dataContainer.remove(path);
Object oldValue = dataContainer.put(path, value.getValue(), value.getKey());

if (!value.getKey().equals(oldValue))
persistentDataHolder.savePersistentDataContainer();

Message.PERSISTENT_DATA_MODIFY.send(sender, args[4], path,
serializer.serialize(value.getKey()));
}

}

private static class RemoveSubCommand implements SubCommand {

@Override
public String getUsage(Locale locale) {
return " <path>";
}

@Override
public int getMinArgs() {
return 6;
}

@Override
public int getMaxArgs() {
return 6;
}

@Override
public void execute(SuperiorSkyblockPlugin plugin, CommandSender sender, IPersistentDataHolder persistentDataHolder, String[] args) {
if (persistentDataHolder.isPersistentDataContainerEmpty()) {
Message.PERSISTENT_DATA_EMPTY.send(sender);
return;
}

PersistentDataContainer dataContainer = persistentDataHolder.getPersistentDataContainer();

if (!dataContainer.has(args[5])) {
Message.PERSISTENT_DATA_EMPTY.send(sender);
return;
}

Object oldValue = dataContainer.remove(args[5]);

if (oldValue != null)
persistentDataHolder.savePersistentDataContainer();

Message.PERSISTENT_DATA_REMOVED.send(sender, args[4], args[5]);
}
}

}
Expand Up @@ -581,6 +581,11 @@ public static void savePersistentDataContainer(Island island) {
));
}

public static void removePersistentDataContainer(Island island) {
runOperationIfRunning(island.getDatabaseBridge(), databaseBridge ->
databaseBridge.deleteObject("players_custom_data", createFilter("island", island)));
}

public static void insertIsland(Island island) {
runOperationIfRunning(island.getDatabaseBridge(), databaseBridge -> {
databaseBridge.insertObject("islands",
Expand Down Expand Up @@ -697,6 +702,38 @@ public static void executeFutureSaves(Island island) {
}
}

public static void executeFutureSaves(Island island, FutureSave futureSave) {
Map<FutureSave, Set<Object>> futureSaves = SAVE_METHODS_TO_BE_EXECUTED.get(island.getUniqueId());

if (futureSaves == null)
return;

Set<Object> values = futureSaves.remove(futureSave);

if (values == null)
return;

if (futureSaves.isEmpty())
SAVE_METHODS_TO_BE_EXECUTED.remove(island.getUniqueId());

switch (futureSave) {
case BLOCK_COUNTS:
saveBlockCounts(island);
break;
case ISLAND_CHESTS:
for (Object islandChest : values)
saveIslandChest(island, (IslandChest) islandChest);
break;
case PERSISTENT_DATA: {
if (island.isPersistentDataContainerEmpty())
removePersistentDataContainer(island);
else
savePersistentDataContainer(island);
break;
}
}
}

private static DatabaseFilter createFilter(String id, Island island, Pair<String, Object>... others) {
List<Pair<String, Object>> filters = new LinkedList<>();
filters.add(new Pair<>(id, island.getUniqueId().toString()));
Expand All @@ -710,7 +747,7 @@ private static void runOperationIfRunning(DatabaseBridge databaseBridge, Consume
databaseBridgeConsumer.accept(databaseBridge);
}

private enum FutureSave {
public enum FutureSave {

BLOCK_COUNTS,
ISLAND_CHESTS,
Expand Down

0 comments on commit a9d02d1

Please sign in to comment.