/* * 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 . */ package fr.neatmonster.nocheatplus.compat; import java.util.Arrays; import java.util.Collection; import java.util.HashMap; import java.util.LinkedHashSet; import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.Set; import org.bukkit.Material; import fr.neatmonster.nocheatplus.utilities.StringUtil; import fr.neatmonster.nocheatplus.utilities.ds.prefixtree.SimpleCharPrefixTree; public class BridgeMaterial { // TODO: Should be non static, ideally. /** Legacy Material by lower case name without preceding 'legacy_' part. */ private static final Map legacy = new HashMap(); /** Actual lower case name to Material map for all existing materials. */ private static final Map all = new HashMap(); static { for (Material mat : Material.values()) { String name = mat.name().toLowerCase(); all.put(name, mat); if (name.startsWith("legacy_")) { legacy.put(name.substring(7), mat); } } } public static Material legacy(String name) { return legacy.get(name.toLowerCase()); } /** * Get current Material by case-insensitive name. * * @param name * @return */ public static Material get(String name) { return all.get(name.toLowerCase()); } /** * Like {@link BridgeMaterial#get(String)}, but return null for non-blocks. * * @param name * @return */ public static Material getBlock(String name) { Material mat = get(name); if (mat == null || !mat.isBlock()) { return null; } else { return mat; } } /** * Get current Material by case-insensitive name. * * @param name * @return * @throws NullPointerException If the material is not present. */ public static Material getNotNull(String name) { final Material mat = get(name); if (mat == null) { throw new NullPointerException("Material not present: " + name); } else { return mat; } } /** * Get current Material by case-insensitive names, return the first Material * instance that exists for a given name. * * @param name * @return */ public static Material getFirst(String... names) { for (String name : names) { final Material mat = get(name); if (mat != null) { return mat; } } return null; } /** * Get current Material by case-insensitive names, return the first Material * instance that exists for a given name. * * @param name * @return * @throws NullPointerException * If no material is present. */ public static Material getFirstNotNull(String... names) { final Material mat = getFirst(names); if (mat == null) { throw new NullPointerException("Material not present: " + StringUtil.join(names, ", ")); } else { return mat; } } public static Set getAll(String... names) { final LinkedHashSet res = new LinkedHashSet(); for (final String name : names) { final Material mat = get(name); if (mat != null) { res.add(mat); } } return res; } public static boolean has(String name) { return all.containsKey(name.toLowerCase()); } ///////////////////////////////////////////////////////// // Specific unique material instances for items (only). ///////////////////////////////////////////////////////// public static final Material DIAMOND_SHOVEL = getFirstNotNull("diamond_shovel", "diamond_spade"); public static final Material GOLDEN_AXE = getFirstNotNull("golden_axe", "gold_axe"); public static final Material GOLDEN_HOE = getFirstNotNull("golden_hoe", "gold_hoe"); public static final Material GOLDEN_PICKAXE = getFirstNotNull("golden_pickaxe", "gold_pickaxe"); public static final Material GOLDEN_SHOVEL = getFirstNotNull("golden_shovel", "gold_spade"); public static final Material GOLDEN_SWORD = getFirstNotNull("golden_sword", "gold_sword"); public static final Material IRON_SHOVEL = getFirstNotNull("iron_shovel", "iron_spade"); public static final Material STONE_SHOVEL = getFirstNotNull("stone_shovel", "stone_spade"); public static final Material WOODEN_AXE = getFirstNotNull("wooden_axe", "wood_axe"); public static final Material WOODEN_HOE = getFirstNotNull("wooden_hoe", "wood_hoe"); public static final Material WOODEN_PICKAXE = getFirstNotNull("wooden_pickaxe", "wood_pickaxe"); public static final Material WOODEN_SHOVEL = getFirstNotNull("wooden_shovel", "wood_spade"); public static final Material WOODEN_SWORD = getFirstNotNull("wooden_sword", "wood_sword"); /////////////////////////////////////////////////// // Specific unique material instances for blocks. /////////////////////////////////////////////////// public static final Material BEETROOTS = getFirst("beetroots", "beetroot_block"); public static final Material BRICKS = getFirst("bricks", "brick"); public static final Material BRICK_SLAB = getFirst("brick_slab"); public static final Material CAKE = getFirstNotNull("cake_block", "cake"); public static final Material CARROTS = getFirst("carrots", "carrot"); public static final Material CAVE_AIR = getFirst("cave_air"); public static final Material CHAIN_COMMAND_BLOCK = getFirst( "chain_command_block", "command_chain"); public static final Material COBBLESTONE_WALL = getFirstNotNull("cobblestone_wall", "cobble_wall"); public static final Material COBWEB = getFirstNotNull("cobweb", "web"); public static final Material COMMAND_BLOCK = getFirstNotNull("command_block", "command"); public static final Material CRAFTING_TABLE = getFirstNotNull("crafting_table", "workbench"); public static final Material DANDELION = getFirstNotNull("dandelion", "yellow_flower"); public static final Material ENCHANTING_TABLE = getFirstNotNull("enchanting_table", "enchantment_table"); public static final Material END_PORTAL = getFirstNotNull("end_portal", "ender_portal"); public static final Material END_PORTAL_FRAME = getFirstNotNull("end_portal_frame", "ender_portal_frame"); public static final Material END_STONE = getFirstNotNull("end_stone", "ender_stone"); public static final Material END_STONE_BRICKS = getFirst("end_stone_bricks", "end_bricks"); public static final Material FARMLAND = getFirstNotNull("farmland", "soil"); /** Could be null for very old Minecraft. */ public static final Material FIREWORK_ROCKET = getFirst("firework_rocket", "firework"); /** Passable (long) grass block. */ public static final Material GRASS = getFirstNotNull("long_grass", "grass"); /** Classic dirt-like grass block. */ public static final Material GRASS_BLOCK = getFirstNotNull("grass_block", "grass"); public static final Material HEAVY_WEIGHTED_PRESSURE_PLATE = getFirstNotNull( "heavy_weighted_pressure_plate", "iron_plate"); public static final Material IRON_BARS = getFirstNotNull("iron_bars", "iron_fence"); /** (Block.) */ public static final Material IRON_DOOR = getFirstNotNull("iron_door_block", "iron_door"); public static final Material LIGHT_WEIGHTED_PRESSURE_PLATE = getFirstNotNull( "light_weighted_pressure_plate", "gold_plate"); public static final Material LILY_PAD = getFirstNotNull("lily_pad", "water_lily"); public static final Material MAGMA_BLOCK = getFirst("magma_block", "magma"); /** (Block.) /*/ public static final Material MELON = getFirstNotNull("melon_block", "melon"); public static final Material MOVING_PISTON = getFirstNotNull("moving_piston", "piston_moving_piece"); public static final Material MYCELIUM = getFirstNotNull("mycelium", "mycel"); public static final Material NETHER_BRICKS = getFirstNotNull("nether_bricks", "nether_brick"); public static final Material NETHER_BRICK_FENCE = getFirstNotNull("nether_brick_fence", "nether_fence"); public static final Material NETHER_PORTAL = getFirstNotNull("nether_portal", "portal"); public static final Material NETHER_QUARTZ_ORE = getFirstNotNull("nether_quartz_ore", "quartz_ore"); public static final Material NETHER_WARTS = getFirstNotNull("nether_warts", "nether_wart"); /** For reference: ordinary log. */ public static final Material OAK_LOG = getFirstNotNull("oak_log", "log"); /** For reference: ordinary wood. */ public static final Material OAK_WOOD = getFirstNotNull("oak_wood", "wood"); /** For reference: the ordinary wooden trap door. */ public static final Material OAK_TRAPDOOR = getFirstNotNull("oak_trapdoor", "trap_door"); /** (Block.) */ public static final Material PISTON = getFirstNotNull("piston_base", "piston"); public static final Material PISTON_HEAD = getFirstNotNull("piston_head", "piston_extension"); public static final Material POTATOES = getFirst("potatoes", "potato"); public static final Material RED_NETHER_BRICKS = getFirst("red_nether_bricks", "red_nether_brick"); /** For reference to have the breaking/shape. */ public static final Material REPEATER = getFirstNotNull("repeater", "diode_block_off"); public static final Material REPEATING_COMMAND_BLOCK = getFirst( "repeating_command_block", "command_repeating"); /** Sign block. */ public static final Material SIGN = getFirstNotNull("sign_post", "sign"); /** Some skull for reference. */ public static final Material SKELETON_SKULL = getFirst("skeleton_skull", "skull"); public static final Material SPAWNER = getFirstNotNull("spawner", "mob_spawner"); /** (Block.) */ public static final Material STICKY_PISTON = getFirstNotNull("piston_sticky_base", "sticky_piston"); public static final Material STONE_BRICKS = getFirstNotNull("stone_bricks", "smooth_brick"); public static final Material STONE_BRICK_STAIRS = getFirstNotNull( "stone_brick_stairs", "smooth_stairs"); public static final Material STONE_PRESSURE_PLATE = getFirstNotNull( "stone_pressure_plate", "stone_plate"); public static final Material STONE_SLAB = getFirstNotNull("stone_slab", "step"); public static final Material SUGAR_CANE = getFirstNotNull("sugar_cane_block", "sugar_cane"); // Reversed // TODO: Which is the old long grass... public static final Material TALL_GRASS = getFirstNotNull("tall_grass", "long_grass"); public static final Material TERRACOTTA = getFirstNotNull("terracotta", "hard_clay"); public static final Material VOID_AIR = get("void_air"); // May be null on legacy spigot. public static final Material WHEAT_CROPS = getFirstNotNull("crops", "wheat"); // Reversed private static void getBySuffix(final String suffix, final AlmostBoolean isBlock, final SimpleCharPrefixTree excludePrefixTree, final Set res) { for (final Entry entry : all.entrySet()) { final String key = entry.getKey(); if (key.endsWith(suffix)) { if (excludePrefixTree.hasPrefix(key)) { continue; } final Material value = entry.getValue(); if (isBlock == AlmostBoolean.MAYBE || !(isBlock.decide() ^ value.isBlock())) { res.add(value); } } } } /** * * @param suffix * @param isBlock * @param excludePrefixes * @return */ public static Set getBySuffix(final String suffix, final AlmostBoolean isBlock, final String... excludePrefixes) { final Set res = new LinkedHashSet(); final SimpleCharPrefixTree prefixTree = new SimpleCharPrefixTree(); prefixTree.feedAll(Arrays.asList(excludePrefixes), false, true); getBySuffix(suffix.toLowerCase(), isBlock, prefixTree, res); return res; } /** * Collect materials for all suffices as * {@link #getBySuffix(String, AlmostBoolean, String...)} does for one.
* * @param suffices * @param isBlock * @param excludePrefixes * @return */ public static Set getBySuffix(final Collection suffices, final AlmostBoolean isBlock, final String... excludePrefixes) { final Set res = new LinkedHashSet(); final SimpleCharPrefixTree prefixTree = new SimpleCharPrefixTree(); prefixTree.feedAll(Arrays.asList(excludePrefixes), false, true); for (final String suffix : suffices) { getBySuffix(suffix.toLowerCase(), isBlock, prefixTree, res); } return res; } public static Set getByPrefix(final String prefix, final AlmostBoolean isBlock) { final Set res = new LinkedHashSet(); for (final Entry entry : all.entrySet()) { final String key = entry.getKey(); if (key.startsWith(prefix)) { final Material value = entry.getValue(); if (isBlock == AlmostBoolean.MAYBE || !(isBlock.decide() ^ value.isBlock())) { res.add(value); } } } return res; } /** * Return materials for which all prefixes and suffices match but none of * excludeContains is contained, respecting the isBlock filter. * * @param prefixes * If prefixes is null, all prefixes will match. * @param suffices * @param isBlock * @param excludeContains * @return */ public static Set getByPrefixAndSuffix(final Collection prefixes, final Collection suffices, final AlmostBoolean isBlock, final String... excludeContains) { final Set res = new LinkedHashSet(); final List useExcludeContains = new LinkedList(); for (final String exclude : excludeContains) { useExcludeContains.add(exclude.toLowerCase()); } final SimpleCharPrefixTree prefixTree; if (prefixes == null) { prefixTree = null; } else { prefixTree = new SimpleCharPrefixTree(); prefixTree.feedAll(prefixes, false, true); } final SimpleCharPrefixTree suffixTree = new SimpleCharPrefixTree(); // reversed inputs (!). for (final String suffix : suffices) { suffixTree.feed(StringUtil.reverse(suffix.toLowerCase())); } final boolean isBlockDecided = isBlock.decide(); for (final Entry entry : all.entrySet()) { final String key = entry.getKey(); if ((prefixTree == null || prefixTree.hasPrefix(key)) && suffixTree.hasPrefix(StringUtil.reverse(key))) { final Material value = entry.getValue(); if (isBlock == AlmostBoolean.MAYBE || !(isBlockDecided ^ value.isBlock())) { boolean match = true; for (final String exclude : useExcludeContains) { if (key.contains(exclude)) { match = false; break; } } if (match) { res.add(entry.getValue()); } } } } return res; } // public static Set getKeySet() { // return all.keySet(); // } }