{"id":16438762,"url":"https://github.com/nidorx/ecs-lib","last_synced_at":"2025-04-09T07:09:45.653Z","repository":{"id":36474856,"uuid":"227001013","full_name":"nidorx/ecs-lib","owner":"nidorx","description":"Tiny and easy to use ECS (Entity Component System) library for game programming","archived":false,"fork":false,"pushed_at":"2023-03-02T08:26:26.000Z","size":7813,"stargazers_count":200,"open_issues_count":17,"forks_count":11,"subscribers_count":7,"default_branch":"master","last_synced_at":"2025-04-02T03:49:04.202Z","etag":null,"topics":["data-oriented-design","ecs","ecs-framework","entity-component","entity-component-architecture","entity-component-system","game","game-development","game-engine","game-programming","gamedev","gameloop","threejs"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","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/nidorx.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","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-12-10T01:19:05.000Z","updated_at":"2025-03-31T13:59:05.000Z","dependencies_parsed_at":"2024-04-12T01:55:30.485Z","dependency_job_id":"5fb43cdb-39c2-453a-8ae8-713941dea53b","html_url":"https://github.com/nidorx/ecs-lib","commit_stats":{"total_commits":90,"total_committers":3,"mean_commits":30.0,"dds":0.3666666666666667,"last_synced_commit":"e4738e088e4653b6ae37ad5d45cac0d2e00be6d9"},"previous_names":[],"tags_count":19,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nidorx%2Fecs-lib","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nidorx%2Fecs-lib/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nidorx%2Fecs-lib/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nidorx%2Fecs-lib/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/nidorx","download_url":"https://codeload.github.com/nidorx/ecs-lib/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247994122,"owners_count":21030050,"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":["data-oriented-design","ecs","ecs-framework","entity-component","entity-component-architecture","entity-component-system","game","game-development","game-engine","game-programming","gamedev","gameloop","threejs"],"created_at":"2024-10-11T09:06:09.633Z","updated_at":"2025-04-09T07:09:45.631Z","avatar_url":"https://github.com/nidorx.png","language":"TypeScript","readme":"\u003cdiv align=\"center\"\u003e\n    \u003ca href=\"https://www.npmjs.com/package/ecs-lib\"\u003e\n        \u003cimg src=\"https://badge.fury.io/js/ecs-lib.svg\" alt=\"npm package\" title=\"npm package\" /\u003e\n    \u003c/a\u003e    \n    \u003ca href=\"https://travis-ci.org/nidorx/ecs-lib\"\u003e\n        \u003cimg src=\"https://travis-ci.org/nidorx/ecs-lib.svg?branch=master\" alt=\"Build Status\" title=\"Build Status\" /\u003e\n    \u003c/a\u003e    \n    \u003ca href=\"https://coveralls.io/github/nidorx/ecs-lib?branch=master\"\u003e\n        \u003cimg src=\"https://coveralls.io/repos/github/nidorx/ecs-lib/badge.svg?branch=master\" alt=\"Coverage Status\" /\u003e\n    \u003c/a\u003e\n    \u003cbr/\u003e    \n    \u003cimg src=\"https://github.com/nidorx/ecs-lib/raw/master/logo.jpg\" width=\"882\" /\u003e\n\u003c/div\u003e\n\n**ecs-lib** is a tiny and easy to use [ECS _(Entity Component System)_](https://en.wikipedia.org/wiki/Entity_component_system) library for game programming. It's written in Typescript but you can use on node.js and web browser too. \n\n\n**TLDR;** Take a look at the [example](https://nidorx.github.io/ecs-lib/) and its [source code](https://github.com/nidorx/ecs-lib/tree/master/example)\n\n\n```bash\nnpm install --save ecs-lib\n```\n\n\n## Table of contents\n   * [Documentation](#documentation)\n      * [World](#world)\n      * [Component](#component)\n         * [Raw data access](#raw-data-access)\n         * [Secondary attributes](#secondary-attributes)\n      * [Entity](#entity)\n         * [Adding and removing from the world](#adding-and-removing-from-the-world)\n         * [Adding and removing components](#adding-and-removing-components)\n         * [Subscribing to changes](#subscribing-to-changes)\n         * [Accessing components](#accessing-components)\n      * [System](#system)\n         * [Adding and removing from the world](#adding-and-removing-from-the-world-1)\n         * [Limiting frequency (FPS)](#limiting-frequency-fps)\n         * [Time Scaling - Slow motion effect](#time-scaling---slow-motion-effect)\n             * [Pausing](#pausing)\n         * [Global systems - all entities](#global-systems---all-entities)\n         * [Before and After update](#before-and-after-update)\n         * [Enter - When adding new entities](#enter---when-adding-new-entities)\n         * [Change - When you add or remove components](#change---when-you-add-or-remove-components)\n         * [Exit - When removing entities](#exit---when-removing-entities)\n   * [API](#api)\n      * [ECS](#ecs)\n      * [Component](#component-1)\n         * [Component\u0026lt;T\u0026gt;](#componentt)\n      * [Entity](#entity-1)\n      * [System](#system-1)\n   * [Feedback, Requests and Roadmap](#feedback-requests-and-roadmap)\n   * [Contributing](#contributing)\n      * [Translating and documenting](#translating-and-documenting)\n      * [Reporting Issues](#reporting-issues)\n      * [Fixing defects and adding improvements](#fixing-defects-and-adding-improvements)\n   * [License](#license)\n\n\n## Documentation\n\nEntity-Component-System (ECS) is a distributed and compositional architectural design pattern that is mostly used in game development. It enables flexible decoupling of domain-specific behaviour, which overcomes many of the drawbacks of traditional object-oriented inheritance.\n\nFor further details:\n\n- [Entity Systems Wiki](http://entity-systems.wikidot.com/)\n- [Evolve Your Hierarchy](http://cowboyprogramming.com/2007/01/05/evolve-your-heirachy/)\n- [ECS on Wikipedia](https://en.wikipedia.org/wiki/Entity_component_system)\n- [Entity Component Systems in Elixir](https://yos.io/2016/09/17/entity-component-systems/)\n\n### World\n\nA ECS instance is used to describe you game world or **Entity System** if you will. The World is a container for Entities, Components, and Systems.\n\n```typescript\nimport ECS from \"ecs-lib\";\n\nconst world = new ECS();\n```\n\n\n### Component\n\nRepresents the different facets of an entity, such as position, velocity, geometry, physics, and hit points for example. Components store only raw data for one aspect of the object, and how it interacts with the world.\n\nIn other words, the component labels the entity as having this particular aspect.\n\n\n```typescript\nimport {Component} from \"ecs-lib\";\n\nexport type Box = {\n    width: number;\n    height: number;\n    depth: number;\n}\n\nexport const BoxComponent = Component.register\u003cBox\u003e();\n```\n\nThe register method generates a new class that represents this type of component, which has a unique identifier. You also have access to the type id from the created instances.\n\n```typescript\nconst boxCmp = new BoxComponent({ width:10, height:10, depth:10 });\n\n// prints true, in this case type = 1\nconsole.log(BoxComponent.type === boxCmp.type);\n```\n\n\u003e You can also have access to the `Component` class from ECS (`ECS.Component.register`)\n\n\n#### Raw data access\n\nComponent instance displays raw data by property `data`\n\n```typescript\nboxCmp.data.width = 33;\nconsole.log(boxCmp.data.width);\n```\n\n#### Secondary attributes\nA component can have attributes. Attributes are secondary values used to save miscellaneous data required by some specialized systems.\n\n```typescript\nboxCmp.attr.specializedSystemMetadata = 33;\nconsole.log(boxCmp.attr.specializedSystemMetadata);\n```\n\n### Entity\n\nThe entity is a general purpose object. An entity is what you use to describe an object in your game. e.g. a player, a gun, etc. It consists only of a unique ID and the list of components that make up this entity.\n\n```typescript\nimport {Entity} from \"ecs-lib\";\nimport {ColorComponent} from \"../component/ColorComponent\";\nimport {Box, BoxComponent} from \"../component/BoxComponent\";\n\nexport default class CubeEntity extends Entity {\n\n    constructor(cube: Box, color: string) {\n        super();\n\n        this.add(new BoxComponent(cube));\n        this.add(new ColorComponent(color));\n    }\n}\n```\n\n\u003e You can also have access to the `Entity` class from ECS (`ECS.Entity`)\n\n\n#### Adding and removing from the world\n\nYou can add multiple instances of the same entity in the world. Each entity is given a **unique identifier** at creation time.\n\n```typescript\nconst cubeEnt = new CubeEntity({\n    width: 10,\n    height: 10,\n    depth: 10\n}, '#FF0000');\n\nconsole.log(cubeEnt, cubeEnt.id);\n\nworld.addEntity(cubeEnt);\n\nworld.removeEntity(cubeEnt);\nworld.removeEntity(cubeEnt.id);\n```\n\n#### Adding and removing components \n\nAt any point in the entity's life cycle, you can add or remove components, using `add` and `remove` methods.\n\n```typescript\ncubeEnt.add(boxCmp);\ncubeEnt.remove(boxCmp);\n```\n\n**ecs-lib** entities can have more than one component per type, it is up to the programmer to control the addition and removal of entity components.\n\n```typescript\ncubeEnt.add(new BoxComponent({ width:10, height:10, depth:10 }));\ncubeEnt.add(new BoxComponent({ width:20, height:20, depth:20 }));\n```\n\n#### Subscribing to changes\n\nIn **ecs-lib** you can be informed when a component is added or removed from an entity by simply subscribing to the entity.\n\nTo unsubscribe, simply invoke the function you received at the time of subscription.\n\n```typescript\nconst cancel = cubeEnt.subscribe((entity)=\u003e{\n    console.log(entity === cubeEnt);\n});\n\ncancel();\n```\n\n#### Accessing components\n\nTo gain access to the components of an entity, simply use the `allFrom` and `oneFrom` methods of the `Component` class to get all or the first instance of this component respectively.\n\n```typescript\nBoxComponent.allFrom(cubeEnt)\n    .forEach((boxCmp)=\u003e{\n        console.log(boxCmp.data.height);\n    });\n\nconst boxCmp = BoxComponent.oneFrom(cubeEnt);\nconsole.log(boxCmp.data.height);\n```\n\n\n### System\n\nRepresents the logic that transforms component data of an entity from its current state to its next state. A system runs on entities that have a specific set of component types.\n\nEach system runs continuously (as if each system had its own thread).\n\nIn **ecs-lib**, a system has a strong connection with component types. You must define which components this system works on in the `System` abstract class constructor.\n\nIf the `update` method is implemented, it will be invoked for every update in the world. Whenever an entity with the characteristics expected by this system is added or removed on world, or it components is changed, the system is informed via the `enter`, `change` and `exit` methods.\n\n```typescript\nimport {Entity, System} from \"ecs-lib\";\nimport KeyboardState from \"../utils/KeyboardState\";\nimport {BoxComponent} from \"../component/BoxComponent\";\nimport {Object3DComponent} from \"../component/Object3DComponent\";\n\nexport default class KeyboardSystem extends System {\n\n    constructor() {\n        super([\n            Object3DComponent.type,\n            BoxComponent.type\n        ]);\n    }\n\n    update(time: number, delta: number, entity: Entity): void {\n        let object3D = Object3DComponent.oneFrom(entity).data;\n        if (KeyboardState.pressed(\"right\")) {\n            object3D.translateX(0.3);\n        } else if (KeyboardState.pressed(\"left\")) {\n            object3D.translateX(-0.3);\n        } else if (KeyboardState.pressed(\"up\")) {\n            object3D.translateZ(-0.3);\n        } else if (KeyboardState.pressed(\"down\")) {\n            object3D.translateZ(0.3);\n        }\n    }\n}\n```\n\n#### Adding and removing from the world\n\nTo add or remove a system to the world, simply use the `addSystem` and `removeSystem` methods.\n\n```typescript\nconst keyboardSys = new KeyboardSystem();\nworld.addSystem(keyboardSys);\nworld.removeSystem(keyboardSys);\n```\n\n#### Limiting frequency (FPS)\n\nIt is possible to limit the maximum number of invocations that the `update` method can perform per second (FPS) by simply entering the `frequency` parameter in the class constructor. This control is useful for example to limit the processing of physics systems to a specific frequency in order to decrease the processing cost.\n\n```typescript\nexport default class PhysicsSystem extends System {\n\n    constructor() {\n        super([\n            Object3DComponent.type,\n            VelocityComponent.type,\n            PositionComponent.type,\n            DirectionComponent.type\n        ], 25);  // \u003c- LIMIT FPS\n    }\n\n    // Will run at 25 FPS\n    update(time: number, delta: number, entity: Entity): void {\n       //... physics stuff\n    }\n}\n```\n\n#### Time Scaling - Slow motion effect\n\nA very interesting feature in **ecs-lib** is the TIMESCALE. This allows you to change the rate that time passes in the game, also known as the timescale. You can set the timescale by changing the `timeScale` property of the world.\n\nA time scale of 1 means normal speed. 0.5 means half the speed and 2.0 means twice the speed. If you set the game's timescale to 0.1, it will be ten times slower but still smooth - a good slow motion effect!\n\nThe timescale works by changing the value returned in the `time` and `delta` properties of the system update method. This means that the behaviors are affected and any movement using delta. If you do not use delta in your motion calculations, motion will not be affected by the timescale! Therefore, to use the timescale, simply use the delta correctly in all movements.\n\n\u003e **ATTENTION!** The systems continue to be invoked obeying their normal frequencies, what changes is only the values received in the time and delta parameters.\n\n```typescript\nexport default class PhysicsSystem extends System {\n\n    constructor() {\n        super([\n            Object3DComponent.type,\n            VelocityComponent.type\n        ], 25);\n    }\n\n    update(time: number, delta: number, entity: Entity): void {\n        let object = Object3DComponent.oneFrom(entity).data;\n        let velocity = VelocityComponent.oneFrom(entity).data;\n        object.position.y += velocity.y * delta;   \n    }\n}\n\nworld.timeScale = 1; // Normal speed\nworld.timeScale = 0.5; // Slow motion\n```\n\n##### Pausing\n\nYou can set the timescale to 0. This stops all movement. It is an easy way to pause the game. Go back to 1 and the game will resume.\n\nYou may find that you can still do things like shoot using the game controls. You can get around this by placing your main game events in a group and activating / deactivating that group while pausing and not pausing.\n\nIt's also a good way to test if you used delta correctly. If you used it correctly, setting the timescale to 0 will stop everything in the game. If you have not used it correctly, some objects may keep moving even if the game should be paused! In this case, you can check how these objects are moved and make sure you are using delta correctly.\n\n#### Global systems - all entities\n\nYou can also create systems that receive updates from all entities, regardless of existing components. To do this, simply enter `[-1]` in the system builder. This functionality may be useful for debugging and other rating mechanisms for your game.\n\n```typescript\nimport {Entity, System} from \"ecs-lib\";\n\nexport default class LogSystem extends System {\n\n    constructor() {\n        super([-1], 0.5); // Logs all entities every 2 seconds (0.5 FPS)\n    }\n\n    update(time: number, delta: number, entity: Entity): void {\n        console.log(entity);\n    }\n}\n```\n\n#### Before and After update\n\nIf necessary, the system can be informed before and after executing the update of its entities in this interaction (respecting the execution frequency defined for that system).\n\n```typescript\nimport {Entity, System} from \"ecs-lib\";\n\nexport default class LogSystem extends System {\n\n    constructor() {\n        super([-1], 0.5); // Logs all entities every 2 seconds (0.5 FPS)\n    }\n\n    beforeUpdateAll(time: number): void {\n        console.log('Before update');\n    }\n    \n    update(time: number, delta: number, entity: Entity): void {\n        console.log(entity);\n    }\n    \n    afterUpdateAll(time: number, entities: Entity[]): void {\n        console.log('After update');\n    }\n}\n```\n\n\n#### Enter - When adding new entities\n\nInvoked when:\n\n 1. An entity with the characteristics (components) expected by this system is added in the world;\n 2. This system is added in the world and this world has one or more entities with the characteristics expected by this system; \n 3. An existing entity in the same world receives a new component at runtime and all of its new components match the standard expected by this system.\n \n It can be used for initialization of new components in this entity, or even registration of this entity in a more complex management system.\n \n ```typescript\n import {Entity, System} from \"ecs-lib\";\n import {BoxGeometry, Mesh, MeshBasicMaterial} from \"three\";\n import {BoxComponent} from \"../component/BoxComponent\";\n import {ColorComponent} from \"../component/ColorComponent\";\n import {Object3DComponent} from \"../component/Object3DComponent\";\n \n export default class CubeFactorySystem extends System {\n \n     constructor() {\n         super([\n             ColorComponent.type,\n             BoxComponent.type\n         ]);\n     }\n     \n     enter(entity: Entity): void {\n         let object = Object3DComponent.oneFrom(entity);\n         if (!object) {\n             const box = BoxComponent.oneFrom(entity).data;\n             const color = ColorComponent.oneFrom(entity).data;\n \n             const geometry = new BoxGeometry(box.width, box.height, box.depth);\n             const material = new MeshBasicMaterial({color: color});\n             const cube = new Mesh(geometry, material);\n \n             // Append new component to entity\n             entity.add(new Object3DComponent(cube));\n         }\n     }\n }\n ```\n \n #### Change - When you add or remove components\n \n A system can also be informed when adding or removing components of an entity by simply implementing the \"change\" method.\n \n ```typescript\n import {Entity, System, Component} from \"ecs-lib\";\n \n export default class LogSystem extends System {\n \n     constructor() {\n         super([-1], 0.5); // Logs all entities every 2 seconds (0.5 FPS)\n     }\n \n     change(entity: Entity, added?: Component\u003cany\u003e, removed?: Component\u003cany\u003e): void {\n         console.log(entity, added, removed);\n     }\n }\n ```\n\n\n#### Exit - When removing entities\n\nInvoked when:\n \n 1. An entity with the characteristics (components) expected by this system is removed from the world;\n 2. This system is removed from the world and this world has one or more entities with the characteristics expected by this system;\n 3. An existing entity in the same world loses a component at runtime and its new component set no longer matches the standard expected by this system;\n \n Can be used to clean memory and references.\n \n ```typescript\nimport {Scene} from \"three\";\nimport {Entity, System} from \"ecs-lib\";\nimport {Object3DComponent} from \"../component/Object3DComponent\";\n\nexport default class SceneObjectSystem extends System {\n\n    private scene: Scene;\n\n    constructor(scene: Scene) {\n        super([\n            Object3DComponent.type\n        ]);\n\n        this.scene = scene;\n    }\n\n    exit(entity: Entity): void {\n        let model = Object3DComponent.oneFrom(entity);\n        this.scene.remove(model.data);\n    }\n}\n```\n\n## API\n\n| name | type | description |\n|---|---- |:---- | \n| \u003ch3\u003eECS\u003c/h2\u003e   |\n| `System` | `System`  | _`static`_ reference to `System` class. _(`ECS.System`)_ |\n| `Entity` | `Entity`  | _`static`_ reference to `Entity` class. _(`ECS.Entity`)_ |\n| `Component` | `Component`  | _`static`_ reference to `Component` class. _(`ECS.Component`)_ |\n| `constructor` | `(systems?: System[])` |  |\n| `getEntity(id: number)` | \u003ccode\u003eEntity \u0026#124; undefined\u003c/code\u003e  | Get an entity by id |\n| `addEntity(entity: Entity)` |  | Add an entity to this world |\n| \u003ccode\u003eremoveEntity(entity: number \u0026#124; Entity)\u003c/code\u003e |  | Remove an entity from this world |\n| `addSystem(system: System)` |  | Add a system in this world |\n| `removeSystem(system: System)` |  | Remove a system from this world |\n| `update()` |  | Invokes the `update` method of the systems in this world. |\n| \u003ch3\u003eComponent\u003c/h2\u003e |\n| `register\u003cT\u003e()` | `Class\u003cComponent\u003cT\u003e\u003e`  | _`static`_ Register a new component class |\n| \u003ch3\u003eComponent\u0026lt;T\u0026gt;\u003c/h2\u003e |\n| `type` | `number`  | _`static`_ reference to type id |\n| `allFrom(entity: Entity)` | `Component\u003cT\u003e[]`  | _`static`_ Get all instances of this component from entity |\n| `oneFrom(entity: Entity)` | `Component\u003cT\u003e`  | _`static`_ Get one instance of this component from entity |\n| `constructor` | `(data: T)` | Create a new instance of this custom component |\n| `type` | `number`  | reference to type id from instance |\n| `data` | `T`  | reference to raw data from instance |\n| \u003ch3\u003eEntity\u003c/h2\u003e |\n| `id` | `number`  | Instance unique id |\n| `active` | `boolean`  | Informs if the entity is active |\n| `add(component: Component)` |  | Add a component to this entity |\n| `remove(component: Component)` |  | Removes a component's reference from this entity |\n| `subscribe(handler: Susbcription)` | `cancel = () =\u003e Entity`  | Allows interested parties to receive information when this entity's component list is updated \u003cbr\u003e `Susbcription = (entity: Entity, added: Component[], removed: Component[]) =\u003e void` |\n| \u003ch3\u003eSystem\u003c/h2\u003e |\n| `constructor` | `(components: number[], frequence: number = 0)`  |  |\n| `id` | `number` | Unique identifier of an instance of this system |\n| `frequence` | `number` | The maximum times per second this system should be updated |\n| `beforeUpdateAll(time: number)` | | Invoked before updating entities available for this system. It is only invoked when there are entities with the characteristics expected by this system. |\n| `update(time: number, delta: number, entity: Entity)` | | Invoked in updates, limited to the value set in the \"frequency\" attribute |\n| `afterUpdateAll(time: number, entities: Entity[])` | | Invoked after performing update of entities available for this system. It is only invoked when there are entities with the characteristics expected by this system. |\n| `change(entity: Entity, added?: Component\u003cany\u003e, removed?: Component\u003cany\u003e)` | | Invoked when an expected feature of this system is added or removed from the entity |\n| `enter(entity: Entity)` | | Invoked when: \u003cbr\u003e**A)** An entity with the characteristics (components) expected by this system is added in the world; \u003cbr\u003e**B)** This system is added in the world and this world has one or more entities with the characteristics expected by this system; \u003cbr\u003e**C)** An existing entity in the same world receives a new component at runtime and all of its new components match the standard expected by this system. |\n| `exit(entity: Entity)` | | Invoked when: \u003cbr\u003e**A)** An entity with the characteristics (components) expected by this system is removed from the world; \u003cbr\u003e**B)** This system is removed from the world and this world has one or more entities with the characteristics expected by this system; \u003cbr\u003e**C)** An existing entity in the same world loses a component at runtime and its new component set no longer matches the standard expected by this system |\n\n\n## Feedback, Requests and Roadmap\n\nPlease use [GitHub issues] for feedback, questions or comments.\n\nIf you have specific feature requests or would like to vote on what others are recommending, please go to the [GitHub issues] section as well. I would love to see what you are thinking.\n\n## Contributing\n\nYou can contribute in many ways to this project.\n\n### Translating and documenting\n\nI'm not a native speaker of the English language, so you may have noticed a lot of grammar errors in this documentation.\n\nYou can FORK this project and suggest improvements to this document (https://github.com/nidorx/ecs-lib/edit/master/README.md).\n\nIf you find it more convenient, report a issue with the details on [GitHub issues].\n\n### Reporting Issues\n\nIf you have encountered a problem with this component please file a defect on [GitHub issues].\n\nDescribe as much detail as possible to get the problem reproduced and eventually corrected.\n\n### Fixing defects and adding improvements\n\n1. Fork it (\u003chttps://github.com/nidorx/ecs-lib/fork\u003e)\n2. Commit your changes (`git commit -am 'Add some fooBar'`)\n3. Push to your master branch (`git push`)\n4. Create a new Pull Request\n\n## License\n\nThis code is distributed under the terms and conditions of the [MIT license](LICENSE).\n\n\n[GitHub issues]: https://github.com/nidorx/ecs-lib/issues\n","funding_links":[],"categories":["Code","💻 Programming"],"sub_categories":["Engines and Frameworks","Code"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnidorx%2Fecs-lib","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fnidorx%2Fecs-lib","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnidorx%2Fecs-lib/lists"}