de.xaniox.leaderboardextensions.ExtensionLeaderboardWall.java Source code

Java tutorial

Introduction

Here is the source code for de.xaniox.leaderboardextensions.ExtensionLeaderboardWall.java

Source

/*
 * This file is part of addons.
 * Copyright (c) 2014-2016 Matthias Werning
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
 */
package de.xaniox.leaderboardextensions;

import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import com.google.common.util.concurrent.FutureCallback;
import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.bukkit.BukkitUtil;
import com.sk89q.worldedit.regions.CuboidRegion;
import com.sk89q.worldedit.regions.Region;
import de.xaniox.heavyspleef.commands.base.Command;
import de.xaniox.heavyspleef.commands.base.CommandContext;
import de.xaniox.heavyspleef.commands.base.CommandException;
import de.xaniox.heavyspleef.commands.base.PlayerOnly;
import de.xaniox.heavyspleef.core.HeavySpleef;
import de.xaniox.heavyspleef.core.PlayerPostActionHandler;
import de.xaniox.heavyspleef.core.config.ConfigType;
import de.xaniox.heavyspleef.core.config.DatabaseConfig;
import de.xaniox.heavyspleef.core.config.SignLayoutConfiguration;
import de.xaniox.heavyspleef.core.event.GameEndEvent;
import de.xaniox.heavyspleef.core.event.Subscribe;
import de.xaniox.heavyspleef.core.event.Subscribe.Priority;
import de.xaniox.heavyspleef.core.extension.Extension;
import de.xaniox.heavyspleef.core.extension.ExtensionLobbyWall.SignRow;
import de.xaniox.heavyspleef.core.extension.ExtensionLobbyWall.SignRow.SignLooper;
import de.xaniox.heavyspleef.core.extension.ExtensionManager;
import de.xaniox.heavyspleef.core.extension.GameExtension;
import de.xaniox.heavyspleef.core.i18n.Messages;
import de.xaniox.heavyspleef.core.player.SpleefPlayer;
import de.xaniox.heavyspleef.core.script.Variable;
import de.xaniox.heavyspleef.core.stats.Statistic;
import org.bukkit.Material;
import org.bukkit.block.Block;
import org.bukkit.block.Sign;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.bukkit.event.player.PlayerInteractEvent;
import org.dom4j.Element;

import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.logging.Level;

@Extension(name = "leaderboard-wall", hasCommands = true)
public class ExtensionLeaderboardWall extends GameExtension {

    @Command(name = "addleaderboardwall", minArgs = 1, usage = "/spleef addleaderboardwall <name>", descref = LEMessages.ADDLEADERBOARDWALL, i18nref = LeaderboardAddOn.I18N_REFERENCE, permission = LEPermissions.PERMISSION_ADD_LEADERBOARD_WALL)
    public static void onAddLeaderboardWallCommand(CommandContext context, HeavySpleef heavySpleef,
            LeaderboardAddOn addon) throws CommandException {
        CommandSender sender = context.getSender();
        if (sender instanceof Player) {
            sender = heavySpleef.getSpleefPlayer(sender);
        }

        DatabaseConfig config = heavySpleef.getConfiguration(ConfigType.DATABASE_CONFIG);
        if (!config.isStatisticsModuleEnabled()) {
            sender.sendMessage(addon.getI18n().getString(Messages.Command.NEED_STATISTICS_ENABLED));
            return;
        }

        String name = context.getString(0);
        ExtensionManager manager = addon.getGlobalExtensionManager();
        for (ExtensionLeaderboardWall wall : manager.getExtensionsByType(ExtensionLeaderboardWall.class, false)) {
            if (!wall.getName().equalsIgnoreCase(name)) {
                continue;
            }

            throw new CommandException(addon.getI18n().getString(LEMessages.WALL_ALREADY_EXISTS));
        }

        ExtensionLeaderboardWall wall = new ExtensionLeaderboardWall(name);
        wall.setLayoutConfig(addon.getWallConfig());
        manager.addExtension(wall);

        sender.sendMessage(
                addon.getI18n().getVarString(LEMessages.WALL_ADDED).setVariable("name", name).toString());
        addon.saveExtensions();
    }

    @Command(name = "removeleaderboardwall", minArgs = 1, usage = "/spleef removeleaderboardwall <name>", descref = LEMessages.REMOVELEADERBOARDWALL, i18nref = LeaderboardAddOn.I18N_REFERENCE, permission = LEPermissions.PERMISSION_REMOVE_LEADERBOARD_WALL)
    public static void onRemoveLeaderboardWallCommand(CommandContext context, HeavySpleef heavySpleef,
            LeaderboardAddOn addon) throws CommandException {
        CommandSender sender = context.getSender();
        if (sender instanceof Player) {
            sender = heavySpleef.getSpleefPlayer(sender);
        }

        String name = context.getString(0);
        ExtensionManager manager = addon.getGlobalExtensionManager();
        ExtensionLeaderboardWall removed = null;

        for (ExtensionLeaderboardWall wall : manager.getExtensionsByType(ExtensionLeaderboardWall.class, false)) {
            if (!wall.getName().equalsIgnoreCase(name)) {
                continue;
            }

            removed = wall;
            wall.clearWall();
            manager.removeExtension(wall);
            break;
        }

        sender.sendMessage(
                addon.getI18n().getVarString(removed != null ? LEMessages.WALL_REMOVED : LEMessages.WALL_NOT_FOUND)
                        .setVariable("name", removed != null ? removed.getName() : name).toString());
        addon.saveExtensions();
    }

    @Command(name = "addleaderboardrow", minArgs = 1, usage = "/spleef addleaderboardrow <name>", descref = LEMessages.ADDLEADERBOARDROW, i18nref = LeaderboardAddOn.I18N_REFERENCE, permission = LEPermissions.PERMISSION_ADD_LEADERBOARD_ROW)
    @PlayerOnly
    public static void onAddLeaderboardRowCommand(CommandContext context, HeavySpleef heavySpleef,
            final LeaderboardAddOn addon) throws CommandException {
        processRowCommand(context, heavySpleef, addon, true);
    }

    @Command(name = "removeleaderboardrow", minArgs = 1, usage = "/spleef removeleaderboardrow <name>", descref = LEMessages.REMOVELEADERBOARDROW, i18nref = LeaderboardAddOn.I18N_REFERENCE, permission = LEPermissions.PERMISSION_REMOVE_LEADERBOARD_ROW)
    @PlayerOnly
    public static void onRemoveLeaderboardRow(CommandContext context, HeavySpleef heavySpleef,
            final LeaderboardAddOn addon) throws CommandException {
        processRowCommand(context, heavySpleef, addon, false);
    }

    private static void processRowCommand(CommandContext context, HeavySpleef heavySpleef,
            final LeaderboardAddOn addon, final boolean add) throws CommandException {
        final SpleefPlayer player = heavySpleef.getSpleefPlayer(context.getSender());

        String name = context.getString(0);
        ExtensionManager manager = addon.getGlobalExtensionManager();
        ExtensionLeaderboardWall found = null;

        for (ExtensionLeaderboardWall wall : manager.getExtensionsByType(ExtensionLeaderboardWall.class, false)) {
            if (!wall.getName().equalsIgnoreCase(name)) {
                continue;
            }

            found = wall;
        }

        if (found == null) {
            throw new CommandException(
                    addon.getI18n().getVarString(LEMessages.WALL_NOT_FOUND).setVariable(name, "name").toString());
        }

        heavySpleef.getPostActionHandler().addPostAction(player, PlayerInteractEvent.class,
                new PlayerPostActionHandler.PostActionCallback<PlayerInteractEvent>() {

                    @Override
                    public void onPostAction(PlayerInteractEvent event, SpleefPlayer player, Object cookie) {
                        ExtensionLeaderboardWall wall = (ExtensionLeaderboardWall) cookie;
                        Block block = event.getClickedBlock();

                        event.setCancelled(true);
                        if (block == null || block.getType() != Material.WALL_SIGN) {
                            addon.getI18n().getString(Messages.Command.BLOCK_NOT_A_SIGN);
                            return;
                        }

                        Sign sign = (Sign) block.getState();
                        int removed = 0;

                        if (add) {
                            SignRow row = SignRow.generateRow(sign);
                            wall.addRow(row);
                        } else {
                            for (Iterator<SignRow> iterator = wall.getRows().iterator(); iterator.hasNext();) {
                                SignRow candidate = iterator.next();
                                org.bukkit.util.Vector start = candidate.getStart();
                                org.bukkit.util.Vector end = candidate.getEnd();

                                Vector startVec = BukkitUtil.toVector(start);
                                Vector endVec = BukkitUtil.toVector(end);
                                Vector blockVec = BukkitUtil.toVector(block);

                                Region region = new CuboidRegion(startVec, endVec);

                                if (!region.contains(blockVec)) {
                                    continue;
                                }

                                candidate.clearAll();
                                iterator.remove();
                                removed++;
                            }
                        }

                        wall.update();
                        player.sendMessage(
                                addon.getI18n().getVarString(add ? LEMessages.ROW_ADDED : LEMessages.ROWS_REMOVED)
                                        .setVariable("removed", String.valueOf(removed)).toString());
                        addon.saveExtensions();
                    }

                }, found);

        player.sendMessage(addon.getI18n().getString(LEMessages.CLICK_ON_SIGN));
    }

    private String name;
    private SignLayoutConfiguration layoutConfig;
    private List<SignRow> rows;

    protected ExtensionLeaderboardWall() {
        this.rows = Lists.newArrayList();
    }

    public ExtensionLeaderboardWall(String name) {
        this();
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public void setLayoutConfig(SignLayoutConfiguration layoutConfig) {
        this.layoutConfig = layoutConfig;
    }

    public List<SignRow> getRows() {
        return rows;
    }

    public void addRow(SignRow row) {
        if (rows.contains(row)) {
            throw new IllegalArgumentException("SignRow already added");
        }

        rows.add(row);
    }

    public void removeRow(SignRow row) {
        rows.remove(row);
    }

    public void removeRow(int index) {
        rows.remove(index);
    }

    @Subscribe(priority = Priority.MONITOR)
    public void onGameEnd(GameEndEvent event) {
        update();
    }

    public void update() {
        int lengthSum = 0;
        for (SignRow row : rows) {
            lengthSum += row.getLength();
        }

        heavySpleef.getDatabaseHandler().getTopStatistics(0, lengthSum,
                new FutureCallback<Map<String, Statistic>>() {

                    @Override
                    public void onSuccess(Map<String, Statistic> result) {
                        update(result);
                    }

                    @Override
                    public void onFailure(Throwable t) {
                        heavySpleef.getLogger().log(Level.WARNING,
                                "Cannot retrieve top statistics for leaderboard wall", t);
                    }
                });
    }

    public void update(Map<String, Statistic> statistics) {
        Iterator<Entry<String, Statistic>> iterator = statistics.entrySet().iterator();
        int index = 0;

        for (SignRow row : rows) {
            WallSignLooper looper = new WallSignLooper(iterator, index);
            row.loopSigns(looper);

            index = looper.getIndex();
        }
    }

    public void clearWall() {
        for (SignRow row : rows) {
            row.clearAll();
        }
    }

    @Override
    public void marshal(Element element) {
        element.addElement("name").setText(name);
        for (SignRow row : rows) {
            Element rowElement = element.addElement("row");
            row.marshal(rowElement);
        }
    }

    @SuppressWarnings("unchecked")
    @Override
    public void unmarshal(Element element) {
        name = element.elementText("name");

        List<Element> rowElements = element.elements("row");
        for (Element rowElement : rowElements) {
            SignRow row = new SignRow();
            row.unmarshal(rowElement);
            rows.add(row);
        }
    }

    private class WallSignLooper implements SignLooper {

        private Iterator<Entry<String, Statistic>> iterator;
        private int index;

        public WallSignLooper(Iterator<Entry<String, Statistic>> iterator, int index) {
            this.iterator = iterator;
            this.index = index;
        }

        public int getIndex() {
            return index;
        }

        @Override
        public LoopReturn loop(int rowIndex, Sign sign) {
            if (!iterator.hasNext()) {
                return LoopReturn.RETURN;
            }

            Entry<String, Statistic> entry = iterator.next();
            Set<Variable> variables = Sets.newHashSet();
            entry.getValue().supply(variables, null);
            variables.add(new Variable("player", entry.getKey()));
            variables.add(new Variable("rank", index + 1));
            layoutConfig.getLayout().inflate(sign, variables);
            sign.update();

            ++index;
            return LoopReturn.DEFAULT;
        }

    }

}