Package com.sk89q.commandbook

Source Code of com.sk89q.commandbook.AFKComponent$AFKSession

package com.sk89q.commandbook;

import com.sk89q.commandbook.session.PersistentSession;
import com.sk89q.commandbook.session.SessionComponent;
import com.sk89q.commandbook.util.LocationUtil;
import com.sk89q.commandbook.util.entity.player.PlayerUtil;
import com.sk89q.minecraft.util.commands.Command;
import com.sk89q.minecraft.util.commands.CommandContext;
import com.sk89q.minecraft.util.commands.CommandException;
import com.sk89q.minecraft.util.commands.CommandPermissions;
import com.zachsthings.libcomponents.ComponentInformation;
import com.zachsthings.libcomponents.Depend;
import com.zachsthings.libcomponents.InjectComponent;
import com.zachsthings.libcomponents.bukkit.BukkitComponent;
import com.zachsthings.libcomponents.config.ConfigurationBase;
import com.zachsthings.libcomponents.config.Setting;
import org.bukkit.ChatColor;
import org.bukkit.Server;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.entity.EntityDamageByEntityEvent;
import org.bukkit.event.entity.EntityTargetEvent;
import org.bukkit.event.inventory.InventoryClickEvent;
import org.bukkit.event.inventory.InventoryCloseEvent;
import org.bukkit.event.inventory.InventoryOpenEvent;
import org.bukkit.event.player.*;

import java.util.Collection;
import java.util.concurrent.TimeUnit;
import java.util.logging.Logger;

@ComponentInformation(friendlyName = "AFK Checker", desc = "AFK Checking and management.")
@Depend(components = {GodComponent.class, SessionComponent.class})
public class AFKComponent extends BukkitComponent implements Runnable, Listener {

    private final CommandBook inst = CommandBook.inst();
    private final Logger log = CommandBook.logger();
    private final Server server = CommandBook.server();

    @InjectComponent private GodComponent godComp;
    @InjectComponent private SessionComponent sessions;

    private LocalConfiguration config;

    @Override
    public void enable() {

        config = configure(new LocalConfiguration());

        CommandBook.registerEvents(this);
        if (config.useMovementEvent) {
            CommandBook.registerEvents(new MovementListener());
        }

        registerCommands(Commands.class);
        server.getScheduler().runTaskTimer(inst, this, 20, 20);
    }

    @Override
    public void reload() {

        super.reload();
        configure(config);
    }

    private static class LocalConfiguration extends ConfigurationBase {

        @Setting("use-movement-event")
        public boolean useMovementEvent = true;
        @Setting("movement-threshold")
        public double movementThreshold = .04;
        @Setting("sneak-movement-threshold")
        public double sneakMovementThreshold = .004;
        @Setting("afk-minutes")
        public int afkMinutes = 3;
        @Setting("afk-kick-minutes")
        public int afkKickMinutes = 60;
        @Setting("afk-general-sleep-ignored")
        public boolean afkGeneralSleepIgnored = true;
        @Setting("afk-command-sleep-ignored")
        public boolean afkCommandSleepIgnored = false;
        @Setting("afk-general-protection")
        public boolean afkGeneralProtection = true;
        @Setting("afk-command-protection")
        public boolean afkCommandProtection = false;
        @Setting("npc-compatibility-mode")
        public boolean npcCompatibilty = false;
    }

    /**
     * Determines if a player is marked as AFK.
     *
     * @param player the player to check
     * @return true if the player should be kicked
     */
    public boolean isAfk(Player player) {

        return sessions.getSession(AFKSession.class, player).isAFK();
    }

    /**
     * Determines if a time is sufficient to be AFK.
     *
     * @param time the last update time
     * @return true if the player should be kicked
     */
    public boolean isAfk(long time) {

        return time != 0 && System.currentTimeMillis() - time >= TimeUnit.MINUTES.toMillis(config.afkMinutes);
    }

    /**
     * Determines if a player should be kicked for being AFK.
     *
     * @param player the player to check
     * @return true if the player should be kicked
     */
    public boolean shouldKick(Player player) {

        return shouldKick(sessions.getSession(AFKSession.class, player).getLastUpdate());
    }

    /**
     * Determines if a time is sufficient to be kicked for being AFK.
     *
     * @param time the last update time
     * @return true if the player should be kicked
     */
    public boolean shouldKick(long time) {

        if (config.afkKickMinutes < 1) return false;

        double maxP = server.getMaxPlayers();
        double curP = server.getOnlinePlayers().size();

        double fraction = ((maxP - curP) + maxP * .2) / maxP;
        int duration = (int) Math.max(config.afkMinutes + 2, Math.min(config.afkKickMinutes, config.afkKickMinutes * fraction));
        return time != 0 && System.currentTimeMillis() - time >= TimeUnit.MINUTES.toMillis(duration);
    }

    /**
     * Determines if a player can be set to ignored for the sleep check.
     *
     * @param player the player to check
     * @return true if the player can be set to ignored for the sleep check
     */
    public boolean canIgnoreSleep(Player player) {

        AFKSession session = sessions.getSession(AFKSession.class, player);
        return (session.isRequested() && canIgnoreSleep(true)) || (isAfk(session.getLastUpdate()) && canIgnoreSleep(false));
    }

    /**
     * Determines if a player can be set to ignored for the sleep check.
     *
     * @param requested whether or not the player requested to be afk
     * @return true if the player can be set to ignored for the sleep check
     */
    public boolean canIgnoreSleep(boolean requested) {

        return !requested && config.afkGeneralSleepIgnored || requested && config.afkCommandSleepIgnored;
    }

    /**
     * Determines if a player can be protected.
     *
     * @param player the player to check
     * @return true if the player can be protected
     */
    public boolean canProtect(Player player) {

        AFKSession session = sessions.getSession(AFKSession.class, player);
        return (session.isRequested() && canProtect(true)) || (isAfk(session.getLastUpdate()) && canProtect(false));
    }

    /**
     * Determines if a player can be protected.
     *
     * @param requested whether or not the player requested to be afk
     * @return true if the player can be protected
     */
    public boolean canProtect(boolean requested) {

        return !requested && config.afkGeneralProtection || requested && config.afkCommandProtection;
    }

    /**
     * Updates a player's last active time.
     *
     * @param player player to update
     */
    public void update(Player player) {

        AFKSession session = sessions.getSession(AFKSession.class, player);

        // Update the time and remove the idle message
        session.setLastUpdate(System.currentTimeMillis());
        session.setIdleStatus(null);

        // Restore god mode setting
        if (godComp != null && session.isProtected() && godComp.hasGodMode(player)) {
            godComp.disableGodMode(player);
            session.setProtected(false);
        }
    }

    @Override
    public void run() {

        Collection<? extends Player> onlinePlayers = config.npcCompatibilty ? server.getOnlinePlayers() : null;
        for (final AFKSession session : sessions.getSessions(AFKSession.class).values()) {

            if (session == null) continue;
            final Player target = session.getPlayer();
            if (target == null || !session.getPlayer().isValid()) continue;

            if (onlinePlayers != null && (target.hasMetadata("NPC") || !onlinePlayers.contains(target))) {
                continue;
            }

            boolean passedTime = isAfk(session.getLastUpdate());
            if (session.isRequested() || passedTime) {
                if (shouldKick(session.getLastUpdate())) {
                    // Restore sleep ignored setting
                    if (session.isSleepIgnored()) {
                        target.setSleepingIgnored(false);
                        session.setSleepIgnored(false);
                    }

                    server.getScheduler().runTaskLater(inst, new Runnable() {

                        @Override
                        public void run() {

                            target.kickPlayer("Inactivity - " + (System.currentTimeMillis() - session.getLastUpdate()) / 60000 + " Minutes");
                        }
                    }, 1);
                } else if (!session.isAFK()) {

                    // Grey out list name
                    String name = target.getName();
                    session.setLastTabName(target.getPlayerListName());
                    target.setPlayerListName(ChatColor.GRAY + name.substring(0, Math.min(14, name.length())));

                    // Mark the player as AFK
                    session.setAFK(true);
                    target.sendMessage(ChatColor.YELLOW + "You are now marked as AFK.");
                }

                // Check and set sleep ignored
                if (canIgnoreSleep(session.isRequested()) || (passedTime && canIgnoreSleep(false))) {
                    if (!target.isSleepingIgnored()) {
                        target.setSleepingIgnored(true);
                        session.setSleepIgnored(true);
                    }
                }

                // Check and set god mode
                if (godComp != null && (canProtect(session.isRequested()) || (passedTime && canProtect(false)))) {
                    if (!godComp.hasGodMode(target)) {
                        godComp.enableGodMode(target);
                        session.setProtected(true);
                    }
                }
            } else if (session.isAFK()) {

                // Fix list name
                String lastName = session.getLastTabName();
                target.setPlayerListName(lastName == null ? target.getName() : lastName);

                // Restore sleep ignored setting
                if (session.isSleepIgnored()) {
                    target.setSleepingIgnored(false);
                    session.setSleepIgnored(false);
                }

                // Mark the player as not AFK
                session.setAFK(false);
                target.sendMessage(ChatColor.YELLOW + "You are no longer marked as AFK.");
            }
        }
    }

    public class Commands {
        @Command(aliases = {"afk", "away"},
                usage = "", desc = "Set yourself as away",
                flags = "", min = 0, max = -1)
        @CommandPermissions({"commandbook.away"})
        public void afk(CommandContext args, CommandSender sender) throws CommandException {

            Player player = PlayerUtil.checkPlayer(sender);

            String status = "";
            if (args.argsLength() > 0) {
                status = args.getJoinedStrings(0);

                // Make sure someone isn't playing around with this
                if (status.equals("null")) {
                    status = "";
                }
            }
            sessions.getSession(AFKSession.class, player).setIdleStatus(status);

            player.sendMessage(ChatColor.YELLOW
                    + (status.isEmpty() ? "Set as away" : "Set away status to \"" + status + "\"")
                    + ".");
        }
    }

    @EventHandler
    public void onEntityTargetPlayer(EntityTargetEvent event) {

        if (event.getTarget() instanceof Player) {

            if (canProtect((Player) event.getTarget())) {
                event.setCancelled(true);
            }
        }
    }

    @EventHandler
    public void onPlayerJoin(PlayerJoinEvent event) {

        update(event.getPlayer());
    }

    @EventHandler
    public void onPlayerChat(AsyncPlayerChatEvent event) {

        update(event.getPlayer());
    }

    @EventHandler
    public void onCommand(PlayerCommandPreprocessEvent event) {

        update(event.getPlayer());
    }

    @EventHandler
    public void onPlayerInteract(PlayerInteractEvent event) {

        update(event.getPlayer());
    }

    @EventHandler
    public void onPlayerFish(PlayerFishEvent event) {

        update(event.getPlayer());
    }

    @EventHandler
    public void onInventoryOpen(InventoryOpenEvent event) {

        if (event.getPlayer() instanceof Player) update((Player) event.getPlayer());
    }

    @EventHandler
    public void onInventoryClick(InventoryClickEvent event) {

        if (event.getWhoClicked() instanceof Player) update((Player) event.getWhoClicked());
    }

    @EventHandler
    public void onInventoryClose(InventoryCloseEvent event) {

        if (event.getPlayer() instanceof Player) update((Player) event.getPlayer());
    }

    @EventHandler
    public void onEntityDamageEntityEvent(EntityDamageByEntityEvent event) {

        if (event.getDamager() instanceof Player) update((Player) event.getDamager());
    }

    public class MovementListener implements Listener {
        @EventHandler
        public void onMoveChange(PlayerMoveEvent event) {

            Player player = event.getPlayer();
            double distanceSQ = LocationUtil.distanceSquared2D(event.getFrom(), event.getTo());

            if (distanceSQ > config.movementThreshold
                    || (player.isSneaking() && distanceSQ > config.sneakMovementThreshold)) {
                update(player);
            }
        }
    }

    // AFK Session
    public static class AFKSession extends PersistentSession {

        @Setting("idle-status") private String idleStatus = "null";
        private String lastTabName;
        private long lastUpdate = 0;
        private boolean protect = false;
        private boolean sleepIgnored = false;
        private boolean awayFromKeyboard = false;

        protected AFKSession() {
            super(THIRTY_MINUTES);
        }

        public Player getPlayer() {
            CommandSender sender = super.getOwner();
            return sender instanceof Player ? (Player) sender : null;
        }

        public String getIdleStatus() {
            return idleStatus.equals("null") ? "" : idleStatus;
        }

        public void setIdleStatus(String status) {
            this.idleStatus = status == null ? "null" : status;
        }

        public String getLastTabName() {
            return lastTabName;
        }

        public void setLastTabName(String lastTabName) {
            this.lastTabName = lastTabName;
        }

        public boolean isRequested() {
            return !idleStatus.equals("null");
        }

        public long getLastUpdate() {
            return lastUpdate;
        }

        public void setLastUpdate(long lastUpdate) {
            this.lastUpdate = lastUpdate;
        }

        public boolean isProtected() {
            return protect;
        }

        public void setProtected(boolean protect) {
            this.protect = protect;
        }

        public boolean isSleepIgnored() {
            return sleepIgnored;
        }

        public void setSleepIgnored(boolean sleepIgnored) {
            this.sleepIgnored = sleepIgnored;
        }

        public boolean isAFK() {
            return awayFromKeyboard;
        }

        public void setAFK(boolean awayFromKeyboard) {
            this.awayFromKeyboard = awayFromKeyboard;
        }
    }
}
TOP

Related Classes of com.sk89q.commandbook.AFKComponent$AFKSession

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.