diff --git a/docs/scarpet/Full.md b/docs/scarpet/Full.md index de176790..59ad59c2 100644 --- a/docs/scarpet/Full.md +++ b/docs/scarpet/Full.md @@ -3429,10 +3429,10 @@ If called with `false` value, it will disable AI in the mob. `true` will enable Sets if the entity obeys any collisions, including collisions with the terrain and basic physics. Not affecting players, since they are controlled client side. -### `modify(e, 'effect', name?, duration?, amplifier?, show_particles?, show_icon?)` +### `modify(e, 'effect', name?, duration?, amplifier?, show_particles?, show_icon?, ambient?)` -Applies status effect to the living entity. Takes several optional parameters, which default to `0`, `true` -and `true`. If no duration is specified, or if it's null or 0, the effect is removed. If name is not specified, +Applies status effect to the living entity. Takes several optional parameters, which default to `0`, `true`, +`true` and `false`. If no duration is specified, or if it's null or 0, the effect is removed. If name is not specified, it clears all effects. ### `modify(e, 'home', null), modify(e, 'home', block, distance?), modify(e, 'home', x, y, z, distance?)` @@ -4432,6 +4432,12 @@ Consult section about container operations in `Expression` to learn about possib Excapes all the special characters in the string or nbt tag and returns a string that can be stored in nbt directly as a string value. +### `tag_matches(daddy_tag, baby_tag, match_lists?)` + +Utility returning `true` if `baby_tag` is fully contained in `daddy_tag`. Anything matches `null` baby tag, and +Nothing is contained in a `null` daddy tag. If `match_lists` is specified and `false`, content of nested lists is ignored. +Default behaviour is to match them. + ### `parse_nbt(tag)` Converts NBT tag to a scarpet value, which you can navigate through much better. @@ -4514,6 +4520,18 @@ Example usages: // not a problem in apps +### `display_title(players, type, title?, fadeInTicks?, stayTicks?, fadeOutTicks),` + +Sends the player (or players if `players` is a list) a title of a specific type, with optionally some times. + * `players` is either an online player or a list of players. When sending a single player, it will throw if the player is invalid or offline. + * `type` is either `'title'`, `'subtitle'`, `actionbar` or `clear`. + Note: `subtitle` will only be displayed if there is a title being displayed (can be an empty one) + * `title` is what title to send to the player. It is required except for `clear` type. Can be a text formatted using `format()` + * `...Ticks` are the number of ticks the title will stay in that state. + If not specified, it will use current defaults (those defaults may have changed from a previous `/title times` execution). + Executing with those will set the times to the specified ones. + Note that `actionbar` type doesn't support changing times (vanilla bug, see [MC-106167](https://bugs.mojang.com/browse/MC-106167)). + ### `logger(msg), logger(type, msg)` Prints the message to system logs, and not to chat. By default prints an info, unless you specify otherwise in the `type` parameter. @@ -4738,7 +4756,7 @@ Available options in the scarpet app space: * `world_seed` - a numeric seed of the world * `world_path` - full path to the world saves folder * `world_folder` - name of the direct folder in the saves that holds world files - * `world_carpet_rules` - returns all Carpet rules in a map form (`rule`->`value`). Includes rules from extensions with their namespace (`namespace:rule`->`value`). You can later listen to rule changes with the `on_carpet_rule_change(rule, newValue)` event. + * `world_carpet_rules` - returns all Carpet rules in a map form (`rule`->`value`). Note that the values are always returned as strings, so you can't do boolean comparisons directly. Includes rules from extensions with their namespace (`namespace:rule`->`value`). You can later listen to rule changes with the `on_carpet_rule_changes(rule, newValue)` event. Relevant gameplay related properties * `game_difficulty` - current difficulty of the game: `'peacefu'`, `'easy'`, `'normal'`, or `'hard'` diff --git a/docs/scarpet/api/Auxiliary.md b/docs/scarpet/api/Auxiliary.md index 3f2ddcd9..e5e9209b 100644 --- a/docs/scarpet/api/Auxiliary.md +++ b/docs/scarpet/api/Auxiliary.md @@ -163,6 +163,12 @@ Consult section about container operations in `Expression` to learn about possib Excapes all the special characters in the string or nbt tag and returns a string that can be stored in nbt directly as a string value. +### `tag_matches(daddy_tag, baby_tag, match_lists?)` + +Utility returning `true` if `baby_tag` is fully contained in `daddy_tag`. Anything matches `null` baby tag, and +Nothing is contained in a `null` daddy tag. If `match_lists` is specified and `false`, content of nested lists is ignored. +Default behaviour is to match them. + ### `parse_nbt(tag)` Converts NBT tag to a scarpet value, which you can navigate through much better. @@ -245,6 +251,18 @@ Example usages: // not a problem in apps +### `display_title(players, type, title?, fadeInTicks?, stayTicks?, fadeOutTicks),` + +Sends the player (or players if `players` is a list) a title of a specific type, with optionally some times. + * `players` is either an online player or a list of players. When sending a single player, it will throw if the player is invalid or offline. + * `type` is either `'title'`, `'subtitle'`, `actionbar` or `clear`. + Note: `subtitle` will only be displayed if there is a title being displayed (can be an empty one) + * `title` is what title to send to the player. It is required except for `clear` type. Can be a text formatted using `format()` + * `...Ticks` are the number of ticks the title will stay in that state. + If not specified, it will use current defaults (those defaults may have changed from a previous `/title times` execution). + Executing with those will set the times to the specified ones. + Note that `actionbar` type doesn't support changing times (vanilla bug, see [MC-106167](https://bugs.mojang.com/browse/MC-106167)). + ### `logger(msg), logger(type, msg)` Prints the message to system logs, and not to chat. By default prints an info, unless you specify otherwise in the `type` parameter. @@ -469,7 +487,7 @@ Available options in the scarpet app space: * `world_seed` - a numeric seed of the world * `world_path` - full path to the world saves folder * `world_folder` - name of the direct folder in the saves that holds world files - * `world_carpet_rules` - returns all Carpet rules in a map form (`rule`->`value`). Includes rules from extensions with their namespace (`namespace:rule`->`value`). You can later listen to rule changes with the `on_carpet_rule_change(rule, newValue)` event. + * `world_carpet_rules` - returns all Carpet rules in a map form (`rule`->`value`). Note that the values are always returned as strings, so you can't do boolean comparisons directly. Includes rules from extensions with their namespace (`namespace:rule`->`value`). You can later listen to rule changes with the `on_carpet_rule_changes(rule, newValue)` event. Relevant gameplay related properties * `game_difficulty` - current difficulty of the game: `'peacefu'`, `'easy'`, `'normal'`, or `'hard'` diff --git a/docs/scarpet/api/Entities.md b/docs/scarpet/api/Entities.md index 794ecc6b..a60d426c 100644 --- a/docs/scarpet/api/Entities.md +++ b/docs/scarpet/api/Entities.md @@ -641,10 +641,10 @@ If called with `false` value, it will disable AI in the mob. `true` will enable Sets if the entity obeys any collisions, including collisions with the terrain and basic physics. Not affecting players, since they are controlled client side. -### `modify(e, 'effect', name?, duration?, amplifier?, show_particles?, show_icon?)` +### `modify(e, 'effect', name?, duration?, amplifier?, show_particles?, show_icon?, ambient?)` -Applies status effect to the living entity. Takes several optional parameters, which default to `0`, `true` -and `true`. If no duration is specified, or if it's null or 0, the effect is removed. If name is not specified, +Applies status effect to the living entity. Takes several optional parameters, which default to `0`, `true`, +`true` and `false`. If no duration is specified, or if it's null or 0, the effect is removed. If name is not specified, it clears all effects. ### `modify(e, 'home', null), modify(e, 'home', block, distance?), modify(e, 'home', x, y, z, distance?)` diff --git a/docs/scarpet/resources/editors/idea/2.txt b/docs/scarpet/resources/editors/idea/2.txt index ae16592b..642a8bc5 100644 --- a/docs/scarpet/resources/editors/idea/2.txt +++ b/docs/scarpet/resources/editors/idea/2.txt @@ -19,11 +19,14 @@ create_marker current_dimension custom_dimension day_time +delete_file destroy diamond +display_title draw_shape drop_item emitted_light +encode_nbt entity_area entity_event entity_id @@ -61,6 +64,7 @@ modify nbt neighbours opacity +parse_nbt particle particle_line particle_rect @@ -86,11 +90,13 @@ scoreboard scoreboard_add scoreboard_remove scoreboard_display +tag_matches team_add team_list team_remove team_leave team_property +read_file see_sky set set_biome @@ -118,4 +124,5 @@ update view_distance volume without_updates -world_time \ No newline at end of file +world_time +write_file \ No newline at end of file diff --git a/docs/scarpet/resources/editors/npp/scarpet.xml b/docs/scarpet/resources/editors/npp/scarpet.xml index 92da9036..65a7800d 100644 --- a/docs/scarpet/resources/editors/npp/scarpet.xml +++ b/docs/scarpet/resources/editors/npp/scarpet.xml @@ -58,6 +58,8 @@ structure_eligibility structures structure_references set_structure reset_chunk reload_chunk custom_dimension add_chunk_ticket + display_title + scoreboard scoreboard_add scoreboard_remove scoreboard_display team_add team_list team_remove team_leave team_property @@ -78,7 +80,8 @@ plop harvest destroy schedule nbt draw_shape create_marker remove_all_markers - load_app_data store_app_data escape_nbt statistic + load_app_data store_app_data read_file write_file delete_file + escape_nbt parse_nbt encode_nbt tag_matches statistic euler pi null true false x y z p diff --git a/src/main/java/carpet/fakes/BlockPredicateInterface.java b/src/main/java/carpet/fakes/BlockPredicateInterface.java new file mode 100644 index 00000000..cd1e4349 --- /dev/null +++ b/src/main/java/carpet/fakes/BlockPredicateInterface.java @@ -0,0 +1,17 @@ +package carpet.fakes; + +import carpet.script.value.Value; +import net.minecraft.block.Block; +import net.minecraft.block.BlockState; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.tag.Tag; + +import java.util.Map; + +public interface BlockPredicateInterface +{ + BlockState getCMBlockState(); + Tag getCMBlockTag(); + Map getCMProperties(); + CompoundTag getCMDataTag(); +} diff --git a/src/main/java/carpet/mixins/StatePredicate_scarpetMixin.java b/src/main/java/carpet/mixins/StatePredicate_scarpetMixin.java new file mode 100644 index 00000000..5ef599e9 --- /dev/null +++ b/src/main/java/carpet/mixins/StatePredicate_scarpetMixin.java @@ -0,0 +1,57 @@ +package carpet.mixins; + +import carpet.fakes.BlockPredicateInterface; +import carpet.script.value.StringValue; +import carpet.script.value.Value; +import carpet.script.value.ValueConversions; +import net.minecraft.block.Block; +import net.minecraft.block.BlockState; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.state.property.Property; +import net.minecraft.tag.Tag; +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; + +import java.util.Map; +import java.util.Set; +import java.util.stream.Collectors; + +@Mixin(targets = "net.minecraft.command.argument.BlockPredicateArgumentType$StatePredicate") +public class StatePredicate_scarpetMixin implements BlockPredicateInterface +{ + + @Shadow @Final private BlockState state; + + @Shadow @Final /*@Nullable*/ private CompoundTag nbt; + + @Shadow @Final private Set> properties; + + @Override + public BlockState getCMBlockState() + { + return state; + } + + @Override + public Tag getCMBlockTag() + { + return null; + } + + @Override + public Map getCMProperties() + { + return properties.stream().collect(Collectors.toMap( + p -> StringValue.of(p.getName()), + p -> ValueConversions.fromProperty(state, p), + (a, b) -> b + )); + } + + @Override + public CompoundTag getCMDataTag() + { + return nbt; + } +} diff --git a/src/main/java/carpet/mixins/TagPredicate_scarpetMixin.java b/src/main/java/carpet/mixins/TagPredicate_scarpetMixin.java new file mode 100644 index 00000000..f64062e0 --- /dev/null +++ b/src/main/java/carpet/mixins/TagPredicate_scarpetMixin.java @@ -0,0 +1,52 @@ +package carpet.mixins; + +import carpet.fakes.BlockPredicateInterface; +import carpet.script.value.StringValue; +import carpet.script.value.Value; +import net.minecraft.block.Block; +import net.minecraft.block.BlockState; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.tag.Tag; +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; + +import java.util.Map; +import java.util.stream.Collectors; + +@Mixin(targets = "net.minecraft.command.argument.BlockPredicateArgumentType$TagPredicate") +public class TagPredicate_scarpetMixin implements BlockPredicateInterface +{ + @Shadow @Final private Tag tag; + + @Shadow @Final private Map properties; + + @Shadow @Final /*@Nullable*/ private CompoundTag nbt; + + @Override + public BlockState getCMBlockState() + { + return null; + } + + @Override + public Tag getCMBlockTag() + { + return tag; + } + + @Override + public Map getCMProperties() + { + return properties.entrySet().stream().collect(Collectors.toMap( + e -> new StringValue(e.getKey()), + e -> new StringValue(e.getValue()) + )); + } + + @Override + public CompoundTag getCMDataTag() + { + return nbt; + } +} diff --git a/src/main/java/carpet/script/api/Auxiliary.java b/src/main/java/carpet/script/api/Auxiliary.java index 3a7f080b..a873f804 100644 --- a/src/main/java/carpet/script/api/Auxiliary.java +++ b/src/main/java/carpet/script/api/Auxiliary.java @@ -40,13 +40,17 @@ import net.minecraft.entity.EquipmentSlot; import net.minecraft.entity.decoration.ArmorStandEntity; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NbtHelper; import net.minecraft.nbt.StringTag; import net.minecraft.nbt.Tag; import net.minecraft.network.packet.s2c.play.PlaySoundIdS2CPacket; +import net.minecraft.network.packet.s2c.play.TitleS2CPacket; +import net.minecraft.network.packet.s2c.play.TitleS2CPacket.Action; import net.minecraft.particle.ParticleEffect; import net.minecraft.server.MinecraftServer; import net.minecraft.server.command.CommandOutput; import net.minecraft.server.command.ServerCommandSource; +import net.minecraft.server.network.ServerPlayNetworkHandler; import net.minecraft.server.network.ServerPlayerEntity; import net.minecraft.server.world.ServerWorld; import net.minecraft.sound.SoundCategory; @@ -73,7 +77,9 @@ import java.util.HashMap; import java.util.List; import java.util.Locale; import java.util.Map; +import java.util.concurrent.atomic.AtomicInteger; import java.util.stream.Collectors; +import java.util.stream.Stream; import static java.lang.Math.max; import static java.lang.Math.min; @@ -400,13 +406,23 @@ public class Auxiliary { Value parsed = ((NBTSerializableValue) v).toValue(); return (cc, tt) -> parsed; } - NBTSerializableValue ret = NBTSerializableValue.parseString(v.getString()); + NBTSerializableValue ret = NBTSerializableValue.parseString(v.getString(), false); if (ret == null) return LazyValue.NULL; Value parsed = ret.toValue(); return (cc, tt) -> parsed; }); + expression.addFunction("tag_matches", (lv) -> { + int numParam = lv.size(); + if (numParam != 2 && numParam != 3) throw new InternalExpressionException("'tag_matches' requires 2 or 3 arguments"); + if (lv.get(1).isNull()) return Value.TRUE; + if (lv.get(0).isNull()) return Value.FALSE; + Tag source = ((NBTSerializableValue)(NBTSerializableValue.fromValue(lv.get(0)))).getTag(); + Tag match = ((NBTSerializableValue)(NBTSerializableValue.fromValue(lv.get(1)))).getTag(); + return new NumericValue(NbtHelper.matches(match, source, numParam == 2 || lv.get(2).getBoolean())); + }); + expression.addLazyFunction("encode_nbt", -1, (c, t, lv) -> { int argSize = lv.size(); if (argSize==0 || argSize > 2) throw new InternalExpressionException("'encode_nbt' requires 1 or 2 parameters"); @@ -434,6 +450,7 @@ public class Auxiliary { if (lv.size() == 2) { ServerPlayerEntity player = EntityValue.getPlayerByValue(s.getMinecraftServer(), res); + if (player == null) return LazyValue.NULL; s = player.getCommandSource(); res = lv.get(1).evalValue(c); } @@ -455,6 +472,66 @@ public class Auxiliary { Value finalRes = res; return (_c, _t) -> finalRes; // pass through for variables }); + expression.addLazyFunction("display_title", -1, (c, t, lv) -> { + if (lv.size() < 2) throw new InternalExpressionException("'display_title' needs at least a target, type and message, and optionally times"); + Value pVal = lv.get(0).evalValue(c); + if (!(pVal instanceof ListValue)) pVal = ListValue.of(pVal); + MinecraftServer server = ((CarpetContext)c).s.getMinecraftServer(); + Stream targets = ((ListValue) pVal).getItems().stream().map(v -> + { + ServerPlayerEntity player = EntityValue.getPlayerByValue(server, v); + if (player == null) throw new InternalExpressionException("'display_title' requires a valid online player or a list of players as first argument. "+v.getString()+" is not a player."); + return player; + }); + TitleS2CPacket.Action action; + switch (lv.get(1).evalValue(c).getString().toLowerCase(Locale.ROOT)) + { + case "title": + action = Action.TITLE; + break; + case "subtitle": + action = Action.SUBTITLE; + break; + case "actionbar": + action = Action.ACTIONBAR; + break; + case "clear": + action = Action.CLEAR; + break; + default: + throw new InternalExpressionException("'display_title' requires 'title', 'subtitle', 'actionbar' or 'clear' as second argument"); + } + if (action != Action.CLEAR && lv.size() < 3) + throw new InternalExpressionException("Third argument of 'display_title' must be present except for 'clear' type"); + Text title = null; + if (lv.size() > 2) + { + pVal = lv.get(2).evalValue(c); + if (pVal instanceof FormattedTextValue) + title = ((FormattedTextValue) pVal).getText(); + else + title = Text.of(pVal.getString()); + } + TitleS2CPacket timesPacket; + if (lv.size() > 3) + { + int in = NumericValue.asNumber(lv.get(3).evalValue(c),"fade in for display_title" ).getInt(); + int stay = NumericValue.asNumber(lv.get(4).evalValue(c),"stay for display_title" ).getInt(); + int out = NumericValue.asNumber(lv.get(5).evalValue(c),"fade out for display_title" ).getInt(); + timesPacket = new TitleS2CPacket(Action.TIMES, null, in, stay, out); + } + else timesPacket = null; + + TitleS2CPacket packet = new TitleS2CPacket(action, title); + AtomicInteger total = new AtomicInteger(0); + targets.forEach(p -> { + if (timesPacket != null) p.networkHandler.sendPacket(timesPacket); + p.networkHandler.sendPacket(packet); + total.getAndIncrement(); + }); + Value ret = NumericValue.of(total.get()); + return (cc, tt) -> ret; + }); expression.addLazyFunction("format", -1, (c, t, lv) -> { if (lv.size() == 0 ) throw new InternalExpressionException("'format' requires at least one component"); diff --git a/src/main/java/carpet/script/api/Entities.java b/src/main/java/carpet/script/api/Entities.java index a836dec3..361e0e9f 100644 --- a/src/main/java/carpet/script/api/Entities.java +++ b/src/main/java/carpet/script/api/Entities.java @@ -137,7 +137,7 @@ public class Entities { { Value nbt = lv.get(position.offset).evalValue(c); NBTSerializableValue v = (nbt instanceof NBTSerializableValue) ? (NBTSerializableValue) nbt - : NBTSerializableValue.parseString(nbt.getString()); + : NBTSerializableValue.parseString(nbt.getString(), true); hasTag = true; tag = v.getCompoundTag(); diff --git a/src/main/java/carpet/script/api/WorldAccess.java b/src/main/java/carpet/script/api/WorldAccess.java index 258c6b59..75b0c711 100644 --- a/src/main/java/carpet/script/api/WorldAccess.java +++ b/src/main/java/carpet/script/api/WorldAccess.java @@ -808,9 +808,7 @@ public class WorldAccess { tag = ((NBTSerializableValue) tagValue).getCompoundTag(); else { - NBTSerializableValue readTag = NBTSerializableValue.parseString(tagValue.getString()); - if (readTag == null) - throw new InternalExpressionException("Incorrect tag: "+tagValue.getString()); + NBTSerializableValue readTag = NBTSerializableValue.parseString(tagValue.getString(), true); tag = readTag.getCompoundTag(); } } diff --git a/src/main/java/carpet/script/command/CommandArgument.java b/src/main/java/carpet/script/command/CommandArgument.java index 2327d93f..97234e4d 100644 --- a/src/main/java/carpet/script/command/CommandArgument.java +++ b/src/main/java/carpet/script/command/CommandArgument.java @@ -36,6 +36,7 @@ import net.minecraft.advancement.Advancement; import net.minecraft.command.CommandSource; import net.minecraft.command.argument.AngleArgumentType; import net.minecraft.command.argument.BlockPosArgumentType; +import net.minecraft.command.argument.BlockPredicateArgumentType; import net.minecraft.command.argument.BlockStateArgument; import net.minecraft.command.argument.BlockStateArgumentType; import net.minecraft.command.argument.ColorArgumentType; @@ -126,6 +127,9 @@ public abstract class CommandArgument }, false ), + new VanillaUnconfigurableArgument( "blockpredicate", BlockPredicateArgumentType::blockPredicate, + (c, p) -> ValueConversions.ofBlockPredicate(c.getSource().getMinecraftServer().getTagManager(), BlockPredicateArgumentType.getBlockPredicate(c, p)), false + ), // block_predicate todo - not sure about the returned format. Needs to match block tags used in the API (future) new VanillaUnconfigurableArgument("teamcolor", ColorArgumentType::color, (c, p) -> { diff --git a/src/main/java/carpet/script/value/EntityValue.java b/src/main/java/carpet/script/value/EntityValue.java index 0fedc0bc..ce1248ab 100644 --- a/src/main/java/carpet/script/value/EntityValue.java +++ b/src/main/java/carpet/script/value/EntityValue.java @@ -1271,7 +1271,10 @@ public class EntityValue extends Value boolean showIcon = true; if (lv.size() > 4) showIcon = lv.get(4).getBoolean(); - le.addStatusEffect(new StatusEffectInstance(effect, duration, amplifier, showParticles, showIcon)); + boolean ambient = false; + if (lv.size() > 5) + showIcon = lv.get(5).getBoolean(); + le.addStatusEffect(new StatusEffectInstance(effect, duration, amplifier, ambient, showParticles, showIcon)); return; } } @@ -1284,7 +1287,7 @@ public class EntityValue extends Value le.removeStatusEffect(effect); return; } - throw new InternalExpressionException("'effect' needs either no arguments (clear) or effect name, duration, and optional amplifier, show particles and show icon"); + throw new InternalExpressionException("'effect' needs either no arguments (clear) or effect name, duration, and optional amplifier, show particles, show icon and ambient"); }); put("gamemode", (e,v)->{ diff --git a/src/main/java/carpet/script/value/NBTSerializableValue.java b/src/main/java/carpet/script/value/NBTSerializableValue.java index 9471b7f3..f8bc58e3 100644 --- a/src/main/java/carpet/script/value/NBTSerializableValue.java +++ b/src/main/java/carpet/script/value/NBTSerializableValue.java @@ -104,7 +104,7 @@ public class NBTSerializableValue extends Value implements ContainerValueInterfa return id.toString(); } - public static NBTSerializableValue parseString(String nbtString) + public static NBTSerializableValue parseString(String nbtString, boolean fail) { Tag tag; try @@ -113,7 +113,8 @@ public class NBTSerializableValue extends Value implements ContainerValueInterfa } catch (CommandSyntaxException e) { - throw new InternalExpressionException("Incorrect NBT tag: nbtString"); + if (fail) throw new InternalExpressionException("Incorrect NBT tag: "+ nbtString); + return null; } NBTSerializableValue value = new NBTSerializableValue(tag); value.nbtString = null; @@ -331,7 +332,7 @@ public class NBTSerializableValue extends Value implements ContainerValueInterfa return v; if (v instanceof NullValue) return Value.NULL; - return NBTSerializableValue.parseString(v.getString()); + return NBTSerializableValue.parseString(v.getString(), true); } diff --git a/src/main/java/carpet/script/value/NumericValue.java b/src/main/java/carpet/script/value/NumericValue.java index b4e47501..caec9776 100644 --- a/src/main/java/carpet/script/value/NumericValue.java +++ b/src/main/java/carpet/script/value/NumericValue.java @@ -227,7 +227,7 @@ public class NumericValue extends Value } public NumericValue(boolean boolval) { - this(boolval?1.0D:0.0D); + this(boolval?1L:0L); } @Override diff --git a/src/main/java/carpet/script/value/ValueConversions.java b/src/main/java/carpet/script/value/ValueConversions.java index a47887ba..adb26099 100644 --- a/src/main/java/carpet/script/value/ValueConversions.java +++ b/src/main/java/carpet/script/value/ValueConversions.java @@ -1,9 +1,11 @@ package carpet.script.value; +import carpet.fakes.BlockPredicateInterface; import carpet.script.exception.InternalExpressionException; import carpet.utils.BlockInfo; import net.minecraft.block.BlockState; import net.minecraft.block.MapColor; +import net.minecraft.block.pattern.CachedBlockPosition; import net.minecraft.entity.Entity; import net.minecraft.entity.ai.brain.LookTarget; import net.minecraft.entity.ai.brain.WalkTarget; @@ -21,6 +23,7 @@ import net.minecraft.server.world.ServerWorld; import net.minecraft.state.property.Property; import net.minecraft.structure.StructurePiece; import net.minecraft.structure.StructureStart; +import net.minecraft.tag.TagManager; import net.minecraft.util.Identifier; import net.minecraft.util.StringIdentifiable; @@ -40,6 +43,7 @@ import java.util.Locale; import java.util.Map; import java.util.Set; import java.util.UUID; +import java.util.function.Predicate; import java.util.stream.Collectors; public class ValueConversions @@ -379,4 +383,15 @@ public class ValueConversions if (ret == null) return ListValue.of(Value.NULL, NumericValue.of(itemSlot)); return ret; } + + public static Value ofBlockPredicate(TagManager tagManager, Predicate blockPredicate) + { + BlockPredicateInterface predicateData = (BlockPredicateInterface) blockPredicate; + return ListValue.of( + predicateData.getCMBlockState()==null?Value.NULL:of(Registry.BLOCK.getId(predicateData.getCMBlockState().getBlock())), + predicateData.getCMBlockTag()==null?Value.NULL:of(tagManager.getBlocks().getTagId(predicateData.getCMBlockTag())), + MapValue.wrap(predicateData.getCMProperties()), + predicateData.getCMDataTag() == null?Value.NULL:new NBTSerializableValue(predicateData.getCMDataTag()) + ); + } } diff --git a/src/main/resources/carpet.mixins.json b/src/main/resources/carpet.mixins.json index efb7510a..8bf78b46 100644 --- a/src/main/resources/carpet.mixins.json +++ b/src/main/resources/carpet.mixins.json @@ -176,6 +176,8 @@ "RecipeManager_scarpetMixin", "Ingredient_scarpetMixin", "BlockStateArgument_scarpetMixin", + "StatePredicate_scarpetMixin", + "TagPredicate_scarpetMixin", "HorseBaseEntity_scarpetMixin", "PillagerEntity_scarpetMixin",