[BLEEDING][BREAKING] Swift way in to Bukkit shape models (slabs first).

Remains warnings, registry debugging output without checking config.
This commit is contained in:
asofold 2018-08-21 11:45:15 +02:00
parent 54c022f74d
commit 56f1a37969
17 changed files with 206 additions and 49 deletions

View File

@ -59,18 +59,6 @@ public class BlockCacheBukkit extends BlockCache {
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

@ -1,7 +1,13 @@
package fr.neatmonster.nocheatplus.compat.bukkit;
import java.util.Map;
import org.bukkit.Material;
import org.bukkit.World;
import fr.neatmonster.nocheatplus.compat.bukkit.model.BukkitShapeModel;
/**
* BlockCache for MCAccessBukkitModern.
*
@ -10,6 +16,13 @@ import org.bukkit.World;
*/
public class BlockCacheBukkitModern extends BlockCacheBukkit {
private Map<Material, BukkitShapeModel> shapeModels;
public BlockCacheBukkitModern(Map<Material, BukkitShapeModel> shapeModels) {
super(null);
this.shapeModels = shapeModels;
}
public BlockCacheBukkitModern(World world) {
super(world);
}
@ -22,8 +35,27 @@ public class BlockCacheBukkitModern extends BlockCacheBukkit {
@Override
public double[] fetchBounds(int x, int y, int z) {
// minX, minY, minZ, maxX, maxY, maxZ
// TODO: Fetch what's possible to fetch/guess (...).
return super.fetchBounds(x, y, z);
// TODO: Consider to store the last used block/stuff within BlockCacheBukkit already.
//final Block block = world.getBlockAt(x, y, z);
//final BlockState state = block.getState();
//final MaterialData materialData = state.getData();
//final BlockData blockData = state.getBlockData();
Material mat = getType(x, y, z);
final BukkitShapeModel shapeModel = shapeModels.get(mat);
if (shapeModel == null) {
return super.fetchBounds(x, y, z);
}
else {
return shapeModel.getShape(this, world, x, y, z);
}
}
// TODO: Might refine standsOnEntity as well.
}

View File

@ -15,12 +15,17 @@
package fr.neatmonster.nocheatplus.compat.bukkit;
import java.util.LinkedHashSet;
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.logging.StaticLog;
import fr.neatmonster.nocheatplus.utilities.StringUtil;
import fr.neatmonster.nocheatplus.utilities.map.BlockFlags;
import fr.neatmonster.nocheatplus.utilities.map.BlockProperties;
public class MCAccessBukkit extends MCAccessBukkitBase implements BlockPropertiesSetup {
@ -31,22 +36,24 @@ public class MCAccessBukkit extends MCAccessBukkitBase implements BlockPropertie
@Override
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> itchyBlocks = new LinkedHashSet<Material>();
for (final Material mat : Material.values()) {
if (!mat.isBlock()) {
continue;
}
else if (guessItchyBlock(mat)) {
// Uncertain bounding-box, allow passing through.
StaticLog.logDebug("Itchy: " + mat);
long flags = BlockProperties.F_IGN_PASSABLE;
if ((BlockProperties.isSolid(mat)
|| BlockProperties.isGround(mat))) {
if ((BlockFlags.hasAnyFlag(flags, BlockFlags.SOLID_GROUND))) {
// Block can be ground, so allow standing on any height.
flags |= BlockProperties.F_GROUND | BlockProperties.F_GROUND_HEIGHT;
}
BlockProperties.setBlockFlags(mat, BlockProperties.getBlockFlags(mat) | flags);
/*
* TODO: Might have to set all blocks to ground here, rather
* catch flowers and the like with MaterialUtil.
*/
BlockFlags.addFlags(mat, flags);
itchyBlocks.add(mat);
}
}
// Blocks that are reported to be full and solid, but which are not.
@ -56,8 +63,12 @@ public class MCAccessBukkit extends MCAccessBukkitBase implements BlockPropertie
}) {
if (!processedBlocks.contains(mat)) {
BlockProperties.setBlockFlags(mat, BlockProperties.getBlockFlags(mat) | flags);
itchyBlocks.add(mat);
}
}
if (!itchyBlocks.isEmpty()) {
StaticLog.logDebug("The following blocks can not be modeled correctly: " + StringUtil.join(itchyBlocks, ", "));
}
}
}

View File

@ -88,9 +88,6 @@ public class MCAccessBukkitBase implements MCAccess {
return false;
}
// TODO: Directional stairs / slabs (wall heads, ...)
// TODO: Ground heads/skulls.
// TODO: Use working route.
return guessItchyBlockPre1_13(mat);
}

View File

@ -1,13 +1,31 @@
package fr.neatmonster.nocheatplus.compat.bukkit;
import java.util.HashMap;
import java.util.Map;
import org.bukkit.Material;
import fr.neatmonster.nocheatplus.compat.blocks.init.BlockInit;
import fr.neatmonster.nocheatplus.compat.bukkit.model.BukkitShapeModel;
import fr.neatmonster.nocheatplus.compat.bukkit.model.BukkitSlab;
import fr.neatmonster.nocheatplus.config.WorldConfigProvider;
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 MCAccessBukkitModern extends MCAccessBukkit {
protected final Map<Material, BukkitShapeModel> shapeModels = new HashMap<Material, BukkitShapeModel>();
private static final BukkitShapeModel MODEL_SLAB = new BukkitSlab();
public MCAccessBukkitModern() {
super();
BlockInit.assertMaterialExists("OAK_LOG");
BlockInit.assertMaterialExists("VOID_AIR");
}
@Override
public String getMCVersion() {
return "1.13|?";
@ -15,13 +33,33 @@ public class MCAccessBukkitModern extends MCAccessBukkit {
@Override
public BlockCache getBlockCache() {
return new BlockCacheBukkitModern(null);
return new BlockCacheBukkitModern(shapeModels);
}
@Override
public void setupBlockProperties(final WorldConfigProvider<?> worldConfigProvider) {
// TODO: Initialize some blocks and add to this.processedBlocks.
// Pre-process for flags.
// TODO: Also consider removing flags (passable_x4 etc).
for (final Material mat : Material.values()) {
if (MaterialUtil.SLABS.contains(mat)) {
BlockFlags.addFlags(mat, BlockProperties.F_MODEL_SLAB);
}
}
// Sort to processed by flags.
for (final Material mat : Material.values()) {
final long flags = BlockProperties.getBlockFlags(mat);
// Step.
if (BlockFlags.hasAnyFlag(flags, BlockProperties.F_MODEL_SLAB)) {
processedBlocks.add(mat);
shapeModels.put(mat, MODEL_SLAB);
}
// Stairs.
// Fences. // TODO: May need specialized models for edge cases?
// Thin fences.
// ... (heads, chests, static, shulker box ...)
}
super.setupBlockProperties(worldConfigProvider);
}

View File

@ -0,0 +1,10 @@
package fr.neatmonster.nocheatplus.compat.bukkit.model;
import org.bukkit.World;
public interface BukkitShapeModel extends ShapeModel<World> {
/*
* TODO: Subject to removal/change (there might be abstract classes for some
* shapes later on, and then this'll be redundant interfaces).
*/
}

View File

@ -0,0 +1,37 @@
package fr.neatmonster.nocheatplus.compat.bukkit.model;
import org.bukkit.World;
import org.bukkit.block.Block;
import org.bukkit.block.BlockState;
import org.bukkit.block.data.BlockData;
import org.bukkit.block.data.type.Slab;
import fr.neatmonster.nocheatplus.utilities.map.BlockCache;
public class BukkitSlab implements BukkitShapeModel {
@Override
public double[] getShape(final BlockCache blockCache,
final World world, final int x, final int y, final int z) {
final Block block = world.getBlockAt(x, y, z);
final BlockState state = block.getState();
final BlockData blockData = state.getBlockData();
if (blockData instanceof Slab) {
final Slab slab = (Slab) blockData;
switch (slab.getType()) {
case BOTTOM:
return new double[] {0.0, 0.0, 0.0, 1.0, 0.5, 1.0};
case TOP:
return new double[] {0.0, 0.5, 0.0, 1.0, 1.0, 1.0};
case DOUBLE:
break;
default:
break;
}
}
return new double[] {0.0, 0.0, 0.0, 1.0, 1.0, 1.0};
}
}

View File

@ -0,0 +1,10 @@
package fr.neatmonster.nocheatplus.compat.bukkit.model;
import fr.neatmonster.nocheatplus.utilities.map.BlockCache;
public interface ShapeModel<W> {
// TODO: Refine +- might have BukkitBlockCacheNode etc.
public double[] getShape(BlockCache blockCache, W world, int x, int y, int z);
}

View File

@ -23,6 +23,7 @@ import fr.neatmonster.nocheatplus.utilities.map.BlockProperties;
public final class BridgeEnchant {
@SuppressWarnings("deprecation")
private static final Enchantment parseEnchantment(final String name) {
try {
return Enchantment.getByName(name);

View File

@ -44,6 +44,7 @@ import fr.neatmonster.nocheatplus.logging.Streams;
import fr.neatmonster.nocheatplus.utilities.ReflectionUtil;
import fr.neatmonster.nocheatplus.utilities.map.BlockProperties;
public class BlockChangeListener implements Listener {
// TODO: Fine grained configurability (also switch flag in MovingListener to a sub-config).
@ -174,6 +175,7 @@ public class BlockChangeListener implements Listener {
}
private BlockFace getDirection(final Block pistonBlock) {
// TODO: Register/store a fetcher thing (DirectionalFromBlock)
final MaterialData data = pistonBlock.getState().getData();
if (data instanceof Directional) {
Directional directional = (Directional) data;

View File

@ -21,6 +21,7 @@ import fr.neatmonster.nocheatplus.compat.blocks.BlockPropertiesSetup;
import fr.neatmonster.nocheatplus.compat.blocks.init.BlockInit;
import fr.neatmonster.nocheatplus.config.WorldConfigProvider;
import fr.neatmonster.nocheatplus.logging.StaticLog;
import fr.neatmonster.nocheatplus.utilities.map.BlockFlags;
/**
* Blocks for Minecraft 1.10.
@ -49,7 +50,10 @@ public class BlocksMC1_10 implements BlockPropertiesSetup {
// 216 BONE_BLOCK
BlockInit.setAs("BONE_BLOCK", Material.COBBLESTONE);
// 217 STRUCTURE_VOID
BlockInit.setAs("STRUCTURE_VOID", "STRUCTURE_BLOCK"); // Like STRUCTURE_BLOCK.
BlockInit.setInstantAir("STRUCTURE_VOID");
// Not sure when: structure block is solid.
BlockFlags.setFullySolidFlags("STRUCTURE_BLOCK");
StaticLog.logInfo("Added block-info for Minecraft 1.10 blocks.");
}

View File

@ -63,11 +63,11 @@ public class BlocksMC1_5 implements BlockPropertiesSetup {
// 149 Redstone Comparator (inactive)
// BlockFlags.addFlags(149, BlockProperties.F_IGN_PASSABLE | BlockProperties.F_GROUND | BlockProperties.F_GROUND_HEIGHT);
BlockInit.setAs("REDSTONE_COMPARATOR_OFF", Material.DIODE_BLOCK_OFF);
BlockInit.setAs("REDSTONE_COMPARATOR_OFF", "DIODE_BLOCK_OFF");
// 150 Redstone Comparator (active)
// BlockFlags.addFlags(150, BlockProperties.F_IGN_PASSABLE | BlockProperties.F_GROUND | BlockProperties.F_GROUND_HEIGHT);
BlockInit.setAs("REDSTONE_COMPARATOR_ON", Material.DIODE_BLOCK_ON);
BlockInit.setAs("REDSTONE_COMPARATOR_ON", "DIODE_BLOCK_ON");
}
else {
// 1.13

View File

@ -64,7 +64,7 @@ public class BlocksMC1_9 implements BlockPropertiesSetup {
// 204(PURPUR_DOUBLE_SLAB / SOLID+GROUND)
if (BridgeMaterial.has("PURPUR_DOUBLE_SLAB")) {
if (BridgeMaterial.has("PURPUR_DOUBLE_SLAB")) {
BlockInit.setAs("PURPUR_DOUBLE_SLAB", Material.DOUBLE_STEP);
BlockInit.setAs("PURPUR_DOUBLE_SLAB", "DOUBLE_STEP");
}
}

View File

@ -16,7 +16,6 @@ package fr.neatmonster.nocheatplus.utilities.map;
import org.bukkit.Material;
// TODO: Auto-generated Javadoc
/**
* Utilities for block-flags.<br>
* Later the flag constant definitions and parsing might be moved here.
@ -25,9 +24,16 @@ import org.bukkit.Material;
*/
public class BlockFlags {
//////////////////
// Summary flags
//////////////////
/** Explicitly set full bounds. */
public static final long FULL_BOUNDS = BlockProperties.F_XZ100 | BlockProperties.F_HEIGHT100;
/** SOLID and GROUND set. Treatment of SOLID/GROUND may be changed later. */
public static final long SOLID_GROUND = BlockProperties.F_SOLID | BlockProperties.F_GROUND;
/**
* Set flags of id same as already set with flags for the given material.
* (Uses BlockProperties.)
@ -133,4 +139,9 @@ public class BlockFlags {
return (flags & testFlags) == 0L;
}
/** Override flags to a fully solid block (set explicitly). */
public static void setFullySolidFlags(String blockId) {
BlockProperties.setBlockFlags(blockId, FULL_BOUNDS | SOLID_GROUND);
}
}

View File

@ -689,11 +689,14 @@ public class BlockProperties {
private static long f_next = 1;
private static long f_flag() {
if (f_next <= 0L) {
throw new IllegalStateException("No more flags available.");
final long flag;
synchronized(BlockProperties.class) {
if (f_next <= 0L) {
throw new IllegalStateException("No more flags available.");
}
flag = f_next;
f_next *= 2L;
}
final long flag = f_next;
f_next *= 2L;
return flag;
}
/** Flag position for stairs. */
@ -852,10 +855,10 @@ public class BlockProperties {
public static final long F_VARIABLE_REDSTONE = f_flag();
/**
* Indicator to start recoding towards multiple flag types (shape, moving,
* interaction, block-type/special, ...).
* BukkitModern model flag, set by MCAccessBukkitModern for routing, iff
* available.
*/
public static final long F_MAX_FLAG = f_flag();
public static final long F_MODEL_SLAB = f_flag();
// TODO: Convenience constants combining all height / minheight flags.
@ -870,16 +873,21 @@ public class BlockProperties {
static{
// Use reflection to get a flag -> name mapping and vice versa.
for (Field field : BlockProperties.class.getDeclaredFields()) {
String name = field.getName();
if (name.startsWith("F_")) {
try {
Long value = field.getLong(BlockProperties.class);
flagNameMap.put(value, name.substring(2));
nameFlagMap.put(name, value);
nameFlagMap.put(name.substring(2), value);
} catch (IllegalArgumentException e) {
} catch (IllegalAccessException e) {
synchronized(BlockProperties.class) {
for (Field field : BlockProperties.class.getDeclaredFields()) {
String name = field.getName();
if (name.startsWith("F_")) {
try {
Long value = field.getLong(BlockProperties.class);
if (flagNameMap.containsKey(value)) {
throw new IllegalStateException("Same value for flag names: " + name + " + " + flagNameMap.get(value));
}
flagNameMap.put(value, name.substring(2));
nameFlagMap.put(name, value);
nameFlagMap.put(name.substring(2), value);
} catch (IllegalArgumentException e) {
} catch (IllegalAccessException e) {
}
}
}
}
@ -2184,7 +2192,7 @@ public class BlockProperties {
duration = (long) (duration / 1.5 - (efficiency - 1) * 100);
}
}
else if (blockId == Material.LOG) {
else if (MaterialUtil.isLog(blockId)) {
duration -= efficiency >= 4 ? 250 : 400;
}
else if (blockProps.tool.toolType == toolProps.toolType) {
@ -2196,7 +2204,7 @@ public class BlockProperties {
}
else if (toolProps.materialBase == MaterialBase.STONE) {
if (blockId == Material.LOG) {
if (MaterialUtil.isLog(blockId)) {
duration -= 100;
}
}

View File

@ -270,6 +270,10 @@ public class MaterialUtil {
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"
@ -474,4 +478,8 @@ public class MaterialUtil {
return SPAWN_EGGS.contains(mat);
}
public static boolean isLog(final Material mat) {
return LOGS.contains(mat);
}
}

View File

@ -167,7 +167,7 @@ public class TestInteractRayTracing {
{FakeBlockCache fbc = new FakeBlockCache();
double[] _fb = new double[]{0.0, 0.0, 0.0, 1.0, 1.0, 1.0};
fbc.set(142, 67, 221, Material.DIRT, 0, _fb);fbc.set(142, 67, 217, BridgeMaterial.GRASS_BLOCK, 0, _fb);fbc.set(142, 69, 219, Material.AIR);fbc.set(142, 68, 218, BridgeMaterial.GRASS_BLOCK, 0, _fb);fbc.set(142, 70, 220, Material.AIR);fbc.set(142, 71, 217, Material.AIR);fbc.set(142, 71, 221, Material.AIR);fbc.set(143, 67, 218, Material.DIRT, 0, _fb);fbc.set(143, 68, 217, BridgeMaterial.GRASS_BLOCK, 0, _fb);fbc.set(143, 68, 221, BridgeMaterial.GRASS_BLOCK, 0, _fb);fbc.set(143, 69, 220, Material.AIR);fbc.set(143, 70, 219, Material.AIR);fbc.set(143, 71, 218, Material.AIR);fbc.set(144, 67, 219, Material.DIRT, 0, _fb);fbc.set(144, 68, 220, BridgeMaterial.GRASS_BLOCK, 0, _fb);fbc.set(144, 69, 217, Material.AIR);
fbc.set(144, 69, 221, BridgeMaterial.TALL_GRASS, 1, new double[]{0.09999999403953552, 0.0, 0.09999999403953552, 0.8999999761581421, 0.800000011920929, 0.8999999761581421});fbc.set(144, 70, 218, Material.AIR);fbc.set(144, 71, 219, Material.AIR);fbc.set(145, 67, 220, Material.DIRT, 0, _fb);fbc.set(145, 68, 219, BridgeMaterial.GRASS_BLOCK, 0, _fb);fbc.set(145, 69, 218, Material.AIR);fbc.set(145, 70, 217, Material.AIR);fbc.set(145, 70, 221, Material.AIR);fbc.set(145, 71, 220, Material.AIR);fbc.set(142, 68, 217, BridgeMaterial.GRASS_BLOCK, 0, _fb);fbc.set(142, 68, 221, BridgeMaterial.GRASS_BLOCK, 0, _fb);fbc.set(142, 67, 218, Material.DIRT, 0, _fb);fbc.set(142, 69, 220, Material.AIR);fbc.set(142, 70, 219, Material.AIR);fbc.set(142, 71, 218, Material.AIR);fbc.set(143, 67, 217, Material.DIRT, 0, _fb);fbc.set(143, 67, 221, Material.DIRT, 0, _fb);fbc.set(143, 68, 218, Material.OBSIDIAN, 0, _fb);fbc.set(143, 69, 219, Material.AIR);fbc.set(143, 70, 220, Material.AIR);fbc.set(143, 71, 217, Material.AIR);fbc.set(143, 71, 221, Material.AIR);fbc.set(144, 67, 220, Material.DIRT, 0, _fb);fbc.set(144, 68, 219, Material.OBSIDIAN, 0, _fb);fbc.set(144, 69, 218, Material.AIR);fbc.set(144, 70, 217, Material.AIR);fbc.set(144, 70, 221, Material.AIR);fbc.set(144, 71, 220, Material.AIR);fbc.set(145, 67, 219, Material.DIRT, 0, _fb);fbc.set(145, 68, 220, BridgeMaterial.GRASS_BLOCK, 0, _fb);fbc.set(145, 69, 217, Material.AIR);fbc.set(145, 69, 221, Material.TORCH, 5, new double[]{0.4000000059604645, 0.0, 0.4000000059604645, 0.6000000238418579, 0.6000000238418579, 0.6000000238418579});fbc.set(145, 70, 218, Material.AIR);fbc.set(145, 71, 219, Material.AIR);fbc.set(142, 67, 219, Material.DIRT, 0, _fb);fbc.set(142, 70, 218, Material.AIR);fbc.set(142, 69, 221, Material.LONG_GRASS, 1, new double[]{0.09999999403953552, 0.0, 0.09999999403953552, 0.8999999761581421, 0.800000011920929, 0.8999999761581421});fbc.set(142, 69, 217, Material.AIR);fbc.set(142, 68, 220, BridgeMaterial.GRASS_BLOCK, 0, _fb);fbc.set(142, 71, 219, Material.AIR);fbc.set(143, 67, 220, Material.DIRT, 0, _fb);fbc.set(143, 68, 219, Material.OBSIDIAN, 0, _fb);fbc.set(143, 69, 218, Material.AIR);fbc.set(143, 70, 217, Material.AIR);fbc.set(143, 70, 221, Material.AIR);fbc.set(143, 71, 220, Material.AIR);fbc.set(144, 67, 217, Material.DIRT, 0, _fb);fbc.set(144, 67, 221, Material.DIRT, 0, _fb);fbc.set(144, 68, 218, Material.OBSIDIAN, 0, _fb);fbc.set(144, 69, 219, Material.AIR);fbc.set(144, 70, 220, Material.AIR);fbc.set(144, 71, 217, Material.AIR);fbc.set(144, 71, 221, Material.AIR);fbc.set(145, 67, 218, Material.DIRT, 0, _fb);fbc.set(145, 68, 217, BridgeMaterial.GRASS_BLOCK, 0, _fb);fbc.set(145, 68, 221, BridgeMaterial.GRASS_BLOCK, 0, _fb);fbc.set(145, 69, 220, Material.AIR);fbc.set(145, 70, 219, Material.AIR);fbc.set(145, 71, 218, Material.AIR);fbc.set(142, 68, 219, BridgeMaterial.GRASS_BLOCK, 0, _fb);fbc.set(142, 70, 217, Material.AIR);fbc.set(142, 67, 220, Material.DIRT, 0, _fb);fbc.set(142, 69, 218, Material.LONG_GRASS, 1, new double[]{0.09999999403953552, 0.0, 0.09999999403953552, 0.8999999761581421, 0.800000011920929, 0.8999999761581421});fbc.set(142, 70, 221, Material.AIR);fbc.set(142, 71, 220, Material.AIR);fbc.set(143, 67, 219, Material.DIRT, 0, _fb);fbc.set(143, 68, 220, BridgeMaterial.GRASS_BLOCK, 0, _fb);fbc.set(143, 69, 217, Material.AIR);fbc.set(143, 69, 221, Material.AIR);fbc.set(143, 70, 218, Material.AIR);fbc.set(143, 71, 219, Material.AIR);fbc.set(144, 67, 218, Material.DIRT, 0, _fb);fbc.set(144, 68, 217, BridgeMaterial.GRASS_BLOCK, 0, _fb);fbc.set(144, 68, 221, BridgeMaterial.GRASS_BLOCK, 0, _fb);fbc.set(144, 69, 220, Material.AIR);fbc.set(144, 70, 219, Material.AIR);fbc.set(144, 71, 218, Material.AIR);fbc.set(145, 67, 217, Material.DIRT, 0, _fb);fbc.set(145, 67, 221, Material.DIRT, 0, _fb);fbc.set(145, 68, 218, BridgeMaterial.GRASS_BLOCK, 0, _fb);fbc.set(145, 69, 219, Material.AIR);fbc.set(145, 70, 220, Material.AIR);fbc.set(145, 71, 217, Material.AIR);fbc.set(145, 71, 221, Material.AIR);InteractRayTracing rt = new CenteredInteractRayTracing(false, 144, 68, 218);rt.setBlockCache(fbc);TestRayTracing.runCoordinates(rt, new double[]{144.01901074886095, 70.62, 220.1221052415879, 144.07776715103876, 68.99423513239826, 219.0}, true, false, 0.0, false, "ingame");rt.cleanup(); fbc.cleanup();}
fbc.set(144, 69, 221, BridgeMaterial.TALL_GRASS, 1, new double[]{0.09999999403953552, 0.0, 0.09999999403953552, 0.8999999761581421, 0.800000011920929, 0.8999999761581421});fbc.set(144, 70, 218, Material.AIR);fbc.set(144, 71, 219, Material.AIR);fbc.set(145, 67, 220, Material.DIRT, 0, _fb);fbc.set(145, 68, 219, BridgeMaterial.GRASS_BLOCK, 0, _fb);fbc.set(145, 69, 218, Material.AIR);fbc.set(145, 70, 217, Material.AIR);fbc.set(145, 70, 221, Material.AIR);fbc.set(145, 71, 220, Material.AIR);fbc.set(142, 68, 217, BridgeMaterial.GRASS_BLOCK, 0, _fb);fbc.set(142, 68, 221, BridgeMaterial.GRASS_BLOCK, 0, _fb);fbc.set(142, 67, 218, Material.DIRT, 0, _fb);fbc.set(142, 69, 220, Material.AIR);fbc.set(142, 70, 219, Material.AIR);fbc.set(142, 71, 218, Material.AIR);fbc.set(143, 67, 217, Material.DIRT, 0, _fb);fbc.set(143, 67, 221, Material.DIRT, 0, _fb);fbc.set(143, 68, 218, Material.OBSIDIAN, 0, _fb);fbc.set(143, 69, 219, Material.AIR);fbc.set(143, 70, 220, Material.AIR);fbc.set(143, 71, 217, Material.AIR);fbc.set(143, 71, 221, Material.AIR);fbc.set(144, 67, 220, Material.DIRT, 0, _fb);fbc.set(144, 68, 219, Material.OBSIDIAN, 0, _fb);fbc.set(144, 69, 218, Material.AIR);fbc.set(144, 70, 217, Material.AIR);fbc.set(144, 70, 221, Material.AIR);fbc.set(144, 71, 220, Material.AIR);fbc.set(145, 67, 219, Material.DIRT, 0, _fb);fbc.set(145, 68, 220, BridgeMaterial.GRASS_BLOCK, 0, _fb);fbc.set(145, 69, 217, Material.AIR);fbc.set(145, 69, 221, Material.TORCH, 5, new double[]{0.4000000059604645, 0.0, 0.4000000059604645, 0.6000000238418579, 0.6000000238418579, 0.6000000238418579});fbc.set(145, 70, 218, Material.AIR);fbc.set(145, 71, 219, Material.AIR);fbc.set(142, 67, 219, Material.DIRT, 0, _fb);fbc.set(142, 70, 218, Material.AIR);fbc.set(142, 69, 221, BridgeMaterial.GRASS, 1, new double[]{0.09999999403953552, 0.0, 0.09999999403953552, 0.8999999761581421, 0.800000011920929, 0.8999999761581421});fbc.set(142, 69, 217, Material.AIR);fbc.set(142, 68, 220, BridgeMaterial.GRASS_BLOCK, 0, _fb);fbc.set(142, 71, 219, Material.AIR);fbc.set(143, 67, 220, Material.DIRT, 0, _fb);fbc.set(143, 68, 219, Material.OBSIDIAN, 0, _fb);fbc.set(143, 69, 218, Material.AIR);fbc.set(143, 70, 217, Material.AIR);fbc.set(143, 70, 221, Material.AIR);fbc.set(143, 71, 220, Material.AIR);fbc.set(144, 67, 217, Material.DIRT, 0, _fb);fbc.set(144, 67, 221, Material.DIRT, 0, _fb);fbc.set(144, 68, 218, Material.OBSIDIAN, 0, _fb);fbc.set(144, 69, 219, Material.AIR);fbc.set(144, 70, 220, Material.AIR);fbc.set(144, 71, 217, Material.AIR);fbc.set(144, 71, 221, Material.AIR);fbc.set(145, 67, 218, Material.DIRT, 0, _fb);fbc.set(145, 68, 217, BridgeMaterial.GRASS_BLOCK, 0, _fb);fbc.set(145, 68, 221, BridgeMaterial.GRASS_BLOCK, 0, _fb);fbc.set(145, 69, 220, Material.AIR);fbc.set(145, 70, 219, Material.AIR);fbc.set(145, 71, 218, Material.AIR);fbc.set(142, 68, 219, BridgeMaterial.GRASS_BLOCK, 0, _fb);fbc.set(142, 70, 217, Material.AIR);fbc.set(142, 67, 220, Material.DIRT, 0, _fb);fbc.set(142, 69, 218, BridgeMaterial.GRASS, 1, new double[]{0.09999999403953552, 0.0, 0.09999999403953552, 0.8999999761581421, 0.800000011920929, 0.8999999761581421});fbc.set(142, 70, 221, Material.AIR);fbc.set(142, 71, 220, Material.AIR);fbc.set(143, 67, 219, Material.DIRT, 0, _fb);fbc.set(143, 68, 220, BridgeMaterial.GRASS_BLOCK, 0, _fb);fbc.set(143, 69, 217, Material.AIR);fbc.set(143, 69, 221, Material.AIR);fbc.set(143, 70, 218, Material.AIR);fbc.set(143, 71, 219, Material.AIR);fbc.set(144, 67, 218, Material.DIRT, 0, _fb);fbc.set(144, 68, 217, BridgeMaterial.GRASS_BLOCK, 0, _fb);fbc.set(144, 68, 221, BridgeMaterial.GRASS_BLOCK, 0, _fb);fbc.set(144, 69, 220, Material.AIR);fbc.set(144, 70, 219, Material.AIR);fbc.set(144, 71, 218, Material.AIR);fbc.set(145, 67, 217, Material.DIRT, 0, _fb);fbc.set(145, 67, 221, Material.DIRT, 0, _fb);fbc.set(145, 68, 218, BridgeMaterial.GRASS_BLOCK, 0, _fb);fbc.set(145, 69, 219, Material.AIR);fbc.set(145, 70, 220, Material.AIR);fbc.set(145, 71, 217, Material.AIR);fbc.set(145, 71, 221, Material.AIR);InteractRayTracing rt = new CenteredInteractRayTracing(false, 144, 68, 218);rt.setBlockCache(fbc);TestRayTracing.runCoordinates(rt, new double[]{144.01901074886095, 70.62, 220.1221052415879, 144.07776715103876, 68.99423513239826, 219.0}, true, false, 0.0, false, "ingame");rt.cleanup(); fbc.cleanup();}
}
}