mirror of
https://github.com/plexusorg/Plex-FAWE.git
synced 2025-06-12 20:43:54 +00:00
Implement remove on set/iter views of BlockMap
Fixes #1354. (cherry picked from commit 637da62e34e676015aa7fbad490cf6f033e55b89)
This commit is contained in:
@ -19,7 +19,6 @@
|
||||
|
||||
package com.sk89q.worldedit.util.collection;
|
||||
|
||||
import com.google.common.collect.AbstractIterator;
|
||||
import com.sk89q.worldedit.math.BlockVector3;
|
||||
import com.sk89q.worldedit.world.block.BaseBlock;
|
||||
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
|
||||
@ -36,6 +35,7 @@ import java.util.AbstractSet;
|
||||
import java.util.Collection;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import java.util.NoSuchElementException;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.function.BiConsumer;
|
||||
@ -43,6 +43,7 @@ import java.util.function.BiFunction;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkState;
|
||||
import static com.sk89q.worldedit.math.BitMath.fixSign;
|
||||
import static com.sk89q.worldedit.math.BitMath.mask;
|
||||
|
||||
@ -245,26 +246,65 @@ public class BlockMap<V> extends AbstractMap<BlockVector3, V> {
|
||||
entrySet = es = new AbstractSet<Entry<BlockVector3, V>>() {
|
||||
@Override
|
||||
public Iterator<Entry<BlockVector3, V>> iterator() {
|
||||
return new AbstractIterator<Entry<BlockVector3, V>>() {
|
||||
return new Iterator<Entry<BlockVector3,V>>() {
|
||||
|
||||
private final ObjectIterator<Long2ObjectMap.Entry<Int2ObjectMap<V>>> primaryIterator
|
||||
= Long2ObjectMaps.fastIterator(maps);
|
||||
private long currentGroupKey;
|
||||
private Long2ObjectMap.Entry<Int2ObjectMap<V>> currentPrimaryEntry;
|
||||
private ObjectIterator<Int2ObjectMap.Entry<V>> secondaryIterator;
|
||||
private boolean finished;
|
||||
private LazyEntry next;
|
||||
|
||||
@Override
|
||||
protected Entry<BlockVector3, V> computeNext() {
|
||||
public boolean hasNext() {
|
||||
if (finished) {
|
||||
return false;
|
||||
}
|
||||
if (next == null) {
|
||||
LazyEntry proposedNext = computeNext();
|
||||
if (proposedNext == null) {
|
||||
finished = true;
|
||||
return false;
|
||||
}
|
||||
next = proposedNext;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private LazyEntry computeNext() {
|
||||
if (secondaryIterator == null || !secondaryIterator.hasNext()) {
|
||||
if (!primaryIterator.hasNext()) {
|
||||
return endOfData();
|
||||
return null;
|
||||
}
|
||||
|
||||
Long2ObjectMap.Entry<Int2ObjectMap<V>> next = primaryIterator.next();
|
||||
currentGroupKey = next.getLongKey();
|
||||
secondaryIterator = Int2ObjectMaps.fastIterator(next.getValue());
|
||||
currentPrimaryEntry = primaryIterator.next();
|
||||
secondaryIterator = Int2ObjectMaps.fastIterator(currentPrimaryEntry.getValue());
|
||||
// be paranoid
|
||||
checkState(secondaryIterator.hasNext(),
|
||||
"Should not have an empty map entry, it should have been removed!");
|
||||
}
|
||||
Int2ObjectMap.Entry<V> next = secondaryIterator.next();
|
||||
return new LazyEntry(currentGroupKey, next.getIntKey(), next.getValue());
|
||||
return new LazyEntry(currentPrimaryEntry.getLongKey(), next.getIntKey(), next.getValue());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Entry<BlockVector3, V> next() {
|
||||
if (!hasNext()) {
|
||||
throw new NoSuchElementException();
|
||||
}
|
||||
LazyEntry tmp = next;
|
||||
next = null;
|
||||
return tmp;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove() {
|
||||
secondaryIterator.remove();
|
||||
// ensure invariants hold
|
||||
if (currentPrimaryEntry.getValue().isEmpty()) {
|
||||
// the remove call cleared this map. call remove on the primary iter
|
||||
primaryIterator.remove();
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
@ -364,13 +404,14 @@ public class BlockMap<V> extends AbstractMap<BlockVector3, V> {
|
||||
@Override
|
||||
public V remove(Object key) {
|
||||
BlockVector3 vec = (BlockVector3) key;
|
||||
Int2ObjectMap<V> activeMap = maps.get(toGroupKey(vec));
|
||||
long groupKey = toGroupKey(vec);
|
||||
Int2ObjectMap<V> activeMap = maps.get(groupKey);
|
||||
if (activeMap == null) {
|
||||
return null;
|
||||
}
|
||||
V removed = activeMap.remove(toInnerKey(vec));
|
||||
if (activeMap.isEmpty()) {
|
||||
maps.remove(toGroupKey(vec));
|
||||
maps.remove(groupKey);
|
||||
}
|
||||
return removed;
|
||||
}
|
||||
@ -429,7 +470,9 @@ public class BlockMap<V> extends AbstractMap<BlockVector3, V> {
|
||||
}
|
||||
if (o instanceof BlockMap) {
|
||||
// optimize by skipping entry translations:
|
||||
return maps.equals(((BlockMap) o).maps);
|
||||
@SuppressWarnings("unchecked")
|
||||
BlockMap<V> other = (BlockMap<V>) o;
|
||||
return maps.equals(other.maps);
|
||||
}
|
||||
return super.equals(o);
|
||||
}
|
||||
|
@ -91,6 +91,7 @@ class Int2BaseBlockMap extends AbstractInt2ObjectMap<BaseBlock> {
|
||||
= Int2IntMaps.fastIterator(commonMap);
|
||||
private final ObjectIterator<Entry<BaseBlock>> uncommonIter
|
||||
= Int2ObjectMaps.fastIterator(uncommonMap);
|
||||
private boolean lastNextFromCommon = false;
|
||||
|
||||
@Override
|
||||
public boolean hasNext() {
|
||||
@ -101,15 +102,26 @@ class Int2BaseBlockMap extends AbstractInt2ObjectMap<BaseBlock> {
|
||||
public Entry<BaseBlock> next() {
|
||||
if (commonIter.hasNext()) {
|
||||
Int2IntMap.Entry e = commonIter.next();
|
||||
lastNextFromCommon = true;
|
||||
return new BasicEntry<>(
|
||||
e.getIntKey(), assumeAsBlock(e.getIntValue())
|
||||
);
|
||||
}
|
||||
if (uncommonIter.hasNext()) {
|
||||
lastNextFromCommon = false;
|
||||
return uncommonIter.next();
|
||||
}
|
||||
throw new NoSuchElementException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove() {
|
||||
if (lastNextFromCommon) {
|
||||
commonIter.remove();
|
||||
} else {
|
||||
uncommonIter.remove();
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user