core

package module
v0.10.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Dec 22, 2025 License: GPL-2.0 Imports: 6 Imported by: 29

README

RPG Toolkit Core

The core module provides fundamental interfaces and types that form the foundation of the RPG toolkit.

Overview

This module defines the essential building blocks for creating RPG game systems, including:

  • Entity Interface: The base interface that all game objects must implement
  • Ref Type: Type-safe references to game mechanics (features, skills, conditions, etc.)
  • Error Definitions: Common error types used throughout the toolkit

Installation

go get github.com/KirkDiggler/rpg-toolkit/core

Usage

Implementing the Entity Interface

All game objects in the RPG toolkit must implement the Entity interface:

type Entity interface {
    GetID() string
    GetType() string
}

Example implementation:

type Character struct {
    id   string
    name string
}

func (c *Character) GetID() string {
    return c.id
}

func (c *Character) GetType() string {
    return "character"
}
Using Refs (Type References)

The Ref type provides a type-safe way to reference game mechanics like features, skills, and conditions:

// Define compile-time constants for core features
var Rage = core.MustNewRef("rage", "core", "feature")
var SneakAttack = core.MustNewRef("sneak_attack", "core", "feature")

// Parse from string format
ref, err := core.ParseString("core:feature:rage")
if err != nil {
    return err
}

// Track where features come from
feature := core.NewSourcedRef(Rage, "class:barbarian")

// JSON serialization works automatically
// Outputs: {"id": "core:feature:rage", "source": "class:barbarian"}
Ref Structure

A Ref consists of three parts:

  • Module: Which module defined this ("core", "artificer", "homebrew")
  • Type: Category of mechanic ("feature", "proficiency", "skill", "condition")
  • Value: The specific identifier ("rage", "sneak_attack")

String format: module:type:value

Error Handling

The core module provides several predefined errors and error types for detailed reporting:

// Using predefined errors
if entity == nil {
    return core.ErrNilEntity
}

// Creating detailed entity errors
err := core.NewEntityError("create", "character", "char-123", core.ErrDuplicateEntity)

// Ref validation errors
ref, err := core.ParseString("invalid::format")
if core.IsParseError(err) {
    // Handle parse error
}

Common Errors

Entity Errors
  • ErrEntityNotFound: Entity cannot be found
  • ErrInvalidEntity: Entity is invalid or malformed
  • ErrDuplicateEntity: Entity with the same ID already exists
  • ErrNilEntity: Nil entity provided
  • ErrEmptyEntityID: Entity has an empty or invalid ID
  • ErrInvalidType: Entity has an invalid or unrecognized type
Ref Errors
  • ErrEmptyString: Ref string is empty
  • ErrInvalidFormat: String doesn't match expected format
  • ErrEmptyComponent: One of the Ref components is empty
  • ErrInvalidCharacters: Component contains invalid characters
  • ErrTooManySegments: More than 3 segments in string
  • ErrTooFewSegments: Fewer than 3 segments in string

Testing

Run tests with:

go test ./...

License

[Add your license information here]

Documentation

Overview

Package core provides fundamental interfaces and types that define entities in the RPG toolkit ecosystem without imposing any game-specific attributes.

Purpose: This package establishes the base contracts that all game entities must fulfill, providing identity and type information without imposing any game-specific attributes or behaviors. It is the foundation upon which all other packages build.

Scope:

  • Entity interface: Basic identity contract (ID, Type)
  • Ref type: Type-safe references to game mechanics (features, skills, etc.)
  • Error types: Common errors used across packages
  • No game logic, stats, or behaviors
  • No persistence or storage concerns
  • Pure interfaces and contracts

Non-Goals:

  • Game statistics: HP, AC, attributes belong in game implementations
  • Entity behaviors: Use the behavior package for AI/actions
  • Persistence: Storage/serialization belongs in repository implementations
  • Game rules: All game-specific logic belongs in rulebooks
  • Entity creation: Factories and builders belong in games
  • Entity relationships: Parent/child, ownership are game-specific

Integration: This package is imported by all other toolkit packages as it defines the fundamental Entity contract and Ref system. It has no dependencies on other toolkit packages, maintaining its position at the base of the dependency hierarchy. This ensures the toolkit remains loosely coupled.

Entity Example:

// Game implements the Entity interface
type Monster struct {
    id   string
    kind string
    // Game-specific fields like HP, AC, etc.
}

func (m *Monster) GetID() string   { return m.id }
func (m *Monster) GetType() string { return m.kind }

// The toolkit can work with any Entity
var entity core.Entity = &Monster{id: "goblin-1", kind: "goblin"}

Ref Example:

// Define compile-time constants for core features
var Rage = core.MustNewRef(core.RefInput{
	Module: "core",
	Type:   "feature",
	ID:     "rage",
})

// Track where features come from
feature := core.NewSourcedRef(Rage, "class:barbarian")

// Store in character data
character.Features = append(character.Features, feature)

Package core provides the fundamental interfaces and types for the RPG toolkit.

Index

Constants

This section is empty.

Variables

View Source
var (
	// ErrEntityNotFound is returned when an entity cannot be found.
	ErrEntityNotFound = errors.New("entity not found")

	// ErrInvalidEntity is returned when an entity is invalid or malformed.
	ErrInvalidEntity = errors.New("invalid entity")

	// ErrDuplicateEntity is returned when attempting to create an entity with an ID that already exists.
	ErrDuplicateEntity = errors.New("duplicate entity")

	// ErrNilEntity is returned when a nil entity is provided where a valid entity is expected.
	ErrNilEntity = errors.New("nil entity")

	// ErrEmptyEntityID is returned when an entity has an empty or invalid ID.
	ErrEmptyEntityID = errors.New("empty entity ID")

	// ErrInvalidType is returned when an entity has an invalid or unrecognized type.
	ErrInvalidType = errors.New("invalid entity type")

	// ErrInsufficientStrength is returned when a character lacks the strength requirement for an item.
	ErrInsufficientStrength = errors.New("insufficient strength")

	// ErrMissingProficiency is returned when a character lacks the required proficiency for an item.
	ErrMissingProficiency = errors.New("missing proficiency")

	// ErrIncompatibleSlot is returned when an item cannot be equipped in the specified slot.
	ErrIncompatibleSlot = errors.New("incompatible slot")

	// ErrSlotOccupied is returned when attempting to equip an item to an already occupied slot.
	ErrSlotOccupied = errors.New("slot occupied")

	// ErrRequiresAttunement is returned when attempting to use a magic item that requires attunement.
	ErrRequiresAttunement = errors.New("requires attunement")

	// ErrAttunementLimit is returned when a character has reached their attunement limit.
	ErrAttunementLimit = errors.New("attunement limit reached")

	// ErrTwoHandedConflict is returned when a two-handed item conflicts with equipped items.
	ErrTwoHandedConflict = errors.New("two-handed conflict")

	// ErrClassRestriction is returned when a character's class cannot use an item.
	ErrClassRestriction = errors.New("class restriction")

	// ErrRaceRestriction is returned when a character's race cannot use an item.
	ErrRaceRestriction = errors.New("race restriction")

	// ErrAlignmentRestriction is returned when a character's alignment prevents item use.
	ErrAlignmentRestriction = errors.New("alignment restriction")
)

Common errors that can occur throughout the RPG toolkit.

View Source
var (
	// ErrEmptyString indicates the identifier string is empty
	ErrEmptyString = errors.New("identifier string cannot be empty")

	// ErrInvalidFormat indicates the string doesn't match expected format
	ErrInvalidFormat = errors.New("invalid identifier format")

	// ErrEmptyComponent indicates one of the identifier components is empty
	ErrEmptyComponent = errors.New("identifier component cannot be empty")

	// ErrInvalidCharacters indicates a component contains invalid characters
	ErrInvalidCharacters = errors.New("identifier contains invalid characters")

	// ErrTooManySegments indicates more segments than expected
	ErrTooManySegments = errors.New("too many segments in identifier")

	// ErrTooFewSegments indicates fewer segments than expected
	ErrTooFewSegments = errors.New("too few segments in identifier")
)

Sentinel errors for common identifier validation failures. These are used for programmatic error checking with errors.Is()

Functions

func IsEmptyComponent added in v0.1.2

func IsEmptyComponent(err error) bool

IsEmptyComponent checks if the error indicates an empty component

func IsEmptyString added in v0.1.2

func IsEmptyString(err error) bool

IsEmptyString checks if the error indicates an empty string

func IsInvalidCharacters added in v0.1.2

func IsInvalidCharacters(err error) bool

IsInvalidCharacters checks if the error indicates invalid characters

func IsInvalidFormat added in v0.1.2

func IsInvalidFormat(err error) bool

IsInvalidFormat checks if the error indicates invalid format

func IsParseError added in v0.1.2

func IsParseError(err error) bool

IsParseError checks if an error is a ParseError

func IsValidationError added in v0.1.2

func IsValidationError(err error) bool

IsValidationError checks if an error is a ValidationError

Types

type Action added in v0.5.0

type Action[T any] interface {
	Entity // Has GetID() and GetType()

	// CanActivate checks if this action can currently be activated.
	// Should return an error if the action cannot be used (no resources,
	// conditions not met, on cooldown, etc.)
	CanActivate(ctx context.Context, owner Entity, input T) error

	// Activate performs the action.
	// Should consume resources, apply effects, and trigger events as needed.
	// The owner is the entity performing the action.
	Activate(ctx context.Context, owner Entity, input T) error
}

Action represents something that can be activated in the game. The generic type T defines what input the action requires.

Actions are the fundamental unit of "doing things" in RPGs - casting spells, using abilities, activating items, or any other triggered behavior. The toolkit provides this interface, but all implementations live in rulebooks.

Example usage in a rulebook:

type RageInput struct{}  // No input needed for rage

type Rage struct {
    id   string
    uses int
}

func (r *Rage) GetID() string { return r.id }
func (r *Rage) GetType() string { return "feature" }

func (r *Rage) CanActivate(ctx context.Context, owner Entity, input RageInput) error {
    if r.uses <= 0 {
        return errors.New("no rage uses remaining")
    }
    return nil
}

func (r *Rage) Activate(ctx context.Context, owner Entity, input RageInput) error {
    r.uses--
    // Apply rage effects via event bus
    return nil
}

type Entity

type Entity interface {
	// GetID returns the unique identifier for this entity.
	// The ID should be unique within the entity's type scope.
	GetID() string

	// GetType returns the type of this entity.
	// This helps categorize entities (e.g., EntityTypeCharacter, EntityTypeItem).
	// Returns an EntityType constant, not a raw string.
	GetType() EntityType
}

Entity represents a fundamental game object in the RPG system. All game entities (characters, items, locations, etc.) must implement this interface.

type EntityError

type EntityError struct {
	EntityID   string
	EntityType string
	Op         string // Operation that caused the error
	Err        error  // Underlying error
}

EntityError represents an error related to a specific entity.

func NewEntityError

func NewEntityError(op, entityType, entityID string, err error) *EntityError

NewEntityError creates a new EntityError.

func (*EntityError) Error

func (e *EntityError) Error() string

Error implements the error interface for EntityError.

func (*EntityError) Unwrap

func (e *EntityError) Unwrap() error

Unwrap returns the underlying error.

type EntityType added in v0.6.0

type EntityType string

EntityType identifies the category of an entity. Rulebooks and modules define constants of this type for their entities.

type EquipmentError added in v0.1.1

type EquipmentError struct {
	CharacterID string
	ItemID      string
	Slot        string
	Op          string // Operation that caused the error
	Err         error  // Underlying error
}

EquipmentError represents an error related to equipment validation.

func NewEquipmentError added in v0.1.1

func NewEquipmentError(op, characterID, itemID, slot string, err error) *EquipmentError

NewEquipmentError creates a new EquipmentError.

func (*EquipmentError) Error added in v0.1.1

func (e *EquipmentError) Error() string

Error implements the error interface for EquipmentError.

func (*EquipmentError) Unwrap added in v0.1.1

func (e *EquipmentError) Unwrap() error

Unwrap returns the underlying error.

type ID added in v0.9.3

type ID = string

ID is the base type for all game content identifiers. Domain packages alias this type for their specific content types (e.g., classes.Class, features.Feature, skills.Skill).

type Module added in v0.9.5

type Module = string

Module identifies which module defined content (e.g., "dnd5e", "wildemount"). Domain packages define their module constant using this type.

type ParseError added in v0.1.2

type ParseError struct {
	// Input is the original string that failed to parse
	Input string

	// Component indicates which part failed (module, type, or value)
	Component string

	// Position is the character position where the error was detected
	Position int

	// Err is the underlying error
	Err error
}

ParseError provides detailed information about parsing failures. It includes the position and component where the error occurred.

func NewParseError added in v0.1.2

func NewParseError(input, component string, position int, err error) *ParseError

NewParseError creates a ParseError with the given details

func (*ParseError) Error added in v0.1.2

func (e *ParseError) Error() string

Error implements the error interface

func (*ParseError) Unwrap added in v0.1.2

func (e *ParseError) Unwrap() error

Unwrap returns the underlying error for errors.Is/As support

type Ref added in v0.1.2

type Ref struct {
	// Module identifies which module defined this Ref ("dnd5e", "wildemount", etc.)
	Module Module `json:"module"`

	// Type categorizes the identifier ("features", "conditions", "classes", etc.)
	Type Type `json:"type"`

	// ID is the unique identifier within the module namespace
	ID ID `json:"id"`
}

Ref represents a unique identifier for a game mechanic. It's designed to be extensible - external modules can create new IDs while core modules provide type-safe constructors for known IDs.

func MustNewRef added in v0.1.2

func MustNewRef(input RefInput) *Ref

MustNewRef creates a new identifier, panicking on validation error. Use this for compile-time constants where you know the values are valid.

func NewRef added in v0.1.2

func NewRef(input RefInput) (*Ref, error)

NewRef creates a new identifier with validation using RefInput

func ParseString added in v0.1.2

func ParseString(s string) (*Ref, error)

ParseString parses the string format with detailed error reporting

func (*Ref) Equals added in v0.1.2

func (id *Ref) Equals(other *Ref) bool

Equals checks if two identifiers are the same

func (*Ref) IsValid added in v0.1.2

func (id *Ref) IsValid() error

IsValid checks if the identifier has all required fields

func (*Ref) MarshalJSON added in v0.1.2

func (id *Ref) MarshalJSON() ([]byte, error)

MarshalJSON implements json.Marshaler

func (*Ref) String added in v0.1.2

func (id *Ref) String() string

String returns the full identifier as module:type:id

func (*Ref) UnmarshalJSON added in v0.1.2

func (id *Ref) UnmarshalJSON(data []byte) error

UnmarshalJSON implements json.Unmarshaler

type RefInput added in v0.2.0

type RefInput struct {
	Module string // e.g., "dnd5e", "core"
	Type   string // e.g., "spell", "feature", "skill"
	ID     ID     // e.g., "charm_person", "rage", "acrobatics"
}

RefInput provides a structured way to create a Ref with clear field names

type Source added in v0.1.2

type Source struct {
	Category SourceCategory
	Name     string
}

Source represents the source of an identifier

func (*Source) String added in v0.1.2

func (s *Source) String() string

String returns the source as a string in the format "category:name"

type SourceCategory added in v0.1.2

type SourceCategory string

SourceCategory represents the category of an identifier

const (
	// SourceClass represents a class source
	SourceClass SourceCategory = "class"
	// SourceRace represents a race source
	SourceRace SourceCategory = "race"
	// SourceBackground represents a background source
	SourceBackground SourceCategory = "background"
	// SourceFeat represents a feat source
	SourceFeat SourceCategory = "feat"
	// SourceItem represents an item source
	SourceItem SourceCategory = "item"
	// SourceManual represents a manual source (DM granted)
	SourceManual SourceCategory = "manual"
)

type SourcedRef added in v0.1.2

type SourcedRef struct {
	Ref    *Ref
	Source *Source // Not a string anymore!
}

SourcedRef represents an identifier with its source

type Topic added in v0.9.0

type Topic string

Topic represents a typed event routing key for pub/sub systems. Topics provide compile-time safety and avoid magic strings.

type Type added in v0.9.5

type Type = string

Type categorizes content within a module (e.g., "features", "conditions", "classes"). Domain packages define their type constant using this type.

type TypedRef added in v0.3.0

type TypedRef[T any] struct {
	Ref *Ref
}

TypedRef associates a Ref with a specific type at compile time. This enables type-safe event subscriptions and other ref-based operations.

func (TypedRef[T]) String added in v0.3.0

func (tr TypedRef[T]) String() string

String returns the string representation of the underlying ref

type ValidationError added in v0.1.2

type ValidationError struct {
	// Field is the identifier field that failed validation (Module, Type, or Value)
	Field string

	// Value is the invalid value that failed validation
	Value string

	// Rule describes which validation rule failed
	Rule string

	// Err is the underlying error
	Err error
}

ValidationError provides detailed validation failure information. It includes which validation rule failed and the invalid value.

func NewValidationError added in v0.1.2

func NewValidationError(field, value, rule string, err error) *ValidationError

NewValidationError creates a ValidationError with the given details

func (*ValidationError) Error added in v0.1.2

func (e *ValidationError) Error() string

Error implements the error interface

func (*ValidationError) Unwrap added in v0.1.2

func (e *ValidationError) Unwrap() error

Unwrap returns the underlying error

type WithSourcedRef added in v0.1.2

type WithSourcedRef struct {
	ID     *Ref    `json:"id"`
	Source *Source `json:"source"` // "race:elf", "class:fighter", "background:soldier"
}

WithSourcedRef bundles an identifier with its source (where it came from)

func NewWithSourcedRef added in v0.1.2

func NewWithSourcedRef(id *Ref, source *Source) WithSourcedRef

NewWithSourcedRef creates an identifier with source information

Directories

Path Synopsis
Package chain provides interfaces for ordered processing of data through stages.
Package chain provides interfaces for ordered processing of data through stages.
Package combat provides type definitions for combat-related constants.
Package combat provides type definitions for combat-related constants.
Package damage provides type definitions for damage-related constants.
Package damage provides type definitions for damage-related constants.
Package effect provides interfaces for modifying chains with typed effects.
Package effect provides interfaces for modifying chains with typed effects.
Package events provides type definitions for event-related constants.
Package events provides type definitions for event-related constants.
Package features provides type definitions for feature-related constants.
Package features provides type definitions for feature-related constants.
Package mock is a generated GoMock package.
Package mock is a generated GoMock package.
Package resources provides type definitions for resource-related constants.
Package resources provides type definitions for resource-related constants.
Package spells provides type definitions for spell-related constants.
Package spells provides type definitions for spell-related constants.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL