added support for block predicate argument support and tag_matches function. Fixes #563

This commit is contained in:
gnembon committed 2020-11-29 00:33:01 -04:00
1 parent 076ad62fad
commit e15afd9763
16 files changed
+187 -13

No files matched your search

+6
View File
@@ -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 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. 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)` ### `parse_nbt(tag)`
Converts NBT tag to a scarpet value, which you can navigate through much better. Converts NBT tag to a scarpet value, which you can navigate through much better.
+7 -1
View File
@@ -19,12 +19,14 @@ create_marker
current_dimension current_dimension
custom_dimension custom_dimension
day_time day_time
delete_file
destroy destroy
diamond diamond
display_title display_title
draw_shape draw_shape
drop_item drop_item
emitted_light emitted_light
encode_nbt
entity_area entity_area
entity_event entity_event
entity_id entity_id
@@ -62,6 +64,7 @@ modify
nbt nbt
neighbours neighbours
opacity opacity
parse_nbt
particle particle
particle_line particle_line
particle_rect particle_rect
@@ -87,11 +90,13 @@ scoreboard
scoreboard_add scoreboard_add
scoreboard_remove scoreboard_remove
scoreboard_display scoreboard_display
tag_matches
team_add team_add
team_list team_list
team_remove team_remove
team_leave team_leave
team_property team_property
read_file
see_sky see_sky
set set
set_biome set_biome
@@ -119,4 +124,5 @@ update
view_distance view_distance
volume volume
without_updates without_updates
world_time world_time
write_file
@@ -80,7 +80,8 @@
plop harvest destroy schedule nbt draw_shape create_marker remove_all_markers 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
</Keywords> </Keywords>
<Keywords name="Keywords3">euler pi null true false</Keywords> <Keywords name="Keywords3">euler pi null true false</Keywords>
<Keywords name="Keywords4">x y z p</Keywords> <Keywords name="Keywords4">x y z p</Keywords>
+1 -1
View File
@@ -6,7 +6,7 @@ org.gradle.jvmargs=-Xmx1G
# or better: https://modmuss50.me/fabric.html # or better: https://modmuss50.me/fabric.html
minecraft_version=1.16.4 minecraft_version=1.16.4
yarn_mappings=1.16.4+build.7 yarn_mappings=1.16.4+build.7
loader_version=0.10.7 loader_version=0.10.8
# Mod Properties # Mod Properties
mod_version = 1.4.19+v201125 mod_version = 1.4.19+v201125
@@ -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<Block> getCMBlockTag();
Map<Value, Value> getCMProperties();
CompoundTag getCMDataTag();
}
@@ -0,0 +1,58 @@
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.command.argument.BlockPredicateArgumentType;
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(BlockPredicateArgumentType.StatePredicate.class)
public class StatePredicate_scarpetMixin implements BlockPredicateInterface
{
@Shadow @Final private BlockState state;
@Shadow @Final /*@Nullable*/ private CompoundTag nbt;
@Shadow @Final private Set<Property<?>> properties;
@Override
public BlockState getCMBlockState()
{
return state;
}
@Override
public Tag<Block> getCMBlockTag()
{
return null;
}
@Override
public Map<Value, Value> 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;
}
}
@@ -0,0 +1,53 @@
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.command.argument.BlockPredicateArgumentType;
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(BlockPredicateArgumentType.TagPredicate.class)
public class TagPredicate_scarpetMixin implements BlockPredicateInterface
{
@Shadow @Final private Tag<Block> tag;
@Shadow @Final private Map<String, String> properties;
@Shadow @Final /*@Nullable*/ private CompoundTag nbt;
@Override
public BlockState getCMBlockState()
{
return null;
}
@Override
public Tag<Block> getCMBlockTag()
{
return tag;
}
@Override
public Map<Value, Value> getCMProperties()
{
return properties.entrySet().stream().collect(Collectors.toMap(
e -> new StringValue(e.getKey()),
e -> new StringValue(e.getValue())
));
}
@Override
public CompoundTag getCMDataTag()
{
return nbt;
}
}
+12 -1
View File
@@ -40,6 +40,7 @@ import net.minecraft.entity.EquipmentSlot;
import net.minecraft.entity.decoration.ArmorStandEntity; import net.minecraft.entity.decoration.ArmorStandEntity;
import net.minecraft.entity.player.PlayerEntity; import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.ItemStack; import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NbtHelper;
import net.minecraft.nbt.StringTag; import net.minecraft.nbt.StringTag;
import net.minecraft.nbt.Tag; import net.minecraft.nbt.Tag;
import net.minecraft.network.packet.s2c.play.PlaySoundIdS2CPacket; import net.minecraft.network.packet.s2c.play.PlaySoundIdS2CPacket;
@@ -405,13 +406,23 @@ public class Auxiliary {
Value parsed = ((NBTSerializableValue) v).toValue(); Value parsed = ((NBTSerializableValue) v).toValue();
return (cc, tt) -> parsed; return (cc, tt) -> parsed;
} }
NBTSerializableValue ret = NBTSerializableValue.parseString(v.getString()); NBTSerializableValue ret = NBTSerializableValue.parseString(v.getString(), false);
if (ret == null) if (ret == null)
return LazyValue.NULL; return LazyValue.NULL;
Value parsed = ret.toValue(); Value parsed = ret.toValue();
return (cc, tt) -> parsed; 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) -> { expression.addLazyFunction("encode_nbt", -1, (c, t, lv) -> {
int argSize = lv.size(); int argSize = lv.size();
if (argSize==0 || argSize > 2) throw new InternalExpressionException("'encode_nbt' requires 1 or 2 parameters"); if (argSize==0 || argSize > 2) throw new InternalExpressionException("'encode_nbt' requires 1 or 2 parameters");
@@ -137,7 +137,7 @@ public class Entities {
{ {
Value nbt = lv.get(position.offset).evalValue(c); Value nbt = lv.get(position.offset).evalValue(c);
NBTSerializableValue v = (nbt instanceof NBTSerializableValue) ? (NBTSerializableValue) nbt NBTSerializableValue v = (nbt instanceof NBTSerializableValue) ? (NBTSerializableValue) nbt
: NBTSerializableValue.parseString(nbt.getString()); : NBTSerializableValue.parseString(nbt.getString(), true);
hasTag = true; hasTag = true;
tag = v.getCompoundTag(); tag = v.getCompoundTag();
@@ -808,9 +808,7 @@ public class WorldAccess {
tag = ((NBTSerializableValue) tagValue).getCompoundTag(); tag = ((NBTSerializableValue) tagValue).getCompoundTag();
else else
{ {
NBTSerializableValue readTag = NBTSerializableValue.parseString(tagValue.getString()); NBTSerializableValue readTag = NBTSerializableValue.parseString(tagValue.getString(), true);
if (readTag == null)
throw new InternalExpressionException("Incorrect tag: "+tagValue.getString());
tag = readTag.getCompoundTag(); tag = readTag.getCompoundTag();
} }
} }
@@ -36,6 +36,7 @@ import net.minecraft.advancement.Advancement;
import net.minecraft.command.CommandSource; import net.minecraft.command.CommandSource;
import net.minecraft.command.argument.AngleArgumentType; import net.minecraft.command.argument.AngleArgumentType;
import net.minecraft.command.argument.BlockPosArgumentType; import net.minecraft.command.argument.BlockPosArgumentType;
import net.minecraft.command.argument.BlockPredicateArgumentType;
import net.minecraft.command.argument.BlockStateArgument; import net.minecraft.command.argument.BlockStateArgument;
import net.minecraft.command.argument.BlockStateArgumentType; import net.minecraft.command.argument.BlockStateArgumentType;
import net.minecraft.command.argument.ColorArgumentType; import net.minecraft.command.argument.ColorArgumentType;
@@ -126,6 +127,9 @@ public abstract class CommandArgument
}, },
false 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) // block_predicate todo - not sure about the returned format. Needs to match block tags used in the API (future)
new VanillaUnconfigurableArgument("teamcolor", ColorArgumentType::color, new VanillaUnconfigurableArgument("teamcolor", ColorArgumentType::color,
(c, p) -> { (c, p) -> {
@@ -104,7 +104,7 @@ public class NBTSerializableValue extends Value implements ContainerValueInterfa
return id.toString(); return id.toString();
} }
public static NBTSerializableValue parseString(String nbtString) public static NBTSerializableValue parseString(String nbtString, boolean fail)
{ {
Tag tag; Tag tag;
try try
@@ -113,7 +113,8 @@ public class NBTSerializableValue extends Value implements ContainerValueInterfa
} }
catch (CommandSyntaxException e) 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); NBTSerializableValue value = new NBTSerializableValue(tag);
value.nbtString = null; value.nbtString = null;
@@ -331,7 +332,7 @@ public class NBTSerializableValue extends Value implements ContainerValueInterfa
return v; return v;
if (v instanceof NullValue) if (v instanceof NullValue)
return Value.NULL; return Value.NULL;
return NBTSerializableValue.parseString(v.getString()); return NBTSerializableValue.parseString(v.getString(), true);
} }
@@ -227,7 +227,7 @@ public class NumericValue extends Value
} }
public NumericValue(boolean boolval) public NumericValue(boolean boolval)
{ {
this(boolval?1.0D:0.0D); this(boolval?1L:0L);
} }
@Override @Override
@@ -1,9 +1,11 @@
package carpet.script.value; package carpet.script.value;
import carpet.fakes.BlockPredicateInterface;
import carpet.script.exception.InternalExpressionException; import carpet.script.exception.InternalExpressionException;
import carpet.utils.BlockInfo; import carpet.utils.BlockInfo;
import net.minecraft.block.BlockState; import net.minecraft.block.BlockState;
import net.minecraft.block.MaterialColor; import net.minecraft.block.MaterialColor;
import net.minecraft.block.pattern.CachedBlockPosition;
import net.minecraft.entity.Entity; import net.minecraft.entity.Entity;
import net.minecraft.entity.ai.brain.LookTarget; import net.minecraft.entity.ai.brain.LookTarget;
import net.minecraft.entity.ai.brain.WalkTarget; 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.state.property.Property;
import net.minecraft.structure.StructurePiece; import net.minecraft.structure.StructurePiece;
import net.minecraft.structure.StructureStart; import net.minecraft.structure.StructureStart;
import net.minecraft.tag.TagManager;
import net.minecraft.util.Identifier; import net.minecraft.util.Identifier;
import net.minecraft.util.StringIdentifiable; import net.minecraft.util.StringIdentifiable;
@@ -40,6 +43,7 @@ import java.util.Locale;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.UUID; import java.util.UUID;
import java.util.function.Predicate;
import java.util.stream.Collectors; import java.util.stream.Collectors;
public class ValueConversions public class ValueConversions
@@ -379,4 +383,15 @@ public class ValueConversions
if (ret == null) return ListValue.of(Value.NULL, NumericValue.of(itemSlot)); if (ret == null) return ListValue.of(Value.NULL, NumericValue.of(itemSlot));
return ret; return ret;
} }
public static Value ofBlockPredicate(TagManager tagManager, Predicate<CachedBlockPosition> 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())
);
}
} }
+3 -1
View File
@@ -2,4 +2,6 @@ accessWidener v1 named
accessible class net/minecraft/server/world/ThreadedAnvilChunkStorage$TicketManager accessible class net/minecraft/server/world/ThreadedAnvilChunkStorage$TicketManager
accessible class net/minecraft/server/world/ServerLightingProvider$Stage accessible class net/minecraft/server/world/ServerLightingProvider$Stage
accessible class net/minecraft/recipe/Ingredient$Entry accessible class net/minecraft/recipe/Ingredient$Entry
accessible class net/minecraft/command/argument/BlockPredicateArgumentType$StatePredicate
accessible class net/minecraft/command/argument/BlockPredicateArgumentType$TagPredicate
+2
View File
@@ -174,6 +174,8 @@
"RecipeManager_scarpetMixin", "RecipeManager_scarpetMixin",
"Ingredient_scarpetMixin", "Ingredient_scarpetMixin",
"BlockStateArgument_scarpetMixin", "BlockStateArgument_scarpetMixin",
"StatePredicate_scarpetMixin",
"TagPredicate_scarpetMixin",
"HorseBaseEntity_scarpetMixin", "HorseBaseEntity_scarpetMixin",
"PillagerEntity_scarpetMixin", "PillagerEntity_scarpetMixin",