More smart block setup (first batch).

* Initialize fully solid (in terms of shape + passable) blocks
explicitly with full bounds and solid flags.
* Use MaterialUtil#addBlocks and BridgeMaterial#getAllBlocks where
appropriate.
* MCAccessBukkit(Base): don't touch fully solid nor fully passable ones.
This commit is contained in:
asofold 2018-08-20 15:11:37 +02:00
parent 0f3b4ae166
commit 07368361e2
9 changed files with 210 additions and 57 deletions

View File

@ -58,6 +58,19 @@ public class BlockCacheBukkit extends BlockCache {
@Override
public double[] fetchBounds(final int x, final int y, final int z){
// minX, minY, minZ, maxX, maxY, maxZ
/*
* TODO: Since whenever available: use bukkit methods to do the
* (somewhat) obvious shapes. Might introduce block models and for now
* trigger with flags (stairs, half_blocks), then get the precise shape
* via evaluating directional/whatnot. Reliably detect full blocks.
* Attempt to initialize more smart (don't override flags for anything
* known otherwise, ModelBlock with a
* directional/soandso-bukklit-interface based shape building with
* parameter(s).)
*/
// TODO: Want to maintain a list with manual entries or at least half / full blocks ?
// Always return full bounds, needs extra adaption to BlockProperties (!).
return new double[]{0D, 0D, 0D, 1D, 1D, 1D};

View File

@ -15,18 +15,11 @@
package fr.neatmonster.nocheatplus.compat.bukkit;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.bukkit.Material;
import fr.neatmonster.nocheatplus.compat.BridgeMaterial;
import fr.neatmonster.nocheatplus.compat.blocks.BlockPropertiesSetup;
import fr.neatmonster.nocheatplus.config.WorldConfigProvider;
import fr.neatmonster.nocheatplus.utilities.map.BlockProperties;
import fr.neatmonster.nocheatplus.utilities.map.MaterialUtil;
public class MCAccessBukkit extends MCAccessBukkitBase implements BlockPropertiesSetup{
@ -38,34 +31,10 @@ public class MCAccessBukkit extends MCAccessBukkitBase implements BlockPropertie
public void setupBlockProperties(final WorldConfigProvider<?> worldConfigProvider) {
// Note deprecation suppression: These ids should be unique for a server run, that should be ok for setting up generic properties.
// TODO: (?) Set some generic properties matching what BlockCache.getShape returns.
final Set<Material> fullBlocks = new HashSet<Material>();
for (final Material mat : new Material[]{
// TODO: Ice !? / Packed ice !?
Material.GLASS, Material.GLOWSTONE, Material.ICE,
BridgeMaterial.COMMAND_BLOCK, Material.BEACON,
BridgeMaterial.PISTON,
}) {
fullBlocks.add(mat);
}
@SuppressWarnings("unchecked")
final List<Set<Material>> fullBlockSets = Arrays.asList(
// TODO: GLASS_TYPES, ICE_TYPES,
MaterialUtil.LEAVES,
BridgeMaterial.getAll(
"repeating_command_block", "chain_command_block"
));
for (final Set<Material> set : fullBlockSets) {
for (final Material mat : set) {
fullBlocks.add(mat);
}
}
for (final Material mat : Material.values()) {
if (!mat.isBlock()) {
continue;
}
else if (fullBlocks.contains(mat)) {
continue;
}
else if (guessItchyBlock(mat)) {
// Uncertain bounding-box, allow passing through.
long flags = BlockProperties.F_IGN_PASSABLE;
@ -80,6 +49,7 @@ public class MCAccessBukkit extends MCAccessBukkitBase implements BlockPropertie
for (final Material mat : new Material[]{
Material.ENDER_PORTAL_FRAME,
}) {
// TODO: Add BlockFlags.FULL_BOUNDS?
final long flags = BlockProperties.F_IGN_PASSABLE | BlockProperties.F_GROUND_HEIGHT;
BlockProperties.setBlockFlags(mat, BlockProperties.getBlockFlags(mat) | flags);
}

View File

@ -34,6 +34,8 @@ import fr.neatmonster.nocheatplus.compat.MCAccess;
import fr.neatmonster.nocheatplus.utilities.PotionUtil;
import fr.neatmonster.nocheatplus.utilities.ReflectionUtil;
import fr.neatmonster.nocheatplus.utilities.map.BlockCache;
import fr.neatmonster.nocheatplus.utilities.map.BlockFlags;
import fr.neatmonster.nocheatplus.utilities.map.BlockProperties;
import fr.neatmonster.nocheatplus.utilities.map.MaterialUtil;
public class MCAccessBukkitBase implements MCAccess {
@ -46,6 +48,40 @@ public class MCAccessBukkitBase implements MCAccess {
}
protected boolean guessItchyBlock(final Material mat) {
// General considerations first.
if (BlockProperties.isAir(mat) || BlockProperties.isLiquid(mat)) {
return false;
}
// Fully solid/ground blocks.
final long flags = BlockProperties.getBlockFlags(mat);
/*
* Skip fully passable blocks (partially passable blocks may be itchy,
* though slabs will be easy to handle).
*/
if (BlockFlags.hasAnyFlag(flags,BlockProperties.F_IGN_PASSABLE)) {
// TODO: Blocks with min_height may actually be ok, if xz100 and some height are set.
if (BlockFlags.hasNoFlags(flags,
BlockProperties.F_GROUND_HEIGHT
| BlockProperties.F_GROUND
| BlockProperties.F_SOLID)) {
// Explicitly passable.
return false;
}
else {
// Potentially itchy.
return true;
}
}
long testFlags = (BlockProperties.F_SOLID | BlockProperties.F_XZ100
| BlockProperties.F_HEIGHT100);
if (BlockFlags.hasAllFlags(flags, testFlags)) {
// Fully solid block!
return false;
}
// TODO: Directional stairs / slabs (wall heads, ...)
// TODO: Ground heads/skulls.
// TODO: Use working route.
return guessItchyBlockPre1_13(mat);
}

View File

@ -143,6 +143,17 @@ public class BridgeMaterial {
return res;
}
public static Set<Material> getAllBlocks(String... names) {
final LinkedHashSet<Material> res = new LinkedHashSet<Material>();
for (final String name : names) {
final Material mat = get(name);
if (mat != null && mat.isBlock()) {
res.add(mat);
}
}
return res;
}
public static boolean has(String name) {
return all.containsKey(name.toLowerCase());
}

View File

@ -80,7 +80,7 @@ public class BlocksMC1_13 implements BlockPropertiesSetup {
BlockInit.setInstantAir("WALL_TORCH");
// Stone types.
for (Material mat : BridgeMaterial.getAll("andesite", "diorite", "granite",
for (Material mat : BridgeMaterial.getAllBlocks("andesite", "diorite", "granite",
"polished_andesite", "polished_diorite", "polished_granite",
"smooth_stone")) {
BlockInit.setAs(mat, Material.STONE);

View File

@ -25,6 +25,9 @@ import org.bukkit.Material;
*/
public class BlockFlags {
/** Explicitly set full bounds. */
public static final long FULL_BOUNDS = BlockProperties.F_XZ100 | BlockProperties.F_HEIGHT100;
/**
* Set flags of id same as already set with flags for the given material.
* (Uses BlockProperties.)
@ -97,4 +100,37 @@ public class BlockFlags {
BlockProperties.setBlockFlags(id, BlockProperties.getBlockFlags(id) & ~flags);
}
/**
* Test if any flags within testFlags are contained.
*
* @param flags
* @param testFlags
* @return
*/
public static boolean hasAnyFlag(long flags, long testFlags) {
return (flags & testFlags) != 0L;
}
/**
* Test if all flags within testFlags are contained.
*
* @param flags
* @param testFlags
* @return
*/
public static boolean hasAllFlags(long flags, long testFlags) {
return (flags & testFlags) == testFlags;
}
/**
* Test if no flags within testFlags are contained.
*
* @param flags
* @param testFlags
* @return
*/
public static boolean hasNoFlags(long flags, long testFlags) {
return (flags & testFlags) == 0L;
}
}

View File

@ -1550,6 +1550,19 @@ public class BlockProperties {
// TODO: Model shears directly somehow (per-block list).
}
// Fully solid blocks (shape / passable) - simplifies MCAccessBukkit setup, aim at 1.13+.
for (Material mat : MaterialUtil.FULLY_SOLID_BLOCKS) {
BlockFlags.addFlags(mat,
// Full bounds for sure.
BlockFlags.FULL_BOUNDS
/*
* Ensure solid is set (slight abuse/ambiguity
* with ground, and potential future use of
* Material#isSolid.
*/
| BlockProperties.F_SOLID);
}
}
/**

View File

@ -66,6 +66,28 @@ public class MaterialUtil {
return res;
}
/**
* 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> addBlocks(Set<Material> set, String... names) {
final LinkedHashSet<Material> res = new LinkedHashSet<Material>(set);
res.addAll(BridgeMaterial.getAllBlocks(names));
return res;
}
private 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).
@ -99,7 +121,7 @@ public class MaterialUtil {
// (May not always have all aspects in common.)
/////////////////////////////////////////////////
public static final Set<Material> BANNERS = Collections.unmodifiableSet(add(
public static final Set<Material> BANNERS = Collections.unmodifiableSet(addBlocks(
BridgeMaterial.getByPrefixAndSuffix(
null,
Arrays.asList("_banner"),
@ -107,7 +129,7 @@ public class MaterialUtil {
"legacy", "_wall"
), "standing_banner"));
public static final Set<Material> BEDS = Collections.unmodifiableSet(add(
public static final Set<Material> BEDS = Collections.unmodifiableSet(addBlocks(
BridgeMaterial.getBySuffix("_bed", AlmostBoolean.YES,
"legacy"), "bed_block"));
@ -126,15 +148,15 @@ public class MaterialUtil {
public static final Set<Material> BUSHES = Collections.unmodifiableSet(
BridgeMaterial.getBySuffix("bush", AlmostBoolean.YES, "legacy", "potted"));
public static final Set<Material> CARPETS = Collections.unmodifiableSet(add(
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(add(
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(add(
public static final Set<Material> CONCRETE_POWDER_BLOCKS = Collections.unmodifiableSet(addBlocks(
BridgeMaterial.getBySuffix("_concrete_powder", AlmostBoolean.YES, "legacy"),
"concrete_powder"));
@ -156,16 +178,16 @@ public class MaterialUtil {
));
/** Flower pot and potted plants / things. */
public static final Set<Material> FLOWER_POTS = Collections.unmodifiableSet(add(
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(add(
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(add(
public static final Set<Material> GLASS_PANES = Collections.unmodifiableSet(addBlocks(
BridgeMaterial.getBySuffix("_glass_pane", AlmostBoolean.YES, "legacy"),
"glass_pane", "thin_glass"));
@ -174,7 +196,7 @@ public class MaterialUtil {
);
/** Heads placed on the ground. Includes skulls. */
public static final Set<Material> HEADS_GROUND = Collections.unmodifiableSet(add(
public static final Set<Material> HEADS_GROUND = Collections.unmodifiableSet(addBlocks(
BridgeMaterial.getByPrefixAndSuffix(
null,
Arrays.asList("_skull", "_head"),
@ -192,14 +214,14 @@ public class MaterialUtil {
));
/** Blocks that are infested with silverfish. */
public static final Set<Material> INFESTED_BLOCKS = Collections.unmodifiableSet(add(
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.getAll("lava", "stationary_lava"));
BridgeMaterial.getAllBlocks("lava", "stationary_lava"));
public static final Set<Material> LEAVES = Collections.unmodifiableSet(add(
public static final Set<Material> LEAVES = Collections.unmodifiableSet(addBlocks(
BridgeMaterial.getByPrefixAndSuffix(
woodTypes,
Arrays.asList("_leaves"), // Strictly _pressure_plate for 1.13.
@ -208,7 +230,7 @@ public class MaterialUtil {
), "leaves", "leaves_2"));
/** LOGS. */
public static final Set<Material> LOGS = Collections.unmodifiableSet(add(
public static final Set<Material> LOGS = Collections.unmodifiableSet(addBlocks(
BridgeMaterial.getByPrefixAndSuffix(
woodTypes,
Arrays.asList("_log"),
@ -217,7 +239,7 @@ public class MaterialUtil {
), "log", "log_2"));
/** Mushroom blocks (huge ones). */
public static final Set<Material> MUSHROOM_BLOCKS = Collections.unmodifiableSet(add(
public static final Set<Material> MUSHROOM_BLOCKS = Collections.unmodifiableSet(addBlocks(
BridgeMaterial.getBySuffix(
"_mushroom_block",
AlmostBoolean.YES,
@ -233,7 +255,7 @@ public class MaterialUtil {
"dead", "legacy"
));
public static final Set<Material> PLANKS = Collections.unmodifiableSet(add(
public static final Set<Material> PLANKS = Collections.unmodifiableSet(addBlocks(
BridgeMaterial.getBySuffix("_planks", AlmostBoolean.YES, "legacy"),
"wood"));
@ -266,7 +288,7 @@ public class MaterialUtil {
);
/** All ordinary terracotta (hard clay) blocks. */
public static final Set<Material> TERRACOTTA_BLOCKS = Collections.unmodifiableSet(add(
public static final Set<Material> TERRACOTTA_BLOCKS = Collections.unmodifiableSet(addBlocks(
// TODO: exclude GLAZED or not?
BridgeMaterial.getByPrefixAndSuffix(
null, Arrays.asList("_terracotta"),
@ -279,7 +301,32 @@ public class MaterialUtil {
public static final Set<Material> TULIPS = Collections.unmodifiableSet(
BridgeMaterial.getBySuffix("tulip", AlmostBoolean.YES, "legacy", "potted"));
public static final Set<Material> WALL_BANNERS = Collections.unmodifiableSet(add(
/**
* 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",
"command_block"
),
AlmostBoolean.YES, "legacy"),
"observer", "structure_block",
"note_block", "piston", "piston_base", "tnt",
"dispenser", "dropper", "furnace",
"pumpkin", "melon_block", "hay_block", "bone_block",
"nether_wart_block", "cobweb", "web",
"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",
"sand", "stone", "gravel", "dirt", "grass_block", "grass",
"sea_lantern", "redstone_lamp"
));
public static final Set<Material> WALL_BANNERS = Collections.unmodifiableSet(addBlocks(
BridgeMaterial.getByPrefixAndSuffix(
null,
Arrays.asList("_wall_banner"),
@ -289,10 +336,10 @@ public class MaterialUtil {
/** All water blocks. */
public static final Set<Material> WATER = Collections.unmodifiableSet(
BridgeMaterial.getAll("water", "stationary_water"));
BridgeMaterial.getAllBlocks("water", "stationary_water"));
/** Wood types (1.13 rather). */
public static final Set<Material> WOOD_BLOCKS = Collections.unmodifiableSet(add(
public static final Set<Material> WOOD_BLOCKS = Collections.unmodifiableSet(addBlocks(
BridgeMaterial.getByPrefixAndSuffix(
woodTypes,
Arrays.asList("_wood"),
@ -315,7 +362,7 @@ public class MaterialUtil {
"trap"
));
public static final Set<Material> WOODEN_FENCES = Collections.unmodifiableSet(add(
public static final Set<Material> WOODEN_FENCES = Collections.unmodifiableSet(addBlocks(
BridgeMaterial.getByPrefixAndSuffix(
woodTypes,
Arrays.asList("_fence"),
@ -323,7 +370,7 @@ public class MaterialUtil {
// , ...
), "fence"));
public static final Set<Material> WOODEN_FENCE_GATES = Collections.unmodifiableSet(add(
public static final Set<Material> WOODEN_FENCE_GATES = Collections.unmodifiableSet(addBlocks(
BridgeMaterial.getByPrefixAndSuffix(
woodTypes,
Arrays.asList("_fence_gate"),
@ -358,7 +405,7 @@ public class MaterialUtil {
// , ...
));
public static final Set<Material> WOODEN_TRAP_DOORS = Collections.unmodifiableSet(add(
public static final Set<Material> WOODEN_TRAP_DOORS = Collections.unmodifiableSet(addBlocks(
BridgeMaterial.getByPrefixAndSuffix(
woodTypes,
Arrays.asList("_trap_door", "_trapdoor"),
@ -366,13 +413,40 @@ public class MaterialUtil {
// , ...
), "trap_door"));
public static final Set<Material> WOOL_BLOCKS = Collections.unmodifiableSet(add(
public static final Set<Material> WOOL_BLOCKS = Collections.unmodifiableSet(addBlocks(
BridgeMaterial.getBySuffix(
"_wool",
AlmostBoolean.YES,
"legacy"
), "wool"));
///////////////////////////////
// Collections of collections
///////////////////////////////
/**
* 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
));
////////////////////
// Access methods.

View File

@ -17,6 +17,7 @@ package fr.neatmonster.nocheatplus.test;
import org.bukkit.Material;
import org.junit.Test;
import fr.neatmonster.nocheatplus.compat.BridgeMaterial;
import fr.neatmonster.nocheatplus.logging.StaticLog;
import fr.neatmonster.nocheatplus.utilities.build.BuildParameters;
import fr.neatmonster.nocheatplus.utilities.collision.PassableRayTracing;
@ -152,8 +153,7 @@ public class TestPassableRayTracing {
final double[] stepBounds = new double[]{0.0, 0.0, 0.0, 1.0, 0.5, 1.0};
for (int x = 0; x < 16; x++) {
for (int z = 0; z < 16; z++) {
// STONE = HACK (CompatBukkit block-flags problem).
bc.set(x, 65, z, Material.STONE, stepBounds);
bc.set(x, 65, z, BridgeMaterial.STONE_SLAB, stepBounds);
}
}
PassableRayTracing rt = new PassableRayTracing();