Skip to content

Condition System

The condition system provides condition evaluation capabilities for EmakiCoreLib, supporting comparison operators, logical combinations, and automatic type inference. It is primarily used with the @if prefix in the action system, but can also be called independently by other modules.

Basic Syntax

The basic form of a condition expression is:

<left_value> <operator> <right_value>
yaml
# Examples
"@if=%player_level%>=10 givemoney amount=500"
"@if=%player_world%==world sendmessage message=你在主世界"

Supported Operators

OperatorDescriptionExample
==Equal to%player_world%==world
!=Not equal to%player_world%!=world_nether
<Less than%player_level%<10
<=Less than or equal to%player_health%<=5
>Greater than%player_level%>20
>=Greater than or equal to%balance%>=1000

Logical Combinators

Multiple conditions can be connected using logical combinators:

CombinatorDescriptionExample
&&Logical AND (all must be satisfied)%player_level%>=10&&%player_world%==world
||Logical OR (any one satisfied)%player_world%==world||%player_world%==world_the_end
yaml
actions:
  # Level >= 10 and in the overworld
  - "@if=%player_level%>=10&&%player_world%==world givemoney amount=500"

  # In the overworld or the End
  - "@if=%player_world%==world||%player_world%==world_the_end sendmessage message=<green>安全区域"

Warning

&& and || cannot be mixed in the same @if expression. For complex logic, use structured condition configuration (see below).

Structured Condition Configuration

For complex condition logic, structured condition configuration can be used in YAML:

all_of — All Must Be Satisfied

The overall result is true when all sub-conditions are true (logical AND).

yaml
conditions:
  type: all_of
  conditions:
    - "%player_level% >= 10"
    - "%player_world% == world"
    - "%balance% >= 500"

any_of — Any One Satisfied

The overall result is true when any sub-condition is true (logical OR).

yaml
conditions:
  type: any_of
  conditions:
    - "%player_world% == world"
    - "%player_world% == world_the_end"
    - "%player_world% == world_nether"

at_least — At Least N Satisfied

The overall result is true when at least count sub-conditions are true.

yaml
conditions:
  type: at_least
  count: 2
  conditions:
    - "%player_level% >= 10"
    - "%balance% >= 1000"
    - "%player_health% >= 15"
    - "%player_food_level% >= 18"

exactly — Exactly N Satisfied

The overall result is true when exactly count sub-conditions are true.

yaml
conditions:
  type: exactly
  count: 1
  conditions:
    - "%player_world% == world"
    - "%player_world% == world_nether"
    - "%player_world% == world_the_end"

Nested Combinations

Structured conditions support nesting, allowing arbitrarily complex logic:

yaml
conditions:
  type: all_of
  conditions:
    - "%player_level% >= 10"
    - type: any_of
      conditions:
        - "%player_world% == world"
        - "%player_world% == world_the_end"
    - type: at_least
      count: 1
      conditions:
        - "%balance% >= 500"
        - "%player_is_op% == true"

Type Inference

The condition system automatically infers the type of comparison values:

Inference RuleDescriptionExample
Both sides are numericCompared as numbers%player_level%>=10 → numeric comparison
Either side is non-numericCompared as strings%player_world%==world → string comparison
Boolean valuestrue / false compared as strings%player_is_op%==true → string comparison
yaml
# Numeric comparison — supports <, <=, >, >=
"@if=%player_level%>=10 ..."        # 10, 11, 12... all satisfy
"@if=%balance%<100 ..."             # 99.9, 50, 0 all satisfy

# String comparison — only supports == and !=
"@if=%player_world%==world ..."     # Exact match for "world"
"@if=%player_name%!=Steve ..."      # Not equal to "Steve"

Warning

When using <, <=, >, >= operators with string values, the system compares lexicographically. This is usually not the intended behavior — it is recommended to use only == and != for string comparisons.

Usage in @if Prefix

@if is the most common way to use the condition system:

yaml
actions:
  # Simple condition
  - "@if=%player_level%>=10 givemoney amount=500"

  # Combined conditions
  - "@if=%player_level%>=20&&%player_world%==world givemoney amount=2000"

  # Combined with other control prefixes
  - "@if=%player_level%>=30 @chance=0.5 @delay=20 givemoney amount=5000"

Programming Interface

java
ConditionService conditionService = EmakiServiceRegistry.get(ConditionService.class);

// Evaluate a simple condition
Map<String, String> placeholders = Map.of(
    "player_level", "15",
    "player_world", "world"
);

boolean result = conditionService.evaluate("%player_level% >= 10", placeholders);
// true

// Evaluate a structured condition
ConditionConfig config = ConditionConfig.allOf(
    SimpleCondition.of("%player_level%", ">=", "10"),
    SimpleCondition.of("%player_world%", "==", "world")
);

boolean result2 = conditionService.evaluate(config, placeholders);
// true

Tip

Condition evaluation is a lightweight operation with no I/O or complex computation involved, making it safe to use in high-frequency paths. Placeholders are replaced with actual values before evaluation, so any registered placeholder can be used in condition expressions.

Released under the GPL-3.0 License