mirror of
https://github.com/NoCheatPlus/NoCheatPlus.git
synced 2025-03-09 21:19:07 +01:00
Add framework for (debug-) logging map parts with ray-tracing / cuboids.
Not very efficient in terms of code-output, but enabling us to log test cases for visible (and potentially passable too), using real-life examples. * Add the capability to log a FakeBlockCache as java code. * Add utility to record map parts (cuboid, ray-tracing with margin) to a FakeBlockCache. Missing: * Actually log stuff (visible).
This commit is contained in:
parent
9e7736963f
commit
aa147f692b
@ -70,7 +70,7 @@ public class Visible extends Check {
|
||||
// Initialize.
|
||||
blockCache.setAccess(loc.getWorld());
|
||||
rayTracing.setBlockCache(blockCache);
|
||||
collides = checkRayTracing(eyeX, eyeY, eyeZ, direction.getX(), direction.getY(), direction.getZ(), blockX, blockY, blockZ, face, tags);
|
||||
collides = checkRayTracing(eyeX, eyeY, eyeZ, direction.getX(), direction.getY(), direction.getZ(), blockX, blockY, blockZ, face, tags, data.debug);
|
||||
// Cleanup.
|
||||
rayTracing.cleanup();
|
||||
blockCache.cleanup();
|
||||
@ -107,7 +107,7 @@ public class Visible extends Check {
|
||||
return cancel;
|
||||
}
|
||||
|
||||
private boolean checkRayTracing(final double eyeX, final double eyeY, final double eyeZ, final double dirX, final double dirY, final double dirZ, final int blockX, final int blockY, final int blockZ, final BlockFace face, final List<String> tags){
|
||||
private boolean checkRayTracing(final double eyeX, final double eyeY, final double eyeZ, final double dirX, final double dirY, final double dirZ, final int blockX, final int blockY, final int blockZ, final BlockFace face, final List<String> tags, final boolean debug){
|
||||
// Block of eyes.
|
||||
final int eyeBlockX = Location.locToBlock(eyeX);
|
||||
final int eyeBlockY = Location.locToBlock(eyeY);
|
||||
@ -170,17 +170,27 @@ public class Visible extends Check {
|
||||
// Perform ray-tracing.
|
||||
rayTracing.set(eyeX, eyeY, eyeZ, collideX, collideY, collideZ, blockX, blockY, blockZ);
|
||||
rayTracing.loop();
|
||||
|
||||
final boolean collides;
|
||||
if (rayTracing.collides()) {
|
||||
tags.add("raytracing");
|
||||
return true;
|
||||
collides = true;
|
||||
}
|
||||
else if (rayTracing.getStepsDone() > rayTracing.getMaxSteps()) {
|
||||
tags.add("raytracing_maxsteps");
|
||||
return true;
|
||||
collides = true;
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
collides = false;
|
||||
}
|
||||
if (collides && debug) {
|
||||
/*
|
||||
* Consider using a configuration setting for extended debugging
|
||||
* (e.g. make DEBUG_LEVEL accessible by API and config).
|
||||
*/
|
||||
// TODO: public static void InteractRayTracing.logTestCase(...).
|
||||
}
|
||||
return collides;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -289,4 +289,32 @@ public class DebugUtil {
|
||||
NCPAPIProvider.getNoCheatPlusAPI().getLogManager().debug(Streams.TRACE_FILE, builder.toString());
|
||||
}
|
||||
|
||||
public static String toJava(final double[] doubles) {
|
||||
final StringBuilder builder = new StringBuilder(20 + doubles.length * 20);
|
||||
toJava(doubles, builder);
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param doubles
|
||||
* @param builder
|
||||
*/
|
||||
public static void toJava(final double[] doubles, final StringBuilder builder) {
|
||||
if (doubles == null) {
|
||||
builder.append("null");
|
||||
return;
|
||||
}
|
||||
builder.append("new double[] {");
|
||||
if (doubles.length > 0) {
|
||||
builder.append(doubles[0]);
|
||||
}
|
||||
for (int i = 1; i < doubles.length; i++) {
|
||||
builder.append(", " + doubles[i]);
|
||||
}
|
||||
builder.append("}");
|
||||
}
|
||||
|
||||
// TODO: method to log raytracing/recorder directly with prefix message.
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,96 @@
|
||||
package fr.neatmonster.nocheatplus.logging.debug;
|
||||
|
||||
import fr.neatmonster.nocheatplus.utilities.BlockCache;
|
||||
import fr.neatmonster.nocheatplus.utilities.FakeBlockCache;
|
||||
import fr.neatmonster.nocheatplus.utilities.RayTracing;
|
||||
|
||||
/**
|
||||
* Record blocks along a ray (and potentially other). Changes to blocks are not
|
||||
* recorded.
|
||||
*
|
||||
* @author asofold
|
||||
*
|
||||
*/
|
||||
public class MapRecorder {
|
||||
|
||||
/**
|
||||
* Record all blocks including shapes with margin, using ray-tracing.<br>
|
||||
* No cleanup is done here. Might want to set maxSteps (the current
|
||||
* implementation should scale reliably with distances).
|
||||
*
|
||||
* @author asofold
|
||||
*
|
||||
*/
|
||||
protected static class TraceRecorder extends RayTracing {
|
||||
|
||||
private final BlockCache worldAccess;
|
||||
private final FakeBlockCache recorder;
|
||||
private final int margin; // TODO: separated y margin(s) ?
|
||||
|
||||
public TraceRecorder(BlockCache worldAccess, FakeBlockCache recorder, int margin) {
|
||||
this.worldAccess = worldAccess;
|
||||
this.recorder = recorder;
|
||||
this.margin = margin;
|
||||
// TODO: maxSteps ? [In some cases it might be better with limiting recording by the steps done.]
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean step(int blockX, int blockY, int blockZ, double oX, double oY, double oZ, double dT, boolean isPrimary) {
|
||||
if (margin > 0) {
|
||||
recordCuboid(worldAccess, recorder, blockX - margin, blockY - margin, blockZ - margin, blockX + margin, blockY + margin, blockZ + margin);
|
||||
} else {
|
||||
recorder.set(blockX, blockY, blockZ, worldAccess.getTypeId(blockX, blockY, blockZ), worldAccess.getData(blockX, blockY, blockZ), worldAccess.getBounds(blockX, blockY, blockZ));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Record the entire cuboid. Already present entries are not updated.
|
||||
* @param worldAccess
|
||||
* @param recorder
|
||||
* @param xMin
|
||||
* @param yMin
|
||||
* @param zMin
|
||||
* @param xMax
|
||||
* @param yMax
|
||||
* @param zMax
|
||||
*/
|
||||
public static void recordCuboid(final BlockCache worldAccess, final FakeBlockCache recorder,
|
||||
final int xMin, final int yMin, final int zMin, final int xMax, final int yMax, final int zMax) {
|
||||
for (int x = xMin; x <= xMax; x ++) {
|
||||
for (int z = zMin; z <= zMax; z ++) {
|
||||
for (int y = yMin; y <= yMax; y ++) {
|
||||
if (!recorder.hasIdEntry(x, y, z)) {
|
||||
// Use get... methods for efficiency in certain use cases..
|
||||
recorder.set(x, y, z, worldAccess.getTypeId(x, y, z), worldAccess.getData(x, y, z), worldAccess.getBounds(x, y, z));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Record blocks along a ray.
|
||||
* @param worldAccess
|
||||
* @param recorder
|
||||
* @param x0
|
||||
* @param y0
|
||||
* @param z0
|
||||
* @param x1
|
||||
* @param y1
|
||||
* @param z1
|
||||
* @param margin If greater than 0, a cuboid is recorded (2 * margin + 1 length per side).
|
||||
* @param maxSteps
|
||||
*/
|
||||
public static void recordTrace(final BlockCache worldAccess, final FakeBlockCache recorder,
|
||||
final double x0, final double y0, final double z0, final double x1, final double y1, final double z1,
|
||||
final int margin, final int maxSteps){
|
||||
final TraceRecorder traceRecorder = new TraceRecorder(worldAccess, recorder, margin);
|
||||
traceRecorder.setMaxSteps(maxSteps);
|
||||
traceRecorder.set(x0, y0, z0, x1, y1, z1);
|
||||
traceRecorder.loop();
|
||||
}
|
||||
|
||||
}
|
@ -1,10 +1,14 @@
|
||||
package fr.neatmonster.nocheatplus.utilities;
|
||||
|
||||
import java.util.Iterator;
|
||||
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.entity.Entity;
|
||||
|
||||
import fr.neatmonster.nocheatplus.logging.debug.DebugUtil;
|
||||
import fr.neatmonster.nocheatplus.utilities.ds.CoordMap;
|
||||
import fr.neatmonster.nocheatplus.utilities.ds.CoordMap.Entry;
|
||||
|
||||
/**
|
||||
* Stand-alone BlockCache for setting data by access methods, for testing purposes.
|
||||
@ -88,10 +92,32 @@ public class FakeBlockCache extends BlockCache {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Fill the entire cuboid.
|
||||
* @param x1
|
||||
* @param y1
|
||||
* @param z1
|
||||
* @param x2
|
||||
* @param y2
|
||||
* @param z2
|
||||
* @param type
|
||||
*/
|
||||
public void fill(int x1, int y1, int z1, int x2, int y2, int z2, Material type) {
|
||||
fill(x1, y1, z1, x2, y2, z2, BlockProperties.getId(type), 0, new double[]{0.0, 0.0, 0.0, 1.0, 1.0, 1.0});
|
||||
}
|
||||
|
||||
/**
|
||||
* Fill the entire cuboid.
|
||||
* @param x1
|
||||
* @param y1
|
||||
* @param z1
|
||||
* @param x2
|
||||
* @param y2
|
||||
* @param z2
|
||||
* @param typeId
|
||||
* @param data
|
||||
* @param bounds
|
||||
*/
|
||||
public void fill(int x1, int y1, int z1, int x2, int y2, int z2, int typeId, int data, double[] bounds) {
|
||||
for (int x = x1; x <= x2; x++) {
|
||||
for (int y = y1; y <= y2; y ++) {
|
||||
@ -102,10 +128,32 @@ public class FakeBlockCache extends BlockCache {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Horizontal walls.
|
||||
* @param x1
|
||||
* @param y1
|
||||
* @param z1
|
||||
* @param x2
|
||||
* @param y2
|
||||
* @param z2
|
||||
* @param type
|
||||
*/
|
||||
public void walls(int x1, int y1, int z1, int x2, int y2, int z2, Material type) {
|
||||
walls(x1, y1, z1, x2, y2, z2, BlockProperties.getId(type), 0, new double[]{0.0, 0.0, 0.0, 1.0, 1.0, 1.0});
|
||||
}
|
||||
|
||||
/**
|
||||
* Horizontal walls.
|
||||
* @param x1
|
||||
* @param y1
|
||||
* @param z1
|
||||
* @param x2
|
||||
* @param y2
|
||||
* @param z2
|
||||
* @param typeId
|
||||
* @param data
|
||||
* @param bounds
|
||||
*/
|
||||
public void walls(int x1, int y1, int z1, int x2, int y2, int z2, int typeId, int data, double[] bounds) {
|
||||
for (int x = x1; x <= x2; x++) {
|
||||
for (int y = y1; y <= y2; y ++) {
|
||||
@ -118,10 +166,32 @@ public class FakeBlockCache extends BlockCache {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Walls, floor, ceiling.
|
||||
* @param x1
|
||||
* @param y1
|
||||
* @param z1
|
||||
* @param x2
|
||||
* @param y2
|
||||
* @param z2
|
||||
* @param type
|
||||
*/
|
||||
public void room(int x1, int y1, int z1, int x2, int y2, int z2, Material type) {
|
||||
room(x1, y1, z1, x2, y2, z2, BlockProperties.getId(type), 0, new double[]{0.0, 0.0, 0.0, 1.0, 1.0, 1.0});
|
||||
}
|
||||
|
||||
/**
|
||||
* Walls, floor, ceiling.
|
||||
* @param x1
|
||||
* @param y1
|
||||
* @param z1
|
||||
* @param x2
|
||||
* @param y2
|
||||
* @param z2
|
||||
* @param typeId
|
||||
* @param data
|
||||
* @param bounds
|
||||
*/
|
||||
public void room(int x1, int y1, int z1, int x2, int y2, int z2, int typeId, int data, double[] bounds) {
|
||||
for (int x = x1; x <= x2; x++) {
|
||||
for (int y = y1; y <= y2; y ++) {
|
||||
@ -134,6 +204,53 @@ public class FakeBlockCache extends BlockCache {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test if any an id is set for this block position.
|
||||
* @param x
|
||||
* @param y
|
||||
* @param z
|
||||
* @return
|
||||
*/
|
||||
public boolean hasIdEntry(int x, int y, int z) {
|
||||
return idMapStored.contains(x, y, z);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a line of java code to construct a new FakeBlockCache with the same content (no newlines).
|
||||
* @param builder
|
||||
* @param fbcName Variable name of the FakeBlockCache instance.
|
||||
*/
|
||||
public void toJava(final StringBuilder builder, final String fbcName) {
|
||||
builder.append("FakeBlockCache " + fbcName + " = new FakeBlockCache();");
|
||||
// Assume id is always set.
|
||||
final Iterator<Entry<Integer>> it = idMapStored.iterator();
|
||||
final int airId = BlockProperties.getId(Material.AIR);
|
||||
while (it.hasNext()) {
|
||||
Entry<Integer> entry = it.next();
|
||||
final int x = entry.getX();
|
||||
final int y = entry.getY();
|
||||
final int z = entry.getZ();
|
||||
final Integer id = entry.getValue();
|
||||
if (id == airId) {
|
||||
builder.append(fbcName + ".set(" + x + ", " + y + ", " + z + ", " + id + ");");
|
||||
} else {
|
||||
final Integer data = dataMapStored.get(x, y, z);
|
||||
final double[] bounds = boundsMapStored.get(x, y, z);
|
||||
if (bounds == null) {
|
||||
if (data == null) { // Consider 0 too.
|
||||
builder.append(fbcName + ".set(" + x + ", " + y + ", " + z + ", " + id + ");");
|
||||
} else {
|
||||
builder.append(fbcName + ".set(" + x + ", " + y + ", " + z + ", " + id + ", " + data + ");");
|
||||
}
|
||||
} else {
|
||||
builder.append(fbcName + ".set(" + x + ", " + y + ", " + z + ", " + id + ", " + data + ", ");
|
||||
DebugUtil.toJava(bounds, builder);
|
||||
builder.append(");");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setAccess(World world) {
|
||||
// Ignore.
|
||||
@ -173,4 +290,12 @@ public class FakeBlockCache extends BlockCache {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cleanup() {
|
||||
super.cleanup();
|
||||
idMapStored.clear();
|
||||
dataMapStored.clear();
|
||||
boundsMapStored.clear();
|
||||
}
|
||||
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user