From d0ea5121f21920b468e40554299463a3f3f291a8 Mon Sep 17 00:00:00 2001 From: Kenzie Togami Date: Thu, 4 Oct 2018 17:18:01 -0700 Subject: [PATCH] Make some BlockType fields lazy, to avoid early Platform dependencies --- .../worldedit/world/block/BlockType.java | 70 +++++++++++++------ 1 file changed, 49 insertions(+), 21 deletions(-) diff --git a/worldedit-core/src/main/java/com/sk89q/worldedit/world/block/BlockType.java b/worldedit-core/src/main/java/com/sk89q/worldedit/world/block/BlockType.java index 3378353c6..7ab125e95 100644 --- a/worldedit-core/src/main/java/com/sk89q/worldedit/world/block/BlockType.java +++ b/worldedit-core/src/main/java/com/sk89q/worldedit/world/block/BlockType.java @@ -19,6 +19,8 @@ package com.sk89q.worldedit.world.block; +import static com.google.common.base.Preconditions.checkArgument; + import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; import com.sk89q.worldedit.WorldEdit; @@ -34,7 +36,9 @@ import com.sk89q.worldedit.world.registry.LegacyMapper; import java.util.ArrayList; import java.util.List; import java.util.Map; +import java.util.concurrent.atomic.AtomicReference; import java.util.function.Function; +import java.util.function.Supplier; import javax.annotation.Nullable; @@ -42,11 +46,12 @@ public class BlockType { public static final NamespacedRegistry REGISTRY = new NamespacedRegistry<>("block type"); - private String id; - private BlockState defaultState; - private Map properties; - private BlockMaterial blockMaterial; - private Map, Object>, BlockState> blockStatesMap; + private final String id; + private final Function values; + private final AtomicReference defaultState = new AtomicReference<>(); + private final AtomicReference> properties = new AtomicReference<>(); + private final AtomicReference blockMaterial = new AtomicReference<>(); + private final AtomicReference, Object>, BlockState>> blockStatesMap = new AtomicReference<>(); public BlockType(String id) { this(id, null); @@ -58,11 +63,37 @@ public class BlockType { id = "minecraft:" + id; } this.id = id; - this.blockStatesMap = BlockState.generateStateMap(this); - this.defaultState = new ArrayList<>(this.blockStatesMap.values()).get(0); - if (values != null) { - this.defaultState = values.apply(this.defaultState); + this.values = values; + } + + private T updateField(AtomicReference field, Supplier value) { + T result = field.get(); + if (result == null) { + // swap in new value, if someone doesn't beat us + T update = value.get(); + if (field.compareAndSet(null, update)) { + // use ours + result = update; + } else { + // update to real value + result = field.get(); + } } + return result; + } + + private Map, Object>, BlockState> getBlockStatesMap() { + return updateField(blockStatesMap, () -> BlockState.generateStateMap(this)); + } + + private BlockState getDefaultStateMemoized() { + return updateField(defaultState, () -> { + BlockState defaultState = new ArrayList<>(getBlockStatesMap().values()).get(0); + if (values != null) { + defaultState = values.apply(defaultState); + } + return defaultState; + }); } /** @@ -94,11 +125,8 @@ public class BlockType { * @return The properties map */ public Map getPropertyMap() { - if (properties == null) { - properties = ImmutableMap.copyOf(WorldEdit.getInstance().getPlatformManager() - .queryCapability(Capability.GAME_HOOKS).getRegistries().getBlockRegistry().getProperties(this)); - } - return this.properties; + return updateField(properties, () -> ImmutableMap.copyOf(WorldEdit.getInstance().getPlatformManager() + .queryCapability(Capability.GAME_HOOKS).getRegistries().getBlockRegistry().getProperties(this))); } /** @@ -117,7 +145,9 @@ public class BlockType { * @return The property */ public Property getProperty(String name) { - return getPropertyMap().get(name); + Property property = getPropertyMap().get(name); + checkArgument(property != null, "%s has no property named %s", this, name); + return property; } /** @@ -126,7 +156,7 @@ public class BlockType { * @return The default state */ public BlockState getDefaultState() { - return this.defaultState; + return getDefaultStateMemoized(); } /** @@ -135,7 +165,7 @@ public class BlockType { * @return All possible states */ public List getAllStates() { - return ImmutableList.copyOf(this.blockStatesMap.values()); + return ImmutableList.copyOf(getBlockStatesMap().values()); } /** @@ -163,10 +193,8 @@ public class BlockType { * @return The material */ public BlockMaterial getMaterial() { - if (this.blockMaterial == null) { - this.blockMaterial = WorldEdit.getInstance().getPlatformManager().queryCapability(Capability.GAME_HOOKS).getRegistries().getBlockRegistry().getMaterial(this); - } - return this.blockMaterial; + return updateField(blockMaterial, () -> WorldEdit.getInstance().getPlatformManager() + .queryCapability(Capability.GAME_HOOKS).getRegistries().getBlockRegistry().getMaterial(this)); } /**