Skip to content

Commit

Permalink
[BLEEDING][BREAKING] MC 1.13 Material changes, first batch.
Browse files Browse the repository at this point in the history
First batch:
* Initialize blocks somehow, so no errors nor missing blocks happen
during startup.

Possibly Missing:
* There might be references of removed/renamed material (blocks/items)
throughout the code.
* Some blocks may behave different now/then.

Missing:
* Block#getData may not reflect (all?) properties anymore.
* Block shape getting is missing. Block shapes are now (potentially)
more complex to process. Concept might be to keep a double array for the
rough bounds, and add an (optional +- null) array of arrays for sub
shapes, if present (IBlockCacheNode). So a first rough update is more
simple/compatible.
  • Loading branch information
asofold committed Aug 20, 2018
1 parent f6f94d4 commit 62df128
Show file tree
Hide file tree
Showing 38 changed files with 1,773 additions and 454 deletions.
Expand Up @@ -430,4 +430,8 @@ public static boolean endsWithAnyOf(final String input, final String... endsWith
return false;
}

public static String reverse(final String input) {
return new StringBuilder(input).reverse().toString();
}

}
Expand Up @@ -20,34 +20,93 @@

import org.junit.Test;

import fr.neatmonster.nocheatplus.utilities.StringUtil;
import fr.neatmonster.nocheatplus.utilities.ds.prefixtree.SimpleCharPrefixTree;

public class TestSimpleCharPrefixTree {
private List<String> feed = Arrays.asList(
"op", "op dummy", "ncp info"
);

private List<String> mustFind = Arrays.asList(
"op", "op dummy", "ncp info", "ncp info test"
);

private List<String> mustNotFind = Arrays.asList(
"opp", "opp dummy", "op dummy2", "ncp", "ncp dummy"
);

@Test
public void testPrefixWords(){
SimpleCharPrefixTree tree = new SimpleCharPrefixTree();
tree.feedAll(feed, false, true);
for (String input : mustFind){
if (!tree.hasPrefixWords(input)){
fail("Expect to be matched: '" + input + "'");
}
}
for (String input : mustNotFind){
if (tree.hasPrefixWords(input)){
fail("Expect not to be matched: '" + input + "'");
}
}
}
private List<String> feed = Arrays.asList(
"op", "op dummy", "ncp info"
);

private List<String> mustFind = Arrays.asList(
"op", "op dummy", "ncp info", "ncp info test"
);

private List<String> mustNotFindWords = Arrays.asList(
"opp", "opp dummy", "op dummy2", "ncp", "ncp dummy"
);

private List<String> mustNotFindPrefix = Arrays.asList(
"ok", "ncp", "ncp dummy", "ncp inf"
);

/** Numbers are neither prefix nor suffix of each other. */
private List<String> uniqueNumbers = Arrays.asList(
"123456", "2345678", "34567", "456789"
);

@Test
public void testPrefixWords(){
SimpleCharPrefixTree tree = new SimpleCharPrefixTree();
tree.feedAll(feed, false, true);
for (String input : mustFind){
if (!tree.hasPrefixWords(input)){
fail("Expect to be matched: '" + input + "'");
}
}
for (String input : mustNotFindWords){
if (tree.hasPrefixWords(input)){
fail("Expect not to be matched: '" + input + "'");
}
}
}

@Test
public void testHasPrefix() {
SimpleCharPrefixTree tree = new SimpleCharPrefixTree();
tree.feedAll(feed, false, true);
// Same tests as with prefix words.
for (String input : mustFind){
if (!tree.hasPrefix(input)){
fail("Expect to be matched: '" + input + "'");
}
}
for (String input : mustNotFindPrefix){
if (tree.hasPrefix(input)){
fail("Expect not to be matched: '" + input + "'");
}
}
// Extra
if (!tree.hasPrefix("ncp infocrabs")) {
fail("'ncp info' should be a prefix of 'ncp infocrabs'.");
}
}

@Test
public void testSuffixTree() {
SimpleCharPrefixTree prefixTree = new SimpleCharPrefixTree();
prefixTree.feedAll(uniqueNumbers, false, true);
SimpleCharPrefixTree suffixTree = new SimpleCharPrefixTree();
for (String key : uniqueNumbers) {
suffixTree.feed(StringUtil.reverse(key));
}
for (String input : uniqueNumbers) {
if (!prefixTree.hasPrefix(input)) {
fail("Fed data not matching prefix tree: " + input);
}
if (suffixTree.hasPrefix(input)) {
fail("Non-reversed data is matching suffix tree: " + input);
}
}
for (String input : uniqueNumbers) {
input = StringUtil.reverse(input);
if (prefixTree.hasPrefix(input)) {
fail("Reversed fed data is matching prefix tree: " + input);
}
if (!suffixTree.hasPrefix(input)) {
fail("Reversed fed data not matching suffix tree: " + input);
}
}
}

}
Expand Up @@ -26,6 +26,7 @@
import org.bukkit.event.entity.EntityPortalEnterEvent;

import fr.neatmonster.nocheatplus.NCPAPIProvider;
import fr.neatmonster.nocheatplus.compat.BridgeMaterial;
import fr.neatmonster.nocheatplus.compat.versions.ServerVersion;
import fr.neatmonster.nocheatplus.logging.Streams;
import fr.neatmonster.nocheatplus.utilities.ReflectionUtil;
Expand Down Expand Up @@ -92,7 +93,10 @@ else if (entity instanceof Item) {
if (worldData.getGenericInstance(InventoryConfig.class).hotFixFallingBlockEndPortalActive) {
final BlockCache blockCache = wrapBlockCache.getBlockCache();
blockCache.setAccess(world);
final boolean nearbyPortal = BlockProperties.collidesId(blockCache, loc.getX() - 2.0, loc.getY() - 2.0, loc.getZ() - 2.0, loc.getX() + 3.0, loc.getY() + 3.0, loc.getZ() + 3.0, Material.ENDER_PORTAL);
final boolean nearbyPortal = BlockProperties.collidesId(blockCache,
loc.getX() - 2.0, loc.getY() - 2.0, loc.getZ() - 2.0,
loc.getX() + 3.0, loc.getY() + 3.0, loc.getZ() + 3.0,
BridgeMaterial.END_PORTAL);
blockCache.cleanup();
if (nearbyPortal) {
// Likely spigot currently removes entities entering portals anyway (cross-world teleport issues).
Expand Down
Expand Up @@ -15,14 +15,18 @@
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{

Expand All @@ -37,12 +41,24 @@ public void setupBlockProperties(final WorldConfigProvider<?> worldConfigProvide
final Set<Material> fullBlocks = new HashSet<Material>();
for (final Material mat : new Material[]{
// TODO: Ice !? / Packed ice !?
Material.GLASS, Material.GLOWSTONE, Material.ICE, Material.LEAVES,
Material.COMMAND, Material.BEACON,
Material.PISTON_BASE,
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;
Expand Down
Expand Up @@ -34,6 +34,7 @@
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.MaterialUtil;

public class MCAccessBukkitBase implements MCAccess {

Expand Down Expand Up @@ -239,15 +240,14 @@ public double getWidth(final Entity entity) {

@Override
public AlmostBoolean isBlockLiquid(final Material mat) {
if (mat == null) return AlmostBoolean.MAYBE;
switch (mat) {
case STATIONARY_LAVA:
case STATIONARY_WATER:
case WATER:
case LAVA:
return AlmostBoolean.YES;
default:
return AlmostBoolean.NO;
if (mat == null) {
return AlmostBoolean.MAYBE;
}
else if (MaterialUtil.WATER.contains(mat) || MaterialUtil.LAVA.contains(mat)) {
return AlmostBoolean.YES;
}
else {
return AlmostBoolean.NO;
}
}

Expand Down
Expand Up @@ -95,7 +95,7 @@ public void setClickedBlock(Block block, int tick, long now, Material tool) {
clickedY = block.getY();
clickedZ = block.getZ();
clickedTick = tick;
clickedTool = tool == Material.AIR ? null : tool;
clickedTool = BlockProperties.isAir(tool) ? null : tool;
}

/**
Expand Down
Expand Up @@ -24,6 +24,7 @@
import fr.neatmonster.nocheatplus.checks.CheckType;
import fr.neatmonster.nocheatplus.checks.ViolationData;
import fr.neatmonster.nocheatplus.checks.blockinteract.BlockInteractData;
import fr.neatmonster.nocheatplus.compat.BridgeMaterial;
import fr.neatmonster.nocheatplus.permissions.Permissions;
import fr.neatmonster.nocheatplus.players.IPlayerData;
import fr.neatmonster.nocheatplus.utilities.map.BlockProperties;
Expand All @@ -42,7 +43,10 @@ public boolean check(final Player player, final Block block, final Material plac
final Block blockAgainst, final boolean isInteractBlock,
final BlockPlaceData data, final BlockPlaceConfig cc, final IPlayerData pData) {
boolean violation = false;
// TODO: Make more precise (workarounds like WATER_LILY, general points, such as action?).
/*
* TODO: Make more precise (workarounds like BridgeMisc.LILY_PAD,
* general points, such as action?).
*/
// Workaround for signs on cactus and similar.
final BlockInteractData bdata = pData.getGenericInstance(BlockInteractData.class); // TODO: pass as argument.
final Material againstType = blockAgainst.getType();
Expand All @@ -65,7 +69,7 @@ else if (!pData.hasPermission(Permissions.BLOCKPLACE_AGAINST_AIR, player)) {
}
else if (BlockProperties.isLiquid(againstType)) {
// TODO: F_PLACE_AGAINST_WATER|LIQUID...
if ((placedMat != Material.WATER_LILY
if ((placedMat != BridgeMaterial.LILY_PAD
|| !BlockProperties.isLiquid(block.getRelative(BlockFace.DOWN).getType()))
&& !pData.hasPermission(Permissions.BLOCKPLACE_AGAINST_LIQUIDS, player)) {
violation = true;
Expand Down
Expand Up @@ -27,6 +27,7 @@
import fr.neatmonster.nocheatplus.checks.Check;
import fr.neatmonster.nocheatplus.checks.CheckType;
import fr.neatmonster.nocheatplus.checks.ViolationData;
import fr.neatmonster.nocheatplus.compat.BridgeMaterial;
import fr.neatmonster.nocheatplus.players.IPlayerData;
import fr.neatmonster.nocheatplus.utilities.StringUtil;
import fr.neatmonster.nocheatplus.utilities.TickTask;
Expand Down Expand Up @@ -59,8 +60,8 @@ public boolean check(final Player player, final Block block, final String[] line
final BlockPlaceData data = pData.getGenericInstance(BlockPlaceData.class);
final BlockPlaceConfig cc = pData.getGenericInstance(BlockPlaceConfig.class);
Material mat = block.getType();
if (mat == Material.SIGN_POST || mat == Material.WALL_SIGN) {
mat = Material.SIGN;
if (mat == BridgeMaterial.SIGN || mat == Material.WALL_SIGN) {
mat = Material.SIGN; // ITEM
}
if (data.autoSignPlacedHash != BlockPlaceListener.getBlockPlaceHash(block, mat)){
tags.add("block_mismatch");
Expand Down
Expand Up @@ -56,10 +56,10 @@
import fr.neatmonster.nocheatplus.players.IPlayerData;
import fr.neatmonster.nocheatplus.players.PlayerFactoryArgument;
import fr.neatmonster.nocheatplus.stats.Counters;
import fr.neatmonster.nocheatplus.utilities.InventoryUtil;
import fr.neatmonster.nocheatplus.utilities.ReflectionUtil;
import fr.neatmonster.nocheatplus.utilities.TickTask;
import fr.neatmonster.nocheatplus.utilities.map.BlockProperties;
import fr.neatmonster.nocheatplus.utilities.map.MaterialUtil;
import fr.neatmonster.nocheatplus.worlds.WorldFactoryArgument;

/**
Expand Down Expand Up @@ -375,14 +375,14 @@ public void onPlayerInteract(final PlayerInteractEvent event) {
final IPlayerData pData = DataManager.getPlayerData(player);
final BlockPlaceConfig cc = pData.getGenericInstance(BlockPlaceConfig.class);
final Material type = stack.getType();
if (InventoryUtil.isBoat(type)) {
if (MaterialUtil.isBoat(type)) {
if (cc.preventBoatsAnywhere) {
// TODO: Alter config (activation, allow on top of ground).
// TODO: Version/plugin specific alteration for 'default'.
checkBoatsAnywhere(player, event, cc, pData);
}
}
else if (type == Material.MONSTER_EGG) {
else if (MaterialUtil.isSpawnEgg(type)) {
// Check blockplace.speed.
if (speed.isEnabled(player, pData) && speed.check(player, cc, pData)) {
// If the check was positive, cancel the event.
Expand Down
Expand Up @@ -65,6 +65,7 @@
import fr.neatmonster.nocheatplus.stats.Counters;
import fr.neatmonster.nocheatplus.utilities.InventoryUtil;
import fr.neatmonster.nocheatplus.utilities.ReflectionUtil;
import fr.neatmonster.nocheatplus.utilities.map.MaterialUtil;
import fr.neatmonster.nocheatplus.worlds.WorldFactoryArgument;

/**
Expand Down Expand Up @@ -455,7 +456,7 @@ else if (MovingUtil.hasScheduledPlayerSetBack(player)) {
// TODO: Activate mob-egg check only for specific server versions.
final ItemStack stack = Bridge1_9.getUsedItem(player, event);
Entity entity = event.getRightClicked();
if (stack != null && stack.getType() == Material.MONSTER_EGG
if (stack != null && MaterialUtil.isSpawnEgg(stack.getType())
&& (entity == null || entity instanceof LivingEntity || entity instanceof ComplexEntityPart)
&& items.isEnabled(player, DataManager.getPlayerData(player))) {
event.setCancelled(true);
Expand Down
Expand Up @@ -1925,6 +1925,13 @@ else if (to == null) {
// Always keep fall damage.
player.setFallDistance((float) fallDistance);
data.noFallFallDistance = (float) fallDistance;

// TEST: Detect jumping on a just placed fence.
// 1. Detect the low correction teleport.
// 2. Detect the fence.
// 3. Verify the past move.
// (4. Check for a block change entry or last placed block.)
// TODO: REMOVE TEST
}
else if (fallDistance > 1.0 && fallDistance - player.getFallDistance() > 0.0) {
// Reset fall distance if set so in the config.
Expand Down Expand Up @@ -2817,10 +2824,10 @@ private void outputMoveDebug(final Player player, final PlayerLocation from, fin
if (from.getBlockFlags() != 0) {
builder.append("\nfrom flags: " + StringUtil.join(BlockProperties.getFlagNames(from.getBlockFlags()), "+"));
}
if (from.getTypeId() != Material.AIR) {
if (!BlockProperties.isAir(from.getTypeId())) {
DebugUtil.addBlockInfo(builder, from, "\nfrom");
}
if (from.getTypeIdBelow() != Material.AIR) {
if (!BlockProperties.isAir(from.getTypeIdBelow())) {
DebugUtil.addBlockBelowInfo(builder, from, "\nfrom");
}
if (!from.isOnGround() && from.isOnGround(0.5)) {
Expand All @@ -2830,10 +2837,10 @@ private void outputMoveDebug(final Player player, final PlayerLocation from, fin
if (to.getBlockFlags() != 0) {
builder.append("\nto flags: " + StringUtil.join(BlockProperties.getFlagNames(to.getBlockFlags()), "+"));
}
if (to.getTypeId() != Material.AIR) {
if (!BlockProperties.isAir(to.getTypeId())) {
DebugUtil.addBlockInfo(builder, to, "\nto");
}
if (to.getTypeIdBelow() != Material.AIR) {
if (!BlockProperties.isAir(to.getTypeIdBelow())) {
DebugUtil.addBlockBelowInfo(builder, to, "\nto");
}
if (!to.isOnGround() && to.isOnGround(0.5)) {
Expand Down
Expand Up @@ -38,7 +38,7 @@
public class NoFall extends Check {

/*
* TODO: Due to soil not converting back to dirt with the current
* TODO: Due to farmland/soil not converting back to dirt with the current
* implementation: Implement packet sync with moving events. Then alter
* packet on-ground and mc fall distance for a new default concept. As a
* fall back either the old method, or an adaption with scheduled/later fall
Expand Down

0 comments on commit 62df128

Please sign in to comment.