Skip to content

Block Predicates

Sirttas edited this page May 28, 2021 · 32 revisions

DataPack Anvil provide Advanced block predicates that can be serialized in datapacks. They all inherit from the IBlockPosPredicate.

Uage

The Interface provide the IBlockPosPredicate#test(IWorldReader, BlockPos) that allow us to check if the block at those coordinates match our predicate.

Data

Lets take back the example we use in Data Manager, here is our data with a predicate:

public class MyData {

	 private String stringValue;
	 private int integerValue;
	 private IBlockPosPredicate predicate;

// getters and setters...
}

Serialization

But we still need to serialize and deserialize it.

If you are working with codecs you ca simply use the block predicate codec IBlockPosPredicate#CODEC.

If you are using serializer there are 4 methods in IBlockPosPredicate to serialize and deserialize a predicate to json and PacketBuffer.

  • JsonElement write()
  • write(PacketBuffer)
  • IBlockPosPredicate read(JsonElement)
  • IBlockPosPredicate read(PacketBuffer)

With our example it will look like this:

private void enqueueIMC(InterModEnqueueEvent event) {
	DataManagerIMC.enqueue(() -> new DataManagerIMC<>((new ResourceLoaction("mymod", "mydata"), MY_DATA_MANAGER).withSerializer(
	json -> {
		MyData myData = new MyData();

		myData.setStringValue(JSONUtils.getString(json, "stringValue"));
		myData.setIntegerValue(JSONUtils.getInt(json, "integerValue"));
		myData.setPredicate(IBlockPosPredicate.read(json.get("predicate")));
		return myData;
	}, buf -> {
		MyData myData = new MyData();

		myData.setStringValue(buf.readString());
		myData.setIntegerValue(buf.readInt());
		myData.setPredicate(IBlockPosPredicate.read(buf));
		return myData;
	}, (buf, myData) -> {
		buf.writeString(myData.getStringValue());
		buf.writeInt(myData.getIntegerValue());
		myData.getPredicate().write(buf);
	}));
}

Logic

Block predicates offers a few methods to create them using logic operators. This includes:

  • not to get thin inverse of the current predicate
  • and to create an and operation between multiple predicates
  • or to create an or operation between multiple predicates
  • match can take a Block, an array of Block, a ITag<Block> or a BlockState. this will gives you a predicate that check if a block match the corresponding argument.

Predicates

A few block predicates are already present:

dpanvil:any

This predicate always return true.
Example:

{
    "type": "dpanvil:any"
}

dpanvil:none

This predicate always return false.
Example:

{
    "type": "dpanvil:none"
}

dpanvil:and

This predicate is true if all the predicates it contains are true.
Example:

{
    "type": "dpanvil:and",
    "values": [
        ...
    ]
}

dpanvil:or

This predicate is true if any predicate it contains is true.
Example:

{
    "type": "dpanvil:or",
    "values": [
        ...
    ]
}

dpanvil:not

This predicate is true if the predicate it contains is false.
Example:

{
    "type": "dpanvil:not",
    "value": {
        ...
    }
}

dpanvil:block

This predicate is true if the tested block match its block.
Example:

{
    "type": "dpanvil:block",
    "block": "minecraft:stone"
}

dpanvil:blocks

This predicate is true if the tested block match one of its blocks.
Example:

{
    "type": "dpanvil:blocks",
    "block": [
        "minecraft:stone",
        "minecraft:dirt"
    ]
}

dpanvil:tag

This predicate is true if its tag contains the tested block.
Example:

{
    "type": "dpanvil:tag",
    "tag": "minecraft:planks"
}

dpanvil:blockstate

This predicate is true if its blockstate match the tested blockstate.
BlockStates can be found here: https://minecraft.gamepedia.com/Block_states
Example:

{
    "type": "dpanvil:blockstate",
    "Name": "minecraft:wheat",
    "Properties": [
        ...
    ]
}

Custom Predicates

You can create your own implementation of IBlockPostPredicate for your own needs. you only need to implement two methods:

  • test: called when you want to test if this predicate is true or false
  • getType: return the type of predicate (can be retrieved using an @ObjectHolder)

Then you need to add it to the BlockPosPredicateType forge registry:

@SubscribeEvent
public static void registerBlockPosPredicateSerializers(RegistryEvent.Register<BlockPosPredicateType<?>> event) {
	IForgeRegistry<BlockPosPredicateType<?>> registry = event.getRegistry();

	registry.register(new BlockPosPredicateType<>(MyPredicate.CODEC).setRegistryName(new ResourceLocation("mymod", "my_predicate"));
}

Note: you need to use a codec, take a look here for useful links on how codecs work.

Clone this wiki locally