Mirror von
https://github.com/GeyserMC/Geyser.git
synchronisiert 2024-11-16 04:50:07 +01:00
Merge remote-tracking branch 'origin/master' into feature/1.21.2
Dieser Commit ist enthalten in:
Commit
214cacff3b
@ -15,7 +15,7 @@ The ultimate goal of this project is to allow Minecraft: Bedrock Edition users t
|
||||
Special thanks to the DragonProxy project for being a trailblazer in protocol translation and for all the team members who have joined us here!
|
||||
|
||||
## Supported Versions
|
||||
Geyser is currently supporting Minecraft Bedrock 1.20.80 - 1.21.40 and Minecraft Java 1.21.2/1.21.3. For more information, please see [here](https://geysermc.org/wiki/geyser/supported-versions/).
|
||||
Geyser is currently supporting Minecraft Bedrock 1.20.80 - 1.21.43 and Minecraft Java 1.21.2/1.21.3. For more information, please see [here](https://geysermc.org/wiki/geyser/supported-versions/).
|
||||
|
||||
## Setting Up
|
||||
Take a look [here](https://geysermc.org/wiki/geyser/setup/) for how to set up Geyser.
|
||||
|
@ -70,6 +70,11 @@ public interface GeyserConnection extends Connection, CommandSource {
|
||||
*/
|
||||
void closeForm();
|
||||
|
||||
/**
|
||||
* Gets the Bedrock protocol version of the player.
|
||||
*/
|
||||
int protocolVersion();
|
||||
|
||||
/**
|
||||
* @param javaId the Java entity ID to look up.
|
||||
* @return a {@link GeyserEntity} if present in this connection's entity tracker.
|
||||
|
@ -231,9 +231,14 @@ public class GeyserImpl implements GeyserApi, EventRegistrar {
|
||||
}
|
||||
logger.info("******************************************");
|
||||
|
||||
/* Initialize registries */
|
||||
Registries.init();
|
||||
BlockRegistries.init();
|
||||
/*
|
||||
First load the registries and then populate them.
|
||||
Both the block registries and the common registries depend on each other,
|
||||
so maintaining this order is crucial for Geyser to load.
|
||||
*/
|
||||
Registries.load();
|
||||
BlockRegistries.populate();
|
||||
Registries.populate();
|
||||
|
||||
RegistryCache.init();
|
||||
|
||||
@ -723,7 +728,9 @@ public class GeyserImpl implements GeyserApi, EventRegistrar {
|
||||
runIfNonNull(newsHandler, NewsHandler::shutdown);
|
||||
runIfNonNull(erosionUnixListener, UnixSocketClientListener::close);
|
||||
|
||||
Registries.RESOURCE_PACKS.get().clear();
|
||||
if (Registries.RESOURCE_PACKS.loaded()) {
|
||||
Registries.RESOURCE_PACKS.get().clear();
|
||||
}
|
||||
|
||||
this.setEnabled(false);
|
||||
}
|
||||
|
@ -37,7 +37,6 @@ import org.geysermc.geyser.entity.properties.GeyserEntityProperties;
|
||||
import org.geysermc.geyser.entity.type.Entity;
|
||||
import org.geysermc.geyser.registry.Registries;
|
||||
import org.geysermc.geyser.translator.entity.EntityMetadataTranslator;
|
||||
import org.geysermc.geyser.util.EnvironmentUtils;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.EntityMetadata;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.MetadataType;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.entity.type.EntityType;
|
||||
@ -146,13 +145,8 @@ public record EntityDefinition<T extends Entity>(EntityFactory<T> factory, Entit
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build the given entity. If a testing environment has been discovered the entity is not registered,
|
||||
* otherwise it is. This is to prevent all the registries from loading, which will fail (and should
|
||||
* not be loaded) while testing
|
||||
*/
|
||||
public EntityDefinition<T> build() {
|
||||
return build(!EnvironmentUtils.isUnitTesting);
|
||||
return build(true);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -145,7 +145,6 @@ import org.geysermc.geyser.entity.type.living.monster.raid.VindicatorEntity;
|
||||
import org.geysermc.geyser.entity.type.player.PlayerEntity;
|
||||
import org.geysermc.geyser.registry.Registries;
|
||||
import org.geysermc.geyser.translator.text.MessageTranslator;
|
||||
import org.geysermc.geyser.util.EnvironmentUtils;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.MetadataType;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.BooleanEntityMetadata;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.FloatEntityMetadata;
|
||||
@ -1161,10 +1160,7 @@ public final class EntityDefinitions {
|
||||
.identifier("minecraft:armor_stand") // Emulated
|
||||
.build(false); // Never sent over the network
|
||||
|
||||
// causes the registries to load
|
||||
if (!EnvironmentUtils.isUnitTesting) {
|
||||
Registries.JAVA_ENTITY_IDENTIFIERS.get().put("minecraft:marker", null); // We don't need an entity definition for this as it is never sent over the network
|
||||
}
|
||||
Registries.JAVA_ENTITY_IDENTIFIERS.get().put("minecraft:marker", null); // We don't need an entity definition for this as it is never sent over the network
|
||||
}
|
||||
|
||||
private static EntityDefinition<BoatEntity> buildBoat(EntityDefinition<BoatEntity> base, EntityType entityType, BoatEntity.BoatVariant variant) {
|
||||
|
@ -32,7 +32,7 @@ import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataType;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* A write-only wrapper for temporarily storing entity metadata that will be sent to Bedrock.
|
||||
* A wrapper for temporarily storing entity metadata that will be sent to Bedrock.
|
||||
*/
|
||||
public final class GeyserDirtyMetadata {
|
||||
private final Map<EntityDataType<?>, Object> metadata = new Object2ObjectLinkedOpenHashMap<>();
|
||||
@ -53,6 +53,14 @@ public final class GeyserDirtyMetadata {
|
||||
return !metadata.isEmpty();
|
||||
}
|
||||
|
||||
/**
|
||||
* Intended for testing purposes only
|
||||
*/
|
||||
public <T> T get(EntityDataType<T> entityData) {
|
||||
//noinspection unchecked
|
||||
return (T) metadata.get(entityData);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return metadata.toString();
|
||||
|
@ -27,6 +27,7 @@ package org.geysermc.geyser.entity.type.living;
|
||||
|
||||
import lombok.Getter;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
import org.cloudburstmc.math.vector.Vector3f;
|
||||
import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataType;
|
||||
import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes;
|
||||
@ -36,6 +37,7 @@ import org.geysermc.geyser.entity.EntityDefinition;
|
||||
import org.geysermc.geyser.entity.EntityDefinitions;
|
||||
import org.geysermc.geyser.entity.type.LivingEntity;
|
||||
import org.geysermc.geyser.item.Items;
|
||||
import org.geysermc.geyser.scoreboard.Team;
|
||||
import org.geysermc.geyser.session.GeyserSession;
|
||||
import org.geysermc.geyser.util.InteractionResult;
|
||||
import org.geysermc.geyser.util.MathUtils;
|
||||
@ -123,6 +125,12 @@ public class ArmorStandEntity extends LivingEntity {
|
||||
this.position = position;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateNametag(@Nullable Team team) {
|
||||
// unlike all other LivingEntities, armor stands are not affected by team nametag visibility
|
||||
super.updateNametag(team, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setDisplayName(EntityMetadata<Optional<Component>, ?> entityMetadata) {
|
||||
super.setDisplayName(entityMetadata);
|
||||
|
@ -43,7 +43,6 @@ import org.cloudburstmc.protocol.bedrock.data.AbilityLayer;
|
||||
import org.cloudburstmc.protocol.bedrock.data.GameType;
|
||||
import org.cloudburstmc.protocol.bedrock.data.PlayerPermission;
|
||||
import org.cloudburstmc.protocol.bedrock.data.command.CommandPermission;
|
||||
import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataMap;
|
||||
import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes;
|
||||
import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag;
|
||||
import org.cloudburstmc.protocol.bedrock.data.entity.EntityLinkData;
|
||||
@ -112,20 +111,6 @@ public class PlayerEntity extends LivingEntity implements GeyserPlayerEntity {
|
||||
this.texturesProperty = texturesProperty;
|
||||
}
|
||||
|
||||
/**
|
||||
* Do not use! For testing purposes only
|
||||
*/
|
||||
public PlayerEntity(GeyserSession session, long geyserId, UUID uuid, String username) {
|
||||
super(session, -1, geyserId, uuid, EntityDefinitions.PLAYER, Vector3f.ZERO, Vector3f.ZERO, 0, 0, 0);
|
||||
this.username = username;
|
||||
this.nametag = username;
|
||||
this.texturesProperty = null;
|
||||
|
||||
// clear initial metadata
|
||||
dirtyMetadata.apply(new EntityDataMap());
|
||||
setFlagsDirty(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void initializeMetadata() {
|
||||
super.initializeMetadata();
|
||||
@ -193,11 +178,7 @@ public class PlayerEntity extends LivingEntity implements GeyserPlayerEntity {
|
||||
if (session.getEntityCache().getPlayerEntity(uuid) == null)
|
||||
return;
|
||||
|
||||
if (session.getEntityCache().getEntityByGeyserId(geyserId) == null) {
|
||||
session.getEntityCache().spawnEntity(this);
|
||||
} else {
|
||||
spawnEntity();
|
||||
}
|
||||
session.getEntityCache().spawnEntity(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -52,7 +52,7 @@ public final class GameProtocol {
|
||||
* release of the game that Geyser supports.
|
||||
*/
|
||||
public static final BedrockCodec DEFAULT_BEDROCK_CODEC = CodecProcessor.processCodec(Bedrock_v748.CODEC.toBuilder()
|
||||
.minecraftVersion("1.21.40")
|
||||
.minecraftVersion("1.21.43")
|
||||
.build());
|
||||
|
||||
/**
|
||||
@ -80,10 +80,10 @@ public final class GameProtocol {
|
||||
.minecraftVersion("1.21.20 - 1.21.23")
|
||||
.build()));
|
||||
SUPPORTED_BEDROCK_CODECS.add(CodecProcessor.processCodec(Bedrock_v729.CODEC.toBuilder()
|
||||
.minecraftVersion("1.21.30/1.21.31")
|
||||
.build()));
|
||||
.minecraftVersion("1.21.30/1.21.31")
|
||||
.build()));
|
||||
SUPPORTED_BEDROCK_CODECS.add(DEFAULT_BEDROCK_CODEC.toBuilder()
|
||||
.minecraftVersion("1.21.40")
|
||||
.minecraftVersion("1.21.40/1.21.41/1.21.43")
|
||||
.build());
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,103 @@
|
||||
/*
|
||||
* Copyright (c) 2024 GeyserMC. http://geysermc.org
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
* @author GeyserMC
|
||||
* @link https://github.com/GeyserMC/Geyser
|
||||
*/
|
||||
|
||||
package org.geysermc.geyser.registry;
|
||||
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
import org.geysermc.geyser.registry.loader.RegistryLoader;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
public abstract class AbstractMappedDeferredRegistry<K, V, M extends Map<K, V>, R extends AbstractMappedRegistry<K, V, M>> extends DeferredRegistry<M, R> {
|
||||
protected <I> AbstractMappedDeferredRegistry(Function<RegistryLoader<I, M>, R> registryLoader, RegistryLoader<I, M> deferredLoader) {
|
||||
super(registryLoader, deferredLoader);
|
||||
}
|
||||
|
||||
protected <I> AbstractMappedDeferredRegistry(Function<RegistryLoader<I, M>, R> registryLoader, Supplier<RegistryLoader<I, M>> deferredLoader) {
|
||||
super(registryLoader, deferredLoader);
|
||||
}
|
||||
|
||||
protected <I> AbstractMappedDeferredRegistry(I input, RegistryInitializer<M, R> registryInitializer, RegistryLoader<I, M> deferredLoader) {
|
||||
super(input, registryInitializer, deferredLoader);
|
||||
}
|
||||
|
||||
protected <I> AbstractMappedDeferredRegistry(I input, RegistryInitializer<M, R> registryInitializer, Supplier<RegistryLoader<I, M>> deferredLoader) {
|
||||
super(input, registryInitializer, deferredLoader);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the value registered by the given key.
|
||||
*
|
||||
* @param key the key
|
||||
* @return the value registered by the given key.
|
||||
*/
|
||||
public @Nullable V get(K key) {
|
||||
return get().get(key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns and maps the value by the given key if present.
|
||||
*
|
||||
* @param key the key
|
||||
* @param mapper the mapper
|
||||
* @param <U> the type
|
||||
* @return the mapped value from the given key if present
|
||||
*/
|
||||
public <U> Optional<U> map(K key, Function<? super V, ? extends U> mapper) {
|
||||
V value = this.get(key);
|
||||
if (value == null) {
|
||||
return Optional.empty();
|
||||
} else {
|
||||
return Optional.ofNullable(mapper.apply(value));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the value registered by the given key or the default value
|
||||
* specified if null.
|
||||
*
|
||||
* @param key the key
|
||||
* @param defaultValue the default value
|
||||
* @return the value registered by the given key or the default value
|
||||
* specified if null.
|
||||
*/
|
||||
public V getOrDefault(K key, V defaultValue) {
|
||||
return get().getOrDefault(key, defaultValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a new value into this registry with the given key.
|
||||
*
|
||||
* @param key the key
|
||||
* @param value the value
|
||||
* @return a new value into this registry with the given key.
|
||||
*/
|
||||
public V register(K key, V value) {
|
||||
return get().put(key, value);
|
||||
}
|
||||
}
|
@ -69,7 +69,7 @@ public class BlockRegistries {
|
||||
/**
|
||||
* A mapped registry containing which holds block IDs to its {@link BlockCollision}.
|
||||
*/
|
||||
public static final ListRegistry<BlockCollision> COLLISIONS;
|
||||
public static final ListDeferredRegistry<BlockCollision> COLLISIONS = ListDeferredRegistry.create(Pair.of("org.geysermc.geyser.translator.collision.CollisionRemapper", "mappings/collisions.nbt"), CollisionRegistryLoader::new);
|
||||
|
||||
/**
|
||||
* A registry which stores Java IDs to {@link Block}, containing miscellaneous information about
|
||||
@ -130,22 +130,17 @@ public class BlockRegistries {
|
||||
*/
|
||||
public static final SimpleMappedRegistry<String, CustomSkull> CUSTOM_SKULLS = SimpleMappedRegistry.create(RegistryLoaders.empty(Object2ObjectOpenHashMap::new));
|
||||
|
||||
static {
|
||||
public static void populate() {
|
||||
Blocks.VAULT.javaId(); // FIXME
|
||||
CustomSkullRegistryPopulator.populate();
|
||||
BlockRegistryPopulator.populate(BlockRegistryPopulator.Stage.PRE_INIT);
|
||||
CustomBlockRegistryPopulator.populate(CustomBlockRegistryPopulator.Stage.DEFINITION);
|
||||
CustomBlockRegistryPopulator.populate(CustomBlockRegistryPopulator.Stage.NON_VANILLA_REGISTRATION);
|
||||
BlockRegistryPopulator.populate(BlockRegistryPopulator.Stage.INIT_JAVA);
|
||||
COLLISIONS = ListRegistry.create(Pair.of("org.geysermc.geyser.translator.collision.CollisionRemapper", "mappings/collisions.nbt"), CollisionRegistryLoader::new);
|
||||
COLLISIONS.load();
|
||||
CustomBlockRegistryPopulator.populate(CustomBlockRegistryPopulator.Stage.VANILLA_REGISTRATION);
|
||||
CustomBlockRegistryPopulator.populate(CustomBlockRegistryPopulator.Stage.CUSTOM_REGISTRATION);
|
||||
BlockRegistryPopulator.populate(BlockRegistryPopulator.Stage.INIT_BEDROCK);
|
||||
BlockRegistryPopulator.populate(BlockRegistryPopulator.Stage.POST_INIT);
|
||||
}
|
||||
|
||||
public static void init() {
|
||||
// no-op
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -43,32 +43,36 @@ import java.util.function.Supplier;
|
||||
*
|
||||
* @param <M> the value being held by the registry
|
||||
*/
|
||||
public final class DeferredRegistry<M> implements IRegistry<M> {
|
||||
private final Registry<M> backingRegistry;
|
||||
class DeferredRegistry<M, R extends IRegistry<M>> implements IRegistry<M> {
|
||||
private final R backingRegistry;
|
||||
private final Supplier<M> loader;
|
||||
|
||||
private boolean loaded;
|
||||
|
||||
private <I> DeferredRegistry(Function<RegistryLoader<I, M>, Registry<M>> registryLoader, RegistryLoader<I, M> deferredLoader) {
|
||||
protected <I> DeferredRegistry(Function<RegistryLoader<I, M>, R> registryLoader, RegistryLoader<I, M> deferredLoader) {
|
||||
this.backingRegistry = registryLoader.apply(RegistryLoaders.uninitialized());
|
||||
this.loader = () -> deferredLoader.load(null);
|
||||
}
|
||||
|
||||
private <I> DeferredRegistry(Function<RegistryLoader<I, M>, Registry<M>> registryLoader, Supplier<RegistryLoader<I, M>> deferredLoader) {
|
||||
protected <I> DeferredRegistry(Function<RegistryLoader<I, M>, R> registryLoader, Supplier<RegistryLoader<I, M>> deferredLoader) {
|
||||
this.backingRegistry = registryLoader.apply(RegistryLoaders.uninitialized());
|
||||
this.loader = () -> deferredLoader.get().load(null);
|
||||
}
|
||||
|
||||
private <I> DeferredRegistry(I input, RegistryInitializer<M> registryInitializer, RegistryLoader<I, M> deferredLoader) {
|
||||
protected <I> DeferredRegistry(I input, RegistryInitializer<M, R> registryInitializer, RegistryLoader<I, M> deferredLoader) {
|
||||
this.backingRegistry = registryInitializer.initialize(input, RegistryLoaders.uninitialized());
|
||||
this.loader = () -> deferredLoader.load(input);
|
||||
}
|
||||
|
||||
private <I> DeferredRegistry(I input, RegistryInitializer<M> registryInitializer, Supplier<RegistryLoader<I, M>> deferredLoader) {
|
||||
protected <I> DeferredRegistry(I input, RegistryInitializer<M, R> registryInitializer, Supplier<RegistryLoader<I, M>> deferredLoader) {
|
||||
this.backingRegistry = registryInitializer.initialize(input, RegistryLoaders.uninitialized());
|
||||
this.loader = () -> deferredLoader.get().load(input);
|
||||
}
|
||||
|
||||
protected R backingRegistry() {
|
||||
return this.backingRegistry;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the underlying value held by this registry.
|
||||
*
|
||||
@ -113,55 +117,10 @@ public final class DeferredRegistry<M> implements IRegistry<M> {
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new deferred registry.
|
||||
*
|
||||
* @param registryLoader the registry loader
|
||||
* @param deferredLoader the deferred loader
|
||||
* @param <I> the input type
|
||||
* @param <M> the registry type
|
||||
* @return the new deferred registry
|
||||
* Whether this registry was loaded.
|
||||
*/
|
||||
public static <I, M> DeferredRegistry<M> create(Function<RegistryLoader<I, M>, Registry<M>> registryLoader, RegistryLoader<I, M> deferredLoader) {
|
||||
return new DeferredRegistry<>(registryLoader, deferredLoader);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new deferred registry.
|
||||
*
|
||||
* @param registryLoader the registry loader
|
||||
* @param deferredLoader the deferred loader
|
||||
* @param <I> the input type
|
||||
* @param <M> the registry type
|
||||
* @return the new deferred registry
|
||||
*/
|
||||
public static <I, M> DeferredRegistry<M> create(Function<RegistryLoader<I, M>, Registry<M>> registryLoader, Supplier<RegistryLoader<I, M>> deferredLoader) {
|
||||
return new DeferredRegistry<>(registryLoader, deferredLoader);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new deferred registry.
|
||||
*
|
||||
* @param registryInitializer the registry initializer
|
||||
* @param deferredLoader the deferred loader
|
||||
* @param <I> the input type
|
||||
* @param <M> the registry type
|
||||
* @return the new deferred registry
|
||||
*/
|
||||
public static <I, M> DeferredRegistry<M> create(I input, RegistryInitializer<M> registryInitializer, RegistryLoader<I, M> deferredLoader) {
|
||||
return new DeferredRegistry<>(input, registryInitializer, deferredLoader);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new deferred registry.
|
||||
*
|
||||
* @param registryInitializer the registry initializer
|
||||
* @param deferredLoader the deferred loader
|
||||
* @param <I> the input type
|
||||
* @param <M> the registry type
|
||||
* @return the new deferred registry
|
||||
*/
|
||||
public static <I, M> DeferredRegistry<M> create(I input, RegistryInitializer<M> registryInitializer, Supplier<RegistryLoader<I, M>> deferredLoader) {
|
||||
return new DeferredRegistry<>(input, registryInitializer, deferredLoader);
|
||||
public boolean loaded() {
|
||||
return this.loaded;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -169,7 +128,7 @@ public final class DeferredRegistry<M> implements IRegistry<M> {
|
||||
*
|
||||
* @param <M> the registry type
|
||||
*/
|
||||
interface RegistryInitializer<M> {
|
||||
public interface RegistryInitializer<M, R extends IRegistry<M>> {
|
||||
|
||||
/**
|
||||
* Initializes the registry.
|
||||
@ -179,6 +138,6 @@ public final class DeferredRegistry<M> implements IRegistry<M> {
|
||||
* @param <I> the input type
|
||||
* @return the initialized registry
|
||||
*/
|
||||
<I> Registry<M> initialize(I input, RegistryLoader<I, M> registryLoader);
|
||||
<I> R initialize(I input, RegistryLoader<I, M> registryLoader);
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,175 @@
|
||||
/*
|
||||
* Copyright (c) 2024 GeyserMC. http://geysermc.org
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
* @author GeyserMC
|
||||
* @link https://github.com/GeyserMC/Geyser
|
||||
*/
|
||||
|
||||
package org.geysermc.geyser.registry;
|
||||
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
import org.geysermc.geyser.registry.loader.RegistryLoader;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
public class ListDeferredRegistry<V> extends DeferredRegistry<List<V>, ListRegistry<V>> {
|
||||
protected <I> ListDeferredRegistry(Function<RegistryLoader<I, List<V>>, ListRegistry<V>> registryLoader, RegistryLoader<I, List<V>> deferredLoader) {
|
||||
super(registryLoader, deferredLoader);
|
||||
}
|
||||
|
||||
protected <I> ListDeferredRegistry(Function<RegistryLoader<I, List<V>>, ListRegistry<V>> registryLoader, Supplier<RegistryLoader<I, List<V>>> deferredLoader) {
|
||||
super(registryLoader, deferredLoader);
|
||||
}
|
||||
|
||||
protected <I> ListDeferredRegistry(I input, RegistryInitializer<List<V>, ListRegistry<V>> registryInitializer, RegistryLoader<I, List<V>> deferredLoader) {
|
||||
super(input, registryInitializer, deferredLoader);
|
||||
}
|
||||
|
||||
protected <I> ListDeferredRegistry(I input, RegistryInitializer<List<V>, ListRegistry<V>> registryInitializer, Supplier<RegistryLoader<I, List<V>>> deferredLoader) {
|
||||
super(input, registryInitializer, deferredLoader);
|
||||
}
|
||||
/**
|
||||
* Returns the value registered by the given index.
|
||||
*
|
||||
* @param index the index
|
||||
* @return the value registered by the given index.
|
||||
*/
|
||||
@Nullable
|
||||
public V get(int index) {
|
||||
return backingRegistry().get(index);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the value registered by the given index or the default value
|
||||
* specified if null.
|
||||
*
|
||||
* @param index the index
|
||||
* @param defaultValue the default value
|
||||
* @return the value registered by the given key or the default value
|
||||
* specified if null.
|
||||
*/
|
||||
public V getOrDefault(int index, V defaultValue) {
|
||||
return backingRegistry().getOrDefault(index, defaultValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a new value into this registry with the given index.
|
||||
*
|
||||
* @param index the index
|
||||
* @param value the value
|
||||
* @return a new value into this registry with the given index.
|
||||
*/
|
||||
public V register(int index, V value) {
|
||||
return backingRegistry().register(index, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a new value into this registry with the given index, even if this value would normally be outside
|
||||
* the range of a list.
|
||||
*
|
||||
* @param index the index
|
||||
* @param value the value
|
||||
* @param defaultValue the default value to fill empty spaces in the registry with.
|
||||
* @return a new value into this registry with the given index.
|
||||
*/
|
||||
public V registerWithAnyIndex(int index, V value, V defaultValue) {
|
||||
return backingRegistry().registerWithAnyIndex(index, value, defaultValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* Mark this registry as unsuitable for new additions. The backing list will then be optimized for storage.
|
||||
*/
|
||||
public void freeze() {
|
||||
backingRegistry().freeze();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new deferred registry.
|
||||
*
|
||||
* @param registryLoader the registry loader
|
||||
* @param deferredLoader the deferred loader
|
||||
* @param <I> the input type
|
||||
* @return the new deferred registry
|
||||
*/
|
||||
public static <I, V> ListDeferredRegistry<V> create(Function<RegistryLoader<I, List<V>>, ListRegistry<V>> registryLoader, RegistryLoader<I, List<V>> deferredLoader) {
|
||||
return new ListDeferredRegistry<>(registryLoader, deferredLoader);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new deferred registry.
|
||||
*
|
||||
* @param registryLoader the registry loader
|
||||
* @param deferredLoader the deferred loader
|
||||
* @param <I> the input type
|
||||
* @return the new deferred registry
|
||||
*/
|
||||
public static <I, V> ListDeferredRegistry<V> create(Function<RegistryLoader<I, List<V>>, ListRegistry<V>> registryLoader, Supplier<RegistryLoader<I, List<V>>> deferredLoader) {
|
||||
return new ListDeferredRegistry<>(registryLoader, deferredLoader);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new deferred registry.
|
||||
*
|
||||
* @param registryInitializer the registry initializer
|
||||
* @param deferredLoader the deferred loader
|
||||
* @param <I> the input type
|
||||
* @return the new deferred registry
|
||||
*/
|
||||
public static <I, V> ListDeferredRegistry<V> create(I input, RegistryInitializer<List<V>, ListRegistry<V>> registryInitializer, RegistryLoader<I, List<V>> deferredLoader) {
|
||||
return new ListDeferredRegistry<>(input, registryInitializer, deferredLoader);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new deferred registry.
|
||||
*
|
||||
* @param registryInitializer the registry initializer
|
||||
* @param deferredLoader the deferred loader
|
||||
* @param <I> the input type
|
||||
* @return the new deferred registry
|
||||
*/
|
||||
public static <I, V> ListDeferredRegistry<V> create(I input, RegistryInitializer<List<V>, ListRegistry<V>> registryInitializer, Supplier<RegistryLoader<I, List<V>>> deferredLoader) {
|
||||
return new ListDeferredRegistry<>(input, registryInitializer, deferredLoader);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new deferred registry.
|
||||
*
|
||||
* @param deferredLoader the deferred loader
|
||||
* @param <I> the input type
|
||||
* @return the new deferred registry
|
||||
*/
|
||||
public static <I, V> ListDeferredRegistry<V> create(I input, RegistryLoader<I, List<V>> deferredLoader) {
|
||||
return create(input, ListRegistry::create, deferredLoader);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new deferred registry.
|
||||
*
|
||||
* @param deferredLoader the deferred loader
|
||||
* @param <I> the input type
|
||||
* @return the new deferred registry
|
||||
*/
|
||||
public static <I, V> ListDeferredRegistry<V> create(I input, Supplier<RegistryLoader<I, List<V>>> deferredLoader) {
|
||||
return create(input, ListRegistry::create, deferredLoader);
|
||||
}
|
||||
}
|
@ -140,6 +140,18 @@ public class ListRegistry<M> extends Registry<List<M>> {
|
||||
return new ListRegistry<>(null, registryLoader);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new integer mapped registry with the given {@link RegistryLoader} and input.
|
||||
*
|
||||
* @param registryLoader the registry loader
|
||||
* @param <I> the input
|
||||
* @param <M> the type value
|
||||
* @return a new registry with the given RegistryLoader
|
||||
*/
|
||||
public static <I, M> ListRegistry<M> create(I input, RegistryLoader<I, List<M>> registryLoader) {
|
||||
return new ListRegistry<>(input, registryLoader);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new integer mapped registry with the given {@link RegistryLoader} and input.
|
||||
*
|
||||
|
@ -73,6 +73,8 @@ import java.util.Set;
|
||||
* Holds all the common registries in Geyser.
|
||||
*/
|
||||
public final class Registries {
|
||||
private static boolean loaded = false;
|
||||
|
||||
/**
|
||||
* A registry holding all the providers.
|
||||
* This has to be initialized first to allow extensions to access providers during other registry events.
|
||||
@ -80,9 +82,9 @@ public final class Registries {
|
||||
public static final SimpleMappedRegistry<Class<?>, ProviderSupplier> PROVIDERS = SimpleMappedRegistry.create(new IdentityHashMap<>(), ProviderRegistryLoader::new);
|
||||
|
||||
/**
|
||||
* A registry holding a CompoundTag of the known entity identifiers.
|
||||
* A registry holding a NbtMap of the known entity identifiers.
|
||||
*/
|
||||
public static final SimpleRegistry<NbtMap> BEDROCK_ENTITY_IDENTIFIERS = SimpleRegistry.create("bedrock/entity_identifiers.dat", RegistryLoaders.NBT);
|
||||
public static final SimpleDeferredRegistry<NbtMap> BEDROCK_ENTITY_IDENTIFIERS = SimpleDeferredRegistry.create("bedrock/entity_identifiers.dat", RegistryLoaders.NBT);
|
||||
|
||||
/**
|
||||
* A registry containing all the Bedrock packet translators.
|
||||
@ -90,19 +92,19 @@ public final class Registries {
|
||||
public static final PacketTranslatorRegistry<BedrockPacket> BEDROCK_PACKET_TRANSLATORS = PacketTranslatorRegistry.create();
|
||||
|
||||
/**
|
||||
* A registry holding a CompoundTag of all the known biomes.
|
||||
* A registry holding a NbtMap of all the known biomes.
|
||||
*/
|
||||
public static final SimpleRegistry<NbtMap> BIOMES_NBT = SimpleRegistry.create("bedrock/biome_definitions.dat", RegistryLoaders.NBT);
|
||||
public static final SimpleDeferredRegistry<NbtMap> BIOMES_NBT = SimpleDeferredRegistry.create("bedrock/biome_definitions.dat", RegistryLoaders.NBT);
|
||||
|
||||
/**
|
||||
* A mapped registry which stores Java biome identifiers and their Bedrock biome identifier.
|
||||
*/
|
||||
public static final SimpleRegistry<Object2IntMap<String>> BIOME_IDENTIFIERS = SimpleRegistry.create("mappings/biomes.json", BiomeIdentifierRegistryLoader::new);
|
||||
public static final SimpleDeferredRegistry<Object2IntMap<String>> BIOME_IDENTIFIERS = SimpleDeferredRegistry.create("mappings/biomes.json", BiomeIdentifierRegistryLoader::new);
|
||||
|
||||
/**
|
||||
* A mapped registry which stores a block entity identifier to its {@link BlockEntityTranslator}.
|
||||
*/
|
||||
public static final SimpleMappedRegistry<BlockEntityType, BlockEntityTranslator> BLOCK_ENTITIES = SimpleMappedRegistry.create("org.geysermc.geyser.translator.level.block.entity.BlockEntity", BlockEntityRegistryLoader::new);
|
||||
public static final SimpleMappedDeferredRegistry<BlockEntityType, BlockEntityTranslator> BLOCK_ENTITIES = SimpleMappedDeferredRegistry.create("org.geysermc.geyser.translator.level.block.entity.BlockEntity", BlockEntityRegistryLoader::new);
|
||||
|
||||
/**
|
||||
* A map containing all entity types and their respective Geyser definitions
|
||||
@ -129,6 +131,9 @@ public final class Registries {
|
||||
*/
|
||||
public static final ListRegistry<Item> JAVA_ITEMS = ListRegistry.create(RegistryLoaders.empty(ArrayList::new));
|
||||
|
||||
/**
|
||||
* A registry containing item identifiers.
|
||||
*/
|
||||
public static final SimpleMappedRegistry<String, Item> JAVA_ITEM_IDENTIFIERS = SimpleMappedRegistry.create(RegistryLoaders.empty(Object2ObjectOpenHashMap::new));
|
||||
|
||||
/**
|
||||
@ -141,48 +146,65 @@ public final class Registries {
|
||||
* A mapped registry holding the {@link ParticleType} to a corresponding {@link ParticleMapping}, containing various pieces of
|
||||
* data primarily for how Bedrock should handle the particle.
|
||||
*/
|
||||
public static final SimpleMappedRegistry<ParticleType, ParticleMapping> PARTICLES = SimpleMappedRegistry.create("mappings/particles.json", ParticleTypesRegistryLoader::new);
|
||||
public static final SimpleMappedDeferredRegistry<ParticleType, ParticleMapping> PARTICLES = SimpleMappedDeferredRegistry.create("mappings/particles.json", ParticleTypesRegistryLoader::new);
|
||||
|
||||
/**
|
||||
* A registry holding all the potion mixes.
|
||||
*/
|
||||
public static final VersionedRegistry<Set<PotionMixData>> POTION_MIXES;
|
||||
public static final VersionedDeferredRegistry<Set<PotionMixData>> POTION_MIXES = VersionedDeferredRegistry.create(VersionedRegistry::create, PotionMixRegistryLoader::new);
|
||||
|
||||
/**
|
||||
* A versioned registry holding all the recipes, with the net ID being the key, and {@link GeyserRecipe} as the value.
|
||||
*/
|
||||
//public static final SimpleMappedRegistry<RecipeType, List<GeyserRecipe>> RECIPES = SimpleMappedRegistry.create("mappings/recipes.nbt", RecipeRegistryLoader::new);
|
||||
//public static final SimpleMappedDeferredRegistry<RecipeType, List<GeyserRecipe>> RECIPES = SimpleMappedDeferredRegistry.create("mappings/recipes.nbt", RecipeRegistryLoader::new);
|
||||
|
||||
/**
|
||||
* A mapped registry holding {@link ResourcePack}'s with the pack uuid as keys.
|
||||
*/
|
||||
public static final DeferredRegistry<Map<String, ResourcePack>> RESOURCE_PACKS = DeferredRegistry.create(GeyserImpl.getInstance().packDirectory(), SimpleMappedRegistry::create, RegistryLoaders.RESOURCE_PACKS);
|
||||
public static final SimpleMappedDeferredRegistry<String, ResourcePack> RESOURCE_PACKS = SimpleMappedDeferredRegistry.create(GeyserImpl.getInstance().packDirectory(), RegistryLoaders.RESOURCE_PACKS);
|
||||
|
||||
/**
|
||||
* A mapped registry holding sound identifiers to their corresponding {@link SoundMapping}.
|
||||
*/
|
||||
public static final SimpleMappedRegistry<String, SoundMapping> SOUNDS = SimpleMappedRegistry.create("mappings/sounds.json", SoundRegistryLoader::new);
|
||||
public static final SimpleMappedDeferredRegistry<String, SoundMapping> SOUNDS = SimpleMappedDeferredRegistry.create("mappings/sounds.json", SoundRegistryLoader::new);
|
||||
|
||||
/**
|
||||
* A mapped registry holding {@link LevelEvent}s to their corresponding {@link LevelEventTranslator}.
|
||||
*/
|
||||
public static final SimpleMappedRegistry<LevelEvent, LevelEventTranslator> SOUND_LEVEL_EVENTS = SimpleMappedRegistry.create("mappings/effects.json", SoundEventsRegistryLoader::new);
|
||||
public static final SimpleMappedDeferredRegistry<LevelEvent, LevelEventTranslator> SOUND_LEVEL_EVENTS = SimpleMappedDeferredRegistry.create("mappings/effects.json", SoundEventsRegistryLoader::new);
|
||||
|
||||
/**
|
||||
* A mapped registry holding {@link SoundTranslator}s to their corresponding {@link SoundInteractionTranslator}.
|
||||
*/
|
||||
public static final SimpleMappedRegistry<SoundTranslator, SoundInteractionTranslator<?>> SOUND_TRANSLATORS = SimpleMappedRegistry.create("org.geysermc.geyser.translator.sound.SoundTranslator", SoundTranslatorRegistryLoader::new);
|
||||
public static final SimpleMappedDeferredRegistry<SoundTranslator, SoundInteractionTranslator<?>> SOUND_TRANSLATORS = SimpleMappedDeferredRegistry.create("org.geysermc.geyser.translator.sound.SoundTranslator", SoundTranslatorRegistryLoader::new);
|
||||
|
||||
public static void init() {
|
||||
// no-op
|
||||
public static void load() {
|
||||
if (loaded) return;
|
||||
loaded = true;
|
||||
|
||||
// the following registries are registries that are more complicated than initializing as an empty collection.
|
||||
// They generally have in common that they either depend on loading a resource file directly or indirectly
|
||||
// (by using the Items or Blocks class, which loads all the blocks)
|
||||
|
||||
BEDROCK_ENTITY_IDENTIFIERS.load();
|
||||
BIOMES_NBT.load();
|
||||
BIOME_IDENTIFIERS.load();
|
||||
BLOCK_ENTITIES.load();
|
||||
PARTICLES.load();
|
||||
// load potion mixes later
|
||||
//RECIPES.load();
|
||||
RESOURCE_PACKS.load();
|
||||
SOUNDS.load();
|
||||
SOUND_LEVEL_EVENTS.load();
|
||||
SOUND_TRANSLATORS.load();
|
||||
}
|
||||
|
||||
static {
|
||||
public static void populate() {
|
||||
PacketRegistryPopulator.populate();
|
||||
ItemRegistryPopulator.populate();
|
||||
|
||||
// Create registries that require other registries to load first
|
||||
POTION_MIXES = VersionedRegistry.create(PotionMixRegistryLoader::new);
|
||||
// potion mixes depend on other registries
|
||||
POTION_MIXES.load();
|
||||
|
||||
// Remove unneeded client generation data from NbtMapBuilder
|
||||
NbtMapBuilder biomesNbt = NbtMap.builder();
|
||||
|
@ -25,9 +25,8 @@
|
||||
|
||||
package org.geysermc.geyser.registry;
|
||||
|
||||
import org.geysermc.geyser.registry.loader.RegistryLoader;
|
||||
|
||||
import java.util.function.Consumer;
|
||||
import org.geysermc.geyser.registry.loader.RegistryLoader;
|
||||
|
||||
/**
|
||||
* A wrapper around a value which is loaded based on the output from the provided
|
||||
@ -111,4 +110,4 @@ public abstract class Registry<M> implements IRegistry<M> {
|
||||
public void register(Consumer<M> consumer) {
|
||||
consumer.accept(this.mappings);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,119 @@
|
||||
/*
|
||||
* Copyright (c) 2024 GeyserMC. http://geysermc.org
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
* @author GeyserMC
|
||||
* @link https://github.com/GeyserMC/Geyser
|
||||
*/
|
||||
|
||||
package org.geysermc.geyser.registry;
|
||||
|
||||
import org.geysermc.geyser.registry.loader.RegistryLoader;
|
||||
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
public class SimpleDeferredRegistry<V> extends DeferredRegistry<V, SimpleRegistry<V>> {
|
||||
protected <I> SimpleDeferredRegistry(Function<RegistryLoader<I, V>, SimpleRegistry<V>> registryLoader, RegistryLoader<I, V> deferredLoader) {
|
||||
super(registryLoader, deferredLoader);
|
||||
}
|
||||
|
||||
protected <I> SimpleDeferredRegistry(Function<RegistryLoader<I, V>, SimpleRegistry<V>> registryLoader, Supplier<RegistryLoader<I, V>> deferredLoader) {
|
||||
super(registryLoader, deferredLoader);
|
||||
}
|
||||
|
||||
protected <I> SimpleDeferredRegistry(I input, RegistryInitializer<V, SimpleRegistry<V>> registryInitializer, RegistryLoader<I, V> deferredLoader) {
|
||||
super(input, registryInitializer, deferredLoader);
|
||||
}
|
||||
|
||||
protected <I> SimpleDeferredRegistry(I input, RegistryInitializer<V, SimpleRegistry<V>> registryInitializer, Supplier<RegistryLoader<I, V>> deferredLoader) {
|
||||
super(input, registryInitializer, deferredLoader);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new deferred registry.
|
||||
*
|
||||
* @param registryLoader the registry loader
|
||||
* @param deferredLoader the deferred loader
|
||||
* @param <I> the input type
|
||||
* @return the new deferred registry
|
||||
*/
|
||||
public static <I, V> SimpleDeferredRegistry<V> create(Function<RegistryLoader<I, V>, SimpleRegistry<V>> registryLoader, RegistryLoader<I, V> deferredLoader) {
|
||||
return new SimpleDeferredRegistry<>(registryLoader, deferredLoader);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new deferred registry.
|
||||
*
|
||||
* @param registryLoader the registry loader
|
||||
* @param deferredLoader the deferred loader
|
||||
* @param <I> the input type
|
||||
* @return the new deferred registry
|
||||
*/
|
||||
public static <I, V> SimpleDeferredRegistry<V> create(Function<RegistryLoader<I, V>, SimpleRegistry<V>> registryLoader, Supplier<RegistryLoader<I, V>> deferredLoader) {
|
||||
return new SimpleDeferredRegistry<>(registryLoader, deferredLoader);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new deferred registry.
|
||||
*
|
||||
* @param registryInitializer the registry initializer
|
||||
* @param deferredLoader the deferred loader
|
||||
* @param <I> the input type
|
||||
* @return the new deferred registry
|
||||
*/
|
||||
public static <I, V> SimpleDeferredRegistry<V> create(I input, RegistryInitializer<V, SimpleRegistry<V>> registryInitializer, RegistryLoader<I, V> deferredLoader) {
|
||||
return new SimpleDeferredRegistry<>(input, registryInitializer, deferredLoader);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new deferred registry.
|
||||
*
|
||||
* @param registryInitializer the registry initializer
|
||||
* @param deferredLoader the deferred loader
|
||||
* @param <I> the input type
|
||||
* @return the new deferred registry
|
||||
*/
|
||||
public static <I, V> SimpleDeferredRegistry<V> create(I input, RegistryInitializer<V, SimpleRegistry<V>> registryInitializer, Supplier<RegistryLoader<I, V>> deferredLoader) {
|
||||
return new SimpleDeferredRegistry<>(input, registryInitializer, deferredLoader);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new deferred registry.
|
||||
*
|
||||
* @param deferredLoader the deferred loader
|
||||
* @param <I> the input type
|
||||
* @return the new deferred registry
|
||||
*/
|
||||
public static <I, V> SimpleDeferredRegistry<V> create(I input, RegistryLoader<I, V> deferredLoader) {
|
||||
return create(input, SimpleRegistry::create, deferredLoader);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new deferred registry.
|
||||
*
|
||||
* @param deferredLoader the deferred loader
|
||||
* @param <I> the input type
|
||||
* @return the new deferred registry
|
||||
*/
|
||||
public static <I, V> SimpleDeferredRegistry<V> create(I input, Supplier<RegistryLoader<I, V>> deferredLoader) {
|
||||
return create(input, SimpleRegistry::create, deferredLoader);
|
||||
}
|
||||
}
|
@ -0,0 +1,120 @@
|
||||
/*
|
||||
* Copyright (c) 2024 GeyserMC. http://geysermc.org
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
* @author GeyserMC
|
||||
* @link https://github.com/GeyserMC/Geyser
|
||||
*/
|
||||
|
||||
package org.geysermc.geyser.registry;
|
||||
|
||||
import org.geysermc.geyser.registry.loader.RegistryLoader;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
public class SimpleMappedDeferredRegistry<K, V> extends AbstractMappedDeferredRegistry<K, V, Map<K, V>, SimpleMappedRegistry<K, V>> {
|
||||
protected <I> SimpleMappedDeferredRegistry(Function<RegistryLoader<I, Map<K, V>>, SimpleMappedRegistry<K, V>> registryLoader, RegistryLoader<I, Map<K, V>> deferredLoader) {
|
||||
super(registryLoader, deferredLoader);
|
||||
}
|
||||
|
||||
protected <I> SimpleMappedDeferredRegistry(Function<RegistryLoader<I, Map<K, V>>, SimpleMappedRegistry<K, V>> registryLoader, Supplier<RegistryLoader<I, Map<K, V>>> deferredLoader) {
|
||||
super(registryLoader, deferredLoader);
|
||||
}
|
||||
|
||||
protected <I> SimpleMappedDeferredRegistry(I input, RegistryInitializer<Map<K, V>, SimpleMappedRegistry<K, V>> registryInitializer, RegistryLoader<I, Map<K, V>> deferredLoader) {
|
||||
super(input, registryInitializer, deferredLoader);
|
||||
}
|
||||
|
||||
protected <I> SimpleMappedDeferredRegistry(I input, RegistryInitializer<Map<K, V>, SimpleMappedRegistry<K, V>> registryInitializer, Supplier<RegistryLoader<I, Map<K, V>>> deferredLoader) {
|
||||
super(input, registryInitializer, deferredLoader);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new deferred registry.
|
||||
*
|
||||
* @param registryLoader the registry loader
|
||||
* @param deferredLoader the deferred loader
|
||||
* @param <I> the input type
|
||||
* @return the new deferred registry
|
||||
*/
|
||||
public static <I, K, V> SimpleMappedDeferredRegistry<K, V> create(Function<RegistryLoader<I, Map<K, V>>, SimpleMappedRegistry<K, V>> registryLoader, RegistryLoader<I, Map<K, V>> deferredLoader) {
|
||||
return new SimpleMappedDeferredRegistry<>(registryLoader, deferredLoader);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new deferred registry.
|
||||
*
|
||||
* @param registryLoader the registry loader
|
||||
* @param deferredLoader the deferred loader
|
||||
* @param <I> the input type
|
||||
* @return the new deferred registry
|
||||
*/
|
||||
public static <I, K, V> SimpleMappedDeferredRegistry<K, V> create(Function<RegistryLoader<I, Map<K, V>>, SimpleMappedRegistry<K, V>> registryLoader, Supplier<RegistryLoader<I, Map<K, V>>> deferredLoader) {
|
||||
return new SimpleMappedDeferredRegistry<>(registryLoader, deferredLoader);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new deferred registry.
|
||||
*
|
||||
* @param registryInitializer the registry initializer
|
||||
* @param deferredLoader the deferred loader
|
||||
* @param <I> the input type
|
||||
* @return the new deferred registry
|
||||
*/
|
||||
public static <I, K, V> SimpleMappedDeferredRegistry<K, V> create(I input, DeferredRegistry.RegistryInitializer<Map<K, V>, SimpleMappedRegistry<K, V>> registryInitializer, RegistryLoader<I, Map<K, V>> deferredLoader) {
|
||||
return new SimpleMappedDeferredRegistry<>(input, registryInitializer, deferredLoader);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new deferred registry.
|
||||
*
|
||||
* @param registryInitializer the registry initializer
|
||||
* @param deferredLoader the deferred loader
|
||||
* @param <I> the input type
|
||||
* @return the new deferred registry
|
||||
*/
|
||||
public static <I, K, V> SimpleMappedDeferredRegistry<K, V> create(I input, DeferredRegistry.RegistryInitializer<Map<K, V>, SimpleMappedRegistry<K, V>> registryInitializer, Supplier<RegistryLoader<I, Map<K, V>>> deferredLoader) {
|
||||
return new SimpleMappedDeferredRegistry<>(input, registryInitializer, deferredLoader);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new deferred registry.
|
||||
*
|
||||
* @param deferredLoader the deferred loader
|
||||
* @param <I> the input type
|
||||
* @return the new deferred registry
|
||||
*/
|
||||
public static <I, K, V> SimpleMappedDeferredRegistry<K, V> create(I input, RegistryLoader<I, Map<K, V>> deferredLoader) {
|
||||
return create(input, SimpleMappedRegistry::create, deferredLoader);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new deferred registry.
|
||||
*
|
||||
* @param deferredLoader the deferred loader
|
||||
* @param <I> the input type
|
||||
* @return the new deferred registry
|
||||
*/
|
||||
public static <I, K, V> SimpleMappedDeferredRegistry<K, V> create(I input, Supplier<RegistryLoader<I, Map<K, V>>> deferredLoader) {
|
||||
return create(input, SimpleMappedRegistry::create, deferredLoader);
|
||||
}
|
||||
}
|
@ -0,0 +1,114 @@
|
||||
/*
|
||||
* Copyright (c) 2024 GeyserMC. http://geysermc.org
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
* @author GeyserMC
|
||||
* @link https://github.com/GeyserMC/Geyser
|
||||
*/
|
||||
|
||||
package org.geysermc.geyser.registry;
|
||||
|
||||
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
|
||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
import org.geysermc.geyser.registry.loader.RegistryLoader;
|
||||
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
public class VersionedDeferredRegistry<V> extends AbstractMappedDeferredRegistry<Integer, V, Int2ObjectMap<V>, VersionedRegistry<V>> {
|
||||
protected <I> VersionedDeferredRegistry(Function<RegistryLoader<I, Int2ObjectMap<V>>, VersionedRegistry<V>> registryLoader, RegistryLoader<I, Int2ObjectMap<V>> deferredLoader) {
|
||||
super(registryLoader, deferredLoader);
|
||||
}
|
||||
|
||||
protected <I> VersionedDeferredRegistry(Function<RegistryLoader<I, Int2ObjectMap<V>>, VersionedRegistry<V>> registryLoader, Supplier<RegistryLoader<I, Int2ObjectMap<V>>> deferredLoader) {
|
||||
super(registryLoader, deferredLoader);
|
||||
}
|
||||
|
||||
protected <I> VersionedDeferredRegistry(I input, RegistryInitializer<Int2ObjectMap<V>, VersionedRegistry<V>> registryInitializer, RegistryLoader<I, Int2ObjectMap<V>> deferredLoader) {
|
||||
super(input, registryInitializer, deferredLoader);
|
||||
}
|
||||
|
||||
protected <I> VersionedDeferredRegistry(I input, RegistryInitializer<Int2ObjectMap<V>, VersionedRegistry<V>> registryInitializer, Supplier<RegistryLoader<I, Int2ObjectMap<V>>> deferredLoader) {
|
||||
super(input, registryInitializer, deferredLoader);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the closest value for the specified version. Only
|
||||
* returns versions higher up than the specified if one
|
||||
* does not exist for the given one. Useful in the event
|
||||
* that you want to get a resource which is guaranteed for
|
||||
* older versions, but not on newer ones.
|
||||
*
|
||||
* @param version the version
|
||||
* @return the closest value for the specified version
|
||||
* @throws IllegalArgumentException if no values exist at or above the given version
|
||||
*/
|
||||
@NonNull
|
||||
public V forVersion(int version) {
|
||||
return backingRegistry().forVersion(version);
|
||||
}
|
||||
/**
|
||||
* Creates a new deferred registry.
|
||||
*
|
||||
* @param registryLoader the registry loader
|
||||
* @param deferredLoader the deferred loader
|
||||
* @param <I> the input type
|
||||
* @return the new deferred registry
|
||||
*/
|
||||
public static <I, V> VersionedDeferredRegistry<V> create(Function<RegistryLoader<I, Int2ObjectMap<V>>, VersionedRegistry<V>> registryLoader, RegistryLoader<I, Int2ObjectMap<V>> deferredLoader) {
|
||||
return new VersionedDeferredRegistry<>(registryLoader, deferredLoader);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new deferred registry.
|
||||
*
|
||||
* @param registryLoader the registry loader
|
||||
* @param deferredLoader the deferred loader
|
||||
* @param <I> the input type
|
||||
* @return the new deferred registry
|
||||
*/
|
||||
public static <I, V> VersionedDeferredRegistry<V> create(Function<RegistryLoader<I, Int2ObjectMap<V>>, VersionedRegistry<V>> registryLoader, Supplier<RegistryLoader<I, Int2ObjectMap<V>>> deferredLoader) {
|
||||
return new VersionedDeferredRegistry<>(registryLoader, deferredLoader);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new deferred registry.
|
||||
*
|
||||
* @param registryInitializer the registry initializer
|
||||
* @param deferredLoader the deferred loader
|
||||
* @param <I> the input type
|
||||
* @return the new deferred registry
|
||||
*/
|
||||
public static <I, V> VersionedDeferredRegistry<V> create(I input, RegistryInitializer<Int2ObjectMap<V>, VersionedRegistry<V>> registryInitializer, RegistryLoader<I, Int2ObjectMap<V>> deferredLoader) {
|
||||
return new VersionedDeferredRegistry<>(input, registryInitializer, deferredLoader);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new deferred registry.
|
||||
*
|
||||
* @param registryInitializer the registry initializer
|
||||
* @param deferredLoader the deferred loader
|
||||
* @param <I> the input type
|
||||
* @return the new deferred registry
|
||||
*/
|
||||
public static <I, V> VersionedDeferredRegistry<V> create(I input, RegistryInitializer<Int2ObjectMap<V>, VersionedRegistry<V>> registryInitializer, Supplier<RegistryLoader<I, Int2ObjectMap<V>>> deferredLoader) {
|
||||
return new VersionedDeferredRegistry<>(input, registryInitializer, deferredLoader);
|
||||
}
|
||||
}
|
@ -125,4 +125,4 @@ public class PotionMixRegistryLoader implements RegistryLoader<Object, Int2Objec
|
||||
|
||||
return itemMapping;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -46,8 +46,7 @@ public class Conversion685_671 {
|
||||
|
||||
static GeyserMappingItem remapItem(Item item, GeyserMappingItem mapping) {
|
||||
mapping = Conversion712_685.remapItem(item, mapping);
|
||||
|
||||
String identifer = mapping.getBedrockIdentifier();
|
||||
String identifier = mapping.getBedrockIdentifier();
|
||||
|
||||
if (NEW_MUSIC_DISCS.contains(item)) {
|
||||
return mapping.withBedrockIdentifier("minecraft:music_disc_otherside");
|
||||
@ -59,12 +58,12 @@ public class Conversion685_671 {
|
||||
return mapping.withBedrockIdentifier("minecraft:glass_bottle");
|
||||
}
|
||||
|
||||
if (!NEW_BLOCKS.contains(identifer)) {
|
||||
if (!NEW_BLOCKS.contains(identifier)) {
|
||||
return mapping;
|
||||
}
|
||||
|
||||
if (NEW_CORAL_BLOCKS.contains(identifer)) {
|
||||
switch (identifer) {
|
||||
if (NEW_CORAL_BLOCKS.contains(identifier)) {
|
||||
switch (identifier) {
|
||||
case "minecraft:tube_coral_block" -> { return mapping.withBedrockIdentifier("minecraft:coral_block").withBedrockData(0); }
|
||||
case "minecraft:brain_coral_block" -> { return mapping.withBedrockIdentifier("minecraft:coral_block").withBedrockData(1); }
|
||||
case "minecraft:bubble_coral_block" -> { return mapping.withBedrockIdentifier("minecraft:coral_block").withBedrockData(2); }
|
||||
@ -78,8 +77,8 @@ public class Conversion685_671 {
|
||||
}
|
||||
}
|
||||
|
||||
if (NEW_DOUBLE_PLANTS.contains(identifer)) {
|
||||
switch (identifer) {
|
||||
if (NEW_DOUBLE_PLANTS.contains(identifier)) {
|
||||
switch (identifier) {
|
||||
case "minecraft:sunflower" -> { return mapping.withBedrockIdentifier("minecraft:double_plant").withBedrockData(0); }
|
||||
case "minecraft:lilac" -> { return mapping.withBedrockIdentifier("minecraft:double_plant").withBedrockData(1); }
|
||||
case "minecraft:tall_grass" -> { return mapping.withBedrockIdentifier("minecraft:double_plant").withBedrockData(2); }
|
||||
@ -89,8 +88,8 @@ public class Conversion685_671 {
|
||||
}
|
||||
}
|
||||
|
||||
if (NEW_STONE_BLOCK_SLABS.contains(identifer)) {
|
||||
switch (identifer) {
|
||||
if (NEW_STONE_BLOCK_SLABS.contains(identifier)) {
|
||||
switch (identifier) {
|
||||
case "minecraft:smooth_stone_slab" -> { return mapping.withBedrockIdentifier("minecraft:stone_block_slab").withBedrockData(0); }
|
||||
case "minecraft:sandstone_slab" -> { return mapping.withBedrockIdentifier("minecraft:stone_block_slab").withBedrockData(1); }
|
||||
case "minecraft:petrified_oak_slab" -> { return mapping.withBedrockIdentifier("minecraft:stone_block_slab").withBedrockData(2); }
|
||||
@ -102,8 +101,8 @@ public class Conversion685_671 {
|
||||
}
|
||||
}
|
||||
|
||||
if (NEW_TALLGRASSES.contains(identifer)) {
|
||||
switch (identifer) {
|
||||
if (NEW_TALLGRASSES.contains(identifier)) {
|
||||
switch (identifier) {
|
||||
case "minecraft:short_grass" -> { return mapping.withBedrockIdentifier("minecraft:tallgrass").withBedrockData(1); }
|
||||
case "minecraft:fern" -> { return mapping.withBedrockIdentifier("minecraft:tallgrass").withBedrockData(2); }
|
||||
}
|
||||
|
@ -33,35 +33,34 @@ public class Conversion712_685 {
|
||||
|
||||
static GeyserMappingItem remapItem(Item item, GeyserMappingItem mapping) {
|
||||
mapping = Conversion729_712.remapItem(item, mapping);
|
||||
String identifier = mapping.getBedrockIdentifier();
|
||||
|
||||
String identifer = mapping.getBedrockIdentifier();
|
||||
|
||||
if (!NEW_BLOCKS.contains(identifer)) {
|
||||
if (!NEW_BLOCKS.contains(identifier)) {
|
||||
return mapping;
|
||||
}
|
||||
|
||||
if (identifer.equals("minecraft:coarse_dirt")) {
|
||||
if (identifier.equals("minecraft:coarse_dirt")) {
|
||||
return mapping.withBedrockIdentifier("minecraft:dirt").withBedrockData(1);
|
||||
}
|
||||
|
||||
if (identifer.equals("minecraft:dandelion")) {
|
||||
if (identifier.equals("minecraft:dandelion")) {
|
||||
return mapping.withBedrockIdentifier("minecraft:yellow_flower").withBedrockData(0);
|
||||
}
|
||||
|
||||
if (identifer.equals("minecraft:red_sand")) {
|
||||
if (identifier.equals("minecraft:red_sand")) {
|
||||
return mapping.withBedrockIdentifier("minecraft:sand").withBedrockData(1);
|
||||
}
|
||||
|
||||
if (NEW_PRISMARINE_BLOCKS.contains(identifer)) {
|
||||
switch (identifer) {
|
||||
if (NEW_PRISMARINE_BLOCKS.contains(identifier)) {
|
||||
switch (identifier) {
|
||||
case "minecraft:prismarine" -> { return mapping.withBedrockIdentifier("minecraft:prismarine").withBedrockData(0); }
|
||||
case "minecraft:dark_prismarine" -> { return mapping.withBedrockIdentifier("minecraft:prismarine").withBedrockData(1); }
|
||||
case "minecraft:prismarine_bricks" -> { return mapping.withBedrockIdentifier("minecraft:prismarine").withBedrockData(2); }
|
||||
}
|
||||
}
|
||||
|
||||
if (NEW_SANDSTONE_BLOCKS.contains(identifer)) {
|
||||
switch (identifer) {
|
||||
if (NEW_SANDSTONE_BLOCKS.contains(identifier)) {
|
||||
switch (identifier) {
|
||||
case "minecraft:sandstone" -> { return mapping.withBedrockIdentifier("minecraft:sandstone").withBedrockData(0); }
|
||||
case "minecraft:chiseled_sandstone" -> { return mapping.withBedrockIdentifier("minecraft:sandstone").withBedrockData(1); }
|
||||
case "minecraft:cut_sandstone" -> { return mapping.withBedrockIdentifier("minecraft:sandstone").withBedrockData(2); }
|
||||
@ -69,8 +68,8 @@ public class Conversion712_685 {
|
||||
}
|
||||
}
|
||||
|
||||
if (NEW_RED_SANDSTONE_BLOCKS.contains(identifer)) {
|
||||
switch (identifer) {
|
||||
if (NEW_RED_SANDSTONE_BLOCKS.contains(identifier)) {
|
||||
switch (identifier) {
|
||||
case "minecraft:red_sandstone" -> { return mapping.withBedrockIdentifier("minecraft:red_sandstone").withBedrockData(0); }
|
||||
case "minecraft:chiseled_red_sandstone" -> { return mapping.withBedrockIdentifier("minecraft:red_sandstone").withBedrockData(1); }
|
||||
case "minecraft:cut_red_sandstone" -> { return mapping.withBedrockIdentifier("minecraft:red_sandstone").withBedrockData(2); }
|
||||
@ -78,8 +77,8 @@ public class Conversion712_685 {
|
||||
}
|
||||
}
|
||||
|
||||
if (NEW_QUARTZ_BLOCKS.contains(identifer)) {
|
||||
switch (identifer) {
|
||||
if (NEW_QUARTZ_BLOCKS.contains(identifier)) {
|
||||
switch (identifier) {
|
||||
case "minecraft:quartz_block" -> { return mapping.withBedrockIdentifier("minecraft:quartz_block").withBedrockData(0); }
|
||||
case "minecraft:chiseled_quartz_block" -> { return mapping.withBedrockIdentifier("minecraft:quartz_block").withBedrockData(1); }
|
||||
case "minecraft:quartz_pillar" -> { return mapping.withBedrockIdentifier("minecraft:quartz_block").withBedrockData(2); }
|
||||
@ -87,8 +86,8 @@ public class Conversion712_685 {
|
||||
}
|
||||
}
|
||||
|
||||
if (NEW_STONE_BLOCK_SLABS_2.contains(identifer)) {
|
||||
switch (identifer) {
|
||||
if (NEW_STONE_BLOCK_SLABS_2.contains(identifier)) {
|
||||
switch (identifier) {
|
||||
case "minecraft:red_sandstone_slab" -> { return mapping.withBedrockIdentifier("minecraft:stone_block_slab2").withBedrockData(0); }
|
||||
case "minecraft:purpur_slab" -> { return mapping.withBedrockIdentifier("minecraft:stone_block_slab2").withBedrockData(1); }
|
||||
case "minecraft:prismarine_slab" -> { return mapping.withBedrockIdentifier("minecraft:stone_block_slab2").withBedrockData(2); }
|
||||
@ -100,8 +99,8 @@ public class Conversion712_685 {
|
||||
}
|
||||
}
|
||||
|
||||
if (NEW_STONE_BLOCK_SLABS_3.contains(identifer)) {
|
||||
switch (identifer) {
|
||||
if (NEW_STONE_BLOCK_SLABS_3.contains(identifier)) {
|
||||
switch (identifier) {
|
||||
case "minecraft:end_stone_brick_slab" -> { return mapping.withBedrockIdentifier("minecraft:stone_block_slab3").withBedrockData(0); }
|
||||
case "minecraft:smooth_red_sandstone_slab" -> { return mapping.withBedrockIdentifier("minecraft:stone_block_slab3").withBedrockData(1); }
|
||||
case "minecraft:polished_andesite_slab" -> { return mapping.withBedrockIdentifier("minecraft:stone_block_slab3").withBedrockData(2); }
|
||||
@ -113,8 +112,8 @@ public class Conversion712_685 {
|
||||
}
|
||||
}
|
||||
|
||||
if (NEW_STONE_BLOCK_SLABS_4.contains(identifer)) {
|
||||
switch (identifer) {
|
||||
if (NEW_STONE_BLOCK_SLABS_4.contains(identifier)) {
|
||||
switch (identifier) {
|
||||
case "minecraft:mossy_stone_brick_slab" -> { return mapping.withBedrockIdentifier("minecraft:stone_block_slab4").withBedrockData(0); }
|
||||
case "minecraft:smooth_quartz_slab" -> { return mapping.withBedrockIdentifier("minecraft:stone_block_slab4").withBedrockData(1); }
|
||||
case "minecraft:normal_stone_slab" -> { return mapping.withBedrockIdentifier("minecraft:stone_block_slab4").withBedrockData(2); }
|
||||
@ -123,8 +122,8 @@ public class Conversion712_685 {
|
||||
}
|
||||
}
|
||||
|
||||
if (NEW_MONSTER_EGGS.contains(identifer)) {
|
||||
switch (identifer) {
|
||||
if (NEW_MONSTER_EGGS.contains(identifier)) {
|
||||
switch (identifier) {
|
||||
case "minecraft:infested_stone" -> { return mapping.withBedrockIdentifier("minecraft:monster_egg").withBedrockData(0); }
|
||||
case "minecraft:infested_cobblestone" -> { return mapping.withBedrockIdentifier("minecraft:monster_egg").withBedrockData(1); }
|
||||
case "minecraft:infested_stone_bricks" -> { return mapping.withBedrockIdentifier("minecraft:monster_egg").withBedrockData(2); }
|
||||
@ -134,8 +133,8 @@ public class Conversion712_685 {
|
||||
}
|
||||
}
|
||||
|
||||
if (NEW_STONEBRICK_BLOCKS.contains(identifer)) {
|
||||
switch (identifer) {
|
||||
if (NEW_STONEBRICK_BLOCKS.contains(identifier)) {
|
||||
switch (identifier) {
|
||||
case "minecraft:stone_bricks" -> { return mapping.withBedrockIdentifier("minecraft:stonebrick").withBedrockData(0); }
|
||||
case "minecraft:mossy_stone_bricks" -> { return mapping.withBedrockIdentifier("minecraft:stonebrick").withBedrockData(1); }
|
||||
case "minecraft:cracked_stone_bricks" -> { return mapping.withBedrockIdentifier("minecraft:stonebrick").withBedrockData(2); }
|
||||
@ -143,8 +142,8 @@ public class Conversion712_685 {
|
||||
}
|
||||
}
|
||||
|
||||
if (NEW_ANVILS.contains(identifer)) {
|
||||
switch (identifer) {
|
||||
if (NEW_ANVILS.contains(identifier)) {
|
||||
switch (identifier) {
|
||||
case "minecraft:anvil" -> { return mapping.withBedrockIdentifier("minecraft:anvil").withBedrockData(0); }
|
||||
case "minecraft:chipped_anvil" -> { return mapping.withBedrockIdentifier("minecraft:anvil").withBedrockData(4); }
|
||||
case "minecraft:damaged_anvil" -> { return mapping.withBedrockIdentifier("minecraft:anvil").withBedrockData(8); }
|
||||
|
@ -16,6 +16,7 @@ public class Conversion729_712 {
|
||||
private static final List<String> NEW_BLOCKS = Stream.of(NEW_PURPUR_BLOCKS, NEW_WALL_BLOCKS, NEW_SPONGE_BLOCKS, NEW_TNT_BLOCKS, STRUCTURE_VOID).flatMap(List::stream).toList();
|
||||
|
||||
static GeyserMappingItem remapItem(Item item, GeyserMappingItem mapping) {
|
||||
mapping = Conversion748_729.remapItem(item, mapping);
|
||||
String identifier = mapping.getBedrockIdentifier();
|
||||
|
||||
if (!NEW_BLOCKS.contains(identifier)) {
|
||||
|
@ -0,0 +1,48 @@
|
||||
/*
|
||||
* Copyright (c) 2024 GeyserMC. http://geysermc.org
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
* @author GeyserMC
|
||||
* @link https://github.com/GeyserMC/Geyser
|
||||
*/
|
||||
|
||||
package org.geysermc.geyser.registry.populator;
|
||||
|
||||
import org.geysermc.geyser.item.type.Item;
|
||||
import org.geysermc.geyser.registry.type.GeyserMappingItem;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
public class Conversion748_729 {
|
||||
|
||||
private static final Map<String, Integer> NEW_PLAYER_HEADS = Map.of("minecraft:skeleton_skull", 0, "minecraft:wither_skeleton_skull", 1, "minecraft:zombie_head", 2, "minecraft:player_head", 3, "minecraft:creeper_head", 4, "minecraft:dragon_head", 5, "minecraft:piglin_head", 6);
|
||||
|
||||
static GeyserMappingItem remapItem(Item item, GeyserMappingItem mapping) {
|
||||
String identifier = mapping.getBedrockIdentifier();
|
||||
|
||||
if (NEW_PLAYER_HEADS.containsKey(identifier)) {
|
||||
return mapping.withBedrockIdentifier("minecraft:skull")
|
||||
.withBedrockData(NEW_PLAYER_HEADS.get(identifier));
|
||||
}
|
||||
|
||||
return mapping;
|
||||
}
|
||||
|
||||
}
|
@ -33,7 +33,13 @@ import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
|
||||
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
|
||||
import it.unimi.dsi.fastutil.ints.IntOpenHashSet;
|
||||
import it.unimi.dsi.fastutil.ints.IntSet;
|
||||
import it.unimi.dsi.fastutil.objects.*;
|
||||
import it.unimi.dsi.fastutil.objects.Object2IntMap;
|
||||
import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap;
|
||||
import it.unimi.dsi.fastutil.objects.Object2ObjectLinkedOpenHashMap;
|
||||
import it.unimi.dsi.fastutil.objects.Object2ObjectMap;
|
||||
import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;
|
||||
import it.unimi.dsi.fastutil.objects.ObjectArrayList;
|
||||
import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet;
|
||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
import org.cloudburstmc.nbt.NbtMap;
|
||||
import org.cloudburstmc.nbt.NbtMapBuilder;
|
||||
@ -66,10 +72,22 @@ import org.geysermc.geyser.item.type.BlockItem;
|
||||
import org.geysermc.geyser.item.type.Item;
|
||||
import org.geysermc.geyser.registry.BlockRegistries;
|
||||
import org.geysermc.geyser.registry.Registries;
|
||||
import org.geysermc.geyser.registry.type.*;
|
||||
import org.geysermc.geyser.registry.type.BlockMappings;
|
||||
import org.geysermc.geyser.registry.type.GeyserBedrockBlock;
|
||||
import org.geysermc.geyser.registry.type.GeyserMappingItem;
|
||||
import org.geysermc.geyser.registry.type.ItemMapping;
|
||||
import org.geysermc.geyser.registry.type.ItemMappings;
|
||||
import org.geysermc.geyser.registry.type.NonVanillaItemRegistration;
|
||||
import org.geysermc.geyser.registry.type.PaletteItem;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.util.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
/**
|
||||
@ -95,7 +113,7 @@ public class ItemRegistryPopulator {
|
||||
paletteVersions.add(new PaletteVersion("1_20_80", Bedrock_v671.CODEC.getProtocolVersion(), Collections.emptyMap(), Conversion685_671::remapItem));
|
||||
paletteVersions.add(new PaletteVersion("1_21_0", Bedrock_v685.CODEC.getProtocolVersion(), Collections.emptyMap(), Conversion712_685::remapItem));
|
||||
paletteVersions.add(new PaletteVersion("1_21_20", Bedrock_v712.CODEC.getProtocolVersion(), Collections.emptyMap(), Conversion729_712::remapItem));
|
||||
paletteVersions.add(new PaletteVersion("1_21_30", Bedrock_v729.CODEC.getProtocolVersion()));
|
||||
paletteVersions.add(new PaletteVersion("1_21_30", Bedrock_v729.CODEC.getProtocolVersion(), Collections.emptyMap(), Conversion748_729::remapItem));
|
||||
paletteVersions.add(new PaletteVersion("1_21_40", Bedrock_v748.CODEC.getProtocolVersion()));
|
||||
|
||||
GeyserBootstrap bootstrap = GeyserImpl.getInstance().getBootstrap();
|
||||
|
@ -90,6 +90,8 @@ public final class Team {
|
||||
// Remove old team from this map, and from the set of players of the old team.
|
||||
// Java 1.19.3 Mojmap: Scoreboard#addPlayerToTeam calls #removePlayerFromTeam
|
||||
oldTeam.entities.remove(player);
|
||||
// also remove the managed entity if there is one
|
||||
removeManagedEntity(player);
|
||||
}
|
||||
return this;
|
||||
});
|
||||
@ -282,6 +284,15 @@ public final class Team {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Used internally to remove a managed entity without causing an update.
|
||||
* This is fine because its only used when the entity is added to another team,
|
||||
* which will fire the correct nametag updates etc.
|
||||
*/
|
||||
private void removeManagedEntity(String name) {
|
||||
managedEntities.removeIf(entity -> name.equals(entity.teamIdentifier()));
|
||||
}
|
||||
|
||||
private void refreshAllEntities() {
|
||||
for (Entity entity : session().getEntityCache().getEntities().values()) {
|
||||
entity.updateNametag(scoreboard.getTeamFor(entity.teamIdentifier()));
|
||||
|
@ -2217,6 +2217,11 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource {
|
||||
return (int) Math.floor(rakSessionCodec.getPing());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int protocolVersion() {
|
||||
return upstream.getProtocolVersion();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void closeForm() {
|
||||
if (!GameProtocol.isPre1_21_2(this)) {
|
||||
|
@ -69,12 +69,13 @@ public class EntityCache {
|
||||
|
||||
public void spawnEntity(Entity entity) {
|
||||
if (cacheEntity(entity)) {
|
||||
entity.spawnEntity();
|
||||
|
||||
// start tracking newly spawned entities.
|
||||
// This is however not called for players, that's done in addPlayerEntity
|
||||
// start tracking newly spawned entities. Doing this before the actual entity spawn can result in combining
|
||||
// the otherwise sent metadata packet (in the case of team visibility, which sets the NAME metadata to
|
||||
// empty) with the entity spawn packet (which also includes metadata). Resulting in 1 less packet sent.
|
||||
session.getWorldCache().getScoreboard().entityRegistered(entity);
|
||||
|
||||
entity.spawnEntity();
|
||||
|
||||
if (entity instanceof Tickable) {
|
||||
// Start ticking it
|
||||
tickableEntities.add((Tickable) entity);
|
||||
@ -144,8 +145,6 @@ public class EntityCache {
|
||||
// notify scoreboard for new entity
|
||||
var scoreboard = session.getWorldCache().getScoreboard();
|
||||
scoreboard.playerRegistered(entity);
|
||||
// spawnPlayer's entityRegistered is not called for players
|
||||
scoreboard.entityRegistered(entity);
|
||||
}
|
||||
|
||||
public PlayerEntity getPlayerEntity(UUID uuid) {
|
||||
|
@ -25,7 +25,6 @@
|
||||
|
||||
package org.geysermc.geyser.translator.protocol.java.entity.player;
|
||||
|
||||
import org.geysermc.mcprotocollib.auth.GameProfile;
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
import org.cloudburstmc.math.vector.Vector3f;
|
||||
import org.cloudburstmc.protocol.bedrock.packet.PlayerListPacket;
|
||||
@ -35,6 +34,7 @@ import org.geysermc.geyser.session.GeyserSession;
|
||||
import org.geysermc.geyser.skin.SkinManager;
|
||||
import org.geysermc.geyser.translator.protocol.PacketTranslator;
|
||||
import org.geysermc.geyser.translator.protocol.Translator;
|
||||
import org.geysermc.mcprotocollib.auth.GameProfile;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.PlayerListEntry;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.PlayerListEntryAction;
|
||||
import org.geysermc.mcprotocollib.protocol.packet.ingame.clientbound.ClientboundPlayerInfoUpdatePacket;
|
||||
@ -95,8 +95,6 @@ public class JavaPlayerInfoUpdateTranslator extends PacketTranslator<Clientbound
|
||||
if (self) {
|
||||
SkinManager.requestAndHandleSkinAndCape(playerEntity, session, skinAndCape ->
|
||||
GeyserImpl.getInstance().getLogger().debug("Loaded Local Bedrock Java Skin Data for " + session.getClientData().getUsername()));
|
||||
} else {
|
||||
playerEntity.setValid(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -25,17 +25,14 @@
|
||||
|
||||
package org.geysermc.geyser.translator.protocol.java.entity.spawn;
|
||||
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.Pose;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.entity.object.Direction;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.entity.object.FallingBlockData;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.entity.object.ProjectileData;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.entity.object.WardenData;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.entity.type.EntityType;
|
||||
import org.geysermc.mcprotocollib.protocol.packet.ingame.clientbound.entity.spawn.ClientboundAddEntityPacket;
|
||||
import org.cloudburstmc.math.vector.Vector3f;
|
||||
import org.geysermc.geyser.GeyserImpl;
|
||||
import org.geysermc.geyser.entity.EntityDefinition;
|
||||
import org.geysermc.geyser.entity.type.*;
|
||||
import org.geysermc.geyser.entity.type.Entity;
|
||||
import org.geysermc.geyser.entity.type.FallingBlockEntity;
|
||||
import org.geysermc.geyser.entity.type.FishingHookEntity;
|
||||
import org.geysermc.geyser.entity.type.ItemFrameEntity;
|
||||
import org.geysermc.geyser.entity.type.PaintingEntity;
|
||||
import org.geysermc.geyser.entity.type.player.PlayerEntity;
|
||||
import org.geysermc.geyser.registry.Registries;
|
||||
import org.geysermc.geyser.session.GeyserSession;
|
||||
@ -43,6 +40,14 @@ import org.geysermc.geyser.skin.SkinManager;
|
||||
import org.geysermc.geyser.text.GeyserLocale;
|
||||
import org.geysermc.geyser.translator.protocol.PacketTranslator;
|
||||
import org.geysermc.geyser.translator.protocol.Translator;
|
||||
import org.geysermc.geyser.util.EnvironmentUtils;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.Pose;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.entity.object.Direction;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.entity.object.FallingBlockData;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.entity.object.ProjectileData;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.entity.object.WardenData;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.entity.type.EntityType;
|
||||
import org.geysermc.mcprotocollib.protocol.packet.ingame.clientbound.entity.spawn.ClientboundAddEntityPacket;
|
||||
|
||||
@Translator(packet = ClientboundAddEntityPacket.class)
|
||||
public class JavaAddEntityTranslator extends PacketTranslator<ClientboundAddEntityPacket> {
|
||||
@ -83,10 +88,13 @@ public class JavaAddEntityTranslator extends PacketTranslator<ClientboundAddEnti
|
||||
entity.setHeadYaw(headYaw);
|
||||
entity.setMotion(motion);
|
||||
}
|
||||
session.getEntityCache().cacheEntity(entity);
|
||||
|
||||
entity.sendPlayer();
|
||||
SkinManager.requestAndHandleSkinAndCape(entity, session, null);
|
||||
// only load skin if we're not in a test environment.
|
||||
// Otherwise, it tries to load various resources
|
||||
if (!EnvironmentUtils.IS_UNIT_TESTING) {
|
||||
SkinManager.requestAndHandleSkinAndCape(entity, session, null);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -25,13 +25,13 @@
|
||||
|
||||
package org.geysermc.geyser.translator.protocol.java.scoreboard;
|
||||
|
||||
import org.geysermc.mcprotocollib.protocol.packet.ingame.clientbound.scoreboard.ClientboundSetDisplayObjectivePacket;
|
||||
import org.geysermc.geyser.scoreboard.Scoreboard;
|
||||
import org.geysermc.geyser.scoreboard.ScoreboardUpdater;
|
||||
import org.geysermc.geyser.session.GeyserSession;
|
||||
import org.geysermc.geyser.session.cache.WorldCache;
|
||||
import org.geysermc.geyser.translator.protocol.PacketTranslator;
|
||||
import org.geysermc.geyser.translator.protocol.Translator;
|
||||
import org.geysermc.mcprotocollib.protocol.packet.ingame.clientbound.scoreboard.ClientboundSetDisplayObjectivePacket;
|
||||
|
||||
@Translator(packet = ClientboundSetDisplayObjectivePacket.class)
|
||||
public class JavaSetDisplayObjectiveTranslator extends PacketTranslator<ClientboundSetDisplayObjectivePacket> {
|
||||
|
@ -307,7 +307,7 @@ public final class EntityUtils {
|
||||
private static String translatedEntityName(@NonNull String namespace, @NonNull String name, @NonNull GeyserSession session) {
|
||||
// MinecraftLocale would otherwise invoke getBootstrap (which doesn't exist) and create some folders,
|
||||
// so use the default fallback value as used in Minecraft Java
|
||||
if (EnvironmentUtils.isUnitTesting) {
|
||||
if (EnvironmentUtils.IS_UNIT_TESTING) {
|
||||
return "entity." + namespace + "." + name;
|
||||
}
|
||||
return MinecraftLocale.getLocaleString("entity." + namespace + "." + name, session.locale());
|
||||
|
@ -26,7 +26,7 @@
|
||||
package org.geysermc.geyser.util;
|
||||
|
||||
public final class EnvironmentUtils {
|
||||
public static final boolean isUnitTesting = isUnitTesting();
|
||||
public static final boolean IS_UNIT_TESTING = isUnitTesting();
|
||||
|
||||
private EnvironmentUtils() {}
|
||||
|
||||
|
@ -1 +1 @@
|
||||
Subproject commit 4594e8f88738d2e623d0854a8831b9033e60154a
|
||||
Subproject commit 4200a8c57a79a87b5b9e7ea1aaf9d5522c4f5626
|
@ -27,7 +27,7 @@ package org.geysermc.geyser.scoreboard.network;
|
||||
|
||||
import static org.geysermc.geyser.scoreboard.network.util.AssertUtils.assertNextPacket;
|
||||
import static org.geysermc.geyser.scoreboard.network.util.AssertUtils.assertNoNextPacket;
|
||||
import static org.geysermc.geyser.scoreboard.network.util.GeyserMockContextScoreboard.mockAndAddPlayerEntity;
|
||||
import static org.geysermc.geyser.scoreboard.network.util.GeyserMockContextScoreboard.spawnPlayerSilently;
|
||||
import static org.geysermc.geyser.scoreboard.network.util.GeyserMockContextScoreboard.mockContextScoreboard;
|
||||
|
||||
import net.kyori.adventure.text.Component;
|
||||
@ -47,7 +47,7 @@ public class NameVisibilityScoreboardTest {
|
||||
mockContextScoreboard(context -> {
|
||||
var setPlayerTeamTranslator = new JavaSetPlayerTeamTranslator();
|
||||
|
||||
mockAndAddPlayerEntity(context, "player1", 2);
|
||||
spawnPlayerSilently(context, "player1", 2);
|
||||
|
||||
context.translate(
|
||||
setPlayerTeamTranslator,
|
||||
@ -64,12 +64,12 @@ public class NameVisibilityScoreboardTest {
|
||||
new String[]{"player1"}
|
||||
)
|
||||
);
|
||||
assertNextPacket(() -> {
|
||||
assertNextPacket(context, () -> {
|
||||
var packet = new SetEntityDataPacket();
|
||||
packet.setRuntimeEntityId(2);
|
||||
packet.getMetadata().put(EntityDataTypes.NAME, "");
|
||||
return packet;
|
||||
}, context);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@ -78,7 +78,7 @@ public class NameVisibilityScoreboardTest {
|
||||
mockContextScoreboard(context -> {
|
||||
var setPlayerTeamTranslator = new JavaSetPlayerTeamTranslator();
|
||||
|
||||
mockAndAddPlayerEntity(context, "player1", 2);
|
||||
spawnPlayerSilently(context, "player1", 2);
|
||||
|
||||
context.translate(
|
||||
setPlayerTeamTranslator,
|
||||
@ -96,12 +96,12 @@ public class NameVisibilityScoreboardTest {
|
||||
)
|
||||
);
|
||||
// only hidden if session player (Tim203) is in a team as well
|
||||
assertNextPacket(() -> {
|
||||
assertNextPacket(context, () -> {
|
||||
var packet = new SetEntityDataPacket();
|
||||
packet.setRuntimeEntityId(2);
|
||||
packet.getMetadata().put(EntityDataTypes.NAME, "§4prefix§r§4player1§r§4suffix");
|
||||
return packet;
|
||||
}, context);
|
||||
});
|
||||
assertNoNextPacket(context);
|
||||
|
||||
// create another team and add Tim203 to it
|
||||
@ -121,12 +121,12 @@ public class NameVisibilityScoreboardTest {
|
||||
)
|
||||
);
|
||||
// Tim203 is now in another team, so it should be hidden
|
||||
assertNextPacket(() -> {
|
||||
assertNextPacket(context, () -> {
|
||||
var packet = new SetEntityDataPacket();
|
||||
packet.setRuntimeEntityId(2);
|
||||
packet.getMetadata().put(EntityDataTypes.NAME, "");
|
||||
return packet;
|
||||
}, context);
|
||||
});
|
||||
assertNoNextPacket(context);
|
||||
|
||||
// add Tim203 to same team as player1, score should be visible again
|
||||
@ -134,12 +134,12 @@ public class NameVisibilityScoreboardTest {
|
||||
setPlayerTeamTranslator,
|
||||
new ClientboundSetPlayerTeamPacket("team1", TeamAction.ADD_PLAYER, new String[]{"Tim203"})
|
||||
);
|
||||
assertNextPacket(() -> {
|
||||
assertNextPacket(context, () -> {
|
||||
var packet = new SetEntityDataPacket();
|
||||
packet.setRuntimeEntityId(2);
|
||||
packet.getMetadata().put(EntityDataTypes.NAME, "§4prefix§r§4player1§r§4suffix");
|
||||
return packet;
|
||||
}, context);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@ -148,7 +148,7 @@ public class NameVisibilityScoreboardTest {
|
||||
mockContextScoreboard(context -> {
|
||||
var setPlayerTeamTranslator = new JavaSetPlayerTeamTranslator();
|
||||
|
||||
mockAndAddPlayerEntity(context, "player1", 2);
|
||||
spawnPlayerSilently(context, "player1", 2);
|
||||
|
||||
context.translate(
|
||||
setPlayerTeamTranslator,
|
||||
@ -166,12 +166,12 @@ public class NameVisibilityScoreboardTest {
|
||||
)
|
||||
);
|
||||
// Tim203 is not in a team (let alone the same team), so should be visible
|
||||
assertNextPacket(() -> {
|
||||
assertNextPacket(context, () -> {
|
||||
var packet = new SetEntityDataPacket();
|
||||
packet.setRuntimeEntityId(2);
|
||||
packet.getMetadata().put(EntityDataTypes.NAME, "§4prefix§r§4player1§r§4suffix");
|
||||
return packet;
|
||||
}, context);
|
||||
});
|
||||
assertNoNextPacket(context);
|
||||
|
||||
// Tim203 is now in the same team as player1, so should be hidden
|
||||
@ -179,12 +179,12 @@ public class NameVisibilityScoreboardTest {
|
||||
setPlayerTeamTranslator,
|
||||
new ClientboundSetPlayerTeamPacket("team1", TeamAction.ADD_PLAYER, new String[]{"Tim203"})
|
||||
);
|
||||
assertNextPacket(() -> {
|
||||
assertNextPacket(context, () -> {
|
||||
var packet = new SetEntityDataPacket();
|
||||
packet.setRuntimeEntityId(2);
|
||||
packet.getMetadata().put(EntityDataTypes.NAME, "");
|
||||
return packet;
|
||||
}, context);
|
||||
});
|
||||
assertNoNextPacket(context);
|
||||
|
||||
// create another team and add Tim203 to there, score should be visible again
|
||||
@ -203,12 +203,12 @@ public class NameVisibilityScoreboardTest {
|
||||
new String[]{"Tim203"}
|
||||
)
|
||||
);
|
||||
assertNextPacket(() -> {
|
||||
assertNextPacket(context, () -> {
|
||||
var packet = new SetEntityDataPacket();
|
||||
packet.setRuntimeEntityId(2);
|
||||
packet.getMetadata().put(EntityDataTypes.NAME, "§4prefix§r§4player1§r§4suffix");
|
||||
return packet;
|
||||
}, context);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@ -217,7 +217,7 @@ public class NameVisibilityScoreboardTest {
|
||||
mockContextScoreboard(context -> {
|
||||
var setPlayerTeamTranslator = new JavaSetPlayerTeamTranslator();
|
||||
|
||||
mockAndAddPlayerEntity(context, "player1", 2);
|
||||
spawnPlayerSilently(context, "player1", 2);
|
||||
|
||||
context.translate(
|
||||
setPlayerTeamTranslator,
|
||||
@ -234,12 +234,12 @@ public class NameVisibilityScoreboardTest {
|
||||
new String[]{"player1"}
|
||||
)
|
||||
);
|
||||
assertNextPacket(() -> {
|
||||
assertNextPacket(context, () -> {
|
||||
var packet = new SetEntityDataPacket();
|
||||
packet.setRuntimeEntityId(2);
|
||||
packet.getMetadata().put(EntityDataTypes.NAME, "§4prefix§r§4player1§r§4suffix");
|
||||
return packet;
|
||||
}, context);
|
||||
});
|
||||
|
||||
// adding self to another team shouldn't make a difference
|
||||
context.translate(
|
||||
|
@ -25,23 +25,58 @@
|
||||
|
||||
package org.geysermc.geyser.scoreboard.network;
|
||||
|
||||
import static org.geysermc.geyser.scoreboard.network.util.AssertUtils.assertNextPacket;
|
||||
import static org.geysermc.geyser.scoreboard.network.util.AssertUtils.assertNextPacketMatch;
|
||||
import static org.geysermc.geyser.scoreboard.network.util.AssertUtils.assertNextPacketType;
|
||||
import static org.geysermc.geyser.scoreboard.network.util.AssertUtils.assertNoNextPacket;
|
||||
import static org.geysermc.geyser.scoreboard.network.util.GeyserMockContextScoreboard.mockContextScoreboard;
|
||||
import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
||||
import net.kyori.adventure.text.Component;
|
||||
import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes;
|
||||
import org.cloudburstmc.protocol.bedrock.packet.AddEntityPacket;
|
||||
import org.cloudburstmc.protocol.bedrock.packet.AddPlayerPacket;
|
||||
import org.cloudburstmc.protocol.bedrock.packet.MoveEntityAbsolutePacket;
|
||||
import org.cloudburstmc.protocol.bedrock.packet.PlayerListPacket;
|
||||
import org.cloudburstmc.protocol.bedrock.packet.RemoveEntityPacket;
|
||||
import org.cloudburstmc.protocol.bedrock.packet.SetEntityDataPacket;
|
||||
import org.geysermc.geyser.entity.type.living.monster.EnderDragonPartEntity;
|
||||
import org.geysermc.geyser.session.cache.EntityCache;
|
||||
import org.geysermc.geyser.translator.protocol.java.entity.JavaRemoveEntitiesTranslator;
|
||||
import org.geysermc.geyser.translator.protocol.java.entity.JavaSetEntityDataTranslator;
|
||||
import org.geysermc.geyser.translator.protocol.java.entity.player.JavaPlayerInfoUpdateTranslator;
|
||||
import org.geysermc.geyser.translator.protocol.java.entity.spawn.JavaAddEntityTranslator;
|
||||
import org.geysermc.geyser.translator.protocol.java.entity.spawn.JavaAddExperienceOrbTranslator;
|
||||
import org.geysermc.geyser.translator.protocol.java.scoreboard.JavaSetPlayerTeamTranslator;
|
||||
import org.geysermc.mcprotocollib.auth.GameProfile;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.PlayerListEntry;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.PlayerListEntryAction;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.EntityMetadata;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.MetadataType;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.BooleanEntityMetadata;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.ByteEntityMetadata;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.ObjectEntityMetadata;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.entity.player.GameMode;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.entity.type.EntityType;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.scoreboard.CollisionRule;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.scoreboard.NameTagVisibility;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.scoreboard.TeamAction;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.scoreboard.TeamColor;
|
||||
import org.geysermc.mcprotocollib.protocol.packet.ingame.clientbound.ClientboundPlayerInfoUpdatePacket;
|
||||
import org.geysermc.mcprotocollib.protocol.packet.ingame.clientbound.entity.ClientboundRemoveEntitiesPacket;
|
||||
import org.geysermc.mcprotocollib.protocol.packet.ingame.clientbound.entity.ClientboundSetEntityDataPacket;
|
||||
import org.geysermc.mcprotocollib.protocol.packet.ingame.clientbound.entity.spawn.ClientboundAddEntityPacket;
|
||||
import org.geysermc.mcprotocollib.protocol.packet.ingame.clientbound.entity.spawn.ClientboundAddExperienceOrbPacket;
|
||||
import org.geysermc.mcprotocollib.protocol.packet.ingame.clientbound.scoreboard.ClientboundSetPlayerTeamPacket;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.util.EnumSet;
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* Tests that don't fit in a larger system (e.g. sidebar objective) that were reported on GitHub
|
||||
* Tests for issues reported on GitHub.
|
||||
*/
|
||||
public class ScoreboardIssueTests {
|
||||
/**
|
||||
@ -90,4 +125,137 @@ public class ScoreboardIssueTests {
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Test for <a href="https://github.com/GeyserMC/Geyser/issues/5089">#5089</a>.
|
||||
* It follows the reproduction steps with all the packets it sends along its way.
|
||||
* Tested with the 2.0.0-SNAPSHOT version.
|
||||
* Note that this exact issue is actually 2 issues:
|
||||
* <ul>
|
||||
* <li>
|
||||
* An issue caused by remainders of code that was part of the initial PR that added support for players.
|
||||
* The code is now more streamlined.
|
||||
* </li>
|
||||
* <li>Armor stands are excluded from team visibility checks (the only living entity)</li>
|
||||
* </ul>
|
||||
*/
|
||||
@Test
|
||||
void nameNotUpdating() {
|
||||
mockContextScoreboard(context -> {
|
||||
var playerInfoUpdateTranslator = new JavaPlayerInfoUpdateTranslator();
|
||||
var setPlayerTeamTranslator = new JavaSetPlayerTeamTranslator();
|
||||
var addEntityTranslator = new JavaAddEntityTranslator();
|
||||
var setEntityDataTranslator = new JavaSetEntityDataTranslator();
|
||||
|
||||
|
||||
// first command, create NPC
|
||||
|
||||
|
||||
var npcUuid = UUID.fromString("b0eb01d7-52c9-4730-9fd3-2c03fcb00d6e");
|
||||
context.translate(
|
||||
playerInfoUpdateTranslator,
|
||||
new ClientboundPlayerInfoUpdatePacket(
|
||||
EnumSet.of(PlayerListEntryAction.ADD_PLAYER, PlayerListEntryAction.UPDATE_LISTED),
|
||||
new PlayerListEntry[] {
|
||||
new PlayerListEntry(npcUuid, new GameProfile(npcUuid, "1297"), false, 0, GameMode.SURVIVAL, null, null, 0, null, null)
|
||||
}));
|
||||
|
||||
//todo we don't have to remove an entry that was never in the playerlist in the first place
|
||||
assertNextPacket(context, () -> {
|
||||
var packet = new PlayerListPacket();
|
||||
packet.getEntries().add(new PlayerListPacket.Entry(npcUuid));
|
||||
packet.setAction(PlayerListPacket.Action.REMOVE);
|
||||
return packet;
|
||||
});
|
||||
assertNoNextPacket(context);
|
||||
|
||||
context.translate(
|
||||
setPlayerTeamTranslator,
|
||||
new ClientboundSetPlayerTeamPacket(
|
||||
"npc_team_1297",
|
||||
Component.empty(),
|
||||
Component.empty(),
|
||||
Component.empty(),
|
||||
false,
|
||||
false,
|
||||
NameTagVisibility.NEVER,
|
||||
CollisionRule.NEVER,
|
||||
TeamColor.WHITE,
|
||||
new String[0]
|
||||
)
|
||||
);
|
||||
context.translate(
|
||||
setPlayerTeamTranslator,
|
||||
new ClientboundSetPlayerTeamPacket("npc_team_1297", TeamAction.ADD_PLAYER, new String[]{ "1297" }));
|
||||
|
||||
context.translate(addEntityTranslator, new ClientboundAddEntityPacket(1297, npcUuid, EntityType.PLAYER, 1, 2, 3, 4, 5, 6));
|
||||
// then it updates the displayed skin parts, which isn't relevant for us
|
||||
|
||||
assertNextPacketMatch(context, AddPlayerPacket.class, packet -> {
|
||||
assertEquals(3, packet.getRuntimeEntityId());
|
||||
assertEquals(npcUuid, packet.getUuid());
|
||||
assertEquals("1297", packet.getUsername());
|
||||
assertEquals((byte) 1, packet.getMetadata().get(EntityDataTypes.NAMETAG_ALWAYS_SHOW));
|
||||
assertEquals("", packet.getMetadata().get(EntityDataTypes.NAME));
|
||||
});
|
||||
assertNoNextPacket(context);
|
||||
|
||||
|
||||
// second command, create hologram
|
||||
|
||||
|
||||
var hologramUuid = UUID.fromString("b1586291-5f68-44dc-847d-6c123c5b8cbf");
|
||||
context.translate(
|
||||
addEntityTranslator,
|
||||
new ClientboundAddEntityPacket(1298, hologramUuid, EntityType.ARMOR_STAND, 6, 5, 4, 3, 2, 1));
|
||||
|
||||
assertNextPacketMatch(context, AddEntityPacket.class, packet -> {
|
||||
assertEquals(4, packet.getRuntimeEntityId());
|
||||
assertEquals("minecraft:armor_stand", packet.getIdentifier());
|
||||
});
|
||||
|
||||
// metadata set: invisible, custom name, custom name visible
|
||||
context.translate(setEntityDataTranslator, new ClientboundSetEntityDataPacket(1298, new EntityMetadata[]{
|
||||
new ByteEntityMetadata(0, MetadataType.BYTE, (byte) 0x20),
|
||||
new ObjectEntityMetadata<>(2, MetadataType.OPTIONAL_CHAT, Optional.of(Component.text("tesss"))),
|
||||
new BooleanEntityMetadata(3, MetadataType.BOOLEAN, true)
|
||||
}));
|
||||
|
||||
assertNextPacketMatch(context, SetEntityDataPacket.class, packet -> {
|
||||
assertEquals(4, packet.getRuntimeEntityId());
|
||||
var metadata = packet.getMetadata();
|
||||
assertEquals(0.0f, metadata.get(EntityDataTypes.SCALE));
|
||||
assertEquals("tesss", metadata.get(EntityDataTypes.NAME));
|
||||
assertEquals((byte) 1, metadata.get(EntityDataTypes.NAMETAG_ALWAYS_SHOW));
|
||||
});
|
||||
// because the armor stand turned invisible and has a nametag (nametag is hidden when invisible)
|
||||
assertNextPacketType(context, MoveEntityAbsolutePacket.class);
|
||||
|
||||
context.translate(
|
||||
setPlayerTeamTranslator,
|
||||
new ClientboundSetPlayerTeamPacket(
|
||||
"npc_team_1298",
|
||||
Component.empty(),
|
||||
Component.empty(),
|
||||
Component.empty(),
|
||||
false,
|
||||
false,
|
||||
NameTagVisibility.NEVER,
|
||||
CollisionRule.NEVER,
|
||||
TeamColor.WHITE,
|
||||
new String[0]
|
||||
)
|
||||
);
|
||||
context.translate(
|
||||
setPlayerTeamTranslator,
|
||||
new ClientboundSetPlayerTeamPacket("npc_team_1298", TeamAction.ADD_PLAYER, new String[]{ hologramUuid.toString() }));
|
||||
|
||||
assertNextPacket(context, () -> {
|
||||
var packet = new SetEntityDataPacket();
|
||||
packet.getMetadata().put(EntityDataTypes.NAME, "§f§r§ftesss§r§f");
|
||||
packet.setRuntimeEntityId(4);
|
||||
return packet;
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -27,7 +27,7 @@ package org.geysermc.geyser.scoreboard.network.belowname;
|
||||
|
||||
import static org.geysermc.geyser.scoreboard.network.util.AssertUtils.assertNextPacket;
|
||||
import static org.geysermc.geyser.scoreboard.network.util.AssertUtils.assertNoNextPacket;
|
||||
import static org.geysermc.geyser.scoreboard.network.util.GeyserMockContextScoreboard.mockAndAddPlayerEntity;
|
||||
import static org.geysermc.geyser.scoreboard.network.util.GeyserMockContextScoreboard.spawnPlayerSilently;
|
||||
import static org.geysermc.geyser.scoreboard.network.util.GeyserMockContextScoreboard.mockContextScoreboard;
|
||||
|
||||
import net.kyori.adventure.text.Component;
|
||||
@ -80,7 +80,7 @@ public class BasicBelownameScoreboardTests {
|
||||
var setObjectiveTranslator = new JavaSetObjectiveTranslator();
|
||||
var setDisplayObjectiveTranslator = new JavaSetDisplayObjectiveTranslator();
|
||||
|
||||
mockAndAddPlayerEntity(context, "player1", 2);
|
||||
spawnPlayerSilently(context, "player1", 2);
|
||||
|
||||
context.translate(
|
||||
setObjectiveTranslator,
|
||||
@ -98,12 +98,12 @@ public class BasicBelownameScoreboardTests {
|
||||
setDisplayObjectiveTranslator,
|
||||
new ClientboundSetDisplayObjectivePacket(ScoreboardPosition.BELOW_NAME, "objective")
|
||||
);
|
||||
assertNextPacket(() -> {
|
||||
assertNextPacket(context, () -> {
|
||||
var packet = new SetEntityDataPacket();
|
||||
packet.setRuntimeEntityId(2);
|
||||
packet.getMetadata().put(EntityDataTypes.SCORE, "0 §r§9objective");
|
||||
return packet;
|
||||
}, context);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@ -113,7 +113,7 @@ public class BasicBelownameScoreboardTests {
|
||||
var setObjectiveTranslator = new JavaSetObjectiveTranslator();
|
||||
var setDisplayObjectiveTranslator = new JavaSetDisplayObjectiveTranslator();
|
||||
|
||||
mockAndAddPlayerEntity(context, "player1", 2);
|
||||
spawnPlayerSilently(context, "player1", 2);
|
||||
|
||||
context.translate(
|
||||
setObjectiveTranslator,
|
||||
@ -131,24 +131,24 @@ public class BasicBelownameScoreboardTests {
|
||||
setDisplayObjectiveTranslator,
|
||||
new ClientboundSetDisplayObjectivePacket(ScoreboardPosition.BELOW_NAME, "objective")
|
||||
);
|
||||
assertNextPacket(() -> {
|
||||
assertNextPacket(context, () -> {
|
||||
var packet = new SetEntityDataPacket();
|
||||
packet.setRuntimeEntityId(2);
|
||||
packet.getMetadata().put(EntityDataTypes.SCORE, "0 §robjective");
|
||||
return packet;
|
||||
}, context);
|
||||
});
|
||||
assertNoNextPacket(context);
|
||||
|
||||
context.translate(
|
||||
setDisplayObjectiveTranslator,
|
||||
new ClientboundSetDisplayObjectivePacket(ScoreboardPosition.BELOW_NAME, "")
|
||||
);
|
||||
assertNextPacket(() -> {
|
||||
assertNextPacket(context, () -> {
|
||||
var packet = new SetEntityDataPacket();
|
||||
packet.setRuntimeEntityId(2);
|
||||
packet.getMetadata().put(EntityDataTypes.SCORE, "");
|
||||
return packet;
|
||||
}, context);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@ -158,7 +158,7 @@ public class BasicBelownameScoreboardTests {
|
||||
var setObjectiveTranslator = new JavaSetObjectiveTranslator();
|
||||
var setDisplayObjectiveTranslator = new JavaSetDisplayObjectiveTranslator();
|
||||
|
||||
mockAndAddPlayerEntity(context, "player1", 2);
|
||||
spawnPlayerSilently(context, "player1", 2);
|
||||
|
||||
context.translate(
|
||||
setObjectiveTranslator,
|
||||
@ -186,42 +186,42 @@ public class BasicBelownameScoreboardTests {
|
||||
setDisplayObjectiveTranslator,
|
||||
new ClientboundSetDisplayObjectivePacket(ScoreboardPosition.BELOW_NAME, "objective2")
|
||||
);
|
||||
assertNextPacket(() -> {
|
||||
assertNextPacket(context, () -> {
|
||||
var packet = new SetEntityDataPacket();
|
||||
packet.setRuntimeEntityId(2);
|
||||
packet.getMetadata().put(EntityDataTypes.SCORE, "0 §robjective2");
|
||||
return packet;
|
||||
}, context);
|
||||
});
|
||||
assertNoNextPacket(context);
|
||||
|
||||
context.translate(
|
||||
setDisplayObjectiveTranslator,
|
||||
new ClientboundSetDisplayObjectivePacket(ScoreboardPosition.BELOW_NAME, "objective1")
|
||||
);
|
||||
assertNextPacket(() -> {
|
||||
assertNextPacket(context, () -> {
|
||||
var packet = new SetEntityDataPacket();
|
||||
packet.setRuntimeEntityId(2);
|
||||
packet.getMetadata().put(EntityDataTypes.SCORE, "");
|
||||
return packet;
|
||||
}, context);
|
||||
assertNextPacket(() -> {
|
||||
});
|
||||
assertNextPacket(context, () -> {
|
||||
var packet = new SetEntityDataPacket();
|
||||
packet.setRuntimeEntityId(2);
|
||||
packet.getMetadata().put(EntityDataTypes.SCORE, "0 §robjective1");
|
||||
return packet;
|
||||
}, context);
|
||||
});
|
||||
assertNoNextPacket(context);
|
||||
|
||||
context.translate(
|
||||
setDisplayObjectiveTranslator,
|
||||
new ClientboundSetDisplayObjectivePacket(ScoreboardPosition.BELOW_NAME, "")
|
||||
);
|
||||
assertNextPacket(() -> {
|
||||
assertNextPacket(context, () -> {
|
||||
var packet = new SetEntityDataPacket();
|
||||
packet.setRuntimeEntityId(2);
|
||||
packet.getMetadata().put(EntityDataTypes.SCORE, "");
|
||||
return packet;
|
||||
}, context);
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -32,7 +32,6 @@ import static org.geysermc.geyser.scoreboard.network.util.GeyserMockContextScore
|
||||
import java.util.List;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.format.NamedTextColor;
|
||||
import net.kyori.adventure.text.format.Style;
|
||||
import net.kyori.adventure.text.format.TextDecoration;
|
||||
import org.cloudburstmc.protocol.bedrock.data.ScoreInfo;
|
||||
import org.cloudburstmc.protocol.bedrock.packet.RemoveObjectivePacket;
|
||||
@ -75,7 +74,7 @@ public class BasicPlayerlistScoreboardTests {
|
||||
setDisplayObjectiveTranslator,
|
||||
new ClientboundSetDisplayObjectivePacket(ScoreboardPosition.PLAYER_LIST, "objective")
|
||||
);
|
||||
assertNextPacket(() -> {
|
||||
assertNextPacket(context, () -> {
|
||||
var packet = new SetDisplayObjectivePacket();
|
||||
packet.setObjectiveId("0");
|
||||
packet.setDisplayName("objective");
|
||||
@ -83,7 +82,7 @@ public class BasicPlayerlistScoreboardTests {
|
||||
packet.setDisplaySlot("list");
|
||||
packet.setSortOrder(1);
|
||||
return packet;
|
||||
}, context);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@ -98,7 +97,7 @@ public class BasicPlayerlistScoreboardTests {
|
||||
new ClientboundSetObjectivePacket(
|
||||
"objective",
|
||||
ObjectiveAction.ADD,
|
||||
Component.text("objective", Style.style(NamedTextColor.AQUA, TextDecoration.BOLD)),
|
||||
Component.text("objective", NamedTextColor.AQUA, TextDecoration.BOLD),
|
||||
ScoreType.INTEGER,
|
||||
null
|
||||
)
|
||||
@ -109,7 +108,7 @@ public class BasicPlayerlistScoreboardTests {
|
||||
setDisplayObjectiveTranslator,
|
||||
new ClientboundSetDisplayObjectivePacket(ScoreboardPosition.PLAYER_LIST, "objective")
|
||||
);
|
||||
assertNextPacket(() -> {
|
||||
assertNextPacket(context, () -> {
|
||||
var packet = new SetDisplayObjectivePacket();
|
||||
packet.setObjectiveId("0");
|
||||
packet.setDisplayName("§b§lobjective");
|
||||
@ -117,7 +116,7 @@ public class BasicPlayerlistScoreboardTests {
|
||||
packet.setDisplaySlot("list");
|
||||
packet.setSortOrder(1);
|
||||
return packet;
|
||||
}, context);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@ -156,7 +155,7 @@ public class BasicPlayerlistScoreboardTests {
|
||||
setDisplayObjectiveTranslator,
|
||||
new ClientboundSetDisplayObjectivePacket(ScoreboardPosition.PLAYER_LIST, "objective2")
|
||||
);
|
||||
assertNextPacket(() -> {
|
||||
assertNextPacket(context, () -> {
|
||||
var packet = new SetDisplayObjectivePacket();
|
||||
packet.setObjectiveId("0");
|
||||
packet.setDisplayName("objective2");
|
||||
@ -164,26 +163,26 @@ public class BasicPlayerlistScoreboardTests {
|
||||
packet.setDisplaySlot("list");
|
||||
packet.setSortOrder(1);
|
||||
return packet;
|
||||
}, context);
|
||||
assertNextPacket(() -> {
|
||||
});
|
||||
assertNextPacket(context, () -> {
|
||||
var packet = new SetScorePacket();
|
||||
packet.setAction(SetScorePacket.Action.SET);
|
||||
// session player name is Tim203
|
||||
packet.setInfos(List.of(new ScoreInfo(1, "0", 2, ScoreInfo.ScorerType.PLAYER, 1)));
|
||||
return packet;
|
||||
}, context);
|
||||
});
|
||||
assertNoNextPacket(context);
|
||||
|
||||
context.translate(
|
||||
setDisplayObjectiveTranslator,
|
||||
new ClientboundSetDisplayObjectivePacket(ScoreboardPosition.PLAYER_LIST, "objective1")
|
||||
);
|
||||
assertNextPacket(() -> {
|
||||
assertNextPacket(context, () -> {
|
||||
var packet = new RemoveObjectivePacket();
|
||||
packet.setObjectiveId("0");
|
||||
return packet;
|
||||
}, context);
|
||||
assertNextPacket(() -> {
|
||||
});
|
||||
assertNextPacket(context, () -> {
|
||||
var packet = new SetDisplayObjectivePacket();
|
||||
packet.setObjectiveId("2");
|
||||
packet.setDisplayName("objective1");
|
||||
@ -191,14 +190,14 @@ public class BasicPlayerlistScoreboardTests {
|
||||
packet.setDisplaySlot("list");
|
||||
packet.setSortOrder(1);
|
||||
return packet;
|
||||
}, context);
|
||||
assertNextPacket(() -> {
|
||||
});
|
||||
assertNextPacket(context, () -> {
|
||||
var packet = new SetScorePacket();
|
||||
packet.setAction(SetScorePacket.Action.SET);
|
||||
// session player name is Tim203
|
||||
packet.setInfos(List.of(new ScoreInfo(3, "2", 1, ScoreInfo.ScorerType.PLAYER, 1)));
|
||||
return packet;
|
||||
}, context);
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -26,21 +26,22 @@
|
||||
package org.geysermc.geyser.scoreboard.network.server;
|
||||
|
||||
import static org.geysermc.geyser.scoreboard.network.util.AssertUtils.assertNextPacket;
|
||||
import static org.geysermc.geyser.scoreboard.network.util.AssertUtils.assertNextPacketMatch;
|
||||
import static org.geysermc.geyser.scoreboard.network.util.AssertUtils.assertNoNextPacket;
|
||||
import static org.geysermc.geyser.scoreboard.network.util.GeyserMockContextScoreboard.mockAndAddPlayerEntity;
|
||||
import static org.geysermc.geyser.scoreboard.network.util.GeyserMockContextScoreboard.spawnPlayer;
|
||||
import static org.geysermc.geyser.scoreboard.network.util.GeyserMockContextScoreboard.mockContextScoreboard;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
||||
import java.util.List;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.format.NamedTextColor;
|
||||
import net.kyori.adventure.text.format.Style;
|
||||
import net.kyori.adventure.text.format.TextColor;
|
||||
import net.kyori.adventure.text.format.TextDecoration;
|
||||
import org.cloudburstmc.protocol.bedrock.data.ScoreInfo;
|
||||
import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes;
|
||||
import org.cloudburstmc.protocol.bedrock.packet.AddPlayerPacket;
|
||||
import org.cloudburstmc.protocol.bedrock.packet.RemoveObjectivePacket;
|
||||
import org.cloudburstmc.protocol.bedrock.packet.SetDisplayObjectivePacket;
|
||||
import org.cloudburstmc.protocol.bedrock.packet.SetEntityDataPacket;
|
||||
import org.cloudburstmc.protocol.bedrock.packet.SetScorePacket;
|
||||
import org.geysermc.geyser.translator.protocol.java.scoreboard.JavaSetDisplayObjectiveTranslator;
|
||||
import org.geysermc.geyser.translator.protocol.java.scoreboard.JavaSetObjectiveTranslator;
|
||||
@ -88,7 +89,7 @@ public class CubecraftScoreboardTest {
|
||||
setDisplayObjectiveTranslator,
|
||||
new ClientboundSetDisplayObjectivePacket(ScoreboardPosition.SIDEBAR, "sidebar")
|
||||
);
|
||||
assertNextPacket(() -> {
|
||||
assertNextPacket(context, () -> {
|
||||
var packet = new SetDisplayObjectivePacket();
|
||||
packet.setObjectiveId("0");
|
||||
packet.setDisplayName("sidebar");
|
||||
@ -96,7 +97,7 @@ public class CubecraftScoreboardTest {
|
||||
packet.setDisplaySlot("sidebar");
|
||||
packet.setSortOrder(1);
|
||||
return packet;
|
||||
}, context);
|
||||
});
|
||||
|
||||
|
||||
// Now they're going to create a bunch of teams and add players to those teams in a very inefficient way.
|
||||
@ -191,27 +192,23 @@ public class CubecraftScoreboardTest {
|
||||
ObjectiveAction.UPDATE,
|
||||
Component.empty()
|
||||
.append(Component.text(
|
||||
"CubeCraft", Style.style(NamedTextColor.WHITE, TextDecoration.BOLD))),
|
||||
"CubeCraft", NamedTextColor.WHITE, TextDecoration.BOLD)),
|
||||
ScoreType.INTEGER,
|
||||
null));
|
||||
assertNextPacket(
|
||||
() -> {
|
||||
var packet = new RemoveObjectivePacket();
|
||||
packet.setObjectiveId("0");
|
||||
return packet;
|
||||
},
|
||||
context);
|
||||
assertNextPacket(
|
||||
() -> {
|
||||
var packet = new SetDisplayObjectivePacket();
|
||||
packet.setObjectiveId("0");
|
||||
packet.setDisplayName("§f§lCubeCraft");
|
||||
packet.setCriteria("dummy");
|
||||
packet.setDisplaySlot("sidebar");
|
||||
packet.setSortOrder(1);
|
||||
return packet;
|
||||
},
|
||||
context);
|
||||
assertNextPacket(context, () -> {
|
||||
var packet = new RemoveObjectivePacket();
|
||||
packet.setObjectiveId("0");
|
||||
return packet;
|
||||
});
|
||||
assertNextPacket(context, () -> {
|
||||
var packet = new SetDisplayObjectivePacket();
|
||||
packet.setObjectiveId("0");
|
||||
packet.setDisplayName("§f§lCubeCraft");
|
||||
packet.setCriteria("dummy");
|
||||
packet.setDisplaySlot("sidebar");
|
||||
packet.setSortOrder(1);
|
||||
return packet;
|
||||
});
|
||||
|
||||
context.translate(
|
||||
setTeamTranslator,
|
||||
@ -234,7 +231,7 @@ public class CubecraftScoreboardTest {
|
||||
new ClientboundSetPlayerTeamPacket(
|
||||
"SB_l-0",
|
||||
Component.text("SB_l-0"),
|
||||
Component.empty().append(Component.text("", Style.style(NamedTextColor.BLACK))),
|
||||
Component.empty().append(Component.text("", NamedTextColor.BLACK)),
|
||||
Component.empty(),
|
||||
true,
|
||||
true,
|
||||
@ -244,14 +241,12 @@ public class CubecraftScoreboardTest {
|
||||
assertNoNextPacket(context);
|
||||
|
||||
context.translate(setScoreTranslator, new ClientboundSetScorePacket("§0§0", "sidebar", 10));
|
||||
assertNextPacket(
|
||||
() -> {
|
||||
var packet = new SetScorePacket();
|
||||
packet.setAction(SetScorePacket.Action.SET);
|
||||
packet.setInfos(List.of(new ScoreInfo(1, "0", 10, "§r§0§0§r")));
|
||||
return packet;
|
||||
},
|
||||
context);
|
||||
assertNextPacket(context, () -> {
|
||||
var packet = new SetScorePacket();
|
||||
packet.setAction(SetScorePacket.Action.SET);
|
||||
packet.setInfos(List.of(new ScoreInfo(1, "0", 10, "§r§0§0§r")));
|
||||
return packet;
|
||||
});
|
||||
|
||||
context.translate(
|
||||
setTeamTranslator,
|
||||
@ -287,14 +282,12 @@ public class CubecraftScoreboardTest {
|
||||
assertNoNextPacket(context);
|
||||
|
||||
context.translate(setScoreTranslator, new ClientboundSetScorePacket("§0§1", "sidebar", 9));
|
||||
assertNextPacket(
|
||||
() -> {
|
||||
var packet = new SetScorePacket();
|
||||
packet.setAction(SetScorePacket.Action.SET);
|
||||
packet.setInfos(List.of(new ScoreInfo(2, "0", 9, "§bUser: §r§fTim203§r§0§1§r")));
|
||||
return packet;
|
||||
},
|
||||
context);
|
||||
assertNextPacket(context, () -> {
|
||||
var packet = new SetScorePacket();
|
||||
packet.setAction(SetScorePacket.Action.SET);
|
||||
packet.setInfos(List.of(new ScoreInfo(2, "0", 9, "§bUser: §r§fTim203§r§0§1§r")));
|
||||
return packet;
|
||||
});
|
||||
|
||||
context.translate(
|
||||
setTeamTranslator,
|
||||
@ -330,14 +323,12 @@ public class CubecraftScoreboardTest {
|
||||
assertNoNextPacket(context);
|
||||
|
||||
context.translate(setScoreTranslator, new ClientboundSetScorePacket("§0§2", "sidebar", 8));
|
||||
assertNextPacket(
|
||||
() -> {
|
||||
var packet = new SetScorePacket();
|
||||
packet.setAction(SetScorePacket.Action.SET);
|
||||
packet.setInfos(List.of(new ScoreInfo(3, "0", 8, "§bRank: §r§f\uE1AB §r§0§2§r")));
|
||||
return packet;
|
||||
},
|
||||
context);
|
||||
assertNextPacket(context, () -> {
|
||||
var packet = new SetScorePacket();
|
||||
packet.setAction(SetScorePacket.Action.SET);
|
||||
packet.setInfos(List.of(new ScoreInfo(3, "0", 8, "§bRank: §r§f\uE1AB §r§0§2§r")));
|
||||
return packet;
|
||||
});
|
||||
|
||||
context.translate(
|
||||
setTeamTranslator,
|
||||
@ -370,14 +361,12 @@ public class CubecraftScoreboardTest {
|
||||
assertNoNextPacket(context);
|
||||
|
||||
context.translate(setScoreTranslator, new ClientboundSetScorePacket("§0§3", "sidebar", 7));
|
||||
assertNextPacket(
|
||||
() -> {
|
||||
var packet = new SetScorePacket();
|
||||
packet.setAction(SetScorePacket.Action.SET);
|
||||
packet.setInfos(List.of(new ScoreInfo(4, "0", 7, "§r§0§3§r")));
|
||||
return packet;
|
||||
},
|
||||
context);
|
||||
assertNextPacket(context, () -> {
|
||||
var packet = new SetScorePacket();
|
||||
packet.setAction(SetScorePacket.Action.SET);
|
||||
packet.setInfos(List.of(new ScoreInfo(4, "0", 7, "§r§0§3§r")));
|
||||
return packet;
|
||||
});
|
||||
|
||||
context.translate(
|
||||
setTeamTranslator,
|
||||
@ -410,14 +399,12 @@ public class CubecraftScoreboardTest {
|
||||
assertNoNextPacket(context);
|
||||
|
||||
context.translate(setScoreTranslator, new ClientboundSetScorePacket("§0§4", "sidebar", 6));
|
||||
assertNextPacket(
|
||||
() -> {
|
||||
var packet = new SetScorePacket();
|
||||
packet.setAction(SetScorePacket.Action.SET);
|
||||
packet.setInfos(List.of(new ScoreInfo(5, "0", 6, "§r§0§4§r")));
|
||||
return packet;
|
||||
},
|
||||
context);
|
||||
assertNextPacket(context, () -> {
|
||||
var packet = new SetScorePacket();
|
||||
packet.setAction(SetScorePacket.Action.SET);
|
||||
packet.setInfos(List.of(new ScoreInfo(5, "0", 6, "§r§0§4§r")));
|
||||
return packet;
|
||||
});
|
||||
|
||||
context.translate(
|
||||
setTeamTranslator,
|
||||
@ -450,14 +437,12 @@ public class CubecraftScoreboardTest {
|
||||
assertNoNextPacket(context);
|
||||
|
||||
context.translate(setScoreTranslator, new ClientboundSetScorePacket("§0§5", "sidebar", 5));
|
||||
assertNextPacket(
|
||||
() -> {
|
||||
var packet = new SetScorePacket();
|
||||
packet.setAction(SetScorePacket.Action.SET);
|
||||
packet.setInfos(List.of(new ScoreInfo(6, "0", 5, "§r§0§5§r")));
|
||||
return packet;
|
||||
},
|
||||
context);
|
||||
assertNextPacket(context, () -> {
|
||||
var packet = new SetScorePacket();
|
||||
packet.setAction(SetScorePacket.Action.SET);
|
||||
packet.setInfos(List.of(new ScoreInfo(6, "0", 5, "§r§0§5§r")));
|
||||
return packet;
|
||||
});
|
||||
|
||||
context.translate(
|
||||
setTeamTranslator,
|
||||
@ -493,14 +478,12 @@ public class CubecraftScoreboardTest {
|
||||
assertNoNextPacket(context);
|
||||
|
||||
context.translate(setScoreTranslator, new ClientboundSetScorePacket("§0§6", "sidebar", 4));
|
||||
assertNextPacket(
|
||||
() -> {
|
||||
var packet = new SetScorePacket();
|
||||
packet.setAction(SetScorePacket.Action.SET);
|
||||
packet.setInfos(List.of(new ScoreInfo(7, "0", 4, "§bLobby: §r§fEU #10§r§0§6§r")));
|
||||
return packet;
|
||||
},
|
||||
context);
|
||||
assertNextPacket(context, () -> {
|
||||
var packet = new SetScorePacket();
|
||||
packet.setAction(SetScorePacket.Action.SET);
|
||||
packet.setInfos(List.of(new ScoreInfo(7, "0", 4, "§bLobby: §r§fEU #10§r§0§6§r")));
|
||||
return packet;
|
||||
});
|
||||
|
||||
context.translate(
|
||||
setTeamTranslator,
|
||||
@ -536,14 +519,12 @@ public class CubecraftScoreboardTest {
|
||||
assertNoNextPacket(context);
|
||||
|
||||
context.translate(setScoreTranslator, new ClientboundSetScorePacket("§0§7", "sidebar", 3));
|
||||
assertNextPacket(
|
||||
() -> {
|
||||
var packet = new SetScorePacket();
|
||||
packet.setAction(SetScorePacket.Action.SET);
|
||||
packet.setInfos(List.of(new ScoreInfo(8, "0", 3, "§bPlayers: §r§f783§r§0§7§r")));
|
||||
return packet;
|
||||
},
|
||||
context);
|
||||
assertNextPacket(context, () -> {
|
||||
var packet = new SetScorePacket();
|
||||
packet.setAction(SetScorePacket.Action.SET);
|
||||
packet.setInfos(List.of(new ScoreInfo(8, "0", 3, "§bPlayers: §r§f783§r§0§7§r")));
|
||||
return packet;
|
||||
});
|
||||
|
||||
context.translate(
|
||||
setTeamTranslator,
|
||||
@ -576,14 +557,12 @@ public class CubecraftScoreboardTest {
|
||||
assertNoNextPacket(context);
|
||||
|
||||
context.translate(setScoreTranslator, new ClientboundSetScorePacket("§0§8", "sidebar", 2));
|
||||
assertNextPacket(
|
||||
() -> {
|
||||
var packet = new SetScorePacket();
|
||||
packet.setAction(SetScorePacket.Action.SET);
|
||||
packet.setInfos(List.of(new ScoreInfo(9, "0", 2, "§r§0§8§r")));
|
||||
return packet;
|
||||
},
|
||||
context);
|
||||
assertNextPacket(context, () -> {
|
||||
var packet = new SetScorePacket();
|
||||
packet.setAction(SetScorePacket.Action.SET);
|
||||
packet.setInfos(List.of(new ScoreInfo(9, "0", 2, "§r§0§8§r")));
|
||||
return packet;
|
||||
});
|
||||
|
||||
context.translate(
|
||||
setTeamTranslator,
|
||||
@ -616,14 +595,12 @@ public class CubecraftScoreboardTest {
|
||||
assertNoNextPacket(context);
|
||||
|
||||
context.translate(setScoreTranslator, new ClientboundSetScorePacket("§0§9", "sidebar", 1));
|
||||
assertNextPacket(
|
||||
() -> {
|
||||
var packet = new SetScorePacket();
|
||||
packet.setAction(SetScorePacket.Action.SET);
|
||||
packet.setInfos(List.of(new ScoreInfo(10, "0", 1, "§824/09/24 (g2208)§r§0§9§r")));
|
||||
return packet;
|
||||
},
|
||||
context);
|
||||
assertNextPacket(context, () -> {
|
||||
var packet = new SetScorePacket();
|
||||
packet.setAction(SetScorePacket.Action.SET);
|
||||
packet.setInfos(List.of(new ScoreInfo(10, "0", 1, "§824/09/24 (g2208)§r§0§9§r")));
|
||||
return packet;
|
||||
});
|
||||
|
||||
context.translate(
|
||||
setTeamTranslator,
|
||||
@ -656,14 +633,12 @@ public class CubecraftScoreboardTest {
|
||||
assertNoNextPacket(context);
|
||||
|
||||
context.translate(setScoreTranslator, new ClientboundSetScorePacket("§0§a", "sidebar", 0));
|
||||
assertNextPacket(
|
||||
() -> {
|
||||
var packet = new SetScorePacket();
|
||||
packet.setAction(SetScorePacket.Action.SET);
|
||||
packet.setInfos(List.of(new ScoreInfo(11, "0", 0, "§6play.cubecraft.net§r§0§a§r")));
|
||||
return packet;
|
||||
},
|
||||
context);
|
||||
assertNextPacket(context, () -> {
|
||||
var packet = new SetScorePacket();
|
||||
packet.setAction(SetScorePacket.Action.SET);
|
||||
packet.setInfos(List.of(new ScoreInfo(11, "0", 0, "§6play.cubecraft.net§r§0§a§r")));
|
||||
return packet;
|
||||
});
|
||||
|
||||
// after this we get a ClientboundPlayerInfoUpdatePacket with the action UPDATE_DISPLAY_NAME,
|
||||
// but that one is only shown in the tablist so we don't have to handle that.
|
||||
@ -672,85 +647,53 @@ public class CubecraftScoreboardTest {
|
||||
// CubeCraft seems to use two armor stands per player: 1 for the rank badge and 1 for the player name.
|
||||
// So the only thing we have to verify is that the nametag is hidden
|
||||
|
||||
mockAndAddPlayerEntity(context, "A_Player", 2);
|
||||
assertNextPacket(
|
||||
() -> {
|
||||
var packet = new SetEntityDataPacket();
|
||||
packet.setRuntimeEntityId(2);
|
||||
packet.getMetadata().put(EntityDataTypes.NAME, "");
|
||||
return packet;
|
||||
},
|
||||
context);
|
||||
spawnPlayer(context, "A_Player", 2);
|
||||
assertNextPacketMatch(context, AddPlayerPacket.class, packet -> {
|
||||
assertEquals(2, packet.getRuntimeEntityId());
|
||||
assertEquals("", packet.getMetadata().get(EntityDataTypes.NAME));
|
||||
});
|
||||
|
||||
mockAndAddPlayerEntity(context, "B_Player", 3);
|
||||
assertNextPacket(
|
||||
() -> {
|
||||
var packet = new SetEntityDataPacket();
|
||||
packet.setRuntimeEntityId(3);
|
||||
packet.getMetadata().put(EntityDataTypes.NAME, "");
|
||||
return packet;
|
||||
},
|
||||
context);
|
||||
spawnPlayer(context, "B_Player", 3);
|
||||
assertNextPacketMatch(context, AddPlayerPacket.class, packet -> {
|
||||
assertEquals(3, packet.getRuntimeEntityId());
|
||||
assertEquals("", packet.getMetadata().get(EntityDataTypes.NAME));
|
||||
});
|
||||
|
||||
mockAndAddPlayerEntity(context, "E_Player", 4);
|
||||
assertNextPacket(
|
||||
() -> {
|
||||
var packet = new SetEntityDataPacket();
|
||||
packet.setRuntimeEntityId(4);
|
||||
packet.getMetadata().put(EntityDataTypes.NAME, "");
|
||||
return packet;
|
||||
},
|
||||
context);
|
||||
spawnPlayer(context, "E_Player", 4);
|
||||
assertNextPacketMatch(context, AddPlayerPacket.class, packet -> {
|
||||
assertEquals(4, packet.getRuntimeEntityId());
|
||||
assertEquals("", packet.getMetadata().get(EntityDataTypes.NAME));
|
||||
});
|
||||
|
||||
mockAndAddPlayerEntity(context, "H_Player", 5);
|
||||
assertNextPacket(
|
||||
() -> {
|
||||
var packet = new SetEntityDataPacket();
|
||||
packet.setRuntimeEntityId(5);
|
||||
packet.getMetadata().put(EntityDataTypes.NAME, "");
|
||||
return packet;
|
||||
},
|
||||
context);
|
||||
spawnPlayer(context, "H_Player", 5);
|
||||
assertNextPacketMatch(context, AddPlayerPacket.class, packet -> {
|
||||
assertEquals(5, packet.getRuntimeEntityId());
|
||||
assertEquals("", packet.getMetadata().get(EntityDataTypes.NAME));
|
||||
});
|
||||
|
||||
mockAndAddPlayerEntity(context, "J_Player", 6);
|
||||
assertNextPacket(
|
||||
() -> {
|
||||
var packet = new SetEntityDataPacket();
|
||||
packet.setRuntimeEntityId(6);
|
||||
packet.getMetadata().put(EntityDataTypes.NAME, "");
|
||||
return packet;
|
||||
},
|
||||
context);
|
||||
spawnPlayer(context, "J_Player", 6);
|
||||
assertNextPacketMatch(context, AddPlayerPacket.class, packet -> {
|
||||
assertEquals(6, packet.getRuntimeEntityId());
|
||||
assertEquals("", packet.getMetadata().get(EntityDataTypes.NAME));
|
||||
});
|
||||
|
||||
mockAndAddPlayerEntity(context, "K_Player", 7);
|
||||
assertNextPacket(
|
||||
() -> {
|
||||
var packet = new SetEntityDataPacket();
|
||||
packet.setRuntimeEntityId(7);
|
||||
packet.getMetadata().put(EntityDataTypes.NAME, "");
|
||||
return packet;
|
||||
},
|
||||
context);
|
||||
spawnPlayer(context, "K_Player", 7);
|
||||
assertNextPacketMatch(context, AddPlayerPacket.class, packet -> {
|
||||
assertEquals(7, packet.getRuntimeEntityId());
|
||||
assertEquals("", packet.getMetadata().get(EntityDataTypes.NAME));
|
||||
});
|
||||
|
||||
mockAndAddPlayerEntity(context, "L_Player", 8);
|
||||
assertNextPacket(
|
||||
() -> {
|
||||
var packet = new SetEntityDataPacket();
|
||||
packet.setRuntimeEntityId(8);
|
||||
packet.getMetadata().put(EntityDataTypes.NAME, "");
|
||||
return packet;
|
||||
},
|
||||
context);
|
||||
spawnPlayer(context, "L_Player", 8);
|
||||
assertNextPacketMatch(context, AddPlayerPacket.class, packet -> {
|
||||
assertEquals(8, packet.getRuntimeEntityId());
|
||||
assertEquals("", packet.getMetadata().get(EntityDataTypes.NAME));
|
||||
});
|
||||
|
||||
mockAndAddPlayerEntity(context, "O_Player", 9);
|
||||
assertNextPacket(
|
||||
() -> {
|
||||
var packet = new SetEntityDataPacket();
|
||||
packet.setRuntimeEntityId(9);
|
||||
packet.getMetadata().put(EntityDataTypes.NAME, "");
|
||||
return packet;
|
||||
},
|
||||
context);
|
||||
spawnPlayer(context, "O_Player", 9);
|
||||
assertNextPacketMatch(context, AddPlayerPacket.class, packet -> {
|
||||
assertEquals(9, packet.getRuntimeEntityId());
|
||||
assertEquals("", packet.getMetadata().get(EntityDataTypes.NAME));
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -32,7 +32,6 @@ import static org.geysermc.geyser.scoreboard.network.util.GeyserMockContextScore
|
||||
import java.util.List;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.format.NamedTextColor;
|
||||
import net.kyori.adventure.text.format.Style;
|
||||
import net.kyori.adventure.text.format.TextDecoration;
|
||||
import org.cloudburstmc.protocol.bedrock.data.ScoreInfo;
|
||||
import org.cloudburstmc.protocol.bedrock.packet.RemoveObjectivePacket;
|
||||
@ -75,7 +74,7 @@ public class BasicSidebarScoreboardTests {
|
||||
setDisplayObjectiveTranslator,
|
||||
new ClientboundSetDisplayObjectivePacket(ScoreboardPosition.PLAYER_LIST, "objective")
|
||||
);
|
||||
assertNextPacket(() -> {
|
||||
assertNextPacket(context, () -> {
|
||||
var packet = new SetDisplayObjectivePacket();
|
||||
packet.setObjectiveId("0");
|
||||
packet.setDisplayName("objective");
|
||||
@ -83,17 +82,17 @@ public class BasicSidebarScoreboardTests {
|
||||
packet.setDisplaySlot("list");
|
||||
packet.setSortOrder(1);
|
||||
return packet;
|
||||
}, context);
|
||||
});
|
||||
|
||||
context.translate(
|
||||
setDisplayObjectiveTranslator,
|
||||
new ClientboundSetDisplayObjectivePacket(ScoreboardPosition.PLAYER_LIST, "")
|
||||
);
|
||||
assertNextPacket(() -> {
|
||||
assertNextPacket(context, () -> {
|
||||
var packet = new RemoveObjectivePacket();
|
||||
packet.setObjectiveId("0");
|
||||
return packet;
|
||||
}, context);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@ -108,7 +107,7 @@ public class BasicSidebarScoreboardTests {
|
||||
new ClientboundSetObjectivePacket(
|
||||
"objective",
|
||||
ObjectiveAction.ADD,
|
||||
Component.text("objective", Style.style(NamedTextColor.AQUA, TextDecoration.BOLD)),
|
||||
Component.text("objective", NamedTextColor.AQUA, TextDecoration.BOLD),
|
||||
ScoreType.INTEGER,
|
||||
null
|
||||
)
|
||||
@ -119,7 +118,7 @@ public class BasicSidebarScoreboardTests {
|
||||
setDisplayObjectiveTranslator,
|
||||
new ClientboundSetDisplayObjectivePacket(ScoreboardPosition.SIDEBAR, "objective")
|
||||
);
|
||||
assertNextPacket(() -> {
|
||||
assertNextPacket(context, () -> {
|
||||
var packet = new SetDisplayObjectivePacket();
|
||||
packet.setObjectiveId("0");
|
||||
packet.setDisplayName("§b§lobjective");
|
||||
@ -127,7 +126,7 @@ public class BasicSidebarScoreboardTests {
|
||||
packet.setDisplaySlot("sidebar");
|
||||
packet.setSortOrder(1);
|
||||
return packet;
|
||||
}, context);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@ -170,7 +169,7 @@ public class BasicSidebarScoreboardTests {
|
||||
new ClientboundSetDisplayObjectivePacket(ScoreboardPosition.SIDEBAR, "objective2")
|
||||
);
|
||||
|
||||
assertNextPacket(() -> {
|
||||
assertNextPacket(context, () -> {
|
||||
var packet = new SetDisplayObjectivePacket();
|
||||
packet.setObjectiveId("0");
|
||||
packet.setDisplayName("objective2");
|
||||
@ -178,13 +177,13 @@ public class BasicSidebarScoreboardTests {
|
||||
packet.setDisplaySlot("sidebar");
|
||||
packet.setSortOrder(1);
|
||||
return packet;
|
||||
}, context);
|
||||
assertNextPacket(() -> {
|
||||
});
|
||||
assertNextPacket(context, () -> {
|
||||
var packet = new SetScorePacket();
|
||||
packet.setAction(SetScorePacket.Action.SET);
|
||||
packet.setInfos(List.of(new ScoreInfo(1, "0", 2, "Tim203")));
|
||||
return packet;
|
||||
}, context);
|
||||
});
|
||||
assertNoNextPacket(context);
|
||||
|
||||
|
||||
@ -193,12 +192,12 @@ public class BasicSidebarScoreboardTests {
|
||||
new ClientboundSetDisplayObjectivePacket(ScoreboardPosition.SIDEBAR, "objective1")
|
||||
);
|
||||
|
||||
assertNextPacket(() -> {
|
||||
assertNextPacket(context, () -> {
|
||||
var packet = new RemoveObjectivePacket();
|
||||
packet.setObjectiveId("0");
|
||||
return packet;
|
||||
}, context);
|
||||
assertNextPacket(() -> {
|
||||
});
|
||||
assertNextPacket(context, () -> {
|
||||
var packet = new SetDisplayObjectivePacket();
|
||||
packet.setObjectiveId("2");
|
||||
packet.setDisplayName("objective1");
|
||||
@ -206,13 +205,13 @@ public class BasicSidebarScoreboardTests {
|
||||
packet.setDisplaySlot("sidebar");
|
||||
packet.setSortOrder(1);
|
||||
return packet;
|
||||
}, context);
|
||||
assertNextPacket(() -> {
|
||||
});
|
||||
assertNextPacket(context, () -> {
|
||||
var packet = new SetScorePacket();
|
||||
packet.setAction(SetScorePacket.Action.SET);
|
||||
packet.setInfos(List.of(new ScoreInfo(3, "2", 1, "Tim203")));
|
||||
return packet;
|
||||
}, context);
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -98,7 +98,7 @@ public class OrderAndLimitSidebarScoreboardTests {
|
||||
setDisplayObjectiveTranslator,
|
||||
new ClientboundSetDisplayObjectivePacket(ScoreboardPosition.SIDEBAR, "objective")
|
||||
);
|
||||
assertNextPacket(() -> {
|
||||
assertNextPacket(context, () -> {
|
||||
var packet = new SetDisplayObjectivePacket();
|
||||
packet.setObjectiveId("0");
|
||||
packet.setDisplayName("objective");
|
||||
@ -106,8 +106,8 @@ public class OrderAndLimitSidebarScoreboardTests {
|
||||
packet.setDisplaySlot("sidebar");
|
||||
packet.setSortOrder(1);
|
||||
return packet;
|
||||
}, context);
|
||||
assertNextPacket(() -> {
|
||||
});
|
||||
assertNextPacket(context, () -> {
|
||||
var packet = new SetScorePacket();
|
||||
packet.setAction(SetScorePacket.Action.SET);
|
||||
packet.setInfos(List.of(
|
||||
@ -128,7 +128,7 @@ public class OrderAndLimitSidebarScoreboardTests {
|
||||
new ScoreInfo(15, "0", 3, "c")
|
||||
));
|
||||
return packet;
|
||||
}, context);
|
||||
});
|
||||
assertNoNextPacket(context);
|
||||
|
||||
// remove a score
|
||||
@ -136,43 +136,43 @@ public class OrderAndLimitSidebarScoreboardTests {
|
||||
resetScoreTranslator,
|
||||
new ClientboundResetScorePacket("m", "objective")
|
||||
);
|
||||
assertNextPacket(() -> {
|
||||
assertNextPacket(context, () -> {
|
||||
var packet = new SetScorePacket();
|
||||
packet.setAction(SetScorePacket.Action.REMOVE);
|
||||
packet.setInfos(List.of(new ScoreInfo(5, "0", 13, "m")));
|
||||
return packet;
|
||||
}, context);
|
||||
assertNextPacket(() -> {
|
||||
});
|
||||
assertNextPacket(context, () -> {
|
||||
var packet = new SetScorePacket();
|
||||
packet.setAction(SetScorePacket.Action.SET);
|
||||
packet.setInfos(List.of(new ScoreInfo(16, "0", 2, "b")));
|
||||
return packet;
|
||||
}, context);
|
||||
});
|
||||
|
||||
// add a score
|
||||
context.translate(
|
||||
setScoreTranslator,
|
||||
new ClientboundSetScorePacket("aa", "objective", 13)
|
||||
);
|
||||
assertNextPacket(() -> {
|
||||
assertNextPacket(context, () -> {
|
||||
var packet = new SetScorePacket();
|
||||
packet.setAction(SetScorePacket.Action.REMOVE);
|
||||
packet.setInfos(List.of(new ScoreInfo(16, "0", 2, "b")));
|
||||
return packet;
|
||||
}, context);
|
||||
assertNextPacket(() -> {
|
||||
});
|
||||
assertNextPacket(context, () -> {
|
||||
var packet = new SetScorePacket();
|
||||
packet.setAction(SetScorePacket.Action.SET);
|
||||
packet.setInfos(List.of(new ScoreInfo(17, "0", 13, "aa")));
|
||||
return packet;
|
||||
}, context);
|
||||
});
|
||||
|
||||
// add score with same score value (after)
|
||||
context.translate(
|
||||
setScoreTranslator,
|
||||
new ClientboundSetScorePacket("ga", "objective", 9)
|
||||
);
|
||||
assertNextPacket(() -> {
|
||||
assertNextPacket(context, () -> {
|
||||
var packet = new SetScorePacket();
|
||||
packet.setAction(SetScorePacket.Action.REMOVE);
|
||||
packet.setInfos(List.of(
|
||||
@ -180,8 +180,8 @@ public class OrderAndLimitSidebarScoreboardTests {
|
||||
new ScoreInfo(9, "0", 9, "§0§rg")
|
||||
));
|
||||
return packet;
|
||||
}, context);
|
||||
assertNextPacket(() -> {
|
||||
});
|
||||
assertNextPacket(context, () -> {
|
||||
var packet = new SetScorePacket();
|
||||
packet.setAction(SetScorePacket.Action.SET);
|
||||
packet.setInfos(List.of(
|
||||
@ -189,14 +189,14 @@ public class OrderAndLimitSidebarScoreboardTests {
|
||||
new ScoreInfo(18, "0", 9, "§1§rga")
|
||||
));
|
||||
return packet;
|
||||
}, context);
|
||||
});
|
||||
|
||||
// add another score with same score value (before all)
|
||||
context.translate(
|
||||
setScoreTranslator,
|
||||
new ClientboundSetScorePacket("ag", "objective", 9)
|
||||
);
|
||||
assertNextPacket(() -> {
|
||||
assertNextPacket(context, () -> {
|
||||
var packet = new SetScorePacket();
|
||||
packet.setAction(SetScorePacket.Action.REMOVE);
|
||||
packet.setInfos(List.of(
|
||||
@ -205,8 +205,8 @@ public class OrderAndLimitSidebarScoreboardTests {
|
||||
new ScoreInfo(18, "0", 9, "§2§rga")
|
||||
));
|
||||
return packet;
|
||||
}, context);
|
||||
assertNextPacket(() -> {
|
||||
});
|
||||
assertNextPacket(context, () -> {
|
||||
var packet = new SetScorePacket();
|
||||
packet.setAction(SetScorePacket.Action.SET);
|
||||
packet.setInfos(List.of(
|
||||
@ -215,14 +215,14 @@ public class OrderAndLimitSidebarScoreboardTests {
|
||||
new ScoreInfo(18, "0", 9, "§2§rga")
|
||||
));
|
||||
return packet;
|
||||
}, context);
|
||||
});
|
||||
|
||||
// remove score with same value
|
||||
context.translate(
|
||||
resetScoreTranslator,
|
||||
new ClientboundResetScorePacket("g", "objective")
|
||||
);
|
||||
assertNextPacket(() -> {
|
||||
assertNextPacket(context, () -> {
|
||||
var packet = new SetScorePacket();
|
||||
packet.setAction(SetScorePacket.Action.REMOVE);
|
||||
packet.setInfos(List.of(
|
||||
@ -230,8 +230,8 @@ public class OrderAndLimitSidebarScoreboardTests {
|
||||
new ScoreInfo(18, "0", 9, "§1§rga")
|
||||
));
|
||||
return packet;
|
||||
}, context);
|
||||
assertNextPacket(() -> {
|
||||
});
|
||||
assertNextPacket(context, () -> {
|
||||
var packet = new SetScorePacket();
|
||||
packet.setAction(SetScorePacket.Action.SET);
|
||||
packet.setInfos(List.of(
|
||||
@ -239,14 +239,14 @@ public class OrderAndLimitSidebarScoreboardTests {
|
||||
new ScoreInfo(20, "0", 4, "e")
|
||||
));
|
||||
return packet;
|
||||
}, context);
|
||||
});
|
||||
|
||||
// remove the other score with the same value
|
||||
context.translate(
|
||||
resetScoreTranslator,
|
||||
new ClientboundResetScorePacket("ga", "objective")
|
||||
);
|
||||
assertNextPacket(() -> {
|
||||
assertNextPacket(context, () -> {
|
||||
var packet = new SetScorePacket();
|
||||
packet.setAction(SetScorePacket.Action.REMOVE);
|
||||
packet.setInfos(List.of(
|
||||
@ -254,8 +254,8 @@ public class OrderAndLimitSidebarScoreboardTests {
|
||||
new ScoreInfo(19, "0", 9, "ag")
|
||||
));
|
||||
return packet;
|
||||
}, context);
|
||||
assertNextPacket(() -> {
|
||||
});
|
||||
assertNextPacket(context, () -> {
|
||||
var packet = new SetScorePacket();
|
||||
packet.setAction(SetScorePacket.Action.SET);
|
||||
packet.setInfos(List.of(
|
||||
@ -263,7 +263,7 @@ public class OrderAndLimitSidebarScoreboardTests {
|
||||
new ScoreInfo(21, "0", 3, "c")
|
||||
));
|
||||
return packet;
|
||||
}, context);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@ -327,7 +327,7 @@ public class OrderAndLimitSidebarScoreboardTests {
|
||||
setDisplayObjectiveTranslator,
|
||||
new ClientboundSetDisplayObjectivePacket(ScoreboardPosition.SIDEBAR, "objective")
|
||||
);
|
||||
assertNextPacket(() -> {
|
||||
assertNextPacket(context, () -> {
|
||||
var packet = new SetDisplayObjectivePacket();
|
||||
packet.setObjectiveId("0");
|
||||
packet.setDisplayName("objective");
|
||||
@ -335,8 +335,8 @@ public class OrderAndLimitSidebarScoreboardTests {
|
||||
packet.setDisplaySlot("sidebar");
|
||||
packet.setSortOrder(1);
|
||||
return packet;
|
||||
}, context);
|
||||
assertNextPacket(() -> {
|
||||
});
|
||||
assertNextPacket(context, () -> {
|
||||
var packet = new SetScorePacket();
|
||||
packet.setAction(SetScorePacket.Action.SET);
|
||||
packet.setInfos(List.of(
|
||||
@ -357,7 +357,7 @@ public class OrderAndLimitSidebarScoreboardTests {
|
||||
new ScoreInfo(15, "0", 3, "c")
|
||||
));
|
||||
return packet;
|
||||
}, context);
|
||||
});
|
||||
assertNoNextPacket(context);
|
||||
|
||||
// remove a score
|
||||
@ -365,36 +365,36 @@ public class OrderAndLimitSidebarScoreboardTests {
|
||||
resetScoreTranslator,
|
||||
new ClientboundResetScorePacket("m", "objective")
|
||||
);
|
||||
assertNextPacket(() -> {
|
||||
assertNextPacket(context, () -> {
|
||||
var packet = new SetScorePacket();
|
||||
packet.setAction(SetScorePacket.Action.REMOVE);
|
||||
packet.setInfos(List.of(new ScoreInfo(5, "0", 13, "m")));
|
||||
return packet;
|
||||
}, context);
|
||||
assertNextPacket(() -> {
|
||||
});
|
||||
assertNextPacket(context, () -> {
|
||||
var packet = new SetScorePacket();
|
||||
packet.setAction(SetScorePacket.Action.SET);
|
||||
packet.setInfos(List.of(new ScoreInfo(16, "0", 2, "b")));
|
||||
return packet;
|
||||
}, context);
|
||||
});
|
||||
|
||||
// add a score
|
||||
context.translate(
|
||||
setScoreTranslator,
|
||||
new ClientboundSetScorePacket("aa", "objective", 13)
|
||||
);
|
||||
assertNextPacket(() -> {
|
||||
assertNextPacket(context, () -> {
|
||||
var packet = new SetScorePacket();
|
||||
packet.setAction(SetScorePacket.Action.REMOVE);
|
||||
packet.setInfos(List.of(new ScoreInfo(16, "0", 2, "b")));
|
||||
return packet;
|
||||
}, context);
|
||||
assertNextPacket(() -> {
|
||||
});
|
||||
assertNextPacket(context, () -> {
|
||||
var packet = new SetScorePacket();
|
||||
packet.setAction(SetScorePacket.Action.SET);
|
||||
packet.setInfos(List.of(new ScoreInfo(17, "0", 13, "aa")));
|
||||
return packet;
|
||||
}, context);
|
||||
});
|
||||
|
||||
// add some teams for the upcoming score adds
|
||||
context.translate(
|
||||
@ -435,7 +435,7 @@ public class OrderAndLimitSidebarScoreboardTests {
|
||||
setScoreTranslator,
|
||||
new ClientboundSetScorePacket("oa", "objective", 11)
|
||||
);
|
||||
assertNextPacket(() -> {
|
||||
assertNextPacket(context, () -> {
|
||||
var packet = new SetScorePacket();
|
||||
packet.setAction(SetScorePacket.Action.REMOVE);
|
||||
packet.setInfos(List.of(
|
||||
@ -443,8 +443,8 @@ public class OrderAndLimitSidebarScoreboardTests {
|
||||
new ScoreInfo(7, "0", 11, "§0§r§4prefix§r§4o§r§4suffix")
|
||||
));
|
||||
return packet;
|
||||
}, context);
|
||||
assertNextPacket(() -> {
|
||||
});
|
||||
assertNextPacket(context, () -> {
|
||||
var packet = new SetScorePacket();
|
||||
packet.setAction(SetScorePacket.Action.SET);
|
||||
packet.setInfos(List.of(
|
||||
@ -452,7 +452,7 @@ public class OrderAndLimitSidebarScoreboardTests {
|
||||
new ScoreInfo(18, "0", 11, "§1§r§3prefix§r§3oa§r§3suffix")
|
||||
));
|
||||
return packet;
|
||||
}, context);
|
||||
});
|
||||
|
||||
// add a score that on Java should be before 'o', but would be after on Bedrock without manual order
|
||||
// due to the team color
|
||||
@ -460,7 +460,7 @@ public class OrderAndLimitSidebarScoreboardTests {
|
||||
setScoreTranslator,
|
||||
new ClientboundSetScorePacket("ao", "objective", 11)
|
||||
);
|
||||
assertNextPacket(() -> {
|
||||
assertNextPacket(context, () -> {
|
||||
var packet = new SetScorePacket();
|
||||
packet.setAction(SetScorePacket.Action.REMOVE);
|
||||
packet.setInfos(List.of(
|
||||
@ -469,8 +469,8 @@ public class OrderAndLimitSidebarScoreboardTests {
|
||||
new ScoreInfo(18, "0", 11, "§2§r§3prefix§r§3oa§r§3suffix")
|
||||
));
|
||||
return packet;
|
||||
}, context);
|
||||
assertNextPacket(() -> {
|
||||
});
|
||||
assertNextPacket(context, () -> {
|
||||
var packet = new SetScorePacket();
|
||||
packet.setAction(SetScorePacket.Action.SET);
|
||||
packet.setInfos(List.of(
|
||||
@ -479,14 +479,14 @@ public class OrderAndLimitSidebarScoreboardTests {
|
||||
new ScoreInfo(18, "0", 11, "§2§r§3prefix§r§3oa§r§3suffix")
|
||||
));
|
||||
return packet;
|
||||
}, context);
|
||||
});
|
||||
|
||||
// remove original 'o' score
|
||||
context.translate(
|
||||
resetScoreTranslator,
|
||||
new ClientboundResetScorePacket("o", "objective")
|
||||
);
|
||||
assertNextPacket(() -> {
|
||||
assertNextPacket(context, () -> {
|
||||
var packet = new SetScorePacket();
|
||||
packet.setAction(SetScorePacket.Action.REMOVE);
|
||||
packet.setInfos(List.of(
|
||||
@ -494,8 +494,8 @@ public class OrderAndLimitSidebarScoreboardTests {
|
||||
new ScoreInfo(18, "0", 11, "§1§r§3prefix§r§3oa§r§3suffix")
|
||||
));
|
||||
return packet;
|
||||
}, context);
|
||||
assertNextPacket(() -> {
|
||||
});
|
||||
assertNextPacket(context, () -> {
|
||||
var packet = new SetScorePacket();
|
||||
packet.setAction(SetScorePacket.Action.SET);
|
||||
packet.setInfos(List.of(
|
||||
@ -503,14 +503,14 @@ public class OrderAndLimitSidebarScoreboardTests {
|
||||
new ScoreInfo(20, "0", 4, "e")
|
||||
));
|
||||
return packet;
|
||||
}, context);
|
||||
});
|
||||
|
||||
// remove the other score with the same value as 'o'
|
||||
context.translate(
|
||||
resetScoreTranslator,
|
||||
new ClientboundResetScorePacket("oa", "objective")
|
||||
);
|
||||
assertNextPacket(() -> {
|
||||
assertNextPacket(context, () -> {
|
||||
var packet = new SetScorePacket();
|
||||
packet.setAction(SetScorePacket.Action.REMOVE);
|
||||
packet.setInfos(List.of(
|
||||
@ -518,8 +518,8 @@ public class OrderAndLimitSidebarScoreboardTests {
|
||||
new ScoreInfo(19, "0", 11, "§5prefix§r§5ao§r§5suffix")
|
||||
));
|
||||
return packet;
|
||||
}, context);
|
||||
assertNextPacket(() -> {
|
||||
});
|
||||
assertNextPacket(context, () -> {
|
||||
var packet = new SetScorePacket();
|
||||
packet.setAction(SetScorePacket.Action.SET);
|
||||
packet.setInfos(List.of(
|
||||
@ -527,7 +527,7 @@ public class OrderAndLimitSidebarScoreboardTests {
|
||||
new ScoreInfo(21, "0", 3, "c")
|
||||
));
|
||||
return packet;
|
||||
}, context);
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -69,7 +69,7 @@ public class VanillaSidebarScoreboardTests {
|
||||
setDisplayObjectiveTranslator,
|
||||
new ClientboundSetDisplayObjectivePacket(ScoreboardPosition.SIDEBAR, "objective")
|
||||
);
|
||||
assertNextPacket(() -> {
|
||||
assertNextPacket(context, () -> {
|
||||
var packet = new SetDisplayObjectivePacket();
|
||||
packet.setObjectiveId("0");
|
||||
packet.setDisplayName("objective");
|
||||
@ -77,16 +77,16 @@ public class VanillaSidebarScoreboardTests {
|
||||
packet.setDisplaySlot("sidebar");
|
||||
packet.setSortOrder(1);
|
||||
return packet;
|
||||
}, context);
|
||||
});
|
||||
assertNoNextPacket(context);
|
||||
|
||||
context.translate(setScoreTranslator, new ClientboundSetScorePacket("owner", "objective", 1));
|
||||
assertNextPacket(() -> {
|
||||
assertNextPacket(context, () -> {
|
||||
var packet = new SetScorePacket();
|
||||
packet.setAction(SetScorePacket.Action.SET);
|
||||
packet.setInfos(List.of(new ScoreInfo(1, "0", 1, "owner")));
|
||||
return packet;
|
||||
}, context);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@ -114,7 +114,7 @@ public class VanillaSidebarScoreboardTests {
|
||||
setDisplayObjectiveTranslator,
|
||||
new ClientboundSetDisplayObjectivePacket(ScoreboardPosition.SIDEBAR, "objective")
|
||||
);
|
||||
assertNextPacket(() -> {
|
||||
assertNextPacket(context, () -> {
|
||||
var packet = new SetDisplayObjectivePacket();
|
||||
packet.setObjectiveId("0");
|
||||
packet.setDisplayName("objective");
|
||||
@ -122,22 +122,22 @@ public class VanillaSidebarScoreboardTests {
|
||||
packet.setDisplaySlot("sidebar");
|
||||
packet.setSortOrder(1);
|
||||
return packet;
|
||||
}, context);
|
||||
assertNextPacket(() -> {
|
||||
});
|
||||
assertNextPacket(context, () -> {
|
||||
var packet = new SetScorePacket();
|
||||
packet.setAction(SetScorePacket.Action.SET);
|
||||
packet.setInfos(List.of(new ScoreInfo(1, "0", 1, "owner")));
|
||||
return packet;
|
||||
}, context);
|
||||
});
|
||||
assertNoNextPacket(context);
|
||||
|
||||
context.translate(setScoreTranslator, new ClientboundSetScorePacket("owner", "objective", 2));
|
||||
assertNextPacket(() -> {
|
||||
assertNextPacket(context, () -> {
|
||||
var packet = new SetScorePacket();
|
||||
packet.setAction(SetScorePacket.Action.SET);
|
||||
packet.setInfos(List.of(new ScoreInfo(1, "0", 2, "owner")));
|
||||
return packet;
|
||||
}, context);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@ -166,7 +166,7 @@ public class VanillaSidebarScoreboardTests {
|
||||
setDisplayObjectiveTranslator,
|
||||
new ClientboundSetDisplayObjectivePacket(ScoreboardPosition.SIDEBAR, "objective")
|
||||
);
|
||||
assertNextPacket(() -> {
|
||||
assertNextPacket(context, () -> {
|
||||
var packet = new SetDisplayObjectivePacket();
|
||||
packet.setObjectiveId("0");
|
||||
packet.setDisplayName("objective");
|
||||
@ -174,31 +174,31 @@ public class VanillaSidebarScoreboardTests {
|
||||
packet.setDisplaySlot("sidebar");
|
||||
packet.setSortOrder(1);
|
||||
return packet;
|
||||
}, context);
|
||||
assertNextPacket(() -> {
|
||||
});
|
||||
assertNextPacket(context, () -> {
|
||||
var packet = new SetScorePacket();
|
||||
packet.setAction(SetScorePacket.Action.SET);
|
||||
packet.setInfos(List.of(new ScoreInfo(1, "0", 1, "owner")));
|
||||
return packet;
|
||||
}, context);
|
||||
});
|
||||
assertNoNextPacket(context);
|
||||
|
||||
context.translate(
|
||||
setScoreTranslator,
|
||||
new ClientboundSetScorePacket("owner", "objective", 1).withDisplay(Component.text("hi"))
|
||||
);
|
||||
assertNextPacket(() -> {
|
||||
assertNextPacket(context, () -> {
|
||||
var packet = new SetScorePacket();
|
||||
packet.setAction(SetScorePacket.Action.REMOVE);
|
||||
packet.setInfos(List.of(new ScoreInfo(1, "0", 1, "hi")));
|
||||
return packet;
|
||||
}, context);
|
||||
assertNextPacket(() -> {
|
||||
});
|
||||
assertNextPacket(context, () -> {
|
||||
var packet = new SetScorePacket();
|
||||
packet.setAction(SetScorePacket.Action.SET);
|
||||
packet.setInfos(List.of(new ScoreInfo(1, "0", 1, "hi")));
|
||||
return packet;
|
||||
}, context);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@ -227,7 +227,7 @@ public class VanillaSidebarScoreboardTests {
|
||||
setDisplayObjectiveTranslator,
|
||||
new ClientboundSetDisplayObjectivePacket(ScoreboardPosition.SIDEBAR, "objective")
|
||||
);
|
||||
assertNextPacket(() -> {
|
||||
assertNextPacket(context, () -> {
|
||||
var packet = new SetDisplayObjectivePacket();
|
||||
packet.setObjectiveId("0");
|
||||
packet.setDisplayName("objective");
|
||||
@ -235,31 +235,31 @@ public class VanillaSidebarScoreboardTests {
|
||||
packet.setDisplaySlot("sidebar");
|
||||
packet.setSortOrder(1);
|
||||
return packet;
|
||||
}, context);
|
||||
assertNextPacket(() -> {
|
||||
});
|
||||
assertNextPacket(context, () -> {
|
||||
var packet = new SetScorePacket();
|
||||
packet.setAction(SetScorePacket.Action.SET);
|
||||
packet.setInfos(List.of(new ScoreInfo(1, "0", 1, "owner")));
|
||||
return packet;
|
||||
}, context);
|
||||
});
|
||||
assertNoNextPacket(context);
|
||||
|
||||
context.translate(
|
||||
setScoreTranslator,
|
||||
new ClientboundSetScorePacket("owner", "objective", 2).withDisplay(Component.text("hi"))
|
||||
);
|
||||
assertNextPacket(() -> {
|
||||
assertNextPacket(context, () -> {
|
||||
var packet = new SetScorePacket();
|
||||
packet.setAction(SetScorePacket.Action.REMOVE);
|
||||
packet.setInfos(List.of(new ScoreInfo(1, "0", 2, "hi")));
|
||||
return packet;
|
||||
}, context);
|
||||
assertNextPacket(() -> {
|
||||
});
|
||||
assertNextPacket(context, () -> {
|
||||
var packet = new SetScorePacket();
|
||||
packet.setAction(SetScorePacket.Action.SET);
|
||||
packet.setInfos(List.of(new ScoreInfo(1, "0", 2, "hi")));
|
||||
return packet;
|
||||
}, context);
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -26,6 +26,7 @@
|
||||
package org.geysermc.geyser.scoreboard.network.util;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Supplier;
|
||||
import org.cloudburstmc.protocol.bedrock.packet.BedrockPacket;
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
@ -38,7 +39,7 @@ public class AssertUtils {
|
||||
Assertions.assertEquals(expected.get(), actual);
|
||||
}
|
||||
|
||||
public static void assertNextPacket(Supplier<BedrockPacket> expected, GeyserMockContext context) {
|
||||
public static void assertNextPacket(GeyserMockContext context, Supplier<BedrockPacket> expected) {
|
||||
assertContextEquals(expected, context.nextPacket());
|
||||
}
|
||||
|
||||
@ -50,6 +51,16 @@ public class AssertUtils {
|
||||
Assertions.assertEquals(type, actual.getClass());
|
||||
}
|
||||
|
||||
public static <T extends BedrockPacket> void assertNextPacketMatch(GeyserMockContext context, Class<T> type, Consumer<T> matcher) {
|
||||
var actual = context.nextPacket();
|
||||
if (actual == null) {
|
||||
Assertions.fail("Expected another packet!");
|
||||
}
|
||||
Assertions.assertEquals(type, actual.getClass(), "Expected packet to be an instance of " + type);
|
||||
//noinspection unchecked verified in the line above me
|
||||
matcher.accept((T) actual);
|
||||
}
|
||||
|
||||
public static void assertNoNextPacket(GeyserMockContext context) {
|
||||
Assertions.assertEquals(
|
||||
Collections.emptyList(),
|
||||
|
@ -35,16 +35,15 @@ import java.util.function.Consumer;
|
||||
import org.cloudburstmc.protocol.bedrock.packet.BedrockPacket;
|
||||
import org.geysermc.geyser.GeyserImpl;
|
||||
import org.geysermc.geyser.configuration.GeyserConfiguration;
|
||||
import org.geysermc.geyser.registry.Registries;
|
||||
import org.geysermc.geyser.session.GeyserSession;
|
||||
import org.geysermc.geyser.translator.protocol.PacketTranslator;
|
||||
import org.mockito.MockedStatic;
|
||||
import org.mockito.Mockito;
|
||||
|
||||
public class GeyserMockContext {
|
||||
private final List<Object> mocksAndSpies = new ArrayList<>();
|
||||
private final List<Object> storedObjects = new ArrayList<>();
|
||||
private final List<BedrockPacket> packets = Collections.synchronizedList(new ArrayList<>());
|
||||
private MockedStatic<GeyserImpl> geyserImplMock;
|
||||
|
||||
public static void mockContext(Consumer<GeyserMockContext> geyserContext) {
|
||||
var context = new GeyserMockContext();
|
||||
@ -59,9 +58,9 @@ public class GeyserMockContext {
|
||||
var logger = context.storeObject(new EmptyGeyserLogger());
|
||||
when(geyserImpl.getLogger()).thenReturn(logger);
|
||||
|
||||
try (var mocked = mockStatic(GeyserImpl.class)) {
|
||||
mocked.when(GeyserImpl::getInstance).thenReturn(geyserImpl);
|
||||
context.geyserImplMock = mocked;
|
||||
try (var geyserImplMock = mockStatic(GeyserImpl.class)) {
|
||||
geyserImplMock.when(GeyserImpl::getInstance).thenReturn(geyserImpl);
|
||||
|
||||
geyserContext.accept(context);
|
||||
}
|
||||
}
|
||||
@ -136,8 +135,4 @@ public class GeyserMockContext {
|
||||
public <T> void translate(PacketTranslator<T> translator, T packet) {
|
||||
translator.translate(session(), packet);
|
||||
}
|
||||
|
||||
public MockedStatic<GeyserImpl> geyserImplMock() {
|
||||
return geyserImplMock;
|
||||
}
|
||||
}
|
||||
|
@ -25,6 +25,7 @@
|
||||
|
||||
package org.geysermc.geyser.scoreboard.network.util;
|
||||
|
||||
import static org.geysermc.geyser.scoreboard.network.util.AssertUtils.assertNextPacketType;
|
||||
import static org.geysermc.geyser.scoreboard.network.util.AssertUtils.assertNoNextPacket;
|
||||
import static org.geysermc.geyser.scoreboard.network.util.GeyserMockContext.mockContext;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
@ -34,6 +35,8 @@ import static org.mockito.Mockito.when;
|
||||
|
||||
import java.util.UUID;
|
||||
import java.util.function.Consumer;
|
||||
import org.cloudburstmc.math.vector.Vector3f;
|
||||
import org.cloudburstmc.protocol.bedrock.packet.AddPlayerPacket;
|
||||
import org.cloudburstmc.protocol.bedrock.packet.BedrockPacket;
|
||||
import org.geysermc.geyser.GeyserImpl;
|
||||
import org.geysermc.geyser.entity.type.player.PlayerEntity;
|
||||
@ -82,15 +85,20 @@ public class GeyserMockContextScoreboard {
|
||||
when(worldCache.increaseAndGetScoreboardPacketsPerSecond()).thenReturn(0);
|
||||
}
|
||||
|
||||
public static PlayerEntity mockAndAddPlayerEntity(GeyserMockContext context, String username, long geyserId) {
|
||||
var playerEntity = spy(new PlayerEntity(context.session(), geyserId, UUID.randomUUID(), username));
|
||||
// fake the player being spawned
|
||||
when(playerEntity.isValid()).thenReturn(true);
|
||||
public static PlayerEntity spawnPlayerSilently(GeyserMockContext context, String username, long geyserId) {
|
||||
var player = spawnPlayer(context, username, geyserId);
|
||||
assertNextPacketType(context, AddPlayerPacket.class);
|
||||
return player;
|
||||
}
|
||||
|
||||
public static PlayerEntity spawnPlayer(GeyserMockContext context, String username, long geyserId) {
|
||||
var playerEntity = spy(new PlayerEntity(context.session(), (int) geyserId, geyserId, UUID.randomUUID(), Vector3f.ZERO, Vector3f.ZERO, 0, 0, 0, username, null));
|
||||
|
||||
var entityCache = context.mockOrSpy(EntityCache.class);
|
||||
entityCache.addPlayerEntity(playerEntity);
|
||||
// called when the player spawns
|
||||
entityCache.cacheEntity(playerEntity);
|
||||
entityCache.spawnEntity(playerEntity);
|
||||
|
||||
return playerEntity;
|
||||
}
|
||||
}
|
||||
|
Laden…
In neuem Issue referenzieren
Einen Benutzer sperren