diff --git a/docs/scarpet/Full.md b/docs/scarpet/Full.md index f7a4941b..0dac5b15 100644 --- a/docs/scarpet/Full.md +++ b/docs/scarpet/Full.md @@ -976,16 +976,17 @@ and maps, where the iterator returns all the map keys ### `break(), break(expr), continue(), continue(expr)` These allow to control execution of a loop either skipping current iteration code, using `continue`, or finishing the -current loop, using `break`. `break` and `continue` can only be used inside `for, while, loop, map, filter and reduce` +current loop, using `break`. `break` and `continue` can only be used inside `for`, `c_for`, `while`, `loop`, `map`, +`filter`, `reduce` as well as Minecraft API block loops, `scan` and `volume` functions, while `break` can be used in `first` as well. Outside of the internal expressions of these functions, -calling `break` or `continue` will cause an error. In case of the nexted loops, and more complex setups, use +calling `break` or `continue` will cause an error. In case of the nested loops, and more complex setups, use custom `try` and `throw` setup. Please check corresponding loop function description what `continue` and `break` do in their contexts, but in general case, passed values to `break` and `continue` will be used in place of the return value of the internal iteration expression. -### `cfor(init, condition, increment, body)` +### `c_for(init, condition, increment, body)` `c_for` Mimics c-style tri-arg (plus body) for loops. Return value of `c_for` is number of iterations performed in the loop. Unlike other loops, the `body` is not provided with pre-initialized `_` style variables - all initialization @@ -2073,11 +2074,19 @@ Evaluates expression over area of blocks defined by its center (`cx, cy, cz`), e by `dx, dy, dz` blocks, or optionally in negative with `d` coords, and `p` coords in positive values. `expr` receives `_x, _y, _z` as coords of current analyzed block and `_`, which represents the block itself. +Returns number of successful evaluations of `expr` (with `true` boolean result) unless called in void context, +which would cause the expression not be evaluated for their boolean value. + +`scan` also handles `continue` and `break` statements, using `continue`'s return value to use in place of expression +return value. `break` return value has no effect. + ### `volume(x1, y1, z1, x2, y2, z2, expr)` Evaluates expression for each block in the area, the same as the `scan`function, but using two opposite corners of the rectangular cuboid. Any corners can be specified, its like you would do with `/fill` command. +For return value and handling `break` and `continue` statements, see `scan` function above. + ### `neighbours(x, y, z), neighbours(block), neighbours(l(x,y,z))` Returns the list of 6 neighbouring blocks to the argument. Commonly used with other loop functions like `for`. @@ -2747,6 +2756,32 @@ used to display current events and bounded functions. use `add_to` ro register n unbind a specific function from an event. Function to be bounded to an event needs to have the same number of parameters as the action is attempting to bind to (see list above). All calls in modules loaded via `/script load` that have functions listed above will be automatically bounded and unbounded when script is unloaded. +# Scoreboard + +### `scoreboard()`, `scoreboard(objective)`, `scoreboard(objective, key)`, `scoreboard(objective, key, value)` + +Displays or modifies individual scoreboard values. With no arguments, returns the list of current objectives. +With specified `objective`, lists all keys (players) associated with current objective. With specified `objective`, +`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`. + +### `scoreboard_add(objective, criterion?)` + +Adds a new objective to scoreboard. If `criterion` is not specified, assumes `'dummy'`. Returns `false` if objective +already existed, `true` otherwise. + +
+scoreboard_add('counter')
+scoreboard_add('lvl','level')
+
+
+### `scoreboard_remove(objective)`
+
+Removes an objective. Returns `true` if objective has existed and has been removed.
+
+### `scoreboard_display(objective, place)`
+
+sets display location for a specified `objective`. If `place` is `null`, then display is cleared.
# Auxiliary aspects
Collection of other methods that control smaller, yet still important aspects of the game
diff --git a/docs/scarpet/api/Scoreboard.md b/docs/scarpet/api/Scoreboard.md
new file mode 100644
index 00000000..5e64285b
--- /dev/null
+++ b/docs/scarpet/api/Scoreboard.md
@@ -0,0 +1,26 @@
+# Scoreboard
+
+### `scoreboard()`, `scoreboard(objective)`, `scoreboard(objective, key)`, `scoreboard(objective, key, value)`
+
+Displays or modifies individual scoreboard values. With no arguments, returns the list of current objectives.
+With specified `objective`, lists all keys (players) associated with current objective. With specified `objective`,
+`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`.
+
+### `scoreboard_add(objective, criterion?)`
+
+Adds a new objective to scoreboard. If `criterion` is not specified, assumes `'dummy'`. Returns `false` if objective
+already existed, `true` otherwise.
+
+
+scoreboard_add('counter')
+scoreboard_add('lvl','level')
+
+
+### `scoreboard_remove(objective)`
+
+Removes an objective. Returns `true` if objective has existed and has been removed.
+
+### `scoreboard_display(objective, place)`
+
+sets display location for a specified `objective`. If `place` is `null`, then display is cleared.
diff --git a/mergedoc.bat b/mergedoc.bat
index ad269be7..16559437 100644
--- a/mergedoc.bat
+++ b/mergedoc.bat
@@ -1,2 +1,2 @@
-cat docs/scarpet/language/Overview.md docs/scarpet/language/VariablesAndConstants.md docs/scarpet/language/Operators.md docs/scarpet/language/Math.md docs/scarpet/language/SystemFunctions.md docs/scarpet/language/LoopsAndHigherOrderFunctions.md docs/scarpet/language/FunctionsAndControlFlow.md docs/scarpet/language/Containers.md docs/scarpet/api/Overview.md docs/scarpet/api/BlocksAndWorldAccess.md docs/scarpet/api/BlockIterations.md docs/scarpet/api/Entities.md docs/scarpet/api/Inventories.md docs/scarpet/api/Events.md docs/scarpet/api/Auxiliary.md docs/scarpet/api/ScriptCommand.md > docs/scarpet/Full.md
+cat docs/scarpet/language/Overview.md docs/scarpet/language/VariablesAndConstants.md docs/scarpet/language/Operators.md docs/scarpet/language/Math.md docs/scarpet/language/SystemFunctions.md docs/scarpet/language/LoopsAndHigherOrderFunctions.md docs/scarpet/language/FunctionsAndControlFlow.md docs/scarpet/language/Containers.md docs/scarpet/api/Overview.md docs/scarpet/api/BlocksAndWorldAccess.md docs/scarpet/api/BlockIterations.md docs/scarpet/api/Entities.md docs/scarpet/api/Inventories.md docs/scarpet/api/Events.md docs/scarpet/api/Scoreboard.md docs/scarpet/api/Auxiliary.md docs/scarpet/api/ScriptCommand.md > docs/scarpet/Full.md
diff --git a/src/main/java/carpet/script/CarpetExpression.java b/src/main/java/carpet/script/CarpetExpression.java
index 2507062b..08aec98e 100644
--- a/src/main/java/carpet/script/CarpetExpression.java
+++ b/src/main/java/carpet/script/CarpetExpression.java
@@ -77,6 +77,7 @@ import net.minecraft.nbt.Tag;
import net.minecraft.particle.ParticleEffect;
import net.minecraft.predicate.entity.EntityPredicates;
import net.minecraft.scoreboard.Scoreboard;
+import net.minecraft.scoreboard.ScoreboardCriterion;
import net.minecraft.scoreboard.ScoreboardObjective;
import net.minecraft.scoreboard.ScoreboardPlayerScore;
import net.minecraft.server.MinecraftServer;
@@ -1260,7 +1261,7 @@ public class CarpetExpression
}
- public void Scoreboard()
+ public void API_Scoreboard()
{
// scoreboard(player,'objective')
// scoreboard(player, objective, newValue)
@@ -1268,8 +1269,20 @@ public class CarpetExpression
{
CarpetContext cc = (CarpetContext)c;
Scoreboard scoreboard = cc.s.getMinecraftServer().getScoreboard();
+ if (lv.size()==0)
+ {
+ Value ret = ListValue.wrap(scoreboard.getObjectiveNames().stream().map(StringValue::new).collect(Collectors.toList()));
+ return (_c, _t) -> ret;
+ }
+ String objectiveName = lv.get(0).evalValue(c).getString();
+ ScoreboardObjective objective = scoreboard.getObjective(objectiveName);
+ if (objective == null) throw new InternalExpressionException("Unknown objective: "+objectiveName);
+ if (lv.size()==1)
+ {
+ Value ret = ListValue.wrap(scoreboard.getAllPlayerScores(objective).stream().map(s -> new StringValue(s.getPlayerName())).collect(Collectors.toList()));
+ return (_c, _t) -> ret;
+ }
String key;
- String target = lv.get(0).evalValue(c).getString();
Value keyValue = lv.get(1).evalValue(c);
if (keyValue instanceof EntityValue)
{
@@ -1287,9 +1300,6 @@ public class CarpetExpression
{
key = keyValue.getString();
}
- ScoreboardObjective objective = scoreboard.getObjective(target);
- if (objective == null)
- return LazyValue.NULL;
if (!scoreboard.playerHasObjective(key, objective) && lv.size()==2)
return LazyValue.NULL;
ScoreboardPlayerScore scoreboardPlayerScore = scoreboard.getPlayerScore(key, objective);
@@ -1301,9 +1311,67 @@ public class CarpetExpression
return (_c, _t) -> retval;
});
- //"objective_remove", "objective_add", "objective_keys", "set_display"
+ this.expr.addLazyFunction("scoreboard_remove", 1, (c, t, lv)-> {
+ CarpetContext cc = (CarpetContext)c;
+ Scoreboard scoreboard = cc.s.getMinecraftServer().getScoreboard();
+ String objectiveName = lv.get(0).evalValue(c).getString();
+ ScoreboardObjective objective = scoreboard.getObjective(objectiveName);
+ if (objective == null)
+ return LazyValue.FALSE;
+ scoreboard.removeObjective(objective);
+ return LazyValue.TRUE;
+ });
+ // objective_add('lvl','level')
+ // objective_add('counter')
+ this.expr.addLazyFunction("scoreboard_add", -1, (c, t, lv)-> {
+ CarpetContext cc = (CarpetContext)c;
+ Scoreboard scoreboard = cc.s.getMinecraftServer().getScoreboard();
+ if (lv.size() == 0 || lv.size()>2) throw new InternalExpressionException("'scoreboard_add' should have one or two parameters");
+ String objectiveName = lv.get(0).evalValue(c).getString();
+ ScoreboardCriterion criterion;
+ if (lv.size() == 1 )
+ {
+ criterion = ScoreboardCriterion.DUMMY;
+ }
+ else
+ {
+ String critetionName = lv.get(1).evalValue(c).getString();
+ criterion = ScoreboardCriterion.createStatCriterion(critetionName).orElse(null);
+ if (criterion==null)
+ {
+ throw new InternalExpressionException("Unknown scoreboard criterion: "+critetionName);
+ }
+ }
+
+ ScoreboardObjective objective = scoreboard.getObjective(objectiveName);
+ if (objective != null)
+ return LazyValue.FALSE;
+
+ scoreboard.addObjective(objectiveName, criterion, new LiteralText(objectiveName), criterion.getCriterionType());
+ return LazyValue.TRUE;
+ });
+
+ this.expr.addLazyFunction("scoreboard_display", 2, (c, t, lv) ->
+ {
+ CarpetContext cc = (CarpetContext)c;
+ Scoreboard scoreboard = cc.s.getMinecraftServer().getScoreboard();
+ String location = lv.get(0).evalValue(c).getString();
+ int slot = Scoreboard.getDisplaySlotId(location);
+ if (slot < 0) throw new InternalExpressionException("Invalid objective slot: "+location);
+ Value target = lv.get(1).evalValue(c);
+ if (target instanceof NullValue)
+ {
+ scoreboard.setObjectiveSlot(slot, null);
+ return (_c, _t) -> new NumericValue(slot);
+ }
+ String objectiveString = target.getString();
+ ScoreboardObjective objective = scoreboard.getObjective(objectiveString);
+ if (objective == null) throw new InternalExpressionException("Objective doesn't exist: "+objectiveString);
+ scoreboard.setObjectiveSlot(slot, objective);
+ return (_c, _t) -> new NumericValue(slot);
+ });
}
public void API_InventoryManipulation()
@@ -2790,7 +2858,7 @@ public class CarpetExpression
API_InventoryManipulation();
API_IteratingOverAreasOfBlocks();
API_AuxiliaryAspects();
- Scoreboard();
+ API_Scoreboard();
}
public boolean fillAndScanCommand(ScriptHost host, int x, int y, int z)