3
0
Mirror von https://github.com/GeyserMC/Geyser.git synchronisiert 2024-11-19 14:30:17 +01:00

Fix some mount offsets and strange behaviors with GSit (#2701)

* Prevent boats from floating when a Bedrock player rides in the back

* Update llama and shulker mount height offset

* Fix Trader llama mount offset

* Change passengers to an IntList

Also move rotation lock stuff to EntityUtils

* Allow EntityCache.getEntityByJavaId to return the session's player

Removes many checks from several translators.

* Fix mount offset on armorstands and area effect clouds

Also prevent area effect clouds from despawning when used as an invisible entity (used in GSit to offset players riding on other players)

* Update mount offsets on height changes

TODO test this

* Actually update vehicleId and optimize StriderEntity metadata update

* Don't hide marker armor stands and properly update mount offsets

* What?

* Remove y offset for Shulkers riding other entities

* Confirm teleports in the order received

This allows Bedrock players to move after standing up when using GSit

* Fix mount offset for riders on baby zoglins

* Cache only the latest teleport and confirm teleports immediately

* Fix crawling with GSit

* Inline var and undo respawn method

* Use Entity reference for vehicles

* Remove ridingVehicleEntity from GeyserSession

* Use Entity references for passengers and drop cachedPlayerEntityLinks

* Reuse variable and remove setVehicle(null)
Dieser Commit ist enthalten in:
David Choo 2021-12-18 11:43:57 -05:00 committet von GitHub
Ursprung 90442a8922
Commit 754bb42c19
Es konnte kein GPG-Schlüssel zu dieser Signatur gefunden werden
GPG-Schlüssel-ID: 4AEE18F83AFDEB23
43 geänderte Dateien mit 263 neuen und 366 gelöschten Zeilen

Datei anzeigen

@ -47,18 +47,19 @@ public class AreaEffectCloudEntity extends Entity {
protected void initializeMetadata() { protected void initializeMetadata() {
super.initializeMetadata(); super.initializeMetadata();
// Without this the cloud doesn't appear, // Without this the cloud doesn't appear,
dirtyMetadata.put(EntityData.AREA_EFFECT_CLOUD_DURATION, 600); dirtyMetadata.put(EntityData.AREA_EFFECT_CLOUD_DURATION, Integer.MAX_VALUE);
// This disabled client side shrink of the cloud // This disabled client side shrink of the cloud
dirtyMetadata.put(EntityData.AREA_EFFECT_CLOUD_RADIUS, 0.0f); dirtyMetadata.put(EntityData.AREA_EFFECT_CLOUD_RADIUS, 0.0f);
dirtyMetadata.put(EntityData.AREA_EFFECT_CLOUD_CHANGE_RATE, -0.005f); dirtyMetadata.put(EntityData.AREA_EFFECT_CLOUD_CHANGE_RATE, Float.MIN_VALUE);
dirtyMetadata.put(EntityData.AREA_EFFECT_CLOUD_CHANGE_ON_PICKUP, -0.5f); dirtyMetadata.put(EntityData.AREA_EFFECT_CLOUD_CHANGE_ON_PICKUP, Float.MIN_VALUE);
setFlag(EntityFlag.FIRE_IMMUNE, true); setFlag(EntityFlag.FIRE_IMMUNE, true);
} }
public void setRadius(FloatEntityMetadata entityMetadata) { public void setRadius(FloatEntityMetadata entityMetadata) {
float value = entityMetadata.getPrimitiveValue(); // Anything less than 0.5 will cause the cloud to despawn
float value = Math.max(entityMetadata.getPrimitiveValue(), 0.5f);
dirtyMetadata.put(EntityData.AREA_EFFECT_CLOUD_RADIUS, value); dirtyMetadata.put(EntityData.AREA_EFFECT_CLOUD_RADIUS, value);
dirtyMetadata.put(EntityData.BOUNDING_BOX_WIDTH, 2.0f * value); dirtyMetadata.put(EntityData.BOUNDING_BOX_WIDTH, 2.0f * value);
} }

Datei anzeigen

@ -84,8 +84,12 @@ public class BoatEntity extends Entity {
MoveEntityAbsolutePacket moveEntityPacket = new MoveEntityAbsolutePacket(); MoveEntityAbsolutePacket moveEntityPacket = new MoveEntityAbsolutePacket();
moveEntityPacket.setRuntimeEntityId(geyserId); moveEntityPacket.setRuntimeEntityId(geyserId);
// Minimal glitching when ClientboundMoveVehiclePacket is sent if (session.getPlayerEntity().getVehicle() == this && session.getPlayerEntity().isRidingInFront()) {
moveEntityPacket.setPosition(session.getRidingVehicleEntity() == this ? position.up(EntityDefinitions.PLAYER.offset() - this.definition.offset()) : this.position); // Minimal glitching when ClientboundMoveVehiclePacket is sent
moveEntityPacket.setPosition(position.up(EntityDefinitions.PLAYER.offset() - this.definition.offset()));
} else {
moveEntityPacket.setPosition(this.position);
}
moveEntityPacket.setRotation(getBedrockRotation()); moveEntityPacket.setRotation(getBedrockRotation());
moveEntityPacket.setOnGround(isOnGround); moveEntityPacket.setOnGround(isOnGround);
moveEntityPacket.setTeleported(teleported); moveEntityPacket.setTeleported(teleported);
@ -128,7 +132,7 @@ public class BoatEntity extends Entity {
paddleTimeLeft = 0f; paddleTimeLeft = 0f;
if (!this.passengers.isEmpty()) { if (!this.passengers.isEmpty()) {
// Get the entity by the first stored passenger and convey motion in this manner // Get the entity by the first stored passenger and convey motion in this manner
Entity entity = session.getEntityCache().getEntityByJavaId(this.passengers.iterator().nextLong()); Entity entity = this.passengers.get(0);
if (entity != null) { if (entity != null) {
updateLeftPaddle(session, entity); updateLeftPaddle(session, entity);
} }
@ -144,7 +148,7 @@ public class BoatEntity extends Entity {
if (isPaddlingRight) { if (isPaddlingRight) {
paddleTimeRight = 0f; paddleTimeRight = 0f;
if (!this.passengers.isEmpty()) { if (!this.passengers.isEmpty()) {
Entity entity = session.getEntityCache().getEntityByJavaId(this.passengers.iterator().nextLong()); Entity entity = this.passengers.get(0);
if (entity != null) { if (entity != null) {
updateRightPaddle(session, entity); updateRightPaddle(session, entity);
} }

Datei anzeigen

@ -39,7 +39,6 @@ import com.nukkitx.protocol.bedrock.packet.AddEntityPacket;
import com.nukkitx.protocol.bedrock.packet.MoveEntityAbsolutePacket; import com.nukkitx.protocol.bedrock.packet.MoveEntityAbsolutePacket;
import com.nukkitx.protocol.bedrock.packet.RemoveEntityPacket; import com.nukkitx.protocol.bedrock.packet.RemoveEntityPacket;
import com.nukkitx.protocol.bedrock.packet.SetEntityDataPacket; import com.nukkitx.protocol.bedrock.packet.SetEntityDataPacket;
import it.unimi.dsi.fastutil.longs.LongOpenHashSet;
import lombok.AccessLevel; import lombok.AccessLevel;
import lombok.Getter; import lombok.Getter;
import lombok.Setter; import lombok.Setter;
@ -48,8 +47,11 @@ import org.geysermc.geyser.entity.EntityDefinition;
import org.geysermc.geyser.entity.GeyserDirtyMetadata; import org.geysermc.geyser.entity.GeyserDirtyMetadata;
import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.translator.text.MessageTranslator; import org.geysermc.geyser.translator.text.MessageTranslator;
import org.geysermc.geyser.util.EntityUtils;
import org.geysermc.geyser.util.MathUtils; import org.geysermc.geyser.util.MathUtils;
import java.util.Collections;
import java.util.List;
import java.util.Optional; import java.util.Optional;
import java.util.UUID; import java.util.UUID;
@ -90,7 +92,8 @@ public class Entity {
protected String nametag = ""; protected String nametag = "";
/* Metadata end */ /* Metadata end */
protected LongOpenHashSet passengers = new LongOpenHashSet(); protected List<Entity> passengers = Collections.emptyList();
protected Entity vehicle;
/** /**
* A container to store temporary metadata before it's sent to Bedrock. * A container to store temporary metadata before it's sent to Bedrock.
*/ */
@ -181,11 +184,11 @@ public class Entity {
public boolean despawnEntity() { public boolean despawnEntity() {
if (!valid) return true; if (!valid) return true;
for (long passenger : passengers) { // Make sure all passengers on the despawned entity are updated for (Entity passenger : passengers) { // Make sure all passengers on the despawned entity are updated
Entity entity = session.getEntityCache().getEntityByJavaId(passenger); if (passenger == null) continue;
if (entity == null) continue; passenger.setVehicle(null);
entity.setFlag(EntityFlag.RIDING, false); passenger.setFlag(EntityFlag.RIDING, false);
entity.updateBedrockMetadata(); passenger.updateBedrockMetadata();
} }
RemoveEntityPacket removeEntityPacket = new RemoveEntityPacket(); RemoveEntityPacket removeEntityPacket = new RemoveEntityPacket();
@ -391,6 +394,8 @@ public class Entity {
if (height != boundingBoxHeight) { if (height != boundingBoxHeight) {
boundingBoxHeight = height; boundingBoxHeight = height;
dirtyMetadata.put(EntityData.BOUNDING_BOX_HEIGHT, boundingBoxHeight); dirtyMetadata.put(EntityData.BOUNDING_BOX_HEIGHT, boundingBoxHeight);
updatePassengerOffsets();
} }
} }
@ -435,6 +440,30 @@ public class Entity {
return Vector3f.from(pitch, headYaw, yaw); return Vector3f.from(pitch, headYaw, yaw);
} }
/**
* Update the mount offsets of each passenger on this vehicle
*/
protected void updatePassengerOffsets() {
for (Entity passenger : passengers) {
if (passenger != null) {
boolean rider = passengers.get(0) == this;
EntityUtils.updateMountOffset(passenger, this, rider, true, passengers.size() > 1);
passenger.updateBedrockMetadata();
}
}
}
/**
* Update this entity's mount offset
*/
protected void updateMountOffset() {
if (vehicle != null) {
boolean rider = vehicle.getPassengers().get(0) == this;
EntityUtils.updateMountOffset(this, vehicle, rider, true, vehicle.getPassengers().size() > 1);
updateBedrockMetadata();
}
}
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public <I extends Entity> I as(Class<I> entityClass) { public <I extends Entity> I as(Class<I> entityClass) {
return entityClass.isInstance(this) ? (I) this : null; return entityClass.isInstance(this) ? (I) this : null;

Datei anzeigen

@ -78,13 +78,7 @@ public class FishingHookEntity extends ThrowableEntity {
public void setHookedEntity(IntEntityMetadata entityMetadata) { public void setHookedEntity(IntEntityMetadata entityMetadata) {
int hookedEntityId = entityMetadata.getPrimitiveValue() - 1; int hookedEntityId = entityMetadata.getPrimitiveValue() - 1;
Entity entity; Entity entity = session.getEntityCache().getEntityByJavaId(hookedEntityId);
if (session.getPlayerEntity().getEntityId() == hookedEntityId) {
entity = session.getPlayerEntity();
} else {
entity = session.getEntityCache().getEntityByJavaId(hookedEntityId);
}
if (entity != null) { if (entity != null) {
bedrockTargetId = entity.getGeyserId(); bedrockTargetId = entity.getGeyserId();
dirtyMetadata.put(EntityData.TARGET_EID, bedrockTargetId); dirtyMetadata.put(EntityData.TARGET_EID, bedrockTargetId);

Datei anzeigen

@ -146,13 +146,14 @@ public class ArmorStandEntity extends LivingEntity {
isMarker = (xd & 0x10) == 0x10; isMarker = (xd & 0x10) == 0x10;
if (oldIsMarker != isMarker) { if (oldIsMarker != isMarker) {
if (isMarker) { if (isMarker) {
dirtyMetadata.put(EntityData.BOUNDING_BOX_WIDTH, 0.0f); setBoundingBoxWidth(0.0f);
dirtyMetadata.put(EntityData.BOUNDING_BOX_HEIGHT, 0.0f); setBoundingBoxHeight(0.0f);
dirtyMetadata.put(EntityData.SCALE, 0f); dirtyMetadata.put(EntityData.SCALE, 0f);
} else { } else {
toggleSmallStatus(); toggleSmallStatus();
} }
updateMountOffset();
updateSecondEntityStatus(false); updateSecondEntityStatus(false);
} }
@ -376,8 +377,8 @@ public class ArmorStandEntity extends LivingEntity {
* If this armor stand is not a marker, set its bounding box size and scale. * If this armor stand is not a marker, set its bounding box size and scale.
*/ */
private void toggleSmallStatus() { private void toggleSmallStatus() {
dirtyMetadata.put(EntityData.BOUNDING_BOX_WIDTH, isSmall ? 0.25f : definition.width()); setBoundingBoxWidth(isSmall ? 0.25f : definition.width());
dirtyMetadata.put(EntityData.BOUNDING_BOX_HEIGHT, isSmall ? 0.9875f : definition.height()); setBoundingBoxHeight(isSmall ? 0.9875f : definition.height());
dirtyMetadata.put(EntityData.SCALE, isSmall ? 0.55f : 1f); dirtyMetadata.put(EntityData.SCALE, isSmall ? 0.55f : 1f);
} }

Datei anzeigen

@ -60,12 +60,8 @@ public class StriderEntity extends AnimalEntity {
// Needs to copy the parent state // Needs to copy the parent state
if (getFlag(EntityFlag.RIDING)) { if (getFlag(EntityFlag.RIDING)) {
boolean parentShaking = false; boolean parentShaking = false;
//TODO optimize if (vehicle instanceof StriderEntity) {
for (Entity ent : session.getEntityCache().getEntities().values()) { parentShaking = vehicle.getFlag(EntityFlag.SHAKING);
if (ent.getPassengers().contains(entityId) && ent instanceof StriderEntity) {
parentShaking = ent.getFlag(EntityFlag.SHAKING);
break;
}
} }
setFlag(EntityFlag.BREATHING, !parentShaking); setFlag(EntityFlag.BREATHING, !parentShaking);
@ -76,10 +72,9 @@ public class StriderEntity extends AnimalEntity {
} }
// Update the passengers if we have any // Update the passengers if we have any
for (long passenger : passengers) { for (Entity passenger : passengers) {
Entity passengerEntity = session.getEntityCache().getEntityByJavaId(passenger); if (passenger != null) {
if (passengerEntity != null) { passenger.updateBedrockMetadata();
passengerEntity.updateBedrockMetadata();
} }
} }

Datei anzeigen

@ -42,13 +42,7 @@ public class GuardianEntity extends MonsterEntity {
public void setGuardianTarget(IntEntityMetadata entityMetadata) { public void setGuardianTarget(IntEntityMetadata entityMetadata) {
int entityId = entityMetadata.getPrimitiveValue(); int entityId = entityMetadata.getPrimitiveValue();
Entity entity; Entity entity = session.getEntityCache().getEntityByJavaId(entityId);
if (session.getPlayerEntity().getEntityId() == entityId) {
entity = session.getPlayerEntity();
} else {
entity = session.getEntityCache().getEntityByJavaId(entityId);
}
if (entity != null) { if (entity != null) {
dirtyMetadata.put(EntityData.TARGET_EID, entity.getGeyserId()); dirtyMetadata.put(EntityData.TARGET_EID, entity.getGeyserId());
} else { } else {

Datei anzeigen

@ -44,6 +44,8 @@ public class PiglinEntity extends BasePiglinEntity {
boolean isBaby = entityMetadata.getPrimitiveValue(); boolean isBaby = entityMetadata.getPrimitiveValue();
dirtyMetadata.put(EntityData.SCALE, isBaby? .55f : 1f); dirtyMetadata.put(EntityData.SCALE, isBaby? .55f : 1f);
setFlag(EntityFlag.BABY, isBaby); setFlag(EntityFlag.BABY, isBaby);
updateMountOffset();
} }
public void setChargingCrossbow(BooleanEntityMetadata entityMetadata) { public void setChargingCrossbow(BooleanEntityMetadata entityMetadata) {

Datei anzeigen

@ -60,15 +60,11 @@ public class WitherEntity extends MonsterEntity {
private void setTargetId(EntityData entityData, IntEntityMetadata entityMetadata) { private void setTargetId(EntityData entityData, IntEntityMetadata entityMetadata) {
int entityId = entityMetadata.getPrimitiveValue(); int entityId = entityMetadata.getPrimitiveValue();
Entity entity; Entity entity = session.getEntityCache().getEntityByJavaId(entityId);
if (session.getPlayerEntity().getEntityId() == entityId) {
entity = session.getPlayerEntity();
} else {
entity = session.getEntityCache().getEntityByJavaId(entityId);
}
if (entity != null) { if (entity != null) {
dirtyMetadata.put(entityData, entity.getGeyserId()); dirtyMetadata.put(entityData, entity.getGeyserId());
} else {
dirtyMetadata.put(entityData, (long) 0);
} }
} }

Datei anzeigen

@ -42,7 +42,17 @@ public class ZoglinEntity extends MonsterEntity {
public void setBaby(BooleanEntityMetadata entityMetadata) { public void setBaby(BooleanEntityMetadata entityMetadata) {
boolean isBaby = entityMetadata.getPrimitiveValue(); boolean isBaby = entityMetadata.getPrimitiveValue();
dirtyMetadata.put(EntityData.SCALE, isBaby? .55f : 1f); if (isBaby != getFlag(EntityFlag.BABY)) {
setFlag(EntityFlag.BABY, isBaby); dirtyMetadata.put(EntityData.SCALE, isBaby ? .55f : 1f);
setFlag(EntityFlag.BABY, isBaby);
updatePassengerOffsets();
}
}
@Override
public float getBoundingBoxHeight() {
float scale = getFlag(EntityFlag.BABY) ? 0.55f : 1f;
return scale * definition.height();
} }
} }

Datei anzeigen

@ -45,6 +45,8 @@ public class ZombieEntity extends MonsterEntity {
boolean isBaby = entityMetadata.getPrimitiveValue(); boolean isBaby = entityMetadata.getPrimitiveValue();
dirtyMetadata.put(EntityData.SCALE, isBaby ? .55f : 1.0f); dirtyMetadata.put(EntityData.SCALE, isBaby ? .55f : 1.0f);
setFlag(EntityFlag.BABY, isBaby); setFlag(EntityFlag.BABY, isBaby);
updateMountOffset();
} }
public void setConvertingToDrowned(BooleanEntityMetadata entityMetadata) { public void setConvertingToDrowned(BooleanEntityMetadata entityMetadata) {

Datei anzeigen

@ -123,14 +123,6 @@ public class PlayerEntity extends LivingEntity {
setFlagsDirty(false); setFlagsDirty(false);
long linkedEntityId = session.getEntityCache().getCachedPlayerEntityLink(entityId);
if (linkedEntityId != -1) {
Entity linkedEntity = session.getEntityCache().getEntityByJavaId(linkedEntityId);
if (linkedEntity != null) {
addPlayerPacket.getEntityLinks().add(new EntityLinkData(linkedEntity.getGeyserId(), geyserId, EntityLinkData.Type.RIDER, false, false));
}
}
valid = true; valid = true;
session.sendUpstreamPacket(addPlayerPacket); session.sendUpstreamPacket(addPlayerPacket);
} }

Datei anzeigen

@ -35,11 +35,14 @@ import com.nukkitx.math.vector.Vector3f;
import com.nukkitx.protocol.bedrock.data.AttributeData; import com.nukkitx.protocol.bedrock.data.AttributeData;
import com.nukkitx.protocol.bedrock.data.entity.EntityData; import com.nukkitx.protocol.bedrock.data.entity.EntityData;
import com.nukkitx.protocol.bedrock.data.entity.EntityFlag; import com.nukkitx.protocol.bedrock.data.entity.EntityFlag;
import com.nukkitx.protocol.bedrock.packet.MovePlayerPacket;
import com.nukkitx.protocol.bedrock.packet.RespawnPacket;
import com.nukkitx.protocol.bedrock.packet.UpdateAttributesPacket; import com.nukkitx.protocol.bedrock.packet.UpdateAttributesPacket;
import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;
import lombok.Getter; import lombok.Getter;
import org.geysermc.geyser.entity.attribute.GeyserAttributeType; import org.geysermc.geyser.entity.attribute.GeyserAttributeType;
import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.text.GeyserLocale;
import org.geysermc.geyser.util.AttributeUtils; import org.geysermc.geyser.util.AttributeUtils;
import java.util.Collections; import java.util.Collections;
@ -73,7 +76,7 @@ public class SessionPlayerEntity extends PlayerEntity {
private final GeyserSession session; private final GeyserSession session;
public SessionPlayerEntity(GeyserSession session) { public SessionPlayerEntity(GeyserSession session) {
super(session, 1, 1, new GameProfile(UUID.randomUUID(), "unknown"), Vector3f.ZERO, Vector3f.ZERO, 0, 0, 0); super(session, -1, 1, new GameProfile(UUID.randomUUID(), "unknown"), Vector3f.ZERO, Vector3f.ZERO, 0, 0, 0);
valid = true; valid = true;
this.session = session; this.session = session;
@ -112,7 +115,10 @@ public class SessionPlayerEntity extends PlayerEntity {
@Override @Override
public void setFlags(ByteEntityMetadata entityMetadata) { public void setFlags(ByteEntityMetadata entityMetadata) {
super.setFlags(entityMetadata); super.setFlags(entityMetadata);
session.setSwimmingInWater((entityMetadata.getPrimitiveValue() & 0x10) == 0x10 && getFlag(EntityFlag.SPRINTING)); // Swimming/crawling is controlled by the Java server
boolean swimming = (entityMetadata.getPrimitiveValue() & 0x10) == 0x10;
session.setSwimming(swimming);
session.setSwimmingInWater(swimming && getFlag(EntityFlag.SPRINTING));
refreshSpeed = true; refreshSpeed = true;
} }

Datei anzeigen

@ -42,9 +42,7 @@ import com.github.steveice10.mc.protocol.data.game.recipe.Recipe;
import com.github.steveice10.mc.protocol.data.game.statistic.CustomStatistic; import com.github.steveice10.mc.protocol.data.game.statistic.CustomStatistic;
import com.github.steveice10.mc.protocol.data.game.statistic.Statistic; import com.github.steveice10.mc.protocol.data.game.statistic.Statistic;
import com.github.steveice10.mc.protocol.packet.handshake.serverbound.ClientIntentionPacket; import com.github.steveice10.mc.protocol.packet.handshake.serverbound.ClientIntentionPacket;
import com.github.steveice10.mc.protocol.packet.ingame.serverbound.level.ServerboundAcceptTeleportationPacket;
import com.github.steveice10.mc.protocol.packet.ingame.serverbound.player.ServerboundMovePlayerPosPacket; import com.github.steveice10.mc.protocol.packet.ingame.serverbound.player.ServerboundMovePlayerPosPacket;
import com.github.steveice10.mc.protocol.packet.ingame.serverbound.player.ServerboundMovePlayerPosRotPacket;
import com.github.steveice10.mc.protocol.packet.ingame.serverbound.player.ServerboundPlayerAbilitiesPacket; import com.github.steveice10.mc.protocol.packet.ingame.serverbound.player.ServerboundPlayerAbilitiesPacket;
import com.github.steveice10.mc.protocol.packet.login.serverbound.ServerboundCustomQueryPacket; import com.github.steveice10.mc.protocol.packet.login.serverbound.ServerboundCustomQueryPacket;
import com.github.steveice10.packetlib.BuiltinFlags; import com.github.steveice10.packetlib.BuiltinFlags;
@ -68,7 +66,6 @@ import it.unimi.dsi.fastutil.ints.*;
import it.unimi.dsi.fastutil.longs.Long2ObjectMap; import it.unimi.dsi.fastutil.longs.Long2ObjectMap;
import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap; import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap;
import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;
import it.unimi.dsi.fastutil.objects.ObjectIterator;
import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet;
import lombok.AccessLevel; import lombok.AccessLevel;
import lombok.Getter; import lombok.Getter;
@ -167,7 +164,8 @@ public class GeyserSession implements GeyserConnection, CommandSender {
private final TagCache tagCache; private final TagCache tagCache;
private final WorldCache worldCache; private final WorldCache worldCache;
private final Int2ObjectMap<TeleportCache> teleportMap = new Int2ObjectOpenHashMap<>(); @Setter
private TeleportCache unconfirmedTeleport;
private final WorldBorder worldBorder; private final WorldBorder worldBorder;
/** /**
@ -333,9 +331,6 @@ public class GeyserSession implements GeyserConnection, CommandSender {
@Setter @Setter
private Vector3f lastInteractionPlayerPosition = Vector3f.ZERO; private Vector3f lastInteractionPlayerPosition = Vector3f.ZERO;
@Setter
private Entity ridingVehicleEntity;
/** /**
* The entity that the client is currently looking at. * The entity that the client is currently looking at.
*/ */
@ -1247,73 +1242,23 @@ public class GeyserSession implements GeyserConnection, CommandSender {
return itemNetId.getAndIncrement(); return itemNetId.getAndIncrement();
} }
public void addTeleport(TeleportCache teleportCache) {
teleportMap.put(teleportCache.getTeleportConfirmId(), teleportCache);
ObjectIterator<Int2ObjectMap.Entry<TeleportCache>> it = teleportMap.int2ObjectEntrySet().iterator();
// Remove any teleports with a higher number - maybe this is a world change that reset the ID to 0?
while (it.hasNext()) {
Int2ObjectMap.Entry<TeleportCache> entry = it.next();
int nextID = entry.getValue().getTeleportConfirmId();
if (nextID > teleportCache.getTeleportConfirmId()) {
it.remove();
}
}
}
public void confirmTeleport(Vector3d position) { public void confirmTeleport(Vector3d position) {
if (teleportMap.size() == 0) { if (unconfirmedTeleport == null) {
return; return;
} }
int teleportID = -1;
for (Int2ObjectMap.Entry<TeleportCache> entry : teleportMap.int2ObjectEntrySet()) { if (unconfirmedTeleport.canConfirm(position)) {
if (entry.getValue().canConfirm(position)) { unconfirmedTeleport = null;
if (entry.getValue().getTeleportConfirmId() > teleportID) { return;
teleportID = entry.getValue().getTeleportConfirmId();
}
}
} }
if (teleportID != -1) { // Resend the teleport every few packets until Bedrock responds
ObjectIterator<Int2ObjectMap.Entry<TeleportCache>> it = teleportMap.int2ObjectEntrySet().iterator(); unconfirmedTeleport.incrementUnconfirmedFor();
if (unconfirmedTeleport.shouldResend()) {
// Confirm the current teleport and any earlier ones unconfirmedTeleport.resetUnconfirmedFor();
while (it.hasNext()) { geyser.getLogger().debug("Resending teleport " + unconfirmedTeleport.getTeleportConfirmId());
TeleportCache entry = it.next().getValue(); getPlayerEntity().moveAbsolute(Vector3f.from(unconfirmedTeleport.getX(), unconfirmedTeleport.getY(), unconfirmedTeleport.getZ()),
int nextID = entry.getTeleportConfirmId(); unconfirmedTeleport.getYaw(), unconfirmedTeleport.getPitch(), playerEntity.isOnGround(), true);
if (nextID <= teleportID) {
ServerboundAcceptTeleportationPacket teleportConfirmPacket = new ServerboundAcceptTeleportationPacket(nextID);
sendDownstreamPacket(teleportConfirmPacket);
// Servers (especially ones like Hypixel) expect exact coordinates given back to them.
ServerboundMovePlayerPosRotPacket positionPacket = new ServerboundMovePlayerPosRotPacket(playerEntity.isOnGround(),
entry.getX(), entry.getY(), entry.getZ(), entry.getYaw(), entry.getPitch());
sendDownstreamPacket(positionPacket);
it.remove();
geyser.getLogger().debug("Confirmed teleport " + nextID);
}
}
}
if (teleportMap.size() > 0) {
int resendID = -1;
for (Int2ObjectMap.Entry<TeleportCache> entry : teleportMap.int2ObjectEntrySet()) {
TeleportCache teleport = entry.getValue();
teleport.incrementUnconfirmedFor();
if (teleport.shouldResend()) {
if (teleport.getTeleportConfirmId() >= resendID) {
resendID = teleport.getTeleportConfirmId();
}
}
}
if (resendID != -1) {
geyser.getLogger().debug("Resending teleport " + resendID);
TeleportCache teleport = teleportMap.get(resendID);
getPlayerEntity().moveAbsolute(Vector3f.from(teleport.getX(), teleport.getY(), teleport.getZ()),
teleport.getYaw(), teleport.getPitch(), playerEntity.isOnGround(), true);
}
} }
} }

Datei anzeigen

@ -56,15 +56,12 @@ public class EntityCache {
private final Long2LongMap entityIdTranslations = new Long2LongOpenHashMap(); private final Long2LongMap entityIdTranslations = new Long2LongOpenHashMap();
private final Map<UUID, PlayerEntity> playerEntities = new Object2ObjectOpenHashMap<>(); private final Map<UUID, PlayerEntity> playerEntities = new Object2ObjectOpenHashMap<>();
private final Map<UUID, BossBar> bossBars = new Object2ObjectOpenHashMap<>(); private final Map<UUID, BossBar> bossBars = new Object2ObjectOpenHashMap<>();
private final Long2LongMap cachedPlayerEntityLinks = new Long2LongOpenHashMap();
@Getter @Getter
private final AtomicLong nextEntityId = new AtomicLong(2L); private final AtomicLong nextEntityId = new AtomicLong(2L);
public EntityCache(GeyserSession session) { public EntityCache(GeyserSession session) {
this.session = session; this.session = session;
cachedPlayerEntityLinks.defaultReturnValue(-1L);
} }
public void spawnEntity(Entity entity) { public void spawnEntity(Entity entity) {
@ -112,8 +109,6 @@ public class EntityCache {
} }
session.getPlayerWithCustomHeads().clear(); session.getPlayerWithCustomHeads().clear();
// As a precaution
cachedPlayerEntityLinks.clear();
} }
public Entity getEntityByGeyserId(long geyserId) { public Entity getEntityByGeyserId(long geyserId) {
@ -121,6 +116,9 @@ public class EntityCache {
} }
public Entity getEntityByJavaId(long javaId) { public Entity getEntityByJavaId(long javaId) {
if (javaId == session.getPlayerEntity().getEntityId()) {
return session.getPlayerEntity();
}
return entities.get(entityIdTranslations.get(javaId)); return entities.get(entityIdTranslations.get(javaId));
} }
@ -160,14 +158,6 @@ public class EntityCache {
bossBars.values().forEach(BossBar::updateBossBar); bossBars.values().forEach(BossBar::updateBossBar);
} }
public long getCachedPlayerEntityLink(long playerId) {
return cachedPlayerEntityLinks.remove(playerId);
}
public void addCachedPlayerEntityLink(long playerId, long linkedEntityId) {
cachedPlayerEntityLinks.put(playerId, linkedEntityId);
}
public List<Tickable> getTickableEntities() { public List<Tickable> getTickableEntities() {
return tickableEntities; return tickableEntities;
} }

Datei anzeigen

@ -66,6 +66,10 @@ public class TeleportCache {
unconfirmedFor++; unconfirmedFor++;
} }
public void resetUnconfirmedFor() {
unconfirmedFor = 0;
}
public boolean shouldResend() { public boolean shouldResend() {
return unconfirmedFor >= RESEND_THRESHOLD; return unconfirmedFor >= RESEND_THRESHOLD;
} }

Datei anzeigen

@ -151,7 +151,7 @@ public class WorldBorder {
// Move the player back, but allow gravity to take place // Move the player back, but allow gravity to take place
// Teleported = true makes going back better, but disconnects the player from their mounted entity // Teleported = true makes going back better, but disconnects the player from their mounted entity
playerEntity.moveAbsolute(Vector3f.from(playerEntity.getPosition().getX(), (newPosition.getY() - EntityDefinitions.PLAYER.offset()), playerEntity.getPosition().getZ()), playerEntity.moveAbsolute(Vector3f.from(playerEntity.getPosition().getX(), (newPosition.getY() - EntityDefinitions.PLAYER.offset()), playerEntity.getPosition().getZ()),
playerEntity.getYaw(), playerEntity.getPitch(), playerEntity.getHeadYaw(), playerEntity.isOnGround(), session.getRidingVehicleEntity() == null); playerEntity.getYaw(), playerEntity.getPitch(), playerEntity.getHeadYaw(), playerEntity.isOnGround(), playerEntity.getVehicle() == null);
} }
return isInWorldBorder; return isInWorldBorder;
} }

Datei anzeigen

@ -45,7 +45,7 @@ public class BedrockMoveEntityAbsoluteTranslator extends PacketTranslator<MoveEn
public void translate(GeyserSession session, MoveEntityAbsolutePacket packet) { public void translate(GeyserSession session, MoveEntityAbsolutePacket packet) {
session.setLastVehicleMoveTimestamp(System.currentTimeMillis()); session.setLastVehicleMoveTimestamp(System.currentTimeMillis());
Entity ridingEntity = session.getRidingVehicleEntity(); Entity ridingEntity = session.getPlayerEntity().getVehicle();
if (ridingEntity != null && session.getWorldBorder().isPassingIntoBorderBoundaries(packet.getPosition(), false)) { if (ridingEntity != null && session.getWorldBorder().isPassingIntoBorderBoundaries(packet.getPosition(), false)) {
Vector3f position = Vector3f.from(ridingEntity.getPosition().getX(), packet.getPosition().getY(), Vector3f position = Vector3f.from(ridingEntity.getPosition().getX(), packet.getPosition().getY(),
ridingEntity.getPosition().getZ()); ridingEntity.getPosition().getZ());

Datei anzeigen

@ -54,7 +54,7 @@ public class BedrockPlayerInputTranslator extends PacketTranslator<PlayerInputPa
// Bedrock only sends movement vehicle packets while moving // Bedrock only sends movement vehicle packets while moving
// This allows horses to take damage while standing on magma // This allows horses to take damage while standing on magma
Entity vehicle = session.getRidingVehicleEntity(); Entity vehicle = session.getPlayerEntity().getVehicle();
boolean sendMovement = false; boolean sendMovement = false;
if (vehicle instanceof AbstractHorseEntity && !(vehicle instanceof LlamaEntity)) { if (vehicle instanceof AbstractHorseEntity && !(vehicle instanceof LlamaEntity)) {
sendMovement = vehicle.isOnGround(); sendMovement = vehicle.isOnGround();

Datei anzeigen

@ -77,16 +77,17 @@ public class BedrockActionTranslator extends PacketTranslator<PlayerActionPacket
session.sendUpstreamPacket(attributesPacket); session.sendUpstreamPacket(attributesPacket);
break; break;
case START_SWIMMING: case START_SWIMMING:
ServerboundPlayerCommandPacket startSwimPacket = new ServerboundPlayerCommandPacket((int) entity.getEntityId(), PlayerState.START_SPRINTING); if (!session.getPlayerEntity().getFlag(EntityFlag.SWIMMING)) {
session.sendDownstreamPacket(startSwimPacket); ServerboundPlayerCommandPacket startSwimPacket = new ServerboundPlayerCommandPacket((int) entity.getEntityId(), PlayerState.START_SPRINTING);
session.sendDownstreamPacket(startSwimPacket);
session.setSwimming(true); }
break; break;
case STOP_SWIMMING: case STOP_SWIMMING:
ServerboundPlayerCommandPacket stopSwimPacket = new ServerboundPlayerCommandPacket((int) entity.getEntityId(), PlayerState.STOP_SPRINTING); // Prevent packet spam when Bedrock players are crawling near the edge of a block
session.sendDownstreamPacket(stopSwimPacket); if (session.isSwimmingInWater()) {
ServerboundPlayerCommandPacket stopSwimPacket = new ServerboundPlayerCommandPacket((int) entity.getEntityId(), PlayerState.STOP_SPRINTING);
session.setSwimming(false); session.sendDownstreamPacket(stopSwimPacket);
}
break; break;
case START_GLIDE: case START_GLIDE:
// Otherwise gliding will not work in creative // Otherwise gliding will not work in creative
@ -134,13 +135,17 @@ public class BedrockActionTranslator extends PacketTranslator<PlayerActionPacket
session.setSneaking(false); session.setSneaking(false);
break; break;
case START_SPRINT: case START_SPRINT:
ServerboundPlayerCommandPacket startSprintPacket = new ServerboundPlayerCommandPacket((int) entity.getEntityId(), PlayerState.START_SPRINTING); if (!session.getPlayerEntity().getFlag(EntityFlag.SWIMMING)) {
session.sendDownstreamPacket(startSprintPacket); ServerboundPlayerCommandPacket startSprintPacket = new ServerboundPlayerCommandPacket((int) entity.getEntityId(), PlayerState.START_SPRINTING);
session.setSprinting(true); session.sendDownstreamPacket(startSprintPacket);
session.setSprinting(true);
}
break; break;
case STOP_SPRINT: case STOP_SPRINT:
ServerboundPlayerCommandPacket stopSprintPacket = new ServerboundPlayerCommandPacket((int) entity.getEntityId(), PlayerState.STOP_SPRINTING); if (!session.getPlayerEntity().getFlag(EntityFlag.SWIMMING)) {
session.sendDownstreamPacket(stopSprintPacket); ServerboundPlayerCommandPacket stopSprintPacket = new ServerboundPlayerCommandPacket((int) entity.getEntityId(), PlayerState.STOP_SPRINTING);
session.sendDownstreamPacket(stopSprintPacket);
}
session.setSprinting(false); session.setSprinting(false);
break; break;
case DROP_ITEM: case DROP_ITEM:

Datei anzeigen

@ -74,7 +74,6 @@ public class BedrockInteractTranslator extends PacketTranslator<InteractPacket>
case LEAVE_VEHICLE: case LEAVE_VEHICLE:
ServerboundPlayerCommandPacket sneakPacket = new ServerboundPlayerCommandPacket((int) entity.getEntityId(), PlayerState.START_SNEAKING); ServerboundPlayerCommandPacket sneakPacket = new ServerboundPlayerCommandPacket((int) entity.getEntityId(), PlayerState.START_SNEAKING);
session.sendDownstreamPacket(sneakPacket); session.sendDownstreamPacket(sneakPacket);
session.setRidingVehicleEntity(null);
break; break;
case MOUSEOVER: case MOUSEOVER:
// Handle the buttons for mobile - "Mount", etc; and the suggestions for console - "ZL: Mount", etc // Handle the buttons for mobile - "Mount", etc; and the suggestions for console - "ZL: Mount", etc
@ -97,7 +96,7 @@ public class BedrockInteractTranslator extends PacketTranslator<InteractPacket>
break; break;
case OPEN_INVENTORY: case OPEN_INVENTORY:
if (session.getOpenInventory() == null) { if (session.getOpenInventory() == null) {
Entity ridingEntity = session.getRidingVehicleEntity(); Entity ridingEntity = session.getPlayerEntity().getVehicle();
if (ridingEntity instanceof AbstractHorseEntity) { if (ridingEntity instanceof AbstractHorseEntity) {
if (ridingEntity.getFlag(EntityFlag.TAMED)) { if (ridingEntity.getFlag(EntityFlag.TAMED)) {
// We should request to open the horse inventory instead // We should request to open the horse inventory instead

Datei anzeigen

@ -67,7 +67,8 @@ public class BedrockMovePlayerTranslator extends PacketTranslator<MovePlayerPack
// Send book update before the player moves // Send book update before the player moves
session.getBookEditCache().checkForSend(); session.getBookEditCache().checkForSend();
if (!session.getTeleportMap().isEmpty()) { // Ignore movement packets until Bedrock's position matches the teleported position
if (session.getUnconfirmedTeleport() != null) {
session.confirmTeleport(packet.getPosition().toDouble().sub(0, EntityDefinitions.PLAYER.offset(), 0)); session.confirmTeleport(packet.getPosition().toDouble().sub(0, EntityDefinitions.PLAYER.offset(), 0));
return; return;
} }

Datei anzeigen

@ -38,7 +38,7 @@ import org.geysermc.geyser.translator.protocol.Translator;
public class BedrockRiderJumpTranslator extends PacketTranslator<RiderJumpPacket> { public class BedrockRiderJumpTranslator extends PacketTranslator<RiderJumpPacket> {
@Override @Override
public void translate(GeyserSession session, RiderJumpPacket packet) { public void translate(GeyserSession session, RiderJumpPacket packet) {
Entity vehicle = session.getRidingVehicleEntity(); Entity vehicle = session.getPlayerEntity().getVehicle();
if (vehicle instanceof AbstractHorseEntity) { if (vehicle instanceof AbstractHorseEntity) {
ServerboundPlayerCommandPacket playerCommandPacket = new ServerboundPlayerCommandPacket((int) vehicle.getEntityId(), PlayerState.START_HORSE_JUMP, packet.getJumpStrength()); ServerboundPlayerCommandPacket playerCommandPacket = new ServerboundPlayerCommandPacket((int) vehicle.getEntityId(), PlayerState.START_HORSE_JUMP, packet.getJumpStrength());
session.sendDownstreamPacket(playerCommandPacket); session.sendDownstreamPacket(playerCommandPacket);

Datei anzeigen

@ -41,12 +41,7 @@ public class JavaAnimateTranslator extends PacketTranslator<ClientboundAnimatePa
@Override @Override
public void translate(GeyserSession session, ClientboundAnimatePacket packet) { public void translate(GeyserSession session, ClientboundAnimatePacket packet) {
Entity entity; Entity entity = session.getEntityCache().getEntityByJavaId(packet.getEntityId());
if (packet.getEntityId() == session.getPlayerEntity().getEntityId()) {
entity = session.getPlayerEntity();
} else {
entity = session.getEntityCache().getEntityByJavaId(packet.getEntityId());
}
if (entity == null) if (entity == null)
return; return;

Datei anzeigen

@ -47,12 +47,7 @@ public class JavaEntityEventTranslator extends PacketTranslator<ClientboundEntit
@Override @Override
public void translate(GeyserSession session, ClientboundEntityEventPacket packet) { public void translate(GeyserSession session, ClientboundEntityEventPacket packet) {
Entity entity; Entity entity = session.getEntityCache().getEntityByJavaId(packet.getEntityId());
if (packet.getEntityId() == session.getPlayerEntity().getEntityId()) {
entity = session.getPlayerEntity();
} else {
entity = session.getEntityCache().getEntityByJavaId(packet.getEntityId());
}
if (entity == null) if (entity == null)
return; return;

Datei anzeigen

@ -37,9 +37,6 @@ public class JavaMoveEntityPosRotTranslator extends PacketTranslator<Clientbound
@Override @Override
public void translate(GeyserSession session, ClientboundMoveEntityPosRotPacket packet) { public void translate(GeyserSession session, ClientboundMoveEntityPosRotPacket packet) {
Entity entity = session.getEntityCache().getEntityByJavaId(packet.getEntityId()); Entity entity = session.getEntityCache().getEntityByJavaId(packet.getEntityId());
if (packet.getEntityId() == session.getPlayerEntity().getEntityId()) {
entity = session.getPlayerEntity();
}
if (entity == null) return; if (entity == null) return;
entity.updatePositionAndRotation(packet.getMoveX(), packet.getMoveY(), packet.getMoveZ(), packet.getYaw(), packet.getPitch(), packet.isOnGround()); entity.updatePositionAndRotation(packet.getMoveX(), packet.getMoveY(), packet.getMoveZ(), packet.getYaw(), packet.getPitch(), packet.isOnGround());

Datei anzeigen

@ -36,12 +36,7 @@ public class JavaMoveEntityPosTranslator extends PacketTranslator<ClientboundMov
@Override @Override
public void translate(GeyserSession session, ClientboundMoveEntityPosPacket packet) { public void translate(GeyserSession session, ClientboundMoveEntityPosPacket packet) {
Entity entity; Entity entity = session.getEntityCache().getEntityByJavaId(packet.getEntityId());
if (packet.getEntityId() == session.getPlayerEntity().getEntityId()) {
entity = session.getPlayerEntity();
} else {
entity = session.getEntityCache().getEntityByJavaId(packet.getEntityId());
}
if (entity == null) return; if (entity == null) return;
entity.moveRelative(packet.getMoveX(), packet.getMoveY(), packet.getMoveZ(), entity.getYaw(), entity.getPitch(), entity.getHeadYaw(), packet.isOnGround()); entity.moveRelative(packet.getMoveX(), packet.getMoveY(), packet.getMoveZ(), entity.getYaw(), entity.getPitch(), entity.getHeadYaw(), packet.isOnGround());

Datei anzeigen

@ -37,9 +37,6 @@ public class JavaMoveEntityRotTranslator extends PacketTranslator<ClientboundMov
@Override @Override
public void translate(GeyserSession session, ClientboundMoveEntityRotPacket packet) { public void translate(GeyserSession session, ClientboundMoveEntityRotPacket packet) {
Entity entity = session.getEntityCache().getEntityByJavaId(packet.getEntityId()); Entity entity = session.getEntityCache().getEntityByJavaId(packet.getEntityId());
if (packet.getEntityId() == session.getPlayerEntity().getEntityId()) {
entity = session.getPlayerEntity();
}
if (entity == null) return; if (entity == null) return;
entity.updateRotation(packet.getYaw(), packet.getPitch(), packet.isOnGround()); entity.updateRotation(packet.getYaw(), packet.getPitch(), packet.isOnGround());

Datei anzeigen

@ -37,7 +37,7 @@ public class JavaMoveVehicleTranslator extends PacketTranslator<ClientboundMoveV
@Override @Override
public void translate(GeyserSession session, ClientboundMoveVehiclePacket packet) { public void translate(GeyserSession session, ClientboundMoveVehiclePacket packet) {
Entity entity = session.getRidingVehicleEntity(); Entity entity = session.getPlayerEntity().getVehicle();
if (entity == null) return; if (entity == null) return;
entity.moveAbsolute(Vector3f.from(packet.getX(), packet.getY(), packet.getZ()), packet.getYaw(), packet.getPitch(), false, true); entity.moveAbsolute(Vector3f.from(packet.getX(), packet.getY(), packet.getZ()), packet.getYaw(), packet.getPitch(), false, true);

Datei anzeigen

@ -38,12 +38,9 @@ public class JavaRemoveMobEffectTranslator extends PacketTranslator<ClientboundR
@Override @Override
public void translate(GeyserSession session, ClientboundRemoveMobEffectPacket packet) { public void translate(GeyserSession session, ClientboundRemoveMobEffectPacket packet) {
Entity entity; Entity entity = session.getEntityCache().getEntityByJavaId(packet.getEntityId());
if (packet.getEntityId() == session.getPlayerEntity().getEntityId()) { if (entity == session.getPlayerEntity()) {
entity = session.getPlayerEntity();
session.getEffectCache().removeEffect(packet.getEffect()); session.getEffectCache().removeEffect(packet.getEffect());
} else {
entity = session.getEntityCache().getEntityByJavaId(packet.getEntityId());
} }
if (entity == null) if (entity == null)
return; return;

Datei anzeigen

@ -36,13 +36,7 @@ public class JavaRotateHeadTranslator extends PacketTranslator<ClientboundRotate
@Override @Override
public void translate(GeyserSession session, ClientboundRotateHeadPacket packet) { public void translate(GeyserSession session, ClientboundRotateHeadPacket packet) {
Entity entity; Entity entity = session.getEntityCache().getEntityByJavaId(packet.getEntityId());
if (packet.getEntityId() == session.getPlayerEntity().getEntityId()) {
entity = session.getPlayerEntity();
} else {
entity = session.getEntityCache().getEntityByJavaId(packet.getEntityId());
}
if (entity == null) return; if (entity == null) return;
entity.updateHeadLookRotation(packet.getHeadYaw()); entity.updateHeadLookRotation(packet.getHeadYaw());

Datei anzeigen

@ -40,12 +40,7 @@ public class JavaSetEntityDataTranslator extends PacketTranslator<ClientboundSet
@SuppressWarnings({"rawtypes", "unchecked"}) @SuppressWarnings({"rawtypes", "unchecked"})
@Override @Override
public void translate(GeyserSession session, ClientboundSetEntityDataPacket packet) { public void translate(GeyserSession session, ClientboundSetEntityDataPacket packet) {
Entity entity; Entity entity = session.getEntityCache().getEntityByJavaId(packet.getEntityId());
if (packet.getEntityId() == session.getPlayerEntity().getEntityId()) {
entity = session.getPlayerEntity();
} else {
entity = session.getEntityCache().getEntityByJavaId(packet.getEntityId());
}
if (entity == null) return; if (entity == null) return;
EntityDefinition<?> definition = entity.getDefinition(); EntityDefinition<?> definition = entity.getDefinition();

Datei anzeigen

@ -43,33 +43,23 @@ public class JavaSetEntityLinkTranslator extends PacketTranslator<ClientboundSet
@Override @Override
public void translate(GeyserSession session, ClientboundSetEntityLinkPacket packet) { public void translate(GeyserSession session, ClientboundSetEntityLinkPacket packet) {
Entity holderId; Entity holderId = session.getEntityCache().getEntityByJavaId(packet.getEntityId());
if (packet.getEntityId() == session.getPlayerEntity().getEntityId()) {
holderId = session.getPlayerEntity();
} else {
holderId = session.getEntityCache().getEntityByJavaId(packet.getEntityId());
}
if (!(holderId instanceof MobEntity mobEntity)) { if (!(holderId instanceof MobEntity mobEntity)) {
return; return;
} }
Entity attachedToId; Entity attachedToId = session.getEntityCache().getEntityByJavaId(packet.getAttachedToId());
if (packet.getAttachedToId() == session.getPlayerEntity().getEntityId()) { if (attachedToId == null || packet.getAttachedToId() == 0) {
attachedToId = session.getPlayerEntity(); // Is not being leashed
} else { mobEntity.setFlag(EntityFlag.LEASHED, false);
attachedToId = session.getEntityCache().getEntityByJavaId(packet.getAttachedToId()); mobEntity.setLeashHolderBedrockId(-1L);
if ((attachedToId == null || packet.getAttachedToId() == 0)) { mobEntity.updateBedrockMetadata();
// Is not being leashed EntityEventPacket eventPacket = new EntityEventPacket();
mobEntity.setFlag(EntityFlag.LEASHED, false); eventPacket.setRuntimeEntityId(holderId.getGeyserId());
mobEntity.setLeashHolderBedrockId(-1L); eventPacket.setType(EntityEventType.REMOVE_LEASH);
mobEntity.updateBedrockMetadata(); eventPacket.setData(0);
EntityEventPacket eventPacket = new EntityEventPacket(); session.sendUpstreamPacket(eventPacket);
eventPacket.setRuntimeEntityId(holderId.getGeyserId()); return;
eventPacket.setType(EntityEventType.REMOVE_LEASH);
eventPacket.setData(0);
session.sendUpstreamPacket(eventPacket);
return;
}
} }
mobEntity.setFlag(EntityFlag.LEASHED, true); mobEntity.setFlag(EntityFlag.LEASHED, true);

Datei anzeigen

@ -41,17 +41,12 @@ public class JavaSetEntityMotionTranslator extends PacketTranslator<ClientboundS
@Override @Override
public void translate(GeyserSession session, ClientboundSetEntityMotionPacket packet) { public void translate(GeyserSession session, ClientboundSetEntityMotionPacket packet) {
Entity entity; Entity entity = session.getEntityCache().getEntityByJavaId(packet.getEntityId());
if (packet.getEntityId() == session.getPlayerEntity().getEntityId()) {
entity = session.getPlayerEntity();
} else {
entity = session.getEntityCache().getEntityByJavaId(packet.getEntityId());
}
if (entity == null) return; if (entity == null) return;
entity.setMotion(Vector3f.from(packet.getMotionX(), packet.getMotionY(), packet.getMotionZ())); entity.setMotion(Vector3f.from(packet.getMotionX(), packet.getMotionY(), packet.getMotionZ()));
if (entity == session.getRidingVehicleEntity() && entity instanceof AbstractHorseEntity) { if (entity == session.getPlayerEntity().getVehicle() && entity instanceof AbstractHorseEntity) {
// Horses for some reason teleport back when a SetEntityMotionPacket is sent while // Horses for some reason teleport back when a SetEntityMotionPacket is sent while
// a player is riding on them. Java clients seem to ignore it anyways. // a player is riding on them. Java clients seem to ignore it anyways.
return; return;

Datei anzeigen

@ -44,13 +44,7 @@ public class JavaSetEquipmentTranslator extends PacketTranslator<ClientboundSetE
@Override @Override
public void translate(GeyserSession session, ClientboundSetEquipmentPacket packet) { public void translate(GeyserSession session, ClientboundSetEquipmentPacket packet) {
Entity entity; Entity entity = session.getEntityCache().getEntityByJavaId(packet.getEntityId());
if (packet.getEntityId() == session.getPlayerEntity().getEntityId()) {
entity = session.getPlayerEntity();
} else {
entity = session.getEntityCache().getEntityByJavaId(packet.getEntityId());
}
if (entity == null) if (entity == null)
return; return;

Datei anzeigen

@ -29,100 +29,73 @@ import com.github.steveice10.mc.protocol.packet.ingame.clientbound.entity.Client
import com.nukkitx.protocol.bedrock.data.entity.EntityData; import com.nukkitx.protocol.bedrock.data.entity.EntityData;
import com.nukkitx.protocol.bedrock.data.entity.EntityLinkData; import com.nukkitx.protocol.bedrock.data.entity.EntityLinkData;
import com.nukkitx.protocol.bedrock.packet.SetEntityLinkPacket; import com.nukkitx.protocol.bedrock.packet.SetEntityLinkPacket;
import it.unimi.dsi.fastutil.longs.LongOpenHashSet;
import org.geysermc.geyser.entity.type.Entity;
import org.geysermc.geyser.entity.EntityDefinitions; import org.geysermc.geyser.entity.EntityDefinitions;
import org.geysermc.geyser.entity.type.Entity;
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;
import org.geysermc.geyser.util.EntityUtils; import org.geysermc.geyser.util.EntityUtils;
import java.util.Arrays; import java.util.ArrayList;
import java.util.List;
@Translator(packet = ClientboundSetPassengersPacket.class) @Translator(packet = ClientboundSetPassengersPacket.class)
public class JavaSetPassengersTranslator extends PacketTranslator<ClientboundSetPassengersPacket> { public class JavaSetPassengersTranslator extends PacketTranslator<ClientboundSetPassengersPacket> {
@Override @Override
public void translate(GeyserSession session, ClientboundSetPassengersPacket packet) { public void translate(GeyserSession session, ClientboundSetPassengersPacket packet) {
Entity entity; Entity entity = session.getEntityCache().getEntityByJavaId(packet.getEntityId());
if (packet.getEntityId() == session.getPlayerEntity().getEntityId()) {
entity = session.getPlayerEntity();
} else {
entity = session.getEntityCache().getEntityByJavaId(packet.getEntityId());
}
if (entity == null) return; if (entity == null) return;
LongOpenHashSet passengers = entity.getPassengers().clone(); // Handle new/existing passengers
boolean rider = true; List<Entity> newPassengers = new ArrayList<>();
for (long passengerId : packet.getPassengerIds()) { for (long passengerId : packet.getPassengerIds()) {
Entity passenger = session.getEntityCache().getEntityByJavaId(passengerId); Entity passenger = session.getEntityCache().getEntityByJavaId(passengerId);
if (passengerId == session.getPlayerEntity().getEntityId()) { if (passenger == session.getPlayerEntity()) {
passenger = session.getPlayerEntity(); session.getPlayerEntity().setVehicle(entity);
session.setRidingVehicleEntity(entity);
// We need to confirm teleports before entering a vehicle, or else we will likely exit right out // We need to confirm teleports before entering a vehicle, or else we will likely exit right out
session.confirmTeleport(passenger.getPosition().sub(0, EntityDefinitions.PLAYER.offset(), 0).toDouble()); session.confirmTeleport(passenger.getPosition().sub(0, EntityDefinitions.PLAYER.offset(), 0).toDouble());
} }
// Passenger hasn't loaded in (likely since we're waiting for a skin response)
// and entity link needs to be set later
if (passenger == null && passengerId != 0) {
session.getEntityCache().addCachedPlayerEntityLink(passengerId, packet.getEntityId());
}
if (passenger == null) { if (passenger == null) {
// Can occur if the passenger is outside the client's tracking range
// In this case, another SetPassengers packet will be sent when the passenger is spawned.
continue; continue;
} }
boolean rider = packet.getPassengerIds()[0] == passengerId;
EntityLinkData.Type type = rider ? EntityLinkData.Type.RIDER : EntityLinkData.Type.PASSENGER; EntityLinkData.Type type = rider ? EntityLinkData.Type.RIDER : EntityLinkData.Type.PASSENGER;
SetEntityLinkPacket linkPacket = new SetEntityLinkPacket(); SetEntityLinkPacket linkPacket = new SetEntityLinkPacket();
linkPacket.setEntityLink(new EntityLinkData(entity.getGeyserId(), passenger.getGeyserId(), type, false)); linkPacket.setEntityLink(new EntityLinkData(entity.getGeyserId(), passenger.getGeyserId(), type, false, false));
session.sendUpstreamPacket(linkPacket); session.sendUpstreamPacket(linkPacket);
passengers.add(passengerId); newPassengers.add(passenger);
// Head rotation on boats
if (entity.getDefinition() == EntityDefinitions.BOAT) {
passenger.getDirtyMetadata().put(EntityData.RIDER_ROTATION_LOCKED, (byte) 1);
passenger.getDirtyMetadata().put(EntityData.RIDER_MAX_ROTATION, 90f);
passenger.getDirtyMetadata().put(EntityData.RIDER_MIN_ROTATION, 1f);
passenger.getDirtyMetadata().put(EntityData.RIDER_ROTATION_OFFSET, -90f);
} else {
passenger.getDirtyMetadata().put(EntityData.RIDER_ROTATION_LOCKED, (byte) 0);
passenger.getDirtyMetadata().put(EntityData.RIDER_MAX_ROTATION, 0f);
passenger.getDirtyMetadata().put(EntityData.RIDER_MIN_ROTATION, 0f);
}
passenger.updateBedrockMetadata();
rider = false;
}
entity.setPassengers(passengers);
for (long passengerId : entity.getPassengers()) {
Entity passenger = session.getEntityCache().getEntityByJavaId(passengerId);
if (passengerId == session.getPlayerEntity().getEntityId()) {
passenger = session.getPlayerEntity();
}
if (passenger == null) {
continue;
}
if (Arrays.stream(packet.getPassengerIds()).noneMatch(id -> id == passengerId)) {
SetEntityLinkPacket linkPacket = new SetEntityLinkPacket();
linkPacket.setEntityLink(new EntityLinkData(entity.getGeyserId(), passenger.getGeyserId(), EntityLinkData.Type.REMOVE, false));
session.sendUpstreamPacket(linkPacket);
passengers.remove(passenger.getEntityId());
passenger.getDirtyMetadata().put(EntityData.RIDER_ROTATION_LOCKED, (byte) 0);
passenger.getDirtyMetadata().put(EntityData.RIDER_MAX_ROTATION, 0f);
passenger.getDirtyMetadata().put(EntityData.RIDER_MIN_ROTATION, 0f);
passenger.getDirtyMetadata().put(EntityData.RIDER_ROTATION_OFFSET, 0f);
EntityUtils.updateMountOffset(passenger, entity, false, false, (packet.getPassengerIds().length > 1));
} else {
EntityUtils.updateMountOffset(passenger, entity, (packet.getPassengerIds()[0] == passengerId), true, (packet.getPassengerIds().length > 1));
}
passenger.setVehicle(entity);
EntityUtils.updateRiderRotationLock(passenger, entity, true);
EntityUtils.updateMountOffset(passenger, entity, rider, true, (packet.getPassengerIds().length > 1));
// Force an update to the passenger metadata // Force an update to the passenger metadata
passenger.updateBedrockMetadata(); passenger.updateBedrockMetadata();
} }
// Handle passengers that were removed
for (Entity passenger : entity.getPassengers()) {
if (passenger == null) {
continue;
}
if (!newPassengers.contains(passenger)) {
SetEntityLinkPacket linkPacket = new SetEntityLinkPacket();
linkPacket.setEntityLink(new EntityLinkData(entity.getGeyserId(), passenger.getGeyserId(), EntityLinkData.Type.REMOVE, false, false));
session.sendUpstreamPacket(linkPacket);
passenger.setVehicle(null);
EntityUtils.updateRiderRotationLock(passenger, entity, false);
EntityUtils.updateMountOffset(passenger, entity, false, false, (packet.getPassengerIds().length > 1));
// Force an update to the passenger metadata
passenger.updateBedrockMetadata();
}
}
entity.setPassengers(newPassengers);
switch (entity.getDefinition().entityType()) { switch (entity.getDefinition().entityType()) {
case HORSE, SKELETON_HORSE, DONKEY, MULE, RAVAGER -> { case HORSE, SKELETON_HORSE, DONKEY, MULE, RAVAGER -> {
entity.getDirtyMetadata().put(EntityData.RIDER_MAX_ROTATION, 181.0f); entity.getDirtyMetadata().put(EntityData.RIDER_MAX_ROTATION, 181.0f);

Datei anzeigen

@ -49,12 +49,7 @@ public class JavaTakeItemEntityTranslator extends PacketTranslator<ClientboundTa
Entity collectedEntity = session.getEntityCache().getEntityByJavaId(packet.getCollectedEntityId()); Entity collectedEntity = session.getEntityCache().getEntityByJavaId(packet.getCollectedEntityId());
if (collectedEntity == null) return; if (collectedEntity == null) return;
// Collector is the entity 'picking up' the item // Collector is the entity 'picking up' the item
Entity collectorEntity; Entity collectorEntity = session.getEntityCache().getEntityByJavaId(packet.getCollectorEntityId());
if (packet.getCollectorEntityId() == session.getPlayerEntity().getEntityId()) {
collectorEntity = session.getPlayerEntity();
} else {
collectorEntity = session.getEntityCache().getEntityByJavaId(packet.getCollectorEntityId());
}
if (collectorEntity == null) return; if (collectorEntity == null) return;
if (collectedEntity instanceof ExpOrbEntity) { if (collectedEntity instanceof ExpOrbEntity) {
// Player just picked up an experience orb // Player just picked up an experience orb

Datei anzeigen

@ -38,9 +38,6 @@ public class JavaTeleportEntityTranslator extends PacketTranslator<ClientboundTe
@Override @Override
public void translate(GeyserSession session, ClientboundTeleportEntityPacket packet) { public void translate(GeyserSession session, ClientboundTeleportEntityPacket packet) {
Entity entity = session.getEntityCache().getEntityByJavaId(packet.getEntityId()); Entity entity = session.getEntityCache().getEntityByJavaId(packet.getEntityId());
if (packet.getEntityId() == session.getPlayerEntity().getEntityId()) {
entity = session.getPlayerEntity();
}
if (entity == null) return; if (entity == null) return;
entity.teleport(Vector3f.from(packet.getX(), packet.getY(), packet.getZ()), packet.getYaw(), packet.getPitch(), packet.isOnGround()); entity.teleport(Vector3f.from(packet.getX(), packet.getY(), packet.getZ()), packet.getYaw(), packet.getPitch(), packet.isOnGround());

Datei anzeigen

@ -37,12 +37,7 @@ public class JavaUpdateAttributesTranslator extends PacketTranslator<Clientbound
@Override @Override
public void translate(GeyserSession session, ClientboundUpdateAttributesPacket packet) { public void translate(GeyserSession session, ClientboundUpdateAttributesPacket packet) {
Entity entity; Entity entity = session.getEntityCache().getEntityByJavaId(packet.getEntityId());
if (packet.getEntityId() == session.getPlayerEntity().getEntityId()) {
entity = session.getPlayerEntity();
} else {
entity = session.getEntityCache().getEntityByJavaId(packet.getEntityId());
}
if (!(entity instanceof LivingEntity livingEntity)) return; if (!(entity instanceof LivingEntity livingEntity)) return;
livingEntity.updateBedrockAttributes(session, packet.getAttributes()); livingEntity.updateBedrockAttributes(session, packet.getAttributes());

Datei anzeigen

@ -38,12 +38,9 @@ public class JavaUpdateMobEffectTranslator extends PacketTranslator<ClientboundU
@Override @Override
public void translate(GeyserSession session, ClientboundUpdateMobEffectPacket packet) { public void translate(GeyserSession session, ClientboundUpdateMobEffectPacket packet) {
Entity entity; Entity entity = session.getEntityCache().getEntityByJavaId(packet.getEntityId());
if (packet.getEntityId() == session.getPlayerEntity().getEntityId()) { if (entity == session.getPlayerEntity()) {
entity = session.getPlayerEntity();
session.getEffectCache().setEffect(packet.getEffect(), packet.getAmplifier()); session.getEffectCache().setEffect(packet.getEffect(), packet.getAmplifier());
} else {
entity = session.getEntityCache().getEntityByJavaId(packet.getEntityId());
} }
if (entity == null) if (entity == null)
return; return;

Datei anzeigen

@ -28,22 +28,22 @@ package org.geysermc.geyser.translator.protocol.java.entity.player;
import com.github.steveice10.mc.protocol.data.game.entity.player.PositionElement; import com.github.steveice10.mc.protocol.data.game.entity.player.PositionElement;
import com.github.steveice10.mc.protocol.packet.ingame.clientbound.entity.player.ClientboundPlayerPositionPacket; import com.github.steveice10.mc.protocol.packet.ingame.clientbound.entity.player.ClientboundPlayerPositionPacket;
import com.github.steveice10.mc.protocol.packet.ingame.serverbound.level.ServerboundAcceptTeleportationPacket; import com.github.steveice10.mc.protocol.packet.ingame.serverbound.level.ServerboundAcceptTeleportationPacket;
import com.github.steveice10.mc.protocol.packet.ingame.serverbound.player.ServerboundMovePlayerPosRotPacket;
import com.nukkitx.math.vector.Vector3f; import com.nukkitx.math.vector.Vector3f;
import com.nukkitx.protocol.bedrock.data.entity.EntityData;
import com.nukkitx.protocol.bedrock.data.entity.EntityLinkData; import com.nukkitx.protocol.bedrock.data.entity.EntityLinkData;
import com.nukkitx.protocol.bedrock.packet.MovePlayerPacket; import com.nukkitx.protocol.bedrock.packet.MovePlayerPacket;
import com.nukkitx.protocol.bedrock.packet.RespawnPacket; import com.nukkitx.protocol.bedrock.packet.RespawnPacket;
import com.nukkitx.protocol.bedrock.packet.SetEntityLinkPacket; import com.nukkitx.protocol.bedrock.packet.SetEntityLinkPacket;
import org.geysermc.geyser.entity.type.Entity;
import org.geysermc.geyser.entity.EntityDefinitions; import org.geysermc.geyser.entity.EntityDefinitions;
import org.geysermc.geyser.entity.type.player.PlayerEntity; import org.geysermc.geyser.entity.type.Entity;
import org.geysermc.geyser.entity.type.player.SessionPlayerEntity;
import org.geysermc.geyser.session.GeyserSession; import org.geysermc.geyser.session.GeyserSession;
import org.geysermc.geyser.session.cache.TeleportCache; import org.geysermc.geyser.session.cache.TeleportCache;
import org.geysermc.geyser.text.GeyserLocale;
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;
import org.geysermc.geyser.util.ChunkUtils; import org.geysermc.geyser.util.ChunkUtils;
import org.geysermc.geyser.util.EntityUtils; import org.geysermc.geyser.util.EntityUtils;
import org.geysermc.geyser.text.GeyserLocale;
@Translator(packet = ClientboundPlayerPositionPacket.class) @Translator(packet = ClientboundPlayerPositionPacket.class)
public class JavaPlayerPositionTranslator extends PacketTranslator<ClientboundPlayerPositionPacket> { public class JavaPlayerPositionTranslator extends PacketTranslator<ClientboundPlayerPositionPacket> {
@ -53,9 +53,10 @@ public class JavaPlayerPositionTranslator extends PacketTranslator<ClientboundPl
if (!session.isLoggedIn()) if (!session.isLoggedIn())
return; return;
PlayerEntity entity = session.getPlayerEntity(); SessionPlayerEntity entity = session.getPlayerEntity();
if (!session.isSpawned()) { if (!session.isSpawned()) {
// The server sends an absolute teleport everytime the player is respawned
Vector3f pos = Vector3f.from(packet.getX(), packet.getY(), packet.getZ()); Vector3f pos = Vector3f.from(packet.getX(), packet.getY(), packet.getZ());
entity.setPosition(pos); entity.setPosition(pos);
entity.setYaw(packet.getYaw()); entity.setYaw(packet.getYaw());
@ -78,9 +79,10 @@ public class JavaPlayerPositionTranslator extends PacketTranslator<ClientboundPl
session.sendUpstreamPacket(movePlayerPacket); session.sendUpstreamPacket(movePlayerPacket);
session.setSpawned(true); session.setSpawned(true);
// Make sure the player moves away from (0, 32767, 0) before accepting movement packets
session.setUnconfirmedTeleport(new TeleportCache(packet.getX(), packet.getY(), packet.getZ(), packet.getPitch(), packet.getYaw(), packet.getTeleportId()));
ServerboundAcceptTeleportationPacket teleportConfirmPacket = new ServerboundAcceptTeleportationPacket(packet.getTeleportId()); acceptTeleport(session, packet.getX(), packet.getY(), packet.getZ(), packet.getYaw(), packet.getPitch(), packet.getTeleportId());
session.sendDownstreamPacket(teleportConfirmPacket);
ChunkUtils.updateChunkPosition(session, pos.toInt()); ChunkUtils.updateChunkPosition(session, pos.toInt());
@ -88,22 +90,19 @@ public class JavaPlayerPositionTranslator extends PacketTranslator<ClientboundPl
return; return;
} }
session.setSpawned(true); Entity vehicle = session.getPlayerEntity().getVehicle();
if (packet.isDismountVehicle() && vehicle != null) {
if (packet.isDismountVehicle() && session.getRidingVehicleEntity() != null) {
Entity vehicle = session.getRidingVehicleEntity();
SetEntityLinkPacket linkPacket = new SetEntityLinkPacket(); SetEntityLinkPacket linkPacket = new SetEntityLinkPacket();
linkPacket.setEntityLink(new EntityLinkData(vehicle.getGeyserId(), entity.getGeyserId(), EntityLinkData.Type.REMOVE, false, false)); linkPacket.setEntityLink(new EntityLinkData(vehicle.getGeyserId(), entity.getGeyserId(), EntityLinkData.Type.REMOVE, false, false));
session.sendUpstreamPacket(linkPacket); session.sendUpstreamPacket(linkPacket);
vehicle.getPassengers().remove(entity.getEntityId());
entity.getDirtyMetadata().put(EntityData.RIDER_ROTATION_LOCKED, (byte) 0);
entity.getDirtyMetadata().put(EntityData.RIDER_MAX_ROTATION, 0f);
entity.getDirtyMetadata().put(EntityData.RIDER_MIN_ROTATION, 0f);
entity.getDirtyMetadata().put(EntityData.RIDER_ROTATION_OFFSET, 0f);
session.setRidingVehicleEntity(null);
entity.updateBedrockMetadata();
EntityUtils.updateMountOffset(entity, vehicle, false, false, entity.getPassengers().size() > 1); vehicle.getPassengers().remove(entity);
session.getPlayerEntity().setVehicle(null);
EntityUtils.updateRiderRotationLock(entity, null, false);
EntityUtils.updateMountOffset(entity, null, false, false, entity.getPassengers().size() > 1);
entity.updateBedrockMetadata();
} }
// If coordinates are relative, then add to the existing coordinate // If coordinates are relative, then add to the existing coordinate
@ -119,9 +118,9 @@ public class JavaPlayerPositionTranslator extends PacketTranslator<ClientboundPl
float newYaw = packet.getYaw() + float newYaw = packet.getYaw() +
(packet.getRelative().contains(PositionElement.YAW) ? entity.getBedrockRotation().getY() : 0); (packet.getRelative().contains(PositionElement.YAW) ? entity.getBedrockRotation().getY() : 0);
session.getGeyser().getLogger().debug("Teleport from " + entity.getPosition().getX() + " " + (entity.getPosition().getY() - EntityDefinitions.PLAYER.offset()) + " " + entity.getPosition().getZ()); int id = packet.getTeleportId();
session.addTeleport(new TeleportCache(newX, newY, newZ, newPitch, newYaw, packet.getTeleportId())); session.getGeyser().getLogger().debug("Teleport (" + id + ") from " + entity.getPosition().getX() + " " + (entity.getPosition().getY() - EntityDefinitions.PLAYER.offset()) + " " + entity.getPosition().getZ());
Vector3f lastPlayerPosition = entity.getPosition().down(EntityDefinitions.PLAYER.offset()); Vector3f lastPlayerPosition = entity.getPosition().down(EntityDefinitions.PLAYER.offset());
float lastPlayerPitch = entity.getBedrockRotation().getX(); float lastPlayerPitch = entity.getBedrockRotation().getX();
@ -131,9 +130,22 @@ public class JavaPlayerPositionTranslator extends PacketTranslator<ClientboundPl
session.getGeyser().getLogger().debug("to " + entity.getPosition().getX() + " " + (entity.getPosition().getY() - EntityDefinitions.PLAYER.offset()) + " " + entity.getPosition().getZ()); session.getGeyser().getLogger().debug("to " + entity.getPosition().getX() + " " + (entity.getPosition().getY() - EntityDefinitions.PLAYER.offset()) + " " + entity.getPosition().getZ());
// Bedrock ignores teleports that are extremely close to the player's original position and orientation, // Bedrock ignores teleports that are extremely close to the player's original position and orientation,
// so check if we can immediately confirm the teleport // so check if we need to cache the teleport
if (lastPlayerPosition.distanceSquared(teleportDestination) < 0.001 && Math.abs(newPitch - lastPlayerPitch) < 5) { if (lastPlayerPosition.distanceSquared(teleportDestination) < 0.001 && Math.abs(newPitch - lastPlayerPitch) < 5) {
session.confirmTeleport(lastPlayerPosition.toDouble()); session.setUnconfirmedTeleport(null);
} else {
session.setUnconfirmedTeleport(new TeleportCache(newX, newY, newZ, newPitch, newYaw, id));
} }
acceptTeleport(session, newX, newY, newZ, newYaw, newPitch, id);
}
private void acceptTeleport(GeyserSession session, double x, double y, double z, float yaw, float pitch, int id) {
// Confirm the teleport when we receive it to match Java edition
ServerboundAcceptTeleportationPacket teleportConfirmPacket = new ServerboundAcceptTeleportationPacket(id);
session.sendDownstreamPacket(teleportConfirmPacket);
// Servers (especially ones like Hypixel) expect exact coordinates given back to them.
ServerboundMovePlayerPosRotPacket positionPacket = new ServerboundMovePlayerPosRotPacket(false, x, y, z, yaw, pitch);
session.sendDownstreamPacket(positionPacket);
} }
} }

Datei anzeigen

@ -71,12 +71,7 @@ public class JavaAddEntityTranslator extends PacketTranslator<ClientboundAddEnti
} else if (packet.getType() == EntityType.FISHING_BOBBER) { } else if (packet.getType() == EntityType.FISHING_BOBBER) {
// Fishing bobbers need the owner for the line // Fishing bobbers need the owner for the line
int ownerEntityId = ((ProjectileData) packet.getData()).getOwnerId(); int ownerEntityId = ((ProjectileData) packet.getData()).getOwnerId();
Entity owner; Entity owner = session.getEntityCache().getEntityByJavaId(ownerEntityId);
if (session.getPlayerEntity().getEntityId() == ownerEntityId) {
owner = session.getPlayerEntity();
} else {
owner = session.getEntityCache().getEntityByJavaId(ownerEntityId);
}
// Java clients only spawn fishing hooks with a player as its owner // Java clients only spawn fishing hooks with a player as its owner
if (owner instanceof PlayerEntity) { if (owner instanceof PlayerEntity) {
entity = new FishingHookEntity(session, packet.getEntityId(), session.getEntityCache().getNextEntityId().incrementAndGet(), packet.getUuid(), entity = new FishingHookEntity(session, packet.getEntityId(), session.getEntityCache().getNextEntityId().incrementAndGet(), packet.getUuid(),

Datei anzeigen

@ -28,6 +28,7 @@ package org.geysermc.geyser.util;
import com.github.steveice10.mc.protocol.data.game.entity.Effect; import com.github.steveice10.mc.protocol.data.game.entity.Effect;
import com.github.steveice10.mc.protocol.data.game.entity.type.EntityType; import com.github.steveice10.mc.protocol.data.game.entity.type.EntityType;
import com.nukkitx.math.vector.Vector3f; import com.nukkitx.math.vector.Vector3f;
import com.nukkitx.protocol.bedrock.data.entity.EntityData;
import com.nukkitx.protocol.bedrock.data.entity.EntityFlag; import com.nukkitx.protocol.bedrock.data.entity.EntityFlag;
import org.geysermc.geyser.entity.type.Entity; import org.geysermc.geyser.entity.type.Entity;
import org.geysermc.geyser.entity.EntityDefinitions; import org.geysermc.geyser.entity.EntityDefinitions;
@ -74,7 +75,7 @@ public final class EntityUtils {
switch (mount.getDefinition().entityType()) { switch (mount.getDefinition().entityType()) {
case CHICKEN, SPIDER -> mountedHeightOffset = height * 0.5f; case CHICKEN, SPIDER -> mountedHeightOffset = height * 0.5f;
case DONKEY, MULE -> mountedHeightOffset -= 0.25f; case DONKEY, MULE -> mountedHeightOffset -= 0.25f;
case LLAMA -> mountedHeightOffset = height * 0.67f; case TRADER_LLAMA, LLAMA -> mountedHeightOffset = height * 0.6f;
case MINECART, HOPPER_MINECART, TNT_MINECART, CHEST_MINECART, FURNACE_MINECART, SPAWNER_MINECART, case MINECART, HOPPER_MINECART, TNT_MINECART, CHEST_MINECART, FURNACE_MINECART, SPAWNER_MINECART,
COMMAND_BLOCK_MINECART -> mountedHeightOffset = 0; COMMAND_BLOCK_MINECART -> mountedHeightOffset = 0;
case BOAT -> mountedHeightOffset = -0.1f; case BOAT -> mountedHeightOffset = -0.1f;
@ -144,20 +145,22 @@ public final class EntityUtils {
float yOffset = mountedHeightOffset + heightOffset; float yOffset = mountedHeightOffset + heightOffset;
float zOffset = 0; float zOffset = 0;
switch (mount.getDefinition().entityType()) { switch (mount.getDefinition().entityType()) {
case BOAT: case BOAT -> {
// Without the X offset, more than one entity on a boat is stacked on top of each other // Without the X offset, more than one entity on a boat is stacked on top of each other
if (rider && moreThanOneEntity) { if (rider && moreThanOneEntity) {
xOffset = 0.2f; xOffset = 0.2f;
} else if (moreThanOneEntity) { } else if (moreThanOneEntity) {
xOffset = -0.6f; xOffset = -0.6f;
} }
break; }
case CHICKEN: case CHICKEN -> zOffset = -0.1f;
zOffset = -0.1f; case TRADER_LLAMA, LLAMA -> zOffset = -0.3f;
break; }
case LLAMA: if (passenger.getDefinition().entityType() == EntityType.SHULKER) {
zOffset = -0.3f; switch (mount.getDefinition().entityType()) {
break; case MINECART, HOPPER_MINECART, TNT_MINECART, CHEST_MINECART, FURNACE_MINECART, SPAWNER_MINECART,
COMMAND_BLOCK_MINECART, BOAT -> yOffset = 0.1875f;
}
} }
/* /*
* Bedrock Differences * Bedrock Differences
@ -165,8 +168,10 @@ public final class EntityUtils {
* Horses are tinier * Horses are tinier
* Players, Minecarts, and Boats have different origins * Players, Minecarts, and Boats have different origins
*/ */
if (passenger.getDefinition().entityType() == EntityType.PLAYER && mount.getDefinition().entityType() != EntityType.PLAYER) { if (passenger.getDefinition().entityType() == EntityType.PLAYER) {
yOffset += EntityDefinitions.PLAYER.offset(); if (mount.getDefinition().entityType() != EntityType.PLAYER && mount.getDefinition().entityType() != EntityType.AREA_EFFECT_CLOUD) {
yOffset += EntityDefinitions.PLAYER.offset();
}
} }
switch (mount.getDefinition().entityType()) { switch (mount.getDefinition().entityType()) {
case MINECART, HOPPER_MINECART, TNT_MINECART, CHEST_MINECART, FURNACE_MINECART, SPAWNER_MINECART, case MINECART, HOPPER_MINECART, TNT_MINECART, CHEST_MINECART, FURNACE_MINECART, SPAWNER_MINECART,
@ -175,7 +180,21 @@ public final class EntityUtils {
Vector3f offset = Vector3f.from(xOffset, yOffset, zOffset); Vector3f offset = Vector3f.from(xOffset, yOffset, zOffset);
passenger.setRiderSeatPosition(offset); passenger.setRiderSeatPosition(offset);
} }
passenger.updateBedrockMetadata(); }
public static void updateRiderRotationLock(Entity passenger, Entity mount, boolean isRiding) {
if (isRiding && mount.getDefinition() == EntityDefinitions.BOAT) {
// Head rotation is locked while riding in a boat
passenger.getDirtyMetadata().put(EntityData.RIDER_ROTATION_LOCKED, (byte) 1);
passenger.getDirtyMetadata().put(EntityData.RIDER_MAX_ROTATION, 90f);
passenger.getDirtyMetadata().put(EntityData.RIDER_MIN_ROTATION, 1f);
passenger.getDirtyMetadata().put(EntityData.RIDER_ROTATION_OFFSET, -90f);
} else {
passenger.getDirtyMetadata().put(EntityData.RIDER_ROTATION_LOCKED, (byte) 0);
passenger.getDirtyMetadata().put(EntityData.RIDER_MAX_ROTATION, 0f);
passenger.getDirtyMetadata().put(EntityData.RIDER_MIN_ROTATION, 0f);
passenger.getDirtyMetadata().put(EntityData.RIDER_ROTATION_OFFSET, 0f);
}
} }
private EntityUtils() { private EntityUtils() {