diff --git a/docs/scarpet/Full.md b/docs/scarpet/Full.md index f20de214..20369350 100644 --- a/docs/scarpet/Full.md +++ b/docs/scarpet/Full.md @@ -1913,6 +1913,11 @@ Here is a list of built-in types, with their return value formats, as well as a * `'players'`: returning a list of valid player name string, logged in or not. If configured with `'single'` returns only one player or `null`. * `'intrange'`: same as `'floatrange'`, but requiring integers. * `'enchantment'`: name of an enchantment + * `'slot'`: provides a list of inventory type and slot. Can be configured with `'restrict'` requiring + `'player'`, `'enderchest'`, `'equipment'`, `'armor'`, `'weapon'`, `'container'`, `'villager'` or `'horse'` restricting selection of + available slots. Scarpet supports all vanilla slots, except for `horse.chest` - chest item, not items themselves. This you would + need to manage yourself via nbt directly. Also, for entities that change their capacity, like llamas, you need to check yourself if + the specified container slot is valid for your entity. * `'item'`: triple of item type, count of 1, and nbt. * `'message'`: text with expanded embedded player names * `'effect'`: string representing a status effect @@ -3586,29 +3591,30 @@ health back to the villager after being harmed. ## Manipulating inventories of blocks and entities Most functions in this category require inventory as the first argument. Inventory could be specified by an entity, -or a block, or position (three coordinates) of a potential block with inventory. Player enderchest inventory require -two arguments, keyword `'enderchest'`, followed by the player entity argument, or a single argument as a string of a -form: `'enderchest_steve'`. If your player name starts with enderchest, it can be always accessed by passing a player +or a block, or position (three coordinates) of a potential block with inventory, or can be preceded with inventory +type. +Inventory type can be `null` (default), `'enderchest'` denoting player enderchest storage, or `'equipment'` applying to +entities hand and armour pieces. Then the type can be followed by entity, block or position coordinates. +For instance, player enderchest inventory requires +two arguments, keyword `'enderchest'`, followed by the player entity argument, (or a single argument as a string of a +form: `'enderchest_steve'` for legacy support). If your player name starts with `'enderchest_'`, first of all, tough luck, +but then it can be always accessed by passing a player entity value. If all else fails, it will try to identify first three arguments as coordinates of a block position of -a block inventory. Player inventories can also be called by their name. +a block inventory. Player inventories can also be called by their name. -You can also use `'equipment'` as a keyword preceeding an entity indicating the need of access that entity as a mob. -Equipment inventory -consists of its armour and hand items, and a few living entites can have both, their regular inventory, and their equipment inventory. For some -entities (players) their regular inventory already contains the equipment. For entity types that only have -their equipment inventory, the equipment is returned by default. +A few living entities can have both: their regular inventory, and their equipment inventory. +Player's regular inventory already contains the equipment, but you can access the equipment part as well, as well as +their enderchest separately. For entity types that only have +their equipment inventory, the equipment is returned by default (`null` type). + +If that's confusing see examples under `inventory_size` on how to access inventories. All other `inventory_...()` functions +use the same scheme. -
-inventory_size(player()) => 41 // items
-inventory_size('enderchest', player()) => 27 // equipment
-inventory_size('equipment', player()) => 6 // equipment
-
If the entity or a block doesn't have
-an inventory, they typically do nothing and return null.
+an inventory, all API functions typically do nothing and return null.
Most items returned are in the form of a triple of item name, count, and nbt or the extra data associated with an item.
-Manipulating of the nbt data can be costly, but retrieving them from the tuple to match other aspects is cheap
### `stack_limit(item)`
@@ -3681,14 +3687,26 @@ item name that serves as a replacement after crafting is done. Currently it can
### `inventory_size(inventory)`
Returns the size of the inventory for the entity or block in question. Returns null if the block or entity don't
-have an inventory
+have an inventory.
inventory_size(player()) => 41
inventory_size('enderchest', player()) => 27 // enderchest
inventory_size('equipment', player()) => 6 // equipment
+inventory_size(null, player()) => 41 // default inventory for players
+
inventory_size(x,y,z) => 27 // chest
inventory_size(block(pos)) => 5 // hopper
+
+horse = spawn('horse', x, y, z);
+inventory_size(horse); => 2 // default horse inventory
+inventory_size('equipment', horse); => 6 // unused horse equipment inventory
+inventory_size(null, horse); => 2 // default horse
+
+creeper = spawn('creeper', x, y, z);
+inventory_size(creeper); => 6 // default creeper inventory is equipment since it has no other
+inventory_size('equipment', creeper); => 6 // unused horse equipment inventory
+inventory_size(null, creeper); => 6 // creeper default is its equipment
### `inventory_has_items(inventory)`
@@ -4157,8 +4175,83 @@ for the objective.
### `scoreboard_display(place, objective)`
-sets display location for a specified `objective`. If `objective` is `null`, then display is cleared. If objective is invalid,
+Sets display location for a specified `objective`. If `objective` is `null`, then display is cleared. If objective is invalid,
returns `null`.
+
+# Team
+
+### `team_list()`, `team_list(team)`
+
+Returns all available teams as a list with no arguments.
+
+When a `team` is specified, it returns all the players inside that team. If the `team` is invalid, returns `null`.
+
+### `team_add(team)`, `team_add(team,player)`
+
+With one argument, creates a new `team` and returns its name if successful, or `null` if team already exists.
+
+
+`team_add('admin')` -> Create a team with the name 'admin'
+`team_add('admin','Steve')` -> Joing the player 'Steve' into the team 'admin'
+
+If a `player` is specified, the player will join the given `team`. Returns `true` if player joined the team, or `false` if nothing changed since the player was already in this team. If the team is invalid, returns `null`
+
+### `team_remove(team)`
+
+Removes a `team`. Returns `true` if the team was deleted, or `null` if the team is invalid.
+
+### `team_leave(player)`
+
+Removes the `player` from the team he is in. Returns `true` if the player left a team, otherwise `false`.
+
+`team_leave('Steve')` -> Removes Steve from the team he is currently in
+`for(team_list('admin'), team_leave('admin', _))` -> Remove all players from team 'admin'
+
+### `team_property(team,property,value?)`
+
+Reads the `property` of the `team` if no `value` is specified. If a `value` is added as a third argument, it sets the `property` to that `value`.
+
+* `collisionRule`
+ * Type: String
+ * Options: always, never, pushOtherTeams, pushOwnTeam
+
+* `color`
+ * Type: String
+ * Options: See [team command](https://minecraft.gamepedia.com/Commands/team#Arguments) (same strings as `'teamcolor'` [command argument](https://github.com/gnembon/fabric-carpet/blob/master/docs/scarpet/Full.md#command-argument-types] options))
+
+* `displayName`
+ * Type: String or FormattedText, when querying returns FormattedText
+
+* `prefix`
+ * Type: String or FormattedText, when querying returns FormattedText
+
+* `suffix`
+ * Type: String or FormattedText, when querying returns FormattedText
+
+* `friendlyFire`
+ * Type: boolean
+
+* `seeFriendlyInvisibles`
+ * Type: boolean
+
+* `nametagVisibility`
+ * Type: String
+ * Options: always, never, hideForOtherTeams, hideForOwnTeam
+
+* `deathMessageVisibility`
+ * Type: String
+ * Options: always, never, hideForOtherTeams, hideForOwnTeam
+
+Examples:
+
+```
+team_property('admin','color','dark_red') Make the team color for team 'admin' dark red
+team_property('admin','prefix',format('r Admin | ')) Set prefix of all players in 'admin'
+team_property('admin','display_name','Administrators') Set display name for team 'admin'
+team_property('admin','seeFriendlyInvisibles',true) Make all players in 'admin' see other admins even when invisible
+team_property('admin','deathMessageVisibility','hideForOtherTeams') Make all players in 'admin' see other admins even when invisible
+```
+
# Auxiliary aspects
Collection of other methods that control smaller, yet still important aspects of the game
diff --git a/docs/scarpet/api/Inventories.md b/docs/scarpet/api/Inventories.md
index e2a68f18..1ecc692b 100644
--- a/docs/scarpet/api/Inventories.md
+++ b/docs/scarpet/api/Inventories.md
@@ -3,29 +3,30 @@
## Manipulating inventories of blocks and entities
Most functions in this category require inventory as the first argument. Inventory could be specified by an entity,
-or a block, or position (three coordinates) of a potential block with inventory. Player enderchest inventory require
-two arguments, keyword `'enderchest'`, followed by the player entity argument, or a single argument as a string of a
-form: `'enderchest_steve'`. If your player name starts with enderchest, it can be always accessed by passing a player
+or a block, or position (three coordinates) of a potential block with inventory, or can be preceded with inventory
+type.
+Inventory type can be `null` (default), `'enderchest'` denoting player enderchest storage, or `'equipment'` applying to
+entities hand and armour pieces. Then the type can be followed by entity, block or position coordinates.
+For instance, player enderchest inventory requires
+two arguments, keyword `'enderchest'`, followed by the player entity argument, (or a single argument as a string of a
+form: `'enderchest_steve'` for legacy support). If your player name starts with `'enderchest_'`, first of all, tough luck,
+but then it can be always accessed by passing a player
entity value. If all else fails, it will try to identify first three arguments as coordinates of a block position of
-a block inventory. Player inventories can also be called by their name.
+a block inventory. Player inventories can also be called by their name.
-You can also use `'equipment'` as a keyword preceeding an entity indicating the need of access that entity as a mob.
-Equipment inventory
-consists of its armour and hand items, and a few living entites can have both, their regular inventory, and their equipment inventory. For some
-entities (players) their regular inventory already contains the equipment. For entity types that only have
-their equipment inventory, the equipment is returned by default.
+A few living entities can have both: their regular inventory, and their equipment inventory.
+Player's regular inventory already contains the equipment, but you can access the equipment part as well, as well as
+their enderchest separately. For entity types that only have
+their equipment inventory, the equipment is returned by default (`null` type).
+
+If that's confusing see examples under `inventory_size` on how to access inventories. All other `inventory_...()` functions
+use the same scheme.
-
-inventory_size(player()) => 41 // items
-inventory_size('enderchest', player()) => 27 // equipment
-inventory_size('equipment', player()) => 6 // equipment
-
If the entity or a block doesn't have
-an inventory, they typically do nothing and return null.
+an inventory, all API functions typically do nothing and return null.
Most items returned are in the form of a triple of item name, count, and nbt or the extra data associated with an item.
-Manipulating of the nbt data can be costly, but retrieving them from the tuple to match other aspects is cheap
### `stack_limit(item)`
@@ -98,14 +99,26 @@ item name that serves as a replacement after crafting is done. Currently it can
### `inventory_size(inventory)`
Returns the size of the inventory for the entity or block in question. Returns null if the block or entity don't
-have an inventory
+have an inventory.
inventory_size(player()) => 41
inventory_size('enderchest', player()) => 27 // enderchest
inventory_size('equipment', player()) => 6 // equipment
+inventory_size(null, player()) => 41 // default inventory for players
+
inventory_size(x,y,z) => 27 // chest
inventory_size(block(pos)) => 5 // hopper
+
+horse = spawn('horse', x, y, z);
+inventory_size(horse); => 2 // default horse inventory
+inventory_size('equipment', horse); => 6 // unused horse equipment inventory
+inventory_size(null, horse); => 2 // default horse
+
+creeper = spawn('creeper', x, y, z);
+inventory_size(creeper); => 6 // default creeper inventory is equipment since it has no other
+inventory_size('equipment', creeper); => 6 // unused horse equipment inventory
+inventory_size(null, creeper); => 6 // creeper default is its equipment
### `inventory_has_items(inventory)`
diff --git a/docs/scarpet/api/Overview.md b/docs/scarpet/api/Overview.md
index 3e6ddbdf..9e9fc5bd 100644
--- a/docs/scarpet/api/Overview.md
+++ b/docs/scarpet/api/Overview.md
@@ -214,6 +214,11 @@ Here is a list of built-in types, with their return value formats, as well as a
* `'players'`: returning a list of valid player name string, logged in or not. If configured with `'single'` returns only one player or `null`.
* `'intrange'`: same as `'floatrange'`, but requiring integers.
* `'enchantment'`: name of an enchantment
+ * `'slot'`: provides a list of inventory type and slot. Can be configured with `'restrict'` requiring
+ `'player'`, `'enderchest'`, `'equipment'`, `'armor'`, `'weapon'`, `'container'`, `'villager'` or `'horse'` restricting selection of
+ available slots. Scarpet supports all vanilla slots, except for `horse.chest` - chest item, not items themselves. This you would
+ need to manage yourself via nbt directly. Also, for entities that change their capacity, like llamas, you need to check yourself if
+ the specified container slot is valid for your entity.
* `'item'`: triple of item type, count of 1, and nbt.
* `'message'`: text with expanded embedded player names
* `'effect'`: string representing a status effect
diff --git a/docs/scarpet/api/Scoreboard.md b/docs/scarpet/api/Scoreboard.md
index d2feb12d..0be72203 100644
--- a/docs/scarpet/api/Scoreboard.md
+++ b/docs/scarpet/api/Scoreboard.md
@@ -27,5 +27,80 @@ for the objective.
### `scoreboard_display(place, objective)`
-sets display location for a specified `objective`. If `objective` is `null`, then display is cleared. If objective is invalid,
+Sets display location for a specified `objective`. If `objective` is `null`, then display is cleared. If objective is invalid,
returns `null`.
+
+# Team
+
+### `team_list()`, `team_list(team)`
+
+Returns all available teams as a list with no arguments.
+
+When a `team` is specified, it returns all the players inside that team. If the `team` is invalid, returns `null`.
+
+### `team_add(team)`, `team_add(team,player)`
+
+With one argument, creates a new `team` and returns its name if successful, or `null` if team already exists.
+
+
+`team_add('admin')` -> Create a team with the name 'admin'
+`team_add('admin','Steve')` -> Joing the player 'Steve' into the team 'admin'
+
+If a `player` is specified, the player will join the given `team`. Returns `true` if player joined the team, or `false` if nothing changed since the player was already in this team. If the team is invalid, returns `null`
+
+### `team_remove(team)`
+
+Removes a `team`. Returns `true` if the team was deleted, or `null` if the team is invalid.
+
+### `team_leave(player)`
+
+Removes the `player` from the team he is in. Returns `true` if the player left a team, otherwise `false`.
+
+`team_leave('Steve')` -> Removes Steve from the team he is currently in
+`for(team_list('admin'), team_leave('admin', _))` -> Remove all players from team 'admin'
+
+### `team_property(team,property,value?)`
+
+Reads the `property` of the `team` if no `value` is specified. If a `value` is added as a third argument, it sets the `property` to that `value`.
+
+* `collisionRule`
+ * Type: String
+ * Options: always, never, pushOtherTeams, pushOwnTeam
+
+* `color`
+ * Type: String
+ * Options: See [team command](https://minecraft.gamepedia.com/Commands/team#Arguments) (same strings as `'teamcolor'` [command argument](https://github.com/gnembon/fabric-carpet/blob/master/docs/scarpet/Full.md#command-argument-types] options))
+
+* `displayName`
+ * Type: String or FormattedText, when querying returns FormattedText
+
+* `prefix`
+ * Type: String or FormattedText, when querying returns FormattedText
+
+* `suffix`
+ * Type: String or FormattedText, when querying returns FormattedText
+
+* `friendlyFire`
+ * Type: boolean
+
+* `seeFriendlyInvisibles`
+ * Type: boolean
+
+* `nametagVisibility`
+ * Type: String
+ * Options: always, never, hideForOtherTeams, hideForOwnTeam
+
+* `deathMessageVisibility`
+ * Type: String
+ * Options: always, never, hideForOtherTeams, hideForOwnTeam
+
+Examples:
+
+```
+team_property('admin','color','dark_red') Make the team color for team 'admin' dark red
+team_property('admin','prefix',format('r Admin | ')) Set prefix of all players in 'admin'
+team_property('admin','display_name','Administrators') Set display name for team 'admin'
+team_property('admin','seeFriendlyInvisibles',true) Make all players in 'admin' see other admins even when invisible
+team_property('admin','deathMessageVisibility','hideForOtherTeams') Make all players in 'admin' see other admins even when invisible
+```
+
diff --git a/docs/scarpet/resources/editors/idea/2.txt b/docs/scarpet/resources/editors/idea/2.txt
index 012ad76f..db4d0d7b 100644
--- a/docs/scarpet/resources/editors/idea/2.txt
+++ b/docs/scarpet/resources/editors/idea/2.txt
@@ -84,6 +84,11 @@ scoreboard
scoreboard_add
scoreboard_remove
scoreboard_display
+team_add
+team_list
+team_remove
+team_leave
+team_property
see_sky
set
set_biome
diff --git a/docs/scarpet/resources/editors/npp/scarpet.xml b/docs/scarpet/resources/editors/npp/scarpet.xml
index cad62780..3ad710dc 100644
--- a/docs/scarpet/resources/editors/npp/scarpet.xml
+++ b/docs/scarpet/resources/editors/npp/scarpet.xml
@@ -60,6 +60,8 @@
scoreboard scoreboard_add scoreboard_remove scoreboard_display
+ team_add team_list team_remove team_leave team_property
+
player spawn entity_id entity_list entity_area entity_selector query modify entity_event entity_load_handler entity_types
stack_limit item_category recipe_data crafting_remaining_item
diff --git a/docs/scarpet/resources/editors/npp/scarpet_v1.7_notepad++.xml b/docs/scarpet/resources/editors/npp/scarpet_v1.7_notepad++.xml
index ffb50e58..a24fe8f0 100644
--- a/docs/scarpet/resources/editors/npp/scarpet_v1.7_notepad++.xml
+++ b/docs/scarpet/resources/editors/npp/scarpet_v1.7_notepad++.xml
@@ -60,6 +60,8 @@
scoreboard scoreboard_add scoreboard_remove scoreboard_display
+ team_add team_list team_remove team_leave team_property
+
player spawn entity_id entity_list entity_area entity_selector query modify entity_event
stack_limit item_category recipe_data crafting_remaining_item
diff --git a/src/main/java/carpet/script/api/Scoreboards.java b/src/main/java/carpet/script/api/Scoreboards.java
index 881bfd26..af653369 100644
--- a/src/main/java/carpet/script/api/Scoreboards.java
+++ b/src/main/java/carpet/script/api/Scoreboards.java
@@ -9,14 +9,20 @@ import carpet.script.value.ListValue;
import carpet.script.value.NullValue;
import carpet.script.value.NumericValue;
import carpet.script.value.StringValue;
+import carpet.script.value.FormattedTextValue;
import carpet.script.value.Value;
import net.minecraft.entity.Entity;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.scoreboard.Scoreboard;
+import net.minecraft.scoreboard.ServerScoreboard;
import net.minecraft.scoreboard.ScoreboardCriterion;
import net.minecraft.scoreboard.ScoreboardObjective;
import net.minecraft.scoreboard.ScoreboardPlayerScore;
+import net.minecraft.scoreboard.Team;
+import net.minecraft.scoreboard.AbstractTeam;
import net.minecraft.text.LiteralText;
+import net.minecraft.text.Text;
+import net.minecraft.util.Formatting;
import java.util.stream.Collectors;
@@ -147,5 +153,249 @@ public class Scoreboards {
scoreboard.setObjectiveSlot(slot, objective);
return (_c, _t) -> new NumericValue(slot);
});
+
+ expression.addLazyFunction("team_list", -1, (c, t, lv) ->
+ {
+ if(lv.size() > 1) throw new InternalExpressionException("'team_list' requires zero or one parameters");
+ CarpetContext cc = (CarpetContext)c;
+ ServerScoreboard scoreboard = cc.s.getMinecraftServer().getScoreboard();
+ if(lv.size() == 0) {
+ Value ret = ListValue.wrap(scoreboard.getTeamNames().stream().map(StringValue::of).collect(Collectors.toList()));
+ return (_c, _t) -> ret;
+ } else if(lv.size() == 1) {
+ Team team = scoreboard.getTeam(lv.get(0).evalValue(c).getString());
+ if(team == null) return LazyValue.NULL;
+ Value ret = ListValue.wrap(team.getPlayerList().stream().map(StringValue::of).collect(Collectors.toList()));
+ return (_c, _t) -> ret;
+ } else {
+ return LazyValue.NULL;
+ }
+ });
+
+
+ expression.addLazyFunction("team_add", -1, (c, t, lv) ->
+ {
+ if(!(lv.size() < 3 && lv.size() > 0)) throw new InternalExpressionException("'team_add' requires one or two parameters");
+
+ CarpetContext cc = (CarpetContext)c;
+ ServerScoreboard scoreboard = cc.s.getMinecraftServer().getScoreboard();
+ String teamName = lv.get(0).evalValue(c).getString();
+
+ if(lv.size() == 1) {
+ if(scoreboard.getTeam(teamName) == null) {
+ scoreboard.addTeam(teamName);
+ Value ret = new StringValue(teamName);
+ return (_c, _t) -> ret;
+ } else {
+ return LazyValue.NULL;
+ }
+ } else if(lv.size() == 2) {
+ Value playerVal = lv.get(1).evalValue(c);
+
+ String player = EntityValue.getPlayerNameByValue(playerVal);
+ if(player == null) return LazyValue.NULL;
+
+ Team team = scoreboard.getTeam(teamName);
+ if(team == null) return LazyValue.NULL;
+
+ if(team.isEqual(scoreboard.getPlayerTeam(player))) {
+ return LazyValue.FALSE;
+ } else {
+ scoreboard.addPlayerToTeam(player,scoreboard.getTeam(teamName));
+ return LazyValue.TRUE;
+ }
+ } else {
+ return LazyValue.NULL;
+ }
+ });
+
+ expression.addLazyFunction("team_remove", 1, (c, t, lv) ->
+ {
+ CarpetContext cc = (CarpetContext)c;
+ ServerScoreboard scoreboard = cc.s.getMinecraftServer().getScoreboard();
+ Value teamVal = lv.get(0).evalValue(c);
+
+ String team = teamVal.getString();
+
+ if(scoreboard.getTeam(team) != null) {
+ scoreboard.removeTeam(scoreboard.getTeam(team));
+ return LazyValue.TRUE;
+ } else {
+ return LazyValue.NULL;
+ }
+ });
+
+
+ expression.addLazyFunction("team_leave", 1, (c, t, lv) ->
+ {
+ CarpetContext cc = (CarpetContext)c;
+ ServerScoreboard scoreboard = cc.s.getMinecraftServer().getScoreboard();
+ Value playerVal = lv.get(0).evalValue(c);
+
+ String player = EntityValue.getPlayerNameByValue(playerVal);
+ if(player == null) return LazyValue.NULL;
+
+ Value ret = new NumericValue(scoreboard.clearPlayerTeam(player));
+ return (_c, _t) -> ret;
+ });
+
+ expression.addLazyFunction("team_property", -1, (c, t, lv) ->
+ {
+ CarpetContext cc = (CarpetContext)c;
+ ServerScoreboard scoreboard = cc.s.getMinecraftServer().getScoreboard();
+
+ if(lv.size() < 2 || lv.size() > 3) throw new InternalExpressionException("'team_property' requires two or three arguments");
+
+ Value teamVal = lv.get(0).evalValue(c);
+ Value propertyVal = lv.get(1).evalValue(c);
+
+ Value settingVal = null;
+ boolean modifying = false;
+ if(lv.size() == 3) {
+ modifying = true;
+ settingVal = lv.get(2).evalValue(c);
+ }
+
+ Team team = scoreboard.getTeam(teamVal.getString());
+ if(team == null) return LazyValue.NULL;
+
+ if(!(propertyVal instanceof StringValue)) throw new InternalExpressionException("'team_property' requires a string as the second argument");
+
+ switch (propertyVal.getString()) {
+ case "collision_rule":
+ if(!modifying) {
+ Value ret = new StringValue(team.getCollisionRule().name);
+ return (_c, _t) -> ret;
+ }
+
+ if(!(settingVal instanceof StringValue)) throw new InternalExpressionException("'team_property' requires a string as the third argument for the property " + propertyVal.getString());
+
+ AbstractTeam.CollisionRule collisionRule = AbstractTeam.CollisionRule.getRule(settingVal.getString());
+ if(collisionRule == null) throw new InternalExpressionException("Unknown value for property " + propertyVal.getString() + ": " + settingVal.getString());
+ team.setCollisionRule(collisionRule);
+ break;
+ case "color":
+ if(!modifying) {
+ Value ret = new StringValue(team.getColor().getName());
+ return (_c, _t) -> ret;
+ }
+
+ if(!(settingVal instanceof StringValue)) throw new InternalExpressionException("'team_property' requires a string as the third argument for the property " + propertyVal.getString());
+
+ Formatting color = Formatting.byName(settingVal.getString().toUpperCase());
+ if(color == null || !color.isColor()) throw new InternalExpressionException("Unknown value for property " + propertyVal.getString() + ": " + settingVal.getString());
+ team.setColor(color);
+
+ break;
+ case "death_message_visibility":
+ if(!modifying) {
+ Value ret = new StringValue(team.getDeathMessageVisibilityRule().name);
+ return (_c, _t) -> ret;
+ }
+
+ if(!(settingVal instanceof StringValue)) throw new InternalExpressionException("'team_property' requires a string as the third argument for the property " + propertyVal.getString());
+
+ AbstractTeam.VisibilityRule deathMessageVisibility = AbstractTeam.VisibilityRule.getRule(settingVal.getString());
+ if(deathMessageVisibility == null) throw new InternalExpressionException("Unknown value for property " + propertyVal.getString() + ": " + settingVal.getString());
+ team.setDeathMessageVisibilityRule(deathMessageVisibility);
+
+ break;
+ case "display_name":
+ if(!modifying) {
+ Value ret = new FormattedTextValue(team.getDisplayName());
+ return (_c, _t) -> ret;
+ }
+
+ if(!(settingVal instanceof StringValue)) throw new InternalExpressionException("'team_property' requires a string or formatted text as the third argument for the property " + propertyVal.getString());
+
+ Text displayName;
+
+ if(settingVal instanceof FormattedTextValue) {
+ displayName = ((FormattedTextValue) settingVal).getText();
+ } else {
+ displayName = new LiteralText(settingVal.getString());
+ }
+
+ team.setDisplayName(displayName);
+
+ break;
+ case "friendly_fire":
+ if(!modifying) {
+ Value ret = new NumericValue(team.isFriendlyFireAllowed());
+ return (_c, _t) -> ret;
+ }
+
+ if(!(settingVal instanceof NumericValue)) throw new InternalExpressionException("'team_property' requires a boolean as the third argument for the property " + propertyVal.getString());
+
+ boolean friendlyFire = settingVal.getBoolean();
+ team.setFriendlyFireAllowed(friendlyFire);
+ break;
+ case "nametag_visibility":
+ if(!modifying) {
+ Value ret = new StringValue(team.getNameTagVisibilityRule().name);
+ return (_c, _t) -> ret;
+ }
+
+ if(!(settingVal instanceof StringValue)) throw new InternalExpressionException("'team_property' requires a string as the third argument for the property " + propertyVal.getString());
+
+ AbstractTeam.VisibilityRule nametagVisibility = AbstractTeam.VisibilityRule.getRule(settingVal.getString());
+ if(nametagVisibility == null) throw new InternalExpressionException("Unknown value for property " + propertyVal.getString() + ": " + settingVal.getString());
+ team.setNameTagVisibilityRule(nametagVisibility);
+
+ break;
+ case "prefix":
+ if(!modifying) {
+ Value ret = new FormattedTextValue(team.getPrefix());
+ return (_c, _t) -> ret;
+ }
+
+ if(!(settingVal instanceof StringValue)) throw new InternalExpressionException("'team_property ' requires a string or formatted text as the third argument for the property " + propertyVal.getString());
+
+ Text prefix;
+
+ if(settingVal instanceof FormattedTextValue) {
+ prefix = ((FormattedTextValue) settingVal).getText();
+ } else {
+ prefix = new LiteralText(settingVal.getString());
+ }
+
+ team.setPrefix(prefix);
+ break;
+ case "see_friendly_invisibles":
+ if(!modifying) {
+ Value ret = new NumericValue(team.shouldShowFriendlyInvisibles());
+ return (_c, _t) -> ret;
+ }
+
+ if(!(settingVal instanceof NumericValue)) throw new InternalExpressionException("'team_property' requires a boolean as the third argument for the property " + propertyVal.getString());
+
+ boolean seeFriendlyInvisibles = settingVal.getBoolean();
+ team.setShowFriendlyInvisibles(seeFriendlyInvisibles);
+
+ break;
+ case "suffix":
+ if(!modifying) {
+ Value ret = new FormattedTextValue(team.getSuffix());
+ return (_c, _t) -> ret;
+ }
+
+ if(!(settingVal instanceof StringValue)) throw new InternalExpressionException("'team_property' requires a string or formatted text as the third argument for the property " + propertyVal.getString());
+
+ Text suffix;
+
+ if(settingVal instanceof FormattedTextValue) {
+ suffix = ((FormattedTextValue) settingVal).getText();
+ } else {
+ suffix = new LiteralText(settingVal.getString());
+ }
+
+ team.setSuffix(suffix);
+ break;
+ default:
+ throw new InternalExpressionException("team property " + propertyVal.getString() + " is not a valid property");
+ }
+ return LazyValue.TRUE;
+ });
}
}
+
diff --git a/src/main/java/carpet/script/command/CommandArgument.java b/src/main/java/carpet/script/command/CommandArgument.java
index 347c8017..2327d93f 100644
--- a/src/main/java/carpet/script/command/CommandArgument.java
+++ b/src/main/java/carpet/script/command/CommandArgument.java
@@ -47,6 +47,7 @@ import net.minecraft.command.argument.EntitySummonArgumentType;
import net.minecraft.command.argument.GameProfileArgumentType;
import net.minecraft.command.argument.IdentifierArgumentType;
import net.minecraft.command.argument.ItemEnchantmentArgumentType;
+import net.minecraft.command.argument.ItemSlotArgumentType;
import net.minecraft.command.argument.ItemStackArgumentType;
import net.minecraft.command.argument.MessageArgumentType;
import net.minecraft.command.argument.MobEffectArgumentType;
@@ -78,11 +79,14 @@ import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Direction;
import net.minecraft.util.math.Vec2f;
import net.minecraft.util.registry.Registry;
+import org.apache.commons.lang3.tuple.Pair;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
+import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.Map;
@@ -158,6 +162,7 @@ public abstract class CommandArgument
),
// item_predicate ?? //same as item but accepts tags, not sure right now
// slot // item_slot
+ new SlotArgument(),
new VanillaUnconfigurableArgument("item", ItemStackArgumentType::itemStack,
(c, p) -> ValueConversions.of(ItemStackArgumentType.getItemStackArgument(c, p).createStack(1, false)), false
),
@@ -849,6 +854,100 @@ public abstract class CommandArgument
return IntArgument::new;
}
}
+ private static class SlotArgument extends CommandArgument
+ {
+ private String restrict;
+ private static final Map