Skip to content

Commit

Permalink
feat(core): handle scoreboard objective packet with packetevents
Browse files Browse the repository at this point in the history
  • Loading branch information
diogotcorreia committed Dec 18, 2024
1 parent bb5ab44 commit d8a5ff5
Show file tree
Hide file tree
Showing 3 changed files with 108 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ public void setupHandlers() {
if (config.isScoreboards()) {
val scoreboardHandler = new ScoreboardPacketHandler(parser, config);
updatedHandlers.put(PacketType.Play.Server.TEAMS, scoreboardHandler::onTeamsPacket);
updatedHandlers.put(PacketType.Play.Server.SCOREBOARD_OBJECTIVE, scoreboardHandler::onObjectivePacket);
}

receiveHandlers = Collections.unmodifiableMap(updatedHandlers);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.rexcantor64.triton.packetinterceptor.handlers;

import com.github.retrooper.packetevents.event.PacketSendEvent;
import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerScoreboardObjective;
import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerTeams;
import com.rexcantor64.triton.config.MainConfig;
import com.rexcantor64.triton.language.parser.AdventureParser;
Expand Down Expand Up @@ -96,4 +97,42 @@ public void onTeamsPacket(@NotNull PacketSendEvent event, @NotNull TritonLanguag
}
}

public void onObjectivePacket(@NotNull PacketSendEvent event, @NotNull TritonLanguagePlayer<?> languagePlayer) {
val packet = new WrapperPlayServerScoreboardObjective(event);

val action = packet.getMode();
if (action == WrapperPlayServerScoreboardObjective.ObjectiveMode.REMOVE) {
languagePlayer.getPacketEventsRefresh().discardScoreboardObjective(packet.getName());
}

if (action != WrapperPlayServerScoreboardObjective.ObjectiveMode.CREATE && action != WrapperPlayServerScoreboardObjective.ObjectiveMode.UPDATE) {
// we are only interested in new/update actions
return;
}

val originalDisplayName = packet.getDisplayName();

parser.translateComponent(
originalDisplayName,
languagePlayer,
syntax
)
.getResultOrToRemove(Component::empty)
.ifPresent(result -> {
packet.setDisplayName(result);
event.markForReEncode(true);
});

if (event.needsReEncode()) {
languagePlayer.getPacketEventsRefresh().saveScoreboardObjective(
packet.getName(),
originalDisplayName,
packet.getRenderType(),
packet.getScoreFormat()
);
} else {
languagePlayer.getPacketEventsRefresh().discardScoreboardObjective(packet.getName());
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -2,22 +2,28 @@

import com.github.retrooper.packetevents.PacketEvents;
import com.github.retrooper.packetevents.protocol.player.User;
import com.github.retrooper.packetevents.protocol.score.ScoreFormat;
import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerScoreboardObjective;
import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerScoreboardObjective.RenderType;
import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerTeams;
import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerTeams.ScoreBoardTeamInfo;
import com.rexcantor64.triton.Triton;
import com.rexcantor64.triton.config.MainConfig;
import com.rexcantor64.triton.language.parser.AdventureParser;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import lombok.val;
import net.kyori.adventure.text.Component;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

@RequiredArgsConstructor
public class PacketEventsRefresh {
private final Map<String, ScoreBoardTeamInfo> teamsMap = new ConcurrentHashMap<>();
private final Map<String, ScoreboardObjective> objectivesMap = new ConcurrentHashMap<>();

private final TritonLanguagePlayer<?> languagePlayer;

Expand All @@ -44,6 +50,33 @@ public void discardScoreboardTeam(String teamName) {
teamsMap.remove(teamName);
}

/**
* Stores info of an objective for later (i.e., to refresh text when language is changed).
*
* @param objectiveName The name of the objective the info belongs to.
* @param displayName The untranslated display name of the team.
* @param renderType The last render type sent with the packet.
* @param scoreFormat The last score format sent with the packet.
* @since 4.0.0
*/
public void saveScoreboardObjective(@NotNull String objectiveName,
@NotNull Component displayName,
@Nullable RenderType renderType,
@Nullable ScoreFormat scoreFormat) {
val info = new ScoreboardObjective(displayName, renderType, scoreFormat);
objectivesMap.put(objectiveName, info);
}

/**
* Forget info about the given objective.
*
* @param objectiveName The name of the objective to forget.
* @since 4.0.0
*/
public void discardScoreboardObjective(String objectiveName) {
objectivesMap.remove(objectiveName);
}

/**
* Refresh all active features of a player.
*
Expand All @@ -60,7 +93,9 @@ public void refreshAll() {
val cfg = Triton.get().getConfig();

if (cfg.isScoreboards()) {
updateScoreboardTeams(user, cfg.getScoreboardSyntax(), parser);
val syntax = cfg.getScoreboardSyntax();
updateScoreboardTeams(user, syntax, parser);
updateScoreboardObjectives(user, syntax, parser);
}
}

Expand Down Expand Up @@ -106,4 +141,36 @@ private void updateScoreboardTeams(@NotNull User user, @NotNull MainConfig.Featu
user.sendPacketSilently(packet);
}
}

private void updateScoreboardObjectives(@NotNull User user, @NotNull MainConfig.FeatureSyntax syntax, @NotNull AdventureParser parser) {
for (val entry : objectivesMap.entrySet()) {
val info = entry.getValue();

val packet = new WrapperPlayServerScoreboardObjective(
entry.getKey(),
WrapperPlayServerScoreboardObjective.ObjectiveMode.UPDATE,
info.getDisplayName(),
info.getRenderType(),
info.getScoreFormat()
);

parser.translateComponent(
packet.getDisplayName(),
languagePlayer,
syntax
)
.getResultOrToRemove(Component::empty)
.ifPresent(packet::setDisplayName);

user.sendPacketSilently(packet);
}
}

@RequiredArgsConstructor
@Getter
private static class ScoreboardObjective {
private final Component displayName;
private final RenderType renderType;
private final ScoreFormat scoreFormat;
}
}

0 comments on commit d8a5ff5

Please sign in to comment.