net.caseif.flint.steel.util.helper.PlayerHelper.java Source code

Java tutorial

Introduction

Here is the source code for net.caseif.flint.steel.util.helper.PlayerHelper.java

Source

/*
 * The MIT License (MIT)
 *
 * Copyright (c) 2015-2016, Max Roncace <me@caseif.net>
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

package net.caseif.flint.steel.util.helper;

import net.caseif.flint.common.util.helper.CommonPlayerHelper;
import net.caseif.flint.steel.SteelCore;
import net.caseif.flint.steel.util.file.SteelDataFiles;
import net.caseif.flint.util.physical.Location3D;

import com.google.common.base.Optional;
import org.bukkit.Bukkit;
import org.bukkit.configuration.InvalidConfigurationException;
import org.bukkit.configuration.file.YamlConfiguration;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.PlayerInventory;

import java.io.File;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.Collection;

/**
 * Static utility class for player-related functionality.
 *
 * @author Max Roncac
 */
public class PlayerHelper {

    private static final String PLAYER_INVENTORY_PRIMARY_KEY = "primary";
    private static final String PLAYER_INVENTORY_ARMOR_KEY = "armor";

    private static Method getOnlinePlayers;
    public static boolean newOnlinePlayersMethod = false;

    static {
        try {
            getOnlinePlayers = Bukkit.class.getMethod("getOnlinePlayers");
            if (getOnlinePlayers.getReturnType() == Collection.class) {
                newOnlinePlayersMethod = true;
            }
        } catch (NoSuchMethodException ex) {
            SteelCore.logSevere("Failed to get getOnlinePlayers method!");
            ex.printStackTrace();
        }
    }

    /**
     * Pushes the inventory of the given player into persistent storage.
     *
     * @param player The {@link Player} to push the inventory of
     * @throws IOException If an exception occurs while saving into persistent
     *     storage
     */
    @SuppressWarnings("deprecation")
    public static void pushInventory(Player player) throws IOException {
        PlayerInventory inv = player.getInventory();
        // the file to store the inventory in
        File storage = new File(SteelDataFiles.PLAYER_INVENTORY_DIR.getFile(), player.getUniqueId() + ".yml");
        if (storage.exists()) { // verify file isn't already present on disk (meaning it wasn't popped the last time)
            SteelCore.logVerbose("Inventory push requested for player " + player.getName() + ", but "
                    + "inventory was already present in persistent storage. Popping stored inventory first.");
            try {
                popInventory(player);
            } catch (InvalidConfigurationException ex) {
                throw new IOException(ex); // this is probably a bad thing of me to do but it's for a fringe case anyway
            }
        }
        YamlConfiguration yaml = new YamlConfiguration();
        yaml.set(PLAYER_INVENTORY_PRIMARY_KEY, InventoryHelper.serializeInventory(inv));
        yaml.set(PLAYER_INVENTORY_ARMOR_KEY, InventoryHelper.serializeInventory(inv.getArmorContents()));
        yaml.save(storage); // save to disk
        inv.clear(); // clear the inventory to complete the push to disk
        inv.setArmorContents(new ItemStack[inv.getArmorContents().length]);
        player.updateInventory();
    }

    /**
     * Pops the inventory of the given player from persistent storage.
     *
     * @param player The {@link Player} to pop the inventory of
     * @throws IllegalArgumentException If the inventory of the given
     *     {@link Player} is not present in persistent storage
     * @throws IOException If an exception occurs while loading from persistent
     *     storage
     * @throws InvalidConfigurationException If the stored inventory is invalid
     */
    //TODO: generalize some of this code for use with rollback storage
    @SuppressWarnings("deprecation")
    public static void popInventory(Player player)
            throws IllegalArgumentException, IOException, InvalidConfigurationException {
        // the file to load the inventory from
        File storage = new File(SteelDataFiles.PLAYER_INVENTORY_DIR.getFile(), player.getUniqueId() + ".yml");
        if (!storage.exists()) { // verify file is present on disk
            throw new IllegalArgumentException("Inventory pop requested for player " + player.getName() + ", but "
                    + "inventory was not present in persistent storage!");
        }
        YamlConfiguration yaml = new YamlConfiguration();
        yaml.load(storage); // load from disk
        if (!yaml.contains(PLAYER_INVENTORY_PRIMARY_KEY)) {
            throw new InvalidConfigurationException(
                    "Stored inventory is missing required section \"" + PLAYER_INVENTORY_PRIMARY_KEY + "\"");
        }
        player.getInventory().clear();
        player.getInventory().setContents(
                InventoryHelper.deserializeInventory(yaml.getConfigurationSection(PLAYER_INVENTORY_PRIMARY_KEY)));
        if (yaml.contains(PLAYER_INVENTORY_ARMOR_KEY)) {
            player.getInventory().setArmorContents(
                    InventoryHelper.deserializeInventory(yaml.getConfigurationSection(PLAYER_INVENTORY_ARMOR_KEY)));
        }
        player.updateInventory();
        //noinspection ResultOfMethodCallIgnored
        storage.delete();
    }

    /**
     * Stores the given {@link Player}'s current location to persistent storage.
     *
     * @param player The {@link Player} to store the location of
     * @throws InvalidConfigurationException If an exception occurs while saving
     *     to disk
     * @throws IOException If an exception occurs while saving to disk
     */
    public static void storeLocation(Player player) throws InvalidConfigurationException, IOException {
        CommonPlayerHelper.storeLocation(player.getUniqueId(),
                LocationHelper.convertLocation(player.getLocation()));
    }

    /**
     * Pops the given {@link Player}'s stored location from persistent storage,
     * teleporting them to it.
     *
     * @param player The {@link Player} to load the location of and teleport
     * @throws IllegalArgumentException If the player's location is not present
     *     in the persistent store or if an error occurs during deserialization
     * @throws InvalidConfigurationException If an exception occurs while
     *     loading from disk
     * @throws IOException If an exception occurs while saving to disk
     */
    public static void popLocation(Player player)
            throws IllegalArgumentException, InvalidConfigurationException, IOException {
        Optional<Location3D> retLoc = CommonPlayerHelper.getReturnLocation(player.getUniqueId());
        if (!retLoc.isPresent()) {
            throw new IllegalArgumentException(
                    "Location of player " + player.getName() + " not present in persistent store");
        }
        player.teleport(LocationHelper.convertLocation(retLoc.get()));
    }

    /**
     * Version-independent getOnlinePlayers() method.
     *
     * @return a list of online players
     */
    @SuppressWarnings("unchecked")
    public static Collection<? extends Player> getOnlinePlayers() {
        try {
            if (newOnlinePlayersMethod) {
                return (Collection<? extends Player>) getOnlinePlayers.invoke(null);
            } else {
                return Arrays.asList((Player[]) getOnlinePlayers.invoke(null));
            }
        } catch (IllegalAccessException | InvocationTargetException ex) {
            throw new RuntimeException("Failed to invoke getOnlinePlayers method!", ex);
        }
    }

}