Skip to content

Commit

Permalink
Merge pull request #9 from OneLiteFeatherNET/bugfix/protocol-object-r…
Browse files Browse the repository at this point in the history
…egistry

[Chore] Improve internal registry handling for implementation creation.
  • Loading branch information
TheMeinerLP authored May 24, 2024
2 parents 9fd02fd + 9aae26a commit ec8c157
Show file tree
Hide file tree
Showing 16 changed files with 142 additions and 103 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,11 @@
*/
public abstract class Argument<T> {
@ApiStatus.Internal
public static final Registry.Container<ArgumentImpl> CONTAINER = Registry.createStaticContainer(Registry.Resource.COMMAND_ARGUMENTS,
(namespace, properties) -> new ArgumentImpl(NamespaceID.from(namespace), properties.getInt("id")));
public static final Registry.Container<ArgumentImpl> CONTAINER = Registry.createStaticContainer(Registry.Resource.COMMAND_ARGUMENTS, Argument::createImpl);

private static ArgumentImpl createImpl(String namespace, Registry.Properties properties) {
return new ArgumentImpl(NamespaceID.from(namespace), properties.getInt("id"));
}

record ArgumentImpl(NamespaceID namespace, int id) implements StaticProtocolObject {
@Override
Expand Down
7 changes: 5 additions & 2 deletions src/main/java/net/minestom/server/entity/EntityTypeImpl.java
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,11 @@
import static java.util.Map.entry;

record EntityTypeImpl(Registry.EntityEntry registry) implements EntityType {
private static final Registry.Container<EntityType> CONTAINER = Registry.createStaticContainer(Registry.Resource.ENTITIES,
(namespace, properties) -> new EntityTypeImpl(Registry.entity(namespace, properties)));
private static final Registry.Container<EntityType> CONTAINER = Registry.createStaticContainer(Registry.Resource.ENTITIES, EntityTypeImpl::createImpl);

private static EntityType createImpl(String namespace, Registry.Properties properties) {
return new EntityTypeImpl(Registry.entity(namespace, properties));
}
static final Map<String, BiFunction<Entity, Metadata, EntityMeta>> ENTITY_META_SUPPLIER = createMetaMap();

static EntityType get(@NotNull String namespace) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,15 @@
import java.util.concurrent.atomic.AtomicInteger;

record DamageTypeImpl(Registry.DamageTypeEntry registry, int id) implements DamageType {
private static final Registry.Container<DamageType> CONTAINER;
private static final AtomicInteger INDEX = new AtomicInteger();
private static final Registry.Container<DamageType> CONTAINER = Registry.createStaticContainer(Registry.Resource.DAMAGE_TYPES, DamageTypeImpl::createImpl);

static {
AtomicInteger i = new AtomicInteger();
CONTAINER = Registry.createStaticContainer(Registry.Resource.DAMAGE_TYPES,
(namespace, properties) -> new DamageTypeImpl(Registry.damageType(namespace, properties), i.getAndIncrement()));
private DamageTypeImpl(Registry.DamageTypeEntry registry) {
this(registry, INDEX.getAndIncrement());
}

private static DamageType createImpl(String namespace, Registry.Properties properties) {
return new DamageTypeImpl(Registry.damageType(namespace, properties));
}

static DamageType get(@NotNull String namespace) {
Expand Down
111 changes: 56 additions & 55 deletions src/main/java/net/minestom/server/instance/block/BlockImpl.java
Original file line number Diff line number Diff line change
Expand Up @@ -31,61 +31,7 @@ record BlockImpl(@NotNull Registry.BlockEntry registry,
private static final ObjectArray<PropertyType[]> PROPERTIES_TYPE = ObjectArray.singleThread();
// Block id -> Map<PropertiesValues, Block>
private static final ObjectArray<Map<PropertiesHolder, BlockImpl>> POSSIBLE_STATES = ObjectArray.singleThread();
private static final Registry.Container<Block> CONTAINER = Registry.createStaticContainer(Registry.Resource.BLOCKS,
(namespace, properties) -> {
final int blockId = properties.getInt("id");
final Registry.Properties stateObject = properties.section("states");

// Retrieve properties
PropertyType[] propertyTypes;
{
Registry.Properties stateProperties = properties.section("properties");
if (stateProperties != null) {
final int stateCount = stateProperties.size();
propertyTypes = new PropertyType[stateCount];
int i = 0;
for (var entry : stateProperties) {
final var k = entry.getKey();
final var v = (List<String>) entry.getValue();
propertyTypes[i++] = new PropertyType(k, v);
}
} else {
propertyTypes = new PropertyType[0];
}
}
PROPERTIES_TYPE.set(blockId, propertyTypes);

// Retrieve block states
{
final int propertiesCount = stateObject.size();
PropertiesHolder[] propertiesKeys = new PropertiesHolder[propertiesCount];
BlockImpl[] blocksValues = new BlockImpl[propertiesCount];
int propertiesOffset = 0;
for (var stateEntry : stateObject) {
final String query = stateEntry.getKey();
final var stateOverride = (Map<String, Object>) stateEntry.getValue();
final var propertyMap = BlockUtils.parseProperties(query);
assert propertyTypes.length == propertyMap.size();
byte[] propertiesArray = new byte[propertyTypes.length];
for (var entry : propertyMap.entrySet()) {
final byte keyIndex = findKeyIndex(propertyTypes, entry.getKey(), null);
final byte valueIndex = findValueIndex(propertyTypes[keyIndex], entry.getValue(), null);
propertiesArray[keyIndex] = valueIndex;
}

var mainProperties = Registry.Properties.fromMap(new MergedMap<>(stateOverride, properties.asMap()));
final BlockImpl block = new BlockImpl(Registry.block(namespace, mainProperties),
propertiesArray, null, null);
BLOCK_STATE_MAP.set(block.stateId(), block);
propertiesKeys[propertiesOffset] = new PropertiesHolder(propertiesArray);
blocksValues[propertiesOffset++] = block;
}
POSSIBLE_STATES.set(blockId, ArrayUtils.toMap(propertiesKeys, blocksValues, propertiesOffset));
}
// Register default state
final int defaultState = properties.getInt("defaultStateId");
return getState(defaultState);
});
private static final Registry.Container<Block> CONTAINER = Registry.createStaticContainer(Registry.Resource.BLOCKS, BlockImpl::createImpl);
private static final Cache<NBTCompound, NBTCompound> NBT_CACHE = Caffeine.newBuilder()
.expireAfterWrite(Duration.ofMinutes(5))
.weakValues()
Expand Down Expand Up @@ -214,6 +160,61 @@ private Block compute(byte[] properties) {
return nbt == null && handler == null ? block : new BlockImpl(block.registry(), block.propertiesArray, nbt, handler);
}

private static Block createImpl(String namespace, Registry.Properties properties) {
final int blockId = properties.getInt("id");
final Registry.Properties stateObject = properties.section("states");

// Retrieve properties
PropertyType[] propertyTypes;
{
Registry.Properties stateProperties = properties.section("properties");
if (stateProperties != null) {
final int stateCount = stateProperties.size();
propertyTypes = new PropertyType[stateCount];
int i = 0;
for (var entry : stateProperties) {
final var k = entry.getKey();
final var v = (List<String>) entry.getValue();
propertyTypes[i++] = new PropertyType(k, v);
}
} else {
propertyTypes = new PropertyType[0];
}
}
PROPERTIES_TYPE.set(blockId, propertyTypes);

// Retrieve block states
{
final int propertiesCount = stateObject.size();
PropertiesHolder[] propertiesKeys = new PropertiesHolder[propertiesCount];
BlockImpl[] blocksValues = new BlockImpl[propertiesCount];
int propertiesOffset = 0;
for (var stateEntry : stateObject) {
final String query = stateEntry.getKey();
final var stateOverride = (Map<String, Object>) stateEntry.getValue();
final var propertyMap = BlockUtils.parseProperties(query);
assert propertyTypes.length == propertyMap.size();
byte[] propertiesArray = new byte[propertyTypes.length];
for (var entry : propertyMap.entrySet()) {
final byte keyIndex = findKeyIndex(propertyTypes, entry.getKey(), null);
final byte valueIndex = findValueIndex(propertyTypes[keyIndex], entry.getValue(), null);
propertiesArray[keyIndex] = valueIndex;
}

var mainProperties = Registry.Properties.fromMap(new MergedMap<>(stateOverride, properties.asMap()));
final BlockImpl block = new BlockImpl(Registry.block(namespace, mainProperties),
propertiesArray, null, null);
BLOCK_STATE_MAP.set(block.stateId(), block);
propertiesKeys[propertiesOffset] = new PropertiesHolder(propertiesArray);
blocksValues[propertiesOffset++] = block;
}
POSSIBLE_STATES.set(blockId, ArrayUtils.toMap(propertiesKeys, blocksValues, propertiesOffset));
}
// Register default state
final int defaultState = properties.getInt("defaultStateId");
return getState(defaultState);
}

private static byte findKeyIndex(PropertyType[] properties, String key, BlockImpl block) {
for (byte i = 0; i < properties.length; i++) {
if (properties[i].key().equals(key)) return i;
Expand Down
7 changes: 5 additions & 2 deletions src/main/java/net/minestom/server/item/EnchantmentImpl.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,11 @@
import java.util.Collection;

record EnchantmentImpl(Registry.EnchantmentEntry registry) implements Enchantment {
private static final Registry.Container<Enchantment> CONTAINER = Registry.createStaticContainer(Registry.Resource.ENCHANTMENTS,
(namespace, properties) -> new EnchantmentImpl(Registry.enchantment(namespace, properties)));
private static final Registry.Container<Enchantment> CONTAINER = Registry.createStaticContainer(Registry.Resource.ENCHANTMENTS, EnchantmentImpl::createImpl);

private static Enchantment createImpl(String namespace, Registry.Properties properties) {
return new EnchantmentImpl(Registry.enchantment(namespace, properties));
}

static Enchantment get(@NotNull String namespace) {
return CONTAINER.get(namespace);
Expand Down
7 changes: 5 additions & 2 deletions src/main/java/net/minestom/server/item/MaterialImpl.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,11 @@
import java.util.Collection;

record MaterialImpl(Registry.MaterialEntry registry) implements Material {
private static final Registry.Container<Material> CONTAINER = Registry.createStaticContainer(Registry.Resource.ITEMS,
(namespace, properties) -> new MaterialImpl(Registry.material(namespace, properties)));
private static final Registry.Container<Material> CONTAINER = Registry.createStaticContainer(Registry.Resource.ITEMS, MaterialImpl::createImpl);

private static Material createImpl(String namespace, Registry.Properties properties) {
return new MaterialImpl(Registry.material(namespace, properties));
}

static Material get(@NotNull String namespace) {
return CONTAINER.get(namespace);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,16 +11,15 @@
import java.util.stream.Collectors;

record TrimMaterialImpl(Registry.TrimMaterialEntry registry, int id) implements TrimMaterial {
static final AtomicInteger i = new AtomicInteger();
private static final Registry.Container<TrimMaterial> CONTAINER;
private static final AtomicInteger INDEX = new AtomicInteger();
private static final Registry.Container<TrimMaterial> CONTAINER = Registry.createStaticContainer(Registry.Resource.TRIM_MATERIALS, TrimMaterialImpl::createImpl);

static {
CONTAINER = Registry.createStaticContainer(Registry.Resource.TRIM_MATERIALS,
(namespace, properties) -> new TrimMaterialImpl(Registry.trimMaterial(namespace, properties)));
public TrimMaterialImpl(Registry.TrimMaterialEntry registry) {
this(registry, INDEX.getAndIncrement());
}

public TrimMaterialImpl(Registry.TrimMaterialEntry registry) {
this(registry, i.getAndIncrement());
private static TrimMaterial createImpl(String namespace, Registry.Properties properties) {
return new TrimMaterialImpl(Registry.trimMaterial(namespace, properties));
}

public static TrimMaterial get(String namespace) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,17 +10,16 @@

record TrimPatternImpl(Registry.TrimPatternEntry registry, int id) implements TrimPattern {
static final AtomicInteger i = new AtomicInteger();
private static final Registry.Container<TrimPattern> CONTAINER;

static {
CONTAINER = Registry.createStaticContainer(Registry.Resource.TRIM_PATTERNS,
(namespace, properties) -> new TrimPatternImpl(Registry.trimPattern(namespace, properties)));
}
private static final Registry.Container<TrimPattern> CONTAINER = Registry.createStaticContainer(Registry.Resource.TRIM_PATTERNS, TrimPatternImpl::createImpl);

public TrimPatternImpl(Registry.TrimPatternEntry registry) {
this(registry, i.getAndIncrement());
}

private static TrimPattern createImpl(String namespace, Registry.Properties properties) {
return new TrimPatternImpl(Registry.trimPattern(namespace, properties));
}

public static TrimPattern get(String namespace) {
return CONTAINER.get(namespace);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,15 @@
public record BannerPatternImpl(NamespaceID namespace, int id, String identifier) implements BannerPattern {

private static Map<String, BannerPatternImpl> IDENTIFIERS = new HashMap<>();
private static final Registry.Container<BannerPattern> CONTAINER = Registry.createStaticContainer(Registry.Resource.BANNER_PATTERNS,
(namespace, properties) -> {
int id = properties.getInt("id");
String identifier = properties.getString("identifier");
BannerPatternImpl bannerPattern = new BannerPatternImpl(NamespaceID.from(namespace), id, identifier);
IDENTIFIERS.put(identifier, bannerPattern);
return bannerPattern;
});
private static final Registry.Container<BannerPattern> CONTAINER = Registry.createStaticContainer(Registry.Resource.BANNER_PATTERNS, BannerPatternImpl::createImpl);

private static BannerPattern createImpl(String namespace, Registry.Properties properties) {
int id = properties.getInt("id");
String identifier = properties.getString("identifier");
BannerPatternImpl bannerPattern = new BannerPatternImpl(NamespaceID.from(namespace), id, identifier);
IDENTIFIERS.put(identifier, bannerPattern);
return bannerPattern;
}

static BannerPattern get(@NotNull String namespace) {
return CONTAINER.get(namespace);
Expand Down
7 changes: 5 additions & 2 deletions src/main/java/net/minestom/server/particle/ParticleImpl.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,11 @@
import java.util.Collection;

record ParticleImpl(NamespaceID namespace, int id, ParticleData data) implements Particle {
private static final Registry.Container<Particle> CONTAINER = Registry.createStaticContainer(Registry.Resource.PARTICLES,
(namespace, properties) -> new ParticleImpl(NamespaceID.from(namespace), properties.getInt("id"), ParticleData.defaultData(namespace)));
private static final Registry.Container<Particle> CONTAINER = Registry.createStaticContainer(Registry.Resource.PARTICLES, ParticleImpl::createImpl);

private static Particle createImpl(String namespace, Registry.Properties properties) {
return new ParticleImpl(NamespaceID.from(namespace), properties.getInt("id"), ParticleData.defaultData(namespace));
}

static Particle get(@NotNull String namespace) {
return CONTAINER.get(namespace);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,11 @@
import java.util.Collection;

record PotionEffectImpl(Registry.PotionEffectEntry registry) implements PotionEffect {
private static final Registry.Container<PotionEffect> CONTAINER = Registry.createStaticContainer(Registry.Resource.POTION_EFFECTS,
(namespace, properties) -> new PotionEffectImpl(Registry.potionEffect(namespace, properties)));
private static final Registry.Container<PotionEffect> CONTAINER = Registry.createStaticContainer(Registry.Resource.POTION_EFFECTS, PotionEffectImpl::createImpl);

private static PotionEffect createImpl(String namespace, Registry.Properties properties) {
return new PotionEffectImpl(Registry.potionEffect(namespace, properties));
}

static PotionEffect get(@NotNull String namespace) {
return CONTAINER.get(namespace);
Expand Down
7 changes: 5 additions & 2 deletions src/main/java/net/minestom/server/potion/PotionTypeImpl.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,11 @@
import java.util.Collection;

record PotionTypeImpl(NamespaceID namespace, int id) implements PotionType {
private static final Registry.Container<PotionType> CONTAINER = Registry.createStaticContainer(Registry.Resource.POTION_TYPES,
(namespace, properties) -> new PotionTypeImpl(NamespaceID.from(namespace), properties.getInt("id")));
private static final Registry.Container<PotionType> CONTAINER = Registry.createStaticContainer(Registry.Resource.POTION_TYPES, PotionTypeImpl::createImpl);

private static PotionType createImpl(String namespace, Registry.Properties properties) {
return new PotionTypeImpl(NamespaceID.from(namespace), properties.getInt("id"));
}

static PotionType get(@NotNull String namespace) {
return CONTAINER.get(namespace);
Expand Down
9 changes: 7 additions & 2 deletions src/main/java/net/minestom/server/registry/Registry.java
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ public static Map<String, Map<String, Object>> load(Resource resource) {
}

@ApiStatus.Internal
public static <T extends StaticProtocolObject> Container<T> createStaticContainer(Resource resource, Container.Loader<T> loader) {
public static <T extends StaticProtocolObject> Container<T> createStaticContainer(Resource resource, Loader<T> loader) {
var entries = Registry.load(resource);
Map<String, T> namespaces = new HashMap<>(entries.size());
ObjectArray<T> ids = ObjectArray.singleThread(entries.size());
Expand Down Expand Up @@ -156,7 +156,7 @@ public interface Loader<T extends ProtocolObject> {
}

@ApiStatus.Internal
public static <T extends ProtocolObject> DynamicContainer<T> createDynamicContainer(Resource resource, Container.Loader<T> loader) {
public static <T extends ProtocolObject> DynamicContainer<T> createDynamicContainer(Resource resource, Loader<T> loader) {
var entries = Registry.load(resource);
Map<String, T> namespaces = new HashMap<>(entries.size());
for (var entry : entries.entrySet()) {
Expand Down Expand Up @@ -203,6 +203,11 @@ public interface Loader<T extends ProtocolObject> {
}
}

@FunctionalInterface
public interface Loader<T extends ProtocolObject> {
T get(String namespace, Properties properties);
}

@ApiStatus.Internal
public enum Resource {
BLOCKS("blocks.json"),
Expand Down
7 changes: 5 additions & 2 deletions src/main/java/net/minestom/server/sound/SoundEventImpl.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,11 @@
import java.util.Collection;

record SoundEventImpl(NamespaceID namespace, int id) implements SoundEvent {
private static final Registry.Container<SoundEvent> CONTAINER = Registry.createStaticContainer(Registry.Resource.SOUNDS,
(namespace, properties) -> new SoundEventImpl(NamespaceID.from(namespace), properties.getInt("id")));
private static final Registry.Container<SoundEvent> CONTAINER = Registry.createStaticContainer(Registry.Resource.SOUNDS, SoundEventImpl::createImpl);

private static SoundEvent createImpl(String namespace, Registry.Properties properties) {
return new SoundEventImpl(NamespaceID.from(namespace), properties.getInt("id"));
}

static SoundEvent get(@NotNull String namespace) {
return CONTAINER.get(namespace);
Expand Down
Loading

0 comments on commit ec8c157

Please sign in to comment.