For Mod Developers

Defining Shogi Values

Expose a mod property as a typed ShogiValue with a default provider.

Goal

Define a ShogiValue that exposes one of your mod's properties to Shogi while keeping a safe default when no rule override applies.

Minimal example

Your mod could expose a property like yourmod:your_property like this:

public class YourModRules {
    public static final ShogiScope scope = Shogi.scope(Identifier.fromNamespaceAndPath("yourmod", "rules"), it -> {
        it.setDefaultNamespaces(List.of("yourmod", "shogi"));
    });

    public static final ShogiValue<Entity, Integer> yourProperty =
            scope.intValue(id("your_property"), entity -> entity.totalExperience);
}

This creates an integer-backed value with:

  • the key yourmod:your_property
  • the scope yourmod:rules
  • an Entity resolution context
  • a fallback value provider that is used if Shogi is not installed

Defining a ShogiValue

Create a dedicated scope for your mod, then use the typed helper on that scope that matches the value you want to expose:

public class ExampleModRules {
    public static final ShogiScope scope = Shogi.scope(Identifier.fromNamespaceAndPath("yourmod", "rules"), it -> {
        it.setDefaultNamespaces(List.of("yourmod", "shogi"));
    });

    public static final ShogiValue<Player, Boolean> preventDeath =
            scope.booleanValue(id("prevent_death"), player -> ExampleModConfig.getActive().preventDeath);

    public static final ShogiValue<Entity, Integer> fallingHeight =
            scope.intValue(id("falling_height"), entity -> entity.level().getHeight());

    public static final ShogiValue<Player, String> titleText =
            scope.stringValue(id("title_text"), player -> "Hello World");
}

Available helpers:

  • scope.intValue(...)
  • scope.floatValue(...)
  • scope.booleanValue(...)
  • scope.stringValue(...)
  • scope.componentValue(...)

A mod-owned scope keeps your rule files, default namespaces, and future custom effects under your control.

Resolving a ShogiValue

Once defined, resolve it wherever your mod needs the final value:

int targetHeight = ForgivingVoidRules.fallingHeight.getOrDefault(entity);

Common resolution methods:

  • getOrDefault(context) to use your default provider on failure
  • getOrElse(context, fallback) to supply a one-off fallback
  • getOrThrow(context) to fail hard if resolution does not produce a success value

Networked Values

Some rules can only be resolved on the server and must be synchronized to clients. ShogiValues that are marked as .networked() will resolve to the authoritative server value when resolved on the client. The server will automatically sync updates to this value whenever it is resolved to a new value.

public static final ShogiValue<Player, Boolean> canUseOverlay =
        scope.booleanValue(id("can_use_overlay"), player -> true).networked();
This is an advanced feature and requires your mod to depend on the full Shogi mod. The embedded shogi-api alone will not perform any special handling for networked values.

Scopes

When using helpers from your own scope, such as scope.intValue(...), your values are registered on that scope and rules are parsed with that scope's effects and default namespaces.

You can register specialized effects onto your custom scope that should only be available for rules on values defined on that scope.

Learn more on the Custom Scopes page.

Rule Overrides

After defining a Shogi value, users can target it with rules such as:

{
  "forgivingvoid:falling_height": [
    "is_dimension('minecraft:the_nether') -> 180", 
    "220"
  ]
}

Rules can be configured in the config/<scopeNamespace>.<scopePath>.json file, or individually in a datapack file via data/<propertyNamespace>/<scopeNamespace>/<scopePath>/<propertyPath>.json.

For a yourmod:example property on a yourmod:rules scope, that would be in config/yourmod.rules.json and data/yourmod/yourmod/rules/example.json.

Next guides