mirror of
https://github.com/Minestom/Minestom.git
synced 2025-02-11 01:41:47 +01:00
Ability to get registry packets without MinecraftServer (#2469)
* Ability to get registry packets without MinecraftServer * review fixes
This commit is contained in:
parent
5f7ac6fb72
commit
e6781cd3fa
@ -6,10 +6,7 @@ import net.minestom.server.MinecraftServer;
|
||||
import net.minestom.server.entity.EntityType;
|
||||
import net.minestom.server.instance.block.Block;
|
||||
import net.minestom.server.item.Material;
|
||||
import net.minestom.server.registry.DynamicRegistry;
|
||||
import net.minestom.server.registry.FluidRegistries;
|
||||
import net.minestom.server.registry.ProtocolObject;
|
||||
import net.minestom.server.registry.Registry;
|
||||
import net.minestom.server.registry.*;
|
||||
import net.minestom.server.utils.NamespaceID;
|
||||
import org.jetbrains.annotations.Contract;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@ -19,6 +16,7 @@ import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.function.BiFunction;
|
||||
import java.util.function.Function;
|
||||
|
||||
/**
|
||||
@ -94,32 +92,32 @@ public final class Tag implements ProtocolObject, Keyed {
|
||||
|
||||
public enum BasicType {
|
||||
BLOCKS("minecraft:block", Registry.Resource.BLOCK_TAGS,
|
||||
name -> Objects.requireNonNull(Block.fromNamespaceId(name)).id()),
|
||||
(name, registries) -> Objects.requireNonNull(Block.fromNamespaceId(name)).id()),
|
||||
ITEMS("minecraft:item", Registry.Resource.ITEM_TAGS,
|
||||
name -> Objects.requireNonNull(Material.fromNamespaceId(name)).id()),
|
||||
(name, registries) -> Objects.requireNonNull(Material.fromNamespaceId(name)).id()),
|
||||
FLUIDS("minecraft:fluid", Registry.Resource.FLUID_TAGS,
|
||||
name -> FluidRegistries.getFluid(name).ordinal()),
|
||||
(name, registries) -> FluidRegistries.getFluid(name).ordinal()),
|
||||
ENTITY_TYPES("minecraft:entity_type", Registry.Resource.ENTITY_TYPE_TAGS,
|
||||
name -> Objects.requireNonNull(EntityType.fromNamespaceId(name)).id()),
|
||||
(name, registries) -> Objects.requireNonNull(EntityType.fromNamespaceId(name)).id()),
|
||||
GAME_EVENTS("minecraft:game_event", Registry.Resource.GAMEPLAY_TAGS,
|
||||
name -> FluidRegistries.getFluid(name).ordinal()),
|
||||
(name, registries) -> FluidRegistries.getFluid(name).ordinal()),
|
||||
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 -> MinecraftServer.getEnchantmentRegistry().getId(DynamicRegistry.Key.of(name))),
|
||||
(name, registries) -> registries.enchantment().getId(DynamicRegistry.Key.of(name))),
|
||||
BIOMES("minecraft:worldgen/biome", Registry.Resource.BIOME_TAGS,
|
||||
name -> MinecraftServer.getBiomeRegistry().getId(DynamicRegistry.Key.of(name)));
|
||||
(name, registries) -> registries.biome().getId(DynamicRegistry.Key.of(name)));
|
||||
|
||||
private final static BasicType[] VALUES = values();
|
||||
private final String identifier;
|
||||
private final Registry.Resource resource;
|
||||
private final Function<String, Integer> function;
|
||||
private final BiFunction<String, Registries, Integer> function;
|
||||
|
||||
BasicType(@NotNull String identifier,
|
||||
@Nullable Registry.Resource resource,
|
||||
@Nullable Function<String, Integer> function) {
|
||||
@Nullable BiFunction<String, Registries, Integer> function) {
|
||||
this.identifier = identifier;
|
||||
this.resource = resource;
|
||||
this.function = function;
|
||||
@ -133,7 +131,7 @@ public final class Tag implements ProtocolObject, Keyed {
|
||||
return resource;
|
||||
}
|
||||
|
||||
public Function<String, Integer> getFunction() {
|
||||
public BiFunction<String, Registries, Integer> getFunction() {
|
||||
return function;
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,7 @@
|
||||
package net.minestom.server.gamedata.tags;
|
||||
|
||||
import net.minestom.server.network.packet.server.common.TagsPacket;
|
||||
import net.minestom.server.registry.Registries;
|
||||
import net.minestom.server.utils.NamespaceID;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
@ -40,20 +41,20 @@ public final class TagManager {
|
||||
return Collections.unmodifiableMap(tagMap);
|
||||
}
|
||||
|
||||
public TagsPacket packet() {
|
||||
List<TagsPacket.Registry> registries = new ArrayList<>();
|
||||
public TagsPacket packet(Registries registries) {
|
||||
List<TagsPacket.Registry> registryList = new ArrayList<>();
|
||||
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())).toArray();
|
||||
final int[] values = tag.getValues().stream().mapToInt(value -> type.getFunction().apply(value.asString(), registries)).toArray();
|
||||
tags.add(new TagsPacket.Tag(identifier, values));
|
||||
}
|
||||
registries.add(new TagsPacket.Registry(registry, tags));
|
||||
registryList.add(new TagsPacket.Registry(registry, tags));
|
||||
}
|
||||
return new TagsPacket(registries);
|
||||
return new TagsPacket(registryList);
|
||||
}
|
||||
|
||||
private Set<NamespaceID> getValues(Map<String, Map<String, Object>> main, String value) {
|
||||
|
@ -4,6 +4,7 @@ import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.format.NamedTextColor;
|
||||
import net.minestom.server.MinecraftServer;
|
||||
import net.minestom.server.ServerFlag;
|
||||
import net.minestom.server.ServerProcess;
|
||||
import net.minestom.server.entity.Player;
|
||||
import net.minestom.server.event.EventDispatcher;
|
||||
import net.minestom.server.event.player.AsyncPlayerConfigurationEvent;
|
||||
@ -24,6 +25,7 @@ import net.minestom.server.network.player.GameProfile;
|
||||
import net.minestom.server.network.player.PlayerConnection;
|
||||
import net.minestom.server.network.player.PlayerSocketConnection;
|
||||
import net.minestom.server.network.plugin.LoginPluginMessageProcessor;
|
||||
import net.minestom.server.registry.Registries;
|
||||
import net.minestom.server.registry.StaticProtocolObject;
|
||||
import net.minestom.server.utils.StringUtils;
|
||||
import net.minestom.server.utils.validate.Check;
|
||||
@ -44,10 +46,10 @@ public final class ConnectionManager {
|
||||
private static final Component TIMEOUT_TEXT = Component.text("Timeout", NamedTextColor.RED);
|
||||
private CachedPacket defaultTags;
|
||||
|
||||
private CachedPacket getDefaultTags() {
|
||||
private CachedPacket getDefaultTags(Registries registries) {
|
||||
var defaultTags = this.defaultTags;
|
||||
if (defaultTags == null) {
|
||||
final TagsPacket packet = MinecraftServer.getTagManager().packet();
|
||||
final TagsPacket packet = MinecraftServer.getTagManager().packet(registries);
|
||||
this.defaultTags = defaultTags = new CachedPacket(packet);
|
||||
}
|
||||
return defaultTags;
|
||||
@ -250,20 +252,20 @@ public final class ConnectionManager {
|
||||
}
|
||||
boolean excludeVanilla = knownPacks.contains(SelectKnownPacksPacket.MINECRAFT_CORE);
|
||||
|
||||
var serverProcess = MinecraftServer.process();
|
||||
player.sendPacket(serverProcess.chatType().registryDataPacket(excludeVanilla));
|
||||
player.sendPacket(serverProcess.dimensionType().registryDataPacket(excludeVanilla));
|
||||
player.sendPacket(serverProcess.biome().registryDataPacket(excludeVanilla));
|
||||
player.sendPacket(serverProcess.damageType().registryDataPacket(excludeVanilla));
|
||||
player.sendPacket(serverProcess.trimMaterial().registryDataPacket(excludeVanilla));
|
||||
player.sendPacket(serverProcess.trimPattern().registryDataPacket(excludeVanilla));
|
||||
player.sendPacket(serverProcess.bannerPattern().registryDataPacket(excludeVanilla));
|
||||
player.sendPacket(serverProcess.wolfVariant().registryDataPacket(excludeVanilla));
|
||||
player.sendPacket(serverProcess.enchantment().registryDataPacket(excludeVanilla));
|
||||
player.sendPacket(serverProcess.paintingVariant().registryDataPacket(excludeVanilla));
|
||||
player.sendPacket(serverProcess.jukeboxSong().registryDataPacket(excludeVanilla));
|
||||
Registries registries = MinecraftServer.process();
|
||||
player.sendPacket(registries.chatType().registryDataPacket(registries, excludeVanilla));
|
||||
player.sendPacket(registries.dimensionType().registryDataPacket(registries, excludeVanilla));
|
||||
player.sendPacket(registries.biome().registryDataPacket(registries, excludeVanilla));
|
||||
player.sendPacket(registries.damageType().registryDataPacket(registries, excludeVanilla));
|
||||
player.sendPacket(registries.trimMaterial().registryDataPacket(registries, excludeVanilla));
|
||||
player.sendPacket(registries.trimPattern().registryDataPacket(registries, excludeVanilla));
|
||||
player.sendPacket(registries.bannerPattern().registryDataPacket(registries, excludeVanilla));
|
||||
player.sendPacket(registries.wolfVariant().registryDataPacket(registries, excludeVanilla));
|
||||
player.sendPacket(registries.enchantment().registryDataPacket(registries, excludeVanilla));
|
||||
player.sendPacket(registries.paintingVariant().registryDataPacket(registries, excludeVanilla));
|
||||
player.sendPacket(registries.jukeboxSong().registryDataPacket(registries, excludeVanilla));
|
||||
|
||||
player.sendPacket(getDefaultTags());
|
||||
player.sendPacket(getDefaultTags(registries));
|
||||
}
|
||||
|
||||
// Wait for pending resource packs if any
|
||||
|
@ -213,10 +213,11 @@ public sealed interface DynamicRegistry<T> permits DynamicRegistryImpl {
|
||||
* <p>Returns a {@link SendablePacket} potentially excluding vanilla entries if possible. It is never possible to
|
||||
* exclude vanilla entries if one has been overridden (e.g. via {@link #register(NamespaceID, T)}.</p>
|
||||
*
|
||||
* @param registries Registries provider
|
||||
* @param excludeVanilla Whether to exclude vanilla entries
|
||||
* @return A {@link SendablePacket} containing the registry data
|
||||
*/
|
||||
@ApiStatus.Internal
|
||||
@NotNull SendablePacket registryDataPacket(boolean excludeVanilla);
|
||||
@NotNull SendablePacket registryDataPacket(@NotNull Registries registries, boolean excludeVanilla);
|
||||
|
||||
}
|
||||
|
@ -3,7 +3,6 @@ package net.minestom.server.registry;
|
||||
import net.kyori.adventure.nbt.BinaryTag;
|
||||
import net.kyori.adventure.nbt.CompoundBinaryTag;
|
||||
import net.kyori.adventure.nbt.TagStringIOExt;
|
||||
import net.minestom.server.MinecraftServer;
|
||||
import net.minestom.server.ServerFlag;
|
||||
import net.minestom.server.gamedata.DataPack;
|
||||
import net.minestom.server.network.packet.server.CachedPacket;
|
||||
@ -49,7 +48,8 @@ final class DynamicRegistryImpl<T> implements DynamicRegistry<T> {
|
||||
}
|
||||
}
|
||||
|
||||
private final CachedPacket vanillaRegistryDataPacket = new CachedPacket(() -> createRegistryDataPacket(true));
|
||||
private Registries registries = null;
|
||||
private CachedPacket vanillaRegistryDataPacket = new CachedPacket(() -> createRegistryDataPacket(registries, true));
|
||||
|
||||
private final ReentrantLock lock = new ReentrantLock(); // Protects writes
|
||||
private final List<T> entryById = new CopyOnWriteArrayList<>();
|
||||
@ -143,7 +143,9 @@ final class DynamicRegistryImpl<T> implements DynamicRegistry<T> {
|
||||
entryByName.put(namespaceId, object);
|
||||
idByName.add(namespaceId);
|
||||
packById.add(id, pack);
|
||||
vanillaRegistryDataPacket.invalidate();
|
||||
if (vanillaRegistryDataPacket != null) {
|
||||
vanillaRegistryDataPacket.invalidate();
|
||||
}
|
||||
return Key.of(namespaceId);
|
||||
} finally {
|
||||
lock.unlock();
|
||||
@ -163,7 +165,9 @@ final class DynamicRegistryImpl<T> implements DynamicRegistry<T> {
|
||||
entryByName.remove(namespaceId);
|
||||
idByName.remove(id);
|
||||
packById.remove(id);
|
||||
vanillaRegistryDataPacket.invalidate();
|
||||
if (vanillaRegistryDataPacket != null) {
|
||||
vanillaRegistryDataPacket.invalidate();
|
||||
}
|
||||
return true;
|
||||
} finally {
|
||||
lock.unlock();
|
||||
@ -171,15 +175,23 @@ final class DynamicRegistryImpl<T> implements DynamicRegistry<T> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull SendablePacket registryDataPacket(boolean excludeVanilla) {
|
||||
public @NotNull SendablePacket registryDataPacket(@NotNull Registries registries, boolean excludeVanilla) {
|
||||
// We cache the vanilla packet because that is by far the most common case. If some client claims not to have
|
||||
// the vanilla datapack we can compute the entire thing.
|
||||
return excludeVanilla ? vanillaRegistryDataPacket : createRegistryDataPacket(false);
|
||||
if (excludeVanilla) {
|
||||
if (this.registries != registries) {
|
||||
vanillaRegistryDataPacket.invalidate();
|
||||
this.registries = registries;
|
||||
}
|
||||
return vanillaRegistryDataPacket;
|
||||
}
|
||||
|
||||
return createRegistryDataPacket(registries, false);
|
||||
}
|
||||
|
||||
private @NotNull RegistryDataPacket createRegistryDataPacket(boolean excludeVanilla) {
|
||||
private @NotNull RegistryDataPacket createRegistryDataPacket(@NotNull Registries registries, boolean excludeVanilla) {
|
||||
Check.notNull(nbtType, "Cannot create registry data packet for server-only registry");
|
||||
BinaryTagSerializer.Context context = new BinaryTagSerializer.ContextWithRegistries(MinecraftServer.process(), true);
|
||||
BinaryTagSerializer.Context context = new BinaryTagSerializer.ContextWithRegistries(registries, true);
|
||||
List<RegistryDataPacket.Entry> entries = new ArrayList<>(entryById.size());
|
||||
for (int i = 0; i < entryById.size(); i++) {
|
||||
CompoundBinaryTag data = null;
|
||||
|
Loading…
Reference in New Issue
Block a user