Add access methods for getting a BlockChangeEntry matching flags.

(Slime blocks ahead, somehow.)
This commit is contained in:
asofold 2016-12-07 00:34:40 +01:00
parent 0cd07d2f2a
commit 5afcfdea96
2 changed files with 111 additions and 4 deletions

View File

@ -564,7 +564,52 @@ public class BlockChangeTracker {
final LinkedList<BlockChangeEntry> entries = getValidBlockChangeEntries(tick, worldNode, x, y, z);
if (entries != null) {
for (final BlockChangeEntry entry : entries) {
if (ref == null || ref.canUpdateWith(entry) && (direction == null || entry.direction == direction)) {
if (ref == null
|| ref.canUpdateWith(entry)
&& (direction == null || entry.direction == direction)) {
return entry;
}
}
}
return null;
}
/**
* Query past block states and moved blocks, including direction of moving.
*
* @param ref
* Reference for checking the validity of BlockChangeEntry
* instances. No changes are made to the passed instance,
* canUpdateWith is called. Pass null to skip further validation.
* @param tick
* The current tick. Used for lazy expiration.
* @param worldId
* @param x
* Block Coordinates.
* @param y
* @param z
* @param direction
* Desired direction of a moved block. Pass null to ignore
* direction.
* @param matchFlags
* Only blocks having previous states that have any flags in
* common with matchFlags are considered for output. If
* matchFlags is smaller than zero, the parameter is ignored.
* @return The matching entry, or null if there is no matching entry.
*/
public BlockChangeEntry getBlockChangeEntryMatchFlags(final BlockChangeReference ref, final int tick,
final UUID worldId, final int x, final int y, final int z, final Direction direction,
final long matchFlags) {
final WorldNode worldNode = getValidWorldNode(tick, worldId);
if (worldNode == null) {
return null;
}
// TODO: Might add some policy (start at age, oldest first, newest first).
final LinkedList<BlockChangeEntry> entries = getValidBlockChangeEntries(tick, worldNode, x, y, z);
if (entries != null) {
for (final BlockChangeEntry entry : entries) {
if ((ref == null || ref.canUpdateWith(entry) && (direction == null || entry.direction == direction))
&& (matchFlags < 0 || (matchFlags & BlockProperties.getBlockFlags(entry.previousState.getId())) != 0)) {
return entry;
}
}

View File

@ -1082,8 +1082,8 @@ public class RichBoundsLocation implements IGetBukkitLocation, IGetBlockPosition
* The (always positive) distance to cover.
* @return Returns true, iff an entry was found.
*/
public boolean matchBlockChange(final BlockChangeTracker blockChangeTracker, final BlockChangeReference ref, final Direction direction, final double coverDistance) {
// TODO: update span instead !
public boolean matchBlockChange(final BlockChangeTracker blockChangeTracker, final BlockChangeReference ref,
final Direction direction, final double coverDistance) {
final int tick = TickTask.getTick();
final UUID worldId = world.getUID();
final int iMinX = Location.locToBlock(minX);
@ -1096,7 +1096,69 @@ public class RichBoundsLocation implements IGetBukkitLocation, IGetBlockPosition
for (int x = iMinX; x <= iMaxX; x++) {
for (int z = iMinZ; z <= iMaxZ; z++) {
for (int y = iMinY; y <= iMaxY; y++) {
final BlockChangeEntry entry = blockChangeTracker.getBlockChangeEntry(ref, tick, worldId, x, y, z, direction);
final BlockChangeEntry entry = blockChangeTracker.getBlockChangeEntry(ref, tick, worldId,
x, y, z, direction);
if (entry != null && (minEntry == null || entry.id < minEntry.id)) {
// Check vs. coverDistance, exclude cases where the piston can't push that far.
if (coverDistance > 0.0 && coversDistance(x, y, z, direction, coverDistance)) {
minEntry = entry;
}
}
}
}
}
if (minEntry == null) {
return false;
}
else {
ref.updateSpan(minEntry);
return true;
}
}
/**
* Check for tracked block changes, having moved a block into a certain
* direction, using the full bounding box (pistons), only regarding blocks
* having flags in common with matchFlags. BlockChangeReference.updateSpan
* is called with the earliest entry found (updateFinal has to be called
* extra). This is an opportunistic version without any consistency checking
* done, just updating the span by the earliest entry found.
*
* @param blockChangeTracker
* the block change tracker
* @param ref
* the ref
* @param direction
* the direction
* @param coverDistance
* The (always positive) distance to cover.
* @param matchFlags
* Only blocks with past states having any flags in common with
* matchFlags. If matchFlags is smaller than zero, the parameter
* is ignored.
* @return Returns true, iff an entry was found.
*/
public boolean matchBlockChangeMatchFlags(final BlockChangeTracker blockChangeTracker,
final BlockChangeReference ref, final Direction direction, final double coverDistance,
final long matchFlags) {
/*
* TODO: Not sure with code duplication. Is it better to run
* BlockChangeTracker.getBlockChangeMatchFlags for the other method too?
*/
final int tick = TickTask.getTick();
final UUID worldId = world.getUID();
final int iMinX = Location.locToBlock(minX);
final int iMaxX = Location.locToBlock(maxX);
final int iMinY = Location.locToBlock(minY);
final int iMaxY = Location.locToBlock(maxY);
final int iMinZ = Location.locToBlock(minZ);
final int iMaxZ = Location.locToBlock(maxZ);
BlockChangeEntry minEntry = null;
for (int x = iMinX; x <= iMaxX; x++) {
for (int z = iMinZ; z <= iMaxZ; z++) {
for (int y = iMinY; y <= iMaxY; y++) {
final BlockChangeEntry entry = blockChangeTracker.getBlockChangeEntryMatchFlags(
ref, tick, worldId, x, y, z, direction, matchFlags);
if (entry != null && (minEntry == null || entry.id < minEntry.id)) {
// Check vs. coverDistance, exclude cases where the piston can't push that far.
if (coverDistance > 0.0 && coversDistance(x, y, z, direction, coverDistance)) {