Skip to content
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Start implementing the /scoreboard command
  • Loading branch information
lukeeey committed Sep 24, 2020
commit 367891b5234807c308e4fd5413c8f129b3855211
Original file line number Diff line number Diff line change
@@ -0,0 +1,278 @@
package org.cloudburstmc.server.command.defaults;

import com.nukkitx.protocol.bedrock.data.command.CommandParamType;
import org.cloudburstmc.server.command.Command;
import org.cloudburstmc.server.command.CommandSender;
import org.cloudburstmc.server.command.data.CommandData;
import org.cloudburstmc.server.command.data.CommandParameter;
import org.cloudburstmc.server.locale.TranslationContainer;
import org.cloudburstmc.server.player.Player;
import org.cloudburstmc.server.scoreboard.*;
import org.cloudburstmc.server.scoreboard.impl.CloudScoreboardObjective;
import org.cloudburstmc.server.utils.TextFormat;

/**
* @author lukeeey
*/
public class ScoreboardCommand extends Command {

public ScoreboardCommand() {
super(CommandData.builder("scoreboard")
.setDescription("commands.scoreboard.description")
.setUsageMessage("/scoreboard <args>")
.setPermissions("cloudburst.command.scoreboard")
.addParameters(new CommandParameter[]{
new CommandParameter("objectives", new String[]{"objectives"}),
new CommandParameter("add", new String[]{"add"}),
new CommandParameter("objectiveName", CommandParamType.STRING, false),
new CommandParameter("dummy", new String[]{"dummy"}),
new CommandParameter("displayName", CommandParamType.STRING, true)
}).addParameters(new CommandParameter[]{
new CommandParameter("objectives", new String[]{"objectives"}),
new CommandParameter("remove", new String[]{"remove"}),
new CommandParameter("objective", CommandParamType.STRING, false)
}).addParameters(new CommandParameter[]{
new CommandParameter("objectives", new String[]{"objectives"}),
new CommandParameter("list", new String[]{"list"})
}).addParameters(new CommandParameter[]{
new CommandParameter("objectives", new String[]{"objectives"}),
new CommandParameter("setdisplay", new String[]{"setdisplay"}),
new CommandParameter("displaySlot", new String[]{"list", "sidebar"}),
new CommandParameter("objective", CommandParamType.STRING, true),
new CommandParameter("sortOrder", true, new String[]{"ascending", "descending"})
}).addParameters(new CommandParameter[]{
new CommandParameter("objectives", new String[]{"objectives"}),
new CommandParameter("setdisplay", new String[]{"setdisplay"}),
new CommandParameter("belowname", new String[]{"belowname"}),
new CommandParameter("objective", CommandParamType.STRING, true),
}).addParameters(new CommandParameter[]{
new CommandParameter("players", new String[]{"players"}),
new CommandParameter("list", new String[]{"list"}),
new CommandParameter("playerName", CommandParamType.TARGET, true)
}).addParameters(new CommandParameter[]{
new CommandParameter("players", new String[]{"players"}),
new CommandParameter("reset", new String[]{"reset"}),
new CommandParameter("player", CommandParamType.TARGET, false),
new CommandParameter("objective", CommandParamType.STRING, true)
}).addParameters(new CommandParameter[]{
new CommandParameter("players", new String[]{"players"}),
new CommandParameter("test", new String[]{"test"}),
new CommandParameter("objective", CommandParamType.STRING, false),
new CommandParameter("min", CommandParamType.WILDCARD_INT, false),
new CommandParameter("max", CommandParamType.WILDCARD_INT, true)
}).addParameters(new CommandParameter[]{
new CommandParameter("players", new String[]{"players"}),
new CommandParameter("random", new String[]{"random"}),
new CommandParameter("player", CommandParamType.TARGET, false),
new CommandParameter("objective", CommandParamType.STRING, false),
new CommandParameter("min", CommandParamType.INT, false),
new CommandParameter("max", CommandParamType.INT, false)
}).addParameters(new CommandParameter[]{
new CommandParameter("players", new String[]{"players"}),
new CommandParameter("actionList", new String[]{"set", "add", "remove"}),
new CommandParameter("player", CommandParamType.TARGET, false),
new CommandParameter("objective", CommandParamType.STRING, false),
new CommandParameter("count", CommandParamType.INT, false)
}).addParameters(new CommandParameter[]{
new CommandParameter("players", new String[]{"players"}),
new CommandParameter("operation", new String[]{"operation"}),
new CommandParameter("targetName", CommandParamType.TARGET, false),
new CommandParameter("targetObjective", CommandParamType.STRING, false),
new CommandParameter("operation", CommandParamType.OPERATOR, false),
new CommandParameter("selector", CommandParamType.TARGET, false),
new CommandParameter("objective", CommandParamType.STRING, false)
}).build());
}

@Override
public boolean execute(CommandSender sender, String commandLabel, String[] args) {
if (!this.testPermission(sender)) {
return true;
}
if (args.length == 0 || args.length == 1) {
return false;
}

Scoreboard scoreboard = ((Player) sender).getScoreboard(); // TODO: per-world scoreboard, THIS IS JUST FOR TESTING!

if(scoreboard == null) {
scoreboard = Scoreboard.builder().players((Player) sender).build();
((Player) sender).setScoreboard(scoreboard);
}

if (args[0].equalsIgnoreCase("objectives")) {
switch (args[1]) {
case "add":
if (args.length < 4) {
return false;
}
String name = args[2];
String displayName = name;

if(args.length == 5) {
displayName = args[4]; // criteria is 3rd, always dummy
}

if(name.length() > CloudScoreboardObjective.MAX_NAME_LENGTH) {
sender.sendMessage(new TranslationContainer("%commands.scoreboard.objectives.add.tooLong", name, CloudScoreboardObjective.MAX_NAME_LENGTH));
return true;
}
if(scoreboard.getObjective(name) != null) {
sender.sendMessage(new TranslationContainer("%commands.scoreboard.objectives.add.alreadyExists", name));
return true;
}
if(displayName.length() > CloudScoreboardObjective.MAX_DISPLAY_NAME_LENGTH) {
sender.sendMessage(new TranslationContainer("%commands.scoreboard.objectives.add.displayTooLong", name, CloudScoreboardObjective.MAX_DISPLAY_NAME_LENGTH));
return true;
}

scoreboard.registerObjective(ScoreboardObjective.builder()
.name(name)
.displayName(displayName)
.displayMode(DisplayMode.SIDEBAR)
.criteria(ScoreboardCriteria.DUMMY)
.build());

sender.sendMessage(new TranslationContainer("%commands.scoreboard.objectives.add.success", name));
break;
case "remove":
if(args.length != 3) {
return false;
}
if(scoreboard.getObjective(args[2]) == null) {
return true; // TODO
}
scoreboard.deregisterObjective(args[2]);
sender.sendMessage(new TranslationContainer("%commands.scoreboard.objectives.remove.success", args[2]));
break;
case "list":
if (scoreboard.getObjectives().isEmpty()) {
sender.sendMessage(new TranslationContainer(TextFormat.RED + "%commands.scoreboard.objectives.list.empty"));
return true;
}

sender.sendMessage(new TranslationContainer(TextFormat.GREEN + "%commands.scoreboard.objectives.list.count",
scoreboard.getObjectives().size()));

scoreboard.getObjectives().forEach(objective -> sender.sendMessage(new TranslationContainer("%commands.scoreboard.objectives.list.entry",
objective.getName(), objective.getDisplayName(), objective.getCriteria().name().toLowerCase())));
break;
case "setdisplay":
if(args.length < 3) {
return false;
}
DisplayMode displayMode;

switch(args[2]) {
case "belowname":
displayMode = DisplayMode.BELOWNAME;
break;
case "list":
displayMode = DisplayMode.LIST;
break;
case "sidebar":
displayMode = DisplayMode.SIDEBAR;
break;
default:
sender.sendMessage(new TranslationContainer("%commands.scoreboard.objectives.setdisplay.invalidSlot", args[2]));
return true;
}


if(args.length == 3) {
// TODO: clear display slot
return true;
}
String objectiveName = args[3];
ScoreboardObjective objective = scoreboard.getObjective(objectiveName);

if(objective == null) {
sender.sendMessage(new TranslationContainer(TextFormat.RED + "%commands.scoreboard.objectiveNotFound", objectiveName));
return true;
}

objective.setDisplayMode(displayMode);

if(args.length == 5) {
SortOrder sortOrder = SortOrder.DESCENDING;

switch(args[4]) {
case "ascending": sortOrder = SortOrder.ASCENDING; break;
case "descending": sortOrder = SortOrder.DESCENDING; break;
}

objective.setSortOrder(sortOrder);
}

// sender.sendMessage(new TranslationContainer("%commands.scoreboard.objectives.setdisplay.successSet", args[2], ));

break;
}
}

else if (args[0].equalsIgnoreCase("players")) {
switch (args[1]) {
case "list": // TODO: tracked players
if(args.length == 2) {
sender.sendMessage(new TranslationContainer(TextFormat.GREEN + "%commands.scoreboard.players.list.count", 0));
// TODO
return true;
}
break;
case "reset":
break;
case "test": break;
case "random": break;
case "set":
case "add":
case "remove":
if (args.length != 5) {
return false;
}

// TODO: You can add a score to a player that isnt online in vanilla, meaning just any string of text
// Does a player thats offline need to be set to ScoreType.FAKE, as we cant provide a player instance?

ScoreboardObjective objective = scoreboard.getObjective(args[3]);
if (objective == null) {
sender.sendMessage(new TranslationContainer(TextFormat.RED + "%commands.scoreboard.objectiveNotFound", args[3]));
return true;
}

int count = Integer.parseInt(args[4]);

Score score = objective.getScore(args[2]);
switch(args[1]) {
case "add":
int amount = this.setScore(objective, args[2], ((Player) sender), (score != null ? score.getAmount() + count : count));
sender.sendMessage(new TranslationContainer("%commands.scoreboard.players.add.success", count, args[3], args[2], amount));
break;
case "set":
this.setScore(objective, args[2], ((Player) sender), count);
sender.sendMessage(new TranslationContainer("%commands.scoreboard.players.set.success", args[3], args[2], args[4]));
break;
case "remove":
int removeAmount = this.setScore(objective, args[2], ((Player) sender), (score != null ? score.getAmount() - count : -count));
sender.sendMessage(new TranslationContainer("%commands.scoreboard.players.remove.success", count, args[3], args[2], removeAmount));
break;
}

break;
}
}

return true;
}

private int setScore(ScoreboardObjective objective, String name, Player player, int count) {
Score score = objective.getScore(name);

if(score != null) {
score.setAmount(count);
return score.getAmount();
} else {
objective.getOrCreateScore(name, ScoreType.FAKE, name, count);
return count;
}
}
}
8 changes: 4 additions & 4 deletions src/main/java/org/cloudburstmc/server/player/Player.java
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@
import org.cloudburstmc.server.registry.EntityRegistry;
import org.cloudburstmc.server.registry.ItemRegistry;
import org.cloudburstmc.server.scoreboard.Scoreboard;
import org.cloudburstmc.server.scoreboard.impl.CloudburstScoreboard;
import org.cloudburstmc.server.scoreboard.impl.CloudScoreboard;
import org.cloudburstmc.server.utils.*;

import javax.annotation.Nullable;
Expand Down Expand Up @@ -2012,7 +2012,7 @@ public void close(TextContainer message, String reason, boolean notify) {
this.stopFishing(false);
}
if (this.scoreboard != null) {
((CloudburstScoreboard) this.scoreboard).getPlayers().remove(this);
((CloudScoreboard) this.scoreboard).getPlayers().remove(this);
this.scoreboard = null;
}
}
Expand Down Expand Up @@ -3370,10 +3370,10 @@ public Scoreboard getScoreboard() {
*/
public void setScoreboard(@Nullable Scoreboard scoreboard) {
if (this.scoreboard != null) {
((CloudburstScoreboard) this.scoreboard).hide(this);
((CloudScoreboard) this.scoreboard).hide(this);
}
if (scoreboard != null) {
((CloudburstScoreboard) scoreboard).show(this);
((CloudScoreboard) scoreboard).show(this);
}
this.scoreboard = scoreboard;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -456,6 +456,7 @@ private void registerDefaults() {
this.registerInternal("pardon-ip", new PardonIpCommand());
this.registerInternal("particle", new ParticleCommand());
this.registerInternal("say", new SayCommand());
this.registerInternal("scoreboard", new ScoreboardCommand());
this.registerInternal("seed", new SeedCommand());
this.registerInternal("setworldspawn", new SetWorldSpawnCommand());
this.registerInternal("spawnpoint", new SpawnpointCommand());
Expand Down
4 changes: 2 additions & 2 deletions src/main/java/org/cloudburstmc/server/scoreboard/Score.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package org.cloudburstmc.server.scoreboard;

import org.cloudburstmc.server.scoreboard.impl.CloudburstScore;
import org.cloudburstmc.server.scoreboard.impl.CloudScore;

/**
* Represents a score for a {@link ScoreboardObjective}.
Expand Down Expand Up @@ -65,7 +65,7 @@ public interface Score<T> {
* @return a new instance of a score builder
*/
static <U> ScoreBuilder<U> builder(ScoreType<U> scoreType) {
return CloudburstScore.providedBuilder(scoreType);
return CloudScore.providedBuilder(scoreType);
}

interface ScoreBuilder<T> {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
package org.cloudburstmc.server.scoreboard;

import cn.nukkit.player.Player;
import lombok.AccessLevel;
import lombok.AllArgsConstructor;
import org.cloudburstmc.server.entity.Entity;
import org.cloudburstmc.server.player.Player;

/**
* Represents the score type for the
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
package org.cloudburstmc.server.scoreboard;

import org.cloudburstmc.server.player.Player;
import org.cloudburstmc.server.scoreboard.impl.CloudburstScoreboard;
import org.cloudburstmc.server.scoreboard.impl.CloudScoreboard;

import javax.annotation.Nullable;
import java.util.Collection;
import java.util.Set;

/**
* Represents a scoreboard in the game, which can contain
Expand All @@ -21,6 +22,8 @@ public interface Scoreboard {
@Nullable
ScoreboardObjective getObjective(String objectiveName);

Set<ScoreboardObjective> getObjectives();

/**
* Registers a new {@link ScoreboardObjective} to the scoreboard
* @param objective the objective
Expand All @@ -40,7 +43,7 @@ public interface Scoreboard {
* @return a new instance of a scoreboard builder
*/
static ScoreboardBuilder builder() {
return CloudburstScoreboard.providedBuilder();
return CloudScoreboard.providedBuilder();
}

interface ScoreboardBuilder {
Expand Down
Loading