(For deveolpers) Condition Registry - Redheris/PreventBuild GitHub Wiki
Since the mod uses some sort of Registry to create and process conditions, it should be possible to add new conditions from outside the mod itself.
ICondition
Every condition class inherits from the interface ICondition:
public interface ICondition {
    ConditionCategory getCategory();
    /**
     * Checking the action of left-clicking a block
     */
    default ActionResult attackBlockCheck(PlayerEntity player, Hand hand, int x, int y, int z) {
        return ActionResult.PASS;
    }
    /**
     * Checking the action of placing a block
     */
    default ActionResult placeBlockCheck(PlayerEntity player, Hand hand, int x, int y, int z, BlockHitResult hitResult) {
        return attackBlockCheck(player, hand, x, y, z);
    }
    /**
     * Checking the action of tight-clicking a block
     */
    default ActionResult interactBlockCheck(PlayerEntity player, Hand hand, int x, int y, int z, BlockHitResult hitResult) {
        return placeBlockCheck(player, hand, x, y, z, hitResult);
    }
    /**
     * Checking the action of using an item
     */
    default ActionResult useItemCheck(PlayerEntity player, World world, Hand hand) {
        return attackBlockCheck(player, hand, player.getBlockX(), player.getBlockY(), player.getBlockZ());
    }
    /**
     * Checking the action of right-clicking an entity
     */
    default ActionResult useEntityCheck(PlayerEntity player, World world, Hand hand, Entity entity, EntityHitResult hitResult) {
        return attackBlockCheck(player, hand, entity.getBlockX(), entity.getBlockY(), entity.getBlockZ());
    }
    /**
     * Checking the action of left-clicking an entity
     */
    default ActionResult attackEntityCheck(PlayerEntity player, World world, Hand hand, Entity entity, EntityHitResult hitResult) {
        return useEntityCheck(player, world, hand, entity, hitResult);
    }
    /**
     * Debug string to print the condition.
     * It can be more useful and convenient to use the debug mode
     */
    default String getString(int tabs) {
        return "|\t".repeat(tabs) + this.getClass().getSimpleName();
    }
    default String getString() {
        return getString(0);
    }
}
All you have to do is create a new condition class that inherits from ICondition and override the method (or methods) you need and set the category.
For example:
public class HeldItemCondition implements ICondition {
    private final String[] items;
    public HeldItemCondition(String[] items) {
        this.items = items;
    }
    @Override
    public ConditionCategory getCategory() {
        return ConditionCategory.MISCELLANEOUS;
    }
    @Override
    public ActionResult attackBlockCheck(PlayerEntity player, Hand hand, int x, int y, int z) {
        String itemName = player.getStackInHand(hand).getItem().getTranslationKey();
        if (Arrays.stream(this.items).anyMatch(i -> i.equalsIgnoreCase(itemName)))
            return ActionResult.FAIL;
        return ActionResult.PASS;
    }
}
Registering
Each of the implemented conditions is registered in the Conditions.java class by calling a method register(String key, ConditionFactory factory) from ConditionRegistry.java.
Each of register() calls is registering a new keyword for parsing from the .cfg config files.
- key: Keyword (e.g.- "x>",- "block:")
- factory: Functional interface with the method- (ConditionCategory category, String value)returning a new ICondition object from ConditionCategory and String.
Examples:
ConditionRegistry.register("z:", ZEqualsCondition::parse);
ConditionRegistry.register("x=:", (category, value) ->
        new XEqualsCondition(category, new int[]{Integer.parseInt(value)})
);