NoCheatPlus/NCPCore/src/main/java/fr/neatmonster/nocheatplus/compat/BridgeMaterial.java

421 lines
16 KiB
Java

/*
* 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 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<String, Material> legacy = new HashMap<String, Material>();
/** Actual lower case name to Material map for all existing materials. */
private static final Map<String, Material> all = new HashMap<String, Material>();
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<Material> getAll(String... names) {
final LinkedHashSet<Material> res = new LinkedHashSet<Material>();
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<Material> res) {
for (final Entry<String, Material> 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<Material> getBySuffix(final String suffix,
final AlmostBoolean isBlock, final String... excludePrefixes) {
final Set<Material> res = new LinkedHashSet<Material>();
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. <br>
*
* @param suffices
* @param isBlock
* @param excludePrefixes
* @return
*/
public static Set<Material> getBySuffix(final Collection<String> suffices,
final AlmostBoolean isBlock, final String... excludePrefixes) {
final Set<Material> res = new LinkedHashSet<Material>();
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<Material> getByPrefix(final String prefix, final AlmostBoolean isBlock) {
final Set<Material> res = new LinkedHashSet<Material>();
for (final Entry<String, Material> 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<Material> getByPrefixAndSuffix(final Collection<String> prefixes,
final Collection<String> suffices, final AlmostBoolean isBlock,
final String... excludeContains) {
final Set<Material> res = new LinkedHashSet<Material>();
final List<String> useExcludeContains = new LinkedList<String>();
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<String, Material> 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<String> getKeySet() {
// return all.keySet();
// }
}