Mirror von
https://github.com/GeyserMC/Geyser.git
synchronisiert 2024-11-19 14:30:17 +01:00
Reset metadata and attributes if needed when respawning (#4566)
* Reset metadata and attributes if needed when respawning * Minor edits * Reset attributes in JavaLoginTranslator * Fix client bug when updating absorption and health in the same tick
Dieser Commit ist enthalten in:
Ursprung
576a1b7d7a
Commit
815456c549
@ -51,7 +51,7 @@ public enum GeyserAttributeType {
|
|||||||
MAX_HEALTH("minecraft:generic.max_health", null, 0f, 1024f, 20f),
|
MAX_HEALTH("minecraft:generic.max_health", null, 0f, 1024f, 20f),
|
||||||
|
|
||||||
// Bedrock Attributes
|
// Bedrock Attributes
|
||||||
ABSORPTION(null, "minecraft:absorption", 0f, Float.MAX_VALUE, 0f),
|
ABSORPTION(null, "minecraft:absorption", 0f, 1024f, 0f),
|
||||||
EXHAUSTION(null, "minecraft:player.exhaustion", 0f, 5f, 0f),
|
EXHAUSTION(null, "minecraft:player.exhaustion", 0f, 5f, 0f),
|
||||||
EXPERIENCE(null, "minecraft:player.experience", 0f, 1f, 0f),
|
EXPERIENCE(null, "minecraft:player.experience", 0f, 1f, 0f),
|
||||||
EXPERIENCE_LEVEL(null, "minecraft:player.level", 0f, 24791.00f, 0f),
|
EXPERIENCE_LEVEL(null, "minecraft:player.level", 0f, 24791.00f, 0f),
|
||||||
@ -66,6 +66,10 @@ public enum GeyserAttributeType {
|
|||||||
private final float maximum;
|
private final float maximum;
|
||||||
private final float defaultValue;
|
private final float defaultValue;
|
||||||
|
|
||||||
|
public AttributeData getAttribute() {
|
||||||
|
return getAttribute(defaultValue);
|
||||||
|
}
|
||||||
|
|
||||||
public AttributeData getAttribute(float value) {
|
public AttributeData getAttribute(float value) {
|
||||||
return getAttribute(value, maximum);
|
return getAttribute(value, maximum);
|
||||||
}
|
}
|
||||||
|
@ -55,6 +55,7 @@ import org.cloudburstmc.protocol.bedrock.packet.SetEntityLinkPacket;
|
|||||||
import org.cloudburstmc.protocol.bedrock.packet.UpdateAttributesPacket;
|
import org.cloudburstmc.protocol.bedrock.packet.UpdateAttributesPacket;
|
||||||
import org.geysermc.geyser.api.entity.type.player.GeyserPlayerEntity;
|
import org.geysermc.geyser.api.entity.type.player.GeyserPlayerEntity;
|
||||||
import org.geysermc.geyser.entity.EntityDefinitions;
|
import org.geysermc.geyser.entity.EntityDefinitions;
|
||||||
|
import org.geysermc.geyser.entity.attribute.GeyserAttributeType;
|
||||||
import org.geysermc.geyser.entity.type.Entity;
|
import org.geysermc.geyser.entity.type.Entity;
|
||||||
import org.geysermc.geyser.entity.type.LivingEntity;
|
import org.geysermc.geyser.entity.type.LivingEntity;
|
||||||
import org.geysermc.geyser.entity.type.living.animal.tameable.ParrotEntity;
|
import org.geysermc.geyser.entity.type.living.animal.tameable.ParrotEntity;
|
||||||
@ -283,7 +284,7 @@ public class PlayerEntity extends LivingEntity implements GeyserPlayerEntity {
|
|||||||
attributesPacket.setRuntimeEntityId(geyserId);
|
attributesPacket.setRuntimeEntityId(geyserId);
|
||||||
// Setting to a higher maximum since plugins/datapacks can probably extend the Bedrock soft limit
|
// Setting to a higher maximum since plugins/datapacks can probably extend the Bedrock soft limit
|
||||||
attributesPacket.setAttributes(Collections.singletonList(
|
attributesPacket.setAttributes(Collections.singletonList(
|
||||||
new AttributeData("minecraft:absorption", 0.0f, 1024f, entityMetadata.getPrimitiveValue(), 0.0f)));
|
GeyserAttributeType.ABSORPTION.getAttribute(entityMetadata.getPrimitiveValue())));
|
||||||
session.sendUpstreamPacket(attributesPacket);
|
session.sendUpstreamPacket(attributesPacket);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -307,7 +308,7 @@ public class PlayerEntity extends LivingEntity implements GeyserPlayerEntity {
|
|||||||
* Sets the parrot occupying the shoulder. Bedrock Edition requires a full entity whereas Java Edition just
|
* Sets the parrot occupying the shoulder. Bedrock Edition requires a full entity whereas Java Edition just
|
||||||
* spawns it from the NBT data provided
|
* spawns it from the NBT data provided
|
||||||
*/
|
*/
|
||||||
private void setParrot(CompoundTag tag, boolean isLeft) {
|
protected void setParrot(CompoundTag tag, boolean isLeft) {
|
||||||
if (tag != null && !tag.isEmpty()) {
|
if (tag != null && !tag.isEmpty()) {
|
||||||
if ((isLeft && leftParrot != null) || (!isLeft && rightParrot != null)) {
|
if ((isLeft && leftParrot != null) || (!isLeft && rightParrot != null)) {
|
||||||
// No need to update a parrot's data when it already exists
|
// No need to update a parrot's data when it already exists
|
||||||
|
@ -30,6 +30,7 @@ import com.github.steveice10.mc.protocol.data.game.entity.attribute.AttributeTyp
|
|||||||
import com.github.steveice10.mc.protocol.data.game.entity.metadata.GlobalPos;
|
import com.github.steveice10.mc.protocol.data.game.entity.metadata.GlobalPos;
|
||||||
import com.github.steveice10.mc.protocol.data.game.entity.metadata.Pose;
|
import com.github.steveice10.mc.protocol.data.game.entity.metadata.Pose;
|
||||||
import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.ByteEntityMetadata;
|
import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.ByteEntityMetadata;
|
||||||
|
import com.github.steveice10.mc.protocol.data.game.entity.metadata.type.FloatEntityMetadata;
|
||||||
import com.github.steveice10.mc.protocol.data.game.entity.player.GameMode;
|
import com.github.steveice10.mc.protocol.data.game.entity.player.GameMode;
|
||||||
import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;
|
import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
@ -255,13 +256,51 @@ public class SessionPlayerEntity extends PlayerEntity {
|
|||||||
return session.getAuthData().uuid();
|
return session.getAuthData().uuid();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setAbsorptionHearts(FloatEntityMetadata entityMetadata) {
|
||||||
|
// The bedrock client can glitch when sending a health and absorption attribute in the same tick
|
||||||
|
// This can happen when switching servers. Resending the absorption attribute fixes the issue
|
||||||
|
attributes.put(GeyserAttributeType.ABSORPTION, GeyserAttributeType.ABSORPTION.getAttribute(entityMetadata.getPrimitiveValue()));
|
||||||
|
super.setAbsorptionHearts(entityMetadata);
|
||||||
|
}
|
||||||
|
|
||||||
public void resetMetadata() {
|
public void resetMetadata() {
|
||||||
// Reset all metadata to their default values
|
// Reset all metadata to their default values
|
||||||
// This is used when a player respawns
|
// This is used when a player respawns
|
||||||
|
this.flags.clear();
|
||||||
this.initializeMetadata();
|
this.initializeMetadata();
|
||||||
|
|
||||||
// Reset air
|
// Reset air
|
||||||
this.resetAir();
|
this.resetAir();
|
||||||
|
|
||||||
|
// Explicitly reset all metadata not handled by initializeMetadata
|
||||||
|
setParrot(null, true);
|
||||||
|
setParrot(null, false);
|
||||||
|
|
||||||
|
// Absorption is metadata in java edition
|
||||||
|
attributes.remove(GeyserAttributeType.ABSORPTION);
|
||||||
|
UpdateAttributesPacket attributesPacket = new UpdateAttributesPacket();
|
||||||
|
attributesPacket.setRuntimeEntityId(geyserId);
|
||||||
|
attributesPacket.setAttributes(Collections.singletonList(
|
||||||
|
GeyserAttributeType.ABSORPTION.getAttribute(0f)));
|
||||||
|
session.sendUpstreamPacket(attributesPacket);
|
||||||
|
|
||||||
|
dirtyMetadata.put(EntityDataTypes.EFFECT_COLOR, 0);
|
||||||
|
dirtyMetadata.put(EntityDataTypes.EFFECT_AMBIENCE, (byte) 0);
|
||||||
|
dirtyMetadata.put(EntityDataTypes.FREEZING_EFFECT_STRENGTH, 0f);
|
||||||
|
|
||||||
|
silent = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void resetAttributes() {
|
||||||
|
attributes.clear();
|
||||||
|
maxHealth = GeyserAttributeType.MAX_HEALTH.getDefaultValue();
|
||||||
|
|
||||||
|
UpdateAttributesPacket attributesPacket = new UpdateAttributesPacket();
|
||||||
|
attributesPacket.setRuntimeEntityId(geyserId);
|
||||||
|
attributesPacket.setAttributes(Collections.singletonList(
|
||||||
|
GeyserAttributeType.MOVEMENT_SPEED.getAttribute()));
|
||||||
|
session.sendUpstreamPacket(attributesPacket);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void resetAir() {
|
public void resetAir() {
|
||||||
|
@ -712,7 +712,7 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource {
|
|||||||
// Default move speed
|
// Default move speed
|
||||||
// Bedrock clients move very fast by default until they get an attribute packet correcting the speed
|
// Bedrock clients move very fast by default until they get an attribute packet correcting the speed
|
||||||
attributesPacket.setAttributes(Collections.singletonList(
|
attributesPacket.setAttributes(Collections.singletonList(
|
||||||
new AttributeData("minecraft:movement", 0.0f, 1024f, 0.1f, 0.1f)));
|
GeyserAttributeType.MOVEMENT_SPEED.getAttribute()));
|
||||||
upstream.sendPacket(attributesPacket);
|
upstream.sendPacket(attributesPacket);
|
||||||
|
|
||||||
GameRulesChangedPacket gamerulePacket = new GameRulesChangedPacket();
|
GameRulesChangedPacket gamerulePacket = new GameRulesChangedPacket();
|
||||||
|
@ -71,7 +71,7 @@ public class JavaLoginTranslator extends PacketTranslator<ClientboundLoginPacket
|
|||||||
// Remove all bossbars
|
// Remove all bossbars
|
||||||
session.getEntityCache().removeAllBossBars();
|
session.getEntityCache().removeAllBossBars();
|
||||||
// Remove extra hearts, hunger, etc.
|
// Remove extra hearts, hunger, etc.
|
||||||
entity.getAttributes().clear();
|
entity.resetAttributes();
|
||||||
entity.resetMetadata();
|
entity.resetMetadata();
|
||||||
|
|
||||||
// Reset weather
|
// Reset weather
|
||||||
|
@ -49,6 +49,14 @@ public class JavaRespawnTranslator extends PacketTranslator<ClientboundRespawnPa
|
|||||||
SessionPlayerEntity entity = session.getPlayerEntity();
|
SessionPlayerEntity entity = session.getPlayerEntity();
|
||||||
PlayerSpawnInfo spawnInfo = packet.getCommonPlayerSpawnInfo();
|
PlayerSpawnInfo spawnInfo = packet.getCommonPlayerSpawnInfo();
|
||||||
|
|
||||||
|
if (!packet.isKeepMetadata()) {
|
||||||
|
entity.resetMetadata();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!packet.isKeepAttributes()) {
|
||||||
|
entity.resetAttributes();
|
||||||
|
}
|
||||||
|
|
||||||
session.setSpawned(false);
|
session.setSpawned(false);
|
||||||
|
|
||||||
entity.setHealth(entity.getMaxHealth());
|
entity.setHealth(entity.getMaxHealth());
|
||||||
|
Laden…
In neuem Issue referenzieren
Einen Benutzer sperren