mirror of
https://github.com/Minestom/Minestom.git
synced 2025-01-07 00:48:28 +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)
|
* @see #withProperty(String, String)
|
||||||
*/
|
*/
|
||||||
@Contract(pure = true)
|
@Contract(pure = true)
|
||||||
default @NotNull Block withProperties(@NotNull Map<@NotNull String, @NotNull String> properties) {
|
@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;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new block with a tag modified.
|
* Creates a new block with a tag modified.
|
||||||
|
@ -14,41 +14,63 @@ import java.util.HashMap;
|
|||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
class BlockImpl implements Block {
|
final class BlockImpl implements Block {
|
||||||
private static final Cache<NBTCompound, NBTCompound> NBT_CACHE = Caffeine.newBuilder()
|
private static final Cache<NBTCompound, NBTCompound> NBT_CACHE = Caffeine.newBuilder()
|
||||||
.expireAfterWrite(Duration.ofMinutes(5))
|
.expireAfterWrite(Duration.ofMinutes(5))
|
||||||
.weakValues()
|
.weakValues()
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
private final Registry.BlockEntry registry;
|
private final Registry.BlockEntry registry;
|
||||||
|
private final BlockLoader.PropertyEntry propertyEntry;
|
||||||
private final Map<String, String> properties;
|
private final Map<String, String> properties;
|
||||||
private final NBTCompound nbt;
|
private final NBTCompound nbt;
|
||||||
private final BlockHandler handler;
|
private final BlockHandler handler;
|
||||||
|
|
||||||
BlockImpl(@NotNull Registry.BlockEntry registry,
|
BlockImpl(@NotNull Registry.BlockEntry registry,
|
||||||
|
@NotNull BlockLoader.PropertyEntry propertyEntry,
|
||||||
@NotNull Map<String, String> properties,
|
@NotNull Map<String, String> properties,
|
||||||
@Nullable NBTCompound nbt,
|
@Nullable NBTCompound nbt,
|
||||||
@Nullable BlockHandler handler) {
|
@Nullable BlockHandler handler) {
|
||||||
this.registry = registry;
|
this.registry = registry;
|
||||||
|
this.propertyEntry = propertyEntry;
|
||||||
this.properties = Collections.unmodifiableMap(properties);
|
this.properties = Collections.unmodifiableMap(properties);
|
||||||
this.nbt = nbt;
|
this.nbt = nbt;
|
||||||
this.handler = handler;
|
this.handler = handler;
|
||||||
}
|
}
|
||||||
|
|
||||||
BlockImpl(@NotNull Registry.BlockEntry registry,
|
BlockImpl(@NotNull Registry.BlockEntry registry,
|
||||||
|
@NotNull BlockLoader.PropertyEntry propertyEntry,
|
||||||
@NotNull Map<String, String> properties) {
|
@NotNull Map<String, String> properties) {
|
||||||
this(registry, properties, null, null);
|
this(registry, propertyEntry, properties, null, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public @NotNull Block withProperty(@NotNull String property, @NotNull String value) {
|
public @NotNull Block withProperty(@NotNull String property, @NotNull String value) {
|
||||||
var properties = new HashMap<>(this.properties);
|
var properties = new HashMap<>(this.properties);
|
||||||
properties.put(property, value);
|
properties.put(property, value);
|
||||||
Block block = BlockLoader.getProperties(name(), properties);
|
Block block = propertyEntry.getProperties(properties);
|
||||||
if (block == null)
|
if (block == null)
|
||||||
throw new IllegalArgumentException("Invalid property: " + property + ":" + value);
|
throw new IllegalArgumentException("Invalid property: " + property + ":" + value);
|
||||||
if (nbt != null || handler != null)
|
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;
|
return block;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -57,12 +79,12 @@ class BlockImpl implements Block {
|
|||||||
var compound = Objects.requireNonNullElseGet(nbt(), NBTCompound::new);
|
var compound = Objects.requireNonNullElseGet(nbt(), NBTCompound::new);
|
||||||
tag.write(compound, value);
|
tag.write(compound, value);
|
||||||
final var nbt = compound.getSize() > 0 ? NBT_CACHE.get(compound, c -> compound) : null;
|
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
|
@Override
|
||||||
public @NotNull Block withHandler(@Nullable BlockHandler handler) {
|
public @NotNull Block withHandler(@Nullable BlockHandler handler) {
|
||||||
return new BlockImpl(registry, properties, nbt, handler);
|
return new BlockImpl(registry, propertyEntry, properties, nbt, handler);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -26,8 +26,6 @@ class BlockLoader {
|
|||||||
|
|
||||||
// Block namespace -> registry data
|
// Block namespace -> registry data
|
||||||
private static final Map<String, Block> NAMESPACE_MAP = new HashMap<>();
|
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
|
// Block id -> registry data
|
||||||
private static final Int2ObjectMap<Block> BLOCK_ID_MAP = new Int2ObjectOpenHashMap<>();
|
private static final Int2ObjectMap<Block> BLOCK_ID_MAP = new Int2ObjectOpenHashMap<>();
|
||||||
// Block state -> block object
|
// Block state -> block object
|
||||||
@ -49,11 +47,6 @@ class BlockLoader {
|
|||||||
return BLOCK_STATE_MAP.get(stateId);
|
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() {
|
static Collection<Block> values() {
|
||||||
return Collections.unmodifiableCollection(NAMESPACE_MAP.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) {
|
private static void retrieveState(String namespace, JsonObject object, JsonObject stateObject) {
|
||||||
PropertyEntry propertyEntry = new PropertyEntry();
|
PropertyEntry propertyEntry = new PropertyEntry();
|
||||||
stateObject.entrySet().forEach(stateEntry -> {
|
stateObject.entrySet().forEach(stateEntry -> {
|
||||||
@ -86,10 +75,17 @@ class BlockLoader {
|
|||||||
JsonObject stateOverride = stateEntry.getValue().getAsJsonObject();
|
JsonObject stateOverride = stateEntry.getValue().getAsJsonObject();
|
||||||
final int stateId = stateOverride.get("stateId").getAsInt();
|
final int stateId = stateOverride.get("stateId").getAsInt();
|
||||||
final var propertyMap = BlockUtils.parseProperties(query);
|
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);
|
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