mirror of
https://github.com/Minestom/Minestom.git
synced 2025-01-02 14:38:26 +01:00
Improve block#withProperty/ies performance
This commit is contained in:
parent
14e42f7907
commit
4d2b925edd
@ -46,13 +46,7 @@ public interface Block extends ProtocolObject, TagReadable, BlockConstants {
|
||||
* @see #withProperty(String, String)
|
||||
*/
|
||||
@Contract(pure = true)
|
||||
default @NotNull Block withProperties(@NotNull Map<@NotNull String, @NotNull String> properties) {
|
||||
Block block = this;
|
||||
for (var entry : properties.entrySet()) {
|
||||
block = block.withProperty(entry.getKey(), entry.getValue());
|
||||
}
|
||||
return block;
|
||||
}
|
||||
@NotNull Block withProperties(@NotNull Map<@NotNull String, @NotNull String> properties);
|
||||
|
||||
/**
|
||||
* Creates a new block with a tag modified.
|
||||
|
@ -14,41 +14,63 @@ import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
|
||||
class BlockImpl implements Block {
|
||||
final class BlockImpl implements Block {
|
||||
private static final Cache<NBTCompound, NBTCompound> NBT_CACHE = Caffeine.newBuilder()
|
||||
.expireAfterWrite(Duration.ofMinutes(5))
|
||||
.weakValues()
|
||||
.build();
|
||||
|
||||
private final Registry.BlockEntry registry;
|
||||
private final BlockLoader.PropertyEntry propertyEntry;
|
||||
private final Map<String, String> properties;
|
||||
private final NBTCompound nbt;
|
||||
private final BlockHandler handler;
|
||||
|
||||
BlockImpl(@NotNull Registry.BlockEntry registry,
|
||||
@NotNull BlockLoader.PropertyEntry propertyEntry,
|
||||
@NotNull Map<String, String> properties,
|
||||
@Nullable NBTCompound nbt,
|
||||
@Nullable BlockHandler handler) {
|
||||
this.registry = registry;
|
||||
this.propertyEntry = propertyEntry;
|
||||
this.properties = Collections.unmodifiableMap(properties);
|
||||
this.nbt = nbt;
|
||||
this.handler = handler;
|
||||
}
|
||||
|
||||
BlockImpl(@NotNull Registry.BlockEntry registry,
|
||||
@NotNull BlockLoader.PropertyEntry propertyEntry,
|
||||
@NotNull Map<String, String> properties) {
|
||||
this(registry, properties, null, null);
|
||||
this(registry, propertyEntry, properties, null, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Block withProperty(@NotNull String property, @NotNull String value) {
|
||||
var properties = new HashMap<>(this.properties);
|
||||
properties.put(property, value);
|
||||
Block block = BlockLoader.getProperties(name(), properties);
|
||||
Block block = propertyEntry.getProperties(properties);
|
||||
if (block == null)
|
||||
throw new IllegalArgumentException("Invalid property: " + property + ":" + value);
|
||||
if (nbt != null || handler != null)
|
||||
return new BlockImpl(block.registry(), block.properties(), nbt, handler);
|
||||
return new BlockImpl(block.registry(), propertyEntry, block.properties(), nbt, handler);
|
||||
return block;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Block withProperties(@NotNull Map<@NotNull String, @NotNull String> properties) {
|
||||
Block block;
|
||||
if (this.properties.size() == properties.size()) {
|
||||
// Map should be complete
|
||||
block = propertyEntry.getProperties(properties);
|
||||
} else {
|
||||
var newProperties = new HashMap<>(this.properties);
|
||||
newProperties.putAll(properties);
|
||||
block = propertyEntry.getProperties(newProperties);
|
||||
}
|
||||
if (block == null)
|
||||
throw new IllegalArgumentException("Invalid properties: " + properties);
|
||||
if (nbt != null || handler != null)
|
||||
return new BlockImpl(block.registry(), propertyEntry, block.properties(), nbt, handler);
|
||||
return block;
|
||||
}
|
||||
|
||||
@ -57,12 +79,12 @@ class BlockImpl implements Block {
|
||||
var compound = Objects.requireNonNullElseGet(nbt(), NBTCompound::new);
|
||||
tag.write(compound, value);
|
||||
final var nbt = compound.getSize() > 0 ? NBT_CACHE.get(compound, c -> compound) : null;
|
||||
return new BlockImpl(registry, properties, nbt, handler);
|
||||
return new BlockImpl(registry, propertyEntry, properties, nbt, handler);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Block withHandler(@Nullable BlockHandler handler) {
|
||||
return new BlockImpl(registry, properties, nbt, handler);
|
||||
return new BlockImpl(registry, propertyEntry, properties, nbt, handler);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -26,8 +26,6 @@ class BlockLoader {
|
||||
|
||||
// Block namespace -> registry data
|
||||
private static final Map<String, Block> NAMESPACE_MAP = new HashMap<>();
|
||||
// Block namespace -> properties map to block access
|
||||
private static final Map<String, PropertyEntry> BLOCK_PROPERTY_MAP = new HashMap<>();
|
||||
// Block id -> registry data
|
||||
private static final Int2ObjectMap<Block> BLOCK_ID_MAP = new Int2ObjectOpenHashMap<>();
|
||||
// Block state -> block object
|
||||
@ -49,11 +47,6 @@ class BlockLoader {
|
||||
return BLOCK_STATE_MAP.get(stateId);
|
||||
}
|
||||
|
||||
static @Nullable Block getProperties(String namespace, Map<String, String> properties) {
|
||||
final var entry = BLOCK_PROPERTY_MAP.get(namespace);
|
||||
return entry.propertyMap.get(properties);
|
||||
}
|
||||
|
||||
static Collection<Block> values() {
|
||||
return Collections.unmodifiableCollection(NAMESPACE_MAP.values());
|
||||
}
|
||||
@ -75,10 +68,6 @@ class BlockLoader {
|
||||
});
|
||||
}
|
||||
|
||||
private static class PropertyEntry {
|
||||
private final Map<Map<String, String>, Block> propertyMap = new ConcurrentHashMap<>();
|
||||
}
|
||||
|
||||
private static void retrieveState(String namespace, JsonObject object, JsonObject stateObject) {
|
||||
PropertyEntry propertyEntry = new PropertyEntry();
|
||||
stateObject.entrySet().forEach(stateEntry -> {
|
||||
@ -86,10 +75,17 @@ class BlockLoader {
|
||||
JsonObject stateOverride = stateEntry.getValue().getAsJsonObject();
|
||||
final int stateId = stateOverride.get("stateId").getAsInt();
|
||||
final var propertyMap = BlockUtils.parseProperties(query);
|
||||
final Block block = new BlockImpl(Registry.block(object, stateOverride), propertyMap);
|
||||
final Block block = new BlockImpl(Registry.block(object, stateOverride), propertyEntry, propertyMap);
|
||||
BLOCK_STATE_MAP.put(stateId, block);
|
||||
propertyEntry.propertyMap.put(propertyMap, block);
|
||||
propertyEntry.map.put(propertyMap, block);
|
||||
});
|
||||
BLOCK_PROPERTY_MAP.put(namespace, propertyEntry);
|
||||
}
|
||||
|
||||
protected static class PropertyEntry {
|
||||
private final Map<Map<String, String>, Block> map = new ConcurrentHashMap<>();
|
||||
|
||||
public @Nullable Block getProperties(Map<String, String> properties) {
|
||||
return map.get(properties);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user