/
ChunkBatchingExtent.java
119 lines (102 loc) · 4.14 KB
/
ChunkBatchingExtent.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
/*
* WorldEdit, a Minecraft world manipulation toolkit
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldEdit team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldedit.extent.reorder;
import com.sk89q.worldedit.BlockVector2D;
import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.Vector2D;
import com.sk89q.worldedit.WorldEditException;
import com.sk89q.worldedit.extent.AbstractDelegateExtent;
import com.sk89q.worldedit.extent.Extent;
import com.sk89q.worldedit.function.operation.Operation;
import com.sk89q.worldedit.function.operation.RunContext;
import com.sk89q.worldedit.function.operation.SetLocatedBlocks;
import com.sk89q.worldedit.util.collection.LocatedBlockList;
import com.sk89q.worldedit.world.block.BlockStateHolder;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
import java.util.SortedMap;
import java.util.TreeMap;
/**
* A special extent that batches changes into Minecraft chunks. This helps
* improve the speed of setting the blocks, since chunks do not need to be
* loaded repeatedly, however it does take more memory due to caching the
* blocks.
*/
public class ChunkBatchingExtent extends AbstractDelegateExtent {
/**
* 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<Vector2D> REGION_OPTIMIZED_SORT =
Comparator.<Vector2D, Vector2D>comparing(vec -> vec.divide(32).floor(), Vector2D.COMPARING_GRID_ARRANGEMENT)
.thenComparing(Vector2D.COMPARING_GRID_ARRANGEMENT);
private final SortedMap<BlockVector2D, LocatedBlockList> batches = new TreeMap<>(REGION_OPTIMIZED_SORT);
private boolean enabled;
public ChunkBatchingExtent(Extent extent) {
this(extent, true);
}
public ChunkBatchingExtent(Extent extent, boolean enabled) {
super(extent);
this.enabled = enabled;
}
public boolean isEnabled() {
return enabled;
}
public void setEnabled(boolean enabled) {
this.enabled = enabled;
}
@Override
public boolean setBlock(Vector location, BlockStateHolder block) throws WorldEditException {
if (!enabled) {
return getExtent().setBlock(location, block);
}
BlockVector2D chunkPos = new BlockVector2D(location.getBlockX() >> 4, location.getBlockZ() >> 4);
batches.computeIfAbsent(chunkPos, k -> new LocatedBlockList()).add(location, block);
return true;
}
@Override
protected Operation commitBefore() {
if (!enabled) {
return null;
}
return new Operation() {
// we get modified between create/resume -- only create this on resume to prevent CME
private Iterator<LocatedBlockList> batchIterator;
@Override
public Operation resume(RunContext run) throws WorldEditException {
if (batchIterator == null) {
batchIterator = batches.values().iterator();
}
if (!batchIterator.hasNext()) {
return null;
}
new SetLocatedBlocks(getExtent(), batchIterator.next()).resume(run);
batchIterator.remove();
return this;
}
@Override
public void cancel() {
}
@Override
public void addStatusMessages(List<String> messages) {
}
};
}
}