Skip to content

Argonath-Systems/04-framework-condition

Repository files navigation

Condition Framework

C4 Component Diagram

@startuml
!include https://raw.githubusercontent.com/plantuml-stdlib/C4-PlantUML/master/C4_Component.puml

title Component Diagram for Condition Framework

Container(condition_fw, "Condition Framework", "Java Library", "Composable condition evaluation engine")

Container_Boundary(condition_boundary, "Condition Modules") {
    Component(core, "Condition Engine", "Core", "Evaluation logic")
    Component(types, "Built-in Conditions", "impl", "Player, Inventory, Location checks")
    Component(parser, "Serializer", "YAML/JSON", "Config parsing")
    Component(debug, "Debug Tracer", "Utils", "Evaluation tracing")
}

System_Ext(accessor, "Accessor API", "Dependency")
System_Ext(core_lib, "Core Lib", "Dependency")
System_Ext(mod, "Standalone Mod", "Uses Conditions")

Rel(condition_fw, accessor, "Uses")
Rel(condition_fw, core_lib, "Uses")
Rel(mod, condition_fw, "Uses")
@enduml

Specification

SF-03: Condition Framework

[!abstract] Product Overview A generic, composable condition evaluation library for Hytale modders. Provides a fluent API for building complex conditional logic without boilerplate code.

Product Identity

Attribute Value
Mod ID sf-condition-framework
Maven Artifact com.lordofthetales.framework:condition-framework
CurseForge Slug hytale-condition-framework
License MIT (free, open source)
Monetization Free (reputation builder)
Target Audience Mod developers
Dependencies SF-01 Accessor API, SF-02 Core Library

Value Proposition

Problem Statement

Every Hytale mod that needs conditional logic (shops, quests, spawners, gates, events) ends up writing custom if-then code. This leads to:

  • Duplicated logic across mods
  • Inconsistent condition evaluation
  • No serialization for config files
  • Hard to debug nested conditions

Solution

A standardized condition library that:

  • Provides 20+ built-in condition types
  • Supports AND/OR/NOT composition
  • Serializes to/from YAML/JSON
  • Offers debug mode with evaluation traces
  • Is fully type-safe with generics

Feature Specification

CF-001: Core Condition Interface

/**
 * Base condition interface with composition support.
 * @param <C> The context type for evaluation
 */
public interface Condition<C extends ConditionContext> {
    
    /**
     * Evaluate this condition against a context.
     * @param context The evaluation context
     * @return true if condition is met
     */
    boolean evaluate(C context);
    
    /**
     * Get human-readable description.
     */
    String getDescription();
    
    /**
     * Get unique condition type identifier for serialization.
     */
    String getType();
    
    // ===== Composition Methods =====
    
    default Condition<C> and(Condition<C> other) {
        return new AndCondition<>(this, other);
    }
    
    default Condition<C> or(Condition<C> other) {
        return new OrCondition<>(this, other);
    }
    
    default Condition<C> not() {
        return new NotCondition<>(this);
    }
    
    // ===== Static Factories =====
    
    static <C extends ConditionContext> Condition<C> always() {
        return ctx -> true;
    }
    
    static <C extends ConditionContext> Condition<C> never() {
        return ctx -> false;
    }
    
    static <C extends ConditionContext> Condition<C> all(List<Condition<C>> conditions) {
        return new AllCondition<>(conditions);
    }
    
    static <C extends ConditionContext> Condition<C> any(List<Condition<C>> conditions) {
        return new AnyCondition<>(conditions);
    }
}

CF-002: Built-in Condition Types

Category Condition Description Parameters
Player HasLevel Player meets minimum level minLevel: int
Player HasPermission Player has permission node permission: string
Player HasPlaytime Player has X hours played minHours: int
Player IsInGroup Player in permission group group: string
Inventory HasItem Has item in inventory itemId: string, count: int
Inventory HasItemTag Has item with tag tag: string, count: int
Inventory HasEmptySlots Has N empty slots slots: int
Inventory HasCurrency Has enough currency currency: string, amount: int
Location InZone Player in named zone zoneId: string
Location InBiome Player in biome type biome: string
Location NearLocation Within radius of point x,y,z: int, radius: int
Location InWorld Player in world/dimension world: string
Time TimeOfDay Game time in range start: int, end: int
Time DayOfWeek Real-world day days: list
Time DateRange Real-world date range start: date, end: date
State HasFlag Player has boolean flag flag: string
State HasVariable Variable comparison var: string, op: enum, value: any
State Cooldown Cooldown has elapsed key: string, duration: duration
Random Chance Random chance probability: float
Custom Script Custom script evaluation script: string

CF-003: Condition Context

/**
 * Base context interface - extend for your mod's needs.
 */
public interface ConditionContext {
    /**
     * Get the player UUID being evaluated.
     */
    UUID getPlayerId();
    
    /**
     * Get the current timestamp.
     */
    Instant getTimestamp();
    
    /**
     * Get arbitrary data by key.
     */
    <T> Optional<T> getData(String key, Class<T> type);
}

/**
 * Default player-focused context implementation.
 */
public class PlayerConditionContext implements ConditionContext {
    private final UUID playerId;
    private final Player player;
    private final Map<String, Object> additionalData;
    
    // Player-specific accessors
    public int getLevel() { ... }
    public Vec3 getPosition() { ... }
    public String getCurrentZone() { ... }
    public String getCurrentBiome() { ... }
    public Inventory getInventory() { ... }
    public Set<String> getPermissions() { ... }
    public Map<String, Object> getFlags() { ... }
    
    // Builder for extensibility
    public static Builder builder(Player player) {
        return new Builder(player);
    }
    
    public static class Builder {
        public Builder withData(String key, Object value) { ... }
        public PlayerConditionContext build() { ... }
    }
}

CF-004: YAML/JSON Serialization

# Example condition configuration
conditions:
  can_enter_dungeon:
    type: all
    conditions:
      - type: has_level
        min_level: 20
      - type: has_item
        item_id: "dungeon_key"
        count: 1
      - type: not
        condition:
          type: has_flag
          flag: "dungeon_cooldown"

  shop_discount:
    type: any
    conditions:
      - type: is_in_group
        group: "vip"
      - type: has_playtime
        min_hours: 100
/**
 * Condition serialization/deserialization.
 */
public class ConditionSerializer {
    
    private final Map<String, ConditionFactory<?>> factories;
    
    /**
     * Register a custom condition type.
     */
    public <C extends ConditionContext> void register(
            String type, 
            ConditionFactory<C> factory) {
        factories.put(type, factory);
    }
    
    /**
     * Deserialize condition from config.
     */
    public <C extends ConditionContext> Condition<C> deserialize(
            ConfigurationSection config) {
        String type = config.getString("type");
        ConditionFactory<C> factory = getFactory(type);
        return factory.create(config);
    }
    
    /**
     * Serialize condition to config.
     */
    public void serialize(Condition<?> condition, ConfigurationSection config) {
        config.set("type", condition.getType());
        condition.serialize(config);
    }
}

@FunctionalInterface
public interface ConditionFactory<C extends ConditionContext> {
    Condition<C> create(ConfigurationSection config);
}

CF-005: Debug Mode & Evaluation Tracing

/**
 * Debug evaluator that traces condition evaluation.
 */
public class DebugConditionEvaluator<C extends ConditionContext> {
    
    public EvaluationTrace evaluate(Condition<C> condition, C context) {
        EvaluationTrace trace = new EvaluationTrace(condition.getType());
        
        boolean result = evaluateWithTrace(condition, context, trace);
        trace.setResult(result);
        
        return trace;
    }
    
    private boolean evaluateWithTrace(
            Condition<C> condition, 
            C context, 
            EvaluationTrace trace) {
        
        long startTime = System.nanoTime();
        
        if (condition instanceof CompositeCondition<C> composite) {
            for (Condition<C> child : composite.getChildren()) {
                EvaluationTrace childTrace = new EvaluationTrace(child.getType());
                evaluateWithTrace(child, context, childTrace);
                trace.addChild(childTrace);
            }
        }
        
        boolean result = condition.evaluate(context);
        
        trace.setDurationNanos(System.nanoTime() - startTime);
        trace.setResult(result);
        trace.setDescription(condition.getDescription());
        
        return result;
    }
}

public class EvaluationTrace {
    private final String conditionType;
    private boolean result;
    private long durationNanos;
    private String description;
    private List<EvaluationTrace> children;
    
    public String toPrettyString() {
        // Returns formatted tree:
        // ✓ all (0.5ms)
        //   ✓ has_level >= 20 (0.1ms)
        //   ✓ has_item: dungeon_key x1 (0.2ms)
        //   ✓ not (0.2ms)
        //     ✗ has_flag: dungeon_cooldown (0.1ms)
    }
}

API Examples

Basic Usage

// Build conditions fluently
Condition<PlayerConditionContext> canEnter = Conditions.hasLevel(20)
    .and(Conditions.hasItem("key", 1))
    .and(Conditions.inZone("dungeon_entrance"));

// Evaluate
PlayerConditionContext ctx = PlayerConditionContext.builder(player).build();
if (canEnter.evaluate(ctx)) {
    openDoor();
}

Config-Driven Conditions

// Load from config
ConditionSerializer serializer = new ConditionSerializer();
serializer.registerDefaults();

Condition<?> condition = serializer.deserialize(config.getSection("entry_requirement"));

// Use in your mod
if (condition.evaluate(context)) {
    allowEntry();
}

Custom Condition Types

// Define custom condition
public class HasReputationCondition implements Condition<MyModContext> {
    private final String factionId;
    private final int minReputation;
    
    @Override
    public boolean evaluate(MyModContext context) {
        return context.getReputation(factionId) >= minReputation;
    }
    
    @Override
    public String getType() { return "has_reputation"; }
    
    @Override
    public String getDescription() {
        return String.format("Reputation with %s >= %d", factionId, minReputation);
    }
}

// Register
serializer.register("has_reputation", config -> new HasReputationCondition(
    config.getString("faction"),
    config.getInt("min_reputation")
));

Configuration

# condition-framework.yml
condition_framework:
  debug_mode: false
  trace_slow_conditions_ms: 10
  cache_evaluations: true
  cache_ttl_seconds: 5
  
  # Performance limits
  max_condition_depth: 10
  max_conditions_per_composite: 50
  
  # Script conditions (if enabled)
  scripting:
    enabled: false
    engine: "javascript"
    max_execution_ms: 100

Performance

Operation Target Notes
Simple condition eval < 0.1ms Single condition
Composite (10 conditions) < 1ms AND/OR with 10 children
Deserialization < 5ms Per condition tree
Cache hit < 0.01ms When caching enabled

Testing Requirements

Unit Tests

  • All built-in condition types
  • AND/OR/NOT composition
  • Serialization round-trip
  • Custom condition registration
  • Debug trace output

Integration Tests

  • Config file loading
  • Cache invalidation
  • Performance benchmarks

Distribution

Maven/Gradle Dependency

dependencies {
    implementation 'com.lordofthetales:condition-framework:1.0.0'
}

CurseForge

  • Category: Libraries
  • Game: Hytale
  • Tags: library, api, conditions, logic

Roadmap

Version Features
1.0.0 Core conditions, serialization, debug mode
1.1.0 Caching, performance optimizations
1.2.0 Script condition support
2.0.0 Async evaluation, reactive conditions

Related Documents

Design

Component Context

@startuml
!include https://raw.githubusercontent.com/plantuml-stdlib/C4-PlantUML/master/C4_Component.puml

title Component Diagram for SF-03: Condition Framework

Container_Boundary(framework, "SF-03: Condition Framework") {
    Component(CoreConditionInterface, "Core Condition Interface", "CF-001", "Component for Core Condition Interface")
    Component(BuiltinConditionTypes, "Built-in Condition Types", "CF-002", "Component for Built-in Condition Types")
    Component(ConditionContext, "Condition Context", "CF-003", "Component for Condition Context")
    Component(YAMLJSONSerialization, "YAML/JSON Serialization", "CF-004", "Component for YAML/JSON Serialization")
    Component(DebugModeEvaluationTracing, "Debug Mode & Evaluation Tracing", "CF-005", "Component for Debug Mode & Evaluation Tracing")
}

@enduml

About

Hytale modding component: framework-condition

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Packages

 
 
 

Contributors