me.st28.flexseries.flexcore.player.PlayerManager.java Source code

Java tutorial

Introduction

Here is the source code for me.st28.flexseries.flexcore.player.PlayerManager.java

Source

/**
 * FlexCore - Licensed under the MIT License (MIT)
 *
 * Copyright (c) Stealth2800 <http://stealthyone.com/>
 * Copyright (c) contributors <https://github.com/FlexSeries>
 *
 * 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 me.st28.flexseries.flexcore.player;

import me.st28.flexseries.flexcore.FlexCore;
import me.st28.flexseries.flexcore.events.PlayerJoinLoadedEvent;
import me.st28.flexseries.flexcore.events.PlayerLeaveEvent;
import me.st28.flexseries.flexcore.message.MessageReference;
import me.st28.flexseries.flexcore.player.loading.PlayerLoadCycle;
import me.st28.flexseries.flexcore.player.loading.PlayerLoader;
import me.st28.flexseries.flexcore.plugin.module.FlexModule;
import me.st28.flexseries.flexcore.storage.flatfile.YamlFileManager;
import org.apache.commons.lang.StringEscapeUtils;
import org.apache.commons.lang.Validate;
import org.bukkit.Bukkit;
import org.bukkit.configuration.file.FileConfiguration;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.player.AsyncPlayerPreLoginEvent;
import org.bukkit.event.player.AsyncPlayerPreLoginEvent.Result;
import org.bukkit.event.player.PlayerJoinEvent;
import org.bukkit.event.player.PlayerKickEvent;
import org.bukkit.event.player.PlayerQuitEvent;

import java.io.File;
import java.util.*;
import java.util.Map.Entry;

public final class PlayerManager extends FlexModule<FlexCore> implements Listener, PlayerLoader {

    private String unloadedMessage;

    private final List<String> loginMessageOrder = new ArrayList<>();

    /* Configuration Options */
    private long loadTimeout;
    private boolean enableJoinMessageChange;
    private boolean enableQuitMessageChange;

    private final Set<UUID> handledPlayers = new HashSet<>();
    private final Map<UUID, PlayerLoadCycle> cachedCycles = new HashMap<>();

    private File playerDir;
    private final Map<UUID, PlayerData> playerData = new HashMap<>();

    public PlayerManager(FlexCore plugin) {
        super(plugin, "players", "Manages players", true);
    }

    @Override
    protected void handleLoad() {
        playerDir = new File(getDataFolder() + File.separator + "userdata");
        playerDir.mkdirs();
    }

    @Override
    protected void handleReload() {
        playerDir.mkdirs();

        FileConfiguration config = getConfig();

        loadTimeout = config.getLong("load timeout", 100L);
        enableJoinMessageChange = config.getBoolean("modify join message", true);
        enableQuitMessageChange = config.getBoolean("modify quit message", true);

        loginMessageOrder.clear();
        loginMessageOrder.addAll(config.getStringList("player join.message order"));

        unloadedMessage = StringEscapeUtils.unescapeJava(
                config.getString("player join.unloaded message", "Unable to load your data.\nPlease try again."));
    }

    @Override
    protected void handleSave(boolean async) {
        for (UUID uuid : playerData.keySet()) {
            savePlayer(uuid);
        }
    }

    private void savePlayer(UUID uuid) {
        PlayerData data = getPlayerData(uuid);
        if (data == null)
            return;

        YamlFileManager file = new YamlFileManager(playerDir + File.separator + uuid.toString() + ".yml");

        data.save(file.getConfig());

        file.save();
    }

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

    @Override
    public boolean loadPlayer(UUID uuid, String name, PlayerLoadCycle cycle) {
        if (!playerData.containsKey(uuid)) {
            PlayerData data = new PlayerData(uuid,
                    new YamlFileManager(playerDir + File.separator + uuid.toString() + ".yml").getConfig());
            playerData.put(uuid, data);
        }

        PlayerLoadCycle.completedCycle(cycle, this);
        return true;
    }

    /**
     * @return a {@link PlayerData} instance for a specified player.
     */
    public PlayerData getPlayerData(UUID uuid) {
        Validate.notNull(uuid, "UUID cannot be null.");
        return playerData.get(uuid);
    }

    private void handleOfficialLogin(final Player p, final PlayerLoadCycle cycle, final String joinMessage) {
        PlayerData playerData = getPlayerData(p.getUniqueId());
        if (playerData.firstJoin == null) {
            playerData.firstJoin = System.currentTimeMillis();
        }
        playerData.lastLogin = System.currentTimeMillis();

        String curIp = p.getAddress().toString();
        playerData.lastIp = curIp;
        if (!playerData.ips.contains(curIp)) {
            playerData.ips.add(curIp);
        }

        String curName = p.getName();
        playerData.lastName = curName;
        if (!playerData.names.contains(curName)) {
            playerData.names.add(curName);
        }

        PlayerJoinLoadedEvent newJoinEvent = new PlayerJoinLoadedEvent(p, cycle.getCustomData());
        if (enableJoinMessageChange) {
            newJoinEvent.setJoinMessage(MessageReference.createPlain(joinMessage));
        }

        Bukkit.getPluginManager().callEvent(newJoinEvent);

        if (enableJoinMessageChange) {
            for (Player op : Bukkit.getOnlinePlayers()) {
                MessageReference message = newJoinEvent.getJoinMessage(op.getUniqueId());

                if (message != null) {
                    message.sendTo(op);
                }
            }
        }

        Map<String, MessageReference> loginMessages = newJoinEvent.getLoginMessages();
        List<String> sent = new ArrayList<>();

        for (String identifier : loginMessageOrder) {
            MessageReference message = loginMessages.get(identifier);
            if (message != null) {
                message.sendTo(p);
                sent.add(identifier);
            }
        }

        if (sent.size() != loginMessages.size()) {
            for (Entry<String, MessageReference> entry : loginMessages.entrySet()) {
                if (!sent.contains(entry.getKey())) {
                    entry.getValue().sendTo(p);
                }
            }
        }
    }

    @EventHandler(priority = EventPriority.HIGHEST)
    public void onPlayerJoinHighest(PlayerJoinEvent e) {
        Player p = e.getPlayer();
        UUID uuid = p.getUniqueId();

        // Make sure the player's data was properly loaded.
        if (!handledPlayers.contains(uuid)) {
            p.kickPlayer(unloadedMessage);
            return;
        }

        handleOfficialLogin(p, cachedCycles.remove(uuid), e.getJoinMessage());

        if (enableJoinMessageChange) {
            e.setJoinMessage(null);
        }
    }

    @EventHandler(priority = EventPriority.HIGHEST)
    public void onPlayerQuitHighest(PlayerQuitEvent e) {
        handlePlayerLeave(e.getPlayer(), e.getQuitMessage());

        if (enableQuitMessageChange) {
            e.setQuitMessage(null);
        }
    }

    @EventHandler(ignoreCancelled = true, priority = EventPriority.MONITOR)
    public void onPlayerKick(PlayerKickEvent e) {
        handlePlayerLeave(e.getPlayer(), e.getLeaveMessage());
    }

    private void handlePlayerLeave(Player p, String message) {
        if (!handledPlayers.remove(p.getUniqueId())) {
            return;
        }

        getPlayerData(p.getUniqueId()).lastLogout = System.currentTimeMillis();

        PlayerLeaveEvent newLeaveEvent = new PlayerLeaveEvent(p);
        if (enableQuitMessageChange) {
            newLeaveEvent.setLeaveMessage(MessageReference.createPlain(message));
        }

        Bukkit.getPluginManager().callEvent(newLeaveEvent);

        if (enableQuitMessageChange) {
            for (Player op : Bukkit.getOnlinePlayers()) {
                MessageReference plMessage = newLeaveEvent.getLeaveMessage(op.getUniqueId());

                if (plMessage != null) {
                    plMessage.sendTo(op);
                }
            }
        }

        savePlayer(p.getUniqueId());
    }

    @EventHandler(priority = EventPriority.HIGHEST)
    public void onAsyncPlayerPreLogin(AsyncPlayerPreLoginEvent e) {
        if (e.getLoginResult() != Result.ALLOWED)
            return;

        final UUID uuid = e.getUniqueId();
        if (uuid == null)
            return;
        handledPlayers.add(uuid);

        // Begin loading
        PlayerLoadCycle cycle = new PlayerLoadCycle(uuid, e.getName(), loadTimeout);

        final Object loadLock = new Object();

        cycle.startLoading(loadLock);

        synchronized (loadLock) {
            while (cycle.getLoadResult() == null) {
                try {
                    loadLock.wait();
                } catch (InterruptedException ex) {
                    break;
                }
            }
        }

        if (!cycle.getLoadResult().isSuccess()) {
            e.disallow(Result.KICK_OTHER, cycle.getLoadResult().getFailMessage());
        } else {
            e.allow();

            cachedCycles.put(uuid, cycle);
        }
    }

}