In Cardinal, the main.go file is used as the entry point for your game shard implementation. This is where you will initialize your world and register your component, message, query, and system to it.

Example

A typical main.go file will look like this:

main.go
package main

import (
	"errors"
	"github.com/argus-labs/starter-game-template/cardinal/component"
	"github.com/argus-labs/starter-game-template/cardinal/msg"
	"github.com/argus-labs/starter-game-template/cardinal/query"
	"github.com/argus-labs/starter-game-template/cardinal/system"
	"github.com/rs/zerolog/log"
	"pkg.world.dev/world-engine/cardinal"
)

func main() {
	w, err := cardinal.NewWorld()
	if err != nil {
		log.Fatal().Err(err).Msg("")
	}

	// Register components
	// NOTE: You must register your components here for it to be accessible.
	Must(
		cardinal.RegisterComponent[component.Player](w),
		cardinal.RegisterComponent[component.Health](w),
	)

	// Register messages (user action)
	// NOTE: You must register your messages here for it to be executed.
	Must(
		cardinal.RegisterMessage[msg.CreatePlayerRequest, msg.CreatePlayerResponse](w, "create_player"),
		cardinal.RegisterMessage[msg.AttackPlayerRequest, msg.AttackPlayerResponse](w, "attack_player"),
    )

	// Register queries
	// NOTE: You must register your queries here for it to be accessible.
	Must(
		cardinal.RegisterQuery[query.WorldVarsRequest, query.WorldVarsResponse](w,
		"world-vars",
		query.WorldVars,
	))

	// Register systems
	// Each system executes sequentially in the order they are added.
	// NOTE: You must register your systems here for it to be executed.
	Must(cardinal.RegisterSystems(w,
		system.AttackSystem,
		system.RegenSystem,
		system.PlayerSpawnerSystem,
	))

	// Start the game shard
	Must(w.StartGame())
}

func Must(err ...error) {
	e := errors.Join(err...)
	if e != nil {
		log.Fatal().Err(e).Msg("")
	}
}