3
0
Mirror von https://github.com/GeyserMC/Geyser.git synchronisiert 2024-11-20 06:50:09 +01:00

Fixes for Camel dash and pose transition

Dieser Commit ist enthalten in:
AJ Ferguson 2024-05-17 03:12:52 -04:00
Ursprung b25087448c
Commit 8d72970db9
5 geänderte Dateien mit 95 neuen und 33 gelöschten Zeilen

Datei anzeigen

@ -926,7 +926,7 @@ public final class EntityDefinitions {
.type(EntityType.CAMEL) .type(EntityType.CAMEL)
.height(2.375f).width(1.7f) .height(2.375f).width(1.7f)
.addTranslator(MetadataType.BOOLEAN, CamelEntity::setDashing) .addTranslator(MetadataType.BOOLEAN, CamelEntity::setDashing)
.addTranslator(null) // Last pose change tick .addTranslator(MetadataType.LONG, CamelEntity::setLastPoseTick)
.build(); .build();
HORSE = EntityDefinition.inherited(HorseEntity::new, abstractHorseEntityBase) HORSE = EntityDefinition.inherited(HorseEntity::new, abstractHorseEntityBase)
.type(EntityType.HORSE) .type(EntityType.HORSE)

Datei anzeigen

@ -46,6 +46,7 @@ import org.geysermc.mcprotocollib.protocol.data.game.entity.attribute.AttributeT
import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.Pose; import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.Pose;
import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.BooleanEntityMetadata; 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.ByteEntityMetadata;
import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.LongEntityMetadata;
import java.util.UUID; import java.util.UUID;
@ -120,12 +121,23 @@ public class CamelEntity extends AbstractHorseEntity implements ClientVehicle {
} }
public void setDashing(BooleanEntityMetadata entityMetadata) { public void setDashing(BooleanEntityMetadata entityMetadata) {
// Java sends true to show dash animation and start the dash cooldown,
// false ends the dash animation, not the cooldown.
// Bedrock shows dash animation if HAS_DASH_COOLDOWN is set and the camel is above ground
if (entityMetadata.getPrimitiveValue()) { if (entityMetadata.getPrimitiveValue()) {
setFlag(EntityFlag.HAS_DASH_COOLDOWN, true); setFlag(EntityFlag.HAS_DASH_COOLDOWN, true);
vehicleComponent.startDashCooldown(); vehicleComponent.startDashCooldown();
} else if (!isClientControlled()) { // Don't remove dash cooldown prematurely if client is controlling
setFlag(EntityFlag.HAS_DASH_COOLDOWN, false);
} }
} }
public void setLastPoseTick(LongEntityMetadata entityMetadata) {
// Tick is based on world time. If negative, the camel is sitting.
// Must be compared to world time to know if the camel is fully standing/sitting or transitioning.
vehicleComponent.setLastPoseTick(entityMetadata.getPrimitiveValue());
}
@Override @Override
protected AttributeData calculateAttribute(Attribute javaAttribute, GeyserAttributeType type) { protected AttributeData calculateAttribute(Attribute javaAttribute, GeyserAttributeType type) {
AttributeData attributeData = super.calculateAttribute(javaAttribute, type); AttributeData attributeData = super.calculateAttribute(javaAttribute, type);

Datei anzeigen

@ -25,6 +25,7 @@
package org.geysermc.geyser.entity.vehicle; package org.geysermc.geyser.entity.vehicle;
import lombok.Setter;
import org.cloudburstmc.math.vector.Vector3f; import org.cloudburstmc.math.vector.Vector3f;
import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag; import org.cloudburstmc.protocol.bedrock.data.entity.EntityFlag;
import org.geysermc.geyser.entity.type.living.animal.horse.CamelEntity; import org.geysermc.geyser.entity.type.living.animal.horse.CamelEntity;
@ -32,7 +33,15 @@ import org.geysermc.geyser.entity.type.player.SessionPlayerEntity;
import org.geysermc.mcprotocollib.protocol.data.game.entity.Effect; import org.geysermc.mcprotocollib.protocol.data.game.entity.Effect;
public class CamelVehicleComponent extends VehicleComponent<CamelEntity> { public class CamelVehicleComponent extends VehicleComponent<CamelEntity> {
private float horseJumpStrength = 0.42f; // This is the default for Camels. Not sent by vanilla Java server when spawned private static final int STANDING_TICKS = 52;
private static final int DASH_TICKS = 55;
@Setter
private float horseJumpStrength = 0.42f; // Not sent by vanilla Java server when spawned
@Setter
private long lastPoseTick;
private int dashTick; private int dashTick;
private int jumpBoost; private int jumpBoost;
@ -40,26 +49,78 @@ public class CamelVehicleComponent extends VehicleComponent<CamelEntity> {
super(vehicle); super(vehicle);
} }
public void setHorseJumpStrength(float horseJumpStrength) {
this.horseJumpStrength = horseJumpStrength;
}
public void startDashCooldown() { public void startDashCooldown() {
this.dashTick = vehicle.getSession().getTicks() + 55; this.dashTick = vehicle.getSession().getTicks() + DASH_TICKS;
} }
@Override @Override
public void tickVehicle() { public void tickVehicle() {
if (vehicle.getFlag(EntityFlag.HAS_DASH_COOLDOWN)) { if (this.dashTick != 0) {
if (vehicle.getSession().getTicks() > dashTick) { if (vehicle.getSession().getTicks() > this.dashTick) {
vehicle.setFlag(EntityFlag.HAS_DASH_COOLDOWN, false); vehicle.setFlag(EntityFlag.HAS_DASH_COOLDOWN, false);
vehicle.updateBedrockMetadata(); this.dashTick = 0;
} else {
vehicle.setFlag(EntityFlag.HAS_DASH_COOLDOWN, true);
} }
} }
vehicle.setFlag(EntityFlag.CAN_DASH, vehicle.getFlag(EntityFlag.SADDLED) && !isStationary());
vehicle.updateBedrockMetadata();
super.tickVehicle(); super.tickVehicle();
} }
@Override
public void onDismount() {
vehicle.setFlag(EntityFlag.HAS_DASH_COOLDOWN, false);
vehicle.updateBedrockMetadata();
}
@Override
protected boolean travel(CamelEntity vehicle, float speed) {
if (vehicle.isOnGround() && isStationary()) {
vehicle.setMotion(vehicle.getMotion().mul(0, 1, 0));
}
return super.travel(vehicle, speed);
}
@Override
protected Vector3f getInputVelocity(CamelEntity vehicle, float speed) {
if (isStationary()) {
return Vector3f.ZERO;
}
SessionPlayerEntity player = vehicle.getSession().getPlayerEntity();
Vector3f inputVelocity = super.getInputVelocity(vehicle, speed);
float jumpStrength = player.getVehicleJumpStrength();
if (jumpStrength > 0) {
player.setVehicleJumpStrength(0);
if (jumpStrength >= 90) {
jumpStrength = 1.0f;
} else {
jumpStrength = 0.4f + 0.4f * jumpStrength / 90.0f;
}
return inputVelocity.add(Vector3f.createDirectionDeg(0, -player.getYaw())
.mul(22.2222f * jumpStrength * this.moveSpeed * getVelocityMultiplier(vehicle))
.up(1.4285f * jumpStrength * (this.horseJumpStrength * getJumpVelocityMultiplier(vehicle) + (this.jumpBoost * 0.1f))));
}
return inputVelocity;
}
/**
* Checks if the camel is sitting
* or transitioning to standing pose.
*/
private boolean isStationary() {
// Java checks if sitting using lastPoseTick
return this.lastPoseTick < 0 || vehicle.getSession().getWorldTicks() < this.lastPoseTick + STANDING_TICKS;
}
@Override @Override
public void setEffect(Effect effect, int effectAmplifier) { public void setEffect(Effect effect, int effectAmplifier) {
if (effect == Effect.JUMP_BOOST) { if (effect == Effect.JUMP_BOOST) {
@ -77,21 +138,4 @@ public class CamelVehicleComponent extends VehicleComponent<CamelEntity> {
super.removeEffect(effect); super.removeEffect(effect);
} }
} }
@Override
protected Vector3f getJumpVelocity(CamelEntity vehicle) {
SessionPlayerEntity player = vehicle.getSession().getPlayerEntity();
float jumpStrength = player.getVehicleJumpStrength();
if (jumpStrength > 0) {
player.setVehicleJumpStrength(0);
jumpStrength = jumpStrength >= 90 ? 1.0f : 0.4f + 0.4f * jumpStrength / 90.0f;
return Vector3f.createDirectionDeg(0, -player.getYaw())
.mul(22.2222f * jumpStrength * moveSpeed * getVelocityMultiplier(vehicle))
.up(1.4285f * jumpStrength * (horseJumpStrength * getJumpVelocityMultiplier(vehicle) + (jumpBoost * 0.1f)));
}
return Vector3f.ZERO;
}
} }

Datei anzeigen

@ -96,7 +96,9 @@ public class VehicleComponent<T extends LivingEntity & ClientVehicle> {
} }
public void setHeight(float height) { public void setHeight(float height) {
boundingBox.setSizeY(Double.parseDouble(Float.toString(height))); double doubleHeight = Double.parseDouble(Float.toString(height));
boundingBox.translate(0, (doubleHeight - boundingBox.getSizeY()) / 2, 0);
boundingBox.setSizeY(doubleHeight);
} }
public void moveAbsolute(double x, double y, double z) { public void moveAbsolute(double x, double y, double z) {
@ -131,6 +133,10 @@ public class VehicleComponent<T extends LivingEntity & ClientVehicle> {
return moveSpeed; return moveSpeed;
} }
public void onDismount() {
//
}
public void tickVehicle() { public void tickVehicle() {
if (!vehicle.isClientControlled()) { if (!vehicle.isClientControlled()) {
return; return;
@ -489,10 +495,6 @@ public class VehicleComponent<T extends LivingEntity & ClientVehicle> {
)); ));
} }
protected Vector3f getJumpVelocity(T vehicle) {
return Vector3f.ZERO;
}
/** /**
* @return True if there was a horizontal collision * @return True if there was a horizontal collision
*/ */
@ -511,7 +513,6 @@ public class VehicleComponent<T extends LivingEntity & ClientVehicle> {
// TODO: isImmobile? set input to 0 and jump to false // TODO: isImmobile? set input to 0 and jump to false
motion = motion.add(getInputVelocity(vehicle, speed)); motion = motion.add(getInputVelocity(vehicle, speed));
motion = motion.add(getJumpVelocity(vehicle));
Vector3f movementMultiplier = getBlockMovementMultiplier(vehicle); Vector3f movementMultiplier = getBlockMovementMultiplier(vehicle);
if (movementMultiplier != null) { if (movementMultiplier != null) {

Datei anzeigen

@ -30,6 +30,7 @@ import org.cloudburstmc.protocol.bedrock.data.entity.EntityLinkData;
import org.cloudburstmc.protocol.bedrock.packet.SetEntityLinkPacket; import org.cloudburstmc.protocol.bedrock.packet.SetEntityLinkPacket;
import org.geysermc.geyser.entity.EntityDefinitions; import org.geysermc.geyser.entity.EntityDefinitions;
import org.geysermc.geyser.entity.type.Entity; import org.geysermc.geyser.entity.type.Entity;
import org.geysermc.geyser.entity.vehicle.ClientVehicle;
import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.translator.protocol.PacketTranslator; import org.geysermc.geyser.translator.protocol.PacketTranslator;
import org.geysermc.geyser.translator.protocol.Translator; import org.geysermc.geyser.translator.protocol.Translator;
@ -100,6 +101,10 @@ public class JavaSetPassengersTranslator extends PacketTranslator<ClientboundSet
// as of Java 1.19.3, but the scheduled future checks for the vehicle being null anyway. // as of Java 1.19.3, but the scheduled future checks for the vehicle being null anyway.
session.getMountVehicleScheduledFuture().cancel(false); session.getMountVehicleScheduledFuture().cancel(false);
} }
if (entity instanceof ClientVehicle clientVehicle) {
clientVehicle.getVehicleComponent().onDismount();
}
} }
} }
} }