fix: Add game events for packet registry (#2612)

This commit is contained in:
Phillipp Glanz 2025-01-22 06:20:23 +01:00 committed by GitHub
parent 0d47d97417
commit e1d0366841
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 293 additions and 21 deletions

View File

@ -52,6 +52,7 @@ public class Generators {
generator.generate(resource("attributes.json"), "net.minestom.server.entity.attribute", "Attribute", "AttributeImpl", "Attributes");
generator.generate(resource("feature_flags.json"), "net.minestom.server", "FeatureFlag", "FeatureFlagImpl", "FeatureFlags");
generator.generate(resource("villager_professions.json"), "net.minestom.server.entity", "VillagerProfession", "VillagerProfessionImpl", "VillagerProfessions");
generator.generate(resource("game_events.json"), "net.minestom.server.game", "GameEvent", "GameEventImpl", "GameEvents");
// Dynamic registries

View File

@ -0,0 +1,127 @@
package net.minestom.server.game;
/**
* Code autogenerated, do not edit!
*/
@SuppressWarnings("unused")
interface GameEvents {
GameEvent BLOCK_ACTIVATE = GameEventImpl.get("minecraft:block_activate");
GameEvent BLOCK_ATTACH = GameEventImpl.get("minecraft:block_attach");
GameEvent BLOCK_CHANGE = GameEventImpl.get("minecraft:block_change");
GameEvent BLOCK_CLOSE = GameEventImpl.get("minecraft:block_close");
GameEvent BLOCK_DEACTIVATE = GameEventImpl.get("minecraft:block_deactivate");
GameEvent BLOCK_DESTROY = GameEventImpl.get("minecraft:block_destroy");
GameEvent BLOCK_DETACH = GameEventImpl.get("minecraft:block_detach");
GameEvent BLOCK_OPEN = GameEventImpl.get("minecraft:block_open");
GameEvent BLOCK_PLACE = GameEventImpl.get("minecraft:block_place");
GameEvent CONTAINER_CLOSE = GameEventImpl.get("minecraft:container_close");
GameEvent CONTAINER_OPEN = GameEventImpl.get("minecraft:container_open");
GameEvent DRINK = GameEventImpl.get("minecraft:drink");
GameEvent EAT = GameEventImpl.get("minecraft:eat");
GameEvent ELYTRA_GLIDE = GameEventImpl.get("minecraft:elytra_glide");
GameEvent ENTITY_DAMAGE = GameEventImpl.get("minecraft:entity_damage");
GameEvent ENTITY_DIE = GameEventImpl.get("minecraft:entity_die");
GameEvent ENTITY_DISMOUNT = GameEventImpl.get("minecraft:entity_dismount");
GameEvent ENTITY_INTERACT = GameEventImpl.get("minecraft:entity_interact");
GameEvent ENTITY_MOUNT = GameEventImpl.get("minecraft:entity_mount");
GameEvent ENTITY_PLACE = GameEventImpl.get("minecraft:entity_place");
GameEvent ENTITY_ACTION = GameEventImpl.get("minecraft:entity_action");
GameEvent EQUIP = GameEventImpl.get("minecraft:equip");
GameEvent EXPLODE = GameEventImpl.get("minecraft:explode");
GameEvent FLAP = GameEventImpl.get("minecraft:flap");
GameEvent FLUID_PICKUP = GameEventImpl.get("minecraft:fluid_pickup");
GameEvent FLUID_PLACE = GameEventImpl.get("minecraft:fluid_place");
GameEvent HIT_GROUND = GameEventImpl.get("minecraft:hit_ground");
GameEvent INSTRUMENT_PLAY = GameEventImpl.get("minecraft:instrument_play");
GameEvent ITEM_INTERACT_FINISH = GameEventImpl.get("minecraft:item_interact_finish");
GameEvent ITEM_INTERACT_START = GameEventImpl.get("minecraft:item_interact_start");
GameEvent JUKEBOX_PLAY = GameEventImpl.get("minecraft:jukebox_play");
GameEvent JUKEBOX_STOP_PLAY = GameEventImpl.get("minecraft:jukebox_stop_play");
GameEvent LIGHTNING_STRIKE = GameEventImpl.get("minecraft:lightning_strike");
GameEvent NOTE_BLOCK_PLAY = GameEventImpl.get("minecraft:note_block_play");
GameEvent PRIME_FUSE = GameEventImpl.get("minecraft:prime_fuse");
GameEvent PROJECTILE_LAND = GameEventImpl.get("minecraft:projectile_land");
GameEvent PROJECTILE_SHOOT = GameEventImpl.get("minecraft:projectile_shoot");
GameEvent SCULK_SENSOR_TENDRILS_CLICKING = GameEventImpl.get("minecraft:sculk_sensor_tendrils_clicking");
GameEvent SHEAR = GameEventImpl.get("minecraft:shear");
GameEvent SHRIEK = GameEventImpl.get("minecraft:shriek");
GameEvent SPLASH = GameEventImpl.get("minecraft:splash");
GameEvent STEP = GameEventImpl.get("minecraft:step");
GameEvent SWIM = GameEventImpl.get("minecraft:swim");
GameEvent TELEPORT = GameEventImpl.get("minecraft:teleport");
GameEvent UNEQUIP = GameEventImpl.get("minecraft:unequip");
GameEvent RESONATE_1 = GameEventImpl.get("minecraft:resonate_1");
GameEvent RESONATE_2 = GameEventImpl.get("minecraft:resonate_2");
GameEvent RESONATE_3 = GameEventImpl.get("minecraft:resonate_3");
GameEvent RESONATE_4 = GameEventImpl.get("minecraft:resonate_4");
GameEvent RESONATE_5 = GameEventImpl.get("minecraft:resonate_5");
GameEvent RESONATE_6 = GameEventImpl.get("minecraft:resonate_6");
GameEvent RESONATE_7 = GameEventImpl.get("minecraft:resonate_7");
GameEvent RESONATE_8 = GameEventImpl.get("minecraft:resonate_8");
GameEvent RESONATE_9 = GameEventImpl.get("minecraft:resonate_9");
GameEvent RESONATE_10 = GameEventImpl.get("minecraft:resonate_10");
GameEvent RESONATE_11 = GameEventImpl.get("minecraft:resonate_11");
GameEvent RESONATE_12 = GameEventImpl.get("minecraft:resonate_12");
GameEvent RESONATE_13 = GameEventImpl.get("minecraft:resonate_13");
GameEvent RESONATE_14 = GameEventImpl.get("minecraft:resonate_14");
GameEvent RESONATE_15 = GameEventImpl.get("minecraft:resonate_15");
}

View File

@ -0,0 +1,66 @@
package net.minestom.server.game;
import net.minestom.server.registry.Registry;
import net.minestom.server.registry.StaticProtocolObject;
import net.minestom.server.utils.NamespaceID;
import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Collection;
/**
* Represents a game event.
* Used for a wide variety of events, from weather to bed use to game mode to demo messages.
*/
public sealed interface GameEvent extends StaticProtocolObject permits GameEventImpl {
/**
* Returns the game event registry.
*
* @return the game event registry or null if not found
*/
@Contract(pure = true)
@Nullable
Registry.GameEventEntry registry();
/**
* Gets the namespace ID of this game event.
*
* @return the namespace ID
*/
@Override
@NotNull
NamespaceID namespace();
/**
* Gets the game events from the registry.
*
* @return the game events
*/
static @NotNull Collection<@NotNull GameEvent> values() {
return GameEventImpl.values();
}
/**
* Gets a game event by its namespace ID.
*
* @param namespaceID the namespace ID
* @return the game event or null if not found
*/
static @Nullable GameEvent fromNamespaceId(@NotNull String namespaceID) {
return GameEventImpl.getSafe(namespaceID);
}
/**
* Gets a game event by its namespace ID.
*
* @param namespaceID the namespace ID
* @return the game event or null if not found
*/
static @Nullable GameEvent fromNamespaceId(@NotNull NamespaceID namespaceID) {
return fromNamespaceId(namespaceID.asString());
}
}

View File

@ -0,0 +1,65 @@
package net.minestom.server.game;
import net.minestom.server.registry.Registry;
import net.minestom.server.utils.NamespaceID;
import org.jetbrains.annotations.NotNull;
import java.util.Collection;
/**
* Represents a game event implementation.
* Used for a wide variety of events, from weather to bed use to game mode to demo messages.
*/
record GameEventImpl(Registry.GameEventEntry registry, NamespaceID namespace, int id) implements GameEvent {
private static final Registry.Container<GameEvent> CONTAINER = Registry.createStaticContainer(Registry.Resource.GAME_EVENTS, GameEventImpl::createImpl);
/**
* Creates a new {@link GameEventImpl} with the given namespace and properties.
*
* @param namespace the namespace
* @param properties the properties
* @return a new {@link GameEventImpl}
*/
private static GameEventImpl createImpl(String namespace, Registry.Properties properties) {
return new GameEventImpl(Registry.gameEventEntry(namespace, properties));
}
/**
* Creates a new {@link GameEventImpl} with the given registry.
*
* @param registry the registry
*/
private GameEventImpl(Registry.GameEventEntry registry) {
this(registry, registry.namespace(), registry.main().getInt("id"));
}
/**
* Gets the game events from the registry.
*
* @return the game events
*/
static Collection<GameEvent> values() {
return CONTAINER.values();
}
/**
* Gets a game event by its namespace ID.
*
* @param namespace the namespace ID
* @return the game event or null if not found
*/
public static GameEvent get(@NotNull String namespace) {
return CONTAINER.get(namespace);
}
/**
* Gets a game event by its namespace ID.
*
* @param namespace the namespace ID
* @return the game event or null if not found
*/
static GameEvent getSafe(@NotNull String namespace) {
return CONTAINER.getSafe(namespace);
}
}

View File

@ -2,8 +2,8 @@ package net.minestom.server.gamedata.tags;
import net.kyori.adventure.key.Key;
import net.kyori.adventure.key.Keyed;
import net.minestom.server.MinecraftServer;
import net.minestom.server.entity.EntityType;
import net.minestom.server.game.GameEvent;
import net.minestom.server.instance.block.Block;
import net.minestom.server.item.Material;
import net.minestom.server.registry.*;
@ -14,10 +14,9 @@ import org.jetbrains.annotations.Nullable;
import java.util.Collections;
import java.util.HashSet;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.function.BiFunction;
import java.util.function.Function;
/**
* Represents a group of items, blocks, fluids, entity types or function.
@ -92,32 +91,35 @@ public final class Tag implements ProtocolObject, Keyed {
public enum BasicType {
BLOCKS("minecraft:block", Registry.Resource.BLOCK_TAGS,
(name, registries) -> Objects.requireNonNull(Block.fromNamespaceId(name)).id()),
(blockName, registries) -> Optional.ofNullable(Block.fromNamespaceId(blockName)).map(Block::id)),
ITEMS("minecraft:item", Registry.Resource.ITEM_TAGS,
(name, registries) -> Objects.requireNonNull(Material.fromNamespaceId(name)).id()),
(itemName, registries) -> Optional.ofNullable(Material.fromNamespaceId(itemName)).map(Material::id)),
FLUIDS("minecraft:fluid", Registry.Resource.FLUID_TAGS,
(name, registries) -> FluidRegistries.getFluid(name).ordinal()),
(name, registries) -> Optional.of(name).map(FluidRegistries::getFluid).map(Enum::ordinal)),
ENTITY_TYPES("minecraft:entity_type", Registry.Resource.ENTITY_TYPE_TAGS,
(name, registries) -> Objects.requireNonNull(EntityType.fromNamespaceId(name)).id()),
(entityName, registries) -> Optional.ofNullable(EntityType.fromNamespaceId(entityName)).map(EntityType::id)),
GAME_EVENTS("minecraft:game_event", Registry.Resource.GAMEPLAY_TAGS,
(name, registries) -> FluidRegistries.getFluid(name).ordinal()),
(eventName, registries) -> Optional.ofNullable(GameEvent.fromNamespaceId(eventName)).map(GameEvent::id)),
SOUND_EVENTS("minecraft:sound_event", null, null), // Seems not to be included in server data
POTION_EFFECTS("minecraft:potion_effect", null, null), // Seems not to be included in server data
//todo this is cursed. it does not update as the registry changes. Fix later.
ENCHANTMENTS("minecraft:enchantment", Registry.Resource.ENCHANTMENT_TAGS,
(name, registries) -> registries.enchantment().getId(DynamicRegistry.Key.of(name))),
(name, registries) -> Optional.of(DynamicRegistry.Key.of(name))
.map(DynamicRegistry.Key::namespace)
.map(registries.enchantment()::getId)),
BIOMES("minecraft:worldgen/biome", Registry.Resource.BIOME_TAGS,
(name, registries) -> registries.biome().getId(DynamicRegistry.Key.of(name)));
(name, registries) -> Optional.of(DynamicRegistry.Key.of(name))
.map(DynamicRegistry.Key::namespace)
.map(registries.biome()::getId));
private final static BasicType[] VALUES = values();
private static final BasicType[] VALUES = values();
private final String identifier;
private final Registry.Resource resource;
private final BiFunction<String, Registries, Integer> function;
private final BiFunction<String, Registries, Optional<Integer>> function;
BasicType(@NotNull String identifier,
@Nullable Registry.Resource resource,
@Nullable BiFunction<String, Registries, Integer> function) {
@Nullable BiFunction<String, Registries, Optional<Integer>> function) {
this.identifier = identifier;
this.resource = resource;
this.function = function;
@ -131,7 +133,7 @@ public final class Tag implements ProtocolObject, Keyed {
return resource;
}
public BiFunction<String, Registries, Integer> getFunction() {
public BiFunction<String, Registries, Optional<Integer>> getFunction() {
return function;
}

View File

@ -30,8 +30,8 @@ public final class TagManager {
public @Nullable Tag getTag(Tag.BasicType type, String namespace) {
final var tags = tagMap.get(type);
for (var tag : tags) {
if (tag.getName().asString().equals(namespace))
for (final var tag : tags) {
if (tag.name().equals(namespace))
return tag;
}
return null;
@ -46,10 +46,10 @@ public final class TagManager {
for (Map.Entry<Tag.BasicType, List<Tag>> entry : tagMap.entrySet()) {
final Tag.BasicType type = entry.getKey();
final String registry = type.getIdentifier();
List<TagsPacket.Tag> tags = new ArrayList<>();
for (Tag tag : entry.getValue()) {
final String identifier = tag.getName().asString();
final int[] values = tag.getValues().stream().mapToInt(value -> type.getFunction().apply(value.asString(), registries)).toArray();
final List<TagsPacket.Tag> tags = new ArrayList<>();
for (final Tag tag : entry.getValue()) {
final String identifier = tag.name();
final int[] values = tag.getValues().stream().mapToInt(value -> type.getFunction().apply(value.asString(), registries).orElse(null)).filter(Objects::nonNull).toArray();
tags.add(new TagsPacket.Tag(identifier, values));
}
registryList.add(new TagsPacket.Registry(registry, tags));

View File

@ -137,6 +137,10 @@ public final class Registry {
return new JukeboxSongEntry(namespace, main, null);
}
public static GameEventEntry gameEventEntry(String namespace, Properties properties) {
return new GameEventEntry(namespace, properties, null);
}
public static @NotNull InputStream loadRegistryFile(@NotNull Resource resource) throws IOException {
// 1. Try to load from jar resources
InputStream resourceStream = Registry.class.getClassLoader().getResourceAsStream(resource.name);
@ -245,6 +249,7 @@ public final class Registry {
ENTITY_TYPE_TAGS("tags/entity_type.json"),
FLUID_TAGS("tags/fluid.json"),
GAMEPLAY_TAGS("tags/game_event.json"),
GAME_EVENTS("game_events.json"),
ITEM_TAGS("tags/item.json"),
ENCHANTMENT_TAGS("tags/enchantment.json"),
BIOME_TAGS("tags/biome.json"),
@ -270,6 +275,12 @@ public final class Registry {
}
}
public record GameEventEntry(NamespaceID namespace, Properties main, Properties custom) implements Entry {
public GameEventEntry(String namespace, Properties main, Properties custom) {
this(NamespaceID.from(namespace), main, custom);
}
}
public static final class BlockEntry implements Entry {
private final NamespaceID namespace;
private final int id;