upstream changes

This commit is contained in:
MattBDev
2019-08-15 15:21:24 -04:00
parent 7a57a5dd8c
commit cbbe8b5dfa
36 changed files with 1573 additions and 266 deletions

View File

@ -19,8 +19,7 @@
package com.sk89q.worldedit.extent.reorder;
import com.google.common.collect.Table;
import com.google.common.collect.TreeBasedTable;
import com.google.common.collect.ImmutableSortedSet;
import com.sk89q.worldedit.WorldEditException;
import com.sk89q.worldedit.extent.AbstractBufferingExtent;
import com.sk89q.worldedit.extent.Extent;
@ -28,15 +27,14 @@ import com.sk89q.worldedit.function.operation.Operation;
import com.sk89q.worldedit.function.operation.RunContext;
import com.sk89q.worldedit.math.BlockVector2;
import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.math.RegionOptimizedComparator;
import com.sk89q.worldedit.util.collection.BlockMap;
import com.sk89q.worldedit.world.block.BaseBlock;
import com.sk89q.worldedit.world.block.BlockStateHolder;
import java.util.Comparator;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
/**
* A special extent that batches changes into Minecraft chunks. This helps
@ -46,17 +44,7 @@ import java.util.Set;
*/
public class ChunkBatchingExtent extends AbstractBufferingExtent {
/**
* Comparator optimized for sorting chunks by the region file they reside
* in. This allows for file caches to be used while loading the chunk.
*/
private static final Comparator<BlockVector2> REGION_OPTIMIZED_SORT =
Comparator.comparing((BlockVector2 vec) -> vec.shr(5), BlockVector2.COMPARING_GRID_ARRANGEMENT)
.thenComparing(BlockVector2.COMPARING_GRID_ARRANGEMENT);
private final Table<BlockVector2, BlockVector3, BaseBlock> batches =
TreeBasedTable.create(REGION_OPTIMIZED_SORT, BlockVector3.sortByCoordsYzx());
private final Set<BlockVector3> containedBlocks = new HashSet<>();
private final BlockMap blockMap = BlockMap.create();
private boolean enabled;
public ChunkBatchingExtent(Extent extent) {
@ -80,32 +68,20 @@ public class ChunkBatchingExtent extends AbstractBufferingExtent {
return enabled;
}
private BlockVector2 getChunkPos(BlockVector3 location) {
return location.shr(4).toBlockVector2();
}
private BlockVector3 getInChunkPos(BlockVector3 location) {
return BlockVector3.at(location.getX() & 15, location.getY(), location.getZ() & 15);
}
@Override
public <B extends BlockStateHolder<B>> boolean setBlock(BlockVector3 location, B block) throws WorldEditException {
if (!enabled) {
return setDelegateBlock(location, block);
}
BlockVector2 chunkPos = getChunkPos(location);
BlockVector3 inChunkPos = getInChunkPos(location);
batches.put(chunkPos, inChunkPos, block.toBaseBlock());
containedBlocks.add(location);
blockMap.put(location, block.toBaseBlock());
return true;
}
@Override
protected Optional<BaseBlock> getBufferedBlock(BlockVector3 position) {
if (!containedBlocks.contains(position)) {
return Optional.empty();
}
return Optional.of(batches.get(getChunkPos(position), getInChunkPos(position)));
return Optional.ofNullable(blockMap.get(position));
}
@Override
protected Operation commitBefore() {
if (!commitRequired()) {
@ -114,24 +90,21 @@ public class ChunkBatchingExtent extends AbstractBufferingExtent {
return new Operation() {
// we get modified between create/resume -- only create this on resume to prevent CME
private Iterator<Map.Entry<BlockVector2, Map<BlockVector3, BaseBlock>>> batchIterator;
private Iterator<BlockVector3> iterator;
@Override
public Operation resume(RunContext run) throws WorldEditException {
if (batchIterator == null) {
batchIterator = batches.rowMap().entrySet().iterator();
if (iterator == null) {
iterator = ImmutableSortedSet.copyOf(RegionOptimizedComparator.INSTANCE,
blockMap.keySet()).iterator();
}
if (!batchIterator.hasNext()) {
return null;
while (iterator.hasNext()) {
BlockVector3 position = iterator.next();
BaseBlock block = blockMap.get(position);
getExtent().setBlock(position, block);
}
Map.Entry<BlockVector2, Map<BlockVector3, BaseBlock>> next = batchIterator.next();
BlockVector3 chunkOffset = next.getKey().toBlockVector3().shl(4);
for (Map.Entry<BlockVector3, BaseBlock> block : next.getValue().entrySet()) {
getExtent().setBlock(block.getKey().add(chunkOffset), block.getValue());
containedBlocks.remove(block.getKey());
}
batchIterator.remove();
return this;
blockMap.clear();
return null;
}
@Override

View File

@ -24,23 +24,23 @@ import com.sk89q.worldedit.extent.AbstractBufferingExtent;
import com.sk89q.worldedit.extent.Extent;
import com.sk89q.worldedit.function.operation.Operation;
import com.sk89q.worldedit.function.operation.OperationQueue;
import com.sk89q.worldedit.function.operation.SetLocatedBlocks;
import com.sk89q.worldedit.function.operation.RunContext;
import com.sk89q.worldedit.function.operation.SetBlockMap;
import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.util.collection.LocatedBlockList;
import com.sk89q.worldedit.util.collection.BlockMap;
import com.sk89q.worldedit.world.block.BaseBlock;
import com.sk89q.worldedit.world.block.BlockCategories;
import com.sk89q.worldedit.world.block.BlockState;
import com.sk89q.worldedit.world.block.BlockStateHolder;
import com.sk89q.worldedit.world.block.BlockType;
import com.sk89q.worldedit.world.block.BlockTypes;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
/**
* Re-orders blocks into several stages.
@ -142,8 +142,7 @@ public class MultiStageReorder extends AbstractBufferingExtent implements Reorde
priorityMap.put(BlockTypes.MOVING_PISTON, PlacementPriority.FINAL);
}
private final Set<BlockVector3> containedBlocks = new HashSet<>();
private Map<PlacementPriority, LocatedBlockList> stages = new HashMap<>();
private Map<PlacementPriority, BlockMap> stages = new HashMap<>();
private boolean enabled;
@ -177,7 +176,7 @@ public class MultiStageReorder extends AbstractBufferingExtent implements Reorde
this.enabled = enabled;
for (PlacementPriority priority : PlacementPriority.values()) {
stages.put(priority, new LocatedBlockList());
stages.put(priority, BlockMap.create());
}
}
@ -219,7 +218,7 @@ public class MultiStageReorder extends AbstractBufferingExtent implements Reorde
return setDelegateBlock(location, block);
}
BlockState existing = getBlock(location);
BlockState existing = getExtent().getBlock(location);
PlacementPriority priority = getPlacementPriority(block);
PlacementPriority srcPriority = getPlacementPriority(existing);
@ -228,13 +227,13 @@ public class MultiStageReorder extends AbstractBufferingExtent implements Reorde
switch (srcPriority) {
case FINAL:
stages.get(PlacementPriority.CLEAR_FINAL).add(location, replacement);
stages.get(PlacementPriority.CLEAR_FINAL).put(location, replacement);
break;
case LATE:
stages.get(PlacementPriority.CLEAR_LATE).add(location, replacement);
stages.get(PlacementPriority.CLEAR_LATE).put(location, replacement);
break;
case LAST:
stages.get(PlacementPriority.CLEAR_LAST).add(location, replacement);
stages.get(PlacementPriority.CLEAR_LAST).put(location, replacement);
break;
}
@ -243,16 +242,12 @@ public class MultiStageReorder extends AbstractBufferingExtent implements Reorde
}
}
stages.get(priority).add(location, block);
containedBlocks.add(location);
stages.get(priority).put(location, block.toBaseBlock());
return !existing.equalsFuzzy(block);
}
@Override
protected Optional<BaseBlock> getBufferedBlock(BlockVector3 position) {
if (!containedBlocks.contains(position)) {
return Optional.empty();
}
return stages.values().stream()
.map(blocks -> blocks.get(position))
.filter(Objects::nonNull)
@ -266,7 +261,17 @@ public class MultiStageReorder extends AbstractBufferingExtent implements Reorde
}
List<Operation> operations = new ArrayList<>();
for (PlacementPriority priority : PlacementPriority.values()) {
operations.add(new SetLocatedBlocks(getExtent(), stages.get(priority)));
BlockMap blocks = stages.get(priority);
operations.add(new SetBlockMap(getExtent(), blocks) {
@Override
public Operation resume(RunContext run) throws WorldEditException {
Operation operation = super.resume(run);
if (operation == null) {
blocks.clear();
}
return operation;
}
});
}
return new OperationQueue(operations);