NoCheatPlus/NCPCore/src/main/java/fr/neatmonster/nocheatplus/utilities/map/MaterialUtil.java

549 lines
21 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.utilities.map;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
import java.util.logging.Level;
import org.bukkit.Material;
import fr.neatmonster.nocheatplus.compat.AlmostBoolean;
import fr.neatmonster.nocheatplus.compat.BridgeMaterial;
import fr.neatmonster.nocheatplus.logging.StaticLog;
import fr.neatmonster.nocheatplus.utilities.InventoryUtil;
import fr.neatmonster.nocheatplus.utilities.StringUtil;
/**
* Auxiliary collections and functionality for Material.
*
* @author asofold
*
*/
public class MaterialUtil {
// TODO: Naming conventions for collections (_BLOCKS suffix?).
///////////////////////
// Internal
///////////////////////
private static final List<String> woodTypes = Arrays.asList(
"acacia", "birch", "dark_oak", "jungle", "oak", "spruce",
"wood" // Legacy
);
/**
* Get a new set containing the given set, as well as all non-null results
* from names.
*
* @param set
* @param names
* @return
*/
private static Set<Material> add(Set<Material> set, String... names) {
final LinkedHashSet<Material> res = new LinkedHashSet<Material>(set);
res.addAll(BridgeMaterial.getAll(names));
return res;
}
/**
* Get a new set containing the given set, as well as all non-null results
* from names.
*
* @param set
* @param names
* @return
*/
public static Set<Material> addBlocks(Set<Material> set, String... names) {
final LinkedHashSet<Material> res = new LinkedHashSet<Material>(set);
res.addAll(BridgeMaterial.getAllBlocks(names));
return res;
}
/**
* Get a new set containing the given set, as well as all non-null Material entries.
*
* @param set Set is not checked.
* @param materials
* @return
*/
public static Set<Material> addBlocks(final Set<Material> set, final Material... materials) {
final LinkedHashSet<Material> res = new LinkedHashSet<Material>(set);
for (final Material mat : materials) {
if (mat != null && mat.isBlock()) {
res.add(mat);
}
}
return res;
}
/**
* Get a new set containing all elements of the given sets.
*
* @param sets
* @return
*/
public static Set<Material> join(final Set<Material>...sets ) {
final Set<Material> res = new LinkedHashSet<Material>();
for (final Set<Material> set : sets) {
res.addAll(set);
}
return res;
}
/**
* Dump public static fields of type Set<?> to StaticLog, using
* StringUtil.join (not recursive).
*/
public static void dumpStaticSets(final Class<?> clazz, final Level level) {
final StringBuilder builder = new StringBuilder(6000);
for (Field field : clazz.getDeclaredFields()) {
if (Modifier.isStatic(field.getModifiers())
&& Modifier.isPublic(field.getModifiers())) {
try {
Object obj = field.get(clazz);
if (obj instanceof Set<?>) {
Set<?> set = (Set<?>) obj;
builder.append(clazz.getName());
builder.append('.');
builder.append(field.getName());
builder.append(": ");
StringUtil.join(set, ", ", builder);
builder.append('\n');
}
} catch (IllegalArgumentException e) {
} catch (IllegalAccessException e) {
}
}
}
StaticLog.log(level, builder.toString());
}
/////////////////////////////////////////////////
// Material collections with common properties
// (May not always have all aspects in common.)
/////////////////////////////////////////////////
public static final Set<Material> ALL_BUTTONS = Collections.unmodifiableSet(
BridgeMaterial.getBySuffix("_button", AlmostBoolean.YES, "legacy"));
public static final Set<Material> ALL_DOORS = Collections.unmodifiableSet(
BridgeMaterial.getByPrefixAndSuffix(
null, Arrays.asList("_door"), AlmostBoolean.YES,
"trap", "legacy")
);
public static final Set<Material> ALL_TRAP_DOORS = Collections.unmodifiableSet(
BridgeMaterial.getByPrefixAndSuffix(
null, Arrays.asList("trapdoor", "trap_door"), AlmostBoolean.YES,
"legacy")
);
public static final Set<Material> ALL_PRESSURE_PLATES = Collections.unmodifiableSet(
BridgeMaterial.getBySuffix("_pressure_plate", AlmostBoolean.YES, "legacy"));
public static final Set<Material> BANNERS = Collections.unmodifiableSet(addBlocks(
BridgeMaterial.getByPrefixAndSuffix(
null,
Arrays.asList("_banner"),
AlmostBoolean.YES,
"legacy", "_wall"
), "standing_banner"));
public static final Set<Material> BEDS = Collections.unmodifiableSet(addBlocks(
BridgeMaterial.getBySuffix("_bed", AlmostBoolean.YES,
"legacy"), "bed_block"));
public static final Set<Material> BOATS;
static {
HashSet<Material> temp = new HashSet<Material>();
if (BridgeMaterial.get("boat") != null) {
temp.add(BridgeMaterial.get("boat"));
}
temp.addAll(InventoryUtil.collectItemsByPrefix("BOAT_"));
temp.addAll(InventoryUtil.collectItemsBySuffix("_BOAT"));
BOATS = Collections.unmodifiableSet(temp);
}
public static final Set<Material> CARPETS = Collections.unmodifiableSet(addBlocks(
BridgeMaterial.getBySuffix("_carpet", AlmostBoolean.YES, "legacy"),
"carpet"));
public static final Set<Material> CONCRETE_BLOCKS = Collections.unmodifiableSet(addBlocks(
BridgeMaterial.getBySuffix("_concrete", AlmostBoolean.YES, "legacy"),
"concrete"));
public static final Set<Material> CONCRETE_POWDER_BLOCKS = Collections.unmodifiableSet(addBlocks(
BridgeMaterial.getBySuffix("_concrete_powder", AlmostBoolean.YES, "legacy"),
"concrete_powder"));
/** Dead or alive. */
public static final Set<Material> CORAL_BLOCKS = Collections.unmodifiableSet(
BridgeMaterial.getBySuffix("coral_block", AlmostBoolean.YES, "legacy")
);
/**
* Dead coral parts, that have been passable alive, but which are like stone
* when dead.
*/
public static final Set<Material> DEAD_CORAL_PARTS = Collections.unmodifiableSet(
BridgeMaterial.getByPrefixAndSuffix(
Arrays.asList("dead_"),
Arrays.asList("coral_fan", "coral_wall_fan", "coral"),
AlmostBoolean.YES,
"block", "legacy"
));
/** Flower pot and potted plants / things. */
public static final Set<Material> FLOWER_POTS = Collections.unmodifiableSet(addBlocks(
BridgeMaterial.getByPrefix(
"potted_", AlmostBoolean.YES), "flower_pot"));
/** Stained and other. */
public static final Set<Material> GLASS_BLOCKS = Collections.unmodifiableSet(addBlocks(
BridgeMaterial.getBySuffix("_glass", AlmostBoolean.YES, "legacy"),
"glass"));
public static final Set<Material> GLASS_PANES = Collections.unmodifiableSet(addBlocks(
BridgeMaterial.getBySuffix("_glass_pane", AlmostBoolean.YES, "legacy"),
"glass_pane", "thin_glass"));
public static final Set<Material> GLAZED_TERRACOTTA_BLOCKS = Collections.unmodifiableSet(
BridgeMaterial.getBySuffix("glazed_terracotta", AlmostBoolean.YES, "legacy")
);
/** Heads placed on the ground. Includes skulls. */
public static final Set<Material> HEADS_GROUND = Collections.unmodifiableSet(addBlocks(
BridgeMaterial.getByPrefixAndSuffix(
null,
Arrays.asList("_skull", "_head"),
AlmostBoolean.YES,
"legacy", "_wall_"
), "skull"));
/** Heads placed on the wall. Includes skulls. */
public static final Set<Material> HEADS_WALL = Collections.unmodifiableSet(
BridgeMaterial.getByPrefixAndSuffix(
null,
Arrays.asList("_wall_skull", "_wall_head"),
AlmostBoolean.YES,
"legacy"
));
/** Blocks that are infested with silverfish. */
public static final Set<Material> INFESTED_BLOCKS = Collections.unmodifiableSet(addBlocks(
BridgeMaterial.getByPrefix("infested_", AlmostBoolean.YES), "monster_eggs"));
/** All lava blocks. */
public static final Set<Material> LAVA = Collections.unmodifiableSet(
BridgeMaterial.getAllBlocks("lava", "stationary_lava"));
public static final Set<Material> LEAVES = Collections.unmodifiableSet(addBlocks(
BridgeMaterial.getByPrefixAndSuffix(
woodTypes,
Arrays.asList("_leaves"),
AlmostBoolean.YES
// , ...
), "leaves", "leaves_2"));
/** LOGS. */
public static final Set<Material> LOGS = Collections.unmodifiableSet(addBlocks(
BridgeMaterial.getByPrefixAndSuffix(
woodTypes,
Arrays.asList("_log"),
AlmostBoolean.YES,
"legacy"
), "log", "log_2"));
/** Mushroom blocks (huge ones). */
public static final Set<Material> MUSHROOM_BLOCKS = Collections.unmodifiableSet(addBlocks(
BridgeMaterial.getBySuffix(
"_mushroom_block",
AlmostBoolean.YES,
"legacy"
), "mushroom_stem" , "huge_mushroom_1", "huge_mushroom_2"));
public static final Set<Material> PLANKS = Collections.unmodifiableSet(addBlocks(
BridgeMaterial.getBySuffix("_planks", AlmostBoolean.YES, "legacy"),
"wood"));
/** All rail types. */
public static final Set<Material> RAILS = Collections.unmodifiableSet(
BridgeMaterial.getBySuffix(Arrays.asList("rail", "rails"), AlmostBoolean.YES, "legacy"));
public static final Set<Material> SHULKER_BOXES = Collections.unmodifiableSet(
BridgeMaterial.getBySuffix("shulker_box", AlmostBoolean.YES, "legacy"));
public static final Set<Material> SLABS = Collections.unmodifiableSet(addBlocks(
BridgeMaterial.getBySuffix(Arrays.asList("_slab", "_step"),
AlmostBoolean.YES, "legacy"), "step"));
public static final Set<Material> SPAWN_EGGS = Collections.unmodifiableSet(add(
BridgeMaterial.getBySuffix("_spawn_egg", AlmostBoolean.YES, "legacy"),
"monster_egg"
));
public static final Set<Material> STRIPPED_LOGS = Collections.unmodifiableSet(
BridgeMaterial.getByPrefixAndSuffix(
Arrays.asList("stripped_"),
Arrays.asList("_log"), AlmostBoolean.YES)
);
public static final Set<Material> STRIPPED_WOOD_BLOCKS = Collections.unmodifiableSet(
BridgeMaterial.getByPrefixAndSuffix(
Arrays.asList("stripped_"),
Arrays.asList("_wood"), AlmostBoolean.YES)
);
/** All ordinary terracotta (hard clay) blocks. */
public static final Set<Material> TERRACOTTA_BLOCKS = Collections.unmodifiableSet(addBlocks(
// TODO: exclude GLAZED or not?
BridgeMaterial.getByPrefixAndSuffix(
null, Arrays.asList("_terracotta"),
AlmostBoolean.YES,
"legacy", "glazed"),
"terracotta", "hard_clay", "stained_clay"
));
/**
* Collect fully solid blocks, that are not contained in other collections
* (of blocks that are fully solid too).
*/
public static final Set<Material> VARIOUS_FULLY_SOLID = Collections.unmodifiableSet(addBlocks(
BridgeMaterial.getBySuffix(
Arrays.asList(
"_bricks", "_ore", "prismarine",
"andesite", "diorite", "granite",
"sandstone",
"command_block"
), AlmostBoolean.YES, "legacy"),
"barrier", "structure_block",
"note_block", "tnt",
"piston", "sticky_piston", "piston_base", "piston_sticky_base",
"dispenser", "dropper", "furnace", "observer",
"pumpkin", "melon_block", "hay_block", "bone_block",
"nether_wart_block",
"snow_block", "ice", "magma_block",
"diamond_block", "gold_block", "iron_block", "coal_block",
"emerald_block", "lapis_block", "redstone_block",
"purpur_block", "smooth_stone", "smooth_quartz", "quartz_block",
"quartz_pillar", "bookshelf",
"sand", "stone", "gravel", "dirt", "grass_block", "grass",
"sea_lantern", "redstone_lamp", "glowstone", "sponge", "wet_sponge"
));
public static final Set<Material> WALL_BANNERS = Collections.unmodifiableSet(addBlocks(
BridgeMaterial.getByPrefixAndSuffix(
null,
Arrays.asList("_wall_banner"),
AlmostBoolean.YES,
"legacy"
), "wall_banner"));
/** All water blocks. */
public static final Set<Material> WATER = Collections.unmodifiableSet(
BridgeMaterial.getAllBlocks("water", "stationary_water"));
/** Wood types (1.13 rather). */
public static final Set<Material> WOOD_BLOCKS = Collections.unmodifiableSet(addBlocks(
BridgeMaterial.getByPrefixAndSuffix(
woodTypes,
Arrays.asList("_wood"),
AlmostBoolean.YES
// , ...
), "wood"));
public static final Set<Material> WOODEN_BUTTONS = Collections.unmodifiableSet(
BridgeMaterial.getByPrefixAndSuffix(
woodTypes,
Arrays.asList("_button"),
AlmostBoolean.YES
));
public static final Set<Material> WOODEN_DOORS = Collections.unmodifiableSet(
BridgeMaterial.getByPrefixAndSuffix(
woodTypes,
Arrays.asList("_door"),
AlmostBoolean.YES,
"trap"
));
public static final Set<Material> WOODEN_FENCES = Collections.unmodifiableSet(addBlocks(
BridgeMaterial.getByPrefixAndSuffix(
woodTypes,
Arrays.asList("_fence"),
AlmostBoolean.YES
// , ...
), "fence"));
public static final Set<Material> WOODEN_FENCE_GATES = Collections.unmodifiableSet(addBlocks(
BridgeMaterial.getByPrefixAndSuffix(
woodTypes,
Arrays.asList("_fence_gate"),
AlmostBoolean.YES
// , ...
), "fence_gate"));
/** Wooden pressure plates. */
public static final Set<Material> WOODEN_PRESSURE_PLATES = Collections.unmodifiableSet(
BridgeMaterial.getByPrefixAndSuffix(
woodTypes,
Arrays.asList("_plate"), // Strictly _pressure_plate for 1.13.
AlmostBoolean.YES
// , ...
));
/** Wooden slabs. */
public static final Set<Material> WOODEN_SLABS = Collections.unmodifiableSet(
BridgeMaterial.getByPrefixAndSuffix(
woodTypes,
Arrays.asList("_slab", "_step"),
AlmostBoolean.YES,
"double" // Legacy
));
/** Wooden stairs. */
public static final Set<Material> WOODEN_STAIRS = Collections.unmodifiableSet(
BridgeMaterial.getByPrefixAndSuffix(
woodTypes,
Arrays.asList("_stairs"),
AlmostBoolean.YES
// , ...
));
public static final Set<Material> WOODEN_TRAP_DOORS = Collections.unmodifiableSet(addBlocks(
BridgeMaterial.getByPrefixAndSuffix(
woodTypes,
Arrays.asList("_trap_door", "_trapdoor"),
AlmostBoolean.YES
// , ...
), "trap_door"));
public static final Set<Material> WOOL_BLOCKS = Collections.unmodifiableSet(addBlocks(
BridgeMaterial.getBySuffix(
"_wool",
AlmostBoolean.YES,
"legacy"
), "wool"));
///////////////////////////////
// Collections of collections
///////////////////////////////
/** Instantly breakable, fully passable. */
@SuppressWarnings("unchecked")
public static final Set<Material> INSTANT_PLANTS = Collections.unmodifiableSet(join(
BridgeMaterial.getBySuffix(Arrays.asList(
"bush", "sapling", "tulip", "orchid", "mushroom", "bluet"),
AlmostBoolean.YES, "legacy", "potted"),
BridgeMaterial.getByPrefixAndSuffix(
null,
Arrays.asList("coral_fan", "coral_wall_fan", "coral"),
AlmostBoolean.YES, "dead", "legacy"),
BridgeMaterial.getAllBlocks("attached_melon_stem", "attached_pumpkin_stem",
"allium", "dandelion", "dandelion_yellow",
"double_plant", "fern", "kelp", "kelp_plant", "large_fern",
"lilac", "melon_stem", "nether_wart", "nether_warts",
"oxeye_daisy", "peony", "poppy", "red_rose", "rose_red",
"seagrass", "sunflower", "tall_seagrass", "yellow_flower"
),
new HashSet<Material>(Arrays.asList(BridgeMaterial.TALL_GRASS,
BridgeMaterial.WHEAT_CROPS, BridgeMaterial.CARROTS,
BridgeMaterial.POTATOES, BridgeMaterial.GRASS,
Material.PUMPKIN_STEM, Material.MELON_STEM,
BridgeMaterial.SUGAR_CANE, BridgeMaterial.BEETROOTS))
));
/**
* Sets of fully solid blocks (in terms of: can walk on, can't pass through,
* full bounds - not necessarily 'solid' officially).
*/
@SuppressWarnings("unchecked")
public static final Set<Material> FULLY_SOLID_BLOCKS = Collections.unmodifiableSet(join(
CONCRETE_BLOCKS,
CONCRETE_POWDER_BLOCKS,
CORAL_BLOCKS,
GLASS_BLOCKS,
GLAZED_TERRACOTTA_BLOCKS,
INFESTED_BLOCKS,
LEAVES,
LOGS,
MUSHROOM_BLOCKS,
PLANKS,
STRIPPED_LOGS,
STRIPPED_WOOD_BLOCKS,
TERRACOTTA_BLOCKS,
VARIOUS_FULLY_SOLID,
WOOD_BLOCKS,
WOOL_BLOCKS
));
/**
* Collections of blocks that are fully passable.
*/
@SuppressWarnings("unchecked")
public static final Set<Material> FULLY_PASSABLE_BLOCKS = Collections.unmodifiableSet(join(
ALL_BUTTONS,
ALL_PRESSURE_PLATES,
BANNERS,
RAILS,
WALL_BANNERS,
INSTANT_PLANTS,
BridgeMaterial.getAllBlocks("structure_void", "end_gateway"),
new HashSet<Material>(Arrays.asList(
Material.LEVER,
BridgeMaterial.END_PORTAL,
BridgeMaterial.NETHER_PORTAL))
));
////////////////////
// Access methods.
////////////////////
/**
* Test if the material is a boat.
*
* @param mat
* @return
*/
public static boolean isBoat(final Material mat) {
return BOATS.contains(mat);
}
/**
* Test if the material is a spawn egg.
*
* @param mat
* @return
*/
public static boolean isSpawnEgg(final Material mat) {
return SPAWN_EGGS.contains(mat);
}
public static boolean isLog(final Material mat) {
return LOGS.contains(mat);
}
}