mirror of
https://github.com/GeyserMC/Geyser.git
synced 2025-12-27 10:49:10 +00:00
Continue splitting bedrock entities from java types
This commit is contained in:
@@ -30,6 +30,7 @@ import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import lombok.experimental.Accessors;
|
||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
import org.geysermc.geyser.api.entity.GeyserEntityDefinition;
|
||||
import org.geysermc.geyser.api.entity.property.GeyserEntityProperty;
|
||||
import org.geysermc.geyser.api.util.Identifier;
|
||||
@@ -102,7 +103,7 @@ public class BedrockEntityDefinition implements GeyserEntityDefinition {
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder properties(GeyserEntityProperties.Builder propertiesBuilder) {
|
||||
public Builder properties(GeyserEntityProperties.@Nullable Builder propertiesBuilder) {
|
||||
this.propertiesBuilder = propertiesBuilder;
|
||||
return this;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* Copyright (c) 2025 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.entity;
|
||||
|
||||
public class BedrockEntityDefinitions {
|
||||
|
||||
// TODO re-usable Bedrock entity definitions??????????
|
||||
// Or rather... looking up otherwise??
|
||||
|
||||
}
|
||||
@@ -53,12 +53,6 @@ public record GeyserEntityType(Identifier identifier, int javaId) implements Jav
|
||||
private static final Int2ObjectMap<GeyserEntityType> CUSTOM = new Int2ObjectOpenHashMap<>();
|
||||
private static final Object2ObjectMap<Identifier, GeyserEntityType> CUSTOM_BY_IDENTIFIER = new Object2ObjectOpenHashMap<>();
|
||||
|
||||
public GeyserEntityType {
|
||||
if (!VANILLA.containsValue(this) && !CUSTOM.containsKey(javaId)) {
|
||||
throw new IllegalCallerException("Public constructor of GeyserEntityType should not be used; use one of the static factory methods instead");
|
||||
}
|
||||
}
|
||||
|
||||
private GeyserEntityType(BuiltinEntityType builtin) {
|
||||
this(IdentifierImpl.of(builtin.name().toLowerCase(Locale.ROOT)), builtin.id());
|
||||
}
|
||||
|
||||
@@ -168,6 +168,7 @@ import org.geysermc.geyser.entity.type.living.monster.raid.VindicatorEntity;
|
||||
import org.geysermc.geyser.entity.type.player.AvatarEntity;
|
||||
import org.geysermc.geyser.entity.type.player.MannequinEntity;
|
||||
import org.geysermc.geyser.entity.type.player.PlayerEntity;
|
||||
import org.geysermc.geyser.impl.IdentifierImpl;
|
||||
import org.geysermc.geyser.registry.Registries;
|
||||
import org.geysermc.geyser.translator.text.MessageTranslator;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.MetadataTypes;
|
||||
@@ -335,10 +336,6 @@ public final class VanillaEntities {
|
||||
* Is not sent over the network
|
||||
*/
|
||||
public static final VanillaEntityType<EnderDragonPartEntity> ENDER_DRAGON_PART;
|
||||
/**
|
||||
* Special Bedrock type
|
||||
*/
|
||||
public static final VanillaEntityType<WitherSkullEntity> WITHER_SKULL_DANGEROUS;
|
||||
|
||||
public static final float PLAYER_ENTITY_OFFSET;
|
||||
|
||||
@@ -469,7 +466,7 @@ public final class VanillaEntities {
|
||||
INTERACTION = VanillaEntityType.inherited(InteractionEntity::new, entityBase)
|
||||
.type(BuiltinEntityType.INTERACTION)
|
||||
.heightAndWidth(1.0f) // default size until server specifies otherwise
|
||||
.bedrockIdentifier("minecraft:armor_stand")
|
||||
.bedrockDefinition(ARMOR_STAND.defaultBedrockDefinition())
|
||||
.addTranslator(MetadataTypes.FLOAT, InteractionEntity::setWidth)
|
||||
.addTranslator(MetadataTypes.FLOAT, InteractionEntity::setHeight)
|
||||
.addTranslator(MetadataTypes.BOOLEAN, InteractionEntity::setResponse)
|
||||
@@ -613,8 +610,19 @@ public final class VanillaEntities {
|
||||
.heightAndWidth(0.3125f)
|
||||
.addTranslator(MetadataTypes.BOOLEAN, WitherSkullEntity::setDangerous)
|
||||
.build();
|
||||
WITHER_SKULL_DANGEROUS = VanillaEntityType.inherited(WITHER_SKULL.factory(), WITHER_SKULL)
|
||||
.build(false);
|
||||
|
||||
// Bedrock exclusive entity
|
||||
IdentifierImpl dangerousSkull = IdentifierImpl.of("wither_skull_dangerous");
|
||||
BedrockEntityDefinition bedrockDefinition = BedrockEntityDefinition.builder()
|
||||
.height(WITHER_SKULL.height)
|
||||
.width(WITHER_SKULL.width)
|
||||
.offset(WITHER_SKULL.offset)
|
||||
.identifier(dangerousSkull)
|
||||
.build();
|
||||
Registries.BEDROCK_ENTITY_DEFINITIONS.get().put(dangerousSkull, bedrockDefinition);
|
||||
|
||||
// WITHER_SKULL_DANGEROUS = VanillaEntityType.inherited(WITHER_SKULL.factory(), WITHER_SKULL)
|
||||
// .build(false);
|
||||
}
|
||||
|
||||
// Boats
|
||||
@@ -1246,7 +1254,7 @@ public final class VanillaEntities {
|
||||
|
||||
// As of 1.18 these don't track entity data at all
|
||||
ENDER_DRAGON_PART = VanillaEntityType.<EnderDragonPartEntity>builder(null)
|
||||
.bedrockIdentifier("minecraft:armor_stand") // Emulated
|
||||
.bedrockDefinition(ARMOR_STAND.defaultBedrockDefinition()) // Emulated
|
||||
.build(false); // Never sent over the network
|
||||
|
||||
PLAYER_ENTITY_OFFSET = PLAYER.defaultBedrockDefinition().offset();
|
||||
|
||||
@@ -70,6 +70,7 @@ public class VanillaEntityType<T extends Entity> extends EntityTypeDefinition<T>
|
||||
|
||||
public static class Builder<T extends Entity> extends EntityTypeDefinition.Builder<T> {
|
||||
protected GeyserEntityType type;
|
||||
protected BedrockEntityDefinition bedrockDefinition;
|
||||
|
||||
protected Builder(EntityFactory<T> factory) {
|
||||
super(factory);
|
||||
@@ -128,6 +129,11 @@ public class VanillaEntityType<T extends Entity> extends EntityTypeDefinition<T>
|
||||
return (Builder<T>) super.addTranslator(translator);
|
||||
}
|
||||
|
||||
public Builder<T> bedrockDefinition(BedrockEntityDefinition bedrockDefinition) {
|
||||
this.bedrockDefinition = bedrockDefinition;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public VanillaEntityType<T> build() {
|
||||
return build(true);
|
||||
@@ -136,8 +142,17 @@ public class VanillaEntityType<T extends Entity> extends EntityTypeDefinition<T>
|
||||
private void validateTypeAndIdentifier() {
|
||||
if (type == null) {
|
||||
throw new IllegalStateException("Missing entity type!");
|
||||
} else if (bedrockIdentifier == null) {
|
||||
bedrockIdentifier = type.identifier().toString();
|
||||
}
|
||||
|
||||
if (bedrockDefinition == null) {
|
||||
bedrockDefinition = BedrockEntityDefinition.builder()
|
||||
.height(height)
|
||||
.width(width)
|
||||
.properties(propertiesBuilder)
|
||||
.offset(offset)
|
||||
.identifier(Identifier.of(bedrockIdentifier))
|
||||
.build();
|
||||
Registries.BEDROCK_ENTITY_DEFINITIONS.get().put(Identifier.of(bedrockIdentifier), bedrockDefinition);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -148,16 +163,6 @@ public class VanillaEntityType<T extends Entity> extends EntityTypeDefinition<T>
|
||||
public VanillaEntityType<T> build(boolean register) {
|
||||
validateTypeAndIdentifier();
|
||||
|
||||
BedrockEntityDefinition bedrockDefinition = BedrockEntityDefinition.builder()
|
||||
.height(height)
|
||||
.width(width)
|
||||
.properties(propertiesBuilder)
|
||||
.offset(offset)
|
||||
.identifier(Identifier.of(bedrockIdentifier))
|
||||
.build();
|
||||
// TODO TEST!!!
|
||||
Registries.BEDROCK_ENTITY_DEFINITIONS.get().put(Identifier.of(bedrockIdentifier), bedrockDefinition);
|
||||
|
||||
VanillaEntityType<T> definition = new VanillaEntityType<>(factory, type, bedrockDefinition, translators);
|
||||
if (register && definition.entityType() != null) {
|
||||
Registries.ENTITY_DEFINITIONS.get().putIfAbsent(definition.entityType(), definition);
|
||||
|
||||
@@ -31,7 +31,6 @@ import it.unimi.dsi.fastutil.objects.ObjectArrayList;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.ToString;
|
||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
import org.cloudburstmc.nbt.NbtMap;
|
||||
import org.cloudburstmc.nbt.NbtMapBuilder;
|
||||
import org.cloudburstmc.nbt.NbtType;
|
||||
@@ -106,7 +105,7 @@ public class GeyserEntityProperties {
|
||||
}
|
||||
|
||||
public static class Builder {
|
||||
private GeyserEntityProperties properties;
|
||||
private GeyserEntityProperties properties = new GeyserEntityProperties();
|
||||
private final String identifier;
|
||||
|
||||
public Builder(String identifier) {
|
||||
@@ -122,7 +121,7 @@ public class GeyserEntityProperties {
|
||||
return this;
|
||||
}
|
||||
|
||||
public @Nullable GeyserEntityProperties build() {
|
||||
public @NonNull GeyserEntityProperties build() {
|
||||
return properties;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,7 +38,8 @@ public interface PropertyType<Type, NetworkRepresentation extends EntityProperty
|
||||
|
||||
NetworkRepresentation createValue(int index, @Nullable Type value);
|
||||
|
||||
default void apply(GeyserEntityPropertyManager manager, Type value) {
|
||||
default void apply(@Nullable GeyserEntityPropertyManager manager, Type value) {
|
||||
if (manager == null) return;
|
||||
manager.addProperty(this, value);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -87,7 +87,7 @@ public class Entity implements GeyserEntity {
|
||||
|
||||
protected final GeyserSession session;
|
||||
@Accessors(fluent = true)
|
||||
protected final BedrockEntityDefinition definition;
|
||||
protected BedrockEntityDefinition definition;
|
||||
protected EntityTypeDefinition<?> javaDefinition;
|
||||
|
||||
protected int entityId;
|
||||
@@ -152,7 +152,7 @@ public class Entity implements GeyserEntity {
|
||||
@Setter(AccessLevel.PROTECTED) // For players
|
||||
private boolean flagsDirty = false;
|
||||
|
||||
protected final GeyserEntityPropertyManager propertyManager;
|
||||
protected final @Nullable GeyserEntityPropertyManager propertyManager;
|
||||
|
||||
public Entity(GeyserSession session, int entityId, long geyserId, UUID uuid, EntityTypeDefinition<?> definition, BedrockEntityDefinition bedrockDefinition,
|
||||
Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
|
||||
@@ -171,7 +171,7 @@ public class Entity implements GeyserEntity {
|
||||
|
||||
this.valid = false;
|
||||
// TODO null or empty check
|
||||
this.propertyManager = bedrockDefinition.registeredProperties() == null ? null : new GeyserEntityPropertyManager(bedrockDefinition.registeredProperties());
|
||||
this.propertyManager = bedrockDefinition.registeredProperties().isEmpty() ? null : new GeyserEntityPropertyManager(bedrockDefinition.registeredProperties());
|
||||
|
||||
setPosition(position);
|
||||
setAirSupply(getMaxAir());
|
||||
|
||||
@@ -28,7 +28,8 @@ package org.geysermc.geyser.entity.type;
|
||||
import org.cloudburstmc.math.vector.Vector3f;
|
||||
import org.geysermc.geyser.entity.BedrockEntityDefinition;
|
||||
import org.geysermc.geyser.entity.EntityTypeDefinition;
|
||||
import org.geysermc.geyser.entity.VanillaEntities;
|
||||
import org.geysermc.geyser.impl.IdentifierImpl;
|
||||
import org.geysermc.geyser.registry.Registries;
|
||||
import org.geysermc.geyser.session.GeyserSession;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.BooleanEntityMetadata;
|
||||
|
||||
@@ -36,6 +37,7 @@ import java.util.UUID;
|
||||
|
||||
public class WitherSkullEntity extends FireballEntity {
|
||||
private boolean isCharged;
|
||||
private static final IdentifierImpl DANGEROUS_SKULL = IdentifierImpl.of("wither_skull_dangerous");
|
||||
|
||||
public WitherSkullEntity(GeyserSession session, int entityId, long geyserId, UUID uuid, EntityTypeDefinition<?> definition, BedrockEntityDefinition bedrockDefinition, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw) {
|
||||
super(session, entityId, geyserId, uuid, definition, bedrockDefinition, position, motion, yaw, pitch, headYaw);
|
||||
@@ -48,7 +50,7 @@ public class WitherSkullEntity extends FireballEntity {
|
||||
if (newDangerous != isCharged) {
|
||||
isCharged = newDangerous;
|
||||
// Is an entirely new entity in Bedrock but just a metadata type in Java
|
||||
javaDefinition = isCharged ? VanillaEntities.WITHER_SKULL_DANGEROUS : VanillaEntities.WITHER_SKULL;
|
||||
definition = isCharged ? Registries.BEDROCK_ENTITY_DEFINITIONS.get(DANGEROUS_SKULL) : javaDefinition.defaultBedrockDefinition();
|
||||
despawnEntity();
|
||||
spawnEntity();
|
||||
}
|
||||
|
||||
@@ -50,7 +50,7 @@ public class JavaSetEquipmentTranslator extends PacketTranslator<ClientboundSetE
|
||||
|
||||
if (!(entity instanceof LivingEntity livingEntity)) {
|
||||
session.getGeyser().getLogger().debug("Attempted to add armor to a non-living entity (" +
|
||||
entity.getDefinition().identifier() + ").");
|
||||
entity.definition().identifier() + ").");
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user