{"id":13821501,"url":"https://github.com/Ladysnake/Cardinal-Components-API","last_synced_at":"2025-05-16T12:33:40.041Z","repository":{"id":40606906,"uuid":"178603171","full_name":"Ladysnake/Cardinal-Components-API","owner":"Ladysnake","description":"Component API to add external data to objects.","archived":false,"fork":false,"pushed_at":"2025-04-13T23:17:12.000Z","size":3564,"stargazers_count":183,"open_issues_count":22,"forks_count":44,"subscribers_count":6,"default_branch":"1.21","last_synced_at":"2025-05-08T19:03:33.193Z","etag":null,"topics":["api","fabric","hacktoberfest","minecraft","minecraft-mod","mod","mods","snapshot","snapshots"],"latest_commit_sha":null,"homepage":"https://www.curseforge.com/minecraft/mc-mods/cardinal-components","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Ladysnake.png","metadata":{"files":{"readme":"README.md","changelog":"changelog.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null}},"created_at":"2019-03-30T19:36:00.000Z","updated_at":"2025-04-13T23:15:02.000Z","dependencies_parsed_at":"2024-01-15T15:34:33.852Z","dependency_job_id":"cff218be-6b52-40b7-9d2e-8202da5edc9a","html_url":"https://github.com/Ladysnake/Cardinal-Components-API","commit_stats":null,"previous_names":["ladysnake/cardinal-components-api"],"tags_count":101,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Ladysnake%2FCardinal-Components-API","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Ladysnake%2FCardinal-Components-API/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Ladysnake%2FCardinal-Components-API/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Ladysnake%2FCardinal-Components-API/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Ladysnake","download_url":"https://codeload.github.com/Ladysnake/Cardinal-Components-API/tar.gz/refs/heads/1.21","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254276446,"owners_count":22043866,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["api","fabric","hacktoberfest","minecraft","minecraft-mod","mod","mods","snapshot","snapshots"],"created_at":"2024-08-04T08:01:22.915Z","updated_at":"2025-05-16T12:33:35.029Z","avatar_url":"https://github.com/Ladysnake.png","language":"Java","funding_links":[],"categories":["Java"],"sub_categories":[],"readme":"## **The CCA Maven is moving!**\n\n**As Jfrog has ended their free service for OSS projects, we had to move the maven repository before the 1st of July 2023.\nSee below for the new maven instructions - you will have to update your buildscripts with the new URL to fix dependency resolution failures.**\n\n\u003ch1\u003e\n    \u003cpicture\u003e\n        \u003csource media=\"(prefers-color-scheme: dark)\" srcset=\"banner-white.svg\"\u003e\n        \u003cimg src=\"banner.svg\" alt=\"Cardinal Components API\"\u003e\n    \u003c/picture\u003e \n\u003c/h1\u003e\n\nA components API for Quilt and Fabric that is easy, modular, and extremely fast.\n\n*Cardinal Components API is a library for Minecraft mods to create data\ncomponents that can be attached to various providers. Those components\nprovide a standardized interface for mods to interact with otherwise opaque\nobjects and behaviours, thereby helping both mod creation and compatibility.* [^1]\n\n\n**TL;DR: It allows you to attach data to things**\n\n### An example\n\nLet's say you want to make to add mana to your mod. You would most likely want to have a number stored on the player,\nwhich gets saved alongside it. You may want to display a mana bar on the client, which will require synchronization.\nYou may want your mana to refill slowly over time, which will require ticking.\nAnd then you may want to have something like mana batteries in the world,\nwhich would require re-implementing all that on a custom block or entity.\n\n**Cardinal Components API takes care of it all.**\n\n*Detailed information is available in [the website's **wiki**](https://ladysnake.org/wiki/cardinal-components-api/landing)*.\nThe information below is a condensed form of the latter.  \nIf you have questions or need help with this library, you can also join the [Ladysnake Discord](https://discord.ladysnake.org).\n\n## Features\\*\n\n- 🔗 Attach your components to a variety of vanilla classes\n- 🧩 Implement once, plug anywhere - your data will be saved automatically\n- 📤 Synchronize data with a single helper interface\n- 👥 Choose how your components are copied when a player respawns\n- ⏲️ Tick your components alongside their target\n- 🛠️ Fine-tune everything so that it fits your needs\n- ☄️ And enjoy the blazing speed of ASM-generated extensions\n\n*\\*Non-exhaustive, refer to the wiki and javadoc for the full list.*\n\n## Adding the API to your buildscript:\n\n**Upgrade information: versions 4.1.0 onwards of Cardinal Components API use the `dev.onyxstudios.cardinal-components-api` (lowercase) maven group instead of `io.github.onyxstudios.Cardinal-Components-API`**\n\nLatest versions of Cardinal Components API are available on the Ladysnake maven:\n```gradle\nrepositories {\n    maven {\n        name = 'Ladysnake Mods'\n        url = 'https://maven.ladysnake.org/releases'\n    }\n}\n\ndependencies {\n    // Adds a dependency on the base cardinal components module (required by every other module)\n    // Replace modImplementation with modApi if you expose components in your own API\n    modImplementation \"dev.onyxstudios.cardinal-components-api:cardinal-components-base:\u003cVERSION\u003e\"\n    // Adds a dependency on a specific module\n    modImplementation \"dev.onyxstudios.cardinal-components-api:\u003cMODULE\u003e:\u003cVERSION\u003e\"\n    // Includes Cardinal Components API as a Jar-in-Jar dependency (optional)\n    include \"dev.onyxstudios.cardinal-components-api:cardinal-components-base:\u003cVERSION\u003e\"\n    include \"dev.onyxstudios.cardinal-components-api:\u003cMODULE\u003e:\u003cVERSION\u003e\"\n}\n```\n\nCheck out **https://ladysnake.org/wiki/cardinal-components-api/dev-install** for up-to-date buildscript samples\nwith `build.gradle`, `build.gradle.kts`, and  `libs.versions.toml`.\n\nYou can find the current version of the API in the [**releases**](https://github.com/OnyxStudios/Cardinal-Components-API/releases) tab of the repository on Github.\n\nCardinal Components API is split into several modules. To depend on the all-encompassing master jar, use the dependency string\n`dev.onyxstudios.cardinal-components-api:cardinal-components-api:\u003cVERSION\u003e`.\nThat artifact brings every module to your dev env, but you often do not need all of them for a project.\nAlso note that the maven version of the fat jar is actually empty, so you will have to require users to install it from curseforge or modrinth if you do not bundle all required modules.\n\n**[[List of individual module names and descriptions]](https://github.com/OnyxStudios/Cardinal-Components-API/wiki#modules)**\n\nExample:\n```gradle\n// Adds an API dependency on the base cardinal components module (required by every other module)\nmodApi \"dev.onyxstudios.cardinal-components-api:cardinal-components-base:\u003cVERSION\u003e\"\n// Adds an implementation dependency on the entity module\nmodImplementation \"dev.onyxstudios.cardinal-components-api:cardinal-components-entity:\u003cVERSION\u003e\"\n```\n\n## Basic Usage\n\nTo get started, you only need a class implementing `Component`.\nIt is recommended to have it split into an interface and an implementation,\nso that internals get properly encapsulated and so that the component itself can be used\nas an API by other mods.\n\n**Minimal code example:**\n```java\npublic interface IntComponent extends ComponentV3 {\n    int getValue();\n}\n\nclass RandomIntComponent implements IntComponent {\n    private int value = (int) (Math.random() * 20);\n    @Override public int getValue() { return this.value; }\n    @Override public void readFromNbt(CompoundTag tag) { this.value = tag.getInt(\"value\"); }\n    @Override public void writeToNbt(CompoundTag tag) { tag.putInt(\"value\", this.value); }\n}\n```\n*Note: a component class can be reused for several component types*\n\nIf you want your component to be **automatically synchronized with watching clients**,\nyou can also add the [`AutoSyncedComponent`](./cardinal-components-base/src/main/java/dev/onyxstudios/cca/api/v3/component/sync/AutoSyncedComponent.java)\ninterface to your implementation:\n\n```java\nclass SyncedIntComponent implements IntComponent, AutoSyncedComponent {\n    private int value;\n    private final Entity provider;  // or World, or whatever you are attaching to\n\n    public SyncedIntComponent(Entity provider) { this.provider = provider; }\n\n    public void setValue(int value) {\n        this.value = value;\n        MyComponents.MAGIK.sync(this.provider); // assuming MAGIK is the right key for this component\n    }\n    // implement everything else\n}\n```\n\n**[[More information on component synchronization]](https://github.com/OnyxStudios/Cardinal-Components-API/wiki/Synchronizing-components)**\n\nIf you want your component to **tick alongside its provider**, you can add the\n[`ServerTickingComponent`](./cardinal-components-base/src/main/java/dev/onyxstudios/cca/api/v3/component/tick/ServerTickingComponent.java)\nor [`ClientTickingComponent`](./cardinal-components-base/src/main/java/dev/onyxstudios/cca/api/v3/component/tick/ClientTickingComponent.java)\n(or both) to your *component interface* (here, `IntComponent`). If you'd rather add the ticking interface to a single\ncomponent subclass, **you have to use one of the specific methods provided in the individual modules**\n(here something of the form `registry.beginRegistration(IntComponent.KEY).impl(IncrementingIntComponent.class).end(IncrementingIntComponent::new)`).\n\n```java\nclass IncrementingIntComponent implements IntComponent, ServerTickingComponent {\n    private int value;\n    @Override public void serverTick() { this.value++; }\n    // implement everything else\n}\n```\n\n*Serverside ticking is implemented for all providers except item stacks.\n Clientside ticking is only implemented for entities, block entities, and worlds.*\n\nIf you want your component to **be notified of its provider being loaded and unloaded**, typically for advanced setup or cleanup,\nyou can add the [`ServerLoadAwareComponent`](./cardinal-components-base/src/main/java/dev/onyxstudios/cca/api/v3/component/load/ServerLoadAwareComponent.java)\nor [`ClientLoadAwareComponent`](./cardinal-components-base/src/main/java/dev/onyxstudios/cca/api/v3/component/load/ClientLoadAwareComponent.java)\n(or both) and their \"Unload\" variants to your *component interface* (here, `IntComponent`). Just like with ticking,\nif you'd rather add the (un)load-aware interface to a single component subclass,\n**you have to use one of the specific methods provided in the individual modules**.\n\n```java\nclass IncrementingIntComponent implements IntComponent, ServerLoadAwareComponent {\n    private int value;\n    @Override public void loadServerside() { this.value++; }\n    // implement everything else\n}\n```\n\n*Serverside load and unload is implemented for entities, block entities, chunks, worlds, and scoreboards.\nClientside load and unload is only implemented for entities, block entities, and chunks. This is an experimental feature,\nany feedback welcome.*\n\nThe next step is to choose an identifier for your component, and to declare it as a custom property in your mod's metadata:\n\n**quilt.mod.json** (if you use [Quilt](https://quiltmc.org))\n```json\n{\n    \"schema_version\": 1,\n    \"quilt_loader\": {\n        \"id\": \"mymod\"\n    },\n    \"cardinal-components\": [\n        \"mymod:magik\"\n    ]\n}\n```\n\n**fabric.mod.json** (if you use [Fabric](https://fabricmc.net))\n```json\n{\n    \"schemaVersion\": 1,\n    \"id\": \"mymod\",\n\n    \"custom\": {\n        \"cardinal-components\": [\n            \"mymod:magik\"\n        ]\n    }\n}\n```\n\nComponents can be provided by objects of various classes, depending on which modules you installed.\nThe most common providers are [entities](https://github.com/OnyxStudios/Cardinal-Components-API/wiki/Cardinal-Components-Entity),\n[item stacks](https://github.com/OnyxStudios/Cardinal-Components-API/wiki/Cardinal-Components-Item),\n[worlds](https://github.com/OnyxStudios/Cardinal-Components-API/wiki/Cardinal-Components-World)\nand [chunks](https://github.com/OnyxStudios/Cardinal-Components-API/wiki/Cardinal-Components-Chunk),\nbut more are available.\nTo interact with them, you need to **register a component key**, using `ComponentRegistryV3#getOrCreate`;\nthe resulting `ComponentKey` instance has the query methods you need. You will also need to **attach your\ncomponent** to some providers (here, to players and worlds):\n\n```java\npublic final class MyComponents implements EntityComponentInitializer, WorldComponentInitializer {\n    public static final ComponentKey\u003cIntComponent\u003e MAGIK = \n        ComponentRegistryV3.INSTANCE.getOrCreate(new Identifier(\"mymod:magik\"), IntComponent.class);\n        \n    @Override\n    public void registerEntityComponentFactories(EntityComponentFactoryRegistry registry) {\n        // Add the component to every PlayerEntity instance, and copy it on respawn with keepInventory\n        registry.registerForPlayers(MAGIK, player -\u003e new RandomIntComponent(), RespawnCopyStrategy.INVENTORY);\n    }\n    \n    @Override\n    public void registerWorldComponentFactories(WorldComponentFactoryRegistry registry) {\n        // Add the component to every World instance\n        registry.register(MAGIK, world -\u003e new RandomIntComponent());\n    }    \n}\n```\n\nDo not forget to declare your component initializer as an entrypoint in your mod's metadata:\n\n**quilt.mod.json** (if you use Quilt)\n\n```json\n{\n    \"quilt_loader\": {\n        \"entrypoints\": {\n            \"cardinal-components\": \"a.b.c.MyComponents\"\n        },\n    }\n}\n```\n\n**fabric.mod.json** (if you use Fabric)\n```json\n{\n    \"entrypoints\": {\n        \"cardinal-components\": [\n            \"a.b.c.MyComponents\"\n        ]\n    },\n}\n```\n\n**[[More information on component registration]](https://github.com/OnyxStudios/Cardinal-Components-API/wiki/Registering-and-using-a-component)**\n\nNow, all that is left is to actually use that component. You can access individual instances of your component by using the dedicated getters on your `ComponentKey`:\n\n```java\npublic static void useMagik(Entity provider) { // anything will work, as long as a module allows it!\n    // Retrieve a provided component\n    int magik = provider.getComponent(MAGIK).getValue();\n    // Or, if the object is not guaranteed to provide that component:\n    int magik = MAGIK.maybeGet(provider).map(IntComponent::getValue).orElse(0);\n    // ...\n}\n```\n\n## Test Mod\nA test mod for the API is available in this repository, under `src/testmod`. It makes uses of most features from the API.\nIts code is outlined in a secondary [readme](./src/testmod/readme.md).\n\n[^1]: this description has been made exaggeratedly convoluted for comedic effects.","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FLadysnake%2FCardinal-Components-API","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FLadysnake%2FCardinal-Components-API","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FLadysnake%2FCardinal-Components-API/lists"}