minecraft-src/net/minecraft/server/commands/ScoreboardCommand.java
2025-07-04 03:45:38 +03:00

863 lines
34 KiB
Java

package net.minecraft.server.commands;
import com.google.common.collect.Lists;
import com.mojang.brigadier.CommandDispatcher;
import com.mojang.brigadier.arguments.BoolArgumentType;
import com.mojang.brigadier.arguments.IntegerArgumentType;
import com.mojang.brigadier.arguments.StringArgumentType;
import com.mojang.brigadier.builder.ArgumentBuilder;
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
import com.mojang.brigadier.context.CommandContext;
import com.mojang.brigadier.exceptions.CommandSyntaxException;
import com.mojang.brigadier.exceptions.Dynamic2CommandExceptionType;
import com.mojang.brigadier.exceptions.SimpleCommandExceptionType;
import com.mojang.brigadier.suggestion.Suggestions;
import com.mojang.brigadier.suggestion.SuggestionsBuilder;
import it.unimi.dsi.fastutil.objects.Object2IntMap;
import it.unimi.dsi.fastutil.objects.Object2IntMaps;
import java.util.Collection;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import net.minecraft.commands.CommandBuildContext;
import net.minecraft.commands.CommandSourceStack;
import net.minecraft.commands.Commands;
import net.minecraft.commands.SharedSuggestionProvider;
import net.minecraft.commands.arguments.ComponentArgument;
import net.minecraft.commands.arguments.ObjectiveArgument;
import net.minecraft.commands.arguments.ObjectiveCriteriaArgument;
import net.minecraft.commands.arguments.OperationArgument;
import net.minecraft.commands.arguments.ScoreHolderArgument;
import net.minecraft.commands.arguments.ScoreboardSlotArgument;
import net.minecraft.commands.arguments.StyleArgument;
import net.minecraft.commands.arguments.OperationArgument.Operation;
import net.minecraft.network.chat.Component;
import net.minecraft.network.chat.ComponentUtils;
import net.minecraft.network.chat.Style;
import net.minecraft.network.chat.numbers.BlankFormat;
import net.minecraft.network.chat.numbers.FixedFormat;
import net.minecraft.network.chat.numbers.NumberFormat;
import net.minecraft.network.chat.numbers.StyledFormat;
import net.minecraft.world.scores.DisplaySlot;
import net.minecraft.world.scores.Objective;
import net.minecraft.world.scores.ReadOnlyScoreInfo;
import net.minecraft.world.scores.ScoreAccess;
import net.minecraft.world.scores.ScoreHolder;
import net.minecraft.world.scores.Scoreboard;
import net.minecraft.world.scores.criteria.ObjectiveCriteria;
import org.jetbrains.annotations.Nullable;
public class ScoreboardCommand {
private static final SimpleCommandExceptionType ERROR_OBJECTIVE_ALREADY_EXISTS = new SimpleCommandExceptionType(
Component.translatable("commands.scoreboard.objectives.add.duplicate")
);
private static final SimpleCommandExceptionType ERROR_DISPLAY_SLOT_ALREADY_EMPTY = new SimpleCommandExceptionType(
Component.translatable("commands.scoreboard.objectives.display.alreadyEmpty")
);
private static final SimpleCommandExceptionType ERROR_DISPLAY_SLOT_ALREADY_SET = new SimpleCommandExceptionType(
Component.translatable("commands.scoreboard.objectives.display.alreadySet")
);
private static final SimpleCommandExceptionType ERROR_TRIGGER_ALREADY_ENABLED = new SimpleCommandExceptionType(
Component.translatable("commands.scoreboard.players.enable.failed")
);
private static final SimpleCommandExceptionType ERROR_NOT_TRIGGER = new SimpleCommandExceptionType(
Component.translatable("commands.scoreboard.players.enable.invalid")
);
private static final Dynamic2CommandExceptionType ERROR_NO_VALUE = new Dynamic2CommandExceptionType(
(object, object2) -> Component.translatableEscape("commands.scoreboard.players.get.null", object, object2)
);
public static void register(CommandDispatcher<CommandSourceStack> dispatcher, CommandBuildContext context) {
dispatcher.register(
Commands.literal("scoreboard")
.requires(commandSourceStack -> commandSourceStack.hasPermission(2))
.then(
Commands.literal("objectives")
.then(Commands.literal("list").executes(commandContext -> listObjectives(commandContext.getSource())))
.then(
Commands.literal("add")
.then(
Commands.argument("objective", StringArgumentType.word())
.then(
Commands.argument("criteria", ObjectiveCriteriaArgument.criteria())
.executes(
commandContext -> addObjective(
commandContext.getSource(),
StringArgumentType.getString(commandContext, "objective"),
ObjectiveCriteriaArgument.getCriteria(commandContext, "criteria"),
Component.literal(StringArgumentType.getString(commandContext, "objective"))
)
)
.then(
Commands.argument("displayName", ComponentArgument.textComponent(context))
.executes(
commandContext -> addObjective(
commandContext.getSource(),
StringArgumentType.getString(commandContext, "objective"),
ObjectiveCriteriaArgument.getCriteria(commandContext, "criteria"),
ComponentArgument.getResolvedComponent(commandContext, "displayName")
)
)
)
)
)
)
.then(
Commands.literal("modify")
.then(
Commands.argument("objective", ObjectiveArgument.objective())
.then(
Commands.literal("displayname")
.then(
Commands.argument("displayName", ComponentArgument.textComponent(context))
.executes(
commandContext -> setDisplayName(
commandContext.getSource(),
ObjectiveArgument.getObjective(commandContext, "objective"),
ComponentArgument.getResolvedComponent(commandContext, "displayName")
)
)
)
)
.then(createRenderTypeModify())
.then(
Commands.literal("displayautoupdate")
.then(
Commands.argument("value", BoolArgumentType.bool())
.executes(
commandContext -> setDisplayAutoUpdate(
commandContext.getSource(), ObjectiveArgument.getObjective(commandContext, "objective"), BoolArgumentType.getBool(commandContext, "value")
)
)
)
)
.then(
addNumberFormats(
context,
Commands.literal("numberformat"),
(commandContext, numberFormat) -> setObjectiveFormat(
commandContext.getSource(), ObjectiveArgument.getObjective(commandContext, "objective"), numberFormat
)
)
)
)
)
.then(
Commands.literal("remove")
.then(
Commands.argument("objective", ObjectiveArgument.objective())
.executes(commandContext -> removeObjective(commandContext.getSource(), ObjectiveArgument.getObjective(commandContext, "objective")))
)
)
.then(
Commands.literal("setdisplay")
.then(
Commands.argument("slot", ScoreboardSlotArgument.displaySlot())
.executes(commandContext -> clearDisplaySlot(commandContext.getSource(), ScoreboardSlotArgument.getDisplaySlot(commandContext, "slot")))
.then(
Commands.argument("objective", ObjectiveArgument.objective())
.executes(
commandContext -> setDisplaySlot(
commandContext.getSource(),
ScoreboardSlotArgument.getDisplaySlot(commandContext, "slot"),
ObjectiveArgument.getObjective(commandContext, "objective")
)
)
)
)
)
)
.then(
Commands.literal("players")
.then(
Commands.literal("list")
.executes(commandContext -> listTrackedPlayers(commandContext.getSource()))
.then(
Commands.argument("target", ScoreHolderArgument.scoreHolder())
.suggests(ScoreHolderArgument.SUGGEST_SCORE_HOLDERS)
.executes(commandContext -> listTrackedPlayerScores(commandContext.getSource(), ScoreHolderArgument.getName(commandContext, "target")))
)
)
.then(
Commands.literal("set")
.then(
Commands.argument("targets", ScoreHolderArgument.scoreHolders())
.suggests(ScoreHolderArgument.SUGGEST_SCORE_HOLDERS)
.then(
Commands.argument("objective", ObjectiveArgument.objective())
.then(
Commands.argument("score", IntegerArgumentType.integer())
.executes(
commandContext -> setScore(
commandContext.getSource(),
ScoreHolderArgument.getNamesWithDefaultWildcard(commandContext, "targets"),
ObjectiveArgument.getWritableObjective(commandContext, "objective"),
IntegerArgumentType.getInteger(commandContext, "score")
)
)
)
)
)
)
.then(
Commands.literal("get")
.then(
Commands.argument("target", ScoreHolderArgument.scoreHolder())
.suggests(ScoreHolderArgument.SUGGEST_SCORE_HOLDERS)
.then(
Commands.argument("objective", ObjectiveArgument.objective())
.executes(
commandContext -> getScore(
commandContext.getSource(), ScoreHolderArgument.getName(commandContext, "target"), ObjectiveArgument.getObjective(commandContext, "objective")
)
)
)
)
)
.then(
Commands.literal("add")
.then(
Commands.argument("targets", ScoreHolderArgument.scoreHolders())
.suggests(ScoreHolderArgument.SUGGEST_SCORE_HOLDERS)
.then(
Commands.argument("objective", ObjectiveArgument.objective())
.then(
Commands.argument("score", IntegerArgumentType.integer(0))
.executes(
commandContext -> addScore(
commandContext.getSource(),
ScoreHolderArgument.getNamesWithDefaultWildcard(commandContext, "targets"),
ObjectiveArgument.getWritableObjective(commandContext, "objective"),
IntegerArgumentType.getInteger(commandContext, "score")
)
)
)
)
)
)
.then(
Commands.literal("remove")
.then(
Commands.argument("targets", ScoreHolderArgument.scoreHolders())
.suggests(ScoreHolderArgument.SUGGEST_SCORE_HOLDERS)
.then(
Commands.argument("objective", ObjectiveArgument.objective())
.then(
Commands.argument("score", IntegerArgumentType.integer(0))
.executes(
commandContext -> removeScore(
commandContext.getSource(),
ScoreHolderArgument.getNamesWithDefaultWildcard(commandContext, "targets"),
ObjectiveArgument.getWritableObjective(commandContext, "objective"),
IntegerArgumentType.getInteger(commandContext, "score")
)
)
)
)
)
)
.then(
Commands.literal("reset")
.then(
Commands.argument("targets", ScoreHolderArgument.scoreHolders())
.suggests(ScoreHolderArgument.SUGGEST_SCORE_HOLDERS)
.executes(commandContext -> resetScores(commandContext.getSource(), ScoreHolderArgument.getNamesWithDefaultWildcard(commandContext, "targets")))
.then(
Commands.argument("objective", ObjectiveArgument.objective())
.executes(
commandContext -> resetScore(
commandContext.getSource(),
ScoreHolderArgument.getNamesWithDefaultWildcard(commandContext, "targets"),
ObjectiveArgument.getObjective(commandContext, "objective")
)
)
)
)
)
.then(
Commands.literal("enable")
.then(
Commands.argument("targets", ScoreHolderArgument.scoreHolders())
.suggests(ScoreHolderArgument.SUGGEST_SCORE_HOLDERS)
.then(
Commands.argument("objective", ObjectiveArgument.objective())
.suggests(
(commandContext, suggestionsBuilder) -> suggestTriggers(
commandContext.getSource(), ScoreHolderArgument.getNamesWithDefaultWildcard(commandContext, "targets"), suggestionsBuilder
)
)
.executes(
commandContext -> enableTrigger(
commandContext.getSource(),
ScoreHolderArgument.getNamesWithDefaultWildcard(commandContext, "targets"),
ObjectiveArgument.getObjective(commandContext, "objective")
)
)
)
)
)
.then(
Commands.literal("display")
.then(
Commands.literal("name")
.then(
Commands.argument("targets", ScoreHolderArgument.scoreHolders())
.suggests(ScoreHolderArgument.SUGGEST_SCORE_HOLDERS)
.then(
Commands.argument("objective", ObjectiveArgument.objective())
.then(
Commands.argument("name", ComponentArgument.textComponent(context))
.executes(
commandContext -> setScoreDisplay(
commandContext.getSource(),
ScoreHolderArgument.getNamesWithDefaultWildcard(commandContext, "targets"),
ObjectiveArgument.getObjective(commandContext, "objective"),
ComponentArgument.getResolvedComponent(commandContext, "name")
)
)
)
.executes(
commandContext -> setScoreDisplay(
commandContext.getSource(),
ScoreHolderArgument.getNamesWithDefaultWildcard(commandContext, "targets"),
ObjectiveArgument.getObjective(commandContext, "objective"),
null
)
)
)
)
)
.then(
Commands.literal("numberformat")
.then(
Commands.argument("targets", ScoreHolderArgument.scoreHolders())
.suggests(ScoreHolderArgument.SUGGEST_SCORE_HOLDERS)
.then(
addNumberFormats(
context,
Commands.argument("objective", ObjectiveArgument.objective()),
(commandContext, numberFormat) -> setScoreNumberFormat(
commandContext.getSource(),
ScoreHolderArgument.getNamesWithDefaultWildcard(commandContext, "targets"),
ObjectiveArgument.getObjective(commandContext, "objective"),
numberFormat
)
)
)
)
)
)
.then(
Commands.literal("operation")
.then(
Commands.argument("targets", ScoreHolderArgument.scoreHolders())
.suggests(ScoreHolderArgument.SUGGEST_SCORE_HOLDERS)
.then(
Commands.argument("targetObjective", ObjectiveArgument.objective())
.then(
Commands.argument("operation", OperationArgument.operation())
.then(
Commands.argument("source", ScoreHolderArgument.scoreHolders())
.suggests(ScoreHolderArgument.SUGGEST_SCORE_HOLDERS)
.then(
Commands.argument("sourceObjective", ObjectiveArgument.objective())
.executes(
commandContext -> performOperation(
commandContext.getSource(),
ScoreHolderArgument.getNamesWithDefaultWildcard(commandContext, "targets"),
ObjectiveArgument.getWritableObjective(commandContext, "targetObjective"),
OperationArgument.getOperation(commandContext, "operation"),
ScoreHolderArgument.getNamesWithDefaultWildcard(commandContext, "source"),
ObjectiveArgument.getObjective(commandContext, "sourceObjective")
)
)
)
)
)
)
)
)
)
);
}
private static ArgumentBuilder<CommandSourceStack, ?> addNumberFormats(
CommandBuildContext context, ArgumentBuilder<CommandSourceStack, ?> argumentBuilder, ScoreboardCommand.NumberFormatCommandExecutor executor
) {
return argumentBuilder.then(Commands.literal("blank").executes(commandContext -> executor.run(commandContext, BlankFormat.INSTANCE)))
.then(Commands.literal("fixed").then(Commands.argument("contents", ComponentArgument.textComponent(context)).executes(commandContext -> {
Component component = ComponentArgument.getResolvedComponent(commandContext, "contents");
return executor.run(commandContext, new FixedFormat(component));
})))
.then(Commands.literal("styled").then(Commands.argument("style", StyleArgument.style(context)).executes(commandContext -> {
Style style = StyleArgument.getStyle(commandContext, "style");
return executor.run(commandContext, new StyledFormat(style));
})))
.executes(commandContext -> executor.run(commandContext, null));
}
private static LiteralArgumentBuilder<CommandSourceStack> createRenderTypeModify() {
LiteralArgumentBuilder<CommandSourceStack> literalArgumentBuilder = Commands.literal("rendertype");
for (ObjectiveCriteria.RenderType renderType : ObjectiveCriteria.RenderType.values()) {
literalArgumentBuilder.then(
Commands.literal(renderType.getId())
.executes(commandContext -> setRenderType(commandContext.getSource(), ObjectiveArgument.getObjective(commandContext, "objective"), renderType))
);
}
return literalArgumentBuilder;
}
private static CompletableFuture<Suggestions> suggestTriggers(CommandSourceStack source, Collection<ScoreHolder> targets, SuggestionsBuilder suggestions) {
List<String> list = Lists.<String>newArrayList();
Scoreboard scoreboard = source.getServer().getScoreboard();
for (Objective objective : scoreboard.getObjectives()) {
if (objective.getCriteria() == ObjectiveCriteria.TRIGGER) {
boolean bl = false;
for (ScoreHolder scoreHolder : targets) {
ReadOnlyScoreInfo readOnlyScoreInfo = scoreboard.getPlayerScoreInfo(scoreHolder, objective);
if (readOnlyScoreInfo == null || readOnlyScoreInfo.isLocked()) {
bl = true;
break;
}
}
if (bl) {
list.add(objective.getName());
}
}
}
return SharedSuggestionProvider.suggest(list, suggestions);
}
private static int getScore(CommandSourceStack source, ScoreHolder scoreHolder, Objective objective) throws CommandSyntaxException {
Scoreboard scoreboard = source.getServer().getScoreboard();
ReadOnlyScoreInfo readOnlyScoreInfo = scoreboard.getPlayerScoreInfo(scoreHolder, objective);
if (readOnlyScoreInfo == null) {
throw ERROR_NO_VALUE.create(objective.getName(), scoreHolder.getFeedbackDisplayName());
} else {
source.sendSuccess(
() -> Component.translatable(
"commands.scoreboard.players.get.success", scoreHolder.getFeedbackDisplayName(), readOnlyScoreInfo.value(), objective.getFormattedDisplayName()
),
false
);
return readOnlyScoreInfo.value();
}
}
private static Component getFirstTargetName(Collection<ScoreHolder> scores) {
return ((ScoreHolder)scores.iterator().next()).getFeedbackDisplayName();
}
private static int performOperation(
CommandSourceStack source,
Collection<ScoreHolder> targets,
Objective targetObjectives,
Operation operation,
Collection<ScoreHolder> sourceEntities,
Objective sourceObjective
) throws CommandSyntaxException {
Scoreboard scoreboard = source.getServer().getScoreboard();
int i = 0;
for (ScoreHolder scoreHolder : targets) {
ScoreAccess scoreAccess = scoreboard.getOrCreatePlayerScore(scoreHolder, targetObjectives);
for (ScoreHolder scoreHolder2 : sourceEntities) {
ScoreAccess scoreAccess2 = scoreboard.getOrCreatePlayerScore(scoreHolder2, sourceObjective);
operation.apply(scoreAccess, scoreAccess2);
}
i += scoreAccess.get();
}
if (targets.size() == 1) {
int j = i;
source.sendSuccess(
() -> Component.translatable(
"commands.scoreboard.players.operation.success.single", targetObjectives.getFormattedDisplayName(), getFirstTargetName(targets), j
),
true
);
} else {
source.sendSuccess(
() -> Component.translatable("commands.scoreboard.players.operation.success.multiple", targetObjectives.getFormattedDisplayName(), targets.size()), true
);
}
return i;
}
private static int enableTrigger(CommandSourceStack source, Collection<ScoreHolder> targets, Objective objective) throws CommandSyntaxException {
if (objective.getCriteria() != ObjectiveCriteria.TRIGGER) {
throw ERROR_NOT_TRIGGER.create();
} else {
Scoreboard scoreboard = source.getServer().getScoreboard();
int i = 0;
for (ScoreHolder scoreHolder : targets) {
ScoreAccess scoreAccess = scoreboard.getOrCreatePlayerScore(scoreHolder, objective);
if (scoreAccess.locked()) {
scoreAccess.unlock();
i++;
}
}
if (i == 0) {
throw ERROR_TRIGGER_ALREADY_ENABLED.create();
} else {
if (targets.size() == 1) {
source.sendSuccess(
() -> Component.translatable("commands.scoreboard.players.enable.success.single", objective.getFormattedDisplayName(), getFirstTargetName(targets)), true
);
} else {
source.sendSuccess(
() -> Component.translatable("commands.scoreboard.players.enable.success.multiple", objective.getFormattedDisplayName(), targets.size()), true
);
}
return i;
}
}
}
private static int resetScores(CommandSourceStack source, Collection<ScoreHolder> targets) {
Scoreboard scoreboard = source.getServer().getScoreboard();
for (ScoreHolder scoreHolder : targets) {
scoreboard.resetAllPlayerScores(scoreHolder);
}
if (targets.size() == 1) {
source.sendSuccess(() -> Component.translatable("commands.scoreboard.players.reset.all.single", getFirstTargetName(targets)), true);
} else {
source.sendSuccess(() -> Component.translatable("commands.scoreboard.players.reset.all.multiple", targets.size()), true);
}
return targets.size();
}
private static int resetScore(CommandSourceStack source, Collection<ScoreHolder> targets, Objective objective) {
Scoreboard scoreboard = source.getServer().getScoreboard();
for (ScoreHolder scoreHolder : targets) {
scoreboard.resetSinglePlayerScore(scoreHolder, objective);
}
if (targets.size() == 1) {
source.sendSuccess(
() -> Component.translatable("commands.scoreboard.players.reset.specific.single", objective.getFormattedDisplayName(), getFirstTargetName(targets)), true
);
} else {
source.sendSuccess(
() -> Component.translatable("commands.scoreboard.players.reset.specific.multiple", objective.getFormattedDisplayName(), targets.size()), true
);
}
return targets.size();
}
private static int setScore(CommandSourceStack source, Collection<ScoreHolder> targets, Objective objective, int newValue) {
Scoreboard scoreboard = source.getServer().getScoreboard();
for (ScoreHolder scoreHolder : targets) {
scoreboard.getOrCreatePlayerScore(scoreHolder, objective).set(newValue);
}
if (targets.size() == 1) {
source.sendSuccess(
() -> Component.translatable("commands.scoreboard.players.set.success.single", objective.getFormattedDisplayName(), getFirstTargetName(targets), newValue),
true
);
} else {
source.sendSuccess(
() -> Component.translatable("commands.scoreboard.players.set.success.multiple", objective.getFormattedDisplayName(), targets.size(), newValue), true
);
}
return newValue * targets.size();
}
private static int setScoreDisplay(CommandSourceStack source, Collection<ScoreHolder> targets, Objective objective, @Nullable Component displayName) {
Scoreboard scoreboard = source.getServer().getScoreboard();
for (ScoreHolder scoreHolder : targets) {
scoreboard.getOrCreatePlayerScore(scoreHolder, objective).display(displayName);
}
if (displayName == null) {
if (targets.size() == 1) {
source.sendSuccess(
() -> Component.translatable(
"commands.scoreboard.players.display.name.clear.success.single", getFirstTargetName(targets), objective.getFormattedDisplayName()
),
true
);
} else {
source.sendSuccess(
() -> Component.translatable("commands.scoreboard.players.display.name.clear.success.multiple", targets.size(), objective.getFormattedDisplayName()), true
);
}
} else if (targets.size() == 1) {
source.sendSuccess(
() -> Component.translatable(
"commands.scoreboard.players.display.name.set.success.single", displayName, getFirstTargetName(targets), objective.getFormattedDisplayName()
),
true
);
} else {
source.sendSuccess(
() -> Component.translatable(
"commands.scoreboard.players.display.name.set.success.multiple", displayName, targets.size(), objective.getFormattedDisplayName()
),
true
);
}
return targets.size();
}
private static int setScoreNumberFormat(CommandSourceStack source, Collection<ScoreHolder> targets, Objective objective, @Nullable NumberFormat numberFormat) {
Scoreboard scoreboard = source.getServer().getScoreboard();
for (ScoreHolder scoreHolder : targets) {
scoreboard.getOrCreatePlayerScore(scoreHolder, objective).numberFormatOverride(numberFormat);
}
if (numberFormat == null) {
if (targets.size() == 1) {
source.sendSuccess(
() -> Component.translatable(
"commands.scoreboard.players.display.numberFormat.clear.success.single", getFirstTargetName(targets), objective.getFormattedDisplayName()
),
true
);
} else {
source.sendSuccess(
() -> Component.translatable(
"commands.scoreboard.players.display.numberFormat.clear.success.multiple", targets.size(), objective.getFormattedDisplayName()
),
true
);
}
} else if (targets.size() == 1) {
source.sendSuccess(
() -> Component.translatable(
"commands.scoreboard.players.display.numberFormat.set.success.single", getFirstTargetName(targets), objective.getFormattedDisplayName()
),
true
);
} else {
source.sendSuccess(
() -> Component.translatable("commands.scoreboard.players.display.numberFormat.set.success.multiple", targets.size(), objective.getFormattedDisplayName()),
true
);
}
return targets.size();
}
private static int addScore(CommandSourceStack source, Collection<ScoreHolder> targets, Objective objective, int amount) {
Scoreboard scoreboard = source.getServer().getScoreboard();
int i = 0;
for (ScoreHolder scoreHolder : targets) {
ScoreAccess scoreAccess = scoreboard.getOrCreatePlayerScore(scoreHolder, objective);
scoreAccess.set(scoreAccess.get() + amount);
i += scoreAccess.get();
}
if (targets.size() == 1) {
int j = i;
source.sendSuccess(
() -> Component.translatable("commands.scoreboard.players.add.success.single", amount, objective.getFormattedDisplayName(), getFirstTargetName(targets), j),
true
);
} else {
source.sendSuccess(
() -> Component.translatable("commands.scoreboard.players.add.success.multiple", amount, objective.getFormattedDisplayName(), targets.size()), true
);
}
return i;
}
private static int removeScore(CommandSourceStack source, Collection<ScoreHolder> targets, Objective objective, int amount) {
Scoreboard scoreboard = source.getServer().getScoreboard();
int i = 0;
for (ScoreHolder scoreHolder : targets) {
ScoreAccess scoreAccess = scoreboard.getOrCreatePlayerScore(scoreHolder, objective);
scoreAccess.set(scoreAccess.get() - amount);
i += scoreAccess.get();
}
if (targets.size() == 1) {
int j = i;
source.sendSuccess(
() -> Component.translatable(
"commands.scoreboard.players.remove.success.single", amount, objective.getFormattedDisplayName(), getFirstTargetName(targets), j
),
true
);
} else {
source.sendSuccess(
() -> Component.translatable("commands.scoreboard.players.remove.success.multiple", amount, objective.getFormattedDisplayName(), targets.size()), true
);
}
return i;
}
private static int listTrackedPlayers(CommandSourceStack source) {
Collection<ScoreHolder> collection = source.getServer().getScoreboard().getTrackedPlayers();
if (collection.isEmpty()) {
source.sendSuccess(() -> Component.translatable("commands.scoreboard.players.list.empty"), false);
} else {
source.sendSuccess(
() -> Component.translatable(
"commands.scoreboard.players.list.success", collection.size(), ComponentUtils.formatList(collection, ScoreHolder::getFeedbackDisplayName)
),
false
);
}
return collection.size();
}
private static int listTrackedPlayerScores(CommandSourceStack source, ScoreHolder score) {
Object2IntMap<Objective> object2IntMap = source.getServer().getScoreboard().listPlayerScores(score);
if (object2IntMap.isEmpty()) {
source.sendSuccess(() -> Component.translatable("commands.scoreboard.players.list.entity.empty", score.getFeedbackDisplayName()), false);
} else {
source.sendSuccess(
() -> Component.translatable("commands.scoreboard.players.list.entity.success", score.getFeedbackDisplayName(), object2IntMap.size()), false
);
Object2IntMaps.fastForEach(
object2IntMap,
entry -> source.sendSuccess(
() -> Component.translatable("commands.scoreboard.players.list.entity.entry", ((Objective)entry.getKey()).getFormattedDisplayName(), entry.getIntValue()),
false
)
);
}
return object2IntMap.size();
}
private static int clearDisplaySlot(CommandSourceStack source, DisplaySlot slot) throws CommandSyntaxException {
Scoreboard scoreboard = source.getServer().getScoreboard();
if (scoreboard.getDisplayObjective(slot) == null) {
throw ERROR_DISPLAY_SLOT_ALREADY_EMPTY.create();
} else {
scoreboard.setDisplayObjective(slot, null);
source.sendSuccess(() -> Component.translatable("commands.scoreboard.objectives.display.cleared", slot.getSerializedName()), true);
return 0;
}
}
private static int setDisplaySlot(CommandSourceStack source, DisplaySlot slot, Objective objective) throws CommandSyntaxException {
Scoreboard scoreboard = source.getServer().getScoreboard();
if (scoreboard.getDisplayObjective(slot) == objective) {
throw ERROR_DISPLAY_SLOT_ALREADY_SET.create();
} else {
scoreboard.setDisplayObjective(slot, objective);
source.sendSuccess(() -> Component.translatable("commands.scoreboard.objectives.display.set", slot.getSerializedName(), objective.getDisplayName()), true);
return 0;
}
}
private static int setDisplayName(CommandSourceStack source, Objective objective, Component displayName) {
if (!objective.getDisplayName().equals(displayName)) {
objective.setDisplayName(displayName);
source.sendSuccess(
() -> Component.translatable("commands.scoreboard.objectives.modify.displayname", objective.getName(), objective.getFormattedDisplayName()), true
);
}
return 0;
}
private static int setDisplayAutoUpdate(CommandSourceStack source, Objective objective, boolean displayAutoUpdate) {
if (objective.displayAutoUpdate() != displayAutoUpdate) {
objective.setDisplayAutoUpdate(displayAutoUpdate);
if (displayAutoUpdate) {
source.sendSuccess(
() -> Component.translatable("commands.scoreboard.objectives.modify.displayAutoUpdate.enable", objective.getName(), objective.getFormattedDisplayName()),
true
);
} else {
source.sendSuccess(
() -> Component.translatable("commands.scoreboard.objectives.modify.displayAutoUpdate.disable", objective.getName(), objective.getFormattedDisplayName()),
true
);
}
}
return 0;
}
private static int setObjectiveFormat(CommandSourceStack source, Objective objective, @Nullable NumberFormat format) {
objective.setNumberFormat(format);
if (format != null) {
source.sendSuccess(() -> Component.translatable("commands.scoreboard.objectives.modify.objectiveFormat.set", objective.getName()), true);
} else {
source.sendSuccess(() -> Component.translatable("commands.scoreboard.objectives.modify.objectiveFormat.clear", objective.getName()), true);
}
return 0;
}
private static int setRenderType(CommandSourceStack source, Objective objective, ObjectiveCriteria.RenderType renderType) {
if (objective.getRenderType() != renderType) {
objective.setRenderType(renderType);
source.sendSuccess(() -> Component.translatable("commands.scoreboard.objectives.modify.rendertype", objective.getFormattedDisplayName()), true);
}
return 0;
}
private static int removeObjective(CommandSourceStack source, Objective objective) {
Scoreboard scoreboard = source.getServer().getScoreboard();
scoreboard.removeObjective(objective);
source.sendSuccess(() -> Component.translatable("commands.scoreboard.objectives.remove.success", objective.getFormattedDisplayName()), true);
return scoreboard.getObjectives().size();
}
private static int addObjective(CommandSourceStack source, String name, ObjectiveCriteria criteria, Component displayName) throws CommandSyntaxException {
Scoreboard scoreboard = source.getServer().getScoreboard();
if (scoreboard.getObjective(name) != null) {
throw ERROR_OBJECTIVE_ALREADY_EXISTS.create();
} else {
scoreboard.addObjective(name, criteria, displayName, criteria.getDefaultRenderType(), false, null);
Objective objective = scoreboard.getObjective(name);
source.sendSuccess(() -> Component.translatable("commands.scoreboard.objectives.add.success", objective.getFormattedDisplayName()), true);
return scoreboard.getObjectives().size();
}
}
private static int listObjectives(CommandSourceStack source) {
Collection<Objective> collection = source.getServer().getScoreboard().getObjectives();
if (collection.isEmpty()) {
source.sendSuccess(() -> Component.translatable("commands.scoreboard.objectives.list.empty"), false);
} else {
source.sendSuccess(
() -> Component.translatable(
"commands.scoreboard.objectives.list.success", collection.size(), ComponentUtils.formatList(collection, Objective::getFormattedDisplayName)
),
false
);
}
return collection.size();
}
@FunctionalInterface
public interface NumberFormatCommandExecutor {
int run(CommandContext<CommandSourceStack> commandContext, @Nullable NumberFormat numberFormat) throws CommandSyntaxException;
}
}