Skip to content

Commit 76d6a64

Browse files
authored
Improve state applying pattern performance (#3149)
1 parent 8c003c2 commit 76d6a64

File tree

1 file changed

+32
-9
lines changed

1 file changed

+32
-9
lines changed

worldedit-core/src/main/java/com/sk89q/worldedit/function/pattern/StateApplyingPattern.java

Lines changed: 32 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@
1919

2020
package com.sk89q.worldedit.function.pattern;
2121

22-
import com.google.common.collect.Maps;
2322
import com.sk89q.worldedit.extent.Extent;
2423
import com.sk89q.worldedit.math.BlockVector3;
2524
import com.sk89q.worldedit.registry.state.Property;
@@ -36,8 +35,8 @@
3635
public class StateApplyingPattern extends AbstractExtentPattern {
3736

3837
private final Map<String, String> states;
39-
//FAWE - avoid race conditions
40-
private final Map<BlockType, Map<Property<Object>, Object>> cache = new ConcurrentHashMap<>();
38+
//FAWE - avoid race conditions, faster property applications
39+
private final Map<BlockType, PropertyApplication[]> cache = new ConcurrentHashMap<>();
4140
//FAWE end
4241

4342
public StateApplyingPattern(Extent extent, Map<String, String> statesToSet) {
@@ -47,16 +46,40 @@ public StateApplyingPattern(Extent extent, Map<String, String> statesToSet) {
4746

4847
@Override
4948
public BaseBlock applyBlock(BlockVector3 position) {
50-
BlockState block = getExtent().getBlock(position);
51-
for (Entry<Property<Object>, Object> entry : cache
52-
.computeIfAbsent(block.getBlockType(), (b -> resolveProperties(states, b))).entrySet()) {
53-
//FAWE start
54-
if (block.getBlockType().hasProperty(entry.getKey().getKey())) {
55-
block = block.with(entry.getKey(), entry.getValue());
49+
//FAWE start
50+
BlockState block = position.getBlock(getExtent());
51+
final BlockType blockType = block.getBlockType();
52+
// weak consistency is enough, no need to use computeIfAbsent
53+
PropertyApplication[] applications = cache.get(blockType);
54+
if (applications == null) {
55+
applications = resolvePropertiesFor(blockType);
56+
cache.put(blockType, applications);
57+
}
58+
for (PropertyApplication entry : applications) {
59+
if (blockType.hasProperty(entry.property().getKey())) {
60+
block = block.with(entry.property(), entry.value());
5661
}
5762
//FAWE end
5863
}
5964
return block.toBaseBlock();
6065
}
6166

67+
//FAWE start - faster property application
68+
private record PropertyApplication(Property<Object> property, Object value) {
69+
70+
}
71+
72+
private PropertyApplication[] resolvePropertiesFor(BlockType blockType) {
73+
Map<Property<Object>, Object> map = resolveProperties(states, blockType);
74+
final PropertyApplication[] applications = new PropertyApplication[map.size()];
75+
int i = 0;
76+
for (Entry<Property<Object>, Object> entry : map.entrySet()) {
77+
Property<Object> property = entry.getKey();
78+
Object o = entry.getValue();
79+
applications[i++] = new PropertyApplication(property, o);
80+
}
81+
return applications;
82+
}
83+
//FAWE end
84+
6285
}

0 commit comments

Comments
 (0)