001package com.jeff_media.armorequipevent;
002
003import org.bukkit.Bukkit;
004import org.bukkit.entity.Player;
005import org.bukkit.event.Cancellable;
006import org.bukkit.event.HandlerList;
007import org.bukkit.event.player.PlayerEvent;
008import org.bukkit.inventory.ItemStack;
009import org.bukkit.plugin.java.JavaPlugin;
010
011import javax.annotation.Nullable;
012import java.io.BufferedReader;
013import java.io.IOException;
014import java.io.InputStream;
015import java.io.InputStreamReader;
016import java.util.ArrayList;
017import java.util.List;
018import java.util.stream.Collectors;
019
020/**
021 * Called when a player equips or unequips a piece of armor.
022 *
023 * @author Arnah
024 * @since Jul 30, 2015
025 */
026public final class ArmorEquipEvent extends PlayerEvent implements Cancellable {
027        
028        private static final HandlerList handlers = new HandlerList();
029        private boolean cancel = false;
030        private final EquipMethod equipType;
031        private final ArmorType type;
032        private ItemStack oldArmorPiece, newArmorPiece;
033
034        /**
035         * Registers the listeners for this event. If you forget to call this method, then the event will never get caled.
036         * @param plugin Plugin to call this event from
037         */
038        public static void registerListener(JavaPlugin plugin) {
039                Bukkit.getServer().getPluginManager().registerEvents(new ArmorListener(getBlockedMaterialNames(plugin)), plugin);
040                try{
041                        //Better way to check for this? Only in 1.13.1+?
042                        Class.forName("org.bukkit.event.block.BlockDispenseArmorEvent");
043                        Bukkit.getServer().getPluginManager().registerEvents(new DispenserArmorListener(), plugin);
044                } catch(Exception ignored) {
045
046                }
047        }
048
049        private static List<String> getBlockedMaterialNames(JavaPlugin plugin) {
050                try (InputStream inputStream = plugin.getResource("armorequipevent-blocked.txt")) {
051                        assert inputStream != null;
052                        try (BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream))) {
053                                return reader.lines().collect(Collectors.toList());
054                        } catch (Exception ignored1) {
055
056                        }
057                } catch (IOException ignored2) {
058                        //e.printStackTrace();
059                }
060                return new ArrayList<>();
061        }
062
063        /**
064         * Creates a new ArmorEquipEvent
065         * @param player The player who put on / removed the armor.
066         * @param type The ArmorType of the armor added
067         * @param oldArmorPiece The ItemStack of the armor removed.
068         * @param newArmorPiece The ItemStack of the armor added.
069         */
070        public ArmorEquipEvent(final Player player, final EquipMethod equipType, final ArmorType type, final ItemStack oldArmorPiece, final ItemStack newArmorPiece){
071                super(player);
072                this.equipType = equipType;
073                this.type = type;
074                this.oldArmorPiece = oldArmorPiece;
075                this.newArmorPiece = newArmorPiece;
076        }
077        
078        /**
079         * Gets a list of handlers handling this event.
080         *
081         * @return A list of handlers handling this event.
082         */
083        public static HandlerList getHandlerList(){
084                return handlers;
085        }
086        
087        /**
088         * Gets a list of handlers handling this event.
089         *
090         * @return A list of handlers handling this event.
091         */
092        @Override
093        public final HandlerList getHandlers(){
094                return handlers;
095        }
096        
097        /**
098         * Sets if this event should be cancelled.
099         *
100         * @param cancel If this event should be cancelled. When the event is cancelled, the armor is not changed.
101         */
102        public final void setCancelled(final boolean cancel){
103                this.cancel = cancel;
104        }
105        
106        /**
107         * Gets if this event is cancelled.
108         *
109         * @return If this event is cancelled
110         */
111        public final boolean isCancelled(){
112                return cancel;
113        }
114
115        /**
116         * Returns the type of armor involved in this event
117         * @return ArmorType
118         */
119        public final ArmorType getType(){
120                return type;
121        }
122        
123        /**
124         * Returns the last equipped armor piece, could be a piece of armor, or null
125         */
126        public final ItemStack getOldArmorPiece(){
127                if(ArmorListener.isEmpty(oldArmorPiece)){
128                        return null;
129                }
130                return oldArmorPiece;
131        }
132        
133        public final void setOldArmorPiece(final ItemStack oldArmorPiece){
134                this.oldArmorPiece = oldArmorPiece;
135        }
136        
137        /**
138         * Returns the newly equipped armor or null if the armor was unequipped
139         * @return ItemStack of armor or null
140         */
141        @Nullable
142        public final ItemStack getNewArmorPiece(){
143                if(ArmorListener.isEmpty(newArmorPiece)){
144                        return null;
145                }
146                return newArmorPiece;
147        }
148
149        /**
150         * Sets the new armor piece
151         * @param newArmorPiece The new armor piece
152         */
153        public final void setNewArmorPiece(@Nullable final ItemStack newArmorPiece){
154                this.newArmorPiece = newArmorPiece;
155        }
156        
157        /**
158         * Gets the method used to either equip or unequip an armor piece.
159         */
160        public EquipMethod getMethod(){
161                return equipType;
162        }
163
164        /**
165         * Represents the way of equipping or uneqipping armor.
166         */
167        public enum EquipMethod{// These have got to be the worst documentations ever.
168                /**
169                 * When you shift click an armor piece to equip or unequip
170                 */
171                SHIFT_CLICK,
172                /**
173                 * When you drag and drop the item to equip or unequip
174                 */
175                DRAG,
176                /**
177                 * When you manually equip or unequip the item. Use to be DRAG
178                 */
179                PICK_DROP,
180                /**
181                 * When you right click an armor piece in the hotbar without the inventory open to equip.
182                 */
183                HOTBAR,
184                /**
185                 * When you press the hotbar slot number while hovering over the armor slot to equip or unequip
186                 */
187                HOTBAR_SWAP,
188                /**
189                 * When in range of a dispenser that shoots an armor piece to equip.<br>
190                 * Requires the spigot version to have {@link org.bukkit.event.block.BlockDispenseArmorEvent} implemented.
191                 */
192                DISPENSER,
193                /**
194                 * When an armor piece is removed due to it losing all durability.
195                 */
196                BROKE,
197                /**
198                 * When you die causing all armor to unequip
199                 */
200                DEATH,
201        }
202}