From 7cd941e5d6094d9d00f54ecf88b3f1a3001baa2a Mon Sep 17 00:00:00 2001 From: Marco Date: Sat, 18 Apr 2020 15:48:21 +0200 Subject: [PATCH] Fix BossBars --- .../network/session/cache/BossBar.java | 104 ++++++++++++++++++ .../network/session/cache/EntityCache.java | 26 +++-- .../bedrock/BedrockActionTranslator.java | 1 + .../java/JavaBossBarTranslator.java | 61 ++-------- 4 files changed, 130 insertions(+), 62 deletions(-) create mode 100644 connector/src/main/java/org/geysermc/connector/network/session/cache/BossBar.java diff --git a/connector/src/main/java/org/geysermc/connector/network/session/cache/BossBar.java b/connector/src/main/java/org/geysermc/connector/network/session/cache/BossBar.java new file mode 100644 index 000000000..8ff2c9459 --- /dev/null +++ b/connector/src/main/java/org/geysermc/connector/network/session/cache/BossBar.java @@ -0,0 +1,104 @@ +package org.geysermc.connector.network.session.cache; + +import com.github.steveice10.mc.protocol.data.message.Message; +import com.nukkitx.math.vector.Vector3f; +import com.nukkitx.protocol.bedrock.data.EntityData; +import com.nukkitx.protocol.bedrock.packet.AddEntityPacket; +import com.nukkitx.protocol.bedrock.packet.BossEventPacket; +import com.nukkitx.protocol.bedrock.packet.RemoveEntityPacket; +import org.geysermc.connector.network.session.GeyserSession; +import org.geysermc.connector.utils.MessageUtils; + +public class BossBar { + + private GeyserSession session; + + private long entityId; + private Message title; + private float health; + private int color; + private int overlay; + private int darkenSky; + + public BossBar(GeyserSession session, Message title, float health, int color, int overlay, int darkenSky) { + this.session = session; + this.entityId = session.getEntityCache().getNextEntityId().incrementAndGet(); + this.title = title; + this.health = health; + this.color = color; + this.overlay = overlay; + this.darkenSky = darkenSky; + } + + public void addBossBar() { + addBossEntity(); + updateBossBar(); + } + + public void updateBossBar() { + BossEventPacket bossEventPacket = new BossEventPacket(); + bossEventPacket.setBossUniqueEntityId(entityId); + bossEventPacket.setAction(BossEventPacket.Action.SHOW); + bossEventPacket.setTitle(MessageUtils.getTranslatedBedrockMessage(title, session.getClientData().getLanguageCode())); + bossEventPacket.setHealthPercentage(health); + bossEventPacket.setColor(color); //ignored by client + bossEventPacket.setOverlay(overlay); + bossEventPacket.setDarkenSky(darkenSky); + + session.getUpstream().sendPacket(bossEventPacket); + } + + public void updateTitle(Message title) { + this.title = title; + BossEventPacket bossEventPacket = new BossEventPacket(); + bossEventPacket.setBossUniqueEntityId(entityId); + bossEventPacket.setAction(BossEventPacket.Action.TITLE); + bossEventPacket.setTitle(MessageUtils.getTranslatedBedrockMessage(title, session.getClientData().getLanguageCode())); + + session.getUpstream().sendPacket(bossEventPacket); + } + + public void updateHealth(float health) { + this.health = health; + BossEventPacket bossEventPacket = new BossEventPacket(); + bossEventPacket.setBossUniqueEntityId(entityId); + bossEventPacket.setAction(BossEventPacket.Action.HEALTH_PERCENTAGE); + bossEventPacket.setHealthPercentage(health); + + session.getUpstream().sendPacket(bossEventPacket); + } + + public void removeBossBar() { + BossEventPacket bossEventPacket = new BossEventPacket(); + bossEventPacket.setBossUniqueEntityId(entityId); + bossEventPacket.setAction(BossEventPacket.Action.HIDE); + + session.getUpstream().sendPacket(bossEventPacket); + removeBossEntity(); + } + + /** + * Bedrock still needs an entity to display the BossBar.
+ * Just like 1.8 but it doesn't care about which entity + */ + private void addBossEntity() { + AddEntityPacket addEntityPacket = new AddEntityPacket(); + addEntityPacket.setUniqueEntityId(entityId); + addEntityPacket.setRuntimeEntityId(entityId); + addEntityPacket.setIdentifier("minecraft:creeper"); + addEntityPacket.setEntityType(33); + addEntityPacket.setPosition(session.getPlayerEntity().getPosition()); + addEntityPacket.setRotation(Vector3f.ZERO); + addEntityPacket.setMotion(Vector3f.ZERO); + addEntityPacket.getMetadata().put(EntityData.SCALE, 0.01F); // scale = 0 doesn't work? + + session.getUpstream().sendPacket(addEntityPacket); + } + + private void removeBossEntity() { + RemoveEntityPacket removeEntityPacket = new RemoveEntityPacket(); + removeEntityPacket.setUniqueEntityId(entityId); + + session.getUpstream().sendPacket(removeEntityPacket); + } +} diff --git a/connector/src/main/java/org/geysermc/connector/network/session/cache/EntityCache.java b/connector/src/main/java/org/geysermc/connector/network/session/cache/EntityCache.java index f32ee2a5c..f0b394fd5 100644 --- a/connector/src/main/java/org/geysermc/connector/network/session/cache/EntityCache.java +++ b/connector/src/main/java/org/geysermc/connector/network/session/cache/EntityCache.java @@ -48,7 +48,7 @@ public class EntityCache { private Long2ObjectMap entities = Long2ObjectMaps.synchronize(new Long2ObjectOpenHashMap<>()); private Long2LongMap entityIdTranslations = Long2LongMaps.synchronize(new Long2LongOpenHashMap()); private Map playerEntities = Collections.synchronizedMap(new HashMap<>()); - private Object2LongMap bossbars = new Object2LongOpenHashMap<>(); + private Map bossBars = Collections.synchronizedMap(new HashMap<>()); @Getter private AtomicLong nextEntityId = new AtomicLong(2L); @@ -116,24 +116,30 @@ public class EntityCache { playerEntities.remove(uuid); } - public long addBossBar(UUID uuid) { - long entityId = getNextEntityId().incrementAndGet(); - bossbars.put(uuid, entityId); - return entityId; + public void addBossBar(UUID uuid, BossBar bossBar) { + bossBars.put(uuid, bossBar); + bossBar.addBossBar(); } - public long getBossBar(UUID uuid) { - return bossbars.containsKey(uuid) ? bossbars.get(uuid) : -1; + public BossBar getBossBar(UUID uuid) { + return bossBars.get(uuid); } - public long removeBossBar(UUID uuid) { - return bossbars.remove(uuid); + public void removeBossBar(UUID uuid) { + BossBar bossBar = bossBars.remove(uuid); + if (bossBar != null) { + bossBar.removeBossBar(); + } + } + + public void updateBossBars() { + bossBars.values().forEach(BossBar::updateBossBar); } public void clear() { entities = null; entityIdTranslations = null; playerEntities = null; - bossbars = null; + bossBars = null; } } diff --git a/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockActionTranslator.java b/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockActionTranslator.java index 206f42d1f..7ab713893 100644 --- a/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockActionTranslator.java +++ b/connector/src/main/java/org/geysermc/connector/network/translators/bedrock/BedrockActionTranslator.java @@ -123,6 +123,7 @@ public class BedrockActionTranslator extends PacketTranslator { @Override public void translate(ServerBossBarPacket packet, GeyserSession session) { - BossEventPacket bossEventPacket = new BossEventPacket(); - bossEventPacket.setBossUniqueEntityId(session.getEntityCache().getBossBar(packet.getUuid())); - + BossBar bossBar = session.getEntityCache().getBossBar(packet.getUuid()); switch (packet.getAction()) { case ADD: - long entityId = session.getEntityCache().addBossBar(packet.getUuid()); - addBossEntity(session, entityId); - - bossEventPacket.setAction(BossEventPacket.Action.SHOW); - bossEventPacket.setBossUniqueEntityId(entityId); - bossEventPacket.setTitle(MessageUtils.getTranslatedBedrockMessage(packet.getTitle(), session.getClientData().getLanguageCode())); - bossEventPacket.setHealthPercentage(packet.getHealth()); - bossEventPacket.setColor(0); //ignored by client - bossEventPacket.setOverlay(1); - bossEventPacket.setDarkenSky(0); + bossBar = new BossBar(session, packet.getTitle(), packet.getHealth(), Color.RED.getRGB(), 1, 0); + session.getEntityCache().addBossBar(packet.getUuid(), bossBar); break; case UPDATE_TITLE: - bossEventPacket.setAction(BossEventPacket.Action.TITLE); - bossEventPacket.setTitle(MessageUtils.getTranslatedBedrockMessage(packet.getTitle(), session.getClientData().getLanguageCode())); + if (bossBar != null) bossBar.updateTitle(packet.getTitle()); break; case UPDATE_HEALTH: - bossEventPacket.setAction(BossEventPacket.Action.HEALTH_PERCENTAGE); - bossEventPacket.setHealthPercentage(packet.getHealth()); + if (bossBar != null) bossBar.updateHealth(packet.getHealth()); break; case REMOVE: - bossEventPacket.setAction(BossEventPacket.Action.HIDE); - removeBossEntity(session, session.getEntityCache().removeBossBar(packet.getUuid())); + session.getEntityCache().removeBossBar(packet.getUuid()); break; case UPDATE_STYLE: case UPDATE_FLAGS: //todo return; } - - session.getUpstream().sendPacket(bossEventPacket); - } - - /** - * Bedrock still needs an entity to display the BossBar.
- * Just like 1.8 but it doesn't care about which entity - */ - private void addBossEntity(GeyserSession session, long entityId) { - AddEntityPacket addEntityPacket = new AddEntityPacket(); - addEntityPacket.setUniqueEntityId(entityId); - addEntityPacket.setRuntimeEntityId(entityId); - addEntityPacket.setIdentifier("minecraft:creeper"); - addEntityPacket.setEntityType(33); - addEntityPacket.setPosition(session.getPlayerEntity().getPosition()); - addEntityPacket.setRotation(Vector3f.ZERO); - addEntityPacket.setMotion(Vector3f.ZERO); - addEntityPacket.getMetadata().put(EntityData.SCALE, 0.01F); // scale = 0 doesn't work? - - session.getUpstream().sendPacket(addEntityPacket); - } - - private void removeBossEntity(GeyserSession session, long entityId) { - RemoveEntityPacket removeEntityPacket = new RemoveEntityPacket(); - removeEntityPacket.setUniqueEntityId(entityId); - - session.getUpstream().sendPacket(removeEntityPacket); } }