|
| 1 | +/* |
| 2 | + * Copyright (c) 2025 GeyserMC. http://geysermc.org |
| 3 | + * |
| 4 | + * Permission is hereby granted, free of charge, to any person obtaining a copy |
| 5 | + * of this software and associated documentation files (the "Software"), to deal |
| 6 | + * in the Software without restriction, including without limitation the rights |
| 7 | + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
| 8 | + * copies of the Software, and to permit persons to whom the Software is |
| 9 | + * furnished to do so, subject to the following conditions: |
| 10 | + * |
| 11 | + * The above copyright notice and this permission notice shall be included in |
| 12 | + * all copies or substantial portions of the Software. |
| 13 | + * |
| 14 | + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
| 15 | + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
| 16 | + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
| 17 | + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
| 18 | + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
| 19 | + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN |
| 20 | + * THE SOFTWARE. |
| 21 | + * |
| 22 | + * @author GeyserMC |
| 23 | + * @link https://github.com/GeyserMC/Geyser |
| 24 | + */ |
| 25 | + |
| 26 | +package org.geysermc.geyser.entity; |
| 27 | + |
| 28 | +import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes; |
| 29 | +import org.geysermc.geyser.entity.type.BoatEntity; |
| 30 | +import org.geysermc.geyser.entity.type.ChestBoatEntity; |
| 31 | +import org.geysermc.geyser.entity.type.DisplayBaseEntity; |
| 32 | +import org.geysermc.geyser.entity.type.Entity; |
| 33 | +import org.geysermc.geyser.entity.type.FireballEntity; |
| 34 | +import org.geysermc.geyser.entity.type.HangingEntity; |
| 35 | +import org.geysermc.geyser.entity.type.LivingEntity; |
| 36 | +import org.geysermc.geyser.entity.type.ThrowableItemEntity; |
| 37 | +import org.geysermc.geyser.entity.type.living.AbstractFishEntity; |
| 38 | +import org.geysermc.geyser.entity.type.living.AgeableEntity; |
| 39 | +import org.geysermc.geyser.entity.type.living.MobEntity; |
| 40 | +import org.geysermc.geyser.entity.type.living.animal.horse.AbstractHorseEntity; |
| 41 | +import org.geysermc.geyser.entity.type.living.animal.tameable.TameableEntity; |
| 42 | +import org.geysermc.geyser.entity.type.living.monster.BasePiglinEntity; |
| 43 | +import org.geysermc.geyser.entity.type.living.monster.raid.RaidParticipantEntity; |
| 44 | +import org.geysermc.geyser.entity.type.living.monster.raid.SpellcasterIllagerEntity; |
| 45 | +import org.geysermc.geyser.entity.type.player.AvatarEntity; |
| 46 | +import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.MetadataTypes; |
| 47 | +import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.BooleanEntityMetadata; |
| 48 | +import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.FloatEntityMetadata; |
| 49 | + |
| 50 | +public final class EntityDefinitionBases { |
| 51 | + public static final EntityDefinitionBase<Entity> ENTITY; |
| 52 | + public static final EntityDefinitionBase<DisplayBaseEntity> DISPLAY; |
| 53 | + public static final EntityDefinitionBase<FireballEntity> FIREBALL; |
| 54 | + public static final EntityDefinitionBase<ThrowableItemEntity> THROWABLE; |
| 55 | + public static final EntityDefinitionBase<HangingEntity> HANGING; |
| 56 | + public static final EntityDefinitionBase<BoatEntity> BOAT; |
| 57 | + public static final EntityDefinitionBase<ChestBoatEntity> CHEST_BOAT; |
| 58 | + public static final EntityDefinitionBase<LivingEntity> LIVING_ENTITY; |
| 59 | + public static final EntityDefinitionBase<AvatarEntity> AVATAR; |
| 60 | + public static final EntityDefinitionBase<MobEntity> MOB; |
| 61 | + public static final EntityDefinitionBase<AbstractFishEntity> FISH; |
| 62 | + public static final EntityDefinitionBase<BasePiglinEntity> PIGLIN; |
| 63 | + public static final EntityDefinitionBase<RaidParticipantEntity> RAID_PARTICIPANT; |
| 64 | + public static final EntityDefinitionBase<SpellcasterIllagerEntity> SPELLCASTER; |
| 65 | + public static final EntityDefinitionBase<AgeableEntity> AGEABLE; |
| 66 | + public static final EntityDefinitionBase<AbstractHorseEntity> HORSE; |
| 67 | + public static final EntityDefinitionBase<TameableEntity> TAMABLE; |
| 68 | + |
| 69 | + static { |
| 70 | + ENTITY = EntityDefinition.baseBuilder(Entity.class) |
| 71 | + .addTranslator(MetadataTypes.BYTE, Entity::setFlags) |
| 72 | + .addTranslator(MetadataTypes.INT, Entity::setAir) // Air/bubbles |
| 73 | + .addTranslator(MetadataTypes.OPTIONAL_COMPONENT, Entity::setDisplayName) |
| 74 | + .addTranslator(MetadataTypes.BOOLEAN, Entity::setDisplayNameVisible) |
| 75 | + .addTranslator(MetadataTypes.BOOLEAN, Entity::setSilent) |
| 76 | + .addTranslator(MetadataTypes.BOOLEAN, Entity::setGravity) |
| 77 | + .addTranslator(MetadataTypes.POSE, (entity, entityMetadata) -> entity.setPose(entityMetadata.getValue())) |
| 78 | + .addTranslator(MetadataTypes.INT, Entity::setFreezing) |
| 79 | + .build(); |
| 80 | + DISPLAY = EntityDefinitionBase.baseInherited(DisplayBaseEntity.class, ENTITY) |
| 81 | + .addTranslator(null) // Interpolation delay |
| 82 | + .addTranslator(null) // Transformation interpolation duration |
| 83 | + .addTranslator(null) // Position/Rotation interpolation duration |
| 84 | + .addTranslator(MetadataTypes.VECTOR3, DisplayBaseEntity::setTranslation) // Translation |
| 85 | + .addTranslator(null) // Scale |
| 86 | + .addTranslator(null) // Left rotation |
| 87 | + .addTranslator(null) // Right rotation |
| 88 | + .addTranslator(null) // Billboard render constraints |
| 89 | + .addTranslator(null) // Brightness override |
| 90 | + .addTranslator(null) // View range |
| 91 | + .addTranslator(null) // Shadow radius |
| 92 | + .addTranslator(null) // Shadow strength |
| 93 | + .addTranslator(null) // Width |
| 94 | + .addTranslator(null) // Height |
| 95 | + .addTranslator(null) // Glow color override |
| 96 | + .build(); |
| 97 | + FIREBALL = EntityDefinitionBase.baseInherited(FireballEntity.class, ENTITY) |
| 98 | + .addTranslator(null) // Item |
| 99 | + .build(); |
| 100 | + THROWABLE = EntityDefinitionBase.baseInherited(ThrowableItemEntity.class, ENTITY) |
| 101 | + .addTranslator(MetadataTypes.ITEM_STACK, ThrowableItemEntity::setItem) |
| 102 | + .build(); |
| 103 | + HANGING = EntityDefinitionBase.baseInherited(HangingEntity.class, ENTITY) |
| 104 | + .addTranslator(MetadataTypes.DIRECTION, HangingEntity::setDirectionMetadata) |
| 105 | + .build(); |
| 106 | + BOAT = EntityDefinitionBase.baseInherited(BoatEntity.class, ENTITY) |
| 107 | + .height(0.6f).width(1.6f) |
| 108 | + .offset(0.35f) |
| 109 | + .addTranslator(MetadataTypes.INT, (boatEntity, entityMetadata) -> boatEntity.getDirtyMetadata().put(EntityDataTypes.HURT_TICKS, entityMetadata.getValue())) // Time since last hit |
| 110 | + .addTranslator(MetadataTypes.INT, (boatEntity, entityMetadata) -> boatEntity.getDirtyMetadata().put(EntityDataTypes.HURT_DIRECTION, entityMetadata.getValue())) // Rocking direction |
| 111 | + .addTranslator(MetadataTypes.FLOAT, (boatEntity, entityMetadata) -> |
| 112 | + // 'Health' in Bedrock, damage taken in Java - it makes motion in Bedrock |
| 113 | + boatEntity.getDirtyMetadata().put(EntityDataTypes.STRUCTURAL_INTEGRITY, 40 - ((int) ((FloatEntityMetadata) entityMetadata).getPrimitiveValue()))) |
| 114 | + .addTranslator(MetadataTypes.BOOLEAN, BoatEntity::setPaddlingLeft) |
| 115 | + .addTranslator(MetadataTypes.BOOLEAN, BoatEntity::setPaddlingRight) |
| 116 | + .addTranslator(MetadataTypes.INT, (boatEntity, entityMetadata) -> boatEntity.getDirtyMetadata().put(EntityDataTypes.BOAT_BUBBLE_TIME, entityMetadata.getValue())) // May not actually do anything |
| 117 | + .build(); |
| 118 | + CHEST_BOAT = EntityDefinitionBase.baseInherited(ChestBoatEntity.class, BOAT) |
| 119 | + .build(); |
| 120 | + LIVING_ENTITY = EntityDefinitionBase.baseInherited(LivingEntity.class, ENTITY) |
| 121 | + .addTranslator(MetadataTypes.BYTE, LivingEntity::setLivingEntityFlags) |
| 122 | + .addTranslator(MetadataTypes.FLOAT, LivingEntity::setHealth) |
| 123 | + .addTranslator(MetadataTypes.PARTICLES, LivingEntity::setParticles) |
| 124 | + .addTranslator(MetadataTypes.BOOLEAN, |
| 125 | + (livingEntity, entityMetadata) -> livingEntity.getDirtyMetadata().put(EntityDataTypes.EFFECT_AMBIENCE, (byte) (((BooleanEntityMetadata) entityMetadata).getPrimitiveValue() ? 1 : 0))) |
| 126 | + .addTranslator(null) // Arrow count |
| 127 | + .addTranslator(null) // Stinger count |
| 128 | + .addTranslator(MetadataTypes.OPTIONAL_BLOCK_POS, LivingEntity::setBedPosition) |
| 129 | + .build(); |
| 130 | + AVATAR = EntityDefinitionBase.baseInherited(AvatarEntity.class, LIVING_ENTITY) |
| 131 | + .height(1.8f).width(0.6f) |
| 132 | + .offset(1.62f) |
| 133 | + .addTranslator(null) // Player main hand |
| 134 | + .addTranslator(MetadataTypes.BYTE, AvatarEntity::setSkinVisibility) |
| 135 | + .build(); |
| 136 | + MOB = EntityDefinitionBase.baseInherited(MobEntity.class, LIVING_ENTITY) |
| 137 | + .addTranslator(MetadataTypes.BYTE, MobEntity::setMobFlags) |
| 138 | + .build(); |
| 139 | + FISH = EntityDefinitionBase.baseInherited(AbstractFishEntity.class, MOB) |
| 140 | + .addTranslator(null) // From bucket |
| 141 | + .build(); |
| 142 | + PIGLIN = EntityDefinitionBase.baseInherited(BasePiglinEntity.class, MOB) |
| 143 | + .addTranslator(MetadataTypes.BOOLEAN, BasePiglinEntity::setImmuneToZombification) |
| 144 | + .build(); |
| 145 | + RAID_PARTICIPANT = EntityDefinitionBase.baseInherited(RaidParticipantEntity.class, MOB) |
| 146 | + .addTranslator(null) // Celebrating //TODO |
| 147 | + .build(); |
| 148 | + SPELLCASTER = EntityDefinitionBase.baseInherited(SpellcasterIllagerEntity.class, RAID_PARTICIPANT) |
| 149 | + .addTranslator(MetadataTypes.BYTE, SpellcasterIllagerEntity::setSpellType) |
| 150 | + .build(); |
| 151 | + AGEABLE = EntityDefinitionBase.baseInherited(AgeableEntity.class, MOB) |
| 152 | + .addTranslator(MetadataTypes.BOOLEAN, AgeableEntity::setBaby) |
| 153 | + .build(); |
| 154 | + HORSE = EntityDefinitionBase.baseInherited(AbstractHorseEntity.class, AGEABLE) |
| 155 | + .addTranslator(MetadataTypes.BYTE, AbstractHorseEntity::setHorseFlags) |
| 156 | + .build(); |
| 157 | + TAMABLE = EntityDefinitionBase.baseInherited(TameableEntity.class, AGEABLE) |
| 158 | + .addTranslator(MetadataTypes.BYTE, TameableEntity::setTameableFlags) |
| 159 | + .addTranslator(MetadataTypes.OPTIONAL_LIVING_ENTITY_REFERENCE, TameableEntity::setOwner) |
| 160 | + .build(); |
| 161 | + } |
| 162 | + |
| 163 | + private EntityDefinitionBases() { |
| 164 | + } |
| 165 | +} |
0 commit comments