Java tutorial
/* * 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/>. */ /* * This file is part of HeavySpleef. * Copyright (c) 2014-2015 matzefratze123 * * 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.Sets; import com.google.common.util.concurrent.FutureCallback; import de.xaniox.heavyspleef.commands.base.*; import de.xaniox.heavyspleef.core.HeavySpleef; 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.BlockFace2D; import de.xaniox.heavyspleef.core.extension.ExtensionManager; import de.xaniox.heavyspleef.core.extension.GameExtension; import de.xaniox.heavyspleef.core.game.Game; import de.xaniox.heavyspleef.core.i18n.Messages; import de.xaniox.heavyspleef.core.layout.SignLayout; import de.xaniox.heavyspleef.core.player.SpleefPlayer; import de.xaniox.heavyspleef.core.script.Variable; import de.xaniox.heavyspleef.core.stats.Statistic; import de.xaniox.heavyspleef.core.stats.StatisticRecorder; import org.bukkit.*; import org.bukkit.block.Block; import org.bukkit.block.BlockFace; import org.bukkit.block.Sign; import org.bukkit.block.Skull; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; 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 = "winner-podium", hasCommands = true) public class ExtensionLeaderboardPodium extends GameExtension { @Command(name = "addpodium", descref = LEMessages.ADDPODIUM, i18nref = LeaderboardAddOn.I18N_REFERENCE, minArgs = 1, permission = LEPermissions.PERMISSION_ADD_PODIUM, usage = "/spleef addpodium <name> [small|large]") @PlayerOnly public static void onAddPodiumCommand(CommandContext context, HeavySpleef heavySpleef, LeaderboardAddOn addon) throws CommandException { SpleefPlayer player = heavySpleef.getSpleefPlayer(context.getSender()); DatabaseConfig config = heavySpleef.getConfiguration(ConfigType.DATABASE_CONFIG); if (!config.isStatisticsModuleEnabled()) { player.sendMessage(addon.getI18n().getString(Messages.Command.NEED_STATISTICS_ENABLED)); return; } Location playerLocation = player.getBukkitPlayer().getLocation(); BlockFace2D direction = BlockFace2D.byYaw(playerLocation.getYaw()); PodiumSize size = PodiumSize.SMALL; String name = context.getString(0); String sizeString = context.getStringSafely(1); if (sizeString != null) { size = PodiumSize.byName(sizeString); if (size == null) { size = PodiumSize.SMALL; } } ExtensionManager manager = addon.getGlobalExtensionManager(); for (ExtensionLeaderboardPodium otherPodium : manager.getExtensionsByType(ExtensionLeaderboardPodium.class, false)) { if (!otherPodium.getName().equalsIgnoreCase(name)) { continue; } throw new CommandException(addon.getI18n().getVarString(LEMessages.PODIUM_ALREADY_EXISTS) .setVariable("name", name).toString()); } ExtensionLeaderboardPodium podium = new ExtensionLeaderboardPodium(name, playerLocation, direction, size); podium.setLayoutConfig(addon.getPodiumConfig()); manager.addExtension(podium); podium.update(true); player.sendMessage( addon.getI18n().getVarString(LEMessages.PODIUM_ADDED).setVariable("name", name).toString()); addon.saveExtensions(); } @Command(name = "removepodium", descref = LEMessages.REMOVEPODIUM, i18nref = LeaderboardAddOn.I18N_REFERENCE, minArgs = 1, permission = LEPermissions.PERMISSION_REMOVE_PODIUM, usage = "/spleef removepodium <name>") public static void onRemovePodiumCommand(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(); ExtensionLeaderboardPodium removed = null; for (ExtensionLeaderboardPodium podium : manager.getExtensionsByType(ExtensionLeaderboardPodium.class, false)) { if (!podium.getName().equalsIgnoreCase(name)) { continue; } //A ConcurrentModificationException is prevented because ExtensionManager#getExtensionsByType(Class<Extension>) //returns a copied set and not the actual set of registered extensions manager.removeExtension(podium); podium.update(null, false, true); removed = podium; break; } sender.sendMessage(addon.getI18n() .getVarString(removed != null ? LEMessages.PODIUM_REMOVED : LEMessages.PODIUM_NOT_FOUND) .setVariable("name", removed != null ? removed.getName() : name).toString()); addon.saveExtensions(); } @TabComplete("removepodium") public static void onRemovePodiumTabComplete(CommandContext context, List<String> list, HeavySpleef heavySpleef, LeaderboardAddOn addon) { if (context.argsLength() == 1) { ExtensionManager manager = addon.getGlobalExtensionManager(); for (ExtensionLeaderboardPodium podium : manager.getExtensionsByType(ExtensionLeaderboardPodium.class, false)) { list.add(podium.getName()); } } } private static final byte SKULL_ON_FLOOR = 1; private String name; private Location baseLocation; private BlockFace2D direction; private PodiumSize size; private SignLayoutConfiguration layoutConfig; public ExtensionLeaderboardPodium(String name, Location baseLocation, BlockFace2D direction, PodiumSize size) { this.name = name; this.baseLocation = baseLocation; this.direction = direction; this.size = size; } protected ExtensionLeaderboardPodium() { } public String getName() { return name; } public void setLayoutConfig(SignLayoutConfiguration layoutConfig) { this.layoutConfig = layoutConfig; } @Subscribe(priority = Priority.MONITOR) public void onGameEnd(GameEndEvent event) { Game game = event.getGame(); StatisticRecorder recorder = game.getStatisticRecorder(); if (!recorder.isEnableRating()) { return; } update(false); } public void update(final boolean forceBlocks) { getHeavySpleef().getDatabaseHandler().getTopStatistics(0, size.getStatisticAmount(), new FutureCallback<Map<String, Statistic>>() { @Override public void onSuccess(Map<String, Statistic> result) { update(result, forceBlocks, false); } @Override public void onFailure(Throwable t) { getHeavySpleef().getLogger().log(Level.WARNING, "Cannot retrieve top statistics for podium", t); } }); } @SuppressWarnings("deprecation") public void update(Map<String, Statistic> statistics, boolean forceBlocks, boolean delete) { BlockFace2D rightDir = direction.right(); BlockFace2D leftDir = direction.left(); BlockFace rightFace = rightDir.getBlockFace3D(); BlockFace leftFace = leftDir.getBlockFace3D(); Block baseBlock = baseLocation.getBlock(); if (delete) { baseBlock.setType(Material.AIR); } SignLayout layout = layoutConfig.getLayout(); Iterator<Entry<String, Statistic>> iterator = statistics != null ? statistics.entrySet().iterator() : null; for (int i = 0; i < size.getStatisticAmount(); i++) { Entry<String, Statistic> entry = iterator != null && iterator.hasNext() ? iterator.next() : null; Block position = null; Material type = null; switch (i) { case 0: //Top position = baseBlock.getRelative(BlockFace.UP); type = Material.DIAMOND_BLOCK; break; case 1: //First left position = baseBlock.getRelative(leftFace); type = Material.GOLD_BLOCK; break; case 2: //First right position = baseBlock.getRelative(rightFace); type = Material.IRON_BLOCK; break; case 3: //Second left position = baseBlock.getRelative(leftFace, 2); type = Material.DOUBLE_STEP; break; case 4: //Second right position = baseBlock.getRelative(rightFace, 2); type = Material.DOUBLE_STEP; break; } if (position == null) { continue; } Block signBlock = position.getRelative(direction.getBlockFace3D()); Block skullBlock = position.getRelative(BlockFace.UP); if (delete) { signBlock.setType(Material.AIR); skullBlock.setType(Material.AIR); position.setType(Material.AIR); continue; } if (baseBlock.getType() == Material.AIR || forceBlocks) { baseBlock.setType(Material.DOUBLE_STEP); } if (position.getType() == Material.AIR || forceBlocks) { position.setType(type); } if (entry == null) { continue; } /* For legacy reasons and compatibility */ signBlock.setTypeId(Material.WALL_SIGN.getId(), false); skullBlock.setTypeId(Material.SKULL.getId(), false); Skull skull = (Skull) skullBlock.getState(); skull.setRotation(direction.getBlockFace3D()); skull.setSkullType(SkullType.PLAYER); skull.setOwner(entry.getKey()); skull.setRawData(SKULL_ON_FLOOR); skull.update(true, false); Sign sign = (Sign) signBlock.getState(); Set<Variable> variables = Sets.newHashSet(); entry.getValue().supply(variables, null); variables.add(new Variable("player", entry.getKey())); variables.add(new Variable("rank", i + 1)); layout.inflate(sign, variables); org.bukkit.material.Sign data = new org.bukkit.material.Sign(Material.WALL_SIGN); data.setFacingDirection(direction.getBlockFace3D()); sign.setData(data); sign.update(); } } @Override public void marshal(Element element) { element.addElement("name").addText(name); Element locElement = element.addElement("base-location"); locElement.addElement("world").setText(String.valueOf(baseLocation.getWorld().getName())); locElement.addElement("x").setText(String.valueOf(baseLocation.getBlockX())); locElement.addElement("y").setText(String.valueOf(baseLocation.getBlockY())); locElement.addElement("z").setText(String.valueOf(baseLocation.getBlockZ())); element.addElement("direction").addText(direction.name()); element.addElement("size").addText(size.name()); } @Override public void unmarshal(Element element) { name = element.elementText("name"); Element locElement = element.element("base-location"); World world = Bukkit.getWorld(locElement.elementText("world")); int x = Integer.parseInt(locElement.elementText("x")); int y = Integer.parseInt(locElement.elementText("y")); int z = Integer.parseInt(locElement.elementText("z")); baseLocation = new Location(world, x, y, z); direction = BlockFace2D.valueOf(element.elementText("direction")); size = PodiumSize.valueOf(element.elementText("size")); } public enum PodiumSize { SMALL(3), LARGE(5); private int statisticAmount; private PodiumSize(int statisticAmount) { this.statisticAmount = statisticAmount; } public int getStatisticAmount() { return statisticAmount; } public static PodiumSize byName(String name) { for (PodiumSize size : values()) { if (!size.name().equalsIgnoreCase(name)) { continue; } return size; } return null; } } }