1
0
mirror of https://github.com/GeyserMC/Geyser.git synced 2025-12-29 03:39:22 +00:00

Fixup HappyGhastEntity#isClientControlled check

This commit is contained in:
onebeastchris
2025-06-25 17:37:33 +02:00
parent 1bf7ae3ec2
commit d6897a73e5
11 changed files with 135 additions and 27 deletions

View File

@@ -51,6 +51,7 @@ import org.geysermc.geyser.scoreboard.Team;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.translator.item.ItemTranslator;
import org.geysermc.geyser.util.AttributeUtils;
import org.geysermc.geyser.util.EntityUtils;
import org.geysermc.geyser.util.InteractionResult;
import org.geysermc.geyser.util.MathUtils;
import org.geysermc.mcprotocollib.protocol.data.game.entity.EquipmentSlot;
@@ -537,6 +538,32 @@ public class LivingEntity extends Entity {
}
}
protected boolean hasBodyArmor() {
return this.hasValidEquippableItemForSlot(EquipmentSlot.BODY);
}
private boolean hasValidEquippableItemForSlot(EquipmentSlot slot) {
// MojMap LivingEntity#hasItemInSlot
GeyserItemStack itemInSlot = equipment.get(slot);
if (itemInSlot != null) {
// MojMap LivingEntity#isEquippableInSlot
Equippable equippable = itemInSlot.getComponent(DataComponentTypes.EQUIPPABLE);
if (equippable != null) {
return slot == equippable.slot() &&
canUseSlot(slot) &&
EntityUtils.equipmentUsableByEntity(session, equippable, this.definition.entityType());
} else {
return slot == EquipmentSlot.MAIN_HAND && canUseSlot(EquipmentSlot.MAIN_HAND);
}
}
return false;
}
protected boolean canUseSlot(EquipmentSlot slot) {
return true;
}
/**
* Calculates the complete attribute value to send to Bedrock. Will be overriden if attributes need to be cached.
*/

View File

@@ -30,8 +30,10 @@ import org.checkerframework.checker.nullness.qual.Nullable;
import org.cloudburstmc.math.TrigMath;
import org.cloudburstmc.math.vector.Vector2f;
import org.cloudburstmc.math.vector.Vector3f;
import org.cloudburstmc.protocol.bedrock.data.AttributeData;
import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag;
import org.geysermc.geyser.entity.EntityDefinition;
import org.geysermc.geyser.entity.attribute.GeyserAttributeType;
import org.geysermc.geyser.entity.type.Entity;
import org.geysermc.geyser.entity.type.player.SessionPlayerEntity;
import org.geysermc.geyser.entity.vehicle.ClientVehicle;
@@ -42,12 +44,16 @@ import org.geysermc.geyser.item.type.Item;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.session.cache.tags.ItemTag;
import org.geysermc.geyser.session.cache.tags.Tag;
import org.geysermc.geyser.util.AttributeUtils;
import org.geysermc.geyser.util.InteractionResult;
import org.geysermc.geyser.util.InteractiveTag;
import org.geysermc.mcprotocollib.protocol.data.game.entity.EquipmentSlot;
import org.geysermc.mcprotocollib.protocol.data.game.entity.attribute.Attribute;
import org.geysermc.mcprotocollib.protocol.data.game.entity.attribute.AttributeType;
import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.BooleanEntityMetadata;
import org.geysermc.mcprotocollib.protocol.data.game.entity.player.Hand;
import java.util.List;
import java.util.UUID;
public class HappyGhastEntity extends AnimalEntity implements ClientVehicle {
@@ -180,12 +186,7 @@ public class HappyGhastEntity extends AnimalEntity implements ClientVehicle {
@Override
public boolean isClientControlled() {
// TODO proper check, just lazy
if (body == null) {
return false;
}
// TODO must have ai check
if (staysStill) {
if (!hasBodyArmor() || getFlag(EntityFlag.NO_AI) || staysStill) {
return false;
}
@@ -195,4 +196,25 @@ public class HappyGhastEntity extends AnimalEntity implements ClientVehicle {
private Entity getFirstPassenger() {
return passengers.isEmpty() ? null : passengers.get(0);
}
@Override
protected void updateAttribute(Attribute javaAttribute, List<AttributeData> newAttributes) {
super.updateAttribute(javaAttribute, newAttributes);
if (javaAttribute.getType() instanceof AttributeType.Builtin type) {
switch (type) {
case FLYING_SPEED -> {
AttributeData attributeData = calculateAttribute(javaAttribute, GeyserAttributeType.FLYING_SPEED);
vehicleComponent.setFlyingSpeed(attributeData.getValue());
}
case CAMERA_DISTANCE -> {
vehicleComponent.setCameraDistance((float) AttributeUtils.calculateValue(javaAttribute));
}
}
}
}
@Override
protected boolean canUseSlot(EquipmentSlot slot) {
return slot != EquipmentSlot.BODY ? super.canUseSlot(slot) : this.isAlive() && !this.isBaby();
}
}

View File

@@ -47,6 +47,7 @@ import org.geysermc.geyser.session.cache.tags.Tag;
import org.geysermc.geyser.util.EntityUtils;
import org.geysermc.geyser.util.InteractionResult;
import org.geysermc.geyser.util.InteractiveTag;
import org.geysermc.mcprotocollib.protocol.data.game.entity.EquipmentSlot;
import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.BooleanEntityMetadata;
import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.IntEntityMetadata;
import org.geysermc.mcprotocollib.protocol.data.game.entity.player.Hand;
@@ -195,4 +196,9 @@ public class StriderEntity extends AnimalEntity implements Tickable, ClientVehic
public boolean canWalkOnLava() {
return true;
}
@Override
protected boolean canUseSlot(EquipmentSlot slot) {
return slot != EquipmentSlot.SADDLE ? super.canUseSlot(slot) : this.isAlive() && !this.isBaby();
}
}

View File

@@ -48,6 +48,7 @@ import org.geysermc.geyser.session.cache.tags.Tag;
import org.geysermc.geyser.util.EntityUtils;
import org.geysermc.geyser.util.InteractionResult;
import org.geysermc.geyser.util.InteractiveTag;
import org.geysermc.mcprotocollib.protocol.data.game.entity.EquipmentSlot;
import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.IntEntityMetadata;
import org.geysermc.mcprotocollib.protocol.data.game.entity.player.Hand;
@@ -154,4 +155,9 @@ public class PigEntity extends TemperatureVariantAnimal implements Tickable, Cli
public JavaRegistryKey<BuiltInVariant> variantRegistry() {
return JavaRegistries.PIG_VARIANT;
}
@Override
protected boolean canUseSlot(EquipmentSlot slot) {
return slot != EquipmentSlot.SADDLE ? super.canUseSlot(slot) : this.isAlive() && !this.isBaby();
}
}

View File

@@ -45,6 +45,7 @@ import org.geysermc.geyser.session.cache.tags.ItemTag;
import org.geysermc.geyser.session.cache.tags.Tag;
import org.geysermc.geyser.util.InteractionResult;
import org.geysermc.geyser.util.InteractiveTag;
import org.geysermc.mcprotocollib.protocol.data.game.entity.EquipmentSlot;
import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.ByteEntityMetadata;
import org.geysermc.mcprotocollib.protocol.data.game.entity.player.Hand;
@@ -286,4 +287,13 @@ public class AbstractHorseEntity extends AnimalEntity {
return InteractionResult.SUCCESS;
}
}
@Override
protected boolean canUseSlot(EquipmentSlot slot) {
if (slot != EquipmentSlot.SADDLE) {
return super.canUseSlot(slot);
} else {
return isAlive() && !isBaby() && getFlag(EntityFlag.TAMED);
}
}
}

View File

@@ -29,6 +29,7 @@ import org.cloudburstmc.math.vector.Vector3f;
import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes;
import org.geysermc.geyser.entity.EntityDefinition;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.mcprotocollib.protocol.data.game.entity.EquipmentSlot;
import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.IntEntityMetadata;
import java.util.UUID;
@@ -44,4 +45,9 @@ public class HorseEntity extends AbstractHorseEntity {
dirtyMetadata.put(EntityDataTypes.VARIANT, value & 255);
dirtyMetadata.put(EntityDataTypes.MARK_VARIANT, (value >> 8) % 5);
}
}
@Override
protected boolean canUseSlot(EquipmentSlot slot) {
return true;
}
}

View File

@@ -35,6 +35,7 @@ import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.session.cache.tags.ItemTag;
import org.geysermc.geyser.session.cache.tags.Tag;
import org.geysermc.geyser.util.MathUtils;
import org.geysermc.mcprotocollib.protocol.data.game.entity.EquipmentSlot;
import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.IntEntityMetadata;
import java.util.UUID;
@@ -61,4 +62,9 @@ public class LlamaEntity extends ChestedHorseEntity {
protected @Nullable Tag<Item> getFoodTag() {
return ItemTag.LLAMA_FOOD;
}
@Override
protected boolean canUseSlot(EquipmentSlot slot) {
return true;
}
}

View File

@@ -31,7 +31,7 @@ import org.cloudburstmc.math.vector.Vector3f;
public interface ClientVehicle {
VehicleComponent<?> getVehicleComponent();
// LivingEntity#getRiddenInput
// MojMap LivingEntity#getRiddenInput
Vector3f getRiddenInput(Vector2f input);
// MojMap LivingEntity#getRiddenSpeed

View File

@@ -27,25 +27,31 @@ package org.geysermc.geyser.entity.vehicle;
import lombok.Getter;
import lombok.Setter;
import org.cloudburstmc.math.vector.Vector2f;
import org.cloudburstmc.math.vector.Vector3d;
import org.cloudburstmc.math.vector.Vector3f;
import org.cloudburstmc.protocol.bedrock.data.entity.EntityDataTypes;
import org.geysermc.erosion.util.BlockPositionIterator;
import org.geysermc.geyser.entity.type.living.animal.HappyGhastEntity;
import org.geysermc.geyser.entity.type.player.SessionPlayerEntity;
import org.geysermc.geyser.level.block.Blocks;
import org.geysermc.geyser.level.block.Fluid;
import org.geysermc.geyser.level.block.type.BlockState;
import org.geysermc.geyser.level.physics.BoundingBox;
import org.geysermc.geyser.util.MathUtils;
import org.geysermc.mcprotocollib.protocol.data.game.entity.attribute.AttributeType;
@Setter
@Getter
public class HappyGhastVehicleComponent extends VehicleComponent<HappyGhastEntity> {
@Getter @Setter
private float flyingSpeed;
private float cameraDistance;
public HappyGhastVehicleComponent(HappyGhastEntity vehicle, float stepHeight) {
super(vehicle, stepHeight);
flyingSpeed = 0.05f; // Happy Ghast has different default
// Happy Ghast has different defaults
flyingSpeed = 0.05f;
moveSpeed = 0.05f;
cameraDistance = 8.0f;
}
@Override
@@ -54,6 +60,26 @@ public class HappyGhastVehicleComponent extends VehicleComponent<HappyGhastEntit
vehicle.setYaw(vehicle.getYaw() + addYaw);
}
@Override
public void onMount() {
super.onMount();
SessionPlayerEntity playerEntity = vehicle.getSession().getPlayerEntity();
playerEntity.getDirtyMetadata().put(EntityDataTypes.SEAT_LOCK_RIDER_ROTATION, false);
playerEntity.getDirtyMetadata().put(EntityDataTypes.SEAT_LOCK_RIDER_ROTATION_DEGREES, 181f);
playerEntity.getDirtyMetadata().put(EntityDataTypes.SEAT_THIRD_PERSON_CAMERA_RADIUS, cameraDistance);
playerEntity.getDirtyMetadata().put(EntityDataTypes.SEAT_CAMERA_RELAX_DISTANCE_SMOOTHING, cameraDistance * 0.75f);
playerEntity.getDirtyMetadata().put(EntityDataTypes.CONTROLLING_RIDER_SEAT_INDEX, (byte) 0);
}
@Override
public void onDismount() {
super.onDismount();
SessionPlayerEntity playerEntity = vehicle.getSession().getPlayerEntity();
playerEntity.getDirtyMetadata().put(EntityDataTypes.SEAT_THIRD_PERSON_CAMERA_RADIUS, (float) AttributeType.Builtin.CAMERA_DISTANCE.getDef());
playerEntity.getDirtyMetadata().put(EntityDataTypes.SEAT_CAMERA_RELAX_DISTANCE_SMOOTHING, cameraDistance * 0.75f);
playerEntity.getDirtyMetadata().put(EntityDataTypes.CONTROLLING_RIDER_SEAT_INDEX, (byte) 0);
}
/**
* Called every session tick while the player is mounted on the vehicle.
*/
@@ -72,6 +98,7 @@ public class HappyGhastVehicleComponent extends VehicleComponent<HappyGhastEntit
case LAVA -> 0.5f;
case EMPTY -> 0.91f;
};
// HappyGhast#travel
travel(ctx, flyingSpeed * 5.0f / 3.0f);
vehicle.setMotion(vehicle.getMotion().mul(drag));
}
@@ -98,7 +125,4 @@ public class HappyGhastVehicleComponent extends VehicleComponent<HappyGhastEntit
return result;
}
public class GoodLuckImplementingThisException extends RuntimeException {
}
}

View File

@@ -592,7 +592,7 @@ public class VehicleComponent<T extends LivingEntity & ClientVehicle> {
*
* @return true if there was a horizontal collision
*/
// Mojmap: LivingEntity#moveRelative
// Mojmap: LivingEntity#moveRelative / LivingEntity#move
protected boolean travel(VehicleContext ctx, float speed) {
Vector3f motion = vehicle.getMotion();

View File

@@ -44,11 +44,14 @@ import org.geysermc.geyser.entity.type.living.animal.horse.CamelEntity;
import org.geysermc.geyser.inventory.GeyserItemStack;
import org.geysermc.geyser.item.Items;
import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.session.cache.registry.JavaRegistries;
import org.geysermc.geyser.session.cache.tags.GeyserHolderSet;
import org.geysermc.geyser.text.MinecraftLocale;
import org.geysermc.mcprotocollib.protocol.data.game.entity.Effect;
import org.geysermc.mcprotocollib.protocol.data.game.entity.player.GameMode;
import org.geysermc.mcprotocollib.protocol.data.game.entity.player.Hand;
import org.geysermc.mcprotocollib.protocol.data.game.entity.type.EntityType;
import org.geysermc.mcprotocollib.protocol.data.game.item.component.Equippable;
import java.util.Locale;
@@ -283,23 +286,12 @@ public final class EntityUtils {
passenger.getDirtyMetadata().put(EntityDataTypes.SEAT_LOCK_RIDER_ROTATION_DEGREES, 90f);
passenger.getDirtyMetadata().put(EntityDataTypes.SEAT_HAS_ROTATION, true);
passenger.getDirtyMetadata().put(EntityDataTypes.SEAT_ROTATION_OFFSET_DEGREES, -90f);
} else if (mount instanceof HappyGhastEntity) {
passenger.getDirtyMetadata().put(EntityDataTypes.SEAT_LOCK_RIDER_ROTATION, false);
passenger.getDirtyMetadata().put(EntityDataTypes.SEAT_LOCK_RIDER_ROTATION_DEGREES, 181f);
passenger.getDirtyMetadata().put(EntityDataTypes.SEAT_THIRD_PERSON_CAMERA_RADIUS, 8f);
passenger.getDirtyMetadata().put(EntityDataTypes.SEAT_CAMERA_RELAX_DISTANCE_SMOOTHING, 6f);
passenger.getDirtyMetadata().put(EntityDataTypes.CONTROLLING_RIDER_SEAT_INDEX, (byte) 0);
}
} else {
passenger.getDirtyMetadata().put(EntityDataTypes.SEAT_LOCK_RIDER_ROTATION, false);
passenger.getDirtyMetadata().put(EntityDataTypes.SEAT_LOCK_RIDER_ROTATION_DEGREES, 0f);
passenger.getDirtyMetadata().put(EntityDataTypes.SEAT_HAS_ROTATION, false);
passenger.getDirtyMetadata().put(EntityDataTypes.SEAT_ROTATION_OFFSET_DEGREES, 0f);
// TODO what are defaults here???
passenger.getDirtyMetadata().put(EntityDataTypes.SEAT_THIRD_PERSON_CAMERA_RADIUS, 8f);
passenger.getDirtyMetadata().put(EntityDataTypes.SEAT_CAMERA_RELAX_DISTANCE_SMOOTHING, 6f);
passenger.getDirtyMetadata().put(EntityDataTypes.CONTROLLING_RIDER_SEAT_INDEX, (byte) 0);
}
}
@@ -363,6 +355,15 @@ public final class EntityUtils {
return translatedEntityName("minecraft", typeName, session);
}
public static boolean equipmentUsableByEntity(GeyserSession session, Equippable equippable, EntityType entity) {
if (equippable.allowedEntities() == null) {
return true;
}
GeyserHolderSet<EntityType> holderSet = GeyserHolderSet.fromHolderSet(JavaRegistries.ENTITY_TYPE, equippable.allowedEntities());
return session.getTagCache().is(holderSet, entity);
}
private EntityUtils() {
}
}