diff --git a/pandalib-paper/src/main/java/fr/pandacube/lib/paper/players/PaperOffPlayer.java b/pandalib-paper/src/main/java/fr/pandacube/lib/paper/players/PaperOffPlayer.java index 53b9324..4e02f0f 100644 --- a/pandalib-paper/src/main/java/fr/pandacube/lib/paper/players/PaperOffPlayer.java +++ b/pandalib-paper/src/main/java/fr/pandacube/lib/paper/players/PaperOffPlayer.java @@ -1,9 +1,13 @@ package fr.pandacube.lib.paper.players; +import com.google.common.io.Files; +import fr.pandacube.lib.paper.reflect.util.PrimaryWorlds; import fr.pandacube.lib.paper.reflect.wrapper.craftbukkit.CraftItemStack; import fr.pandacube.lib.paper.reflect.wrapper.craftbukkit.CraftServer; import fr.pandacube.lib.paper.reflect.wrapper.minecraft.nbt.CompoundTag; import fr.pandacube.lib.paper.reflect.wrapper.minecraft.nbt.ListTag; +import fr.pandacube.lib.paper.reflect.wrapper.minecraft.nbt.NbtIo; +import fr.pandacube.lib.paper.util.WorldUtil; import fr.pandacube.lib.players.standalone.AbstractOffPlayer; import fr.pandacube.lib.reflect.wrapper.ReflectWrapper; import org.bukkit.Bukkit; @@ -13,6 +17,8 @@ import org.bukkit.event.inventory.InventoryType; import org.bukkit.inventory.ItemStack; import org.bukkit.scoreboard.Team; +import java.io.File; +import java.io.IOException; import java.util.function.UnaryOperator; /** @@ -142,7 +148,15 @@ public interface PaperOffPlayer extends AbstractOffPlayer { * Player data */ + /** + * Gets the NBT data from the playerdata file. + * It will not work if the player is online, because the data on the file are not synchronized with real-time values. + * @return the NBT data from the playerdata file. + * @throws IllegalStateException if the player is online. + */ default CompoundTag getPlayerData() { + if (isOnline()) + throw new IllegalStateException("Cannot access data file of " + getName() + " because they’re online."); return ReflectWrapper.wrapTyped(Bukkit.getServer(), CraftServer.class) .getServer() .getPlayerList() @@ -150,6 +164,37 @@ public interface PaperOffPlayer extends AbstractOffPlayer { .getPlayerData(getUniqueId().toString()); } + /** + * Saves the provided NBT data to the playerdata file. + * It will not work if the player is online, because the provided data will be lost when the player disconnects. + * @param data the data to save. + * @throws IllegalStateException if the player is online. + * @throws IOException if an IO error occurs. + */ + default void savePlayerData(CompoundTag data) throws IOException { + if (isOnline()) + throw new IllegalStateException("Cannot write data file of " + getName() + " because they’re online."); + File file = getPlayerDataFile(false); + File old = getPlayerDataFile(true); + old.delete(); + Files.move(file, old); + NbtIo.writeCompressed(data, file); + } + + /** + * Gets the file where the playerdata is stored. + * @param old true to return the path of old data, false to return the actual file. + * @return the file where the playerdata is stored. + */ + default File getPlayerDataFile(boolean old) { + File playerDataDir = new File(WorldUtil.worldDir(PrimaryWorlds.PRIMARY_WORLDS.get(0)), "playerdata"); + return new File(playerDataDir, getUniqueId() + (old ? ".dat_old" : ".dat")); + } + + /** + * Gets the content of the player’s inventory. + * @return the content of the player’s inventory. + */ default ItemStack[] getInventoryContent() { ItemStack[] content = new ItemStack[InventoryType.PLAYER.getDefaultSize()]; CompoundTag playerData = getPlayerData(); @@ -179,6 +224,10 @@ public interface PaperOffPlayer extends AbstractOffPlayer { return content; } + /** + * Gets the content of the player’s enderchest. + * @return the content of the player’s enderchest. + */ default ItemStack[] getEnderchestContent() { ItemStack[] content = new ItemStack[InventoryType.ENDER_CHEST.getDefaultSize()]; CompoundTag playerData = getPlayerData();