mirror of
https://github.com/GeyserMC/Geyser.git
synced 2024-08-14 23:57:35 +00:00
parent
50896a24e7
commit
86c0c009e7
5 changed files with 145 additions and 10 deletions
|
@ -28,6 +28,7 @@ package org.geysermc.connector.entity.player;
|
||||||
import com.github.steveice10.mc.auth.data.GameProfile;
|
import com.github.steveice10.mc.auth.data.GameProfile;
|
||||||
import com.github.steveice10.mc.protocol.data.game.entity.metadata.EntityMetadata;
|
import com.github.steveice10.mc.protocol.data.game.entity.metadata.EntityMetadata;
|
||||||
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.scoreboard.ScoreboardPosition;
|
||||||
import com.github.steveice10.opennbt.tag.builtin.CompoundTag;
|
import com.github.steveice10.opennbt.tag.builtin.CompoundTag;
|
||||||
import com.nukkitx.math.vector.Vector3f;
|
import com.nukkitx.math.vector.Vector3f;
|
||||||
import com.nukkitx.math.vector.Vector3i;
|
import com.nukkitx.math.vector.Vector3i;
|
||||||
|
@ -37,10 +38,7 @@ import com.nukkitx.protocol.bedrock.data.command.CommandPermission;
|
||||||
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.data.entity.EntityLinkData;
|
import com.nukkitx.protocol.bedrock.data.entity.EntityLinkData;
|
||||||
import com.nukkitx.protocol.bedrock.packet.AddPlayerPacket;
|
import com.nukkitx.protocol.bedrock.packet.*;
|
||||||
import com.nukkitx.protocol.bedrock.packet.MovePlayerPacket;
|
|
||||||
import com.nukkitx.protocol.bedrock.packet.SetEntityLinkPacket;
|
|
||||||
import com.nukkitx.protocol.bedrock.packet.UpdateAttributesPacket;
|
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import lombok.Setter;
|
import lombok.Setter;
|
||||||
import net.kyori.adventure.text.Component;
|
import net.kyori.adventure.text.Component;
|
||||||
|
@ -50,7 +48,10 @@ import org.geysermc.connector.entity.living.animal.tameable.ParrotEntity;
|
||||||
import org.geysermc.connector.entity.type.EntityType;
|
import org.geysermc.connector.entity.type.EntityType;
|
||||||
import org.geysermc.connector.network.session.GeyserSession;
|
import org.geysermc.connector.network.session.GeyserSession;
|
||||||
import org.geysermc.connector.network.translators.chat.MessageTranslator;
|
import org.geysermc.connector.network.translators.chat.MessageTranslator;
|
||||||
|
import org.geysermc.connector.scoreboard.Objective;
|
||||||
|
import org.geysermc.connector.scoreboard.Score;
|
||||||
import org.geysermc.connector.scoreboard.Team;
|
import org.geysermc.connector.scoreboard.Team;
|
||||||
|
import org.geysermc.connector.scoreboard.UpdateType;
|
||||||
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
@ -85,6 +86,12 @@ public class PlayerEntity extends LivingEntity {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void spawnEntity(GeyserSession session) {
|
public void spawnEntity(GeyserSession session) {
|
||||||
|
// Check to see if the player should have a belowname counterpart added
|
||||||
|
Objective objective = session.getWorldCache().getScoreboard().getObjectiveSlots().get(ScoreboardPosition.BELOW_NAME);
|
||||||
|
if (objective != null) {
|
||||||
|
setBelowNameText(session, objective);
|
||||||
|
}
|
||||||
|
|
||||||
AddPlayerPacket addPlayerPacket = new AddPlayerPacket();
|
AddPlayerPacket addPlayerPacket = new AddPlayerPacket();
|
||||||
addPlayerPacket.setUuid(uuid);
|
addPlayerPacket.setUuid(uuid);
|
||||||
addPlayerPacket.setUsername(username);
|
addPlayerPacket.setUsername(username);
|
||||||
|
@ -326,4 +333,34 @@ public class PlayerEntity extends LivingEntity {
|
||||||
metadata.put(EntityData.BOUNDING_BOX_WIDTH, entityType.getWidth());
|
metadata.put(EntityData.BOUNDING_BOX_WIDTH, entityType.getWidth());
|
||||||
metadata.put(EntityData.BOUNDING_BOX_HEIGHT, height);
|
metadata.put(EntityData.BOUNDING_BOX_HEIGHT, height);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setBelowNameText(GeyserSession session, Objective objective) {
|
||||||
|
if (objective != null && objective.getUpdateType() != UpdateType.REMOVE) {
|
||||||
|
int amount;
|
||||||
|
Score score = objective.getScores().get(username);
|
||||||
|
if (score != null) {
|
||||||
|
amount = score.getCurrentData().getScore();
|
||||||
|
} else {
|
||||||
|
amount = 0;
|
||||||
|
}
|
||||||
|
String displayString = amount + " " + objective.getDisplayName();
|
||||||
|
|
||||||
|
metadata.put(EntityData.SCORE_TAG, displayString);
|
||||||
|
if (valid) {
|
||||||
|
// Already spawned - we still need to run the rest of this code because the spawn packet will be
|
||||||
|
// providing the information
|
||||||
|
SetEntityDataPacket packet = new SetEntityDataPacket();
|
||||||
|
packet.setRuntimeEntityId(geyserId);
|
||||||
|
packet.getMetadata().put(EntityData.SCORE_TAG, displayString);
|
||||||
|
session.sendUpstreamPacket(packet);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (valid && metadata.remove(EntityData.SCORE_TAG) != null) {
|
||||||
|
SetEntityDataPacket packet = new SetEntityDataPacket();
|
||||||
|
packet.setRuntimeEntityId(geyserId);
|
||||||
|
packet.getMetadata().put(EntityData.SCORE_TAG, "");
|
||||||
|
session.sendUpstreamPacket(packet);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -138,6 +138,10 @@ public class EntityCache {
|
||||||
return playerEntities.remove(uuid);
|
return playerEntities.remove(uuid);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Collection<PlayerEntity> getAllPlayerEntities() {
|
||||||
|
return playerEntities.values();
|
||||||
|
}
|
||||||
|
|
||||||
public void addBossBar(UUID uuid, BossBar bossBar) {
|
public void addBossBar(UUID uuid, BossBar bossBar) {
|
||||||
bossBars.put(uuid, bossBar);
|
bossBars.put(uuid, bossBar);
|
||||||
bossBar.addBossBar();
|
bossBar.addBossBar();
|
||||||
|
|
|
@ -26,9 +26,11 @@
|
||||||
package org.geysermc.connector.network.translators.java.scoreboard;
|
package org.geysermc.connector.network.translators.java.scoreboard;
|
||||||
|
|
||||||
import com.github.steveice10.mc.protocol.data.game.scoreboard.ObjectiveAction;
|
import com.github.steveice10.mc.protocol.data.game.scoreboard.ObjectiveAction;
|
||||||
|
import com.github.steveice10.mc.protocol.data.game.scoreboard.ScoreboardPosition;
|
||||||
import com.github.steveice10.mc.protocol.packet.ingame.server.scoreboard.ServerScoreboardObjectivePacket;
|
import com.github.steveice10.mc.protocol.packet.ingame.server.scoreboard.ServerScoreboardObjectivePacket;
|
||||||
import org.geysermc.connector.GeyserConnector;
|
import org.geysermc.connector.GeyserConnector;
|
||||||
import org.geysermc.connector.GeyserLogger;
|
import org.geysermc.connector.GeyserLogger;
|
||||||
|
import org.geysermc.connector.entity.player.PlayerEntity;
|
||||||
import org.geysermc.connector.network.session.GeyserSession;
|
import org.geysermc.connector.network.session.GeyserSession;
|
||||||
import org.geysermc.connector.network.session.cache.WorldCache;
|
import org.geysermc.connector.network.session.cache.WorldCache;
|
||||||
import org.geysermc.connector.network.translators.PacketTranslator;
|
import org.geysermc.connector.network.translators.PacketTranslator;
|
||||||
|
@ -63,7 +65,20 @@ public class JavaScoreboardObjectiveTranslator extends PacketTranslator<ServerSc
|
||||||
switch (packet.getAction()) {
|
switch (packet.getAction()) {
|
||||||
case ADD, UPDATE -> objective.setDisplayName(MessageTranslator.convertMessage(packet.getDisplayName()))
|
case ADD, UPDATE -> objective.setDisplayName(MessageTranslator.convertMessage(packet.getDisplayName()))
|
||||||
.setType(packet.getType().ordinal());
|
.setType(packet.getType().ordinal());
|
||||||
case REMOVE -> scoreboard.unregisterObjective(packet.getName());
|
case REMOVE -> {
|
||||||
|
scoreboard.unregisterObjective(packet.getName());
|
||||||
|
if (objective != null && objective == scoreboard.getObjectiveSlots().get(ScoreboardPosition.BELOW_NAME)) {
|
||||||
|
// Clear the score tag from all players
|
||||||
|
for (PlayerEntity entity : session.getEntityCache().getAllPlayerEntities()) {
|
||||||
|
if (!entity.isValid()) {
|
||||||
|
// Player hasn't spawned yet - don't bother
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
entity.setBelowNameText(session, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (objective == null || !objective.isActive()) {
|
if (objective == null || !objective.isActive()) {
|
||||||
|
|
|
@ -26,9 +26,13 @@
|
||||||
package org.geysermc.connector.network.translators.java.scoreboard;
|
package org.geysermc.connector.network.translators.java.scoreboard;
|
||||||
|
|
||||||
import com.github.steveice10.mc.protocol.data.game.scoreboard.ScoreboardAction;
|
import com.github.steveice10.mc.protocol.data.game.scoreboard.ScoreboardAction;
|
||||||
|
import com.github.steveice10.mc.protocol.data.game.scoreboard.ScoreboardPosition;
|
||||||
import com.github.steveice10.mc.protocol.packet.ingame.server.scoreboard.ServerUpdateScorePacket;
|
import com.github.steveice10.mc.protocol.packet.ingame.server.scoreboard.ServerUpdateScorePacket;
|
||||||
|
import com.nukkitx.protocol.bedrock.data.entity.EntityData;
|
||||||
|
import com.nukkitx.protocol.bedrock.packet.SetEntityDataPacket;
|
||||||
import org.geysermc.connector.GeyserConnector;
|
import org.geysermc.connector.GeyserConnector;
|
||||||
import org.geysermc.connector.GeyserLogger;
|
import org.geysermc.connector.GeyserLogger;
|
||||||
|
import org.geysermc.connector.entity.player.PlayerEntity;
|
||||||
import org.geysermc.connector.network.session.GeyserSession;
|
import org.geysermc.connector.network.session.GeyserSession;
|
||||||
import org.geysermc.connector.network.session.cache.WorldCache;
|
import org.geysermc.connector.network.session.cache.WorldCache;
|
||||||
import org.geysermc.connector.network.translators.PacketTranslator;
|
import org.geysermc.connector.network.translators.PacketTranslator;
|
||||||
|
@ -58,19 +62,40 @@ public class JavaUpdateScoreTranslator extends PacketTranslator<ServerUpdateScor
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If this is the objective that is in use to show the below name text, we need to update the player
|
||||||
|
// attached to this score.
|
||||||
|
boolean isBelowName = objective != null && objective == scoreboard.getObjectiveSlots().get(ScoreboardPosition.BELOW_NAME);
|
||||||
|
|
||||||
switch (packet.getAction()) {
|
switch (packet.getAction()) {
|
||||||
case ADD_OR_UPDATE:
|
case ADD_OR_UPDATE -> {
|
||||||
objective.setScore(packet.getEntry(), packet.getValue());
|
objective.setScore(packet.getEntry(), packet.getValue());
|
||||||
break;
|
if (isBelowName) {
|
||||||
case REMOVE:
|
// Update the below name score on this player
|
||||||
|
setBelowName(session, objective, packet.getEntry(), packet.getValue());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case REMOVE -> {
|
||||||
|
if (packet.getObjective().isEmpty()) {
|
||||||
|
// An empty objective name means all scores are reset for that player (/scoreboard players reset PLAYERNAME)
|
||||||
|
Objective belowName = scoreboard.getObjectiveSlots().get(ScoreboardPosition.BELOW_NAME);
|
||||||
|
if (belowName != null) {
|
||||||
|
setBelowName(session, belowName, packet.getEntry(), 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (objective != null) {
|
if (objective != null) {
|
||||||
objective.removeScore(packet.getEntry());
|
objective.removeScore(packet.getEntry());
|
||||||
|
|
||||||
|
if (isBelowName) {
|
||||||
|
// Update the score on this player to now reflect 0
|
||||||
|
setBelowName(session, objective, packet.getEntry(), 0);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
for (Objective objective1 : scoreboard.getObjectives()) {
|
for (Objective objective1 : scoreboard.getObjectives()) {
|
||||||
objective1.removeScore(packet.getEntry());
|
objective1.removeScore(packet.getEntry());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ScoreboardUpdater will handle it for us if the packets per second
|
// ScoreboardUpdater will handle it for us if the packets per second
|
||||||
|
@ -79,4 +104,43 @@ public class JavaUpdateScoreTranslator extends PacketTranslator<ServerUpdateScor
|
||||||
scoreboard.onUpdate();
|
scoreboard.onUpdate();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param objective the objective that currently resides on the below name display slot
|
||||||
|
*/
|
||||||
|
private void setBelowName(GeyserSession session, Objective objective, String username, int count) {
|
||||||
|
PlayerEntity entity = getPlayerEntity(session, username);
|
||||||
|
if (entity == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
String displayString = count + " " + objective.getDisplayName();
|
||||||
|
|
||||||
|
// Of note: unlike Bedrock, if there is an objective in the below name slot, everyone has a display
|
||||||
|
entity.getMetadata().put(EntityData.SCORE_TAG, displayString);
|
||||||
|
SetEntityDataPacket entityDataPacket = new SetEntityDataPacket();
|
||||||
|
entityDataPacket.setRuntimeEntityId(entity.getGeyserId());
|
||||||
|
entityDataPacket.getMetadata().put(EntityData.SCORE_TAG, displayString);
|
||||||
|
session.sendUpstreamPacket(entityDataPacket);
|
||||||
|
}
|
||||||
|
|
||||||
|
private PlayerEntity getPlayerEntity(GeyserSession session, String username) {
|
||||||
|
// We don't care about the session player, because... they're not going to be seeing their own score
|
||||||
|
if (session.getPlayerEntity().getUsername().equals(username)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (PlayerEntity entity : session.getEntityCache().getAllPlayerEntities()) {
|
||||||
|
if (entity.getUsername().equals(username)) {
|
||||||
|
if (entity.isValid()) {
|
||||||
|
return entity;
|
||||||
|
} else {
|
||||||
|
// The below name text will be applied on spawn
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,6 +33,7 @@ import com.nukkitx.protocol.bedrock.packet.SetScorePacket;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import org.geysermc.connector.GeyserConnector;
|
import org.geysermc.connector.GeyserConnector;
|
||||||
import org.geysermc.connector.GeyserLogger;
|
import org.geysermc.connector.GeyserLogger;
|
||||||
|
import org.geysermc.connector.entity.player.PlayerEntity;
|
||||||
import org.geysermc.connector.network.session.GeyserSession;
|
import org.geysermc.connector.network.session.GeyserSession;
|
||||||
import org.geysermc.connector.utils.LanguageUtils;
|
import org.geysermc.connector.utils.LanguageUtils;
|
||||||
|
|
||||||
|
@ -49,7 +50,8 @@ public final class Scoreboard {
|
||||||
private final AtomicLong nextId = new AtomicLong(0);
|
private final AtomicLong nextId = new AtomicLong(0);
|
||||||
|
|
||||||
private final Map<String, Objective> objectives = new ConcurrentHashMap<>();
|
private final Map<String, Objective> objectives = new ConcurrentHashMap<>();
|
||||||
private final Map<ScoreboardPosition, Objective> objectiveSlots = new HashMap<>();
|
@Getter
|
||||||
|
private final Map<ScoreboardPosition, Objective> objectiveSlots = new EnumMap<>(ScoreboardPosition.class);
|
||||||
private final Map<String, Team> teams = new ConcurrentHashMap<>(); // updated on multiple threads
|
private final Map<String, Team> teams = new ConcurrentHashMap<>(); // updated on multiple threads
|
||||||
|
|
||||||
private int lastAddScoreCount = 0;
|
private int lastAddScoreCount = 0;
|
||||||
|
@ -103,6 +105,19 @@ public final class Scoreboard {
|
||||||
objective.pendingRemove();
|
objective.pendingRemove();
|
||||||
}
|
}
|
||||||
objectiveSlots.put(displaySlot, objective);
|
objectiveSlots.put(displaySlot, objective);
|
||||||
|
|
||||||
|
if (displaySlot == ScoreboardPosition.BELOW_NAME) {
|
||||||
|
// Display the below name score option to all players
|
||||||
|
// Of note: unlike Bedrock, if there is an objective in the below name slot, everyone has a display
|
||||||
|
for (PlayerEntity entity : session.getEntityCache().getAllPlayerEntities()) {
|
||||||
|
if (!entity.isValid()) {
|
||||||
|
// Player hasn't spawned yet - don't bother, it'll be done then
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
entity.setBelowNameText(session, objective);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public Team registerNewTeam(String teamName, String[] players) {
|
public Team registerNewTeam(String teamName, String[] players) {
|
||||||
|
|
Loading…
Reference in a new issue