diff --git a/docs/scarpet/api/Scoreboard.md b/docs/scarpet/api/Scoreboard.md index 9d152098..881df496 100644 --- a/docs/scarpet/api/Scoreboard.md +++ b/docs/scarpet/api/Scoreboard.md @@ -6,13 +6,12 @@ Displays or modifies individual scoreboard values. With no arguments, returns th With specified `objective`, lists all keys (players) associated with current objective, or `null` if objective does not exist. With specified `objective` and `key`, returns current value of the objective for a given player (key). With additional `value` sets a new scoreboard - value, returning previous value associated with the `key`. + value, returning previous value associated with the `key`. If the `value` is null, resets the scoreboard value. ### `scoreboard_add(objective, criterion?)` Adds a new objective to scoreboard. If `criterion` is not specified, assumes `'dummy'`. -If the objective already exists, changes the criterion of that objective and returns `false`. If the criterion was not specified but the objective already exists, returns the current criterion. -If the objective was added, returns `true`. If nothing is affected, returns `null` +Returns `true` if the objective was created, or `null` if an objective with the specified name already exists. Throws `unknown_criterion` if criterion doesn't exist. @@ -33,6 +32,15 @@ for the objective. Sets display location for a specified `objective`. If `objective` is `null`, then display is cleared. If objective is invalid, returns `null`. +### `scoreboard_property(objective, property)` `scoreboard_property(objective, property, value)` + +Reads a property of an `objective` or sets it to a `value` if specified. Available properties are: + +* `criterion` +* `display_name` (Formatted text supported) +* `display_slot`: When reading, returns a list of slots this objective is displayed in, when modifying, displays the objective in the specified slot +* `render_type`: Either `'integer'` or `'hearts'`, defaults to `'integer'` if invalid value specified + # Team ### `team_list()`, `team_list(team)` diff --git a/docs/scarpet/resources/editors/idea/2.txt b/docs/scarpet/resources/editors/idea/2.txt index 1c3251b3..42a7bf9e 100644 --- a/docs/scarpet/resources/editors/idea/2.txt +++ b/docs/scarpet/resources/editors/idea/2.txt @@ -97,6 +97,7 @@ scoreboard scoreboard_add scoreboard_remove scoreboard_display +scoreboard_property tag_matches team_add team_leave diff --git a/docs/scarpet/resources/editors/npp/scarpet.xml b/docs/scarpet/resources/editors/npp/scarpet.xml index c274f9bd..b10e15e4 100644 --- a/docs/scarpet/resources/editors/npp/scarpet.xml +++ b/docs/scarpet/resources/editors/npp/scarpet.xml @@ -62,7 +62,7 @@ display_title - scoreboard scoreboard_add scoreboard_remove scoreboard_display + scoreboard scoreboard_add scoreboard_remove scoreboard_display scoreboard_property team_add team_list team_remove team_leave team_property diff --git a/src/main/java/carpet/script/api/Scoreboards.java b/src/main/java/carpet/script/api/Scoreboards.java index f0a2e598..f60ca14a 100644 --- a/src/main/java/carpet/script/api/Scoreboards.java +++ b/src/main/java/carpet/script/api/Scoreboards.java @@ -35,6 +35,8 @@ import net.minecraft.util.Formatting; import net.minecraft.util.Identifier; import net.minecraft.util.InvalidIdentifierException; +import java.util.ArrayList; +import java.util.List; import java.util.stream.Collectors; public class Scoreboards { @@ -79,16 +81,27 @@ public class Scoreboards { Value ret = ListValue.wrap(scoreboard.getAllPlayerScores(objective).stream().map(s -> new StringValue(s.getPlayerName())).collect(Collectors.toList())); return (_c, _t) -> ret; } + String key = getScoreboardKeyFromValue(lv.get(1).evalValue(c)); - if (!scoreboard.playerHasObjective(key, objective) && lv.size()==2) + if(lv.size()==2) { + if(scoreboard.playerHasObjective(key, objective)) { + return (_c,_t) -> NumericValue.of(scoreboard.getPlayerScore(key,objective).getScore()); + } return LazyValue.NULL; - ScoreboardPlayerScore scoreboardPlayerScore = scoreboard.getPlayerScore(key, objective); - Value retval = new NumericValue(scoreboardPlayerScore.getScore()); - if (lv.size() > 2) - { - scoreboardPlayerScore.setScore(NumericValue.asNumber(lv.get(2).evalValue(c)).getInt()); } - return (_c, _t) -> retval; + + Value value = lv.get(2).evalValue(c); + if(value.isNull()) { + ScoreboardPlayerScore score = scoreboard.getPlayerScore(key, objective); + scoreboard.resetPlayerScore(key,objective); + return (_c,_t) -> NumericValue.of(score.getScore()); + } + if (value instanceof NumericValue) { + ScoreboardPlayerScore score = scoreboard.getPlayerScore(key, objective); + score.setScore(NumericValue.asNumber(value).getInt()); + return (_c,_t) -> NumericValue.of(score.getScore()); + } + throw new InternalExpressionException("'scoreboard' requires a number or null as the third parameter"); }); expression.addLazyFunction("scoreboard_remove", -1, (c, t, lv)-> @@ -139,6 +152,7 @@ public class Scoreboards { ScoreboardObjective objective = scoreboard.getObjective(objectiveName); if (objective != null) { + c.host.issueDeprecation("reading or modifying an objective's criterion with scoreboard_add"); if(lv.size() == 1) return (_c, _t) -> StringValue.of(objective.getCriterion().getName()); if(objective.getCriterion().equals(criterion) || lv.size() == 1) return LazyValue.NULL; ((Scoreboard_scarpetMixin)scoreboard).getObjectivesByCriterion().get(objective.getCriterion()).remove(objective); @@ -152,6 +166,72 @@ public class Scoreboards { return LazyValue.TRUE; }); + expression.addLazyFunction("scoreboard_property", -1, (c, t, lv) -> + { + if(lv.size() < 2) throw new InternalExpressionException("'scoreboard_property' requires at least two parameters"); + CarpetContext cc = (CarpetContext)c; + Scoreboard scoreboard = cc.s.getMinecraftServer().getScoreboard(); + ScoreboardObjective objective = scoreboard.getObjective(lv.get(0).evalValue(c).getString()); + if(objective == null) return LazyValue.NULL; + + boolean modify = lv.size() > 2; + Value setValue = null; + if(modify) { + setValue = lv.get(2).evalValue(c); + } + String property = lv.get(1).evalValue(c).getString(); + switch (property) { + case "criterion": + if(modify) { + ScoreboardCriterion criterion = ScoreboardCriterion.createStatCriterion(setValue.getString()).orElse(null); + if (criterion==null) throw new InternalExpressionException("Unknown scoreboard criterion: "+ setValue.getString()); + if(objective.getCriterion().equals(criterion) || lv.size() == 1) return LazyValue.FALSE; + ((Scoreboard_scarpetMixin)scoreboard).getObjectivesByCriterion().get(objective.getCriterion()).remove(objective); + ((ScoreboardObjective_scarpetMixin) objective).setCriterion(criterion); + (((Scoreboard_scarpetMixin)scoreboard).getObjectivesByCriterion().computeIfAbsent(criterion, (criterion1) -> Lists.newArrayList())).add(objective); + scoreboard.updateObjective(objective); + return LazyValue.TRUE; + } + return (_c, _t) -> StringValue.of(objective.getCriterion().getName()); + case "display_name": + if(modify) { + Text text = (setValue instanceof FormattedTextValue)?((FormattedTextValue) setValue).getText():new LiteralText(setValue.getString()); + objective.setDisplayName(text); + return LazyValue.TRUE; + } + return (_c, _t) -> new FormattedTextValue(objective.getDisplayName()); + case "display_slot": + if(modify) { + int slotId = Scoreboard.getDisplaySlotId(setValue.getString()); + if(slotId == -1) throw new InternalExpressionException("Unknown scoreboard display slot: " + setValue.getString()); + if(objective.equals(scoreboard.getObjectiveForSlot(slotId))) { + return LazyValue.FALSE; + } + scoreboard.setObjectiveSlot(slotId,objective); + return LazyValue.TRUE; + } + + List slots = new ArrayList<>(); + for(int i = 0; i < 19; i++) { + if (scoreboard.getObjectiveForSlot(i) == objective) { + String slotName = Scoreboard.getDisplaySlotName(i); + slots.add(StringValue.of(slotName)); + } + } + return (_c, _t) -> ListValue.wrap(slots); + case "render_type": + if(modify) { + ScoreboardCriterion.RenderType renderType = ScoreboardCriterion.RenderType.getType(setValue.getString().toLowerCase()); + if(objective.getRenderType().equals(renderType)) return LazyValue.FALSE; + objective.setRenderType(renderType); + return LazyValue.TRUE; + } + return (_c, _t) -> StringValue.of(objective.getRenderType().getName()); + default: + throw new InternalExpressionException("scoreboard property '" + property + "' is not a valid property"); + } + }); + expression.addLazyFunction("scoreboard_display", 2, (c, t, lv) -> { CarpetContext cc = (CarpetContext)c; @@ -410,7 +490,7 @@ public class Scoreboards { team.setSuffix(suffix); break; default: - throw new InternalExpressionException("team property " + propertyVal.getString() + " is not a valid property"); + throw new InternalExpressionException("team property '" + propertyVal.getString() + "' is not a valid property"); } return LazyValue.TRUE; });