mirror of
https://github.com/NoCheatPlus/NoCheatPlus.git
synced 2024-09-27 14:13:11 +02:00
Don't add bluntly redundant block change entries.
Match vs. the last entry of existing entries for those coordinates. Seems to be better with piston retract events.
This commit is contained in:
parent
9a6a370f1d
commit
9dca93e650
@ -250,6 +250,24 @@ public class BlockChangeTracker {
|
||||
|| tick <= other.nextEntryTick && other.tick <= nextEntryTick;
|
||||
}
|
||||
|
||||
/**
|
||||
* Test for redundancy between this entry and the given data
|
||||
* (coordinates are not regarded, assuming handling the queue for the
|
||||
* same coordinates).
|
||||
*
|
||||
* @param tick
|
||||
* @param direction
|
||||
* @param previousState
|
||||
* @return
|
||||
*/
|
||||
public boolean isRedundant(final int tick, final Direction direction,
|
||||
final IBlockCacheNode previousState) {
|
||||
return tick == this.tick && direction == this.direction && (
|
||||
previousState == null && this.previousState == null
|
||||
|| previousState.equals(this.previousState)
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/** Change id/count, increasing with each entry added internally. */
|
||||
@ -438,47 +456,37 @@ public class BlockChangeTracker {
|
||||
*/
|
||||
private void addBlockChange(final long changeId, final int tick, final WorldNode worldNode,
|
||||
final int x, final int y, final int z, final Direction direction, final IBlockCacheNode previousState) {
|
||||
worldNode.lastChangeTick = tick;
|
||||
final BlockChangeEntry entry = new BlockChangeEntry(changeId, tick, x, y, z, direction, previousState);
|
||||
LinkedList<BlockChangeEntry> entries = worldNode.blocks.get(x, y, z, MoveOrder.END);
|
||||
ActivityNode activityNode = worldNode.getActivityNode(x, y, z, activityResolution);
|
||||
final ActivityNode activityNode = worldNode.getActivityNode(x, y, z, activityResolution);
|
||||
if (entries != null && !entries.isEmpty()) {
|
||||
// Lazy expiration check for this block.
|
||||
if (entries.getFirst().tick < tick - expirationAgeTicks) {
|
||||
final int expired = expireEntries(tick - expirationAgeTicks, entries);
|
||||
worldNode.size -= expired;
|
||||
activityNode.count -= expired;
|
||||
}
|
||||
// Re-check in case of invalidation.
|
||||
if (!entries.isEmpty()) {
|
||||
// Update the nextEntryTick for the last entry in the list.
|
||||
final BlockChangeEntry lastEntry = entries.getLast();
|
||||
if (lastEntry.isRedundant(tick, direction, previousState)) {
|
||||
// Do not add.
|
||||
return;
|
||||
}
|
||||
else {
|
||||
lastEntry.nextEntryTick = tick;
|
||||
}
|
||||
}
|
||||
// TODO: Other redundancy checks / simplifications for often changing states?
|
||||
}
|
||||
if (entries == null) {
|
||||
entries = new LinkedList<BlockChangeTracker.BlockChangeEntry>();
|
||||
worldNode.blocks.put(x, y, z, entries, MoveOrder.END); // Add to end.
|
||||
}
|
||||
else {
|
||||
// Lazy expiration check for this block.
|
||||
if (!entries.isEmpty()) {
|
||||
if (entries.getFirst().tick < tick - expirationAgeTicks) {
|
||||
final int expired = expireEntries(tick - expirationAgeTicks, entries);
|
||||
worldNode.size -= expired;
|
||||
activityNode.count -= expired;
|
||||
}
|
||||
// Re-check in case of invalidation.
|
||||
if (!entries.isEmpty()) {
|
||||
// Update the nextEntryTick for the last entry in the list.
|
||||
entries.getLast().nextEntryTick = tick;
|
||||
}
|
||||
}
|
||||
}
|
||||
/*
|
||||
* TODO: Prevent too fast changing states (of similar nature) to cause
|
||||
* slowed down checking (isOnGround). Means could be to search for past
|
||||
* states that exactly match the current state, within some timing
|
||||
* margin, and then increase the duration of validity for that past
|
||||
* entry instead of adding a new entry. Needs some care, to not have
|
||||
* that entry invalidated by tick, but could be interesting for the case
|
||||
* of tick-clock-driven piston/door setups, such as survivalfly-traps
|
||||
* and derp-o-matic machines (those could be detected by other means,
|
||||
* however NCP shouldn't impose such restrictions on servers by
|
||||
* default). Thinking of having to use often redundant physics events
|
||||
* (falling blocks?), this will probably be necessary to add, and this
|
||||
* kind of compressing mechanism could still be controlled by further
|
||||
* parameters (both configuration + always for physics).
|
||||
*/
|
||||
entries.add(entry); // Add latest to the end always.
|
||||
entries.add(new BlockChangeEntry(changeId, tick, x, y, z, direction, previousState)); // Add to end.
|
||||
activityNode.count ++;
|
||||
worldNode.size ++;
|
||||
worldNode.lastChangeTick = tick;
|
||||
//DebugUtil.debug("Add block change: " + x + "," + y + "," + z + " " + direction + " " + changeId); // TODO: REMOVE
|
||||
}
|
||||
|
||||
|
@ -172,6 +172,21 @@ public abstract class BlockCache {
|
||||
fetched |= FETCHED_BOUNDS;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(final Object obj) {
|
||||
if (obj instanceof IBlockCacheNode) {
|
||||
final IBlockCacheNode other = (IBlockCacheNode) obj;
|
||||
return id == other.getId()
|
||||
&& (!isDataFetched() && !other.isDataFetched()
|
||||
|| isDataFetched() && other.isDataFetched() && data == other.getData())
|
||||
&& (!isBoundsFetched() && !other.isBoundsFetched()
|
||||
|| isBoundsFetched() && other.isBoundsFetched()
|
||||
&& BlockProperties.isSameShape(bounds, other.getBounds())
|
||||
);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Instance
|
||||
|
@ -3854,7 +3854,7 @@ public class BlockProperties {
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the bounds are the same. No null checks.
|
||||
* Check if the bounds are the same. With null checks.
|
||||
*
|
||||
* @param bounds1
|
||||
* the bounds1
|
||||
@ -3865,6 +3865,11 @@ public class BlockProperties {
|
||||
public static final boolean isSameShape(final double[] bounds1, final double[] bounds2) {
|
||||
// TODO: further exclude simple full shape blocks, or confine to itchy block types
|
||||
// TODO: make flags for it.
|
||||
if (bounds1 == null || bounds2 == null) {
|
||||
if (bounds1 != null || bounds2 != null) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
// Allow as ground for differing shapes.
|
||||
for (int i = 0; i < 6; i++) {
|
||||
if (bounds1[i] != bounds2[i]) {
|
||||
|
Loading…
Reference in New Issue
Block a user