Compare commits

..

129 commits
v1.0 ... main

Author SHA1 Message Date
Justin van der Leij
848652f688
Make example for how to use Concord.utils.loadNamespace for systems more concrete 2024-06-30 10:45:46 +02:00
Justin van der Leij
30b21c4c25
Merge pull request #78 from denisdefreyne/patch-1
Fix typo in README.md
2024-06-30 10:38:53 +02:00
Justin van der Leij
9f187f12e5
Merge pull request #76 from lambtoken/typo-fix
Added missing do keyword in the loops
2024-06-30 10:38:15 +02:00
Denis Defreyne
6575686b3b
Fix typo in README.md
A piece of example code was missing a `,`.
2024-06-29 10:28:12 +02:00
Justin van der Leij
1aaf501401
Update README.md to hint that components should be loaded for systems 2024-05-27 13:53:55 +02:00
lambtoken
f9da8dbe92 Added missing do keyword in the loops 2023-12-23 09:37:03 +01:00
Justin van der Leij
7b8f7b2f0a
Merge pull request #70 from DanielPower/patch-1
Fix link to documentation
2023-02-26 16:28:39 +01:00
Daniel Power
5f4b3b97da
Fix link to documentation 2023-02-18 16:43:56 -03:30
Pablo Mayobre
2386547caa
Normalize slashes to dots when calling require in Utils.loadNamespace
Co-authored-by: Ulhar <ulhar@protonmail.ch>
2023-02-14 22:28:26 -03:00
Brandon Blanker Lim-it
1e4132be21 Added beforeEmit and afterEmit World callbacks (#54)
* Added beforeEmit and afterEmit World callbacks

* Fixed beforeEmit/afterEmit to handle recursive/nested emits;

* Added preventDefaults in beforeEmit
2023-02-14 22:20:34 -03:00
Jesse Viikari
429a448ab6 Add resources to world
- setResource(name, resource) to set a resource
- getResource(name) to retrieve it
2023-02-14 22:20:34 -03:00
Pablo Mayobre
9bccd05019 Usability improvements
- Now entity.key() is the same as entity.key.value
- Entity:serialize only serializes component given correctly
- Any other value inside the Entity is ignored
- Disable some diagnostics used in Lua language server by sumneko
2023-02-14 22:20:34 -03:00
Pablo Mayobre
cf05cfc972 Add ability to clone components
Fixes #51
2023-02-14 22:20:34 -03:00
flamendless
16c77c6a66 Fixed bug with serialization/deserialization 2023-02-14 22:20:34 -03:00
flamendless
61720312cb Added optional table for output for entity:getComponents 2023-02-14 22:20:34 -03:00
Pablo Ariel Mayobre
8e1b14d53b Ignore non-lua files in Utils.loadNamespace
Fixes #48
2023-02-14 22:20:34 -03:00
Pablo Ariel Mayobre
bdfe2523b0 Fix require indentation 2023-02-14 22:20:34 -03:00
flamendless
41fcfac6af Fixed errors on World:deserialize 2023-02-14 22:20:34 -03:00
Pablo Ariel Mayobre
a55efd042a Entity's Keys
You can now give the 'key' component to Entities.

A key will be generated automatically and stored in Entity.key.value.

You can then use this key to fetch the Entity from the World with World:getEntityByKey(key)

The keys are generated with a generator function that can be overriden.
2023-02-14 22:20:34 -03:00
Pablo Ariel Mayobre
3d195c790f Add World:query
This method allows you to query the World in order to find a set of Entities that matches a specific Filter.
2023-02-14 22:20:34 -03:00
Pablo Ariel Mayobre
a4ae392341 World:newEntity
A shortcut for Concord.entity(World)
2023-02-14 22:20:34 -03:00
Pablo Ariel Mayobre
cc0fd1614c Serializable component
You can remove the component to tell Concord an Entity shouldn't be serialized.

It's given automatically on Entity creation, but this can be disabled by changing Entity.SERIALIZE_BY_DEFAULT to false.
2023-02-14 22:20:34 -03:00
Pablo Ariel Mayobre
892f4d4700 Error handling overhaul 2023-02-14 22:20:34 -03:00
Pablo Ariel Mayobre
743d662ef9 Replaced Pools with Filters
Filters allow for a Pool constructor (defaults to Lists) that can be used to define Custom Pools.

The constructor is a function that takes the Filter Definition and returns a Custom Pool with these functions:

:add(e) - Add the Entity to the pool
:remove(e) - Remove the Entity from the pool
:has(e) boolean - Checks if the Entity exists in the pool
:clear() - Clears the Pool from Entities

Fixes #40
2023-02-14 22:20:34 -03:00
Pablo Ariel Mayobre
07bd5d0f28 Fix utils.loadNamespace when passed a table 2023-02-14 22:20:34 -03:00
Pablo Ariel Mayobre
c4594da19d Add Component:removed() callback
Fixes #37

I also added a reference to the Entity inside the Component which will help with #38
2023-02-14 22:20:34 -03:00
Pablo Ariel Mayobre
50249d5ad3 Removed deprecated functionality
Removed hasName/getName on Systems and Worlds.

Removed Entity.__components since it had a duplicate version of the components stored in the Entity itself.
2023-02-14 22:20:34 -03:00
Pablo Ariel Mayobre
695cc2dfe3 Add Component Negation
Fixes #32
2023-02-14 22:20:34 -03:00
Pablo Ariel Mayobre
89eab3fb72 List.sort
Fixes #33
2023-02-14 22:20:34 -03:00
Justin van der Leij
a45d89457b
Merge pull request #66 from wolfboyft/master
Fix bug where loading namespaces using folder/init.lua entries would only work if "folder" was 3 characters
2022-10-17 21:53:30 +02:00
Tachytaenius
940870318d
Fix bug where loading namespaces using folder/init.lua entries would only work if "folder" was 3 characters 2022-10-17 20:17:54 +01:00
Justin van der Leij
821b36c903
Merge pull request #46 from john-cheesman/correct-readme-code
Correct syntax in Systems example code
2022-10-17 15:12:18 +02:00
Justin van der Leij
7a4bfaf33c
Merge pull request #59 from josh-perry/fix-readme-docs-link
Fixed docs link in README
2022-06-01 17:51:12 +02:00
Josh Perry
2acb1458f2 Fixed docs link in README 2022-05-31 20:20:54 +01:00
Justin van der Leij
edc1d2fdbc Fix documentation page building workflow 13 2021-11-02 20:10:14 +01:00
Justin van der Leij
4313dc7856 Fix documentation page building workflow 12 2021-11-02 17:27:18 +01:00
Justin van der Leij
9c22986501 Fix documentation page building workflow 11 2021-11-02 17:23:53 +01:00
Justin van der Leij
73177f4048 Fix documentation page building workflow 10 2021-11-02 17:21:51 +01:00
Justin van der Leij
6ce714ce14 Fix documentation page building workflow 9 2021-11-02 17:21:22 +01:00
Justin van der Leij
e141a6183b Fix documentation page building workflow 8 2021-11-02 17:18:57 +01:00
Justin van der Leij
6329e09138 Fix documentation page building workflow 7 2021-11-02 17:16:51 +01:00
Justin van der Leij
cdf425d301 Fix documentation page building workflow 6 2021-11-02 17:08:25 +01:00
Justin van der Leij
c7625ad376 Fix documentation page building workflow 5 2021-11-02 17:02:38 +01:00
Justin van der Leij
65aae3c2ba Fix documentation page building workflow 4 2021-11-02 16:57:08 +01:00
Justin van der Leij
297b30aa50 Fix documentation page building workflow 3 2021-11-02 16:55:04 +01:00
Justin van der Leij
9aaff0fbcc Fix documentation page building workflow 2 2021-11-02 16:37:30 +01:00
Justin van der Leij
b701493a27 Fix documentation page building workflow 2021-11-02 16:32:24 +01:00
Justin van der Leij
b53f950e3e Add documentation page building workflow 2021-11-02 16:30:23 +01:00
John Cheesman
fd558dd3fe
Correct syntax in Systems example code 2021-05-05 18:32:04 +01:00
Pablo Ariel Mayobre
eb82c3c580
Update version
This will be version 3.0 of Concord
2021-01-09 19:20:03 -03:00
Pablo Ariel Mayobre
1325c4b445
Merge pull request #31 from DanielPower/master
Fix error in readme
2021-01-08 03:49:32 -03:00
Pablo Ariel Mayobre
d5c551046b
Merge pull request #24 from speakk/patch-1
Fix a typo in README.
2021-01-08 03:49:15 -03:00
Daniel Power
2196a41e71 Fix error in readme 2020-11-15 23:44:15 -03:30
Justin van der Leij
dd072adbe9
Merge pull request #30 from josh-perry/master
Regenerated docs
2020-08-18 16:24:21 +02:00
Josh Perry
7979226c33 Regenerated docs 2020-08-18 15:20:56 +01:00
Justin van der Leij
0897b1e4f9
Merge pull request #29 from Tjakka5/dev
Dev
2020-08-18 11:27:37 +02:00
Tjakka5
3e9c596187 Fix mistakes in readme 2020-05-02 20:51:15 +02:00
Tjakka5
c95a1f2768 Update license 2020-05-02 20:44:58 +02:00
Tjakka5
d56821205d Make repo submodule friendly 2020-05-02 20:44:33 +02:00
Tjakka5
c889b15d44 Remove old examples 2020-05-02 20:42:26 +02:00
Justin van der Leij
b906e2a910 Update docs 2020-03-16 10:35:55 +01:00
Pablo Ariel Mayobre
f640258852
Fix component:serialize can return nil 2020-03-15 01:04:44 -03:00
Pablo Ariel Mayobre
78dc7ee937
Fixed some error messages 2020-03-15 00:20:06 -03:00
Pablo Ariel Mayobre
d8621e4070
Fix serialization function to guard internal values 2020-03-14 19:09:23 -03:00
Pablo Ariel Mayobre
079c1d0e18
Utils.shallowCopy as a default serializer/deserializer for Components 2020-03-14 18:45:15 -03:00
Pablo Ariel Mayobre
9ae805aa43
Fixed: Pool:evaluate should bypass Pool:add filter check 2020-03-14 14:56:33 -03:00
Pablo Ariel Mayobre
16e111176e
Added Utils.loadNamespace
Deleted the previous Concord.loadComponents/Systems/Worlds
2020-03-14 14:55:11 -03:00
Pablo Ariel Mayobre
c640641b09
CONCORD IS DEAD
Long live Concord!!
2020-03-14 07:45:25 -03:00
Tjakka5
5dffe04b72 Fix flushing failing 2020-01-18 19:44:09 +01:00
Tjakka5
5252b0901b Merge branch 'master' of https://github.com/Tjakka5/Concord 2020-01-18 19:27:07 +01:00
Tjakka5
275d54726d Allow emits within emits 2020-01-18 19:26:38 +01:00
Justin van der Leij
be4a5d9ec7
Merge pull request #25 from jackamo/fix/quick-readme-fixes
README: Fix 'Quick Example' to be runnable
2020-01-09 10:58:02 +01:00
Jack Robinson
91f5799e50 README: Fix 'Quick Example' to be runnable 2020-01-09 22:12:39 +13:00
speakk
532151d901
Fix a typo in README. 2020-01-06 02:56:18 +02:00
Justin van der Leij
2cd738a135
Merge pull request #23 from tesselode/ldoc-improvements
make the docs a little nicer
2020-01-04 16:40:23 +01:00
Justin van der Leij
c39151faa7
Merge pull request #22 from tesselode/patch-1
fix typos in readme
2020-01-04 16:40:12 +01:00
Andrew Minnich
a65f88dd5e make the docs a little nicer
main changes:
- add parameter and return types where applicable
- use @module and @classmod tags at the top of files
- remove some redundant descriptions of return values, especially for functions that return a boolean

recommended next steps:
- more consistent grammar
- add links to classes and functions in descriptions where appropriate
- be consistent about naming Systems vs. SystemClasses and Components vs. ComponentClasses
2020-01-04 10:31:05 -05:00
tesselode
f392dc6f07
fix typos 2020-01-04 09:52:50 -05:00
Tjakka5
55ae5fd987 Add helper functions to container. Allow name to be gotten 2020-01-04 13:40:18 +01:00
Tjakka5
6cd66e6737 Add serialization and deserialization functions to component, entity, world 2020-01-04 13:26:26 +01:00
Tjakka5
c217183cb9 Fix typos in readme 2020-01-04 12:24:15 +01:00
Tjakka5
3b52f28fe0 Finish first version of documentation 2020-01-04 11:46:10 +01:00
Tjakka5
cf51bccb81 Fix naming of system:clear, system:setEnable 2020-01-04 11:10:29 +01:00
Tjakka5
90b949f8a5 rename src folder in config.ld 2020-01-04 10:50:41 +01:00
Tjakka5
f502f1b9f6 rename folder src to concord 2020-01-04 10:50:13 +01:00
Tjakka5
451b88cdea Finish system optimization 2020-01-04 10:47:45 +01:00
Tjakka5
424f27ed8a First version of documentation 2020-01-04 04:44:21 +01:00
Tjakka5
0e1023d2ce Publish regenerated LDoc pages 2020-01-04 01:54:21 +01:00
Tjakka5
58d9e44bb1 Remove test files 2020-01-04 01:52:01 +01:00
Tjakka5
df6c6ed73e Merge branch 'master' into dev 2020-01-04 01:48:44 +01:00
Tjakka5
368766bd27 Fix broken LDoc tags 2020-01-04 01:41:58 +01:00
Tjakka5
69a9e83759 Document full project. Lots of small fixes 2020-01-04 01:04:18 +01:00
Tjakka5
f6669b2e63 Improve internal style 2020-01-03 23:12:56 +01:00
Tjakka5
6aeb91d984 Add optional optimization for worlds and systems 2020-01-03 23:01:04 +01:00
Tjakka5
56b5244541 Let System functions return self 2020-01-03 22:20:31 +01:00
Tjakka5
04a35a117e Allow systems to be disabled 2020-01-03 22:19:01 +01:00
Tjakka5
6eaf66308d Revamp how systems are added to worlds 2020-01-03 22:07:13 +01:00
Tjakka5
f6468fbe6b Add Entity:hasWorld 2020-01-03 21:40:09 +01:00
Tjakka5
ce32d16b8d Allow Entity.new to take a world 2020-01-03 21:39:40 +01:00
Tjakka5
fea5fc7223 Fix World:clear 2020-01-03 18:03:12 +01:00
Tjakka5
e5d6e1f4b9 Remove temp tests 2020-01-03 18:02:10 +01:00
Tjakka5
0183421c47 Clean up entity and world. Remove list:get 2019-12-29 15:56:20 +01:00
Tjakka5
38d461f8d6 Fixed entity lifetime problems 2019-12-29 15:05:19 +01:00
Tjakka5
a8bc92a951 Allow for blank components 2019-12-22 23:17:16 +01:00
Tjakka5
144a42dc9e Automate naming process 2019-12-22 23:07:42 +01:00
Tjakka5
e0f88025ba Clean up component vs baseComponent 2019-12-22 21:08:30 +01:00
Tjakka5
f6536d5a0e Add entity:getWorld 2019-12-22 21:02:25 +01:00
Tjakka5
89443bd961 Make e:flush 'private' 2019-12-22 21:01:47 +01:00
Tjakka5
ecb3c2db7e Cache added and removed components 2019-12-22 21:00:53 +01:00
Tjakka5
bb508ee947 Add Entity:getComponents 2019-12-21 12:00:48 +01:00
Tjakka5
073aadf74b Test commit 2019-12-20 19:25:11 +01:00
Tjakka5
2057767e75 Add world:hasSystem, world:getSystem 2019-12-20 19:00:47 +01:00
Tjakka5
276a053b7f Allow named assemblages 2019-12-19 20:19:02 +01:00
Tjakka5
d0e227485e Allow named worlds 2019-12-19 20:14:21 +01:00
Tjakka5
d4efca976c Added named systems 2019-12-19 10:34:02 +01:00
Tjakka5
038111d558 Streamline entity lifetime 2019-12-19 08:47:38 +01:00
Tjakka5
bc47eaa651 Allow for named components 2019-12-11 13:04:09 +01:00
Tjakka5
f7e1be8e1d Remove todo list 2019-12-10 12:22:15 +01:00
Justin van der Leij
4c5e6a06dc
Merge pull request #20 from wolfboyft/patch-1
Fixed a broken luadoc comment
2019-05-22 13:15:13 +02:00
Tachytaenius
cc6783ac31
Fixed a broken luadoc comment
Rewriting this code was haaaard, man...
2019-05-21 19:08:43 +01:00
Justin van der Leij
93da73ad6c
Formatting is hard 2019-05-08 11:44:42 +02:00
Justin van der Leij
052e1cd2ce
Add example games 2019-05-08 11:44:15 +02:00
Justin van der Leij
83162ec02c Rename 'context' to 'world' 2018-11-29 22:04:50 +01:00
Justin van der Leij
26bd0ef937 Rename 'instance' to 'context' 2018-11-26 12:58:41 +01:00
Justin van der Leij
89a3a7fa8a Rename 'lib' directory to 'src' 2018-11-26 12:45:24 +01:00
Justin van der Leij
39ec2106b7 Removed .init 2018-11-26 12:43:48 +01:00
Justin van der Leij
6ddb28ffbc Small fixes 2018-11-26 12:37:28 +01:00
Justin van der Leij
f7a394f057 Added assemblages 2018-11-12 15:18:17 +01:00
Justin van der Leij
11255fd722 Optimized Lists. Added pool.added and .removed. Added entity:ensure 2018-10-02 21:52:23 +02:00
55 changed files with 5503 additions and 2684 deletions

38
.github/workflows/doc.yml vendored Normal file
View file

@ -0,0 +1,38 @@
name: Build Docs
on:
push:
branches:
- master
jobs:
build:
name: Build docs
runs-on: ubuntu-latest
steps:
- name: Check out repository
uses: actions/checkout@v2
- name: Setup Lua
uses: leafo/gh-actions-lua@v8
with:
luaVersion: 5.4
- name: Install Luarocks
uses: leafo/gh-actions-luarocks@v4
- name: Install LDoc
run: luarocks install ldoc
- name: Show
run: luarocks show ldoc
- name: Build docs
run: ldoc .
- name: Deploy
uses: JamesIves/github-pages-deploy-action@4.1.5
with:
branch: gh-pages
folder: docs

5
.gitignore vendored
View file

@ -37,4 +37,7 @@ luac.out
*.app
*.i*86
*.x86_64
*.hex
*.hex
# VSCode
.vscode/

2
.luacheckrc Normal file
View file

@ -0,0 +1,2 @@
---@diagnostic disable: lowercase-global
std="love+luajit"

40
LICENSE
View file

@ -1,21 +1,21 @@
MIT License
Copyright (c) 2018 Justin van der Leij
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
MIT License
Copyright (c) 2018 Justin van der Leij
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

564
README.md
View file

@ -1,39 +1,525 @@
# Concord
Concord is a feature complete ECS.
It's main focus is on speed and usage. You should be able to quickly write code that performs well.
Documentation for Concord can be found in the [Wiki tab](https://github.com/Tjakka5/Concord/wiki).
Auto generated docs for Concord can be found in the [Github page](https://tjakka5.github.io/Concord/). These are still work in progress and might be incomplete though.
## Installation
Download the repository and drop it in your project, then simply require it as:
```lua
local Concord = require(PathToConcord).init()
You will only need to call .init once when you first require it.
```
## Modules
Below is a list of modules.
More information about what each done can be found in the Wiki
```lua
local Concord = require("concord")
local Entity = require("concord.entity")
local Component = require("concord.component")
local System = require("concord.system")
local Instance = require("concord.instance")
```
## Contributors
```
Positive07: Constant support and a good rubberduck
Brbl: Early testing and issue reporting
Josh: Squashed a few bugs and docs
Erasio: Took inspiration from HooECS. Also introduced me to ECS.
```
## Licence
MIT Licensed - Copyright Justin van der Leij (Tjakka5)
# Concord
Concord is a feature complete ECS for LÖVE.
It's main focus is performance and ease of use.
With Concord it is possibile to easily write fast and clean code.
This readme will explain how to use Concord.
Additionally all of Concord is documented using the LDoc format.
Auto generated docs for Concord can be found in `docs` folder, or on the [GitHub page](https://keyslam-group.github.io/Concord/).
---
## Table of Contents
[Installation](#installation)
[ECS](#ecs)
[API](#api) :
- [Components](#components)
- [Entities](#entities)
- [Systems](#systems)
- [Worlds](#worlds)
- [Assemblages](#assemblages)
[Quick Example](#quick-example)
[Contributors](#contributors)
[License](#licence)
---
## Installation
Download the repository and copy the 'concord' folder into your project. Then require it in your project like so:
```lua
local Concord = require("path.to.concord")
```
Concord has a bunch of modules. These can be accessed through Concord:
```lua
-- Modules
local Entity = Concord.entity
local Component = Concord.component
local System = Concord.system
local World = Concord.world
-- Containers
local Components = Concord.components
```
---
## ECS
Concord is an Entity Component System (ECS for short) library.
This is a coding paradigm where _composition_ is used over _inheritance_.
Because of this it is easier to write more modular code. It often allows you to combine any form of behaviour for the objects in your game (Entities).
As the name might suggest, ECS consists of 3 core things: Entities, Components, and Systems. A proper understanding of these is required to use Concord effectively.
We'll start with the simplest one.
### Components
Components are pure raw data. In Concord this is just a table with some fields.
A position component might look like
`{ x = 100, y = 50}`, whereas a health Component might look like `{ currentHealth = 10, maxHealth = 100 }`.
What is most important is that Components are data and nothing more. They have 0 functionality.
### Entities
Entities are the actual objects in your game. Like a player, an enemy, a crate, or a bullet.
Every Entity has it's own set of Components, with their own values.
A crate might have the following components (Note: Not actual Concord syntax):
```lua
{
position = { x = 100, y = 200 },
texture = { path = "crate.png", image = Image },
pushable = { },
}
```
Whereas a player might have the following components:
```lua
{
position = { x = 200, y = 300 },
texture = { path = "player.png", image = Image },
controllable = { keys = "wasd" },
health = { currentHealth = 10, maxHealth = 100},
}
```
Any Component can be given to any Entity (once). Which Components an Entity has will determine how it behaves. This is done through the last thing...
### Systems
Systems are the things that actually _do_ stuff. They contain all your fancy algorithms and cool game logic.
Each System will do one specific task like say, drawing Entities.
For this they will only act on Entities that have the Components needed for this: `position` and `texture`. All other Components are irrelevant.
In Concord this is done something alike this:
```lua
drawSystem = System({pool = {position, texture}}) -- Define a System that takes all Entities with a position and texture Component
function drawSystem:draw() -- Give it a draw function
for _, entity in ipairs(self.pool) do -- Iterate over all Entities that this System acts on
local position = entity.position -- Get the position Component of this Entity
local texture = entity.texture -- Get the texture Component of this Entity
-- Draw the Entity
love.graphics.draw(texture.image, position.x, position.y)
end
end
```
### To summarize...
- Components contain only data.
- Entities contain any set of Components.
- Systems act on Entities that have a required set of Components.
By creating Components and Systems you create modular behaviour that can apply to any Entity.
What if we took our crate from before and gave it the `controllable` Component? It would respond to our user input of course.
Or what if the enemy shot bullets with a `health` Component? It would create bullets that we'd be able to destroy by shooting them.
And all that without writing a single extra line of code. Just reusing code that already existed and is guaranteed to be reuseable.
---
## API
### General design
Concord does a few things that might not be immediately clear. This segment should help understanding.
#### Requiring files
Since you'll have lots of Components and Systems in your game Concord makes it a bit easier to load things in.
```lua
-- Loads all files in the directory. Components automatically register into Concord.components, so loading them into a namespace isn't necessary.
Concord.utils.loadNamespace("path/to/components")
print(Concord.components.componentName)
-- Loads all files in the directory, and puts the return value in the table Systems. The key is their filename without any extension
local Systems = {}
Concord.utils.loadNamespace("path/to/systems", Systems)
myWorld:addSystems(
Systems.healthSystem
Systems.damageSystem,
Systems.moveSystem,
-- etc
)
```
#### Method chaining
```lua
-- Most (if not all) methods will return self
-- This allowes you to chain methods
myEntity
:give("position", 100, 50)
:give("velocity", 200, 0)
:remove("position")
:destroy()
myWorld
:addEntity(fooEntity)
:addEntity(barEntity)
:clear()
:emit("test")
```
### Components
When defining a ComponentClass you need to pass in a name and usually a `populate` function. This will fill the Component with values.
```lua
-- Create the position class with a populate function
-- The component variable is the actual Component given to an Entity
-- The x and y variables are values we pass in when we create the Component
Concord.component("position", function(component, x, y)
component.x = x or 0
component.y = y or 0
end)
-- Create a ComponentClass without a populate function
-- Components of this type won't have any fields.
-- This can be useful to indiciate state.
local pushableComponentClass = Concord.component("position")
```
### Entities
Entities can be freely made and be given Components. You pass the name of the ComponentClass and the values you want to pass. It will then create the Component for you.
Entities can only have a maximum of one of each Component.
Entities can not share Components.
```lua
-- Create a new Entity
local myEntity = Entity()
-- or
local myEntity = Entity(myWorld) -- To add it to a world immediately ( See World )
```
```lua
-- Give the entity the position Component defined above
-- x will become 100. y will become 50
myEntity:give("position", 100, 50)
```
```lua
-- Retrieve a Component
local position = myEntity.position
print(position.x, position.y) -- 100, 50
```
```lua
-- Remove a Component
myEntity:remove("position")
```
```lua
-- Entity:give will override a Component if the Entity already has it
-- Entity:ensure will only put the Component if the Entity does not already have it
Entity:ensure("position", 0, 0) -- Will give
-- Position is {x = 0, y = 0}
Entity:give("position", 50, 50) -- Will override
-- Position is {x = 50, y = 50}
Entity:give("position", 100, 100) -- Will override
-- Position is {x = 100, y = 100}
Entity:ensure("position", 0, 0) -- Wont do anything
-- Position is {x = 100, y = 100}
```
```lua
-- Retrieve all Components
-- WARNING: Do not modify this table. It is read-only
local allComponents = myEntity:getComponents()
for ComponentClass, Component in ipairs(allComponents) do
-- Do stuff
end
```
```lua
-- Assemble the Entity ( See Assemblages )
myEntity:assemble(assemblageFunction, 100, true, "foo")
```
```lua
-- Check if the Entity is in a world
local inWorld = myEntity:inWorld()
-- Get the World the Entity is in
local world = myEntity:getWorld()
```
```lua
-- Destroy the Entity
myEntity:destroy()
```
### Systems
Systems are defined as a SystemClass. Concord will automatically create an instance of a System when it is needed.
Systems get access to Entities through `pools`. They are created using a filter.
Systems can have multiple pools.
```lua
-- Create a System
local mySystemClass = Concord.system({pool = {"position"}}) -- Pool named 'pool' will contain all Entities with a position Component
-- Create a System with multiple pools
local mySystemClass = Concord.system({
pool = { -- This pool will be named 'pool'
"position",
"velocity",
},
secondPool = { -- This pool's name will be 'secondPool'
"health",
"damageable",
}
})
```
```lua
-- If a System has a :init function it will be called on creation
-- world is the World the System was created for
function mySystemClass:init(world)
-- Do stuff
end
```
```lua
-- Defining a function
function mySystemClass:update(dt)
-- Iterate over all entities in the Pool
for _, e in ipairs(self.pool) do
-- Do something with the Components
e.position.x = e.position.x + e.velocity.x * dt
e.position.y = e.position.y + e.velocity.y * dt
end
-- Iterate over all entities in the second Pool
for _, e in ipairs(self.secondPool) do
-- Do something
end
end
```
```lua
-- Systems can be enabled and disabled
-- When systems are disabled their callbacks won't be executed.
-- Note that pools will still be updated
-- This is mainly useful for systems that display debug information
-- Systems are enabled by default
-- Enable a System
mySystem:setEnable(true)
-- Disable a System
mySystem:setEnable(false)
-- Get enabled state
local isEnabled = mySystem:isEnabled()
print(isEnabled) -- false
```
```lua
-- Get the World the System is in
local world = System:getWorld()
```
### Worlds
Worlds are the thing your System and Entities live in.
With Worlds you can `:emit` a callback. All Systems with this callback will then be called.
Worlds can have 1 instance of every SystemClass.
Worlds can have any number of Entities.
```lua
-- Create World
local myWorld = Concord.world()
```
```lua
-- Add an Entity to the World
myWorld:addEntity(myEntity)
-- Remove an Entity from the World
myWorld:removeEntity(myEntity)
```
```lua
-- Add a System to the World
myWorld:addSystem(mySystemClass)
-- Add multiple Systems to the World
myWorld:addSystems(moveSystemClass, renderSystemClass, controlSystemClass)
```
```lua
-- Check if the World has a System
local hasSystem = myWorld:hasSystem(mySystemClass)
-- Get a System from the World
local mySystem = myWorld:getSystem(mySystemClass)
```
```lua
-- Emit an event
-- This will call the 'update' function of all added Systems if they have one
-- They will be called in the order they were added
myWorld:emit("update", dt)
-- You can emit any event with any parameters
myWorld:emit("customCallback", 100, true, "Hello World")
```
```lua
-- Remove all Entities from the World
myWorld:clear()
```
```lua
-- Override-able callbacks
-- Called when an Entity is added to the World
-- e is the Entity added
function myWorld:onEntityAdded(e)
-- Do something
end
-- Called when an Entity is removed from the World
-- e is the Entity removed
function myWorld:onEntityRemoved(e)
-- Do something
end
```
### Assemblages
Assemblages are functions to 'make' Entities something.
An important distinction is that they _append_ Components.
```lua
-- Make an Assemblage function
-- e is the Entity being assembled.
-- cuteness and legs are variables passed in
function animal(e, cuteness, legs)
e
:give(cutenessComponentClass, cuteness)
:give(limbs, legs, 0) -- Variable amount of legs. 0 arm.
end)
-- Make an Assemblage that uses animal
-- cuteness is a variables passed in
function cat(e, cuteness)
e
:assemble(animal, cuteness * 2, 4) -- Cats are twice as cute, and have 4 legs.
:give(soundComponent, "meow.mp3")
end)
```
```lua
-- Use an Assemblage
myEntity:assemble(cat, 100) -- 100 cuteness
```
---
## Quick Example
```lua
local Concord = require("concord")
-- Defining components
Concord.component("position", function(c, x, y)
c.x = x or 0
c.y = y or 0
end)
Concord.component("velocity", function(c, x, y)
c.x = x or 0
c.y = y or 0
end)
local Drawable = Concord.component("drawable")
-- Defining Systems
local MoveSystem = Concord.system({
pool = {"position", "velocity"}
})
function MoveSystem:update(dt)
for _, e in ipairs(self.pool) do
e.position.x = e.position.x + e.velocity.x * dt
e.position.y = e.position.y + e.velocity.y * dt
end
end
local DrawSystem = Concord.system({
pool = {"position", "drawable"}
})
function DrawSystem:draw()
for _, e in ipairs(self.pool) do
love.graphics.circle("fill", e.position.x, e.position.y, 5)
end
end
-- Create the World
local world = Concord.world()
-- Add the Systems
world:addSystems(MoveSystem, DrawSystem)
-- This Entity will be rendered on the screen, and move to the right at 100 pixels a second
local entity_1 = Concord.entity(world)
:give("position", 100, 100)
:give("velocity", 100, 0)
:give("drawable")
-- This Entity will be rendered on the screen, and stay at 50, 50
local entity_2 = Concord.entity(world)
:give("position", 50, 50)
:give("drawable")
-- This Entity does exist in the World, but since it doesn't match any System's filters it won't do anything
local entity_3 = Concord.entity(world)
:give("position", 200, 200)
-- Emit the events
function love.update(dt)
world:emit("update", dt)
end
function love.draw()
world:emit("draw")
end
```
---
## Contributors
- __Positive07__: Constant support and a good rubberduck
- __Brbl__: Early testing and issue reporting
- __Josh__: Squashed a few bugs and generated docs
- __Erasio__: I took inspiration from HooECS. He also introduced me to ECS
- __Speak__: Lots of testing for new features of Concord
- __Tesselode__: Brainstorming and helpful support
---
## License
MIT Licensed - Copyright Justin van der Leij (Tjakka5)

View file

@ -0,0 +1,6 @@
local PATH = (...):gsub("(%.init)$", "")
return {
serializable = require(PATH..".serializable"),
key = require(PATH..".key"),
}

41
concord/builtins/key.lua Normal file
View file

@ -0,0 +1,41 @@
local PATH = (...):gsub('%.builtins%.[^%.]+$', '')
local Component = require(PATH..".component")
local getKey = function (self, key)
local entity = self.__entity
if not entity:inWorld() then
error("entity needs to belong to a world")
end
local world = entity:getWorld()
return world:__assignKey(entity, key)
end
local Key = Component("key", function (self, key)
self.value = getKey(self, key)
end)
function Key:deserialize (data)
self.value = getKey(self, data)
end
function Key.__mt:__call()
return self.value
end
function Key:removed (replaced)
if not replaced then
local entity = self.__entity
if entity:inWorld() then
local world = entity:getWorld()
return world:__clearKey(entity)
end
end
end
return Key

View file

@ -0,0 +1,12 @@
local PATH = (...):gsub('%.builtins%.[^%.]+$', '')
local Component = require(PATH..".component")
local Serializable = Component("serializable")
function Serializable:serialize ()
-- Don't serialize this Component
return nil
end
return Serializable

120
concord/component.lua Normal file
View file

@ -0,0 +1,120 @@
--- A pure data container that is contained by a single entity.
-- @classmod Component
local PATH = (...):gsub('%.[^%.]+$', '')
local Components = require(PATH..".components")
local Utils = require(PATH..".utils")
local Component = {}
Component.__mt = {
__index = Component,
}
--- Creates a new ComponentClass.
-- @tparam function populate Function that populates a Component with values
-- @treturn Component A new ComponentClass
function Component.new(name, populate)
if (type(name) ~= "string") then
Utils.error(2, "bad argument #1 to 'Component.new' (string expected, got %s)", type(name))
end
if (string.match(name, Components.__REJECT_MATCH) ~= "") then
Utils.error(2, "bad argument #1 to 'Component.new' (Component names can't start with '%s', got %s)", Components.__REJECT_PREFIX, name)
end
if (rawget(Components, name)) then
Utils.error(2, "bad argument #1 to 'Component.new' (ComponentClass with name '%s' was already registerd)", name) -- luacheck: ignore
end
if (type(populate) ~= "function" and type(populate) ~= "nil") then
Utils.error(2, "bad argument #1 to 'Component.new' (function/nil expected, got %s)", type(populate))
end
local componentClass = setmetatable({
__populate = populate,
__name = name,
__isComponentClass = true,
}, Component.__mt)
componentClass.__mt = {
__index = componentClass
}
Components[name] = componentClass
return componentClass
end
-- Internal: Populates a Component with values.
function Component:__populate() -- luacheck: ignore
end
-- Callback: When the Component gets removed or replaced in an Entity.
function Component:removed() -- luacheck: ignore
end
-- Callback: When the Component gets serialized as part of an Entity.
function Component:serialize()
local data = Utils.shallowCopy(self, {})
--This values shouldn't be copied over
data.__componentClass = nil
data.__entity = nil
data.__isComponent = nil
data.__isComponentClass = nil
return data
end
-- Callback: When the Component gets deserialized from serialized data.
function Component:deserialize(data)
Utils.shallowCopy(data, self)
end
-- Internal: Creates a new Component.
-- @param entity The Entity that will receive this Component.
-- @return A new Component
function Component:__new(entity)
local component = setmetatable({
__componentClass = self,
__entity = entity,
__isComponent = true,
__isComponentClass = false,
}, self.__mt)
return component
end
-- Internal: Creates and populates a new Component.
-- @param entity The Entity that will receive this Component.
-- @param ... Varargs passed to the populate function
-- @return A new populated Component
function Component:__initialize(entity, ...)
local component = self:__new(entity)
---@diagnostic disable-next-line: redundant-parameter
self.__populate(component, ...)
return component
end
--- Returns true if the Component has a name.
-- @treturn boolean
function Component:hasName()
return self.__name and true or false
end
--- Returns the name of the Component.
-- @treturn string
function Component:getName()
return self.__name
end
return setmetatable(Component, {
__call = function(_, ...)
return Component.new(...)
end,
})

73
concord/components.lua Normal file
View file

@ -0,0 +1,73 @@
--- Container for registered ComponentClasses
-- @module Components
local Components = {}
Components.__REJECT_PREFIX = "!"
Components.__REJECT_MATCH = "^(%"..Components.__REJECT_PREFIX.."?)(.+)"
--- Returns true if the containter has the ComponentClass with the specified name
-- @string name Name of the ComponentClass to check
-- @treturn boolean
function Components.has(name)
return rawget(Components, name) and true or false
end
--- Prefix a component's name with the currently set Reject Prefix
-- @string name Name of the ComponentClass to reject
-- @treturn string
function Components.reject(name)
local ok, err = Components.try(name)
if not ok then error(err, 2) end
return Components.__REJECT_PREFIX..name
end
--- Returns true and the ComponentClass if one was registered with the specified name
-- or false and an error otherwise
-- @string name Name of the ComponentClass to check
-- @boolean acceptRejected Whether to accept names prefixed with the Reject Prefix.
-- @treturn boolean
-- @treturn Component or error string
-- @treturn true if acceptRejected was true and the name had the Reject Prefix, false otherwise.
function Components.try(name, acceptRejected)
if type(name) ~= "string" then
return false, "ComponentsClass name is expected to be a string, got "..type(name)..")"
end
local rejected = false
if acceptRejected then
local prefix
prefix, name = string.match(name, Components.__REJECT_MATCH)
rejected = prefix ~= "" and name
end
local value = rawget(Components, name)
if not value then
return false, "ComponentClass '"..name.."' does not exist / was not registered"
end
return true, value, rejected
end
--- Returns the ComponentClass with the specified name
-- @string name Name of the ComponentClass to get
-- @treturn Component
function Components.get(name)
local ok, value = Components.try(name)
if not ok then error(value, 2) end
return value
end
return setmetatable(Components, {
__index = function(_, name)
local ok, value = Components.try(name)
if not ok then error(value, 2) end
return value end
})

281
concord/entity.lua Normal file
View file

@ -0,0 +1,281 @@
--- An object that exists in a world. An entity
-- contains components which are processed by systems.
-- @classmod Entity
local PATH = (...):gsub('%.[^%.]+$', '')
local Components = require(PATH..".components")
local Type = require(PATH..".type")
local Utils = require(PATH..".utils")
-- Initialize built-in Components (as soon as possible)
local Builtins = require(PATH..".builtins.init") --luacheck: ignore
-- Builtins is unused but the require already registers the Components
local Entity = {
SERIALIZE_BY_DEFAULT = true,
}
Entity.__mt = {
__index = Entity,
}
--- Creates a new Entity. Optionally adds it to a World.
-- @tparam[opt] World world World to add the entity to
-- @treturn Entity A new Entity
function Entity.new(world)
if (world ~= nil and not Type.isWorld(world)) then
Utils.error(2, "bad argument #1 to 'Entity.new' (world/nil expected, got %s)", type(world))
end
local e = setmetatable({
__world = nil,
__isEntity = true,
}, Entity.__mt)
if (world) then
world:addEntity(e)
end
if Entity.SERIALIZE_BY_DEFAULT then
e:give("serializable")
end
return e
end
local function createComponent(e, name, componentClass, ...)
local component = componentClass:__initialize(e, ...)
local hadComponent = not not e[name]
if hadComponent then
e[name]:removed(true)
end
e[name] = component
if not hadComponent then
e:__dirty()
end
end
local function deserializeComponent(e, name, componentData)
local componentClass = Components[name]
local hadComponent = not not e[name]
if hadComponent then
e[name]:removed(true)
end
local component = componentClass:__new(e)
component:deserialize(componentData)
e[name] = component
if not hadComponent then
e:__dirty()
end
end
local function giveComponent(e, ensure, name, ...)
local component
if Type.isComponent(name) then
component = name
name = component:getName()
end
if ensure and e[name] then
return e
end
local ok, componentClass = Components.try(name)
if not ok then
Utils.error(3, "bad argument #1 to 'Entity:%s' (%s)", ensure and 'ensure' or 'give', componentClass)
end
if component then
local data = component:deserialize()
if data == nil then
Utils.error(3, "bad argument #1 to 'Entity:$s' (Component '%s' couldn't be deserialized)", ensure and 'ensure' or 'give', name)
end
deserializeComponent(e, name, data)
else
createComponent(e, name, componentClass, ...)
end
return e
end
local function removeComponent(e, name)
if e[name] then
e[name]:removed(false)
e[name] = nil
e:__dirty()
end
end
--- Gives an Entity a Component.
-- If the Component already exists, it's overridden by this new Component
-- @tparam Component componentClass ComponentClass to add an instance of
-- @param ... additional arguments to pass to the Component's populate function
-- @treturn Entity self
function Entity:give(name, ...)
return giveComponent(self, false, name, ...)
end
--- Ensures an Entity to have a Component.
-- If the Component already exists, no action is taken
-- @tparam Component componentClass ComponentClass to add an instance of
-- @param ... additional arguments to pass to the Component's populate function
-- @treturn Entity self
function Entity:ensure(name, ...)
return giveComponent(self, true, name, ...)
end
--- Removes a Component from an Entity.
-- @tparam Component componentClass ComponentClass of the Component to remove
-- @treturn Entity self
function Entity:remove(name)
local ok, componentClass = Components.try(name)
if not ok then
Utils.error(2, "bad argument #1 to 'Entity:remove' (%s)", componentClass)
end
removeComponent(self, name)
return self
end
--- Assembles an Entity.
-- @tparam function assemblage Function that will assemble an entity
-- @param ... additional arguments to pass to the assemblage function.
-- @treturn Entity self
function Entity:assemble(assemblage, ...)
if type(assemblage) ~= "function" then
Utils.error(2, "bad argument #1 to 'Entity:assemble' (function expected, got %s)", type(assemblage))
end
assemblage(self, ...)
return self
end
--- Destroys the Entity.
-- Removes the Entity from its World if it's in one.
-- @return self
function Entity:destroy()
if self.__world then
self.__world:removeEntity(self)
end
return self
end
-- Internal: Tells the World it's in that this Entity is dirty.
-- @return self
function Entity:__dirty()
if self.__world then
self.__world:__dirtyEntity(self)
end
return self
end
--- Returns true if the Entity has a Component.
-- @tparam Component componentClass ComponentClass of the Component to check
-- @treturn boolean
function Entity:has(name)
local ok, componentClass = Components.try(name)
if not ok then
Utils.error(2, "bad argument #1 to 'Entity:has' (%s)", componentClass)
end
return self[name] and true or false
end
--- Gets a Component from the Entity.
-- @tparam Component componentClass ComponentClass of the Component to get
-- @treturn table
function Entity:get(name)
local ok, componentClass = Components.try(name)
if not ok then
Utils.error(2, "bad argument #1 to 'Entity:get' (%s)", componentClass)
end
return self[name]
end
--- Returns a table of all Components the Entity has.
-- Warning: Do not modify this table.
-- Use Entity:give/ensure/remove instead
-- @treturn table Table of all Components the Entity has
function Entity:getComponents(output)
output = output or {}
local components = Utils.shallowCopy(self, output)
components.__world = nil
components.__isEntity = nil
return components
end
--- Returns true if the Entity is in a World.
-- @treturn boolean
function Entity:inWorld()
return self.__world and true or false
end
--- Returns the World the Entity is in.
-- @treturn World
function Entity:getWorld()
return self.__world
end
function Entity:serialize(ignoreKey)
local data = {}
for name, component in pairs(self) do
-- The key component needs to be treated separately.
if name == "key" and component.__name == "key" then
if not ignoreKey then
data.key = component.value
end
--We only care about components that were properly given to the entity
elseif Type.isComponent(component) and (component.__name == name) then
local componentData = component:serialize()
if componentData ~= nil then
componentData.__name = component.__name
data[#data + 1] = componentData
end
end
end
return data
end
function Entity:deserialize(data)
for i = 1, #data do
local componentData = data[i]
if (not Components.has(componentData.__name)) then
Utils.error(2, "bad argument #1 to 'Entity:deserialize' (ComponentClass '%s' wasn't yet loaded)", tostring(componentData.__name)) -- luacheck: ignore
end
deserializeComponent(self, componentData.__name, componentData)
end
end
return setmetatable(Entity, {
__call = function(_, ...)
return Entity.new(...)
end,
})

199
concord/filter.lua Normal file
View file

@ -0,0 +1,199 @@
--- Used to filter Entities with specific Components
-- A Filter has an associated Pool that can contain any amount of Entities.
-- @classmod Filter
local PATH = (...):gsub('%.[^%.]+$', '')
local List = require(PATH..".list")
local Type = require(PATH..".type")
local Utils = require(PATH..".utils")
local Components = require(PATH..".components")
local Filter = {}
Filter.__mt = {
__index = Filter,
}
--- Validates a Filter Definition to make sure every component is valid.
-- @string name Name for the Filter.
-- @tparam table definition Table containing the Filter Definition
-- @tparam onComponent Optional function, called when a component is valid.
function Filter.validate (errorLevel, name, def, onComponent)
local filter = "World:query filter"
if name then
filter = ("filter '%s'"):format(name)
end
if type(def) ~= 'table' then
Utils.error(3 + errorLevel, "invalid component list for %s (table expected, got %s)", filter, type(def))
end
if not onComponent and def.constructor and not Type.isCallable(def.constructor) then
Utils.error(3 + errorLevel, "invalid pool constructor for %s (callable expected, got %s)", filter, type(def.constructor))
end
for n, component in ipairs(def) do
local ok, err, reject = Components.try(component, true)
if not ok then
Utils.error(3 + errorLevel, "invalid component for %s at position #%d (%s)", filter, n, err)
end
if onComponent then
onComponent(component, reject)
end
end
end
--- Parses the Filter Defintion into two tables
-- required: An array of all the required component names.
-- rejected: An array of all the components that will be rejected.
-- @string name Name for the Filter.
-- @tparam table definition Table containing the Filter Definition
-- @treturn table required
-- @treturn table rejected
function Filter.parse (name, def)
local filter = {}
Filter.validate(1, name, def, function (component, reject)
if reject then
table.insert(filter, reject)
table.insert(filter, false)
else
table.insert(filter, component)
table.insert(filter, true)
end
end)
return filter
end
function Filter.match (e, filter)
for i=#filter, 2, -2 do
local match = filter[i - 0]
local name = filter[i - 1]
if (not e[name]) == match then return false end
end
return true
end
local REQUIRED_METHODS = {"add", "remove", "has", "clear"}
local VALID_POOL_TYPES = {table=true, userdata=true, lightuserdata=true, cdata=true}
function Filter.isValidPool (name, pool)
local poolType = type(pool)
--Check that pool is not nil
if not VALID_POOL_TYPES[poolType] then
Utils.error(3, "invalid value returned by pool '%s' constructor (table expected, got %s).", name, type(pool))
end
--Check if methods are callables
for _, method in ipairs(REQUIRED_METHODS) do
if not Type.isCallable(pool[method]) then
Utils.error(3, "invalid :%s method on pool '%s' (callable expected, got %s).", method, name, type(pool[method]))
end
end
end
--- Creates a new Filter
-- @string name Name for the Filter.
-- @tparam table definition Table containing the Filter Definition
-- @treturn Filter The new Filter
-- @treturn Pool The associated Pool
function Filter.new (name, def)
local pool
if def.constructor then
pool = def.constructor(def)
Filter.isValidPool(name, pool)
else
pool = List()
end
local filter = Filter.parse(name, def)
local filter = setmetatable({
pool = pool,
__filter = filter,
__name = name,
__isFilter = true,
}, Filter.__mt)
return filter, pool
end
--- Checks if an Entity fulfills the Filter requirements.
-- @tparam Entity e Entity to check
-- @treturn boolean
function Filter:eligible(e)
return Filter.match(e, self.__filter)
end
function Filter:evaluate (e)
local has = self.pool:has(e)
local eligible = self:eligible(e)
if not has and eligible then
self.pool:add(e)
elseif has and not eligible then
self.pool:remove(e)
end
return self
end
-- Adds an Entity to the Pool, if it passes the Filter.
-- @param e Entity to add
-- @param bypass Whether to bypass the Filter or not.
-- @treturn Filter self
-- @treturn boolean Whether the entity was added or not.
function Filter:add (e, bypass)
if not bypass and not self:eligible(e) then
return self, false
end
self.pool:add(e)
return self, true
end
-- Remove an Entity from the Pool associated to this Filter.
-- @param e Entity to remove
-- @treturn Filter self
function Filter:remove (e)
self.pool:remove(e)
return self
end
-- Clear the Pool associated to this Filter.
-- @param e Entity to remove
-- @treturn Filter self
function Filter:clear (e)
self.pool:clear(e)
return self
end
-- Check if the Pool bound to this System contains the passed Entity
-- @param e Entity to check
-- @treturn boolean Whether the Entity exists.
function Filter:has (e)
return self.pool:has(e)
end
--- Gets the name of the Filter
-- @treturn string
function Filter:getName()
return self.__name
end
return setmetatable(Filter, {
__call = function(_, ...)
return Filter.new(...)
end,
})

42
concord/init.lua Normal file
View file

@ -0,0 +1,42 @@
---
-- @module Concord
local PATH = (...):gsub('%.init$', '')
local Concord = {
_VERSION = "3.0",
_DESCRIPTION = "A feature-complete ECS library",
_LICENCE = [[
MIT LICENSE
Copyright (c) 2020 Justin van der Leij / Tjakka5
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
]]
}
Concord.entity = require(PATH..".entity")
Concord.component = require(PATH..".component")
Concord.components = require(PATH..".components")
Concord.system = require(PATH..".system")
Concord.world = require(PATH..".world")
Concord.utils = require(PATH..".utils")
return Concord

127
concord/list.lua Normal file
View file

@ -0,0 +1,127 @@
--- Data structure that allows for fast removal at the cost of containing order.
-- @classmod List
local List = {}
List.__mt = {
__index = List
}
--- Creates a new List.
-- @treturn List A new List
function List.new()
return setmetatable({
size = 0,
}, List.__mt)
end
--- Adds an object to the List.
-- Object must be of reference type
-- Object may not be the string 'size', 'onAdded' or 'onRemoved'
-- @param obj Object to add
-- @treturn List self
function List:add(obj)
local size = self.size + 1
self[size] = obj
self[obj] = size
self.size = size
if self.onAdded then self:onAdded(obj) end
return self
end
--- Removes an object from the List.
-- @param obj Object to remove
-- @treturn List self
function List:remove(obj)
local index = self[obj]
if not index then return end
local size = self.size
if index == size then
self[size] = nil
else
local other = self[size]
self[index] = other
self[other] = index
self[size] = nil
end
self[obj] = nil
self.size = size - 1
if self.onRemoved then self:onRemoved(obj) end
return self
end
--- Clears the List completely.
-- @treturn List self
function List:clear()
for i = 1, self.size do
local o = self[i]
self[o] = nil
self[i] = nil
end
self.size = 0
return self
end
--- Returns true if the List has the object.
-- @param obj Object to check for
-- @treturn boolean
function List:has(obj)
return self[obj] and true or false
end
--- Returns the object at an index.
-- @number i Index to get from
-- @return Object at the index
function List:get(i)
return self[i]
end
--- Returns the index of an object in the List.
-- @param obj Object to get index of
-- @treturn number index of object in the List.
function List:indexOf(obj)
if (not self[obj]) then
error("bad argument #1 to 'List:indexOf' (Object was not in List)", 2)
end
return self[obj]
end
--- Sorts the List in place, using the order function.
-- The order function is passed to table.sort internally so documentation on table.sort can be used as reference.
-- @param order Function that takes two Entities (a and b) and returns true if a should go before than b.
-- @treturn List self
function List:sort(order)
table.sort(self, order)
for key, obj in ipairs(self) do
self[obj] = key
end
return self
end
--- Callback for when an item is added to the List.
-- @param obj Object that was added
function List:onAdded (obj) --luacheck: ignore
end
--- Callback for when an item is removed to the List.
-- @param obj Object that was removed
function List:onRemoved (obj) --luacheck: ignore
end
return setmetatable(List, {
__call = function()
return List.new()
end,
})

159
concord/system.lua Normal file
View file

@ -0,0 +1,159 @@
--- Iterates over Entities. From these Entities its get Components and modify them.
-- A System contains 1 or more Pools.
-- A System is contained by 1 World.
-- @classmod System
local PATH = (...):gsub('%.[^%.]+$', '')
local Filter = require(PATH..".filter")
local Utils = require(PATH..".utils")
local System = {
ENABLE_OPTIMIZATION = true,
}
System.mt = {
__index = System,
__call = function(systemClass, world)
local system = setmetatable({
__enabled = true,
__filters = {},
__world = world,
__isSystem = true,
__isSystemClass = false, -- Overwrite value from systemClass
}, systemClass)
-- Optimization: We deep copy the System class into our instance of a system.
-- This grants slightly faster access times at the cost of memory.
-- Since there (generally) won't be many instances of worlds this is a worthwhile tradeoff
if (System.ENABLE_OPTIMIZATION) then
Utils.shallowCopy(systemClass, system)
end
for name, def in pairs(systemClass.__definition) do
local filter, pool = Filter(name, Utils.shallowCopy(def, {}))
system[name] = pool
table.insert(system.__filters, filter)
end
system:init(world)
return system
end,
}
--- Creates a new SystemClass.
-- @param table filters A table containing filters (name = {components...})
-- @treturn System A new SystemClass
function System.new(definition)
definition = definition or {}
for name, def in pairs(definition) do
if type(name) ~= 'string' then
Utils.error(2, "invalid name for filter (string key expected, got %s)", type(name))
end
Filter.validate(0, name, def)
end
local systemClass = setmetatable({
__definition = definition,
__isSystemClass = true,
}, System.mt)
systemClass.__index = systemClass
-- Optimization: We deep copy the World class into our instance of a world.
-- This grants slightly faster access times at the cost of memory.
-- Since there (generally) won't be many instances of worlds this is a worthwhile tradeoff
if (System.ENABLE_OPTIMIZATION) then
Utils.shallowCopy(System, systemClass)
end
return systemClass
end
-- Internal: Evaluates an Entity for all the System's Pools.
-- @param e The Entity to check
-- @treturn System self
function System:__evaluate(e)
for _, filter in ipairs(self.__filters) do
filter:evaluate(e)
end
return self
end
-- Internal: Removes an Entity from the System.
-- @param e The Entity to remove
-- @treturn System self
function System:__remove(e)
for _, filter in ipairs(self.__filters) do
if filter:has(e) then
filter:remove(e)
end
end
return self
end
-- Internal: Clears all Entities from the System.
-- @treturn System self
function System:__clear()
for _, filter in ipairs(self.__filters) do
filter:clear()
end
return self
end
--- Sets if the System is enabled
-- @tparam boolean enable
-- @treturn System self
function System:setEnabled(enable)
if (not self.__enabled and enable) then
self.__enabled = true
self:onEnabled()
elseif (self.__enabled and not enable) then
self.__enabled = false
self:onDisabled()
end
return self
end
--- Returns is the System is enabled
-- @treturn boolean
function System:isEnabled()
return self.__enabled
end
--- Returns the World the System is in.
-- @treturn World
function System:getWorld()
return self.__world
end
--- Callbacks
-- @section Callbacks
--- Callback for system initialization.
-- @tparam World world The World the System was added to
function System:init(world) -- luacheck: ignore
end
--- Callback for when a System is enabled.
function System:onEnabled() -- luacheck: ignore
end
--- Callback for when a System is disabled.
function System:onDisabled() -- luacheck: ignore
end
return setmetatable(System, {
__call = function(_, ...)
return System.new(...)
end,
})

64
concord/type.lua Normal file
View file

@ -0,0 +1,64 @@
--- Type
-- Helper module to do easy type checking for Concord types
local Type = {}
function Type.isCallable(t)
if type(t) == "function" then return true end
local meta = getmetatable(t)
if meta and type(meta.__call) == "function" then return true end
return false
end
--- Returns if object is an Entity.
-- @param t Object to check
-- @treturn boolean
function Type.isEntity(t)
return type(t) == "table" and t.__isEntity or false
end
--- Returns if object is a ComponentClass.
-- @param t Object to check
-- @treturn boolean
function Type.isComponentClass(t)
return type(t) == "table" and t.__isComponentClass or false
end
--- Returns if object is a Component.
-- @param t Object to check
-- @treturn boolean
function Type.isComponent(t)
return type(t) == "table" and t.__isComponent or false
end
--- Returns if object is a SystemClass.
-- @param t Object to check
-- @treturn boolean
function Type.isSystemClass(t)
return type(t) == "table" and t.__isSystemClass or false
end
--- Returns if object is a System.
-- @param t Object to check
-- @treturn boolean
function Type.isSystem(t)
return type(t) == "table" and t.__isSystem or false
end
--- Returns if object is a World.
-- @param t Object to check
-- @treturn boolean
function Type.isWorld(t)
return type(t) == "table" and t.__isWorld or false
end
--- Returns if object is a Filter.
-- @param t Object to check
-- @treturn boolean
function Type.isFilter(t)
return type(t) == "table" and t.__isFilter or false
end
return Type

72
concord/utils.lua Normal file
View file

@ -0,0 +1,72 @@
--- Utils
-- Helper module for misc operations
local Utils = {}
function Utils.error(level, str, ...)
error(string.format(str, ...), level + 1)
end
--- Does a shallow copy of a table and appends it to a target table.
-- @param orig Table to copy
-- @param target Table to append to
function Utils.shallowCopy(orig, target)
for key, value in pairs(orig) do
target[key] = value
end
return target
end
--- Requires files and puts them in a table.
-- Accepts a table of paths to Lua files: {"path/to/file_1", "path/to/another/file_2", "etc"}
-- Accepts a path to a directory with Lua files: "my_files/here"
-- @param pathOrFiles The table of paths or a path to a directory.
-- @param namespace A table that will hold the required files
-- @treturn table The namespace table
function Utils.loadNamespace(pathOrFiles, namespace)
if type(pathOrFiles) ~= "string" and type(pathOrFiles) ~= "table" then
Utils.error(2, "bad argument #1 to 'loadNamespace' (string/table of strings expected, got %s)", type(pathOrFiles))
end
if type(pathOrFiles) == "string" then
local info = love.filesystem.getInfo(pathOrFiles) -- luacheck: ignore
if info == nil or info.type ~= "directory" then
Utils.error(2, "bad argument #1 to 'loadNamespace' (path '%s' not found)", pathOrFiles)
end
local files = love.filesystem.getDirectoryItems(pathOrFiles)
for _, file in ipairs(files) do
local isFile = love.filesystem.getInfo(pathOrFiles .. "/" .. file).type == "file"
if isFile and string.match(file, '%.lua$') ~= nil then
local name = file:sub(1, #file - 4)
local path = pathOrFiles.."."..name
local value = require(path:gsub("%/", "."))
if namespace then namespace[name] = value end
end
end
elseif type(pathOrFiles) == "table" then
for _, path in ipairs(pathOrFiles) do
if type(path) ~= "string" then
Utils.error(2, "bad argument #2 to 'loadNamespace' (string/table of strings expected, got table containing %s)", type(path)) -- luacheck: ignore
end
local name = path
local dotIndex, slashIndex = path:match("^.*()%."), path:match("^.*()%/")
if dotIndex or slashIndex then
name = path:sub((dotIndex or slashIndex) + 1)
end
local value = require(path:gsub("%/", "."))
if namespace then namespace[name] = value end
end
end
return namespace
end
return Utils

515
concord/world.lua Normal file
View file

@ -0,0 +1,515 @@
--- A collection of Systems and Entities.
-- A world emits to let Systems iterate.
-- A World contains any amount of Systems.
-- A World contains any amount of Entities.
-- @classmod World
local PATH = (...):gsub('%.[^%.]+$', '')
local Filter = require(PATH..".filter")
local Entity = require(PATH..".entity")
local Components = require(PATH..".components")
local Type = require(PATH..".type")
local List = require(PATH..".list")
local Utils = require(PATH..".utils")
local World = {
ENABLE_OPTIMIZATION = true,
}
World.__mt = {
__index = World,
}
local defaultGenerator = function (state)
local current = state
state = state +1
return string.format("%d", current), state
end
--- Creates a new World.
-- @treturn World The new World
function World.new()
local world = setmetatable({
__entities = List(),
__systems = List(),
__events = {},
__emitSDepth = 0,
__resources = {},
__hash = {
state = -2^53,
generator = defaultGenerator,
keys = {},
entities = {}
},
__added = List(), __backAdded = List(),
__removed = List(), __backRemoved = List(),
__dirty = List(), __backDirty = List(),
__systemLookup = {},
__isWorld = true,
__ignoreEmits = false
}, World.__mt)
-- Optimization: We deep copy the World class into our instance of a world.
-- This grants slightly faster access times at the cost of memory.
-- Since there (generally) won't be many instances of worlds this is a worthwhile tradeoff
if (World.ENABLE_OPTIMIZATION) then
Utils.shallowCopy(World, world)
end
return world
end
--- Adds an Entity to the World.
-- @tparam Entity e Entity to add
-- @treturn World self
function World:addEntity(e)
if not Type.isEntity(e) then
Utils.error(2, "bad argument #1 to 'World:addEntity' (Entity expected, got %s)", type(e))
end
if e.__world then
error("bad argument #1 to 'World:addEntity' (Entity was already added to a world)", 2)
end
e.__world = self
self.__added:add(e)
return self
end
--- Creates a new Entity and adds it to the World.
-- @treturn Entity e the new Entity
function World:newEntity()
return Entity(self)
end
function World:query(def, onMatch)
local filter = Filter.parse(nil, def)
local list = nil
if not Type.isCallable(onMatch) then
list = type(onMatch) == "table" and onMatch or {}
end
for _, e in ipairs(self.__entities) do
if Filter.match(e, filter) then
if list then
table.insert(list, e)
else
onMatch(e)
end
end
end
return list
end
--- Removes an Entity from the World.
-- @tparam Entity e Entity to remove
-- @treturn World self
function World:removeEntity(e)
if not Type.isEntity(e) then
Utils.error(2, "bad argument #1 to 'World:removeEntity' (Entity expected, got %s)", type(e))
end
if e.__world ~= self then
error("trying to remove an Entity from a World it doesn't belong to", 2)
end
if e:has("key") then
e:remove("key")
end
self.__removed:add(e)
return self
end
-- Internal: Marks an Entity as dirty.
-- @param e Entity to mark as dirty
function World:__dirtyEntity(e)
if not self.__dirty:has(e) then
self.__dirty:add(e)
end
end
-- Internal: Flushes all changes to Entities.
-- This processes all entities. Adding and removing entities, as well as reevaluating dirty entities.
-- @treturn World self
function World:__flush()
-- Early out
if (self.__added.size == 0 and self.__removed.size == 0 and self.__dirty.size == 0) then
return self
end
-- Switch buffers
self.__added, self.__backAdded = self.__backAdded, self.__added
self.__removed, self.__backRemoved = self.__backRemoved, self.__removed
self.__dirty, self.__backDirty = self.__backDirty, self.__dirty
local e
-- Process added entities
for i = 1, self.__backAdded.size do
e = self.__backAdded[i]
if e.__world == self then
self.__entities:add(e)
for j = 1, self.__systems.size do
self.__systems[j]:__evaluate(e)
end
self:onEntityAdded(e)
end
end
self.__backAdded:clear()
-- Process removed entities
for i = 1, self.__backRemoved.size do
e = self.__backRemoved[i]
if e.__world == self then
e.__world = nil
self.__entities:remove(e)
for j = 1, self.__systems.size do
self.__systems[j]:__remove(e)
end
self:onEntityRemoved(e)
end
end
self.__backRemoved:clear()
-- Process dirty entities
for i = 1, self.__backDirty.size do
e = self.__backDirty[i]
if e.__world == self then
for j = 1, self.__systems.size do
self.__systems[j]:__evaluate(e)
end
end
end
self.__backDirty:clear()
return self
end
-- These functions won't be seen as callbacks that will be emitted to.
local blacklistedSystemFunctions = {
"init",
"onEnabled",
"onDisabled",
}
local tryAddSystem = function (world, systemClass)
if (not Type.isSystemClass(systemClass)) then
return false, "SystemClass expected, got "..type(systemClass)
end
if (world.__systemLookup[systemClass]) then
return false, "SystemClass was already added to World"
end
-- Create instance of system
local system = systemClass(world)
world.__systemLookup[systemClass] = system
world.__systems:add(system)
for callbackName, callback in pairs(systemClass) do
-- Skip callback if its blacklisted
if (not blacklistedSystemFunctions[callbackName]) then
-- Make container for all listeners of the callback if it does not exist yet
if (not world.__events[callbackName]) then
world.__events[callbackName] = {}
end
-- Add callback to listeners
local listeners = world.__events[callbackName]
listeners[#listeners + 1] = {
system = system,
callback = callback,
}
end
end
-- Evaluate all existing entities
for j = 1, world.__entities.size do
system:__evaluate(world.__entities[j])
end
return true
end
--- Adds a System to the World.
-- Callbacks are registered automatically
-- Entities added before are added to the System retroactively
-- @see World:emit
-- @tparam System systemClass SystemClass of System to add
-- @treturn World self
function World:addSystem(systemClass)
local ok, err = tryAddSystem(self, systemClass)
if not ok then
Utils.error(2, "bad argument #1 to 'World:addSystem' (%s)", err)
end
return self
end
--- Adds multiple Systems to the World.
-- Callbacks are registered automatically
-- @see World:addSystem
-- @see World:emit
-- @param ... SystemClasses of Systems to add
-- @treturn World self
function World:addSystems(...)
for i = 1, select("#", ...) do
local systemClass = select(i, ...)
local ok, err = tryAddSystem(self, systemClass)
if not ok then
Utils.error(2, "bad argument #%d to 'World:addSystems' (%s)", i, err)
end
end
return self
end
--- Returns if the World has a System.
-- @tparam System systemClass SystemClass of System to check for
-- @treturn boolean
function World:hasSystem(systemClass)
if not Type.isSystemClass(systemClass) then
Utils.error(2, "bad argument #1 to 'World:hasSystem' (SystemClass expected, got %s)", type(systemClass))
end
return self.__systemLookup[systemClass] and true or false
end
--- Gets a System from the World.
-- @tparam System systemClass SystemClass of System to get
-- @treturn System System to get
function World:getSystem(systemClass)
if not Type.isSystemClass(systemClass) then
Utils.error(2, "bad argument #1 to 'World:getSystem' (SystemClass expected, got %s)", type(systemClass))
end
return self.__systemLookup[systemClass]
end
--- Emits a callback in the World.
-- Calls all functions with the functionName of added Systems
-- @string functionName Name of functions to call.
-- @param ... Parameters passed to System's functions
-- @treturn World self
function World:emit(functionName, ...)
if not functionName or type(functionName) ~= "string" then
Utils.error(2, "bad argument #1 to 'World:emit' (String expected, got %s)", type(functionName))
end
local shouldFlush = self.__emitSDepth == 0
self.__emitSDepth = self.__emitSDepth + 1
local listeners = self.__events[functionName]
if not self.__ignoreEmits and Type.isCallable(self.beforeEmit) then
self.__ignoreEmits = true
local preventDefaults = self:beforeEmit(functionName, listeners, ...)
self.__ignoreEmits = false
if preventDefaults then return end
end
if listeners then
for i = 1, #listeners do
local listener = listeners[i]
if (listener.system.__enabled) then
if (shouldFlush) then
self:__flush()
end
listener.callback(listener.system, ...)
end
end
end
if not self.__ignoreEmits and Type.isCallable(self.afterEmit) then
self.__ignoreEmits = true
self:afterEmit(functionName, listeners, ...)
self.__ignoreEmits = false
end
self.__emitSDepth = self.__emitSDepth - 1
return self
end
--- Removes all entities from the World
-- @treturn World self
function World:clear()
for i = 1, self.__entities.size do
self:removeEntity(self.__entities[i])
end
for i = 1, self.__added.size do
local e = self.__added[i]
e.__world = nil
end
self.__added:clear()
self:__flush()
return self
end
function World:getEntities()
return self.__entities
end
function World:getSystems()
return self.__systems
end
function World:serialize(ignoreKeys)
self:__flush()
local data = { generator = self.__hash.state }
for i = 1, self.__entities.size do
local entity = self.__entities[i]
if entity.serializable then
local entityData = entity:serialize(ignoreKeys)
table.insert(data, entityData)
end
end
return data
end
function World:deserialize(data, startClean, ignoreGenerator)
if startClean then
self:clear()
end
if (not ignoreGenerator) then
self.__hash.state = data.generator
end
local entities = {}
for i = 1, #data do
local entity = Entity(self)
if data[i].key then
local component = Components.key:__new(entity)
component:deserialize(data[i].key)
entity.key = component
entity:__dirty()
end
entities[i] = entity
end
for i = 1, #data do
entities[i]:deserialize(data[i])
end
self:__flush()
return self
end
function World:setKeyGenerator(generator, initialState)
if not Type.isCallable(generator) then
Utils.error(2, "bad argument #1 to 'World:setKeyGenerator' (function expected, got %s)", type(generator))
end
self.__hash.generator = generator
self.__hash.state = initialState
return self
end
function World:__clearKey(e)
local key = self.__hash.keys[e]
if key then
self.__hash.keys[e] = nil
self.__hash.entities[key] = nil
end
return self
end
function World:__assignKey(e, key)
local hash = self.__hash
if not key then
key = hash.keys[e]
if key then return key end
key, hash.state = hash.generator(hash.state)
end
if hash.entities[key] and hash.entities[key] ~= e then
Utils.error(4, "Trying to assign a key that is already taken (key: '%s').", key)
elseif hash.keys[e] and hash.keys[e] ~= key then
Utils.error(4, "Trying to assign more than one key to an Entity. (old: '%s', new: '%s')", hash.keys[e], key)
end
hash.keys[e] = key
hash.entities[key] = e
return key
end
function World:getEntityByKey(key)
return self.__hash.entities[key]
end
--- Callback for when an Entity is added to the World.
-- @tparam Entity e The Entity that was added
function World:onEntityAdded(e) -- luacheck: ignore
end
--- Callback for when an Entity is removed from the World.
-- @tparam Entity e The Entity that was removed
function World:onEntityRemoved(e) -- luacheck: ignore
end
--- Sets a named resource in the world
-- @string name Name of the resource
-- @tparam Any resource Resource to set
-- @treturn World self
function World:setResource(name, resource)
self.__resources[name] = resource
return self
end
--- Gets a named resource from the world
-- @string name Name of the resource
-- @treturn Any resource
function World:getResource(name)
return self.__resources[name]
end
return setmetatable(World, {
__call = function(_, ...)
---@diagnostic disable-next-line: redundant-parameter
return World.new(...)
end,
})

View file

@ -1,10 +0,0 @@
function love.conf(t)
t.identity = "Concord Example"
t.version = "11.0"
t.console = true
t.window.vsync = false
t.window.width = 720
t.window.height = 720
end

View file

@ -1,3 +1,4 @@
project = 'Concord'
description = 'A feature-complete ECS library'
file = {'lib', exclude = {'lib/type.lua', 'lib/run.lua'}}
file = {'concord', exclude = {}}
dir = 'docs'

View file

@ -0,0 +1,204 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<head>
<title>Reference</title>
<link rel="stylesheet" href="../ldoc.css" type="text/css" />
</head>
<body>
<div id="container">
<div id="product">
<div id="product_logo"></div>
<div id="product_name"><big><b></b></big></div>
<div id="product_description"></div>
</div> <!-- id="product" -->
<div id="main">
<!-- Menu -->
<div id="navigation">
<br/>
<h1>Concord</h1>
<ul>
<li><a href="../index.html">Index</a></li>
</ul>
<h2>Contents</h2>
<ul>
<li><a href="#Methods">Methods</a></li>
</ul>
<h2>Classes</h2>
<ul class="nowrap">
<li><strong>Assemblage</strong></li>
<li><a href="../classes/Component.html">Component</a></li>
<li><a href="../classes/Entity.html">Entity</a></li>
<li><a href="../classes/List.html">List</a></li>
<li><a href="../classes/Pool.html">Pool</a></li>
<li><a href="../classes/System.html">System</a></li>
<li><a href="../classes/World.html">World</a></li>
</ul>
<h2>Modules</h2>
<ul class="nowrap">
<li><a href="../modules/Assemblages.html">Assemblages</a></li>
<li><a href="../modules/Components.html">Components</a></li>
<li><a href="../modules/Concord.html">Concord</a></li>
<li><a href="../modules/Systems.html">Systems</a></li>
<li><a href="../modules/type.html">type</a></li>
<li><a href="../modules/utils.html">utils</a></li>
<li><a href="../modules/worlds.html">worlds</a></li>
</ul>
</div>
<div id="content">
<h1>Class <code>Assemblage</code></h1>
<p>Gives an entity a set of components.</p>
<p></p>
<h2><a href="#Methods">Methods</a></h2>
<table class="function_list">
<tr>
<td class="name" nowrap><a href="#Assemblage:new">Assemblage:new (assemble)</a></td>
<td class="summary">Creates a new Assemblage.</td>
</tr>
<tr>
<td class="name" nowrap><a href="#Assemblage:assemble">Assemblage:assemble (e, ...)</a></td>
<td class="summary">Assembles an Entity.</td>
</tr>
<tr>
<td class="name" nowrap><a href="#Assemblage:hasName">Assemblage:hasName ()</a></td>
<td class="summary">Returns true if the Assemblage has a name.</td>
</tr>
<tr>
<td class="name" nowrap><a href="#Assemblage:getName">Assemblage:getName ()</a></td>
<td class="summary">Returns the name of the Assemblage.</td>
</tr>
</table>
<br/>
<br/>
<h2 class="section-header "><a name="Methods"></a>Methods</h2>
<dl class="function">
<dt>
<a name = "Assemblage:new"></a>
<strong>Assemblage:new (assemble)</strong>
</dt>
<dd>
Creates a new Assemblage.
<h3>Parameters:</h3>
<ul>
<li><span class="parameter">assemble</span>
<span class="types"><span class="type">function</span></span>
Function that assembles an Entity
</li>
</ul>
<h3>Returns:</h3>
<ol>
<span class="types"><a class="type" href="../classes/Assemblage.html#">Assemblage</a></span>
A new assemblage
</ol>
</dd>
<dt>
<a name = "Assemblage:assemble"></a>
<strong>Assemblage:assemble (e, ...)</strong>
</dt>
<dd>
Assembles an Entity.
<h3>Parameters:</h3>
<ul>
<li><span class="parameter">e</span>
<span class="types"><a class="type" href="../classes/Entity.html#">Entity</a></span>
Entity to assemble
</li>
<li><span class="parameter">...</span>
additional arguments to pass to the assemble function
</li>
</ul>
<h3>Returns:</h3>
<ol>
<span class="types"><a class="type" href="../classes/Assemblage.html#">Assemblage</a></span>
self
</ol>
</dd>
<dt>
<a name = "Assemblage:hasName"></a>
<strong>Assemblage:hasName ()</strong>
</dt>
<dd>
Returns true if the Assemblage has a name.
<h3>Returns:</h3>
<ol>
<span class="types"><span class="type">boolean</span></span>
</ol>
</dd>
<dt>
<a name = "Assemblage:getName"></a>
<strong>Assemblage:getName ()</strong>
</dt>
<dd>
Returns the name of the Assemblage.
<h3>Returns:</h3>
<ol>
<span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.4">string</a></span>
</ol>
</dd>
</dl>
</div> <!-- id="content" -->
</div> <!-- id="main" -->
<div id="about">
<i>generated by <a href="http://github.com/stevedonovan/LDoc">LDoc 1.4.6</a></i>
<i style="float:right;">Last updated 2020-01-04 10:27:07 </i>
</div> <!-- id="about" -->
</div> <!-- id="container" -->
</body>
</html>

166
docs/classes/Component.html Normal file
View file

@ -0,0 +1,166 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<head>
<title>Reference</title>
<link rel="stylesheet" href="../ldoc.css" type="text/css" />
</head>
<body>
<div id="container">
<div id="product">
<div id="product_logo"></div>
<div id="product_name"><big><b></b></big></div>
<div id="product_description"></div>
</div> <!-- id="product" -->
<div id="main">
<!-- Menu -->
<div id="navigation">
<br/>
<h1>Concord</h1>
<ul>
<li><a href="../index.html">Index</a></li>
</ul>
<h2>Contents</h2>
<ul>
<li><a href="#Methods">Methods</a></li>
</ul>
<h2>Classes</h2>
<ul class="nowrap">
<li><strong>Component</strong></li>
<li><a href="../classes/Entity.html">Entity</a></li>
<li><a href="../classes/List.html">List</a></li>
<li><a href="../classes/Pool.html">Pool</a></li>
<li><a href="../classes/System.html">System</a></li>
<li><a href="../classes/World.html">World</a></li>
</ul>
<h2>Modules</h2>
<ul class="nowrap">
<li><a href="../modules/Components.html">Components</a></li>
<li><a href="../modules/Concord.html">Concord</a></li>
<li><a href="../modules/type.html">type</a></li>
<li><a href="../modules/utils.html">utils</a></li>
</ul>
</div>
<div id="content">
<h1>Class <code>Component</code></h1>
<p>A pure data container that is contained by a single entity.</p>
<p></p>
<h2><a href="#Methods">Methods</a></h2>
<table class="function_list">
<tr>
<td class="name" nowrap><a href="#Component:new">Component:new (populate)</a></td>
<td class="summary">Creates a new ComponentClass.</td>
</tr>
<tr>
<td class="name" nowrap><a href="#Component:hasName">Component:hasName ()</a></td>
<td class="summary">Returns true if the Component has a name.</td>
</tr>
<tr>
<td class="name" nowrap><a href="#Component:getName">Component:getName ()</a></td>
<td class="summary">Returns the name of the Component.</td>
</tr>
</table>
<br/>
<br/>
<h2 class="section-header "><a name="Methods"></a>Methods</h2>
<dl class="function">
<dt>
<a name = "Component:new"></a>
<strong>Component:new (populate)</strong>
</dt>
<dd>
Creates a new ComponentClass.
<h3>Parameters:</h3>
<ul>
<li><span class="parameter">populate</span>
<span class="types"><span class="type">function</span></span>
Function that populates a Component with values
</li>
</ul>
<h3>Returns:</h3>
<ol>
<span class="types"><a class="type" href="../classes/Component.html#">Component</a></span>
A new ComponentClass
</ol>
</dd>
<dt>
<a name = "Component:hasName"></a>
<strong>Component:hasName ()</strong>
</dt>
<dd>
Returns true if the Component has a name.
<h3>Returns:</h3>
<ol>
<span class="types"><span class="type">boolean</span></span>
</ol>
</dd>
<dt>
<a name = "Component:getName"></a>
<strong>Component:getName ()</strong>
</dt>
<dd>
Returns the name of the Component.
<h3>Returns:</h3>
<ol>
<span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.4">string</a></span>
</ol>
</dd>
</dl>
</div> <!-- id="content" -->
</div> <!-- id="main" -->
<div id="about">
<i>generated by <a href="http://github.com/stevedonovan/LDoc">LDoc 1.4.6</a></i>
<i style="float:right;">Last updated 2020-08-18 15:20:32 </i>
</div> <!-- id="about" -->
</div> <!-- id="container" -->
</body>
</html>

415
docs/classes/Entity.html Normal file
View file

@ -0,0 +1,415 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<head>
<title>Reference</title>
<link rel="stylesheet" href="../ldoc.css" type="text/css" />
</head>
<body>
<div id="container">
<div id="product">
<div id="product_logo"></div>
<div id="product_name"><big><b></b></big></div>
<div id="product_description"></div>
</div> <!-- id="product" -->
<div id="main">
<!-- Menu -->
<div id="navigation">
<br/>
<h1>Concord</h1>
<ul>
<li><a href="../index.html">Index</a></li>
</ul>
<h2>Contents</h2>
<ul>
<li><a href="#Methods">Methods</a></li>
</ul>
<h2>Classes</h2>
<ul class="nowrap">
<li><a href="../classes/Component.html">Component</a></li>
<li><strong>Entity</strong></li>
<li><a href="../classes/List.html">List</a></li>
<li><a href="../classes/Pool.html">Pool</a></li>
<li><a href="../classes/System.html">System</a></li>
<li><a href="../classes/World.html">World</a></li>
</ul>
<h2>Modules</h2>
<ul class="nowrap">
<li><a href="../modules/Components.html">Components</a></li>
<li><a href="../modules/Concord.html">Concord</a></li>
<li><a href="../modules/type.html">type</a></li>
<li><a href="../modules/utils.html">utils</a></li>
</ul>
</div>
<div id="content">
<h1>Class <code>Entity</code></h1>
<p>An object that exists in a world.</p>
<p> An entity
contains components which are processed by systems.</p>
<h2><a href="#Methods">Methods</a></h2>
<table class="function_list">
<tr>
<td class="name" nowrap><a href="#Entity:new">Entity:new ([world])</a></td>
<td class="summary">Creates a new Entity.</td>
</tr>
<tr>
<td class="name" nowrap><a href="#Entity:give">Entity:give (componentClass, ...)</a></td>
<td class="summary">Gives an Entity a Component.</td>
</tr>
<tr>
<td class="name" nowrap><a href="#Entity:ensure">Entity:ensure (componentClass, ...)</a></td>
<td class="summary">Ensures an Entity to have a Component.</td>
</tr>
<tr>
<td class="name" nowrap><a href="#Entity:remove">Entity:remove (componentClass)</a></td>
<td class="summary">Removes a Component from an Entity.</td>
</tr>
<tr>
<td class="name" nowrap><a href="#Entity:assemble">Entity:assemble (assemblage, ...)</a></td>
<td class="summary">Assembles an Entity.</td>
</tr>
<tr>
<td class="name" nowrap><a href="#Entity:destroy">Entity:destroy ()</a></td>
<td class="summary">Destroys the Entity.</td>
</tr>
<tr>
<td class="name" nowrap><a href="#Entity:has">Entity:has (componentClass)</a></td>
<td class="summary">Returns true if the Entity has a Component.</td>
</tr>
<tr>
<td class="name" nowrap><a href="#Entity:get">Entity:get (componentClass)</a></td>
<td class="summary">Gets a Component from the Entity.</td>
</tr>
<tr>
<td class="name" nowrap><a href="#Entity:getComponents">Entity:getComponents ()</a></td>
<td class="summary">Returns a table of all Components the Entity has.</td>
</tr>
<tr>
<td class="name" nowrap><a href="#Entity:inWorld">Entity:inWorld ()</a></td>
<td class="summary">Returns true if the Entity is in a World.</td>
</tr>
<tr>
<td class="name" nowrap><a href="#Entity:getWorld">Entity:getWorld ()</a></td>
<td class="summary">Returns the World the Entity is in.</td>
</tr>
</table>
<br/>
<br/>
<h2 class="section-header "><a name="Methods"></a>Methods</h2>
<dl class="function">
<dt>
<a name = "Entity:new"></a>
<strong>Entity:new ([world])</strong>
</dt>
<dd>
Creates a new Entity. Optionally adds it to a World.
<h3>Parameters:</h3>
<ul>
<li><span class="parameter">world</span>
<span class="types"><a class="type" href="../classes/World.html#">World</a></span>
World to add the entity to
(<em>optional</em>)
</li>
</ul>
<h3>Returns:</h3>
<ol>
<span class="types"><a class="type" href="../classes/Entity.html#">Entity</a></span>
A new Entity
</ol>
</dd>
<dt>
<a name = "Entity:give"></a>
<strong>Entity:give (componentClass, ...)</strong>
</dt>
<dd>
Gives an Entity a Component.
If the Component already exists, it's overridden by this new Component
<h3>Parameters:</h3>
<ul>
<li><span class="parameter">componentClass</span>
<span class="types"><a class="type" href="../classes/Component.html#">Component</a></span>
ComponentClass to add an instance of
</li>
<li><span class="parameter">...</span>
additional arguments to pass to the Component's populate function
</li>
</ul>
<h3>Returns:</h3>
<ol>
<span class="types"><a class="type" href="../classes/Entity.html#">Entity</a></span>
self
</ol>
</dd>
<dt>
<a name = "Entity:ensure"></a>
<strong>Entity:ensure (componentClass, ...)</strong>
</dt>
<dd>
Ensures an Entity to have a Component.
If the Component already exists, no action is taken
<h3>Parameters:</h3>
<ul>
<li><span class="parameter">componentClass</span>
<span class="types"><a class="type" href="../classes/Component.html#">Component</a></span>
ComponentClass to add an instance of
</li>
<li><span class="parameter">...</span>
additional arguments to pass to the Component's populate function
</li>
</ul>
<h3>Returns:</h3>
<ol>
<span class="types"><a class="type" href="../classes/Entity.html#">Entity</a></span>
self
</ol>
</dd>
<dt>
<a name = "Entity:remove"></a>
<strong>Entity:remove (componentClass)</strong>
</dt>
<dd>
Removes a Component from an Entity.
<h3>Parameters:</h3>
<ul>
<li><span class="parameter">componentClass</span>
<span class="types"><a class="type" href="../classes/Component.html#">Component</a></span>
ComponentClass of the Component to remove
</li>
</ul>
<h3>Returns:</h3>
<ol>
<span class="types"><a class="type" href="../classes/Entity.html#">Entity</a></span>
self
</ol>
</dd>
<dt>
<a name = "Entity:assemble"></a>
<strong>Entity:assemble (assemblage, ...)</strong>
</dt>
<dd>
Assembles an Entity.
<h3>Parameters:</h3>
<ul>
<li><span class="parameter">assemblage</span>
<span class="types"><span class="type">function</span></span>
Function that will assemble an entity
</li>
<li><span class="parameter">...</span>
additional arguments to pass to the assemblage function.
</li>
</ul>
<h3>Returns:</h3>
<ol>
<span class="types"><a class="type" href="../classes/Entity.html#">Entity</a></span>
self
</ol>
</dd>
<dt>
<a name = "Entity:destroy"></a>
<strong>Entity:destroy ()</strong>
</dt>
<dd>
Destroys the Entity.
Removes the Entity from its World if it's in one.
<h3>Returns:</h3>
<ol>
self
</ol>
</dd>
<dt>
<a name = "Entity:has"></a>
<strong>Entity:has (componentClass)</strong>
</dt>
<dd>
Returns true if the Entity has a Component.
<h3>Parameters:</h3>
<ul>
<li><span class="parameter">componentClass</span>
<span class="types"><a class="type" href="../classes/Component.html#">Component</a></span>
ComponentClass of the Component to check
</li>
</ul>
<h3>Returns:</h3>
<ol>
<span class="types"><span class="type">boolean</span></span>
</ol>
</dd>
<dt>
<a name = "Entity:get"></a>
<strong>Entity:get (componentClass)</strong>
</dt>
<dd>
Gets a Component from the Entity.
<h3>Parameters:</h3>
<ul>
<li><span class="parameter">componentClass</span>
<span class="types"><a class="type" href="../classes/Component.html#">Component</a></span>
ComponentClass of the Component to get
</li>
</ul>
<h3>Returns:</h3>
<ol>
<span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.5">table</a></span>
</ol>
</dd>
<dt>
<a name = "Entity:getComponents"></a>
<strong>Entity:getComponents ()</strong>
</dt>
<dd>
Returns a table of all Components the Entity has.
Warning: Do not modify this table.
Use Entity:give/ensure/remove instead
<h3>Returns:</h3>
<ol>
<span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.5">table</a></span>
Table of all Components the Entity has
</ol>
</dd>
<dt>
<a name = "Entity:inWorld"></a>
<strong>Entity:inWorld ()</strong>
</dt>
<dd>
Returns true if the Entity is in a World.
<h3>Returns:</h3>
<ol>
<span class="types"><span class="type">boolean</span></span>
</ol>
</dd>
<dt>
<a name = "Entity:getWorld"></a>
<strong>Entity:getWorld ()</strong>
</dt>
<dd>
Returns the World the Entity is in.
<h3>Returns:</h3>
<ol>
<span class="types"><a class="type" href="../classes/World.html#">World</a></span>
</ol>
</dd>
</dl>
</div> <!-- id="content" -->
</div> <!-- id="main" -->
<div id="about">
<i>generated by <a href="http://github.com/stevedonovan/LDoc">LDoc 1.4.6</a></i>
<i style="float:right;">Last updated 2020-08-18 15:20:32 </i>
</div> <!-- id="about" -->
</div> <!-- id="container" -->
</body>
</html>

View file

@ -32,41 +32,43 @@
<h2>Contents</h2>
<ul>
<li><a href="#Functions">Functions</a></li>
<li><a href="#Methods">Methods</a></li>
</ul>
<h2>Classes</h2>
<ul class="nowrap">
<li><a href="../classes/Component.html">Component</a></li>
<li><a href="../classes/Entity.html">Entity</a></li>
<li><strong>List</strong></li>
<li><a href="../classes/Pool.html">Pool</a></li>
<li><a href="../classes/System.html">System</a></li>
<li><a href="../classes/World.html">World</a></li>
</ul>
<h2>Modules</h2>
<ul class="nowrap">
<li><a href="../modules/component.html">component</a></li>
<li><a href="../modules/entity.html">entity</a></li>
<li><a href="../modules/init.html">init</a></li>
<li><a href="../modules/instance.html">instance</a></li>
<li><strong>list</strong></li>
<li><a href="../modules/pool.html">pool</a></li>
<li><a href="../modules/system.html">system</a></li>
<li><a href="../modules/Components.html">Components</a></li>
<li><a href="../modules/Concord.html">Concord</a></li>
<li><a href="../modules/type.html">type</a></li>
<li><a href="../modules/utils.html">utils</a></li>
</ul>
</div>
<div id="content">
<h1>Module <code>list</code></h1>
<p>List</p>
<h1>Class <code>List</code></h1>
<p>Data structure that allows for fast removal at the cost of containing order.</p>
<p></p>
<h2><a href="#Functions">Functions</a></h2>
<h2><a href="#Methods">Methods</a></h2>
<table class="function_list">
<tr>
<td class="name" nowrap><a href="#List.new">List.new ()</a></td>
<td class="name" nowrap><a href="#List:new">List:new ()</a></td>
<td class="summary">Creates a new List.</td>
</tr>
<tr>
<td class="name" nowrap><a href="#List:clear">List:clear ()</a></td>
<td class="summary">Clears the List completely.</td>
</tr>
<tr>
<td class="name" nowrap><a href="#List:add">List:add (obj)</a></td>
<td class="summary">Adds an object to the List.</td>
</tr>
@ -75,12 +77,20 @@
<td class="summary">Removes an object from the List.</td>
</tr>
<tr>
<td class="name" nowrap><a href="#List:get">List:get (index)</a></td>
<td class="summary">Gets an object by numerical index.</td>
<td class="name" nowrap><a href="#List:clear">List:clear ()</a></td>
<td class="summary">Clears the List completely.</td>
</tr>
<tr>
<td class="name" nowrap><a href="#List:has">List:has (obj)</a></td>
<td class="summary">Gets if the List has the object.</td>
<td class="summary">Returns true if the List has the object.</td>
</tr>
<tr>
<td class="name" nowrap><a href="#List:get">List:get (i)</a></td>
<td class="summary">Returns the object at an index.</td>
</tr>
<tr>
<td class="name" nowrap><a href="#List:indexOf">List:indexOf (obj)</a></td>
<td class="summary">Returns the index of an object in the List.</td>
</tr>
</table>
@ -88,12 +98,12 @@
<br/>
<h2 class="section-header "><a name="Functions"></a>Functions</h2>
<h2 class="section-header "><a name="Methods"></a>Methods</h2>
<dl class="function">
<dt>
<a name = "List.new"></a>
<strong>List.new ()</strong>
<a name = "List:new"></a>
<strong>List:new ()</strong>
</dt>
<dd>
Creates a new List.
@ -103,26 +113,8 @@
<h3>Returns:</h3>
<ol>
A new list
</ol>
</dd>
<dt>
<a name = "List:clear"></a>
<strong>List:clear ()</strong>
</dt>
<dd>
Clears the List completely.
<h3>Returns:</h3>
<ol>
self
<span class="types"><a class="type" href="../classes/List.html#">List</a></span>
A new List
</ol>
@ -135,18 +127,21 @@
</dt>
<dd>
Adds an object to the List.
Object must be of reference type
Object may not be the string 'size'
<h3>Parameters:</h3>
<ul>
<li><span class="parameter">obj</span>
The object to add
Object to add
</li>
</ul>
<h3>Returns:</h3>
<ol>
<span class="types"><a class="type" href="../classes/List.html#">List</a></span>
self
</ol>
@ -165,13 +160,14 @@
<h3>Parameters:</h3>
<ul>
<li><span class="parameter">obj</span>
The object to remove
Object to remove
</li>
</ul>
<h3>Returns:</h3>
<ol>
<span class="types"><a class="type" href="../classes/List.html#">List</a></span>
self
</ol>
@ -180,24 +176,19 @@
</dd>
<dt>
<a name = "List:get"></a>
<strong>List:get (index)</strong>
<a name = "List:clear"></a>
<strong>List:clear ()</strong>
</dt>
<dd>
Gets an object by numerical index.
Clears the List completely.
<h3>Parameters:</h3>
<ul>
<li><span class="parameter">index</span>
The index to look at
</li>
</ul>
<h3>Returns:</h3>
<ol>
The object at the index
<span class="types"><a class="type" href="../classes/List.html#">List</a></span>
self
</ol>
@ -209,17 +200,74 @@
<strong>List:has (obj)</strong>
</dt>
<dd>
Gets if the List has the object.
Returns true if the List has the object.
<h3>Parameters:</h3>
<ul>
<li><span class="parameter">obj</span>
The object to search for
true if the list has the object, false otherwise
Object to check for
</li>
</ul>
<h3>Returns:</h3>
<ol>
<span class="types"><span class="type">boolean</span></span>
</ol>
</dd>
<dt>
<a name = "List:get"></a>
<strong>List:get (i)</strong>
</dt>
<dd>
Returns the object at an index.
<h3>Parameters:</h3>
<ul>
<li><span class="parameter">i</span>
<span class="types"><span class="type">number</span></span>
Index to get from
</li>
</ul>
<h3>Returns:</h3>
<ol>
Object at the index
</ol>
</dd>
<dt>
<a name = "List:indexOf"></a>
<strong>List:indexOf (obj)</strong>
</dt>
<dd>
Returns the index of an object in the List.
<h3>Parameters:</h3>
<ul>
<li><span class="parameter">obj</span>
Object to get index of
</li>
</ul>
<h3>Returns:</h3>
<ol>
<span class="types"><span class="type">number</span></span>
index of object in the List.
</ol>
@ -232,7 +280,7 @@
</div> <!-- id="main" -->
<div id="about">
<i>generated by <a href="http://github.com/stevedonovan/LDoc">LDoc 1.4.6</a></i>
<i style="float:right;">Last updated 2018-09-25 18:42:43 </i>
<i style="float:right;">Last updated 2020-08-18 15:20:32 </i>
</div> <!-- id="about" -->
</div> <!-- id="container" -->
</body>

257
docs/classes/Pool.html Normal file
View file

@ -0,0 +1,257 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<head>
<title>Reference</title>
<link rel="stylesheet" href="../ldoc.css" type="text/css" />
</head>
<body>
<div id="container">
<div id="product">
<div id="product_logo"></div>
<div id="product_name"><big><b></b></big></div>
<div id="product_description"></div>
</div> <!-- id="product" -->
<div id="main">
<!-- Menu -->
<div id="navigation">
<br/>
<h1>Concord</h1>
<ul>
<li><a href="../index.html">Index</a></li>
</ul>
<h2>Contents</h2>
<ul>
<li><a href="#Methods">Methods</a></li>
</ul>
<h2>Classes</h2>
<ul class="nowrap">
<li><a href="../classes/Component.html">Component</a></li>
<li><a href="../classes/Entity.html">Entity</a></li>
<li><a href="../classes/List.html">List</a></li>
<li><strong>Pool</strong></li>
<li><a href="../classes/System.html">System</a></li>
<li><a href="../classes/World.html">World</a></li>
</ul>
<h2>Modules</h2>
<ul class="nowrap">
<li><a href="../modules/Components.html">Components</a></li>
<li><a href="../modules/Concord.html">Concord</a></li>
<li><a href="../modules/type.html">type</a></li>
<li><a href="../modules/utils.html">utils</a></li>
</ul>
</div>
<div id="content">
<h1>Class <code>Pool</code></h1>
<p>Used to iterate over Entities with a specific Components
A Pool contain a any amount of Entities.</p>
<p></p>
<h2><a href="#Methods">Methods</a></h2>
<table class="function_list">
<tr>
<td class="name" nowrap><a href="#Pool:new">Pool:new (name, filter)</a></td>
<td class="summary">Creates a new Pool</td>
</tr>
<tr>
<td class="name" nowrap><a href="#Pool:eligible">Pool:eligible (e)</a></td>
<td class="summary">Checks if an Entity is eligible for the Pool.</td>
</tr>
<tr>
<td class="name" nowrap><a href="#Pool:evaluate">Pool:evaluate (e)</a></td>
<td class="summary">Evaluate whether an Entity should be added or removed from the Pool.</td>
</tr>
<tr>
<td class="name" nowrap><a href="#Pool:getName">Pool:getName ()</a></td>
<td class="summary">Gets the name of the Pool</td>
</tr>
<tr>
<td class="name" nowrap><a href="#Pool:getFilter">Pool:getFilter ()</a></td>
<td class="summary">Gets the filter of the Pool.</td>
</tr>
<tr>
<td class="name" nowrap><a href="#Pool:onEntityAdded">Pool:onEntityAdded (e)</a></td>
<td class="summary">Callback for when an Entity is added to the Pool.</td>
</tr>
</table>
<br/>
<br/>
<h2 class="section-header "><a name="Methods"></a>Methods</h2>
<dl class="function">
<dt>
<a name = "Pool:new"></a>
<strong>Pool:new (name, filter)</strong>
</dt>
<dd>
Creates a new Pool
<h3>Parameters:</h3>
<ul>
<li><span class="parameter">name</span>
<span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.4">string</a></span>
Name for the Pool.
</li>
<li><span class="parameter">filter</span>
<span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.5">table</a></span>
Table containing the required BaseComponents
</li>
</ul>
<h3>Returns:</h3>
<ol>
<span class="types"><a class="type" href="../classes/Pool.html#">Pool</a></span>
The new Pool
</ol>
</dd>
<dt>
<a name = "Pool:eligible"></a>
<strong>Pool:eligible (e)</strong>
</dt>
<dd>
Checks if an Entity is eligible for the Pool.
<h3>Parameters:</h3>
<ul>
<li><span class="parameter">e</span>
<span class="types"><a class="type" href="../classes/Entity.html#">Entity</a></span>
Entity to check
</li>
</ul>
<h3>Returns:</h3>
<ol>
<span class="types"><span class="type">boolean</span></span>
</ol>
</dd>
<dt>
<a name = "Pool:evaluate"></a>
<strong>Pool:evaluate (e)</strong>
</dt>
<dd>
Evaluate whether an Entity should be added or removed from the Pool.
<h3>Parameters:</h3>
<ul>
<li><span class="parameter">e</span>
Entity to add or remove
</li>
</ul>
<h3>Returns:</h3>
<ol>
<span class="types"><a class="type" href="../classes/Pool.html#">Pool</a></span>
self
</ol>
</dd>
<dt>
<a name = "Pool:getName"></a>
<strong>Pool:getName ()</strong>
</dt>
<dd>
Gets the name of the Pool
<h3>Returns:</h3>
<ol>
<span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.4">string</a></span>
</ol>
</dd>
<dt>
<a name = "Pool:getFilter"></a>
<strong>Pool:getFilter ()</strong>
</dt>
<dd>
Gets the filter of the Pool.
Warning: Do not modify this filter.
<h3>Returns:</h3>
<ol>
Filter of the Pool.
</ol>
</dd>
<dt>
<a name = "Pool:onEntityAdded"></a>
<strong>Pool:onEntityAdded (e)</strong>
</dt>
<dd>
Callback for when an Entity is added to the Pool.
<h3>Parameters:</h3>
<ul>
<li><span class="parameter">e</span>
<span class="types"><a class="type" href="../classes/Entity.html#">Entity</a></span>
Entity that was added.
</li>
</ul>
</dd>
</dl>
</div> <!-- id="content" -->
</div> <!-- id="main" -->
<div id="about">
<i>generated by <a href="http://github.com/stevedonovan/LDoc">LDoc 1.4.6</a></i>
<i style="float:right;">Last updated 2020-08-18 15:20:32 </i>
</div> <!-- id="about" -->
</div> <!-- id="container" -->
</body>
</html>

315
docs/classes/System.html Normal file
View file

@ -0,0 +1,315 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<head>
<title>Reference</title>
<link rel="stylesheet" href="../ldoc.css" type="text/css" />
</head>
<body>
<div id="container">
<div id="product">
<div id="product_logo"></div>
<div id="product_name"><big><b></b></big></div>
<div id="product_description"></div>
</div> <!-- id="product" -->
<div id="main">
<!-- Menu -->
<div id="navigation">
<br/>
<h1>Concord</h1>
<ul>
<li><a href="../index.html">Index</a></li>
</ul>
<h2>Contents</h2>
<ul>
<li><a href="#Methods">Methods</a></li>
<li><a href="#Callbacks">Callbacks </a></li>
</ul>
<h2>Classes</h2>
<ul class="nowrap">
<li><a href="../classes/Component.html">Component</a></li>
<li><a href="../classes/Entity.html">Entity</a></li>
<li><a href="../classes/List.html">List</a></li>
<li><a href="../classes/Pool.html">Pool</a></li>
<li><strong>System</strong></li>
<li><a href="../classes/World.html">World</a></li>
</ul>
<h2>Modules</h2>
<ul class="nowrap">
<li><a href="../modules/Components.html">Components</a></li>
<li><a href="../modules/Concord.html">Concord</a></li>
<li><a href="../modules/type.html">type</a></li>
<li><a href="../modules/utils.html">utils</a></li>
</ul>
</div>
<div id="content">
<h1>Class <code>System</code></h1>
<p>Iterates over Entities.</p>
<p> From these Entities its get Components and modify them.
A System contains 1 or more Pools.
A System is contained by 1 World.</p>
<h2><a href="#Methods">Methods</a></h2>
<table class="function_list">
<tr>
<td class="name" nowrap><a href="#System:new">System:new (table)</a></td>
<td class="summary">Creates a new SystemClass.</td>
</tr>
<tr>
<td class="name" nowrap><a href="#System:setEnabled">System:setEnabled (enable)</a></td>
<td class="summary">Sets if the System is enabled</td>
</tr>
<tr>
<td class="name" nowrap><a href="#System:isEnabled">System:isEnabled ()</a></td>
<td class="summary">Returns is the System is enabled</td>
</tr>
<tr>
<td class="name" nowrap><a href="#System:getWorld">System:getWorld ()</a></td>
<td class="summary">Returns the World the System is in.</td>
</tr>
<tr>
<td class="name" nowrap><a href="#System:hasName">System:hasName ()</a></td>
<td class="summary">Returns true if the System has a name.</td>
</tr>
<tr>
<td class="name" nowrap><a href="#System:getName">System:getName ()</a></td>
<td class="summary">Returns the name of the System.</td>
</tr>
</table>
<h2><a href="#Callbacks">Callbacks </a></h2>
<table class="function_list">
<tr>
<td class="name" nowrap><a href="#System:init">System:init (world)</a></td>
<td class="summary">Callback for system initialization.</td>
</tr>
<tr>
<td class="name" nowrap><a href="#System:onEnabled">System:onEnabled ()</a></td>
<td class="summary">Callback for when a System is enabled.</td>
</tr>
<tr>
<td class="name" nowrap><a href="#System:onDisabled">System:onDisabled ()</a></td>
<td class="summary">Callback for when a System is disabled.</td>
</tr>
</table>
<br/>
<br/>
<h2 class="section-header "><a name="Methods"></a>Methods</h2>
<dl class="function">
<dt>
<a name = "System:new"></a>
<strong>System:new (table)</strong>
</dt>
<dd>
Creates a new SystemClass.
<h3>Parameters:</h3>
<ul>
<li><span class="parameter">table</span>
filters A table containing filters (name = {components...})
</li>
</ul>
<h3>Returns:</h3>
<ol>
<span class="types"><a class="type" href="../classes/System.html#">System</a></span>
A new SystemClass
</ol>
</dd>
<dt>
<a name = "System:setEnabled"></a>
<strong>System:setEnabled (enable)</strong>
</dt>
<dd>
Sets if the System is enabled
<h3>Parameters:</h3>
<ul>
<li><span class="parameter">enable</span>
<span class="types"><span class="type">boolean</span></span>
</li>
</ul>
<h3>Returns:</h3>
<ol>
<span class="types"><a class="type" href="../classes/System.html#">System</a></span>
self
</ol>
</dd>
<dt>
<a name = "System:isEnabled"></a>
<strong>System:isEnabled ()</strong>
</dt>
<dd>
Returns is the System is enabled
<h3>Returns:</h3>
<ol>
<span class="types"><span class="type">boolean</span></span>
</ol>
</dd>
<dt>
<a name = "System:getWorld"></a>
<strong>System:getWorld ()</strong>
</dt>
<dd>
Returns the World the System is in.
<h3>Returns:</h3>
<ol>
<span class="types"><a class="type" href="../classes/World.html#">World</a></span>
</ol>
</dd>
<dt>
<a name = "System:hasName"></a>
<strong>System:hasName ()</strong>
</dt>
<dd>
Returns true if the System has a name.
<h3>Returns:</h3>
<ol>
<span class="types"><span class="type">boolean</span></span>
</ol>
</dd>
<dt>
<a name = "System:getName"></a>
<strong>System:getName ()</strong>
</dt>
<dd>
Returns the name of the System.
<h3>Returns:</h3>
<ol>
<span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.4">string</a></span>
</ol>
</dd>
</dl>
<h2 class="section-header "><a name="Callbacks"></a>Callbacks </h2>
<dl class="function">
<dt>
<a name = "System:init"></a>
<strong>System:init (world)</strong>
</dt>
<dd>
Callback for system initialization.
<h3>Parameters:</h3>
<ul>
<li><span class="parameter">world</span>
<span class="types"><a class="type" href="../classes/World.html#">World</a></span>
The World the System was added to
</li>
</ul>
</dd>
<dt>
<a name = "System:onEnabled"></a>
<strong>System:onEnabled ()</strong>
</dt>
<dd>
Callback for when a System is enabled.
</dd>
<dt>
<a name = "System:onDisabled"></a>
<strong>System:onDisabled ()</strong>
</dt>
<dd>
Callback for when a System is disabled.
</dd>
</dl>
</div> <!-- id="content" -->
</div> <!-- id="main" -->
<div id="about">
<i>generated by <a href="http://github.com/stevedonovan/LDoc">LDoc 1.4.6</a></i>
<i style="float:right;">Last updated 2020-08-18 15:20:32 </i>
</div> <!-- id="about" -->
</div> <!-- id="container" -->
</body>
</html>

468
docs/classes/World.html Normal file
View file

@ -0,0 +1,468 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<head>
<title>Reference</title>
<link rel="stylesheet" href="../ldoc.css" type="text/css" />
</head>
<body>
<div id="container">
<div id="product">
<div id="product_logo"></div>
<div id="product_name"><big><b></b></big></div>
<div id="product_description"></div>
</div> <!-- id="product" -->
<div id="main">
<!-- Menu -->
<div id="navigation">
<br/>
<h1>Concord</h1>
<ul>
<li><a href="../index.html">Index</a></li>
</ul>
<h2>Contents</h2>
<ul>
<li><a href="#Methods">Methods</a></li>
</ul>
<h2>Classes</h2>
<ul class="nowrap">
<li><a href="../classes/Component.html">Component</a></li>
<li><a href="../classes/Entity.html">Entity</a></li>
<li><a href="../classes/List.html">List</a></li>
<li><a href="../classes/Pool.html">Pool</a></li>
<li><a href="../classes/System.html">System</a></li>
<li><strong>World</strong></li>
</ul>
<h2>Modules</h2>
<ul class="nowrap">
<li><a href="../modules/Components.html">Components</a></li>
<li><a href="../modules/Concord.html">Concord</a></li>
<li><a href="../modules/type.html">type</a></li>
<li><a href="../modules/utils.html">utils</a></li>
</ul>
</div>
<div id="content">
<h1>Class <code>World</code></h1>
<p>A collection of Systems and Entities.</p>
<p>
A world emits to let Systems iterate.
A World contains any amount of Systems.
A World contains any amount of Entities.</p>
<h2><a href="#Methods">Methods</a></h2>
<table class="function_list">
<tr>
<td class="name" nowrap><a href="#World:new">World:new ()</a></td>
<td class="summary">Creates a new World.</td>
</tr>
<tr>
<td class="name" nowrap><a href="#World:addEntity">World:addEntity (e)</a></td>
<td class="summary">Adds an Entity to the World.</td>
</tr>
<tr>
<td class="name" nowrap><a href="#World:removeEntity">World:removeEntity (e)</a></td>
<td class="summary">Removes an Entity from the World.</td>
</tr>
<tr>
<td class="name" nowrap><a href="#World:addSystem">World:addSystem (systemClass)</a></td>
<td class="summary">Adds a System to the World.</td>
</tr>
<tr>
<td class="name" nowrap><a href="#World:addSystems">World:addSystems (...)</a></td>
<td class="summary">Adds multiple Systems to the World.</td>
</tr>
<tr>
<td class="name" nowrap><a href="#World:hasSystem">World:hasSystem (systemClass)</a></td>
<td class="summary">Returns if the World has a System.</td>
</tr>
<tr>
<td class="name" nowrap><a href="#World:getSystem">World:getSystem (systemClass)</a></td>
<td class="summary">Gets a System from the World.</td>
</tr>
<tr>
<td class="name" nowrap><a href="#World:emit">World:emit (functionName, ...)</a></td>
<td class="summary">Emits a callback in the World.</td>
</tr>
<tr>
<td class="name" nowrap><a href="#World:clear">World:clear ()</a></td>
<td class="summary">Removes all entities from the World</td>
</tr>
<tr>
<td class="name" nowrap><a href="#World:hasName">World:hasName ()</a></td>
<td class="summary">Returns true if the World has a name.</td>
</tr>
<tr>
<td class="name" nowrap><a href="#World:getName">World:getName ()</a></td>
<td class="summary">Returns the name of the World.</td>
</tr>
<tr>
<td class="name" nowrap><a href="#World:onEntityAdded">World:onEntityAdded (e)</a></td>
<td class="summary">Callback for when an Entity is added to the World.</td>
</tr>
<tr>
<td class="name" nowrap><a href="#World:onEntityRemoved">World:onEntityRemoved (e)</a></td>
<td class="summary">Callback for when an Entity is removed from the World.</td>
</tr>
</table>
<br/>
<br/>
<h2 class="section-header "><a name="Methods"></a>Methods</h2>
<dl class="function">
<dt>
<a name = "World:new"></a>
<strong>World:new ()</strong>
</dt>
<dd>
Creates a new World.
<h3>Returns:</h3>
<ol>
<span class="types"><a class="type" href="../classes/World.html#">World</a></span>
The new World
</ol>
</dd>
<dt>
<a name = "World:addEntity"></a>
<strong>World:addEntity (e)</strong>
</dt>
<dd>
Adds an Entity to the World.
<h3>Parameters:</h3>
<ul>
<li><span class="parameter">e</span>
<span class="types"><a class="type" href="../classes/Entity.html#">Entity</a></span>
Entity to add
</li>
</ul>
<h3>Returns:</h3>
<ol>
<span class="types"><a class="type" href="../classes/World.html#">World</a></span>
self
</ol>
</dd>
<dt>
<a name = "World:removeEntity"></a>
<strong>World:removeEntity (e)</strong>
</dt>
<dd>
Removes an Entity from the World.
<h3>Parameters:</h3>
<ul>
<li><span class="parameter">e</span>
<span class="types"><a class="type" href="../classes/Entity.html#">Entity</a></span>
Entity to remove
</li>
</ul>
<h3>Returns:</h3>
<ol>
<span class="types"><a class="type" href="../classes/World.html#">World</a></span>
self
</ol>
</dd>
<dt>
<a name = "World:addSystem"></a>
<strong>World:addSystem (systemClass)</strong>
</dt>
<dd>
Adds a System to the World.
Callbacks are registered automatically
Entities added before are added to the System retroactively
<h3>Parameters:</h3>
<ul>
<li><span class="parameter">systemClass</span>
<span class="types"><a class="type" href="../classes/System.html#">System</a></span>
SystemClass of System to add
</li>
</ul>
<h3>Returns:</h3>
<ol>
<span class="types"><a class="type" href="../classes/World.html#">World</a></span>
self
</ol>
<h3>See also:</h3>
<ul>
<a href="../classes/World.html#World:emit">World:emit</a>
</ul>
</dd>
<dt>
<a name = "World:addSystems"></a>
<strong>World:addSystems (...)</strong>
</dt>
<dd>
Adds multiple Systems to the World.
Callbacks are registered automatically
<h3>Parameters:</h3>
<ul>
<li><span class="parameter">...</span>
SystemClasses of Systems to add
</li>
</ul>
<h3>Returns:</h3>
<ol>
<span class="types"><a class="type" href="../classes/World.html#">World</a></span>
self
</ol>
<h3>See also:</h3>
<ul>
<li><a href="../classes/World.html#World:addSystem">World:addSystem</a></li>
<li><a href="../classes/World.html#World:emit">World:emit</a></li>
</ul>
</dd>
<dt>
<a name = "World:hasSystem"></a>
<strong>World:hasSystem (systemClass)</strong>
</dt>
<dd>
Returns if the World has a System.
<h3>Parameters:</h3>
<ul>
<li><span class="parameter">systemClass</span>
<span class="types"><a class="type" href="../classes/System.html#">System</a></span>
SystemClass of System to check for
</li>
</ul>
<h3>Returns:</h3>
<ol>
<span class="types"><span class="type">boolean</span></span>
</ol>
</dd>
<dt>
<a name = "World:getSystem"></a>
<strong>World:getSystem (systemClass)</strong>
</dt>
<dd>
Gets a System from the World.
<h3>Parameters:</h3>
<ul>
<li><span class="parameter">systemClass</span>
<span class="types"><a class="type" href="../classes/System.html#">System</a></span>
SystemClass of System to get
</li>
</ul>
<h3>Returns:</h3>
<ol>
<span class="types"><a class="type" href="../classes/System.html#">System</a></span>
System to get
</ol>
</dd>
<dt>
<a name = "World:emit"></a>
<strong>World:emit (functionName, ...)</strong>
</dt>
<dd>
Emits a callback in the World.
Calls all functions with the functionName of added Systems
<h3>Parameters:</h3>
<ul>
<li><span class="parameter">functionName</span>
<span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.4">string</a></span>
Name of functions to call.
</li>
<li><span class="parameter">...</span>
Parameters passed to System's functions
</li>
</ul>
<h3>Returns:</h3>
<ol>
<span class="types"><a class="type" href="../classes/World.html#">World</a></span>
self
</ol>
</dd>
<dt>
<a name = "World:clear"></a>
<strong>World:clear ()</strong>
</dt>
<dd>
Removes all entities from the World
<h3>Returns:</h3>
<ol>
<span class="types"><a class="type" href="../classes/World.html#">World</a></span>
self
</ol>
</dd>
<dt>
<a name = "World:hasName"></a>
<strong>World:hasName ()</strong>
</dt>
<dd>
Returns true if the World has a name.
<h3>Returns:</h3>
<ol>
<span class="types"><span class="type">boolean</span></span>
</ol>
</dd>
<dt>
<a name = "World:getName"></a>
<strong>World:getName ()</strong>
</dt>
<dd>
Returns the name of the World.
<h3>Returns:</h3>
<ol>
<span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.4">string</a></span>
</ol>
</dd>
<dt>
<a name = "World:onEntityAdded"></a>
<strong>World:onEntityAdded (e)</strong>
</dt>
<dd>
Callback for when an Entity is added to the World.
<h3>Parameters:</h3>
<ul>
<li><span class="parameter">e</span>
<span class="types"><a class="type" href="../classes/Entity.html#">Entity</a></span>
The Entity that was added
</li>
</ul>
</dd>
<dt>
<a name = "World:onEntityRemoved"></a>
<strong>World:onEntityRemoved (e)</strong>
</dt>
<dd>
Callback for when an Entity is removed from the World.
<h3>Parameters:</h3>
<ul>
<li><span class="parameter">e</span>
<span class="types"><a class="type" href="../classes/Entity.html#">Entity</a></span>
The Entity that was removed
</li>
</ul>
</dd>
</dl>
</div> <!-- id="content" -->
</div> <!-- id="main" -->
<div id="about">
<i>generated by <a href="http://github.com/stevedonovan/LDoc">LDoc 1.4.6</a></i>
<i style="float:right;">Last updated 2020-08-18 15:20:32 </i>
</div> <!-- id="about" -->
</div> <!-- id="container" -->
</body>
</html>

View file

@ -31,13 +31,19 @@
<h2>Modules</h2>
<ul class="nowrap">
<li><a href="modules/component.html">component</a></li>
<li><a href="modules/entity.html">entity</a></li>
<li><a href="modules/init.html">init</a></li>
<li><a href="modules/instance.html">instance</a></li>
<li><a href="modules/list.html">list</a></li>
<li><a href="modules/pool.html">pool</a></li>
<li><a href="modules/system.html">system</a></li>
<li><a href="modules/Components.html">Components</a></li>
<li><a href="modules/Concord.html">Concord</a></li>
<li><a href="modules/type.html">type</a></li>
<li><a href="modules/utils.html">utils</a></li>
</ul>
<h2>Classes</h2>
<ul class="nowrap">
<li><a href="classes/Component.html">Component</a></li>
<li><a href="classes/Entity.html">Entity</a></li>
<li><a href="classes/List.html">List</a></li>
<li><a href="classes/Pool.html">Pool</a></li>
<li><a href="classes/System.html">System</a></li>
<li><a href="classes/World.html">World</a></li>
</ul>
</div>
@ -50,32 +56,50 @@
<h2>Modules</h2>
<table class="module_list">
<tr>
<td class="name" nowrap><a href="modules/component.html">component</a></td>
<td class="summary">Component</td>
<td class="name" nowrap><a href="modules/Components.html">Components</a></td>
<td class="summary">Container for registered ComponentClasses</td>
</tr>
<tr>
<td class="name" nowrap><a href="modules/entity.html">entity</a></td>
<td class="summary">Entity</td>
<td class="name" nowrap><a href="modules/Concord.html">Concord</a></td>
<td class="summary"></td>
</tr>
<tr>
<td class="name" nowrap><a href="modules/init.html">init</a></td>
<td class="summary">init</td>
<td class="name" nowrap><a href="modules/type.html">type</a></td>
<td class="summary">Type
Helper module to do easy type checking for Concord types</td>
</tr>
<tr>
<td class="name" nowrap><a href="modules/instance.html">instance</a></td>
<td class="summary">Instance</td>
<td class="name" nowrap><a href="modules/utils.html">utils</a></td>
<td class="summary">Utils
Helper module for misc operations</td>
</tr>
</table>
<h2>Classes</h2>
<table class="module_list">
<tr>
<td class="name" nowrap><a href="classes/Component.html">Component</a></td>
<td class="summary">A pure data container that is contained by a single entity.</td>
</tr>
<tr>
<td class="name" nowrap><a href="modules/list.html">list</a></td>
<td class="summary">List</td>
<td class="name" nowrap><a href="classes/Entity.html">Entity</a></td>
<td class="summary">An object that exists in a world.</td>
</tr>
<tr>
<td class="name" nowrap><a href="modules/pool.html">pool</a></td>
<td class="summary">Pool</td>
<td class="name" nowrap><a href="classes/List.html">List</a></td>
<td class="summary">Data structure that allows for fast removal at the cost of containing order.</td>
</tr>
<tr>
<td class="name" nowrap><a href="modules/system.html">system</a></td>
<td class="summary">System</td>
<td class="name" nowrap><a href="classes/Pool.html">Pool</a></td>
<td class="summary">Used to iterate over Entities with a specific Components
A Pool contain a any amount of Entities.</td>
</tr>
<tr>
<td class="name" nowrap><a href="classes/System.html">System</a></td>
<td class="summary">Iterates over Entities.</td>
</tr>
<tr>
<td class="name" nowrap><a href="classes/World.html">World</a></td>
<td class="summary">A collection of Systems and Entities.</td>
</tr>
</table>
@ -83,7 +107,7 @@
</div> <!-- id="main" -->
<div id="about">
<i>generated by <a href="http://github.com/stevedonovan/LDoc">LDoc 1.4.6</a></i>
<i style="float:right;">Last updated 2018-09-25 18:42:43 </i>
<i style="float:right;">Last updated 2020-08-18 15:20:32 </i>
</div> <!-- id="about" -->
</div> <!-- id="container" -->
</body>

76
docs/modules/Concord.html Normal file
View file

@ -0,0 +1,76 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<head>
<title>Reference</title>
<link rel="stylesheet" href="../ldoc.css" type="text/css" />
</head>
<body>
<div id="container">
<div id="product">
<div id="product_logo"></div>
<div id="product_name"><big><b></b></big></div>
<div id="product_description"></div>
</div> <!-- id="product" -->
<div id="main">
<!-- Menu -->
<div id="navigation">
<br/>
<h1>Concord</h1>
<ul>
<li><a href="../index.html">Index</a></li>
</ul>
<h2>Modules</h2>
<ul class="nowrap">
<li><a href="../modules/Components.html">Components</a></li>
<li><strong>Concord</strong></li>
<li><a href="../modules/type.html">type</a></li>
<li><a href="../modules/utils.html">utils</a></li>
</ul>
<h2>Classes</h2>
<ul class="nowrap">
<li><a href="../classes/Component.html">Component</a></li>
<li><a href="../classes/Entity.html">Entity</a></li>
<li><a href="../classes/List.html">List</a></li>
<li><a href="../classes/Pool.html">Pool</a></li>
<li><a href="../classes/System.html">System</a></li>
<li><a href="../classes/World.html">World</a></li>
</ul>
</div>
<div id="content">
<h1>Module <code>Concord</code></h1>
<p></p>
<p></p>
<br/>
<br/>
</div> <!-- id="content" -->
</div> <!-- id="main" -->
<div id="about">
<i>generated by <a href="http://github.com/stevedonovan/LDoc">LDoc 1.4.6</a></i>
<i style="float:right;">Last updated 2020-08-18 15:20:32 </i>
</div> <!-- id="about" -->
</div> <!-- id="container" -->
</body>
</html>

View file

@ -0,0 +1,182 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<head>
<title>Reference</title>
<link rel="stylesheet" href="../ldoc.css" type="text/css" />
</head>
<body>
<div id="container">
<div id="product">
<div id="product_logo"></div>
<div id="product_name"><big><b></b></big></div>
<div id="product_description"></div>
</div> <!-- id="product" -->
<div id="main">
<!-- Menu -->
<div id="navigation">
<br/>
<h1>Concord</h1>
<ul>
<li><a href="../index.html">Index</a></li>
</ul>
<h2>Contents</h2>
<ul>
<li><a href="#Functions">Functions</a></li>
</ul>
<h2>Modules</h2>
<ul class="nowrap">
<li><strong>Assemblages</strong></li>
<li><a href="../modules/Components.html">Components</a></li>
<li><a href="../modules/Concord.html">Concord</a></li>
<li><a href="../modules/Systems.html">Systems</a></li>
<li><a href="../modules/type.html">type</a></li>
<li><a href="../modules/utils.html">utils</a></li>
<li><a href="../modules/worlds.html">worlds</a></li>
</ul>
<h2>Classes</h2>
<ul class="nowrap">
<li><a href="../classes/Assemblage.html">Assemblage</a></li>
<li><a href="../classes/Component.html">Component</a></li>
<li><a href="../classes/Entity.html">Entity</a></li>
<li><a href="../classes/List.html">List</a></li>
<li><a href="../classes/Pool.html">Pool</a></li>
<li><a href="../classes/System.html">System</a></li>
<li><a href="../classes/World.html">World</a></li>
</ul>
</div>
<div id="content">
<h1>Module <code>Assemblages</code></h1>
<p>A container for registered <a href="../classes/Assemblage.html#">Assemblage</a>s</p>
<p></p>
<h2><a href="#Functions">Functions</a></h2>
<table class="function_list">
<tr>
<td class="name" nowrap><a href="#register">register (name, assemblage)</a></td>
<td class="summary">Registers an Assemblage.</td>
</tr>
<tr>
<td class="name" nowrap><a href="#has">has (name)</a></td>
<td class="summary">Returns true if the containter has an Assemblage with the specified name</td>
</tr>
<tr>
<td class="name" nowrap><a href="#get">get (name)</a></td>
<td class="summary">Returns the Assemblage with the specified name</td>
</tr>
</table>
<br/>
<br/>
<h2 class="section-header "><a name="Functions"></a>Functions</h2>
<dl class="function">
<dt>
<a name = "register"></a>
<strong>register (name, assemblage)</strong>
</dt>
<dd>
Registers an Assemblage.
<h3>Parameters:</h3>
<ul>
<li><span class="parameter">name</span>
<span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.4">string</a></span>
Name to register under
</li>
<li><span class="parameter">assemblage</span>
<span class="types"><a class="type" href="../classes/Assemblage.html#">Assemblage</a></span>
Assemblage to register
</li>
</ul>
</dd>
<dt>
<a name = "has"></a>
<strong>has (name)</strong>
</dt>
<dd>
Returns true if the containter has an Assemblage with the specified name
<h3>Parameters:</h3>
<ul>
<li><span class="parameter">name</span>
<span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.4">string</a></span>
Name of the Assemblage to check
</li>
</ul>
<h3>Returns:</h3>
<ol>
<span class="types"><span class="type">boolean</span></span>
</ol>
</dd>
<dt>
<a name = "get"></a>
<strong>get (name)</strong>
</dt>
<dd>
Returns the Assemblage with the specified name
<h3>Parameters:</h3>
<ul>
<li><span class="parameter">name</span>
<span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.4">string</a></span>
Name of the Assemblage to get
</li>
</ul>
<h3>Returns:</h3>
<ol>
<span class="types"><a class="type" href="../classes/Assemblage.html#">Assemblage</a></span>
</ol>
</dd>
</dl>
</div> <!-- id="content" -->
</div> <!-- id="main" -->
<div id="about">
<i>generated by <a href="http://github.com/stevedonovan/LDoc">LDoc 1.4.6</a></i>
<i style="float:right;">Last updated 2020-01-04 10:27:07 </i>
</div> <!-- id="about" -->
</div> <!-- id="container" -->
</body>
</html>

View file

@ -1,139 +0,0 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<head>
<title>Reference</title>
<link rel="stylesheet" href="../ldoc.css" type="text/css" />
</head>
<body>
<div id="container">
<div id="product">
<div id="product_logo"></div>
<div id="product_name"><big><b></b></big></div>
<div id="product_description"></div>
</div> <!-- id="product" -->
<div id="main">
<!-- Menu -->
<div id="navigation">
<br/>
<h1>Concord</h1>
<ul>
<li><a href="../index.html">Index</a></li>
</ul>
<h2>Contents</h2>
<ul>
<li><a href="#Functions">Functions</a></li>
</ul>
<h2>Modules</h2>
<ul class="nowrap">
<li><strong>component</strong></li>
<li><a href="../modules/entity.html">entity</a></li>
<li><a href="../modules/init.html">init</a></li>
<li><a href="../modules/instance.html">instance</a></li>
<li><a href="../modules/list.html">list</a></li>
<li><a href="../modules/pool.html">pool</a></li>
<li><a href="../modules/system.html">system</a></li>
</ul>
</div>
<div id="content">
<h1>Module <code>component</code></h1>
<p>Component</p>
<p></p>
<h2><a href="#Functions">Functions</a></h2>
<table class="function_list">
<tr>
<td class="name" nowrap><a href="#Component.new">Component.new (populate)</a></td>
<td class="summary">Creates a new Component.</td>
</tr>
<tr>
<td class="name" nowrap><a href="#Component:__initialize">Component:__initialize (...)</a></td>
<td class="summary">Creates and initializes a new Bag.</td>
</tr>
</table>
<br/>
<br/>
<h2 class="section-header "><a name="Functions"></a>Functions</h2>
<dl class="function">
<dt>
<a name = "Component.new"></a>
<strong>Component.new (populate)</strong>
</dt>
<dd>
Creates a new Component.
<h3>Parameters:</h3>
<ul>
<li><span class="parameter">populate</span>
A function that populates the Bag with values
</li>
</ul>
<h3>Returns:</h3>
<ol>
A Component object
</ol>
</dd>
<dt>
<a name = "Component:__initialize"></a>
<strong>Component:__initialize (...)</strong>
</dt>
<dd>
Creates and initializes a new Bag.
<h3>Parameters:</h3>
<ul>
<li><span class="parameter">...</span>
The values passed to the populate function
</li>
</ul>
<h3>Returns:</h3>
<ol>
A new initialized Bag
</ol>
</dd>
</dl>
</div> <!-- id="content" -->
</div> <!-- id="main" -->
<div id="about">
<i>generated by <a href="http://github.com/stevedonovan/LDoc">LDoc 1.4.6</a></i>
<i style="float:right;">Last updated 2018-09-25 18:42:43 </i>
</div> <!-- id="about" -->
</div> <!-- id="container" -->
</body>
</html>

View file

@ -0,0 +1,185 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<head>
<title>Reference</title>
<link rel="stylesheet" href="../ldoc.css" type="text/css" />
</head>
<body>
<div id="container">
<div id="product">
<div id="product_logo"></div>
<div id="product_name"><big><b></b></big></div>
<div id="product_description"></div>
</div> <!-- id="product" -->
<div id="main">
<!-- Menu -->
<div id="navigation">
<br/>
<h1>Concord</h1>
<ul>
<li><a href="../index.html">Index</a></li>
</ul>
<h2>Contents</h2>
<ul>
<li><a href="#Functions">Functions</a></li>
</ul>
<h2>Modules</h2>
<ul class="nowrap">
<li><strong>Components</strong></li>
<li><a href="../modules/Concord.html">Concord</a></li>
<li><a href="../modules/type.html">type</a></li>
<li><a href="../modules/utils.html">utils</a></li>
</ul>
<h2>Classes</h2>
<ul class="nowrap">
<li><a href="../classes/Component.html">Component</a></li>
<li><a href="../classes/Entity.html">Entity</a></li>
<li><a href="../classes/List.html">List</a></li>
<li><a href="../classes/Pool.html">Pool</a></li>
<li><a href="../classes/System.html">System</a></li>
<li><a href="../classes/World.html">World</a></li>
</ul>
</div>
<div id="content">
<h1>Module <code>Components</code></h1>
<p>Container for registered ComponentClasses</p>
<p></p>
<h2><a href="#Functions">Functions</a></h2>
<table class="function_list">
<tr>
<td class="name" nowrap><a href="#has">has (name)</a></td>
<td class="summary">Returns true if the containter has the ComponentClass with the specified name</td>
</tr>
<tr>
<td class="name" nowrap><a href="#try">try (name)</a></td>
<td class="summary">Returns true and the ComponentClass if one was registered with the specified name
or false and an error otherwise</td>
</tr>
<tr>
<td class="name" nowrap><a href="#get">get (name)</a></td>
<td class="summary">Returns the ComponentClass with the specified name</td>
</tr>
</table>
<br/>
<br/>
<h2 class="section-header "><a name="Functions"></a>Functions</h2>
<dl class="function">
<dt>
<a name = "has"></a>
<strong>has (name)</strong>
</dt>
<dd>
Returns true if the containter has the ComponentClass with the specified name
<h3>Parameters:</h3>
<ul>
<li><span class="parameter">name</span>
<span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.4">string</a></span>
Name of the ComponentClass to check
</li>
</ul>
<h3>Returns:</h3>
<ol>
<span class="types"><span class="type">boolean</span></span>
</ol>
</dd>
<dt>
<a name = "try"></a>
<strong>try (name)</strong>
</dt>
<dd>
Returns true and the ComponentClass if one was registered with the specified name
or false and an error otherwise
<h3>Parameters:</h3>
<ul>
<li><span class="parameter">name</span>
<span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.4">string</a></span>
Name of the ComponentClass to check
</li>
</ul>
<h3>Returns:</h3>
<ol>
<li>
<span class="types"><span class="type">boolean</span></span>
</li>
<li>
<span class="types"><a class="type" href="../classes/Component.html#">Component</a></span>
or error string</li>
</ol>
</dd>
<dt>
<a name = "get"></a>
<strong>get (name)</strong>
</dt>
<dd>
Returns the ComponentClass with the specified name
<h3>Parameters:</h3>
<ul>
<li><span class="parameter">name</span>
<span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.4">string</a></span>
Name of the ComponentClass to get
</li>
</ul>
<h3>Returns:</h3>
<ol>
<span class="types"><a class="type" href="../classes/Component.html#">Component</a></span>
</ol>
</dd>
</dl>
</div> <!-- id="content" -->
</div> <!-- id="main" -->
<div id="about">
<i>generated by <a href="http://github.com/stevedonovan/LDoc">LDoc 1.4.6</a></i>
<i style="float:right;">Last updated 2020-08-18 15:20:32 </i>
</div> <!-- id="about" -->
</div> <!-- id="container" -->
</body>
</html>

View file

@ -1,269 +0,0 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<head>
<title>Reference</title>
<link rel="stylesheet" href="../ldoc.css" type="text/css" />
</head>
<body>
<div id="container">
<div id="product">
<div id="product_logo"></div>
<div id="product_name"><big><b></b></big></div>
<div id="product_description"></div>
</div> <!-- id="product" -->
<div id="main">
<!-- Menu -->
<div id="navigation">
<br/>
<h1>Concord</h1>
<ul>
<li><a href="../index.html">Index</a></li>
</ul>
<h2>Contents</h2>
<ul>
<li><a href="#Functions">Functions</a></li>
</ul>
<h2>Modules</h2>
<ul class="nowrap">
<li><a href="../modules/component.html">component</a></li>
<li><strong>entity</strong></li>
<li><a href="../modules/init.html">init</a></li>
<li><a href="../modules/instance.html">instance</a></li>
<li><a href="../modules/list.html">list</a></li>
<li><a href="../modules/pool.html">pool</a></li>
<li><a href="../modules/system.html">system</a></li>
</ul>
</div>
<div id="content">
<h1>Module <code>entity</code></h1>
<p>Entity</p>
<p></p>
<h2><a href="#Functions">Functions</a></h2>
<table class="function_list">
<tr>
<td class="name" nowrap><a href="#Entity.new">Entity.new ()</a></td>
<td class="summary">Creates and initializes a new Entity.</td>
</tr>
<tr>
<td class="name" nowrap><a href="#Entity:give">Entity:give (component, ...)</a></td>
<td class="summary">Gives an Entity a component with values.</td>
</tr>
<tr>
<td class="name" nowrap><a href="#Entity:remove">Entity:remove (component)</a></td>
<td class="summary">Removes a component from an Entity.</td>
</tr>
<tr>
<td class="name" nowrap><a href="#Entity:apply">Entity:apply ()</a></td>
<td class="summary">Checks the Entity against the pools again.</td>
</tr>
<tr>
<td class="name" nowrap><a href="#Entity:destroy">Entity:destroy ()</a></td>
<td class="summary">Destroys the Entity.</td>
</tr>
<tr>
<td class="name" nowrap><a href="#Entity:get">Entity:get (component)</a></td>
<td class="summary">Gets a Component from the Entity.</td>
</tr>
<tr>
<td class="name" nowrap><a href="#Entity:has">Entity:has (component)</a></td>
<td class="summary">Returns true if the Entity has the Component.</td>
</tr>
</table>
<br/>
<br/>
<h2 class="section-header "><a name="Functions"></a>Functions</h2>
<dl class="function">
<dt>
<a name = "Entity.new"></a>
<strong>Entity.new ()</strong>
</dt>
<dd>
Creates and initializes a new Entity.
<h3>Returns:</h3>
<ol>
A new Entity
</ol>
</dd>
<dt>
<a name = "Entity:give"></a>
<strong>Entity:give (component, ...)</strong>
</dt>
<dd>
Gives an Entity a component with values.
<h3>Parameters:</h3>
<ul>
<li><span class="parameter">component</span>
The Component to add
</li>
<li><span class="parameter">...</span>
The values passed to the Component
</li>
</ul>
<h3>Returns:</h3>
<ol>
self
</ol>
</dd>
<dt>
<a name = "Entity:remove"></a>
<strong>Entity:remove (component)</strong>
</dt>
<dd>
Removes a component from an Entity.
<h3>Parameters:</h3>
<ul>
<li><span class="parameter">component</span>
The Component to remove
</li>
</ul>
<h3>Returns:</h3>
<ol>
self
</ol>
</dd>
<dt>
<a name = "Entity:apply"></a>
<strong>Entity:apply ()</strong>
</dt>
<dd>
Checks the Entity against the pools again.
<h3>Returns:</h3>
<ol>
self
</ol>
</dd>
<dt>
<a name = "Entity:destroy"></a>
<strong>Entity:destroy ()</strong>
</dt>
<dd>
Destroys the Entity.
<h3>Returns:</h3>
<ol>
self
</ol>
</dd>
<dt>
<a name = "Entity:get"></a>
<strong>Entity:get (component)</strong>
</dt>
<dd>
Gets a Component from the Entity.
<h3>Parameters:</h3>
<ul>
<li><span class="parameter">component</span>
The Component to get
</li>
</ul>
<h3>Returns:</h3>
<ol>
The Bag from the Component
</ol>
</dd>
<dt>
<a name = "Entity:has"></a>
<strong>Entity:has (component)</strong>
</dt>
<dd>
Returns true if the Entity has the Component.
<h3>Parameters:</h3>
<ul>
<li><span class="parameter">component</span>
The Component to check against
</li>
</ul>
<h3>Returns:</h3>
<ol>
True if the entity has the Bag. False otherwise
</ol>
</dd>
</dl>
</div> <!-- id="content" -->
</div> <!-- id="main" -->
<div id="about">
<i>generated by <a href="http://github.com/stevedonovan/LDoc">LDoc 1.4.6</a></i>
<i style="float:right;">Last updated 2018-09-25 18:42:43 </i>
</div> <!-- id="about" -->
</div> <!-- id="container" -->
</body>
</html>

View file

@ -1,112 +0,0 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<head>
<title>Reference</title>
<link rel="stylesheet" href="../ldoc.css" type="text/css" />
</head>
<body>
<div id="container">
<div id="product">
<div id="product_logo"></div>
<div id="product_name"><big><b></b></big></div>
<div id="product_description"></div>
</div> <!-- id="product" -->
<div id="main">
<!-- Menu -->
<div id="navigation">
<br/>
<h1>Concord</h1>
<ul>
<li><a href="../index.html">Index</a></li>
</ul>
<h2>Contents</h2>
<ul>
<li><a href="#Functions">Functions</a></li>
</ul>
<h2>Modules</h2>
<ul class="nowrap">
<li><a href="../modules/component.html">component</a></li>
<li><a href="../modules/entity.html">entity</a></li>
<li><strong>init</strong></li>
<li><a href="../modules/instance.html">instance</a></li>
<li><a href="../modules/list.html">list</a></li>
<li><a href="../modules/pool.html">pool</a></li>
<li><a href="../modules/system.html">system</a></li>
</ul>
</div>
<div id="content">
<h1>Module <code>init</code></h1>
<p>init</p>
<p></p>
<h2><a href="#Functions">Functions</a></h2>
<table class="function_list">
<tr>
<td class="name" nowrap><a href="#Concord.init">Concord.init (settings)</a></td>
<td class="summary">Initializes the library with some optional settings</td>
</tr>
</table>
<br/>
<br/>
<h2 class="section-header "><a name="Functions"></a>Functions</h2>
<dl class="function">
<dt>
<a name = "Concord.init"></a>
<strong>Concord.init (settings)</strong>
</dt>
<dd>
Initializes the library with some optional settings
<h3>Parameters:</h3>
<ul>
<li><span class="parameter">settings</span>
Table of settings: {
useEvents Flag to overwrite love.run and use events. Defaults to false
}
</li>
</ul>
<h3>Returns:</h3>
<ol>
Concord
</ol>
</dd>
</dl>
</div> <!-- id="content" -->
</div> <!-- id="main" -->
<div id="about">
<i>generated by <a href="http://github.com/stevedonovan/LDoc">LDoc 1.4.6</a></i>
<i style="float:right;">Last updated 2018-09-25 18:42:43 </i>
</div> <!-- id="about" -->
</div> <!-- id="container" -->
</body>
</html>

View file

@ -1,463 +0,0 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<head>
<title>Reference</title>
<link rel="stylesheet" href="../ldoc.css" type="text/css" />
</head>
<body>
<div id="container">
<div id="product">
<div id="product_logo"></div>
<div id="product_name"><big><b></b></big></div>
<div id="product_description"></div>
</div> <!-- id="product" -->
<div id="main">
<!-- Menu -->
<div id="navigation">
<br/>
<h1>Concord</h1>
<ul>
<li><a href="../index.html">Index</a></li>
</ul>
<h2>Contents</h2>
<ul>
<li><a href="#Functions">Functions</a></li>
</ul>
<h2>Modules</h2>
<ul class="nowrap">
<li><a href="../modules/component.html">component</a></li>
<li><a href="../modules/entity.html">entity</a></li>
<li><a href="../modules/init.html">init</a></li>
<li><strong>instance</strong></li>
<li><a href="../modules/list.html">list</a></li>
<li><a href="../modules/pool.html">pool</a></li>
<li><a href="../modules/system.html">system</a></li>
</ul>
</div>
<div id="content">
<h1>Module <code>instance</code></h1>
<p>Instance</p>
<p></p>
<h2><a href="#Functions">Functions</a></h2>
<table class="function_list">
<tr>
<td class="name" nowrap><a href="#Instance.new">Instance.new ()</a></td>
<td class="summary">Creates a new Instance.</td>
</tr>
<tr>
<td class="name" nowrap><a href="#Instance:addEntity">Instance:addEntity (e)</a></td>
<td class="summary">Adds an Entity to the Instance.</td>
</tr>
<tr>
<td class="name" nowrap><a href="#Instance:checkEntity">Instance:checkEntity (e)</a></td>
<td class="summary">Checks an Entity against all the systems in the Instance.</td>
</tr>
<tr>
<td class="name" nowrap><a href="#Instance:removeEntity">Instance:removeEntity (e)</a></td>
<td class="summary">Marks an Entity as removed from the Instance.</td>
</tr>
<tr>
<td class="name" nowrap><a href="#Instance:flush">Instance:flush ()</a></td>
<td class="summary">Completely removes all marked Entities in the Instance.</td>
</tr>
<tr>
<td class="name" nowrap><a href="#Instance:addSystem">Instance:addSystem (system, eventName, callback, enabled)</a></td>
<td class="summary">Adds a System to the Instance.</td>
</tr>
<tr>
<td class="name" nowrap><a href="#Instance:enableSystem">Instance:enableSystem (system, eventName, callback)</a></td>
<td class="summary">Enables a System in the Instance.</td>
</tr>
<tr>
<td class="name" nowrap><a href="#Instance:disableSystem">Instance:disableSystem (system, eventName, callback)</a></td>
<td class="summary">Disables a System in the Instance.</td>
</tr>
<tr>
<td class="name" nowrap><a href="#Instance:setSystem">Instance:setSystem (system, eventName, callback, enable)</a></td>
<td class="summary">Sets a System 'enable' in the Instance.</td>
</tr>
<tr>
<td class="name" nowrap><a href="#Instance:emit">Instance:emit (eventName, ...)</a></td>
<td class="summary">Emits an Event in the Instance.</td>
</tr>
<tr>
<td class="name" nowrap><a href="#Instance:clear">Instance:clear ()</a></td>
<td class="summary">Removes all entities from the Instance</td>
</tr>
<tr>
<td class="name" nowrap><a href="#Instance:onEntityAdded">Instance:onEntityAdded (e)</a></td>
<td class="summary">Default callback for adding an Entity.</td>
</tr>
<tr>
<td class="name" nowrap><a href="#Instance:onEntityRemoved">Instance:onEntityRemoved (e)</a></td>
<td class="summary">Default callback for removing an Entity.</td>
</tr>
</table>
<br/>
<br/>
<h2 class="section-header "><a name="Functions"></a>Functions</h2>
<dl class="function">
<dt>
<a name = "Instance.new"></a>
<strong>Instance.new ()</strong>
</dt>
<dd>
Creates a new Instance.
<h3>Returns:</h3>
<ol>
The new instance
</ol>
</dd>
<dt>
<a name = "Instance:addEntity"></a>
<strong>Instance:addEntity (e)</strong>
</dt>
<dd>
Adds an Entity to the Instance.
<h3>Parameters:</h3>
<ul>
<li><span class="parameter">e</span>
The Entity to add
</li>
</ul>
<h3>Returns:</h3>
<ol>
self
</ol>
</dd>
<dt>
<a name = "Instance:checkEntity"></a>
<strong>Instance:checkEntity (e)</strong>
</dt>
<dd>
Checks an Entity against all the systems in the Instance.
<h3>Parameters:</h3>
<ul>
<li><span class="parameter">e</span>
The Entity to check
</li>
</ul>
<h3>Returns:</h3>
<ol>
self
</ol>
</dd>
<dt>
<a name = "Instance:removeEntity"></a>
<strong>Instance:removeEntity (e)</strong>
</dt>
<dd>
Marks an Entity as removed from the Instance.
<h3>Parameters:</h3>
<ul>
<li><span class="parameter">e</span>
The Entity to mark
</li>
</ul>
<h3>Returns:</h3>
<ol>
self
</ol>
</dd>
<dt>
<a name = "Instance:flush"></a>
<strong>Instance:flush ()</strong>
</dt>
<dd>
Completely removes all marked Entities in the Instance.
<h3>Returns:</h3>
<ol>
self
</ol>
</dd>
<dt>
<a name = "Instance:addSystem"></a>
<strong>Instance:addSystem (system, eventName, callback, enabled)</strong>
</dt>
<dd>
Adds a System to the Instance.
<h3>Parameters:</h3>
<ul>
<li><span class="parameter">system</span>
The System to add
</li>
<li><span class="parameter">eventName</span>
The Event to register to
</li>
<li><span class="parameter">callback</span>
The function name to call. Defaults to eventName
</li>
<li><span class="parameter">enabled</span>
If the system is enabled. Defaults to true
</li>
</ul>
<h3>Returns:</h3>
<ol>
self
</ol>
</dd>
<dt>
<a name = "Instance:enableSystem"></a>
<strong>Instance:enableSystem (system, eventName, callback)</strong>
</dt>
<dd>
Enables a System in the Instance.
<h3>Parameters:</h3>
<ul>
<li><span class="parameter">system</span>
The System to enable
</li>
<li><span class="parameter">eventName</span>
The Event it was registered to
</li>
<li><span class="parameter">callback</span>
The callback it was registered with. Defaults to eventName
</li>
</ul>
<h3>Returns:</h3>
<ol>
self
</ol>
</dd>
<dt>
<a name = "Instance:disableSystem"></a>
<strong>Instance:disableSystem (system, eventName, callback)</strong>
</dt>
<dd>
Disables a System in the Instance.
<h3>Parameters:</h3>
<ul>
<li><span class="parameter">system</span>
The System to disable
</li>
<li><span class="parameter">eventName</span>
The Event it was registered to
</li>
<li><span class="parameter">callback</span>
The callback it was registered with. Defaults to eventName
</li>
</ul>
<h3>Returns:</h3>
<ol>
self
</ol>
</dd>
<dt>
<a name = "Instance:setSystem"></a>
<strong>Instance:setSystem (system, eventName, callback, enable)</strong>
</dt>
<dd>
Sets a System 'enable' in the Instance.
<h3>Parameters:</h3>
<ul>
<li><span class="parameter">system</span>
The System to set
</li>
<li><span class="parameter">eventName</span>
The Event it was registered to
</li>
<li><span class="parameter">callback</span>
The callback it was registered with. Defaults to eventName
</li>
<li><span class="parameter">enable</span>
The state to set it to
</li>
</ul>
<h3>Returns:</h3>
<ol>
self
</ol>
</dd>
<dt>
<a name = "Instance:emit"></a>
<strong>Instance:emit (eventName, ...)</strong>
</dt>
<dd>
Emits an Event in the Instance.
<h3>Parameters:</h3>
<ul>
<li><span class="parameter">eventName</span>
The Event that should be emitted
</li>
<li><span class="parameter">...</span>
Parameters passed to listeners
</li>
</ul>
<h3>Returns:</h3>
<ol>
self
</ol>
</dd>
<dt>
<a name = "Instance:clear"></a>
<strong>Instance:clear ()</strong>
</dt>
<dd>
Removes all entities from the Instance
<h3>Returns:</h3>
<ol>
self
</ol>
</dd>
<dt>
<a name = "Instance:onEntityAdded"></a>
<strong>Instance:onEntityAdded (e)</strong>
</dt>
<dd>
Default callback for adding an Entity.
<h3>Parameters:</h3>
<ul>
<li><span class="parameter">e</span>
The Entity that was added
</li>
</ul>
</dd>
<dt>
<a name = "Instance:onEntityRemoved"></a>
<strong>Instance:onEntityRemoved (e)</strong>
</dt>
<dd>
Default callback for removing an Entity.
<h3>Parameters:</h3>
<ul>
<li><span class="parameter">e</span>
The Entity that was removed
</li>
</ul>
</dd>
</dl>
</div> <!-- id="content" -->
</div> <!-- id="main" -->
<div id="about">
<i>generated by <a href="http://github.com/stevedonovan/LDoc">LDoc 1.4.6</a></i>
<i style="float:right;">Last updated 2018-09-25 18:42:43 </i>
</div> <!-- id="about" -->
</div> <!-- id="container" -->
</body>
</html>

View file

@ -1,142 +0,0 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<head>
<title>Reference</title>
<link rel="stylesheet" href="../ldoc.css" type="text/css" />
</head>
<body>
<div id="container">
<div id="product">
<div id="product_logo"></div>
<div id="product_name"><big><b></b></big></div>
<div id="product_description"></div>
</div> <!-- id="product" -->
<div id="main">
<!-- Menu -->
<div id="navigation">
<br/>
<h1>Concord</h1>
<ul>
<li><a href="../index.html">Index</a></li>
</ul>
<h2>Contents</h2>
<ul>
<li><a href="#Functions">Functions</a></li>
</ul>
<h2>Modules</h2>
<ul class="nowrap">
<li><a href="../modules/component.html">component</a></li>
<li><a href="../modules/entity.html">entity</a></li>
<li><a href="../modules/init.html">init</a></li>
<li><a href="../modules/instance.html">instance</a></li>
<li><a href="../modules/list.html">list</a></li>
<li><strong>pool</strong></li>
<li><a href="../modules/system.html">system</a></li>
</ul>
</div>
<div id="content">
<h1>Module <code>pool</code></h1>
<p>Pool</p>
<p></p>
<h2><a href="#Functions">Functions</a></h2>
<table class="function_list">
<tr>
<td class="name" nowrap><a href="#Pool.new">Pool.new (name, filter)</a></td>
<td class="summary">Creates a new Pool</td>
</tr>
<tr>
<td class="name" nowrap><a href="#Pool:eligible">Pool:eligible (e)</a></td>
<td class="summary">Checks if an Entity is eligible for the Pool.</td>
</tr>
</table>
<br/>
<br/>
<h2 class="section-header "><a name="Functions"></a>Functions</h2>
<dl class="function">
<dt>
<a name = "Pool.new"></a>
<strong>Pool.new (name, filter)</strong>
</dt>
<dd>
Creates a new Pool
<h3>Parameters:</h3>
<ul>
<li><span class="parameter">name</span>
Identifier for the Pool.
</li>
<li><span class="parameter">filter</span>
Table containing the required Components
</li>
</ul>
<h3>Returns:</h3>
<ol>
The new Pool
</ol>
</dd>
<dt>
<a name = "Pool:eligible"></a>
<strong>Pool:eligible (e)</strong>
</dt>
<dd>
Checks if an Entity is eligible for the Pool.
<h3>Parameters:</h3>
<ul>
<li><span class="parameter">e</span>
The Entity to check
</li>
</ul>
<h3>Returns:</h3>
<ol>
True if the entity is eligible, false otherwise
</ol>
</dd>
</dl>
</div> <!-- id="content" -->
</div> <!-- id="main" -->
<div id="about">
<i>generated by <a href="http://github.com/stevedonovan/LDoc">LDoc 1.4.6</a></i>
<i style="float:right;">Last updated 2018-09-25 18:42:43 </i>
</div> <!-- id="about" -->
</div> <!-- id="container" -->
</body>
</html>

View file

@ -1,418 +0,0 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<head>
<title>Reference</title>
<link rel="stylesheet" href="../ldoc.css" type="text/css" />
</head>
<body>
<div id="container">
<div id="product">
<div id="product_logo"></div>
<div id="product_name"><big><b></b></big></div>
<div id="product_description"></div>
</div> <!-- id="product" -->
<div id="main">
<!-- Menu -->
<div id="navigation">
<br/>
<h1>Concord</h1>
<ul>
<li><a href="../index.html">Index</a></li>
</ul>
<h2>Contents</h2>
<ul>
<li><a href="#Functions">Functions</a></li>
</ul>
<h2>Modules</h2>
<ul class="nowrap">
<li><a href="../modules/component.html">component</a></li>
<li><a href="../modules/entity.html">entity</a></li>
<li><a href="../modules/init.html">init</a></li>
<li><a href="../modules/instance.html">instance</a></li>
<li><a href="../modules/list.html">list</a></li>
<li><a href="../modules/pool.html">pool</a></li>
<li><strong>system</strong></li>
</ul>
</div>
<div id="content">
<h1>Module <code>system</code></h1>
<p>System</p>
<p></p>
<h2><a href="#Functions">Functions</a></h2>
<table class="function_list">
<tr>
<td class="name" nowrap><a href="#System.new">System.new (...)</a></td>
<td class="summary">Creates a new System prototype.</td>
</tr>
<tr>
<td class="name" nowrap><a href="#System:__buildPool">System:__buildPool (baseFilter)</a></td>
<td class="summary">Builds a Pool for the System.</td>
</tr>
<tr>
<td class="name" nowrap><a href="#System:__check">System:__check (e)</a></td>
<td class="summary">Checks and applies an Entity to the System's pools.</td>
</tr>
<tr>
<td class="name" nowrap><a href="#System:__remove">System:__remove (e)</a></td>
<td class="summary">Removed an Entity from the System.</td>
</tr>
<tr>
<td class="name" nowrap><a href="#System:__tryAdd">System:__tryAdd (e)</a></td>
<td class="summary">Tries to add an Entity to the System.</td>
</tr>
<tr>
<td class="name" nowrap><a href="#System:__tryRemove">System:__tryRemove (e)</a></td>
<td class="summary">Tries to remove an Entity from the System.</td>
</tr>
<tr>
<td class="name" nowrap><a href="#System:getInstance">System:getInstance ()</a></td>
<td class="summary">Returns the Instance the System is in.</td>
</tr>
<tr>
<td class="name" nowrap><a href="#System:__has">System:__has (e)</a></td>
<td class="summary">Returns if the System has the Entity.</td>
</tr>
<tr>
<td class="name" nowrap><a href="#System:init">System:init (...)</a></td>
<td class="summary">Default callback for system initialization.</td>
</tr>
<tr>
<td class="name" nowrap><a href="#System:entityAdded">System:entityAdded (e)</a></td>
<td class="summary">Default callback for adding an Entity.</td>
</tr>
<tr>
<td class="name" nowrap><a href="#System:entityAddedTo">System:entityAddedTo (e, pool)</a></td>
<td class="summary">Default callback for adding an Entity to a pool.</td>
</tr>
<tr>
<td class="name" nowrap><a href="#System:entityRemoved">System:entityRemoved (e)</a></td>
<td class="summary">Default callback for removing an Entity.</td>
</tr>
<tr>
<td class="name" nowrap><a href="#System:entityRemovedFrom">System:entityRemovedFrom (e, pool)</a></td>
<td class="summary">Default callback for removing an Entity from a pool.</td>
</tr>
</table>
<br/>
<br/>
<h2 class="section-header "><a name="Functions"></a>Functions</h2>
<dl class="function">
<dt>
<a name = "System.new"></a>
<strong>System.new (...)</strong>
</dt>
<dd>
Creates a new System prototype.
<h3>Parameters:</h3>
<ul>
<li><span class="parameter">...</span>
Variable amounts of filters
</li>
</ul>
<h3>Returns:</h3>
<ol>
A new System prototype
</ol>
</dd>
<dt>
<a name = "System:__buildPool"></a>
<strong>System:__buildPool (baseFilter)</strong>
</dt>
<dd>
Builds a Pool for the System.
<h3>Parameters:</h3>
<ul>
<li><span class="parameter">baseFilter</span>
The 'raw' Filter
</li>
</ul>
<h3>Returns:</h3>
<ol>
A new Pool
</ol>
</dd>
<dt>
<a name = "System:__check"></a>
<strong>System:__check (e)</strong>
</dt>
<dd>
Checks and applies an Entity to the System's pools.
<h3>Parameters:</h3>
<ul>
<li><span class="parameter">e</span>
The Entity to check
</li>
</ul>
<h3>Returns:</h3>
<ol>
True if the Entity was added, false if it was removed. Nil if nothing happend
</ol>
</dd>
<dt>
<a name = "System:__remove"></a>
<strong>System:__remove (e)</strong>
</dt>
<dd>
Removed an Entity from the System.
<h3>Parameters:</h3>
<ul>
<li><span class="parameter">e</span>
The Entity to remove
</li>
</ul>
</dd>
<dt>
<a name = "System:__tryAdd"></a>
<strong>System:__tryAdd (e)</strong>
</dt>
<dd>
Tries to add an Entity to the System.
<h3>Parameters:</h3>
<ul>
<li><span class="parameter">e</span>
The Entity to add
</li>
</ul>
</dd>
<dt>
<a name = "System:__tryRemove"></a>
<strong>System:__tryRemove (e)</strong>
</dt>
<dd>
Tries to remove an Entity from the System.
<h3>Parameters:</h3>
<ul>
<li><span class="parameter">e</span>
The Entity to remove
</li>
</ul>
</dd>
<dt>
<a name = "System:getInstance"></a>
<strong>System:getInstance ()</strong>
</dt>
<dd>
Returns the Instance the System is in.
<h3>Returns:</h3>
<ol>
The Instance
</ol>
</dd>
<dt>
<a name = "System:__has"></a>
<strong>System:__has (e)</strong>
</dt>
<dd>
Returns if the System has the Entity.
<h3>Parameters:</h3>
<ul>
<li><span class="parameter">e</span>
The Entity to check for
</li>
</ul>
<h3>Returns:</h3>
<ol>
True if the System has the Entity. False otherwise
</ol>
</dd>
<dt>
<a name = "System:init"></a>
<strong>System:init (...)</strong>
</dt>
<dd>
Default callback for system initialization.
<h3>Parameters:</h3>
<ul>
<li><span class="parameter">...</span>
Varags
</li>
</ul>
</dd>
<dt>
<a name = "System:entityAdded"></a>
<strong>System:entityAdded (e)</strong>
</dt>
<dd>
Default callback for adding an Entity.
<h3>Parameters:</h3>
<ul>
<li><span class="parameter">e</span>
The Entity that was added
</li>
</ul>
</dd>
<dt>
<a name = "System:entityAddedTo"></a>
<strong>System:entityAddedTo (e, pool)</strong>
</dt>
<dd>
Default callback for adding an Entity to a pool.
<h3>Parameters:</h3>
<ul>
<li><span class="parameter">e</span>
The Entity that was added
</li>
<li><span class="parameter">pool</span>
The pool the Entity was added to
</li>
</ul>
</dd>
<dt>
<a name = "System:entityRemoved"></a>
<strong>System:entityRemoved (e)</strong>
</dt>
<dd>
Default callback for removing an Entity.
<h3>Parameters:</h3>
<ul>
<li><span class="parameter">e</span>
The Entity that was removed
</li>
</ul>
</dd>
<dt>
<a name = "System:entityRemovedFrom"></a>
<strong>System:entityRemovedFrom (e, pool)</strong>
</dt>
<dd>
Default callback for removing an Entity from a pool.
<h3>Parameters:</h3>
<ul>
<li><span class="parameter">e</span>
The Entity that was removed
</li>
<li><span class="parameter">pool</span>
The pool the Entity was removed from
</li>
</ul>
</dd>
</dl>
</div> <!-- id="content" -->
</div> <!-- id="main" -->
<div id="about">
<i>generated by <a href="http://github.com/stevedonovan/LDoc">LDoc 1.4.6</a></i>
<i style="float:right;">Last updated 2018-09-25 18:42:43 </i>
</div> <!-- id="about" -->
</div> <!-- id="container" -->
</body>
</html>

181
docs/modules/systems.html Normal file
View file

@ -0,0 +1,181 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<head>
<title>Reference</title>
<link rel="stylesheet" href="../ldoc.css" type="text/css" />
</head>
<body>
<div id="container">
<div id="product">
<div id="product_logo"></div>
<div id="product_name"><big><b></b></big></div>
<div id="product_description"></div>
</div> <!-- id="product" -->
<div id="main">
<!-- Menu -->
<div id="navigation">
<br/>
<h1>Concord</h1>
<ul>
<li><a href="../index.html">Index</a></li>
</ul>
<h2>Contents</h2>
<ul>
<li><a href="#Functions">Functions</a></li>
</ul>
<h2>Modules</h2>
<ul class="nowrap">
<li><a href="../modules/Assemblages.html">Assemblages</a></li>
<li><a href="../modules/Components.html">Components</a></li>
<li><a href="../modules/Concord.html">Concord</a></li>
<li><strong>Systems</strong></li>
<li><a href="../modules/type.html">type</a></li>
<li><a href="../modules/utils.html">utils</a></li>
<li><a href="../modules/worlds.html">worlds</a></li>
</ul>
<h2>Classes</h2>
<ul class="nowrap">
<li><a href="../classes/Assemblage.html">Assemblage</a></li>
<li><a href="../classes/Component.html">Component</a></li>
<li><a href="../classes/Entity.html">Entity</a></li>
<li><a href="../classes/List.html">List</a></li>
<li><a href="../classes/Pool.html">Pool</a></li>
<li><a href="../classes/System.html">System</a></li>
<li><a href="../classes/World.html">World</a></li>
</ul>
</div>
<div id="content">
<h1>Module <code>Systems</code></h1>
<p>Container for registered SystemClasses</p>
<p></p>
<h2><a href="#Functions">Functions</a></h2>
<table class="function_list">
<tr>
<td class="name" nowrap><a href="#register">register (name, systemClass)</a></td>
<td class="summary">Registers a SystemClass.</td>
</tr>
<tr>
<td class="name" nowrap><a href="#has">has (name)</a></td>
<td class="summary">Returns true if the containter has the SystemClass with the name</td>
</tr>
<tr>
<td class="name" nowrap><a href="#get">get (name)</a></td>
<td class="summary">Returns the SystemClass with the name</td>
</tr>
</table>
<br/>
<br/>
<h2 class="section-header "><a name="Functions"></a>Functions</h2>
<dl class="function">
<dt>
<a name = "register"></a>
<strong>register (name, systemClass)</strong>
</dt>
<dd>
Registers a SystemClass.
<h3>Parameters:</h3>
<ul>
<li><span class="parameter">name</span>
<span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.4">string</a></span>
Name to register under
</li>
<li><span class="parameter">systemClass</span>
<span class="types"><a class="type" href="../classes/System.html#">System</a></span>
SystemClass to register
</li>
</ul>
</dd>
<dt>
<a name = "has"></a>
<strong>has (name)</strong>
</dt>
<dd>
Returns true if the containter has the SystemClass with the name
<h3>Parameters:</h3>
<ul>
<li><span class="parameter">name</span>
<span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.4">string</a></span>
Name of the SystemClass to check
</li>
</ul>
<h3>Returns:</h3>
<ol>
<span class="types"><span class="type">boolean</span></span>
</ol>
</dd>
<dt>
<a name = "get"></a>
<strong>get (name)</strong>
</dt>
<dd>
Returns the SystemClass with the name
<h3>Parameters:</h3>
<ul>
<li><span class="parameter">name</span>
<span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.4">string</a></span>
Name of the SystemClass to get
</li>
</ul>
<h3>Returns:</h3>
<ol>
SystemClass with the name
</ol>
</dd>
</dl>
</div> <!-- id="content" -->
</div> <!-- id="main" -->
<div id="about">
<i>generated by <a href="http://github.com/stevedonovan/LDoc">LDoc 1.4.6</a></i>
<i style="float:right;">Last updated 2020-01-04 10:27:07 </i>
</div> <!-- id="about" -->
</div> <!-- id="container" -->
</body>
</html>

268
docs/modules/type.html Normal file
View file

@ -0,0 +1,268 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<head>
<title>Reference</title>
<link rel="stylesheet" href="../ldoc.css" type="text/css" />
</head>
<body>
<div id="container">
<div id="product">
<div id="product_logo"></div>
<div id="product_name"><big><b></b></big></div>
<div id="product_description"></div>
</div> <!-- id="product" -->
<div id="main">
<!-- Menu -->
<div id="navigation">
<br/>
<h1>Concord</h1>
<ul>
<li><a href="../index.html">Index</a></li>
</ul>
<h2>Contents</h2>
<ul>
<li><a href="#Functions">Functions</a></li>
</ul>
<h2>Modules</h2>
<ul class="nowrap">
<li><a href="../modules/Components.html">Components</a></li>
<li><a href="../modules/Concord.html">Concord</a></li>
<li><strong>type</strong></li>
<li><a href="../modules/utils.html">utils</a></li>
</ul>
<h2>Classes</h2>
<ul class="nowrap">
<li><a href="../classes/Component.html">Component</a></li>
<li><a href="../classes/Entity.html">Entity</a></li>
<li><a href="../classes/List.html">List</a></li>
<li><a href="../classes/Pool.html">Pool</a></li>
<li><a href="../classes/System.html">System</a></li>
<li><a href="../classes/World.html">World</a></li>
</ul>
</div>
<div id="content">
<h1>Module <code>type</code></h1>
<p>Type
Helper module to do easy type checking for Concord types</p>
<p></p>
<h2><a href="#Functions">Functions</a></h2>
<table class="function_list">
<tr>
<td class="name" nowrap><a href="#Type.isEntity">Type.isEntity (t)</a></td>
<td class="summary">Returns if object is an Entity.</td>
</tr>
<tr>
<td class="name" nowrap><a href="#Type.isComponentClass">Type.isComponentClass (t)</a></td>
<td class="summary">Returns if object is a ComponentClass.</td>
</tr>
<tr>
<td class="name" nowrap><a href="#Type.isComponent">Type.isComponent (t)</a></td>
<td class="summary">Returns if object is a Component.</td>
</tr>
<tr>
<td class="name" nowrap><a href="#Type.isSystemClass">Type.isSystemClass (t)</a></td>
<td class="summary">Returns if object is a SystemClass.</td>
</tr>
<tr>
<td class="name" nowrap><a href="#Type.isSystem">Type.isSystem (t)</a></td>
<td class="summary">Returns if object is a System.</td>
</tr>
<tr>
<td class="name" nowrap><a href="#Type.isWorld">Type.isWorld (t)</a></td>
<td class="summary">Returns if object is a World.</td>
</tr>
</table>
<br/>
<br/>
<h2 class="section-header "><a name="Functions"></a>Functions</h2>
<dl class="function">
<dt>
<a name = "Type.isEntity"></a>
<strong>Type.isEntity (t)</strong>
</dt>
<dd>
Returns if object is an Entity.
<h3>Parameters:</h3>
<ul>
<li><span class="parameter">t</span>
Object to check
</li>
</ul>
<h3>Returns:</h3>
<ol>
<span class="types"><span class="type">boolean</span></span>
</ol>
</dd>
<dt>
<a name = "Type.isComponentClass"></a>
<strong>Type.isComponentClass (t)</strong>
</dt>
<dd>
Returns if object is a ComponentClass.
<h3>Parameters:</h3>
<ul>
<li><span class="parameter">t</span>
Object to check
</li>
</ul>
<h3>Returns:</h3>
<ol>
<span class="types"><span class="type">boolean</span></span>
</ol>
</dd>
<dt>
<a name = "Type.isComponent"></a>
<strong>Type.isComponent (t)</strong>
</dt>
<dd>
Returns if object is a Component.
<h3>Parameters:</h3>
<ul>
<li><span class="parameter">t</span>
Object to check
</li>
</ul>
<h3>Returns:</h3>
<ol>
<span class="types"><span class="type">boolean</span></span>
</ol>
</dd>
<dt>
<a name = "Type.isSystemClass"></a>
<strong>Type.isSystemClass (t)</strong>
</dt>
<dd>
Returns if object is a SystemClass.
<h3>Parameters:</h3>
<ul>
<li><span class="parameter">t</span>
Object to check
</li>
</ul>
<h3>Returns:</h3>
<ol>
<span class="types"><span class="type">boolean</span></span>
</ol>
</dd>
<dt>
<a name = "Type.isSystem"></a>
<strong>Type.isSystem (t)</strong>
</dt>
<dd>
Returns if object is a System.
<h3>Parameters:</h3>
<ul>
<li><span class="parameter">t</span>
Object to check
</li>
</ul>
<h3>Returns:</h3>
<ol>
<span class="types"><span class="type">boolean</span></span>
</ol>
</dd>
<dt>
<a name = "Type.isWorld"></a>
<strong>Type.isWorld (t)</strong>
</dt>
<dd>
Returns if object is a World.
<h3>Parameters:</h3>
<ul>
<li><span class="parameter">t</span>
Object to check
</li>
</ul>
<h3>Returns:</h3>
<ol>
<span class="types"><span class="type">boolean</span></span>
</ol>
</dd>
</dl>
</div> <!-- id="content" -->
</div> <!-- id="main" -->
<div id="about">
<i>generated by <a href="http://github.com/stevedonovan/LDoc">LDoc 1.4.6</a></i>
<i style="float:right;">Last updated 2020-08-18 15:20:32 </i>
</div> <!-- id="about" -->
</div> <!-- id="container" -->
</body>
</html>

150
docs/modules/utils.html Normal file
View file

@ -0,0 +1,150 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<head>
<title>Reference</title>
<link rel="stylesheet" href="../ldoc.css" type="text/css" />
</head>
<body>
<div id="container">
<div id="product">
<div id="product_logo"></div>
<div id="product_name"><big><b></b></big></div>
<div id="product_description"></div>
</div> <!-- id="product" -->
<div id="main">
<!-- Menu -->
<div id="navigation">
<br/>
<h1>Concord</h1>
<ul>
<li><a href="../index.html">Index</a></li>
</ul>
<h2>Contents</h2>
<ul>
<li><a href="#Functions">Functions</a></li>
</ul>
<h2>Modules</h2>
<ul class="nowrap">
<li><a href="../modules/Components.html">Components</a></li>
<li><a href="../modules/Concord.html">Concord</a></li>
<li><a href="../modules/type.html">type</a></li>
<li><strong>utils</strong></li>
</ul>
<h2>Classes</h2>
<ul class="nowrap">
<li><a href="../classes/Component.html">Component</a></li>
<li><a href="../classes/Entity.html">Entity</a></li>
<li><a href="../classes/List.html">List</a></li>
<li><a href="../classes/Pool.html">Pool</a></li>
<li><a href="../classes/System.html">System</a></li>
<li><a href="../classes/World.html">World</a></li>
</ul>
</div>
<div id="content">
<h1>Module <code>utils</code></h1>
<p>Utils
Helper module for misc operations</p>
<p></p>
<h2><a href="#Functions">Functions</a></h2>
<table class="function_list">
<tr>
<td class="name" nowrap><a href="#Utils.shallowCopy">Utils.shallowCopy (orig, target)</a></td>
<td class="summary">Does a shallow copy of a table and appends it to a target table.</td>
</tr>
<tr>
<td class="name" nowrap><a href="#Utils.loadNamespace">Utils.loadNamespace (pathOrFiles, namespace)</a></td>
<td class="summary">Requires files and puts them in a table.</td>
</tr>
</table>
<br/>
<br/>
<h2 class="section-header "><a name="Functions"></a>Functions</h2>
<dl class="function">
<dt>
<a name = "Utils.shallowCopy"></a>
<strong>Utils.shallowCopy (orig, target)</strong>
</dt>
<dd>
Does a shallow copy of a table and appends it to a target table.
<h3>Parameters:</h3>
<ul>
<li><span class="parameter">orig</span>
Table to copy
</li>
<li><span class="parameter">target</span>
Table to append to
</li>
</ul>
</dd>
<dt>
<a name = "Utils.loadNamespace"></a>
<strong>Utils.loadNamespace (pathOrFiles, namespace)</strong>
</dt>
<dd>
Requires files and puts them in a table.
Accepts a table of paths to Lua files: {"path/to/file_1", "path/to/another/file_2", "etc"}
Accepts a path to a directory with Lua files: "my_files/here"
<h3>Parameters:</h3>
<ul>
<li><span class="parameter">pathOrFiles</span>
The table of paths or a path to a directory.
</li>
<li><span class="parameter">namespace</span>
A table that will hold the required files
</li>
</ul>
<h3>Returns:</h3>
<ol>
<span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.5">table</a></span>
The namespace table
</ol>
</dd>
</dl>
</div> <!-- id="content" -->
</div> <!-- id="main" -->
<div id="about">
<i>generated by <a href="http://github.com/stevedonovan/LDoc">LDoc 1.4.6</a></i>
<i style="float:right;">Last updated 2020-08-18 15:20:32 </i>
</div> <!-- id="about" -->
</div> <!-- id="container" -->
</body>
</html>

181
docs/modules/worlds.html Normal file
View file

@ -0,0 +1,181 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<head>
<title>Reference</title>
<link rel="stylesheet" href="../ldoc.css" type="text/css" />
</head>
<body>
<div id="container">
<div id="product">
<div id="product_logo"></div>
<div id="product_name"><big><b></b></big></div>
<div id="product_description"></div>
</div> <!-- id="product" -->
<div id="main">
<!-- Menu -->
<div id="navigation">
<br/>
<h1>Concord</h1>
<ul>
<li><a href="../index.html">Index</a></li>
</ul>
<h2>Contents</h2>
<ul>
<li><a href="#Functions">Functions</a></li>
</ul>
<h2>Modules</h2>
<ul class="nowrap">
<li><a href="../modules/Assemblages.html">Assemblages</a></li>
<li><a href="../modules/Components.html">Components</a></li>
<li><a href="../modules/Concord.html">Concord</a></li>
<li><a href="../modules/Systems.html">Systems</a></li>
<li><a href="../modules/type.html">type</a></li>
<li><a href="../modules/utils.html">utils</a></li>
<li><strong>worlds</strong></li>
</ul>
<h2>Classes</h2>
<ul class="nowrap">
<li><a href="../classes/Assemblage.html">Assemblage</a></li>
<li><a href="../classes/Component.html">Component</a></li>
<li><a href="../classes/Entity.html">Entity</a></li>
<li><a href="../classes/List.html">List</a></li>
<li><a href="../classes/Pool.html">Pool</a></li>
<li><a href="../classes/System.html">System</a></li>
<li><a href="../classes/World.html">World</a></li>
</ul>
</div>
<div id="content">
<h1>Module <code>worlds</code></h1>
<p>Worlds
Container for registered Worlds</p>
<p></p>
<h2><a href="#Functions">Functions</a></h2>
<table class="function_list">
<tr>
<td class="name" nowrap><a href="#Worlds.register">Worlds.register (name, world)</a></td>
<td class="summary">Registers a World.</td>
</tr>
<tr>
<td class="name" nowrap><a href="#Worlds.has">Worlds.has (name)</a></td>
<td class="summary">Returns true if the containter has the World with the name</td>
</tr>
<tr>
<td class="name" nowrap><a href="#Worlds.get">Worlds.get (name)</a></td>
<td class="summary">Returns the World with the name</td>
</tr>
</table>
<br/>
<br/>
<h2 class="section-header "><a name="Functions"></a>Functions</h2>
<dl class="function">
<dt>
<a name = "Worlds.register"></a>
<strong>Worlds.register (name, world)</strong>
</dt>
<dd>
Registers a World.
<h3>Parameters:</h3>
<ul>
<li><span class="parameter">name</span>
<span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.4">string</a></span>
Name to register under
</li>
<li><span class="parameter">world</span>
World to register
</li>
</ul>
</dd>
<dt>
<a name = "Worlds.has"></a>
<strong>Worlds.has (name)</strong>
</dt>
<dd>
Returns true if the containter has the World with the name
<h3>Parameters:</h3>
<ul>
<li><span class="parameter">name</span>
<span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.4">string</a></span>
Name of the World to check
</li>
</ul>
<h3>Returns:</h3>
<ol>
<span class="types"><span class="type">boolean</span></span>
</ol>
</dd>
<dt>
<a name = "Worlds.get"></a>
<strong>Worlds.get (name)</strong>
</dt>
<dd>
Returns the World with the name
<h3>Parameters:</h3>
<ul>
<li><span class="parameter">name</span>
<span class="types"><a class="type" href="https://www.lua.org/manual/5.1/manual.html#5.4">string</a></span>
Name of the World to get
</li>
</ul>
<h3>Returns:</h3>
<ol>
World with the name
</ol>
</dd>
</dl>
</div> <!-- id="content" -->
</div> <!-- id="main" -->
<div id="about">
<i>generated by <a href="http://github.com/stevedonovan/LDoc">LDoc 1.4.6</a></i>
<i style="float:right;">Last updated 2020-01-04 10:27:07 </i>
</div> <!-- id="about" -->
</div> <!-- id="container" -->
</body>
</html>

View file

@ -1,8 +0,0 @@
local PATH = (...):gsub('%.[^%.]+$', '')
local Concord = require("lib").init({
useEvents = true
})
local C = require(PATH..".src.components")
local S = require(PATH..".src.systems")

View file

@ -1,5 +0,0 @@
local PATH = (...):gsub('%.init$', '')
return {
}

View file

@ -1,118 +0,0 @@
local Concord = require("lib").init({
useEvents = true
})
local Entity = Concord.entity
local Component = Concord.component
local System = Concord.system
local Game = Concord.instance()
Concord.addInstance(Game)
local Position = Component(function(e, x, y)
e.x = x
e.y = y
end)
local Rectangle = Component(function(e, w, h)
e.w = w
e.h = h
end)
local Circle = Component(function(e, r)
e.r = r
end)
local Color = Component(function(e, r, g, b, a)
e.r = r
e.g = g
e.b = b
e.a = a
end)
local RectangleRenderer = System({Position, Rectangle})
function RectangleRenderer:draw()
local e
for i = 1, self.pool.size do
e = self.pool:get(i)
local position = e:get(Position)
local rectangle = e:get(Rectangle)
local color = e:get(Color)
love.graphics.setColor(255, 255, 255)
if color then
love.graphics.setColor(color.r, color.g, color.b, color.a)
end
love.graphics.rectangle("fill", position.x, position.y, rectangle.w, rectangle.h)
end
end
local CircleRenderer = System({Position, Circle})
function CircleRenderer:draw()
local e
for i = 1, self.pool.size do
e = self.pool:get(i)
local position = e:get(Position)
local circle = e:get(Circle)
local color = e:get(Color)
love.graphics.setColor(255, 255, 255)
if color then
love.graphics.setColor(color.r, color.g, color.b, color.a)
end
love.graphics.circle("fill", position.x, position.y, circle.r)
end
end
local RandomRemover = System({})
function RandomRemover:init()
self.time = 0
end
function RandomRemover:update(dt)
self.time = self.time + dt
if self.time >= 0.25 then
self.time = 0
if self.pool.size > 0 then
local i = love.math.random(1, self.pool.size)
self.pool:get(i):destroy()
end
end
love.window.setTitle(love.timer.getFPS())
end
Game:addSystem(RandomRemover(), "update")
Game:addSystem(RectangleRenderer(), "draw")
Game:addSystem(CircleRenderer(), "draw")
for i = 1, 100 do
local e = Entity()
e:give(Position, love.math.random(0, 700), love.math.random(0, 700))
e:give(Rectangle, love.math.random(5, 20), love.math.random(5, 20))
if love.math.random(0, 1) == 0 then
e:give(Color, love.math.random(), love.math.random(), love.math.random(), 1)
end
Game:addEntity(e)
end
for i = 1, 100 do
local e = Entity()
e:give(Position, love.math.random(0, 700), love.math.random(0, 700))
e:give(Circle, love.math.random(5, 20))
if love.math.random(0, 1) == 0 then
e:give(Color, love.math.random(), love.math.random(), love.math.random(), 1)
end
Game:addEntity(e)
end

View file

@ -1,5 +1,3 @@
local PATH = (...):gsub('%.init$', '')
return {
}
return require(PATH..".concord")

View file

@ -1,37 +0,0 @@
--- Component
local Component = {}
Component.__index = Component
--- Creates a new Component.
-- @param populate A function that populates the Bag with values
-- @return A Component object
function Component.new(populate)
local component = setmetatable({
__populate = populate,
__isComponent = true,
}, Component)
component.__mt = {__index = component}
return component
end
--- Creates and initializes a new Bag.
-- @param ... The values passed to the populate function
-- @return A new initialized Bag
function Component:__initialize(...)
if self.__populate then
local bag = setmetatable({}, self.__mt)
self.__populate(bag, ...)
return bag
end
return true
end
return setmetatable(Component, {
__call = function(_, ...) return Component.new(...) end,
})

View file

@ -1,104 +0,0 @@
--- Entity
local PATH = (...):gsub('%.[^%.]+$', '')
local Type = require(PATH..".type")
local List = require(PATH..".list")
local Entity = {}
Entity.__index = Entity
--- Creates and initializes a new Entity.
-- @return A new Entity
function Entity.new()
local e = setmetatable({
components = {},
removed = {},
instances = List(),
__isEntity = true,
}, Entity)
return e
end
--- Gives an Entity a component with values.
-- @param component The Component to add
-- @param ... The values passed to the Component
-- @return self
function Entity:give(component, ...)
if not Type.isComponent(component) then
error("bad argument #1 to 'Entity:give' (Component expected, got "..type(component)..")", 2)
end
local comp = component:__initialize(...)
self.components[component] = comp
self[component] = comp
return self
end
--- Removes a component from an Entity.
-- @param component The Component to remove
-- @return self
function Entity:remove(component)
if not Type.isComponent(component) then
error("bad argument #1 to 'Entity:remove' (Component expected, got "..type(component)..")")
end
self.removed[component] = true
return self
end
--- Checks the Entity against the pools again.
-- @return self
function Entity:apply()
for i = 1, self.instances.size do
self.instances:get(i):checkEntity(self)
end
for component, _ in pairs(self.removed) do
self.components[component] = nil
self[component] = nil
self.removed[component] = nil
end
return self
end
--- Destroys the Entity.
-- @return self
function Entity:destroy()
for i = 1, self.instances.size do
self.instances:get(i):removeEntity(self)
end
return self
end
--- Gets a Component from the Entity.
-- @param component The Component to get
-- @return The Bag from the Component
function Entity:get(component)
if not Type.isComponent(component) then
error("bad argument #1 to 'Entity:get' (Component expected, got "..type(component)..")")
end
return self.components[component]
end
--- Returns true if the Entity has the Component.
-- @param component The Component to check against
-- @return True if the entity has the Bag. False otherwise
function Entity:has(component)
if not Type.isComponent(component) then
error("bad argument #1 to 'Entity:has' (Component expected, got "..type(component)..")")
end
return self.components[component] ~= nil
end
return setmetatable(Entity, {
__call = function(_, ...) return Entity.new(...) end,
})

View file

@ -1,75 +0,0 @@
--- init
local PATH = (...):gsub('%.init$', '')
local Type = require(PATH..".type")
local Concord = {
_VERSION = "1.0",
_DESCRIPTION = "A feature-complete ECS library",
_LICENCE = [[
MIT LICENSE
Copyright (c) 2018 Justin van der Leij / Tjakka5
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
]]
}
--- Initializes the library with some optional settings
-- @param settings Table of settings: {
-- useEvents Flag to overwrite love.run and use events. Defaults to false
-- }
-- @return Concord
function Concord.init(settings)
Concord.entity = require(PATH..".entity")
Concord.component = require(PATH..".component")
Concord.system = require(PATH..".system")
Concord.instance = require(PATH..".instance")
if settings and settings.useEvents then
Concord.instances = {}
Concord.addInstance = function(instance)
if not Type.isInstance(instance) then
error("bad argument #1 to 'Concord.addInstance' (Instance expected, got "..type(instance)..")", 2)
end
table.insert(Concord.instances, instance)
end
Concord.removeInstance = function(instance)
if not Type.isInstance(instance) then
error("bad argument #1 to 'Concord.addInstance' (Instance expected, got "..type(instance)..")", 2)
end
for i, instance in ipairs(Concord.instances) do
table.remove(Concord.instances, i)
break
end
end
love.run = require(PATH..".run")
end
return Concord
end
return Concord

View file

@ -1,259 +0,0 @@
--- Instance
local PATH = (...):gsub('%.[^%.]+$', '')
local Entity = require(PATH..".entity")
local System = require(PATH..".system")
local Type = require(PATH..".type")
local List = require(PATH..".list")
local Instance = {}
Instance.__index = Instance
--- Creates a new Instance.
-- @return The new instance
function Instance.new()
local instance = setmetatable({
entities = List(),
systems = List(),
events = {},
removed = {},
toRemove = nil,
__isInstance = true,
}, Instance)
return instance
end
--- Adds an Entity to the Instance.
-- @param e The Entity to add
-- @return self
function Instance:addEntity(e)
if not Type.isEntity(e) then
error("bad argument #1 to 'Instance:addEntity' (Entity expected, got "..type(e)..")", 2)
end
self:onEntityAdded(e)
e.instances:add(self)
self.entities:add(e)
self:checkEntity(e)
return self
end
--- Checks an Entity against all the systems in the Instance.
-- @param e The Entity to check
-- @return self
function Instance:checkEntity(e)
if not Type.isEntity(e) then
error("bad argument #1 to 'Instance:checkEntity' (Entity expected, got "..type(e)..")", 2)
end
for i = 1, self.systems.size do
self.systems:get(i):__check(e)
end
return self
end
--- Marks an Entity as removed from the Instance.
-- @param e The Entity to mark
-- @return self
function Instance:removeEntity(e)
if not Type.isEntity(e) then
error("bad argument #1 to 'Instance:removeEntity' (Entity expected, got "..type(e)..")", 2)
end
self.removed[#self.removed + 1] = e
return self
end
--- Completely removes all marked Entities in the Instance.
-- @return self
function Instance:flush()
while #self.removed > 0 do
self.toRemove = self.removed
self.removed = {}
for i = 1, #self.toRemove do
local e = self.toRemove[i]
e.instances:remove(self)
self.entities:remove(e)
for i = 1, self.systems.size do
self.systems:get(i):__remove(e)
end
self:onEntityRemoved(e)
end
end
return self
end
--- Adds a System to the Instance.
-- @param system The System to add
-- @param eventName The Event to register to
-- @param callback The function name to call. Defaults to eventName
-- @param enabled If the system is enabled. Defaults to true
-- @return self
function Instance:addSystem(system, eventName, callback, enabled)
if not Type.isSystem(system) then
error("bad argument #1 to 'Instance:addSystem' (System expected, got "..type(system)..")", 2)
end
if system.__instance and system.__instance ~= self then
error("System already in instance '" ..tostring(system.__instance).."'")
end
if not self.systems:has(system) then
self.systems:add(system)
system.__instance = self
system:addedTo(self)
end
if eventName then
self.events[eventName] = self.events[eventName] or {}
local i = #self.events[eventName] + 1
self.events[eventName][i] = {
system = system,
callback = callback or eventName,
enabled = enabled == nil or enabled,
}
if enabled == nil or enabled then
system:enabledCallback(callback or eventName)
end
end
local e
for i = 1, self.entities.size do
e = self.entities:get(i)
self:checkEntity(e)
end
return self
end
--- Enables a System in the Instance.
-- @param system The System to enable
-- @param eventName The Event it was registered to
-- @param callback The callback it was registered with. Defaults to eventName
-- @return self
function Instance:enableSystem(system, eventName, callback)
if not Type.isSystem(system) then
error("bad argument #1 to 'Instance:enableSystem' (System expected, got "..type(system)..")", 2)
end
return self:setSystem(system, eventName, callback, true)
end
--- Disables a System in the Instance.
-- @param system The System to disable
-- @param eventName The Event it was registered to
-- @param callback The callback it was registered with. Defaults to eventName
-- @return self
function Instance:disableSystem(system, eventName, callback)
if not Type.isSystem(system) then
error("bad argument #1 to 'Instance:disableSystem' (System expected, got "..type(system)..")", 2)
end
return self:setSystem(system, eventName, callback, false)
end
--- Sets a System 'enable' in the Instance.
-- @param system The System to set
-- @param eventName The Event it was registered to
-- @param callback The callback it was registered with. Defaults to eventName
-- @param enable The state to set it to
-- @return self
function Instance:setSystem(system, eventName, callback, enable)
if not Type.isSystem(system) then
error("bad argument #1 to 'Instance:setSystem' (System expected, got "..type(system)..")", 2)
end
callback = callback or eventName
if callback then
local listeners = self.events[eventName]
if listeners then
for i = 1, #listeners do
local listener = listeners[i]
if listener.system == system and listener.callback == callback then
if enable and not listener.enabled then
system:enabledCallback(callback)
elseif not enable and listener.enabled then
system:disabledCallback(callback)
end
listener.enabled = enable
break
end
end
end
end
return self
end
--- Emits an Event in the Instance.
-- @param eventName The Event that should be emitted
-- @param ... Parameters passed to listeners
-- @return self
function Instance:emit(eventName, ...)
if not eventName or type(eventName) ~= "string" then
error("bad argument #1 to 'Instance:emit' (String expected, got "..type(eventName)..")")
end
self:flush()
local listeners = self.events[eventName]
if listeners then
for i = 1, #listeners do
local listener = listeners[i]
if listener.enabled then
listener.system[listener.callback](listener.system, ...)
end
end
end
return self
end
--- Removes all entities from the Instance
-- @return self
function Instance:clear()
for i = 1, self.entities.size do
self.entities:get(i):destroy()
end
self:flush()
return self
end
--- Default callback for adding an Entity.
-- @param e The Entity that was added
function Instance:onEntityAdded(e)
end
--- Default callback for removing an Entity.
-- @param e The Entity that was removed
function Instance:onEntityRemoved(e)
end
return setmetatable(Instance, {
__call = function(_, ...) return Instance.new(...) end,
})

View file

@ -1,78 +0,0 @@
--- List
local List = {}
local mt = {__index = List}
--- Creates a new List.
-- @return A new list
function List.new()
return setmetatable({
objects = {},
pointers = {},
size = 0,
}, mt)
end
--- Clears the List completely.
-- @return self
function List:clear()
self.objects = {}
self.pointers = {}
self.size = 0
return self
end
--- Adds an object to the List.
-- @param obj The object to add
-- @return self
function List:add(obj)
local size = self.size + 1
self.objects[size] = obj
self.pointers[obj] = size
self.size = size
return self
end
--- Removes an object from the List.
-- @param obj The object to remove
-- @return self
function List:remove(obj)
local index = self.pointers[obj]
if not index then return end
local size = self.size
if index == size then
self.objects[size] = nil
else
local other = self.objects[size]
self.objects[index] = other
self.pointers[other] = index
self.objects[size] = nil
end
self.pointers[obj] = nil
self.size = size - 1
end
--- Gets an object by numerical index.
-- @param index The index to look at
-- @return The object at the index
function List:get(index)
return self.objects[index]
end
--- Gets if the List has the object.
-- @param obj The object to search for
-- true if the list has the object, false otherwise
function List:has(obj)
return self.pointers[obj] and true
end
return setmetatable(List, {
__call = function() return List.new() end,
})

View file

@ -1,41 +0,0 @@
--- Pool
local PATH = (...):gsub('%.[^%.]+$', '')
local List = require(PATH..".list")
local Pool = {}
Pool.__index = Pool
--- Creates a new Pool
-- @param name Identifier for the Pool.
-- @param filter Table containing the required Components
-- @return The new Pool
function Pool.new(name, filter)
local pool = setmetatable(List(), Pool)
pool.name = name
pool.filter = filter
pool.__isPool = true
return pool
end
--- Checks if an Entity is eligible for the Pool.
-- @param e The Entity to check
-- @return True if the entity is eligible, false otherwise
function Pool:eligible(e)
for _, component in ipairs(self.filter) do
if not e.components[component] or e.removed[component] then
return false
end
end
return true
end
return setmetatable(Pool, {
__index = List,
__call = function(_, ...) return Pool.new(...) end,
})

View file

@ -1,55 +0,0 @@
local PATH = (...):gsub('%.[^%.]+$', '')
local Concord = require(PATH)
return function()
if love.math then
love.math.setRandomSeed(os.time())
love.timer.step()
end
for _, instance in ipairs(Concord.instances) do
instance:emit("load", arg)
end
if love.timer then love.timer.step() end
local dt = 0
return function()
if love.event then
love.event.pump()
for name, a, b, c, d, e, f in love.event.poll() do
for _, instance in ipairs(Concord.instances) do
instance:emit(name, a, b, c, d, e, f)
end
if name == "quit" then
return a or 0
end
end
end
if love.timer then
love.timer.step()
dt = love.timer.getDelta()
end
for _, instance in ipairs(Concord.instances) do
instance:emit("update", dt)
end
if love.graphics and love.graphics.isActive() then
love.graphics.clear(love.graphics.getBackgroundColor())
love.graphics.origin()
for _, instance in ipairs(Concord.instances) do
instance:emit("draw")
end
love.graphics.present()
end
if love.timer then love.timer.sleep(0.001) end
end
end

View file

@ -1,184 +0,0 @@
--- System
local PATH = (...):gsub('%.[^%.]+$', '')
local Component = require(PATH..".component")
local Pool = require(PATH..".pool")
local System = {}
System.mt = {
__index = System,
__call = function(systemProto, ...)
local system = setmetatable({
__all = {},
__pools = {},
__instance = nil,
__isSystem = true,
}, systemProto)
for _, filter in pairs(systemProto.__filter) do
local pool = system:__buildPool(filter)
if not system[pool.name] then
system[pool.name] = pool
system.__pools[#system.__pools + 1] = pool
else
error("Pool with name '"..pool.name.."' already exists.")
end
end
system:init(...)
return system
end,
}
--- Creates a new System prototype.
-- @param ... Variable amounts of filters
-- @return A new System prototype
function System.new(...)
local systemProto = setmetatable({
__filter = {...},
}, System.mt)
systemProto.__index = systemProto
return systemProto
end
--- Builds a Pool for the System.
-- @param baseFilter The 'raw' Filter
-- @return A new Pool
function System:__buildPool(baseFilter)
local name = "pool"
local filter = {}
for i, v in ipairs(baseFilter) do
if type(v) == "table" then
filter[#filter + 1] = v
elseif type(v) == "string" then
name = v
end
end
return Pool(name, filter)
end
--- Checks and applies an Entity to the System's pools.
-- @param e The Entity to check
-- @return True if the Entity was added, false if it was removed. Nil if nothing happend
function System:__check(e)
local systemHas = self:__has(e)
for _, pool in ipairs(self.__pools) do
local poolHas = pool:has(e)
local eligible = pool:eligible(e)
if not poolHas and eligible then
pool:add(e)
self:entityAddedTo(e, pool)
self:__tryAdd(e)
elseif poolHas and not eligible then
pool:remove(e)
self:entityRemovedFrom(e, pool)
self:__tryRemove(e)
end
end
end
--- Removed an Entity from the System.
-- @param e The Entity to remove
function System:__remove(e)
if self:__has(e) then
for _, pool in ipairs(self.__pools) do
if pool:has(e) then
pool:remove(e)
self:entityRemovedFrom(e, pool)
end
end
self.__all[e] = nil
self:entityRemoved(e)
end
end
--- Tries to add an Entity to the System.
-- @param e The Entity to add
function System:__tryAdd(e)
if not self:__has(e) then
self.__all[e] = 0
self:entityAdded(e)
end
self.__all[e] = self.__all[e] + 1
end
--- Tries to remove an Entity from the System.
-- @param e The Entity to remove
function System:__tryRemove(e)
if self:__has(e) then
self.__all[e] = self.__all[e] - 1
if self.__all[e] == 0 then
self.__all[e] = nil
self:entityRemoved(e)
end
end
end
--- Returns the Instance the System is in.
-- @return The Instance
function System:getInstance()
return self.__instance
end
--- Returns if the System has the Entity.
-- @param e The Entity to check for
-- @return True if the System has the Entity. False otherwise
function System:__has(e)
return self.__all[e] and true
end
--- Default callback for system initialization.
-- @param ... Varags
function System:init(...)
end
--- Default callback for adding an Entity.
-- @param e The Entity that was added
function System:entityAdded(e)
end
--- Default callback for adding an Entity to a pool.
-- @param e The Entity that was added
-- @param pool The pool the Entity was added to
function System:entityAddedTo(e, pool)
end
--- Default callback for removing an Entity.
-- @param e The Entity that was removed
function System:entityRemoved(e)
end
--- Default callback for removing an Entity from a pool.
-- @param e The Entity that was removed
-- @param pool The pool the Entity was removed from
function System:entityRemovedFrom(e, pool)
end
-- Default callback for when the System is added to an Instance.
-- @param instance The Instance the System was added to
function System:addedTo(instance)
end
-- Default callback for when a System's callback is enabled.
-- @param callbackName The name of the callback that was enabled
function System:enabledCallback(callbackName)
end
-- Default callback for when a System's callback is disabled.
-- @param callbackName The name of the callback that was disabled
function System:disabledCallback(callbackName)
end
return setmetatable(System, {
__call = function(_, ...) return System.new(...) end,
})

View file

@ -1,19 +0,0 @@
local Type = {}
function Type.isComponent(t)
return type(t) == "table" and t.__isComponent
end
function Type.isEntity(t)
return type(t) == "table" and t.__isEntity
end
function Type.isSystem(t)
return type(t) == "table" and t.__isSystem
end
function Type.isInstance(t)
return type(t) == "table" and t.__isInstance
end
return Type

View file

@ -1,4 +0,0 @@
local file = "examples.simpleDrawing"
-- local file = "examples.baseLayout.main"
require(file)