mirror of
https://github.com/Keyslam-Group/Concord.git
synced 2025-09-10 16:17:48 -04:00
Compare commits
69 commits
Author | SHA1 | Date | |
---|---|---|---|
|
848652f688 | ||
|
30b21c4c25 | ||
|
9f187f12e5 | ||
|
6575686b3b | ||
|
1aaf501401 | ||
|
f9da8dbe92 | ||
|
7b8f7b2f0a | ||
|
5f4b3b97da | ||
|
2386547caa | ||
|
1e4132be21 | ||
|
429a448ab6 | ||
|
9bccd05019 | ||
|
cf05cfc972 | ||
|
16c77c6a66 | ||
|
61720312cb | ||
|
8e1b14d53b | ||
|
bdfe2523b0 | ||
|
41fcfac6af | ||
|
a55efd042a | ||
|
3d195c790f | ||
|
a4ae392341 | ||
|
cc0fd1614c | ||
|
892f4d4700 | ||
|
743d662ef9 | ||
|
07bd5d0f28 | ||
|
c4594da19d | ||
|
50249d5ad3 | ||
|
695cc2dfe3 | ||
|
89eab3fb72 | ||
|
a45d89457b | ||
|
940870318d | ||
|
821b36c903 | ||
|
7a4bfaf33c | ||
|
2acb1458f2 | ||
|
edc1d2fdbc | ||
|
4313dc7856 | ||
|
9c22986501 | ||
|
73177f4048 | ||
|
6ce714ce14 | ||
|
e141a6183b | ||
|
6329e09138 | ||
|
cdf425d301 | ||
|
c7625ad376 | ||
|
65aae3c2ba | ||
|
297b30aa50 | ||
|
9aaff0fbcc | ||
|
b701493a27 | ||
|
b53f950e3e | ||
|
fd558dd3fe | ||
|
eb82c3c580 | ||
|
1325c4b445 | ||
|
d5c551046b | ||
|
2196a41e71 | ||
|
dd072adbe9 | ||
|
7979226c33 | ||
|
0897b1e4f9 | ||
|
3e9c596187 | ||
|
c95a1f2768 | ||
|
d56821205d | ||
|
c889b15d44 | ||
|
b906e2a910 | ||
|
f640258852 | ||
|
78dc7ee937 | ||
|
d8621e4070 | ||
|
079c1d0e18 | ||
|
9ae805aa43 | ||
|
16e111176e | ||
|
c640641b09 | ||
|
532151d901 |
40 changed files with 1229 additions and 1528 deletions
38
.github/workflows/doc.yml
vendored
Normal file
38
.github/workflows/doc.yml
vendored
Normal 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
|
3
.gitignore
vendored
3
.gitignore
vendored
|
@ -38,3 +38,6 @@ luac.out
|
||||||
*.i*86
|
*.i*86
|
||||||
*.x86_64
|
*.x86_64
|
||||||
*.hex
|
*.hex
|
||||||
|
|
||||||
|
# VSCode
|
||||||
|
.vscode/
|
|
@ -1 +1,2 @@
|
||||||
|
---@diagnostic disable: lowercase-global
|
||||||
std="love+luajit"
|
std="love+luajit"
|
||||||
|
|
246
README.md
246
README.md
|
@ -7,7 +7,7 @@ With Concord it is possibile to easily write fast and clean code.
|
||||||
This readme will explain how to use Concord.
|
This readme will explain how to use Concord.
|
||||||
|
|
||||||
Additionally all of Concord is documented using the LDoc format.
|
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://tjakka5.github.io/Concord/).
|
Auto generated docs for Concord can be found in `docs` folder, or on the [GitHub page](https://keyslam-group.github.io/Concord/).
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
@ -25,11 +25,10 @@ Auto generated docs for Concord can be found in `docs` folder, or on the [Github
|
||||||
[Contributors](#contributors)
|
[Contributors](#contributors)
|
||||||
[License](#licence)
|
[License](#licence)
|
||||||
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
Download the repository and copy the 'src' folder in your project. Rename it to something that makes sense (Probably 'concord'), then require it in your project like so:
|
Download the repository and copy the 'concord' folder into your project. Then require it in your project like so:
|
||||||
```lua
|
```lua
|
||||||
local Concord = require("path.to.concord")
|
local Concord = require("path.to.concord")
|
||||||
```
|
```
|
||||||
|
@ -42,13 +41,9 @@ local Entity = Concord.entity
|
||||||
local Component = Concord.component
|
local Component = Concord.component
|
||||||
local System = Concord.system
|
local System = Concord.system
|
||||||
local World = Concord.world
|
local World = Concord.world
|
||||||
local Assemblage = Concord.assemblage
|
|
||||||
|
|
||||||
-- Containers
|
-- Containers
|
||||||
local Components = Concord.components
|
local Components = Concord.components
|
||||||
local Systems = Concord.systems
|
|
||||||
local Worlds = Concord.worlds
|
|
||||||
local Assemblages = Concord.assemblages
|
|
||||||
```
|
```
|
||||||
|
|
||||||
---
|
---
|
||||||
|
@ -56,7 +51,7 @@ local Assemblages = Concord.assemblages
|
||||||
## ECS
|
## ECS
|
||||||
Concord is an Entity Component System (ECS for short) library.
|
Concord is an Entity Component System (ECS for short) library.
|
||||||
This is a coding paradigm where _composition_ is used over _inheritance_.
|
This is a coding paradigm where _composition_ is used over _inheritance_.
|
||||||
Because of this it is easier to write more modular code. It often allowes you to combine any form of behaviour for the objects in your game (Entities).
|
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.
|
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.
|
We'll start with the simplest one.
|
||||||
|
@ -71,7 +66,7 @@ What is most important is that Components are data and nothing more. They have 0
|
||||||
Entities are the actual objects in your game. Like a player, an enemy, a crate, or a bullet.
|
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.
|
Every Entity has it's own set of Components, with their own values.
|
||||||
|
|
||||||
A crate might have the following components:
|
A crate might have the following components (Note: Not actual Concord syntax):
|
||||||
```lua
|
```lua
|
||||||
{
|
{
|
||||||
position = { x = 100, y = 200 },
|
position = { x = 100, y = 200 },
|
||||||
|
@ -100,12 +95,12 @@ For this they will only act on Entities that have the Components needed for this
|
||||||
In Concord this is done something alike this:
|
In Concord this is done something alike this:
|
||||||
|
|
||||||
```lua
|
```lua
|
||||||
drawSystem = System({position, texture}) -- Define a System that takes all Entities with a position and texture Component
|
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
|
function drawSystem:draw() -- Give it a draw function
|
||||||
for _, entity in ipairs(self.pool) do -- Iterate over all Entities that this System acts on
|
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 position = entity.position -- Get the position Component of this Entity
|
||||||
local texture = entity[texture] -- Get the texture Component of this Entity
|
local texture = entity.texture -- Get the texture Component of this Entity
|
||||||
|
|
||||||
-- Draw the Entity
|
-- Draw the Entity
|
||||||
love.graphics.draw(texture.image, position.x, position.y)
|
love.graphics.draw(texture.image, position.x, position.y)
|
||||||
|
@ -133,58 +128,40 @@ And all that without writing a single extra line of code. Just reusing code that
|
||||||
|
|
||||||
Concord does a few things that might not be immediately clear. This segment should help understanding.
|
Concord does a few things that might not be immediately clear. This segment should help understanding.
|
||||||
|
|
||||||
#### Classes
|
#### Requiring files
|
||||||
|
|
||||||
When you define a Component or System you are actually defining a `ComponentClass` and `SystemClass` respectively. From these instances of them can be created. They also act as identifiers for Concord.
|
Since you'll have lots of Components and Systems in your game Concord makes it a bit easier to load things in.
|
||||||
|
|
||||||
For example. If you want to get a specific Component from an Entity, you'd do `Component = Entity:get(ComponentClass)`.
|
|
||||||
When ComponentClasses or SystemClasses are required it will be written clearly in the Documentation.
|
|
||||||
|
|
||||||
#### Containers
|
|
||||||
Since you'll be defining or creating lots of Components, Systems, Worlds and Assemblages, Concord adds container tables for each of them so that they are easily accessible.
|
|
||||||
|
|
||||||
These containers can be accessed through
|
|
||||||
```lua
|
```lua
|
||||||
local Components = require("path.to.concord").components
|
-- Loads all files in the directory. Components automatically register into Concord.components, so loading them into a namespace isn't necessary.
|
||||||
local Systems = require("path.to.concord").systems
|
Concord.utils.loadNamespace("path/to/components")
|
||||||
local Worlds = require("path.to.concord").worlds
|
|
||||||
local Assemblages = require("path.to.concord").aorlds
|
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
|
||||||
|
)
|
||||||
```
|
```
|
||||||
|
|
||||||
Concord has helper functions to fill these containers. There are the following options depending on your needs / preference:
|
|
||||||
```lua
|
|
||||||
-- Loads each file. They are put in the container according to it's filename ( 'src.components.component_1.lua' becomes 'component_1' )
|
|
||||||
Concord.loadComponents({"path.to.component_1", "path.to.component_2", "etc"})
|
|
||||||
|
|
||||||
-- Loads all files in the directory. They are put in the container according to it's filename ( 'src.components.component_1.lua' becomes 'component_1' )
|
|
||||||
Concord.loadComponents("path.to.directory.containing.components")
|
|
||||||
|
|
||||||
|
|
||||||
-- Put the ComponentClass into the container directly. Useful if you want more manual control. Note that you need to require the file in this case
|
|
||||||
Components.register("componentName", ComponentClass)
|
|
||||||
```
|
|
||||||
Things can then be accessed through their names:
|
|
||||||
```lua
|
|
||||||
local component_1_class = Components.component_1
|
|
||||||
local componentName_class = Components.componentName
|
|
||||||
```
|
|
||||||
|
|
||||||
All the above applies the same to all the other containers.
|
|
||||||
|
|
||||||
#### Method chaining
|
#### Method chaining
|
||||||
```lua
|
```lua
|
||||||
-- All functions that do something ( eg. Don't return anything ) will return self
|
-- Most (if not all) methods will return self
|
||||||
-- This allowes you to chain methods
|
-- This allowes you to chain methods
|
||||||
|
|
||||||
entity
|
myEntity
|
||||||
:give(position, 100, 50)
|
:give("position", 100, 50)
|
||||||
:give(velocity, 200, 0)
|
:give("velocity", 200, 0)
|
||||||
:remove(position)
|
:remove("position")
|
||||||
:destroy()
|
:destroy()
|
||||||
|
|
||||||
--
|
myWorld
|
||||||
|
|
||||||
world
|
|
||||||
:addEntity(fooEntity)
|
:addEntity(fooEntity)
|
||||||
:addEntity(barEntity)
|
:addEntity(barEntity)
|
||||||
:clear()
|
:clear()
|
||||||
|
@ -192,13 +169,13 @@ world
|
||||||
```
|
```
|
||||||
|
|
||||||
### Components
|
### Components
|
||||||
When defining a ComponentClass you usually pass in a `populate` function. This will fill the Component with values.
|
When defining a ComponentClass you need to pass in a name and usually a `populate` function. This will fill the Component with values.
|
||||||
|
|
||||||
```lua
|
```lua
|
||||||
-- Create the ComponentClass with a populate function
|
-- Create the position class with a populate function
|
||||||
-- The component variable is the actual Component given to an Entity
|
-- 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
|
-- The x and y variables are values we pass in when we create the Component
|
||||||
local positionComponentClass = Concord.component(function(component, x, y)
|
Concord.component("position", function(component, x, y)
|
||||||
component.x = x or 0
|
component.x = x or 0
|
||||||
component.y = y or 0
|
component.y = y or 0
|
||||||
end)
|
end)
|
||||||
|
@ -206,19 +183,11 @@ end)
|
||||||
-- Create a ComponentClass without a populate function
|
-- Create a ComponentClass without a populate function
|
||||||
-- Components of this type won't have any fields.
|
-- Components of this type won't have any fields.
|
||||||
-- This can be useful to indiciate state.
|
-- This can be useful to indiciate state.
|
||||||
local pushableComponentClass = Concord.component()
|
local pushableComponentClass = Concord.component("position")
|
||||||
```
|
|
||||||
|
|
||||||
```lua
|
|
||||||
-- Manually register the ComponentClass to the container if we want
|
|
||||||
Concord.components.register("positionComponent", positionComponentClass)
|
|
||||||
|
|
||||||
-- Otherwise return the ComponentClass so it can be required
|
|
||||||
return positionComponentClass
|
|
||||||
```
|
```
|
||||||
|
|
||||||
### Entities
|
### Entities
|
||||||
Entities can be freely made and be given Components. You pass the ComponentClass and the values you want to pass. It will then create the Component for you.
|
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 only have a maximum of one of each Component.
|
||||||
Entities can not share Components.
|
Entities can not share Components.
|
||||||
|
@ -233,43 +202,35 @@ local myEntity = Entity(myWorld) -- To add it to a world immediately ( See World
|
||||||
```lua
|
```lua
|
||||||
-- Give the entity the position Component defined above
|
-- Give the entity the position Component defined above
|
||||||
-- x will become 100. y will become 50
|
-- x will become 100. y will become 50
|
||||||
myEntity:give(positionComponentClass, 100, 50)
|
myEntity:give("position", 100, 50)
|
||||||
```
|
```
|
||||||
|
|
||||||
```lua
|
```lua
|
||||||
-- Retrieve a Component
|
-- Retrieve a Component
|
||||||
local positionComponent = myEntity[positionComponentClass]
|
local position = myEntity.position
|
||||||
-- or
|
|
||||||
local positionComponent = myEntity:get(positionComponentClass)
|
|
||||||
|
|
||||||
print(positionComponent.x, positionComponent.y) -- 100, 50
|
print(position.x, position.y) -- 100, 50
|
||||||
```
|
```
|
||||||
|
|
||||||
```lua
|
```lua
|
||||||
-- Remove a Component
|
-- Remove a Component
|
||||||
myEntity:remove(positionComponentClass)
|
myEntity:remove("position")
|
||||||
```
|
|
||||||
|
|
||||||
```lua
|
|
||||||
-- Check if the Entity has a Component
|
|
||||||
local hasPositionComponent = myEntity:has(positionComponentClass)
|
|
||||||
print(hasPositionComponent) -- false
|
|
||||||
```
|
```
|
||||||
|
|
||||||
```lua
|
```lua
|
||||||
-- Entity:give will override a Component if the Entity already has it
|
-- 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 will only put the Component if the Entity does not already have it
|
||||||
|
|
||||||
Entity:ensure(positionComponentClass, 0, 0) -- Will give
|
Entity:ensure("position", 0, 0) -- Will give
|
||||||
-- Position is {x = 0, y = 0}
|
-- Position is {x = 0, y = 0}
|
||||||
|
|
||||||
Entity:give(positionComponentClass, 50, 50) -- Will override
|
Entity:give("position", 50, 50) -- Will override
|
||||||
-- Position is {x = 50, y = 50}
|
-- Position is {x = 50, y = 50}
|
||||||
|
|
||||||
Entity:give(positionComponentClass, 100, 100) -- Will override
|
Entity:give("position", 100, 100) -- Will override
|
||||||
-- Position is {x = 100, y = 100}
|
-- Position is {x = 100, y = 100}
|
||||||
|
|
||||||
Entity:ensure(positionComponentClass, 0, 0) -- Wont do anything
|
Entity:ensure("position", 0, 0) -- Wont do anything
|
||||||
-- Position is {x = 100, y = 100}
|
-- Position is {x = 100, y = 100}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -285,7 +246,7 @@ end
|
||||||
|
|
||||||
```lua
|
```lua
|
||||||
-- Assemble the Entity ( See Assemblages )
|
-- Assemble the Entity ( See Assemblages )
|
||||||
myEntity:assemble(myAssemblage, 100, true, "foo")
|
myEntity:assemble(assemblageFunction, 100, true, "foo")
|
||||||
```
|
```
|
||||||
|
|
||||||
```lua
|
```lua
|
||||||
|
@ -310,28 +271,19 @@ Systems can have multiple pools.
|
||||||
|
|
||||||
```lua
|
```lua
|
||||||
-- Create a System
|
-- Create a System
|
||||||
local mySystemClass = Concord.system({positionComponentClass}) -- Pool will contain all Entities with a position Component
|
local mySystemClass = Concord.system({pool = {"position"}}) -- Pool named 'pool' will contain all Entities with a position Component
|
||||||
|
|
||||||
-- Create a System with multiple pools
|
-- Create a System with multiple pools
|
||||||
local mySystemClass = Concord.system(
|
local mySystemClass = Concord.system({
|
||||||
{ -- This Pool's name will default to 'pool'
|
pool = { -- This pool will be named 'pool'
|
||||||
positionCompomponentClass,
|
"position",
|
||||||
velocityComponentClass,
|
"velocity",
|
||||||
},
|
},
|
||||||
{ -- This Pool's name will be 'secondPool'
|
secondPool = { -- This pool's name will be 'secondPool'
|
||||||
healthComponentClass,
|
"health",
|
||||||
damageableComponentClass,
|
"damageable",
|
||||||
"secondPool",
|
|
||||||
}
|
}
|
||||||
)
|
})
|
||||||
```
|
|
||||||
|
|
||||||
```lua
|
|
||||||
-- Manually register the SystemClass to the container if we want
|
|
||||||
Concord.system.register("mySystem", mySystemClass)
|
|
||||||
|
|
||||||
-- Otherwise return the SystemClass so it can be required
|
|
||||||
return mySystemClass
|
|
||||||
```
|
```
|
||||||
|
|
||||||
```lua
|
```lua
|
||||||
|
@ -347,19 +299,14 @@ end
|
||||||
-- Defining a function
|
-- Defining a function
|
||||||
function mySystemClass:update(dt)
|
function mySystemClass:update(dt)
|
||||||
-- Iterate over all entities in the Pool
|
-- Iterate over all entities in the Pool
|
||||||
for _, e in ipairs(self.pool)
|
for _, e in ipairs(self.pool) do
|
||||||
-- Get the Entity's Components
|
|
||||||
local positionComponent = e[positionComponentClass]
|
|
||||||
local velocityComponent = e[velocityComponentClass]
|
|
||||||
|
|
||||||
-- Do something with the Components
|
-- Do something with the Components
|
||||||
positionComponent.x = positionComponent.x + velocityComponent.x * dt
|
e.position.x = e.position.x + e.velocity.x * dt
|
||||||
positionComponent.y = positionComponent.y + velocityComponent.y * dt
|
e.position.y = e.position.y + e.velocity.y * dt
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
-- Iterate over all entities in the second Pool
|
-- Iterate over all entities in the second Pool
|
||||||
for _, e in ipairs(self.secondPool)
|
for _, e in ipairs(self.secondPool) do
|
||||||
-- Do something
|
-- Do something
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -367,24 +314,20 @@ end
|
||||||
|
|
||||||
```lua
|
```lua
|
||||||
-- Systems can be enabled and disabled
|
-- 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
|
-- Systems are enabled by default
|
||||||
|
|
||||||
-- Enable a System
|
-- Enable a System
|
||||||
mySystem:enable()
|
|
||||||
-- or
|
|
||||||
mySystem:setEnable(true)
|
mySystem:setEnable(true)
|
||||||
|
|
||||||
-- Disable a System
|
-- Disable a System
|
||||||
mySystem:disable()
|
|
||||||
-- or
|
|
||||||
mySystem:setEnable(false)
|
mySystem:setEnable(false)
|
||||||
|
|
||||||
-- Toggle the enable state
|
|
||||||
mySystem:toggleEnabled()
|
|
||||||
|
|
||||||
-- Get enabled state
|
-- Get enabled state
|
||||||
local isEnabled = mySystem:isEnabled()
|
local isEnabled = mySystem:isEnabled()
|
||||||
print(isEnabled) -- true
|
print(isEnabled) -- false
|
||||||
```
|
```
|
||||||
|
|
||||||
```lua
|
```lua
|
||||||
|
@ -405,14 +348,6 @@ Worlds can have any number of Entities.
|
||||||
local myWorld = Concord.world()
|
local myWorld = Concord.world()
|
||||||
```
|
```
|
||||||
|
|
||||||
```lua
|
|
||||||
-- Manually register the World to the container if we want
|
|
||||||
Concord.worlds.register("myWorld", myWorld)
|
|
||||||
|
|
||||||
-- Otherwise return the World so it can be required
|
|
||||||
return myWorld
|
|
||||||
```
|
|
||||||
|
|
||||||
```lua
|
```lua
|
||||||
-- Add an Entity to the World
|
-- Add an Entity to the World
|
||||||
myWorld:addEntity(myEntity)
|
myWorld:addEntity(myEntity)
|
||||||
|
@ -471,33 +406,31 @@ end
|
||||||
|
|
||||||
### Assemblages
|
### Assemblages
|
||||||
|
|
||||||
Assemblages are helpers to 'make' Entities something.
|
Assemblages are functions to 'make' Entities something.
|
||||||
An important distinction is that they _append_ Components.
|
An important distinction is that they _append_ Components.
|
||||||
|
|
||||||
```lua
|
```lua
|
||||||
-- Make an Assemblage
|
-- Make an Assemblage function
|
||||||
-- e is the Entity being assembled.
|
-- e is the Entity being assembled.
|
||||||
-- cuteness and legs are variables passed in
|
-- cuteness and legs are variables passed in
|
||||||
local animalAssemblage(function(e, cuteness, legs)
|
function animal(e, cuteness, legs)
|
||||||
e
|
e
|
||||||
:give(cutenessComponentClass, cuteness)
|
:give(cutenessComponentClass, cuteness)
|
||||||
:give(limbs, legs, 0) -- Variable amount of legs. 0 arm.
|
:give(limbs, legs, 0) -- Variable amount of legs. 0 arm.
|
||||||
end)
|
end)
|
||||||
|
|
||||||
-- Make an Assemblage that used animalAssemblage
|
-- Make an Assemblage that uses animal
|
||||||
-- cuteness is a variables passed in
|
-- cuteness is a variables passed in
|
||||||
local catAssemblage(function(e, cuteness)
|
function cat(e, cuteness)
|
||||||
e
|
e
|
||||||
:assemble(animalAssemblage, cuteness * 2, 4) -- Cats are twice as cute, and have 4 legs.
|
:assemble(animal, cuteness * 2, 4) -- Cats are twice as cute, and have 4 legs.
|
||||||
:give(soundComponent, "meow.mp3")
|
:give(soundComponent, "meow.mp3")
|
||||||
end)
|
end)
|
||||||
```
|
```
|
||||||
|
|
||||||
```lua
|
```lua
|
||||||
-- Use an Assemblage
|
-- Use an Assemblage
|
||||||
myEntity:assemble(catAssemblage, 100) -- 100 cuteness
|
myEntity:assemble(cat, 100) -- 100 cuteness
|
||||||
-- or
|
|
||||||
catAssemblage:assemble(myEntity, 100) -- 100 cuteness
|
|
||||||
```
|
```
|
||||||
|
|
||||||
---
|
---
|
||||||
|
@ -506,43 +439,40 @@ catAssemblage:assemble(myEntity, 100) -- 100 cuteness
|
||||||
```lua
|
```lua
|
||||||
local Concord = require("concord")
|
local Concord = require("concord")
|
||||||
|
|
||||||
-- Defining ComponentClasses
|
-- Defining components
|
||||||
-- I use UpperCamelCase to indicate its a class
|
Concord.component("position", function(c, x, y)
|
||||||
local Position = Concord.component(function(c, x, y)
|
|
||||||
c.x = x or 0
|
c.x = x or 0
|
||||||
c.y = y or 0
|
c.y = y or 0
|
||||||
end)
|
end)
|
||||||
|
|
||||||
local Velocity = Concord.component(function(c, x, y)
|
Concord.component("velocity", function(c, x, y)
|
||||||
c.x = x or 0
|
c.x = x or 0
|
||||||
c.y = y or 0
|
c.y = y or 0
|
||||||
end)
|
end)
|
||||||
|
|
||||||
local Drawable = Concord.component()
|
local Drawable = Concord.component("drawable")
|
||||||
|
|
||||||
|
|
||||||
-- Defining Systems
|
-- Defining Systems
|
||||||
local MoveSystem = Concord.system({Position, Velocity})
|
local MoveSystem = Concord.system({
|
||||||
|
pool = {"position", "velocity"}
|
||||||
|
})
|
||||||
|
|
||||||
function MoveSystem:update(dt)
|
function MoveSystem:update(dt)
|
||||||
for _, e in ipairs(self.pool) do
|
for _, e in ipairs(self.pool) do
|
||||||
-- I use lowerCamelCase to indicate its an instance
|
e.position.x = e.position.x + e.velocity.x * dt
|
||||||
local position = e[Position]
|
e.position.y = e.position.y + e.velocity.y * dt
|
||||||
local velocity = e[Velocity]
|
|
||||||
|
|
||||||
position.x = position.x + velocity.x * dt
|
|
||||||
position.y = position.y + velocity.y * dt
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
local DrawSystem = Concord.system({Position, Drawable})
|
local DrawSystem = Concord.system({
|
||||||
|
pool = {"position", "drawable"}
|
||||||
|
})
|
||||||
|
|
||||||
function DrawSystem:draw()
|
function DrawSystem:draw()
|
||||||
for _, e in ipairs(self.pool) do
|
for _, e in ipairs(self.pool) do
|
||||||
local position = e[Position]
|
love.graphics.circle("fill", e.position.x, e.position.y, 5)
|
||||||
|
|
||||||
love.graphics.circle("fill", position.x, position.y, 5)
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -555,18 +485,18 @@ world:addSystems(MoveSystem, DrawSystem)
|
||||||
|
|
||||||
-- This Entity will be rendered on the screen, and move to the right at 100 pixels a second
|
-- This Entity will be rendered on the screen, and move to the right at 100 pixels a second
|
||||||
local entity_1 = Concord.entity(world)
|
local entity_1 = Concord.entity(world)
|
||||||
:give(Position, 100, 100)
|
:give("position", 100, 100)
|
||||||
:give(Velocity, 100, 0)
|
:give("velocity", 100, 0)
|
||||||
:give(Drawable)
|
:give("drawable")
|
||||||
|
|
||||||
-- This Entity will be rendered on the screen, and stay at 50, 50
|
-- This Entity will be rendered on the screen, and stay at 50, 50
|
||||||
local entity_2 = Concord.entity(world)
|
local entity_2 = Concord.entity(world)
|
||||||
:give(Position, 50, 50)
|
:give("position", 50, 50)
|
||||||
:give(Drawable)
|
:give("drawable")
|
||||||
|
|
||||||
-- This Entity does exist in the World, but since it doesn't match any System's filters it won't do anything
|
-- 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)
|
local entity_3 = Concord.entity(world)
|
||||||
:give(Position, 200, 200)
|
:give("position", 200, 200)
|
||||||
|
|
||||||
|
|
||||||
-- Emit the events
|
-- Emit the events
|
||||||
|
@ -591,5 +521,5 @@ end
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Licence
|
## License
|
||||||
MIT Licensed - Copyright Justin van der Leij (Tjakka5)
|
MIT Licensed - Copyright Justin van der Leij (Tjakka5)
|
||||||
|
|
|
@ -1,49 +0,0 @@
|
||||||
--- Gives an entity a set of components.
|
|
||||||
-- @classmod Assemblage
|
|
||||||
|
|
||||||
local Assemblage = {}
|
|
||||||
Assemblage.__mt = {
|
|
||||||
__index = Assemblage,
|
|
||||||
}
|
|
||||||
|
|
||||||
--- Creates a new Assemblage.
|
|
||||||
-- @tparam function assemble Function that assembles an Entity
|
|
||||||
-- @treturn Assemblage A new assemblage
|
|
||||||
function Assemblage.new(assemble)
|
|
||||||
local assemblage = setmetatable({
|
|
||||||
__assemble = assemble,
|
|
||||||
|
|
||||||
__name = nil,
|
|
||||||
__isAssemblage = true,
|
|
||||||
}, Assemblage.__mt)
|
|
||||||
|
|
||||||
return assemblage
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Assembles an Entity.
|
|
||||||
-- @tparam Entity e Entity to assemble
|
|
||||||
-- @param ... additional arguments to pass to the assemble function
|
|
||||||
-- @treturn Assemblage self
|
|
||||||
function Assemblage:assemble(e, ...)
|
|
||||||
self.__assemble(e, ...)
|
|
||||||
|
|
||||||
return self
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Returns true if the Assemblage has a name.
|
|
||||||
-- @treturn boolean
|
|
||||||
function Assemblage:hasName()
|
|
||||||
return self.__name and true or false
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Returns the name of the Assemblage.
|
|
||||||
-- @treturn string
|
|
||||||
function Assemblage:getName()
|
|
||||||
return self.__name
|
|
||||||
end
|
|
||||||
|
|
||||||
return setmetatable(Assemblage, {
|
|
||||||
__call = function(_, ...)
|
|
||||||
return Assemblage.new(...)
|
|
||||||
end,
|
|
||||||
})
|
|
|
@ -1,49 +0,0 @@
|
||||||
--- A container for registered @{Assemblage}s
|
|
||||||
-- @module Assemblages
|
|
||||||
|
|
||||||
local PATH = (...):gsub('%.[^%.]+$', '')
|
|
||||||
|
|
||||||
local Type = require(PATH..".type")
|
|
||||||
|
|
||||||
local Assemblages = {}
|
|
||||||
|
|
||||||
--- Registers an Assemblage.
|
|
||||||
-- @string name Name to register under
|
|
||||||
-- @tparam Assemblage assemblage Assemblage to register
|
|
||||||
function Assemblages.register(name, assemblage)
|
|
||||||
if (type(name) ~= "string") then
|
|
||||||
error("bad argument #1 to 'Assemblages.register' (string expected, got "..type(name)..")", 3)
|
|
||||||
end
|
|
||||||
|
|
||||||
if (not Type.isAssemblage(assemblage)) then
|
|
||||||
error("bad argument #2 to 'Assemblages.register' (assemblage expected, got "..type(assemblage)..")", 3)
|
|
||||||
end
|
|
||||||
|
|
||||||
if (rawget(Assemblages, name)) then
|
|
||||||
error("bad argument #2 to 'Assemblages.register' (Assemblage with name '"..name.."' was already registerd)", 3)
|
|
||||||
end
|
|
||||||
|
|
||||||
Assemblages[name] = assemblage
|
|
||||||
assemblage.__name = name
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Returns true if the containter has an Assemblage with the specified name
|
|
||||||
-- @string name Name of the Assemblage to check
|
|
||||||
-- @treturn boolean
|
|
||||||
function Assemblages.has(name)
|
|
||||||
return Assemblages[name] and true or false
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Returns the Assemblage with the specified name
|
|
||||||
-- @string name Name of the Assemblage to get
|
|
||||||
-- @treturn Assemblage
|
|
||||||
function Assemblages.get(name)
|
|
||||||
return Assemblages[name]
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
return setmetatable(Assemblages, {
|
|
||||||
__index = function(_, name)
|
|
||||||
error("Attempt to index assemblage '"..tostring(name).."' that does not exist / was not registered", 2)
|
|
||||||
end
|
|
||||||
})
|
|
6
concord/builtins/init.lua
Normal file
6
concord/builtins/init.lua
Normal 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
41
concord/builtins/key.lua
Normal 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
|
12
concord/builtins/serializable.lua
Normal file
12
concord/builtins/serializable.lua
Normal 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
|
|
@ -1,6 +1,11 @@
|
||||||
--- A pure data container that is contained by a single entity.
|
--- A pure data container that is contained by a single entity.
|
||||||
-- @classmod Component
|
-- @classmod Component
|
||||||
|
|
||||||
|
local PATH = (...):gsub('%.[^%.]+$', '')
|
||||||
|
|
||||||
|
local Components = require(PATH..".components")
|
||||||
|
local Utils = require(PATH..".utils")
|
||||||
|
|
||||||
local Component = {}
|
local Component = {}
|
||||||
Component.__mt = {
|
Component.__mt = {
|
||||||
__index = Component,
|
__index = Component,
|
||||||
|
@ -9,15 +14,27 @@ Component.__mt = {
|
||||||
--- Creates a new ComponentClass.
|
--- Creates a new ComponentClass.
|
||||||
-- @tparam function populate Function that populates a Component with values
|
-- @tparam function populate Function that populates a Component with values
|
||||||
-- @treturn Component A new ComponentClass
|
-- @treturn Component A new ComponentClass
|
||||||
function Component.new(populate)
|
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
|
if (type(populate) ~= "function" and type(populate) ~= "nil") then
|
||||||
error("bad argument #1 to 'Component.new' (function/nil expected, got "..type(populate)..")", 2)
|
Utils.error(2, "bad argument #1 to 'Component.new' (function/nil expected, got %s)", type(populate))
|
||||||
end
|
end
|
||||||
|
|
||||||
local componentClass = setmetatable({
|
local componentClass = setmetatable({
|
||||||
__populate = populate,
|
__populate = populate,
|
||||||
|
|
||||||
__name = nil,
|
__name = name,
|
||||||
__isComponentClass = true,
|
__isComponentClass = true,
|
||||||
}, Component.__mt)
|
}, Component.__mt)
|
||||||
|
|
||||||
|
@ -25,25 +42,45 @@ function Component.new(populate)
|
||||||
__index = componentClass
|
__index = componentClass
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Components[name] = componentClass
|
||||||
|
|
||||||
return componentClass
|
return componentClass
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Internal: Populates a Component with values
|
-- Internal: Populates a Component with values.
|
||||||
function Component:__populate() -- luacheck: ignore
|
function Component:__populate() -- luacheck: ignore
|
||||||
end
|
end
|
||||||
|
|
||||||
function Component:serialize() -- luacheck: ignore
|
-- Callback: When the Component gets removed or replaced in an Entity.
|
||||||
|
function Component:removed() -- luacheck: ignore
|
||||||
end
|
end
|
||||||
|
|
||||||
function Component:deserialize(data) -- luacheck: ignore
|
-- 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
|
end
|
||||||
|
|
||||||
-- Internal: Creates a new Component.
|
-- Internal: Creates a new Component.
|
||||||
|
-- @param entity The Entity that will receive this Component.
|
||||||
-- @return A new Component
|
-- @return A new Component
|
||||||
function Component:__new()
|
function Component:__new(entity)
|
||||||
local component = setmetatable({
|
local component = setmetatable({
|
||||||
__componentClass = self,
|
__componentClass = self,
|
||||||
|
|
||||||
|
__entity = entity,
|
||||||
__isComponent = true,
|
__isComponent = true,
|
||||||
__isComponentClass = false,
|
__isComponentClass = false,
|
||||||
}, self.__mt)
|
}, self.__mt)
|
||||||
|
@ -52,11 +89,13 @@ function Component:__new()
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Internal: Creates and populates a new Component.
|
-- Internal: Creates and populates a new Component.
|
||||||
|
-- @param entity The Entity that will receive this Component.
|
||||||
-- @param ... Varargs passed to the populate function
|
-- @param ... Varargs passed to the populate function
|
||||||
-- @return A new populated Component
|
-- @return A new populated Component
|
||||||
function Component:__initialize(...)
|
function Component:__initialize(entity, ...)
|
||||||
local component = self:__new()
|
local component = self:__new(entity)
|
||||||
|
|
||||||
|
---@diagnostic disable-next-line: redundant-parameter
|
||||||
self.__populate(component, ...)
|
self.__populate(component, ...)
|
||||||
|
|
||||||
return component
|
return component
|
||||||
|
|
|
@ -1,48 +1,73 @@
|
||||||
--- Container for registered ComponentClasses
|
--- Container for registered ComponentClasses
|
||||||
-- @module Components
|
-- @module Components
|
||||||
|
|
||||||
local PATH = (...):gsub('%.[^%.]+$', '')
|
|
||||||
|
|
||||||
local Type = require(PATH..".type")
|
|
||||||
|
|
||||||
local Components = {}
|
local Components = {}
|
||||||
|
|
||||||
--- Registers a ComponentClass.
|
Components.__REJECT_PREFIX = "!"
|
||||||
-- @string name Name to register under
|
Components.__REJECT_MATCH = "^(%"..Components.__REJECT_PREFIX.."?)(.+)"
|
||||||
-- @tparam Component componentClass ComponentClass to register
|
|
||||||
function Components.register(name, componentClass)
|
|
||||||
if (type(name) ~= "string") then
|
|
||||||
error("bad argument #1 to 'Components.register' (string expected, got "..type(name)..")", 3)
|
|
||||||
end
|
|
||||||
|
|
||||||
if (not Type.isComponentClass(componentClass)) then
|
|
||||||
error("bad argument #2 to 'Components.register' (ComponentClass expected, got "..type(componentClass)..")", 3)
|
|
||||||
end
|
|
||||||
|
|
||||||
if (rawget(Components, name)) then
|
|
||||||
error("bad argument #2 to 'Components.register' (ComponentClass with name '"..name.."' was already registerd)", 3) -- luacheck: ignore
|
|
||||||
end
|
|
||||||
|
|
||||||
Components[name] = componentClass
|
|
||||||
componentClass.__name = name
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Returns true if the containter has the ComponentClass with the specified name
|
--- Returns true if the containter has the ComponentClass with the specified name
|
||||||
-- @string name Name of the ComponentClass to check
|
-- @string name Name of the ComponentClass to check
|
||||||
-- @treturn boolean
|
-- @treturn boolean
|
||||||
function Components.has(name)
|
function Components.has(name)
|
||||||
return Components[name] and true or false
|
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
|
end
|
||||||
|
|
||||||
--- Returns the ComponentClass with the specified name
|
--- Returns the ComponentClass with the specified name
|
||||||
-- @string name Name of the ComponentClass to get
|
-- @string name Name of the ComponentClass to get
|
||||||
-- @treturn Component
|
-- @treturn Component
|
||||||
function Components.get(name)
|
function Components.get(name)
|
||||||
return Components[name]
|
local ok, value = Components.try(name)
|
||||||
|
|
||||||
|
if not ok then error(value, 2) end
|
||||||
|
|
||||||
|
return value
|
||||||
end
|
end
|
||||||
|
|
||||||
return setmetatable(Components, {
|
return setmetatable(Components, {
|
||||||
__index = function(_, name)
|
__index = function(_, name)
|
||||||
error("Attempt to index ComponentClass '"..tostring(name).."' that does not exist / was not registered", 2)
|
local ok, value = Components.try(name)
|
||||||
end
|
|
||||||
|
if not ok then error(value, 2) end
|
||||||
|
|
||||||
|
return value end
|
||||||
})
|
})
|
||||||
|
|
|
@ -6,8 +6,16 @@ local PATH = (...):gsub('%.[^%.]+$', '')
|
||||||
|
|
||||||
local Components = require(PATH..".components")
|
local Components = require(PATH..".components")
|
||||||
local Type = require(PATH..".type")
|
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,
|
||||||
|
}
|
||||||
|
|
||||||
local Entity = {}
|
|
||||||
Entity.__mt = {
|
Entity.__mt = {
|
||||||
__index = Entity,
|
__index = Entity,
|
||||||
}
|
}
|
||||||
|
@ -17,12 +25,11 @@ Entity.__mt = {
|
||||||
-- @treturn Entity A new Entity
|
-- @treturn Entity A new Entity
|
||||||
function Entity.new(world)
|
function Entity.new(world)
|
||||||
if (world ~= nil and not Type.isWorld(world)) then
|
if (world ~= nil and not Type.isWorld(world)) then
|
||||||
error("bad argument #1 to 'Entity.new' (world/nil expected, got "..type(world)..")", 2)
|
Utils.error(2, "bad argument #1 to 'Entity.new' (world/nil expected, got %s)", type(world))
|
||||||
end
|
end
|
||||||
|
|
||||||
local e = setmetatable({
|
local e = setmetatable({
|
||||||
__world = nil,
|
__world = nil,
|
||||||
__components = {},
|
|
||||||
|
|
||||||
__isEntity = true,
|
__isEntity = true,
|
||||||
}, Entity.__mt)
|
}, Entity.__mt)
|
||||||
|
@ -31,23 +38,86 @@ function Entity.new(world)
|
||||||
world:addEntity(e)
|
world:addEntity(e)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
if Entity.SERIALIZE_BY_DEFAULT then
|
||||||
|
e:give("serializable")
|
||||||
|
end
|
||||||
|
|
||||||
return e
|
return e
|
||||||
end
|
end
|
||||||
|
|
||||||
local function give(e, componentClass, ...)
|
local function createComponent(e, name, componentClass, ...)
|
||||||
local component = componentClass:__initialize(...)
|
local component = componentClass:__initialize(e, ...)
|
||||||
|
local hadComponent = not not e[name]
|
||||||
|
|
||||||
e[componentClass] = component
|
if hadComponent then
|
||||||
e.__components[componentClass] = component
|
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()
|
e:__dirty()
|
||||||
end
|
end
|
||||||
|
|
||||||
local function remove(e, componentClass)
|
|
||||||
e[componentClass] = nil
|
|
||||||
e.__components[componentClass] = nil
|
|
||||||
|
|
||||||
e:__dirty()
|
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Gives an Entity a Component.
|
--- Gives an Entity a Component.
|
||||||
|
@ -55,14 +125,8 @@ end
|
||||||
-- @tparam Component componentClass ComponentClass to add an instance of
|
-- @tparam Component componentClass ComponentClass to add an instance of
|
||||||
-- @param ... additional arguments to pass to the Component's populate function
|
-- @param ... additional arguments to pass to the Component's populate function
|
||||||
-- @treturn Entity self
|
-- @treturn Entity self
|
||||||
function Entity:give(componentClass, ...)
|
function Entity:give(name, ...)
|
||||||
if not Type.isComponentClass(componentClass) then
|
return giveComponent(self, false, name, ...)
|
||||||
error("bad argument #1 to 'Entity:give' (ComponentClass expected, got "..type(componentClass)..")", 2)
|
|
||||||
end
|
|
||||||
|
|
||||||
give(self, componentClass, ...)
|
|
||||||
|
|
||||||
return self
|
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Ensures an Entity to have a Component.
|
--- Ensures an Entity to have a Component.
|
||||||
|
@ -70,43 +134,35 @@ end
|
||||||
-- @tparam Component componentClass ComponentClass to add an instance of
|
-- @tparam Component componentClass ComponentClass to add an instance of
|
||||||
-- @param ... additional arguments to pass to the Component's populate function
|
-- @param ... additional arguments to pass to the Component's populate function
|
||||||
-- @treturn Entity self
|
-- @treturn Entity self
|
||||||
function Entity:ensure(componentClass, ...)
|
function Entity:ensure(name, ...)
|
||||||
if not Type.isComponentClass(componentClass) then
|
return giveComponent(self, true, name, ...)
|
||||||
error("bad argument #1 to 'Entity:ensure' (ComponentClass expected, got "..type(componentClass)..")", 2)
|
|
||||||
end
|
|
||||||
|
|
||||||
if self[componentClass] then
|
|
||||||
return self
|
|
||||||
end
|
|
||||||
|
|
||||||
give(self, componentClass, ...)
|
|
||||||
|
|
||||||
return self
|
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Removes a Component from an Entity.
|
--- Removes a Component from an Entity.
|
||||||
-- @tparam Component componentClass ComponentClass of the Component to remove
|
-- @tparam Component componentClass ComponentClass of the Component to remove
|
||||||
-- @treturn Entity self
|
-- @treturn Entity self
|
||||||
function Entity:remove(componentClass)
|
function Entity:remove(name)
|
||||||
if not Type.isComponentClass(componentClass) then
|
local ok, componentClass = Components.try(name)
|
||||||
error("bad argument #1 to 'Entity:remove' (ComponentClass expected, got "..type(componentClass)..")")
|
|
||||||
|
if not ok then
|
||||||
|
Utils.error(2, "bad argument #1 to 'Entity:remove' (%s)", componentClass)
|
||||||
end
|
end
|
||||||
|
|
||||||
remove(self, componentClass)
|
removeComponent(self, name)
|
||||||
|
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Assembles an Entity.
|
--- Assembles an Entity.
|
||||||
-- @tparam Assemblage assemblage Assemblage to assemble with
|
-- @tparam function assemblage Function that will assemble an entity
|
||||||
-- @param ... additional arguments to pass to the Assemblage's assemble function.
|
-- @param ... additional arguments to pass to the assemblage function.
|
||||||
-- @treturn Entity self
|
-- @treturn Entity self
|
||||||
function Entity:assemble(assemblage, ...)
|
function Entity:assemble(assemblage, ...)
|
||||||
if not Type.isAssemblage(assemblage) then
|
if type(assemblage) ~= "function" then
|
||||||
error("bad argument #1 to 'Entity:assemble' (Assemblage expected, got "..type(assemblage)..")")
|
Utils.error(2, "bad argument #1 to 'Entity:assemble' (function expected, got %s)", type(assemblage))
|
||||||
end
|
end
|
||||||
|
|
||||||
assemblage:assemble(self, ...)
|
assemblage(self, ...)
|
||||||
|
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
@ -135,31 +191,40 @@ end
|
||||||
--- Returns true if the Entity has a Component.
|
--- Returns true if the Entity has a Component.
|
||||||
-- @tparam Component componentClass ComponentClass of the Component to check
|
-- @tparam Component componentClass ComponentClass of the Component to check
|
||||||
-- @treturn boolean
|
-- @treturn boolean
|
||||||
function Entity:has(componentClass)
|
function Entity:has(name)
|
||||||
if not Type.isComponentClass(componentClass) then
|
local ok, componentClass = Components.try(name)
|
||||||
error("bad argument #1 to 'Entity:has' (ComponentClass expected, got "..type(componentClass)..")")
|
|
||||||
|
if not ok then
|
||||||
|
Utils.error(2, "bad argument #1 to 'Entity:has' (%s)", componentClass)
|
||||||
end
|
end
|
||||||
|
|
||||||
return self[componentClass] ~= nil
|
return self[name] and true or false
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Gets a Component from the Entity.
|
--- Gets a Component from the Entity.
|
||||||
-- @tparam Component componentClass ComponentClass of the Component to get
|
-- @tparam Component componentClass ComponentClass of the Component to get
|
||||||
-- @treturn table
|
-- @treturn table
|
||||||
function Entity:get(componentClass)
|
function Entity:get(name)
|
||||||
if not Type.isComponentClass(componentClass) then
|
local ok, componentClass = Components.try(name)
|
||||||
error("bad argument #1 to 'Entity:get' (ComponentClass expected, got "..type(componentClass)..")")
|
|
||||||
|
if not ok then
|
||||||
|
Utils.error(2, "bad argument #1 to 'Entity:get' (%s)", componentClass)
|
||||||
end
|
end
|
||||||
|
|
||||||
return self[componentClass]
|
return self[name]
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Returns a table of all Components the Entity has.
|
--- Returns a table of all Components the Entity has.
|
||||||
-- Warning: Do not modify this table.
|
-- Warning: Do not modify this table.
|
||||||
-- Use Entity:give/ensure/remove instead
|
-- Use Entity:give/ensure/remove instead
|
||||||
-- @treturn table Table of all Components the Entity has
|
-- @treturn table Table of all Components the Entity has
|
||||||
function Entity:getComponents()
|
function Entity:getComponents(output)
|
||||||
return self.__components
|
output = output or {}
|
||||||
|
local components = Utils.shallowCopy(self, output)
|
||||||
|
components.__world = nil
|
||||||
|
components.__isEntity = nil
|
||||||
|
|
||||||
|
return components
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Returns true if the Entity is in a World.
|
--- Returns true if the Entity is in a World.
|
||||||
|
@ -174,17 +239,25 @@ function Entity:getWorld()
|
||||||
return self.__world
|
return self.__world
|
||||||
end
|
end
|
||||||
|
|
||||||
function Entity:serialize()
|
function Entity:serialize(ignoreKey)
|
||||||
local data = {}
|
local data = {}
|
||||||
|
|
||||||
for _, component in pairs(self.__components) do
|
for name, component in pairs(self) do
|
||||||
if component.__name then
|
-- 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()
|
local componentData = component:serialize()
|
||||||
componentData.__name = component.__name
|
|
||||||
|
|
||||||
|
if componentData ~= nil then
|
||||||
|
componentData.__name = component.__name
|
||||||
data[#data + 1] = componentData
|
data[#data + 1] = componentData
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
end
|
||||||
|
|
||||||
return data
|
return data
|
||||||
end
|
end
|
||||||
|
@ -193,19 +266,11 @@ function Entity:deserialize(data)
|
||||||
for i = 1, #data do
|
for i = 1, #data do
|
||||||
local componentData = data[i]
|
local componentData = data[i]
|
||||||
|
|
||||||
if (not Components[componentData.__name]) then
|
if (not Components.has(componentData.__name)) then
|
||||||
error("bad argument #1 to 'Entity:deserialize' (ComponentClass "..type(componentData.__name).." wasn't yet loaded)") -- luacheck: ignore
|
Utils.error(2, "bad argument #1 to 'Entity:deserialize' (ComponentClass '%s' wasn't yet loaded)", tostring(componentData.__name)) -- luacheck: ignore
|
||||||
end
|
end
|
||||||
|
|
||||||
local componentClass = Components[componentData.__name]
|
deserializeComponent(self, componentData.__name, componentData)
|
||||||
|
|
||||||
local component = componentClass:__new()
|
|
||||||
component:deserialize(componentData)
|
|
||||||
|
|
||||||
self[componentClass] = component
|
|
||||||
self.__components[componentClass] = component
|
|
||||||
|
|
||||||
self:__dirty()
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
199
concord/filter.lua
Normal file
199
concord/filter.lua
Normal 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,
|
||||||
|
})
|
|
@ -4,12 +4,12 @@
|
||||||
local PATH = (...):gsub('%.init$', '')
|
local PATH = (...):gsub('%.init$', '')
|
||||||
|
|
||||||
local Concord = {
|
local Concord = {
|
||||||
_VERSION = "2.0 Beta",
|
_VERSION = "3.0",
|
||||||
_DESCRIPTION = "A feature-complete ECS library",
|
_DESCRIPTION = "A feature-complete ECS library",
|
||||||
_LICENCE = [[
|
_LICENCE = [[
|
||||||
MIT LICENSE
|
MIT LICENSE
|
||||||
|
|
||||||
Copyright (c) 2018 Justin van der Leij / Tjakka5
|
Copyright (c) 2020 Justin van der Leij / Tjakka5
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a
|
Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
copy of this software and associated documentation files (the
|
copy of this software and associated documentation files (the
|
||||||
|
@ -33,82 +33,10 @@ local Concord = {
|
||||||
}
|
}
|
||||||
|
|
||||||
Concord.entity = require(PATH..".entity")
|
Concord.entity = require(PATH..".entity")
|
||||||
|
|
||||||
Concord.component = require(PATH..".component")
|
Concord.component = require(PATH..".component")
|
||||||
Concord.components = require(PATH..".components")
|
Concord.components = require(PATH..".components")
|
||||||
|
|
||||||
Concord.system = require(PATH..".system")
|
Concord.system = require(PATH..".system")
|
||||||
Concord.systems = require(PATH..".systems")
|
|
||||||
|
|
||||||
Concord.world = require(PATH..".world")
|
Concord.world = require(PATH..".world")
|
||||||
Concord.worlds = require(PATH..".worlds")
|
Concord.utils = require(PATH..".utils")
|
||||||
|
|
||||||
Concord.assemblage = require(PATH..".assemblage")
|
|
||||||
Concord.assemblages = require(PATH..".assemblages")
|
|
||||||
|
|
||||||
local function load(pathOrFiles, namespace)
|
|
||||||
if (type(pathOrFiles) ~= "string" and type(pathOrFiles) ~= "table") then
|
|
||||||
error("bad argument #1 to 'load' (string/table of strings expected, got "..type(pathOrFiles)..")", 3)
|
|
||||||
end
|
|
||||||
|
|
||||||
if (type(pathOrFiles) == "string") then
|
|
||||||
local info = love.filesystem.getInfo(pathOrFiles) -- luacheck: ignore
|
|
||||||
if (info == nil or info.type ~= "directory") then
|
|
||||||
error("bad argument #1 to 'load' (path '"..pathOrFiles.."' not found)", 3)
|
|
||||||
end
|
|
||||||
|
|
||||||
local files = love.filesystem.getDirectoryItems(pathOrFiles)
|
|
||||||
|
|
||||||
for _, file in ipairs(files) do
|
|
||||||
local name = file:sub(1, #file - 4)
|
|
||||||
local path = pathOrFiles.."."..name
|
|
||||||
|
|
||||||
namespace.register(name, require(path))
|
|
||||||
end
|
|
||||||
elseif (type(pathOrFiles == "table")) then
|
|
||||||
for _, path in ipairs(pathOrFiles) do
|
|
||||||
if (type(path) ~= "string") then
|
|
||||||
error("bad argument #2 to 'load' (string/table of strings expected, got table containing "..type(path)..")", 3) -- 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
|
|
||||||
|
|
||||||
namespace.register(name, require(path))
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Loads ComponentClasses and puts them in the Components container.
|
|
||||||
-- Accepts a table of paths to files: {"component_1", "component_2", "etc"}
|
|
||||||
-- Accepts a path to a directory with ComponentClasses: "components"
|
|
||||||
function Concord.loadComponents(pathOrFiles)
|
|
||||||
load(pathOrFiles, Concord.components)
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Loads SystemClasses and puts them in the Systems container.
|
|
||||||
-- Accepts a table of paths to files: {"system_1", "system_2", "etc"}
|
|
||||||
-- Accepts a path to a directory with SystemClasses: "systems"
|
|
||||||
function Concord.loadSystems(pathOrFiles)
|
|
||||||
load(pathOrFiles, Concord.systems)
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Loads Worlds and puts them in the Worlds container.
|
|
||||||
-- Accepts a table of paths to files: {"world_1", "world_2", "etc"}
|
|
||||||
-- Accepts a path to a directory with Worlds: "worlds"
|
|
||||||
function Concord.loadWorlds(pathOrFiles)
|
|
||||||
load(pathOrFiles, Concord.worlds)
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Loads Assemblages and puts them in the Assemblages container.
|
|
||||||
-- Accepts a table of paths to files: {"assemblage_1", "assemblage_2", "etc"}
|
|
||||||
-- Accepts a path to a directory with Assemblages: "assemblages"
|
|
||||||
function Concord.loadAssemblages(pathOrFiles)
|
|
||||||
load(pathOrFiles, Concord.assemblages)
|
|
||||||
end
|
|
||||||
|
|
||||||
return Concord
|
return Concord
|
||||||
|
|
|
@ -16,23 +16,24 @@ end
|
||||||
|
|
||||||
--- Adds an object to the List.
|
--- Adds an object to the List.
|
||||||
-- Object must be of reference type
|
-- Object must be of reference type
|
||||||
-- Object may not be the string 'size'
|
-- Object may not be the string 'size', 'onAdded' or 'onRemoved'
|
||||||
-- @param obj Object to add
|
-- @param obj Object to add
|
||||||
-- @treturn List self
|
-- @treturn List self
|
||||||
function List:__add(obj)
|
function List:add(obj)
|
||||||
local size = self.size + 1
|
local size = self.size + 1
|
||||||
|
|
||||||
self[size] = obj
|
self[size] = obj
|
||||||
self[obj] = size
|
self[obj] = size
|
||||||
self.size = size
|
self.size = size
|
||||||
|
|
||||||
|
if self.onAdded then self:onAdded(obj) end
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Removes an object from the List.
|
--- Removes an object from the List.
|
||||||
-- @param obj Object to remove
|
-- @param obj Object to remove
|
||||||
-- @treturn List self
|
-- @treturn List self
|
||||||
function List:__remove(obj)
|
function List:remove(obj)
|
||||||
local index = self[obj]
|
local index = self[obj]
|
||||||
if not index then return end
|
if not index then return end
|
||||||
local size = self.size
|
local size = self.size
|
||||||
|
@ -51,12 +52,13 @@ function List:__remove(obj)
|
||||||
self[obj] = nil
|
self[obj] = nil
|
||||||
self.size = size - 1
|
self.size = size - 1
|
||||||
|
|
||||||
|
if self.onRemoved then self:onRemoved(obj) end
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Clears the List completely.
|
--- Clears the List completely.
|
||||||
-- @treturn List self
|
-- @treturn List self
|
||||||
function List:__clear()
|
function List:clear()
|
||||||
for i = 1, self.size do
|
for i = 1, self.size do
|
||||||
local o = self[i]
|
local o = self[i]
|
||||||
|
|
||||||
|
@ -94,6 +96,30 @@ function List:indexOf(obj)
|
||||||
return self[obj]
|
return self[obj]
|
||||||
end
|
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, {
|
return setmetatable(List, {
|
||||||
__call = function()
|
__call = function()
|
||||||
return List.new()
|
return List.new()
|
||||||
|
|
|
@ -1,90 +0,0 @@
|
||||||
--- Used to iterate over Entities with a specific Components
|
|
||||||
-- A Pool contain a any amount of Entities.
|
|
||||||
-- @classmod Pool
|
|
||||||
|
|
||||||
local PATH = (...):gsub('%.[^%.]+$', '')
|
|
||||||
|
|
||||||
local List = require(PATH..".list")
|
|
||||||
|
|
||||||
local Pool = {}
|
|
||||||
Pool.__mt = {
|
|
||||||
__index = Pool,
|
|
||||||
}
|
|
||||||
|
|
||||||
--- Creates a new Pool
|
|
||||||
-- @string name Name for the Pool.
|
|
||||||
-- @tparam table filter Table containing the required BaseComponents
|
|
||||||
-- @treturn Pool The new Pool
|
|
||||||
function Pool.new(name, filter)
|
|
||||||
local pool = setmetatable(List(), Pool.__mt)
|
|
||||||
|
|
||||||
pool.__name = name
|
|
||||||
pool.__filter = filter
|
|
||||||
|
|
||||||
pool.__isPool = true
|
|
||||||
|
|
||||||
return pool
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Checks if an Entity is eligible for the Pool.
|
|
||||||
-- @tparam Entity e Entity to check
|
|
||||||
-- @treturn boolean
|
|
||||||
function Pool:__eligible(e)
|
|
||||||
for _, component in ipairs(self.__filter) do
|
|
||||||
if not e[component] then
|
|
||||||
return false
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
return true
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Internal: Adds an Entity to the Pool.
|
|
||||||
-- @param e Entity to add
|
|
||||||
-- @treturn Pool self
|
|
||||||
function Pool:__add(e)
|
|
||||||
List.__add(self, e)
|
|
||||||
self:onEntityAdded(e)
|
|
||||||
|
|
||||||
return self
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Internal: Removed an Entity from the Pool.
|
|
||||||
-- @param e Entity to remove
|
|
||||||
-- @treturn Pool self
|
|
||||||
function Pool:__remove(e)
|
|
||||||
List.__remove(self, e)
|
|
||||||
self:onEntityRemoved(e)
|
|
||||||
|
|
||||||
return self
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Gets the name of the Pool
|
|
||||||
-- @treturn string
|
|
||||||
function Pool:getName()
|
|
||||||
return self.__name
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Gets the filter of the Pool.
|
|
||||||
-- Warning: Do not modify this filter.
|
|
||||||
-- @return Filter of the Pool.
|
|
||||||
function Pool:getFilter()
|
|
||||||
return self.__filter
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Callback for when an Entity is added to the Pool.
|
|
||||||
-- @tparam Entity e Entity that was added.
|
|
||||||
function Pool:onEntityAdded(e) -- luacheck: ignore
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Callback for when an Entity is removed from the Pool.
|
|
||||||
-- @tparam Entity e Entity that was removed.
|
|
||||||
function Pool:onEntityRemoved(e) -- luacheck: ignore
|
|
||||||
end
|
|
||||||
|
|
||||||
return setmetatable(Pool, {
|
|
||||||
__index = List,
|
|
||||||
__call = function(_, ...)
|
|
||||||
return Pool.new(...)
|
|
||||||
end,
|
|
||||||
})
|
|
|
@ -5,7 +5,7 @@
|
||||||
|
|
||||||
local PATH = (...):gsub('%.[^%.]+$', '')
|
local PATH = (...):gsub('%.[^%.]+$', '')
|
||||||
|
|
||||||
local Pool = require(PATH..".pool")
|
local Filter = require(PATH..".filter")
|
||||||
local Utils = require(PATH..".utils")
|
local Utils = require(PATH..".utils")
|
||||||
|
|
||||||
local System = {
|
local System = {
|
||||||
|
@ -18,28 +18,25 @@ System.mt = {
|
||||||
local system = setmetatable({
|
local system = setmetatable({
|
||||||
__enabled = true,
|
__enabled = true,
|
||||||
|
|
||||||
__pools = {},
|
__filters = {},
|
||||||
__world = world,
|
__world = world,
|
||||||
|
|
||||||
__isSystem = true,
|
__isSystem = true,
|
||||||
__isSystemClass = false, -- Overwrite value from systemClass
|
__isSystemClass = false, -- Overwrite value from systemClass
|
||||||
}, systemClass)
|
}, systemClass)
|
||||||
|
|
||||||
-- Optimization: We deep copy the World class into our instance of a world.
|
-- Optimization: We deep copy the System class into our instance of a system.
|
||||||
-- This grants slightly faster access times at the cost of memory.
|
-- 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
|
-- Since there (generally) won't be many instances of worlds this is a worthwhile tradeoff
|
||||||
if (System.ENABLE_OPTIMIZATION) then
|
if (System.ENABLE_OPTIMIZATION) then
|
||||||
Utils.shallowCopy(systemClass, system)
|
Utils.shallowCopy(systemClass, system)
|
||||||
end
|
end
|
||||||
|
|
||||||
for _, filter in pairs(systemClass.__filter) do
|
for name, def in pairs(systemClass.__definition) do
|
||||||
local pool = system.__buildPool(filter)
|
local filter, pool = Filter(name, Utils.shallowCopy(def, {}))
|
||||||
if not system[pool.__name] then
|
|
||||||
system[pool.__name] = pool
|
system[name] = pool
|
||||||
system.__pools[#system.__pools + 1] = pool
|
table.insert(system.__filters, filter)
|
||||||
else
|
|
||||||
error("Pool with name '"..pool.name.."' already exists.")
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
system:init(world)
|
system:init(world)
|
||||||
|
@ -47,15 +44,23 @@ System.mt = {
|
||||||
return system
|
return system
|
||||||
end,
|
end,
|
||||||
}
|
}
|
||||||
|
|
||||||
--- Creates a new SystemClass.
|
--- Creates a new SystemClass.
|
||||||
-- @param ... Variable amounts of filters
|
-- @param table filters A table containing filters (name = {components...})
|
||||||
-- @treturn System A new SystemClass
|
-- @treturn System A new SystemClass
|
||||||
function System.new(...)
|
function System.new(definition)
|
||||||
local systemClass = setmetatable({
|
definition = definition or {}
|
||||||
__filter = {...},
|
|
||||||
|
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,
|
||||||
|
|
||||||
__name = nil,
|
|
||||||
__isSystemClass = true,
|
__isSystemClass = true,
|
||||||
}, System.mt)
|
}, System.mt)
|
||||||
systemClass.__index = systemClass
|
systemClass.__index = systemClass
|
||||||
|
@ -70,37 +75,12 @@ function System.new(...)
|
||||||
return systemClass
|
return systemClass
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Internal: 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 _, value in ipairs(baseFilter) do
|
|
||||||
if type(value) == "table" then
|
|
||||||
filter[#filter + 1] = value
|
|
||||||
elseif type(value) == "string" then
|
|
||||||
name = value
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
return Pool(name, filter)
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Internal: Evaluates an Entity for all the System's Pools.
|
-- Internal: Evaluates an Entity for all the System's Pools.
|
||||||
-- @param e The Entity to check
|
-- @param e The Entity to check
|
||||||
-- @treturn System self
|
-- @treturn System self
|
||||||
function System:__evaluate(e)
|
function System:__evaluate(e)
|
||||||
for _, pool in ipairs(self.__pools) do
|
for _, filter in ipairs(self.__filters) do
|
||||||
local has = pool:has(e)
|
filter:evaluate(e)
|
||||||
local eligible = pool:__eligible(e)
|
|
||||||
|
|
||||||
if not has and eligible then
|
|
||||||
pool:__add(e)
|
|
||||||
elseif has and not eligible then
|
|
||||||
pool:__remove(e)
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
return self
|
return self
|
||||||
|
@ -110,9 +90,9 @@ end
|
||||||
-- @param e The Entity to remove
|
-- @param e The Entity to remove
|
||||||
-- @treturn System self
|
-- @treturn System self
|
||||||
function System:__remove(e)
|
function System:__remove(e)
|
||||||
for _, pool in ipairs(self.__pools) do
|
for _, filter in ipairs(self.__filters) do
|
||||||
if pool:has(e) then
|
if filter:has(e) then
|
||||||
pool:__remove(e)
|
filter:remove(e)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -122,37 +102,13 @@ end
|
||||||
-- Internal: Clears all Entities from the System.
|
-- Internal: Clears all Entities from the System.
|
||||||
-- @treturn System self
|
-- @treturn System self
|
||||||
function System:__clear()
|
function System:__clear()
|
||||||
for i = 1, #self.__pools do
|
for _, filter in ipairs(self.__filters) do
|
||||||
self.__pools[i]:__clear()
|
filter:clear()
|
||||||
end
|
end
|
||||||
|
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Enables the System.
|
|
||||||
-- @treturn System self
|
|
||||||
function System:enable()
|
|
||||||
self:setEnabled(true)
|
|
||||||
|
|
||||||
return self
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Disables the System.
|
|
||||||
-- @treturn System self
|
|
||||||
function System:disable()
|
|
||||||
self:setEnabled(false)
|
|
||||||
|
|
||||||
return self
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Toggles if the System is enabled.
|
|
||||||
-- @treturn System self
|
|
||||||
function System:toggleEnabled()
|
|
||||||
self:setEnabled(not self.__enabled)
|
|
||||||
|
|
||||||
return self
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Sets if the System is enabled
|
--- Sets if the System is enabled
|
||||||
-- @tparam boolean enable
|
-- @tparam boolean enable
|
||||||
-- @treturn System self
|
-- @treturn System self
|
||||||
|
@ -180,18 +136,6 @@ function System:getWorld()
|
||||||
return self.__world
|
return self.__world
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Returns true if the System has a name.
|
|
||||||
-- @treturn boolean
|
|
||||||
function System:hasName()
|
|
||||||
return self.__name and true or false
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Returns the name of the System.
|
|
||||||
-- @treturn string
|
|
||||||
function System:getName()
|
|
||||||
return self.__name
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Callbacks
|
--- Callbacks
|
||||||
-- @section Callbacks
|
-- @section Callbacks
|
||||||
|
|
||||||
|
|
|
@ -1,48 +0,0 @@
|
||||||
--- Container for registered SystemClasses
|
|
||||||
-- @module Systems
|
|
||||||
|
|
||||||
local PATH = (...):gsub('%.[^%.]+$', '')
|
|
||||||
|
|
||||||
local Type = require(PATH..".type")
|
|
||||||
|
|
||||||
local Systems = {}
|
|
||||||
|
|
||||||
--- Registers a SystemClass.
|
|
||||||
-- @tparam string name Name to register under
|
|
||||||
-- @tparam System systemClass SystemClass to register
|
|
||||||
function Systems.register(name, systemClass)
|
|
||||||
if (type(name) ~= "string") then
|
|
||||||
error("bad argument #1 to 'Systems.register' (string expected, got "..type(name)..")", 3)
|
|
||||||
end
|
|
||||||
|
|
||||||
if (not Type.isSystemClass(systemClass)) then
|
|
||||||
error("bad argument #2 to 'Systems.register' (systemClass expected, got "..type(systemClass)..")", 3)
|
|
||||||
end
|
|
||||||
|
|
||||||
if (rawget(Systems, name)) then
|
|
||||||
error("bad argument #2 to 'Systems.register' (System with name '"..name.."' is already registerd)", 3)
|
|
||||||
end
|
|
||||||
|
|
||||||
Systems[name] = systemClass
|
|
||||||
systemClass.__name = name
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Returns true if the containter has the SystemClass with the name
|
|
||||||
-- @tparam string name Name of the SystemClass to check
|
|
||||||
-- @treturn boolean
|
|
||||||
function Systems.has(name)
|
|
||||||
return Systems[name] and true or false
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Returns the SystemClass with the name
|
|
||||||
-- @tparam string name Name of the SystemClass to get
|
|
||||||
-- @return SystemClass with the name
|
|
||||||
function Systems.get(name)
|
|
||||||
return Systems[name]
|
|
||||||
end
|
|
||||||
|
|
||||||
return setmetatable(Systems, {
|
|
||||||
__index = function(_, name)
|
|
||||||
error("Attempt to index system '"..tostring(name).."' that does not exist / was not registered", 2)
|
|
||||||
end
|
|
||||||
})
|
|
|
@ -3,6 +3,15 @@
|
||||||
|
|
||||||
local Type = {}
|
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.
|
--- Returns if object is an Entity.
|
||||||
-- @param t Object to check
|
-- @param t Object to check
|
||||||
-- @treturn boolean
|
-- @treturn boolean
|
||||||
|
@ -45,11 +54,11 @@ function Type.isWorld(t)
|
||||||
return type(t) == "table" and t.__isWorld or false
|
return type(t) == "table" and t.__isWorld or false
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Returns if object is an Assemblage.
|
--- Returns if object is a Filter.
|
||||||
-- @param t Object to check
|
-- @param t Object to check
|
||||||
-- @treturn boolean
|
-- @treturn boolean
|
||||||
function Type.isAssemblage(t)
|
function Type.isFilter(t)
|
||||||
return type(t) == "table" and t.__isAssemblage or false
|
return type(t) == "table" and t.__isFilter or false
|
||||||
end
|
end
|
||||||
|
|
||||||
return Type
|
return Type
|
||||||
|
|
|
@ -3,6 +3,10 @@
|
||||||
|
|
||||||
local Utils = {}
|
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.
|
--- Does a shallow copy of a table and appends it to a target table.
|
||||||
-- @param orig Table to copy
|
-- @param orig Table to copy
|
||||||
-- @param target Table to append to
|
-- @param target Table to append to
|
||||||
|
@ -10,6 +14,59 @@ function Utils.shallowCopy(orig, target)
|
||||||
for key, value in pairs(orig) do
|
for key, value in pairs(orig) do
|
||||||
target[key] = value
|
target[key] = value
|
||||||
end
|
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
|
end
|
||||||
|
|
||||||
return Utils
|
return Utils
|
|
@ -6,7 +6,9 @@
|
||||||
|
|
||||||
local PATH = (...):gsub('%.[^%.]+$', '')
|
local PATH = (...):gsub('%.[^%.]+$', '')
|
||||||
|
|
||||||
|
local Filter = require(PATH..".filter")
|
||||||
local Entity = require(PATH..".entity")
|
local Entity = require(PATH..".entity")
|
||||||
|
local Components = require(PATH..".components")
|
||||||
local Type = require(PATH..".type")
|
local Type = require(PATH..".type")
|
||||||
local List = require(PATH..".list")
|
local List = require(PATH..".list")
|
||||||
local Utils = require(PATH..".utils")
|
local Utils = require(PATH..".utils")
|
||||||
|
@ -18,6 +20,12 @@ World.__mt = {
|
||||||
__index = World,
|
__index = World,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
local defaultGenerator = function (state)
|
||||||
|
local current = state
|
||||||
|
state = state +1
|
||||||
|
return string.format("%d", current), state
|
||||||
|
end
|
||||||
|
|
||||||
--- Creates a new World.
|
--- Creates a new World.
|
||||||
-- @treturn World The new World
|
-- @treturn World The new World
|
||||||
function World.new()
|
function World.new()
|
||||||
|
@ -28,14 +36,24 @@ function World.new()
|
||||||
__events = {},
|
__events = {},
|
||||||
__emitSDepth = 0,
|
__emitSDepth = 0,
|
||||||
|
|
||||||
|
__resources = {},
|
||||||
|
|
||||||
|
__hash = {
|
||||||
|
state = -2^53,
|
||||||
|
generator = defaultGenerator,
|
||||||
|
keys = {},
|
||||||
|
entities = {}
|
||||||
|
},
|
||||||
|
|
||||||
__added = List(), __backAdded = List(),
|
__added = List(), __backAdded = List(),
|
||||||
__removed = List(), __backRemoved = List(),
|
__removed = List(), __backRemoved = List(),
|
||||||
__dirty = List(), __backDirty = List(),
|
__dirty = List(), __backDirty = List(),
|
||||||
|
|
||||||
__systemLookup = {},
|
__systemLookup = {},
|
||||||
|
|
||||||
__name = nil,
|
|
||||||
__isWorld = true,
|
__isWorld = true,
|
||||||
|
|
||||||
|
__ignoreEmits = false
|
||||||
}, World.__mt)
|
}, World.__mt)
|
||||||
|
|
||||||
-- Optimization: We deep copy the World class into our instance of a world.
|
-- Optimization: We deep copy the World class into our instance of a world.
|
||||||
|
@ -53,7 +71,7 @@ end
|
||||||
-- @treturn World self
|
-- @treturn World self
|
||||||
function World:addEntity(e)
|
function World:addEntity(e)
|
||||||
if not Type.isEntity(e) then
|
if not Type.isEntity(e) then
|
||||||
error("bad argument #1 to 'World:addEntity' (Entity expected, got "..type(e)..")", 2)
|
Utils.error(2, "bad argument #1 to 'World:addEntity' (Entity expected, got %s)", type(e))
|
||||||
end
|
end
|
||||||
|
|
||||||
if e.__world then
|
if e.__world then
|
||||||
|
@ -61,20 +79,55 @@ function World:addEntity(e)
|
||||||
end
|
end
|
||||||
|
|
||||||
e.__world = self
|
e.__world = self
|
||||||
self.__added:__add(e)
|
self.__added:add(e)
|
||||||
|
|
||||||
return self
|
return self
|
||||||
end
|
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.
|
--- Removes an Entity from the World.
|
||||||
-- @tparam Entity e Entity to remove
|
-- @tparam Entity e Entity to remove
|
||||||
-- @treturn World self
|
-- @treturn World self
|
||||||
function World:removeEntity(e)
|
function World:removeEntity(e)
|
||||||
if not Type.isEntity(e) then
|
if not Type.isEntity(e) then
|
||||||
error("bad argument #1 to 'World:removeEntity' (Entity expected, got "..type(e)..")", 2)
|
Utils.error(2, "bad argument #1 to 'World:removeEntity' (Entity expected, got %s)", type(e))
|
||||||
end
|
end
|
||||||
|
|
||||||
self.__removed:__add(e)
|
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
|
return self
|
||||||
end
|
end
|
||||||
|
@ -83,7 +136,7 @@ end
|
||||||
-- @param e Entity to mark as dirty
|
-- @param e Entity to mark as dirty
|
||||||
function World:__dirtyEntity(e)
|
function World:__dirtyEntity(e)
|
||||||
if not self.__dirty:has(e) then
|
if not self.__dirty:has(e) then
|
||||||
self.__dirty:__add(e)
|
self.__dirty:add(e)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -107,7 +160,8 @@ function World:__flush()
|
||||||
for i = 1, self.__backAdded.size do
|
for i = 1, self.__backAdded.size do
|
||||||
e = self.__backAdded[i]
|
e = self.__backAdded[i]
|
||||||
|
|
||||||
self.__entities:__add(e)
|
if e.__world == self then
|
||||||
|
self.__entities:add(e)
|
||||||
|
|
||||||
for j = 1, self.__systems.size do
|
for j = 1, self.__systems.size do
|
||||||
self.__systems[j]:__evaluate(e)
|
self.__systems[j]:__evaluate(e)
|
||||||
|
@ -115,14 +169,16 @@ function World:__flush()
|
||||||
|
|
||||||
self:onEntityAdded(e)
|
self:onEntityAdded(e)
|
||||||
end
|
end
|
||||||
self.__backAdded:__clear()
|
end
|
||||||
|
self.__backAdded:clear()
|
||||||
|
|
||||||
-- Process removed entities
|
-- Process removed entities
|
||||||
for i = 1, self.__backRemoved.size do
|
for i = 1, self.__backRemoved.size do
|
||||||
e = self.__backRemoved[i]
|
e = self.__backRemoved[i]
|
||||||
|
|
||||||
|
if e.__world == self then
|
||||||
e.__world = nil
|
e.__world = nil
|
||||||
self.__entities:__remove(e)
|
self.__entities:remove(e)
|
||||||
|
|
||||||
for j = 1, self.__systems.size do
|
for j = 1, self.__systems.size do
|
||||||
self.__systems[j]:__remove(e)
|
self.__systems[j]:__remove(e)
|
||||||
|
@ -130,17 +186,20 @@ function World:__flush()
|
||||||
|
|
||||||
self:onEntityRemoved(e)
|
self:onEntityRemoved(e)
|
||||||
end
|
end
|
||||||
self.__backRemoved:__clear()
|
end
|
||||||
|
self.__backRemoved:clear()
|
||||||
|
|
||||||
-- Process dirty entities
|
-- Process dirty entities
|
||||||
for i = 1, self.__backDirty.size do
|
for i = 1, self.__backDirty.size do
|
||||||
e = self.__backDirty[i]
|
e = self.__backDirty[i]
|
||||||
|
|
||||||
|
if e.__world == self then
|
||||||
for j = 1, self.__systems.size do
|
for j = 1, self.__systems.size do
|
||||||
self.__systems[j]:__evaluate(e)
|
self.__systems[j]:__evaluate(e)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
self.__backDirty:__clear()
|
end
|
||||||
|
self.__backDirty:clear()
|
||||||
|
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
@ -152,37 +211,31 @@ local blacklistedSystemFunctions = {
|
||||||
"onDisabled",
|
"onDisabled",
|
||||||
}
|
}
|
||||||
|
|
||||||
--- Adds a System to the World.
|
local tryAddSystem = function (world, systemClass)
|
||||||
-- 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)
|
|
||||||
if (not Type.isSystemClass(systemClass)) then
|
if (not Type.isSystemClass(systemClass)) then
|
||||||
error("bad argument #1 to 'World:addSystems' (SystemClass expected, got "..type(systemClass)..")", 2)
|
return false, "SystemClass expected, got "..type(systemClass)
|
||||||
end
|
end
|
||||||
|
|
||||||
if (self.__systemLookup[systemClass]) then
|
if (world.__systemLookup[systemClass]) then
|
||||||
error("bad argument #1 to 'World:addSystems' (SystemClass was already added to World)", 2)
|
return false, "SystemClass was already added to World"
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Create instance of system
|
-- Create instance of system
|
||||||
local system = systemClass(self)
|
local system = systemClass(world)
|
||||||
|
|
||||||
self.__systemLookup[systemClass] = system
|
world.__systemLookup[systemClass] = system
|
||||||
self.__systems:__add(system)
|
world.__systems:add(system)
|
||||||
|
|
||||||
for callbackName, callback in pairs(systemClass) do
|
for callbackName, callback in pairs(systemClass) do
|
||||||
-- Skip callback if its blacklisted
|
-- Skip callback if its blacklisted
|
||||||
if (not blacklistedSystemFunctions[callbackName]) then
|
if (not blacklistedSystemFunctions[callbackName]) then
|
||||||
-- Make container for all listeners of the callback if it does not exist yet
|
-- Make container for all listeners of the callback if it does not exist yet
|
||||||
if (not self.__events[callbackName]) then
|
if (not world.__events[callbackName]) then
|
||||||
self.__events[callbackName] = {}
|
world.__events[callbackName] = {}
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Add callback to listeners
|
-- Add callback to listeners
|
||||||
local listeners = self.__events[callbackName]
|
local listeners = world.__events[callbackName]
|
||||||
listeners[#listeners + 1] = {
|
listeners[#listeners + 1] = {
|
||||||
system = system,
|
system = system,
|
||||||
callback = callback,
|
callback = callback,
|
||||||
|
@ -191,8 +244,24 @@ function World:addSystem(systemClass)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Evaluate all existing entities
|
-- Evaluate all existing entities
|
||||||
for j = 1, self.__entities.size do
|
for j = 1, world.__entities.size do
|
||||||
system:__evaluate(self.__entities[j])
|
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
|
end
|
||||||
|
|
||||||
return self
|
return self
|
||||||
|
@ -208,7 +277,10 @@ function World:addSystems(...)
|
||||||
for i = 1, select("#", ...) do
|
for i = 1, select("#", ...) do
|
||||||
local systemClass = select(i, ...)
|
local systemClass = select(i, ...)
|
||||||
|
|
||||||
self:addSystem(systemClass)
|
local ok, err = tryAddSystem(self, systemClass)
|
||||||
|
if not ok then
|
||||||
|
Utils.error(2, "bad argument #%d to 'World:addSystems' (%s)", i, err)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
return self
|
return self
|
||||||
|
@ -219,7 +291,7 @@ end
|
||||||
-- @treturn boolean
|
-- @treturn boolean
|
||||||
function World:hasSystem(systemClass)
|
function World:hasSystem(systemClass)
|
||||||
if not Type.isSystemClass(systemClass) then
|
if not Type.isSystemClass(systemClass) then
|
||||||
error("bad argument #1 to 'World:getSystem' (systemClass expected, got "..type(systemClass)..")", 2)
|
Utils.error(2, "bad argument #1 to 'World:hasSystem' (SystemClass expected, got %s)", type(systemClass))
|
||||||
end
|
end
|
||||||
|
|
||||||
return self.__systemLookup[systemClass] and true or false
|
return self.__systemLookup[systemClass] and true or false
|
||||||
|
@ -230,7 +302,7 @@ end
|
||||||
-- @treturn System System to get
|
-- @treturn System System to get
|
||||||
function World:getSystem(systemClass)
|
function World:getSystem(systemClass)
|
||||||
if not Type.isSystemClass(systemClass) then
|
if not Type.isSystemClass(systemClass) then
|
||||||
error("bad argument #1 to 'World:getSystem' (systemClass expected, got "..type(systemClass)..")", 2)
|
Utils.error(2, "bad argument #1 to 'World:getSystem' (SystemClass expected, got %s)", type(systemClass))
|
||||||
end
|
end
|
||||||
|
|
||||||
return self.__systemLookup[systemClass]
|
return self.__systemLookup[systemClass]
|
||||||
|
@ -243,7 +315,7 @@ end
|
||||||
-- @treturn World self
|
-- @treturn World self
|
||||||
function World:emit(functionName, ...)
|
function World:emit(functionName, ...)
|
||||||
if not functionName or type(functionName) ~= "string" then
|
if not functionName or type(functionName) ~= "string" then
|
||||||
error("bad argument #1 to 'World:emit' (String expected, got "..type(functionName)..")")
|
Utils.error(2, "bad argument #1 to 'World:emit' (String expected, got %s)", type(functionName))
|
||||||
end
|
end
|
||||||
|
|
||||||
local shouldFlush = self.__emitSDepth == 0
|
local shouldFlush = self.__emitSDepth == 0
|
||||||
|
@ -252,6 +324,13 @@ function World:emit(functionName, ...)
|
||||||
|
|
||||||
local listeners = self.__events[functionName]
|
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
|
if listeners then
|
||||||
for i = 1, #listeners do
|
for i = 1, #listeners do
|
||||||
local listener = listeners[i]
|
local listener = listeners[i]
|
||||||
|
@ -266,6 +345,12 @@ function World:emit(functionName, ...)
|
||||||
end
|
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
|
self.__emitSDepth = self.__emitSDepth - 1
|
||||||
|
|
||||||
return self
|
return self
|
||||||
|
@ -278,9 +363,13 @@ function World:clear()
|
||||||
self:removeEntity(self.__entities[i])
|
self:removeEntity(self.__entities[i])
|
||||||
end
|
end
|
||||||
|
|
||||||
for i = 1, self.__systems.size do
|
for i = 1, self.__added.size do
|
||||||
self.__systems[i]:__clear()
|
local e = self.__added[i]
|
||||||
|
e.__world = nil
|
||||||
end
|
end
|
||||||
|
self.__added:clear()
|
||||||
|
|
||||||
|
self:__flush()
|
||||||
|
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
@ -293,49 +382,103 @@ function World:getSystems()
|
||||||
return self.__systems
|
return self.__systems
|
||||||
end
|
end
|
||||||
|
|
||||||
function World:serialize()
|
function World:serialize(ignoreKeys)
|
||||||
self:__flush()
|
self:__flush()
|
||||||
|
|
||||||
local data = {}
|
local data = { generator = self.__hash.state }
|
||||||
|
|
||||||
for i = 1, self.__entities.size do
|
for i = 1, self.__entities.size do
|
||||||
local entity = self.__entities[i]
|
local entity = self.__entities[i]
|
||||||
|
|
||||||
local entityData = entity:serialize()
|
if entity.serializable then
|
||||||
|
local entityData = entity:serialize(ignoreKeys)
|
||||||
data[i] = entityData
|
table.insert(data, entityData)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
return data
|
return data
|
||||||
end
|
end
|
||||||
|
|
||||||
function World:deserialize(data, append)
|
function World:deserialize(data, startClean, ignoreGenerator)
|
||||||
if (not append) then
|
if startClean then
|
||||||
self:clear()
|
self:clear()
|
||||||
end
|
end
|
||||||
|
|
||||||
|
if (not ignoreGenerator) then
|
||||||
|
self.__hash.state = data.generator
|
||||||
|
end
|
||||||
|
|
||||||
|
local entities = {}
|
||||||
|
|
||||||
for i = 1, #data do
|
for i = 1, #data do
|
||||||
local entityData = data[i]
|
local entity = Entity(self)
|
||||||
|
|
||||||
local entity = Entity()
|
if data[i].key then
|
||||||
entity:deserialize(entityData)
|
local component = Components.key:__new(entity)
|
||||||
|
component:deserialize(data[i].key)
|
||||||
|
entity.key = component
|
||||||
|
|
||||||
self:addEntity(entity)
|
entity:__dirty()
|
||||||
|
end
|
||||||
|
|
||||||
|
entities[i] = entity
|
||||||
|
end
|
||||||
|
|
||||||
|
for i = 1, #data do
|
||||||
|
entities[i]:deserialize(data[i])
|
||||||
end
|
end
|
||||||
|
|
||||||
self:__flush()
|
self:__flush()
|
||||||
|
|
||||||
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Returns true if the World has a name.
|
function World:setKeyGenerator(generator, initialState)
|
||||||
-- @treturn boolean
|
if not Type.isCallable(generator) then
|
||||||
function World:hasName()
|
Utils.error(2, "bad argument #1 to 'World:setKeyGenerator' (function expected, got %s)", type(generator))
|
||||||
return self.__name and true or false
|
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Returns the name of the World.
|
self.__hash.generator = generator
|
||||||
-- @treturn string
|
self.__hash.state = initialState
|
||||||
function World:getName()
|
|
||||||
return self.__name
|
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
|
end
|
||||||
|
|
||||||
--- Callback for when an Entity is added to the World.
|
--- Callback for when an Entity is added to the World.
|
||||||
|
@ -348,8 +491,25 @@ end
|
||||||
function World:onEntityRemoved(e) -- luacheck: ignore
|
function World:onEntityRemoved(e) -- luacheck: ignore
|
||||||
end
|
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, {
|
return setmetatable(World, {
|
||||||
__call = function(_, ...)
|
__call = function(_, ...)
|
||||||
|
---@diagnostic disable-next-line: redundant-parameter
|
||||||
return World.new(...)
|
return World.new(...)
|
||||||
end,
|
end,
|
||||||
})
|
})
|
||||||
|
|
|
@ -1,48 +0,0 @@
|
||||||
--- Worlds
|
|
||||||
-- Container for registered Worlds
|
|
||||||
|
|
||||||
local PATH = (...):gsub('%.[^%.]+$', '')
|
|
||||||
|
|
||||||
local Type = require(PATH..".type")
|
|
||||||
|
|
||||||
local Worlds = {}
|
|
||||||
|
|
||||||
--- Registers a World.
|
|
||||||
-- @tparam string name Name to register under
|
|
||||||
-- @param world World to register
|
|
||||||
function Worlds.register(name, world)
|
|
||||||
if (type(name) ~= "string") then
|
|
||||||
error("bad argument #1 to 'Worlds.register' (string expected, got "..type(name)..")", 3)
|
|
||||||
end
|
|
||||||
|
|
||||||
if (not Type.isWorld(world)) then
|
|
||||||
error("bad argument #2 to 'Worlds.register' (world expected, got "..type(world)..")", 3)
|
|
||||||
end
|
|
||||||
|
|
||||||
if (rawget(Worlds, name)) then
|
|
||||||
error("bad argument #2 to 'Worlds.register' (World with name '"..name.."' is already registerd)", 3)
|
|
||||||
end
|
|
||||||
|
|
||||||
Worlds[name] = world
|
|
||||||
world.__name = name
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Returns true if the containter has the World with the name
|
|
||||||
-- @tparam string name Name of the World to check
|
|
||||||
-- @treturn boolean
|
|
||||||
function Worlds.has(name)
|
|
||||||
return Worlds[name] and true or false
|
|
||||||
end
|
|
||||||
|
|
||||||
--- Returns the World with the name
|
|
||||||
-- @tparam string name Name of the World to get
|
|
||||||
-- @return World with the name
|
|
||||||
function Worlds.get(name)
|
|
||||||
return Worlds[name]
|
|
||||||
end
|
|
||||||
|
|
||||||
return setmetatable(Worlds, {
|
|
||||||
__index = function(_, name)
|
|
||||||
error("Attempt to index world '"..tostring(name).."' that does not exist / was not registered", 2)
|
|
||||||
end
|
|
||||||
})
|
|
|
@ -38,7 +38,6 @@
|
||||||
|
|
||||||
<h2>Classes</h2>
|
<h2>Classes</h2>
|
||||||
<ul class="nowrap">
|
<ul class="nowrap">
|
||||||
<li><a href="../classes/Assemblage.html">Assemblage</a></li>
|
|
||||||
<li><strong>Component</strong></li>
|
<li><strong>Component</strong></li>
|
||||||
<li><a href="../classes/Entity.html">Entity</a></li>
|
<li><a href="../classes/Entity.html">Entity</a></li>
|
||||||
<li><a href="../classes/List.html">List</a></li>
|
<li><a href="../classes/List.html">List</a></li>
|
||||||
|
@ -48,13 +47,10 @@
|
||||||
</ul>
|
</ul>
|
||||||
<h2>Modules</h2>
|
<h2>Modules</h2>
|
||||||
<ul class="nowrap">
|
<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/Components.html">Components</a></li>
|
||||||
<li><a href="../modules/Concord.html">Concord</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/type.html">type</a></li>
|
||||||
<li><a href="../modules/utils.html">utils</a></li>
|
<li><a href="../modules/utils.html">utils</a></li>
|
||||||
<li><a href="../modules/worlds.html">worlds</a></li>
|
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
@ -163,7 +159,7 @@
|
||||||
</div> <!-- id="main" -->
|
</div> <!-- id="main" -->
|
||||||
<div id="about">
|
<div id="about">
|
||||||
<i>generated by <a href="http://github.com/stevedonovan/LDoc">LDoc 1.4.6</a></i>
|
<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>
|
<i style="float:right;">Last updated 2020-08-18 15:20:32 </i>
|
||||||
</div> <!-- id="about" -->
|
</div> <!-- id="about" -->
|
||||||
</div> <!-- id="container" -->
|
</div> <!-- id="container" -->
|
||||||
</body>
|
</body>
|
||||||
|
|
|
@ -38,7 +38,6 @@
|
||||||
|
|
||||||
<h2>Classes</h2>
|
<h2>Classes</h2>
|
||||||
<ul class="nowrap">
|
<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/Component.html">Component</a></li>
|
||||||
<li><strong>Entity</strong></li>
|
<li><strong>Entity</strong></li>
|
||||||
<li><a href="../classes/List.html">List</a></li>
|
<li><a href="../classes/List.html">List</a></li>
|
||||||
|
@ -48,13 +47,10 @@
|
||||||
</ul>
|
</ul>
|
||||||
<h2>Modules</h2>
|
<h2>Modules</h2>
|
||||||
<ul class="nowrap">
|
<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/Components.html">Components</a></li>
|
||||||
<li><a href="../modules/Concord.html">Concord</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/type.html">type</a></li>
|
||||||
<li><a href="../modules/utils.html">utils</a></li>
|
<li><a href="../modules/utils.html">utils</a></li>
|
||||||
<li><a href="../modules/worlds.html">worlds</a></li>
|
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
@ -64,8 +60,7 @@
|
||||||
<h1>Class <code>Entity</code></h1>
|
<h1>Class <code>Entity</code></h1>
|
||||||
<p>An object that exists in a world.</p>
|
<p>An object that exists in a world.</p>
|
||||||
<p> An entity
|
<p> An entity
|
||||||
contains components which are processed by systems.
|
contains components which are processed by systems.</p>
|
||||||
</p>
|
|
||||||
|
|
||||||
|
|
||||||
<h2><a href="#Methods">Methods</a></h2>
|
<h2><a href="#Methods">Methods</a></h2>
|
||||||
|
@ -251,11 +246,11 @@
|
||||||
<h3>Parameters:</h3>
|
<h3>Parameters:</h3>
|
||||||
<ul>
|
<ul>
|
||||||
<li><span class="parameter">assemblage</span>
|
<li><span class="parameter">assemblage</span>
|
||||||
<span class="types"><a class="type" href="../classes/Assemblage.html#">Assemblage</a></span>
|
<span class="types"><span class="type">function</span></span>
|
||||||
Assemblage to assemble with
|
Function that will assemble an entity
|
||||||
</li>
|
</li>
|
||||||
<li><span class="parameter">...</span>
|
<li><span class="parameter">...</span>
|
||||||
additional arguments to pass to the Assemblage's assemble function.
|
additional arguments to pass to the assemblage function.
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
|
@ -413,7 +408,7 @@
|
||||||
</div> <!-- id="main" -->
|
</div> <!-- id="main" -->
|
||||||
<div id="about">
|
<div id="about">
|
||||||
<i>generated by <a href="http://github.com/stevedonovan/LDoc">LDoc 1.4.6</a></i>
|
<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>
|
<i style="float:right;">Last updated 2020-08-18 15:20:32 </i>
|
||||||
</div> <!-- id="about" -->
|
</div> <!-- id="about" -->
|
||||||
</div> <!-- id="container" -->
|
</div> <!-- id="container" -->
|
||||||
</body>
|
</body>
|
||||||
|
|
|
@ -33,13 +33,11 @@
|
||||||
<h2>Contents</h2>
|
<h2>Contents</h2>
|
||||||
<ul>
|
<ul>
|
||||||
<li><a href="#Methods">Methods</a></li>
|
<li><a href="#Methods">Methods</a></li>
|
||||||
<li><a href="#Metamethods">Metamethods</a></li>
|
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
|
|
||||||
<h2>Classes</h2>
|
<h2>Classes</h2>
|
||||||
<ul class="nowrap">
|
<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/Component.html">Component</a></li>
|
||||||
<li><a href="../classes/Entity.html">Entity</a></li>
|
<li><a href="../classes/Entity.html">Entity</a></li>
|
||||||
<li><strong>List</strong></li>
|
<li><strong>List</strong></li>
|
||||||
|
@ -49,13 +47,10 @@
|
||||||
</ul>
|
</ul>
|
||||||
<h2>Modules</h2>
|
<h2>Modules</h2>
|
||||||
<ul class="nowrap">
|
<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/Components.html">Components</a></li>
|
||||||
<li><a href="../modules/Concord.html">Concord</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/type.html">type</a></li>
|
||||||
<li><a href="../modules/utils.html">utils</a></li>
|
<li><a href="../modules/utils.html">utils</a></li>
|
||||||
<li><a href="../modules/worlds.html">worlds</a></li>
|
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
@ -74,6 +69,18 @@
|
||||||
<td class="summary">Creates a new List.</td>
|
<td class="summary">Creates a new List.</td>
|
||||||
</tr>
|
</tr>
|
||||||
<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>
|
||||||
|
<tr>
|
||||||
|
<td class="name" nowrap><a href="#List:remove">List:remove (obj)</a></td>
|
||||||
|
<td class="summary">Removes an object from the 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:has">List:has (obj)</a></td>
|
<td class="name" nowrap><a href="#List:has">List:has (obj)</a></td>
|
||||||
<td class="summary">Returns true if the List has the object.</td>
|
<td class="summary">Returns true if the List has the object.</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
@ -86,21 +93,6 @@
|
||||||
<td class="summary">Returns the index of an object in the List.</td>
|
<td class="summary">Returns the index of an object in the List.</td>
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
<h2><a href="#Metamethods">Metamethods</a></h2>
|
|
||||||
<table class="function_list">
|
|
||||||
<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>
|
|
||||||
<tr>
|
|
||||||
<td class="name" nowrap><a href="#List:__remove">List:__remove (obj)</a></td>
|
|
||||||
<td class="summary">Removes an object from the 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>
|
|
||||||
</table>
|
|
||||||
|
|
||||||
<br/>
|
<br/>
|
||||||
<br/>
|
<br/>
|
||||||
|
@ -128,6 +120,80 @@
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</dd>
|
||||||
|
<dt>
|
||||||
|
<a name = "List:add"></a>
|
||||||
|
<strong>List:add (obj)</strong>
|
||||||
|
</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>
|
||||||
|
Object to add
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<h3>Returns:</h3>
|
||||||
|
<ol>
|
||||||
|
|
||||||
|
<span class="types"><a class="type" href="../classes/List.html#">List</a></span>
|
||||||
|
self
|
||||||
|
</ol>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</dd>
|
||||||
|
<dt>
|
||||||
|
<a name = "List:remove"></a>
|
||||||
|
<strong>List:remove (obj)</strong>
|
||||||
|
</dt>
|
||||||
|
<dd>
|
||||||
|
Removes an object from the List.
|
||||||
|
|
||||||
|
|
||||||
|
<h3>Parameters:</h3>
|
||||||
|
<ul>
|
||||||
|
<li><span class="parameter">obj</span>
|
||||||
|
Object to remove
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<h3>Returns:</h3>
|
||||||
|
<ol>
|
||||||
|
|
||||||
|
<span class="types"><a class="type" href="../classes/List.html#">List</a></span>
|
||||||
|
self
|
||||||
|
</ol>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</dd>
|
||||||
|
<dt>
|
||||||
|
<a name = "List:clear"></a>
|
||||||
|
<strong>List:clear ()</strong>
|
||||||
|
</dt>
|
||||||
|
<dd>
|
||||||
|
Clears the List completely.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<h3>Returns:</h3>
|
||||||
|
<ol>
|
||||||
|
|
||||||
|
<span class="types"><a class="type" href="../classes/List.html#">List</a></span>
|
||||||
|
self
|
||||||
|
</ol>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</dd>
|
</dd>
|
||||||
<dt>
|
<dt>
|
||||||
<a name = "List:has"></a>
|
<a name = "List:has"></a>
|
||||||
|
@ -206,84 +272,6 @@
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</dd>
|
|
||||||
</dl>
|
|
||||||
<h2 class="section-header "><a name="Metamethods"></a>Metamethods</h2>
|
|
||||||
|
|
||||||
<dl class="function">
|
|
||||||
<dt>
|
|
||||||
<a name = "List:__add"></a>
|
|
||||||
<strong>List:__add (obj)</strong>
|
|
||||||
</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>
|
|
||||||
Object to add
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
<h3>Returns:</h3>
|
|
||||||
<ol>
|
|
||||||
|
|
||||||
<span class="types"><a class="type" href="../classes/List.html#">List</a></span>
|
|
||||||
self
|
|
||||||
</ol>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</dd>
|
|
||||||
<dt>
|
|
||||||
<a name = "List:__remove"></a>
|
|
||||||
<strong>List:__remove (obj)</strong>
|
|
||||||
</dt>
|
|
||||||
<dd>
|
|
||||||
Removes an object from the List.
|
|
||||||
|
|
||||||
|
|
||||||
<h3>Parameters:</h3>
|
|
||||||
<ul>
|
|
||||||
<li><span class="parameter">obj</span>
|
|
||||||
Object to remove
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
<h3>Returns:</h3>
|
|
||||||
<ol>
|
|
||||||
|
|
||||||
<span class="types"><a class="type" href="../classes/List.html#">List</a></span>
|
|
||||||
self
|
|
||||||
</ol>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</dd>
|
|
||||||
<dt>
|
|
||||||
<a name = "List:__clear"></a>
|
|
||||||
<strong>List:__clear ()</strong>
|
|
||||||
</dt>
|
|
||||||
<dd>
|
|
||||||
Clears the List completely.
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<h3>Returns:</h3>
|
|
||||||
<ol>
|
|
||||||
|
|
||||||
<span class="types"><a class="type" href="../classes/List.html#">List</a></span>
|
|
||||||
self
|
|
||||||
</ol>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</dd>
|
</dd>
|
||||||
</dl>
|
</dl>
|
||||||
|
|
||||||
|
@ -292,7 +280,7 @@
|
||||||
</div> <!-- id="main" -->
|
</div> <!-- id="main" -->
|
||||||
<div id="about">
|
<div id="about">
|
||||||
<i>generated by <a href="http://github.com/stevedonovan/LDoc">LDoc 1.4.6</a></i>
|
<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>
|
<i style="float:right;">Last updated 2020-08-18 15:20:32 </i>
|
||||||
</div> <!-- id="about" -->
|
</div> <!-- id="about" -->
|
||||||
</div> <!-- id="container" -->
|
</div> <!-- id="container" -->
|
||||||
</body>
|
</body>
|
||||||
|
|
|
@ -33,13 +33,11 @@
|
||||||
<h2>Contents</h2>
|
<h2>Contents</h2>
|
||||||
<ul>
|
<ul>
|
||||||
<li><a href="#Methods">Methods</a></li>
|
<li><a href="#Methods">Methods</a></li>
|
||||||
<li><a href="#Metamethods">Metamethods</a></li>
|
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
|
|
||||||
<h2>Classes</h2>
|
<h2>Classes</h2>
|
||||||
<ul class="nowrap">
|
<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/Component.html">Component</a></li>
|
||||||
<li><a href="../classes/Entity.html">Entity</a></li>
|
<li><a href="../classes/Entity.html">Entity</a></li>
|
||||||
<li><a href="../classes/List.html">List</a></li>
|
<li><a href="../classes/List.html">List</a></li>
|
||||||
|
@ -49,13 +47,10 @@
|
||||||
</ul>
|
</ul>
|
||||||
<h2>Modules</h2>
|
<h2>Modules</h2>
|
||||||
<ul class="nowrap">
|
<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/Components.html">Components</a></li>
|
||||||
<li><a href="../modules/Concord.html">Concord</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/type.html">type</a></li>
|
||||||
<li><a href="../modules/utils.html">utils</a></li>
|
<li><a href="../modules/utils.html">utils</a></li>
|
||||||
<li><a href="../modules/worlds.html">worlds</a></li>
|
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
@ -75,6 +70,14 @@
|
||||||
<td class="summary">Creates a new Pool</td>
|
<td class="summary">Creates a new Pool</td>
|
||||||
</tr>
|
</tr>
|
||||||
<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="name" nowrap><a href="#Pool:getName">Pool:getName ()</a></td>
|
||||||
<td class="summary">Gets the name of the Pool</td>
|
<td class="summary">Gets the name of the Pool</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
@ -87,13 +90,6 @@
|
||||||
<td class="summary">Callback for when an Entity is added to the Pool.</td>
|
<td class="summary">Callback for when an Entity is added to the Pool.</td>
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
<h2><a href="#Metamethods">Metamethods</a></h2>
|
|
||||||
<table class="function_list">
|
|
||||||
<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/>
|
||||||
<br/>
|
<br/>
|
||||||
|
@ -132,6 +128,59 @@
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</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>
|
</dd>
|
||||||
<dt>
|
<dt>
|
||||||
<a name = "Pool:getName"></a>
|
<a name = "Pool:getName"></a>
|
||||||
|
@ -193,37 +242,6 @@
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</dd>
|
|
||||||
</dl>
|
|
||||||
<h2 class="section-header "><a name="Metamethods"></a>Metamethods</h2>
|
|
||||||
|
|
||||||
<dl class="function">
|
|
||||||
<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>
|
</dd>
|
||||||
</dl>
|
</dl>
|
||||||
|
|
||||||
|
@ -232,7 +250,7 @@
|
||||||
</div> <!-- id="main" -->
|
</div> <!-- id="main" -->
|
||||||
<div id="about">
|
<div id="about">
|
||||||
<i>generated by <a href="http://github.com/stevedonovan/LDoc">LDoc 1.4.6</a></i>
|
<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>
|
<i style="float:right;">Last updated 2020-08-18 15:20:32 </i>
|
||||||
</div> <!-- id="about" -->
|
</div> <!-- id="about" -->
|
||||||
</div> <!-- id="container" -->
|
</div> <!-- id="container" -->
|
||||||
</body>
|
</body>
|
||||||
|
|
|
@ -39,7 +39,6 @@
|
||||||
|
|
||||||
<h2>Classes</h2>
|
<h2>Classes</h2>
|
||||||
<ul class="nowrap">
|
<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/Component.html">Component</a></li>
|
||||||
<li><a href="../classes/Entity.html">Entity</a></li>
|
<li><a href="../classes/Entity.html">Entity</a></li>
|
||||||
<li><a href="../classes/List.html">List</a></li>
|
<li><a href="../classes/List.html">List</a></li>
|
||||||
|
@ -49,13 +48,10 @@
|
||||||
</ul>
|
</ul>
|
||||||
<h2>Modules</h2>
|
<h2>Modules</h2>
|
||||||
<ul class="nowrap">
|
<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/Components.html">Components</a></li>
|
||||||
<li><a href="../modules/Concord.html">Concord</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/type.html">type</a></li>
|
||||||
<li><a href="../modules/utils.html">utils</a></li>
|
<li><a href="../modules/utils.html">utils</a></li>
|
||||||
<li><a href="../modules/worlds.html">worlds</a></li>
|
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
@ -66,29 +62,16 @@
|
||||||
<p>Iterates over Entities.</p>
|
<p>Iterates over Entities.</p>
|
||||||
<p> From these Entities its get Components and modify them.
|
<p> From these Entities its get Components and modify them.
|
||||||
A System contains 1 or more Pools.
|
A System contains 1 or more Pools.
|
||||||
A System is contained by 1 World.
|
A System is contained by 1 World.</p>
|
||||||
</p>
|
|
||||||
|
|
||||||
|
|
||||||
<h2><a href="#Methods">Methods</a></h2>
|
<h2><a href="#Methods">Methods</a></h2>
|
||||||
<table class="function_list">
|
<table class="function_list">
|
||||||
<tr>
|
<tr>
|
||||||
<td class="name" nowrap><a href="#System:new">System:new (...)</a></td>
|
<td class="name" nowrap><a href="#System:new">System:new (table)</a></td>
|
||||||
<td class="summary">Creates a new SystemClass.</td>
|
<td class="summary">Creates a new SystemClass.</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td class="name" nowrap><a href="#System:enable">System:enable ()</a></td>
|
|
||||||
<td class="summary">Enables the System.</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td class="name" nowrap><a href="#System:disable">System:disable ()</a></td>
|
|
||||||
<td class="summary">Disables the System.</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td class="name" nowrap><a href="#System:toggleEnabled">System:toggleEnabled ()</a></td>
|
|
||||||
<td class="summary">Toggles if the System is enabled.</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td class="name" nowrap><a href="#System:setEnabled">System:setEnabled (enable)</a></td>
|
<td class="name" nowrap><a href="#System:setEnabled">System:setEnabled (enable)</a></td>
|
||||||
<td class="summary">Sets if the System is enabled</td>
|
<td class="summary">Sets if the System is enabled</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
@ -134,7 +117,7 @@
|
||||||
<dl class="function">
|
<dl class="function">
|
||||||
<dt>
|
<dt>
|
||||||
<a name = "System:new"></a>
|
<a name = "System:new"></a>
|
||||||
<strong>System:new (...)</strong>
|
<strong>System:new (table)</strong>
|
||||||
</dt>
|
</dt>
|
||||||
<dd>
|
<dd>
|
||||||
Creates a new SystemClass.
|
Creates a new SystemClass.
|
||||||
|
@ -142,8 +125,8 @@
|
||||||
|
|
||||||
<h3>Parameters:</h3>
|
<h3>Parameters:</h3>
|
||||||
<ul>
|
<ul>
|
||||||
<li><span class="parameter">...</span>
|
<li><span class="parameter">table</span>
|
||||||
Variable amounts of filters
|
filters A table containing filters (name = {components...})
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
|
@ -157,66 +140,6 @@
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</dd>
|
|
||||||
<dt>
|
|
||||||
<a name = "System:enable"></a>
|
|
||||||
<strong>System:enable ()</strong>
|
|
||||||
</dt>
|
|
||||||
<dd>
|
|
||||||
Enables the System.
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<h3>Returns:</h3>
|
|
||||||
<ol>
|
|
||||||
|
|
||||||
<span class="types"><a class="type" href="../classes/System.html#">System</a></span>
|
|
||||||
self
|
|
||||||
</ol>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</dd>
|
|
||||||
<dt>
|
|
||||||
<a name = "System:disable"></a>
|
|
||||||
<strong>System:disable ()</strong>
|
|
||||||
</dt>
|
|
||||||
<dd>
|
|
||||||
Disables the System.
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<h3>Returns:</h3>
|
|
||||||
<ol>
|
|
||||||
|
|
||||||
<span class="types"><a class="type" href="../classes/System.html#">System</a></span>
|
|
||||||
self
|
|
||||||
</ol>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</dd>
|
|
||||||
<dt>
|
|
||||||
<a name = "System:toggleEnabled"></a>
|
|
||||||
<strong>System:toggleEnabled ()</strong>
|
|
||||||
</dt>
|
|
||||||
<dd>
|
|
||||||
Toggles if the System is enabled.
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<h3>Returns:</h3>
|
|
||||||
<ol>
|
|
||||||
|
|
||||||
<span class="types"><a class="type" href="../classes/System.html#">System</a></span>
|
|
||||||
self
|
|
||||||
</ol>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</dd>
|
</dd>
|
||||||
<dt>
|
<dt>
|
||||||
<a name = "System:setEnabled"></a>
|
<a name = "System:setEnabled"></a>
|
||||||
|
@ -385,7 +308,7 @@
|
||||||
</div> <!-- id="main" -->
|
</div> <!-- id="main" -->
|
||||||
<div id="about">
|
<div id="about">
|
||||||
<i>generated by <a href="http://github.com/stevedonovan/LDoc">LDoc 1.4.6</a></i>
|
<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>
|
<i style="float:right;">Last updated 2020-08-18 15:20:32 </i>
|
||||||
</div> <!-- id="about" -->
|
</div> <!-- id="about" -->
|
||||||
</div> <!-- id="container" -->
|
</div> <!-- id="container" -->
|
||||||
</body>
|
</body>
|
||||||
|
|
|
@ -38,7 +38,6 @@
|
||||||
|
|
||||||
<h2>Classes</h2>
|
<h2>Classes</h2>
|
||||||
<ul class="nowrap">
|
<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/Component.html">Component</a></li>
|
||||||
<li><a href="../classes/Entity.html">Entity</a></li>
|
<li><a href="../classes/Entity.html">Entity</a></li>
|
||||||
<li><a href="../classes/List.html">List</a></li>
|
<li><a href="../classes/List.html">List</a></li>
|
||||||
|
@ -48,13 +47,10 @@
|
||||||
</ul>
|
</ul>
|
||||||
<h2>Modules</h2>
|
<h2>Modules</h2>
|
||||||
<ul class="nowrap">
|
<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/Components.html">Components</a></li>
|
||||||
<li><a href="../modules/Concord.html">Concord</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/type.html">type</a></li>
|
||||||
<li><a href="../modules/utils.html">utils</a></li>
|
<li><a href="../modules/utils.html">utils</a></li>
|
||||||
<li><a href="../modules/worlds.html">worlds</a></li>
|
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
@ -66,8 +62,7 @@
|
||||||
<p>
|
<p>
|
||||||
A world emits to let Systems iterate.
|
A world emits to let Systems iterate.
|
||||||
A World contains any amount of Systems.
|
A World contains any amount of Systems.
|
||||||
A World contains any amount of Entities.
|
A World contains any amount of Entities.</p>
|
||||||
</p>
|
|
||||||
|
|
||||||
|
|
||||||
<h2><a href="#Methods">Methods</a></h2>
|
<h2><a href="#Methods">Methods</a></h2>
|
||||||
|
@ -466,7 +461,7 @@
|
||||||
</div> <!-- id="main" -->
|
</div> <!-- id="main" -->
|
||||||
<div id="about">
|
<div id="about">
|
||||||
<i>generated by <a href="http://github.com/stevedonovan/LDoc">LDoc 1.4.6</a></i>
|
<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>
|
<i style="float:right;">Last updated 2020-08-18 15:20:32 </i>
|
||||||
</div> <!-- id="about" -->
|
</div> <!-- id="about" -->
|
||||||
</div> <!-- id="container" -->
|
</div> <!-- id="container" -->
|
||||||
</body>
|
</body>
|
||||||
|
|
|
@ -31,17 +31,13 @@
|
||||||
|
|
||||||
<h2>Modules</h2>
|
<h2>Modules</h2>
|
||||||
<ul class="nowrap">
|
<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/Components.html">Components</a></li>
|
||||||
<li><a href="modules/Concord.html">Concord</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/type.html">type</a></li>
|
||||||
<li><a href="modules/utils.html">utils</a></li>
|
<li><a href="modules/utils.html">utils</a></li>
|
||||||
<li><a href="modules/worlds.html">worlds</a></li>
|
|
||||||
</ul>
|
</ul>
|
||||||
<h2>Classes</h2>
|
<h2>Classes</h2>
|
||||||
<ul class="nowrap">
|
<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/Component.html">Component</a></li>
|
||||||
<li><a href="classes/Entity.html">Entity</a></li>
|
<li><a href="classes/Entity.html">Entity</a></li>
|
||||||
<li><a href="classes/List.html">List</a></li>
|
<li><a href="classes/List.html">List</a></li>
|
||||||
|
@ -59,10 +55,6 @@
|
||||||
|
|
||||||
<h2>Modules</h2>
|
<h2>Modules</h2>
|
||||||
<table class="module_list">
|
<table class="module_list">
|
||||||
<tr>
|
|
||||||
<td class="name" nowrap><a href="modules/Assemblages.html">Assemblages</a></td>
|
|
||||||
<td class="summary">A container for registered <a href="classes/Assemblage.html#">Assemblage</a>s</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
<tr>
|
||||||
<td class="name" nowrap><a href="modules/Components.html">Components</a></td>
|
<td class="name" nowrap><a href="modules/Components.html">Components</a></td>
|
||||||
<td class="summary">Container for registered ComponentClasses</td>
|
<td class="summary">Container for registered ComponentClasses</td>
|
||||||
|
@ -71,10 +63,6 @@
|
||||||
<td class="name" nowrap><a href="modules/Concord.html">Concord</a></td>
|
<td class="name" nowrap><a href="modules/Concord.html">Concord</a></td>
|
||||||
<td class="summary"></td>
|
<td class="summary"></td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
|
||||||
<td class="name" nowrap><a href="modules/Systems.html">Systems</a></td>
|
|
||||||
<td class="summary">Container for registered SystemClasses</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
<tr>
|
||||||
<td class="name" nowrap><a href="modules/type.html">type</a></td>
|
<td class="name" nowrap><a href="modules/type.html">type</a></td>
|
||||||
<td class="summary">Type
|
<td class="summary">Type
|
||||||
|
@ -85,18 +73,9 @@
|
||||||
<td class="summary">Utils
|
<td class="summary">Utils
|
||||||
Helper module for misc operations</td>
|
Helper module for misc operations</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
|
||||||
<td class="name" nowrap><a href="modules/worlds.html">worlds</a></td>
|
|
||||||
<td class="summary">Worlds
|
|
||||||
Container for registered Worlds</td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
</table>
|
||||||
<h2>Classes</h2>
|
<h2>Classes</h2>
|
||||||
<table class="module_list">
|
<table class="module_list">
|
||||||
<tr>
|
|
||||||
<td class="name" nowrap><a href="classes/Assemblage.html">Assemblage</a></td>
|
|
||||||
<td class="summary">Gives an entity a set of components.</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
<tr>
|
||||||
<td class="name" nowrap><a href="classes/Component.html">Component</a></td>
|
<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>
|
<td class="summary">A pure data container that is contained by a single entity.</td>
|
||||||
|
@ -128,7 +107,7 @@
|
||||||
</div> <!-- id="main" -->
|
</div> <!-- id="main" -->
|
||||||
<div id="about">
|
<div id="about">
|
||||||
<i>generated by <a href="http://github.com/stevedonovan/LDoc">LDoc 1.4.6</a></i>
|
<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>
|
<i style="float:right;">Last updated 2020-08-18 15:20:32 </i>
|
||||||
</div> <!-- id="about" -->
|
</div> <!-- id="about" -->
|
||||||
</div> <!-- id="container" -->
|
</div> <!-- id="container" -->
|
||||||
</body>
|
</body>
|
||||||
|
|
|
@ -30,25 +30,17 @@
|
||||||
<li><a href="../index.html">Index</a></li>
|
<li><a href="../index.html">Index</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
<h2>Contents</h2>
|
|
||||||
<ul>
|
|
||||||
<li><a href="#Functions">Functions</a></li>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
|
|
||||||
<h2>Modules</h2>
|
<h2>Modules</h2>
|
||||||
<ul class="nowrap">
|
<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/Components.html">Components</a></li>
|
||||||
<li><strong>Concord</strong></li>
|
<li><strong>Concord</strong></li>
|
||||||
<li><a href="../modules/Systems.html">Systems</a></li>
|
|
||||||
<li><a href="../modules/type.html">type</a></li>
|
<li><a href="../modules/type.html">type</a></li>
|
||||||
<li><a href="../modules/utils.html">utils</a></li>
|
<li><a href="../modules/utils.html">utils</a></li>
|
||||||
<li><a href="../modules/worlds.html">worlds</a></li>
|
|
||||||
</ul>
|
</ul>
|
||||||
<h2>Classes</h2>
|
<h2>Classes</h2>
|
||||||
<ul class="nowrap">
|
<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/Component.html">Component</a></li>
|
||||||
<li><a href="../classes/Entity.html">Entity</a></li>
|
<li><a href="../classes/Entity.html">Entity</a></li>
|
||||||
<li><a href="../classes/List.html">List</a></li>
|
<li><a href="../classes/List.html">List</a></li>
|
||||||
|
@ -66,129 +58,18 @@
|
||||||
<p></p>
|
<p></p>
|
||||||
|
|
||||||
|
|
||||||
<h2><a href="#Functions">Functions</a></h2>
|
|
||||||
<table class="function_list">
|
|
||||||
<tr>
|
|
||||||
<td class="name" nowrap><a href="#loadComponents">loadComponents (pathOrFiles)</a></td>
|
|
||||||
<td class="summary">Loads ComponentClasses and puts them in the Components container.</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td class="name" nowrap><a href="#loadSystems">loadSystems (pathOrFiles)</a></td>
|
|
||||||
<td class="summary">Loads SystemClasses and puts them in the Systems container.</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td class="name" nowrap><a href="#loadWorlds">loadWorlds (pathOrFiles)</a></td>
|
|
||||||
<td class="summary">Loads Worlds and puts them in the Worlds container.</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td class="name" nowrap><a href="#loadAssemblages">loadAssemblages (pathOrFiles)</a></td>
|
|
||||||
<td class="summary">Loads Assemblages and puts them in the Assemblages container.</td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
|
|
||||||
<br/>
|
<br/>
|
||||||
<br/>
|
<br/>
|
||||||
|
|
||||||
|
|
||||||
<h2 class="section-header "><a name="Functions"></a>Functions</h2>
|
|
||||||
|
|
||||||
<dl class="function">
|
|
||||||
<dt>
|
|
||||||
<a name = "loadComponents"></a>
|
|
||||||
<strong>loadComponents (pathOrFiles)</strong>
|
|
||||||
</dt>
|
|
||||||
<dd>
|
|
||||||
Loads ComponentClasses and puts them in the Components container.
|
|
||||||
Accepts a table of paths to files: {"component_1", "component_2", "etc"}
|
|
||||||
Accepts a path to a directory with ComponentClasses: "components"
|
|
||||||
|
|
||||||
|
|
||||||
<h3>Parameters:</h3>
|
|
||||||
<ul>
|
|
||||||
<li><span class="parameter">pathOrFiles</span>
|
|
||||||
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</dd>
|
|
||||||
<dt>
|
|
||||||
<a name = "loadSystems"></a>
|
|
||||||
<strong>loadSystems (pathOrFiles)</strong>
|
|
||||||
</dt>
|
|
||||||
<dd>
|
|
||||||
Loads SystemClasses and puts them in the Systems container.
|
|
||||||
Accepts a table of paths to files: {"system_1", "system_2", "etc"}
|
|
||||||
Accepts a path to a directory with SystemClasses: "systems"
|
|
||||||
|
|
||||||
|
|
||||||
<h3>Parameters:</h3>
|
|
||||||
<ul>
|
|
||||||
<li><span class="parameter">pathOrFiles</span>
|
|
||||||
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</dd>
|
|
||||||
<dt>
|
|
||||||
<a name = "loadWorlds"></a>
|
|
||||||
<strong>loadWorlds (pathOrFiles)</strong>
|
|
||||||
</dt>
|
|
||||||
<dd>
|
|
||||||
Loads Worlds and puts them in the Worlds container.
|
|
||||||
Accepts a table of paths to files: {"world_1", "world_2", "etc"}
|
|
||||||
Accepts a path to a directory with Worlds: "worlds"
|
|
||||||
|
|
||||||
|
|
||||||
<h3>Parameters:</h3>
|
|
||||||
<ul>
|
|
||||||
<li><span class="parameter">pathOrFiles</span>
|
|
||||||
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</dd>
|
|
||||||
<dt>
|
|
||||||
<a name = "loadAssemblages"></a>
|
|
||||||
<strong>loadAssemblages (pathOrFiles)</strong>
|
|
||||||
</dt>
|
|
||||||
<dd>
|
|
||||||
Loads Assemblages and puts them in the Assemblages container.
|
|
||||||
Accepts a table of paths to files: {"assemblage_1", "assemblage_2", "etc"}
|
|
||||||
Accepts a path to a directory with Assemblages: "assemblages"
|
|
||||||
|
|
||||||
|
|
||||||
<h3>Parameters:</h3>
|
|
||||||
<ul>
|
|
||||||
<li><span class="parameter">pathOrFiles</span>
|
|
||||||
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</dd>
|
|
||||||
</dl>
|
|
||||||
|
|
||||||
|
|
||||||
</div> <!-- id="content" -->
|
</div> <!-- id="content" -->
|
||||||
</div> <!-- id="main" -->
|
</div> <!-- id="main" -->
|
||||||
<div id="about">
|
<div id="about">
|
||||||
<i>generated by <a href="http://github.com/stevedonovan/LDoc">LDoc 1.4.6</a></i>
|
<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>
|
<i style="float:right;">Last updated 2020-08-18 15:20:32 </i>
|
||||||
</div> <!-- id="about" -->
|
</div> <!-- id="about" -->
|
||||||
</div> <!-- id="container" -->
|
</div> <!-- id="container" -->
|
||||||
</body>
|
</body>
|
||||||
|
|
|
@ -38,17 +38,13 @@
|
||||||
|
|
||||||
<h2>Modules</h2>
|
<h2>Modules</h2>
|
||||||
<ul class="nowrap">
|
<ul class="nowrap">
|
||||||
<li><a href="../modules/Assemblages.html">Assemblages</a></li>
|
|
||||||
<li><strong>Components</strong></li>
|
<li><strong>Components</strong></li>
|
||||||
<li><a href="../modules/Concord.html">Concord</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/type.html">type</a></li>
|
||||||
<li><a href="../modules/utils.html">utils</a></li>
|
<li><a href="../modules/utils.html">utils</a></li>
|
||||||
<li><a href="../modules/worlds.html">worlds</a></li>
|
|
||||||
</ul>
|
</ul>
|
||||||
<h2>Classes</h2>
|
<h2>Classes</h2>
|
||||||
<ul class="nowrap">
|
<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/Component.html">Component</a></li>
|
||||||
<li><a href="../classes/Entity.html">Entity</a></li>
|
<li><a href="../classes/Entity.html">Entity</a></li>
|
||||||
<li><a href="../classes/List.html">List</a></li>
|
<li><a href="../classes/List.html">List</a></li>
|
||||||
|
@ -68,13 +64,14 @@
|
||||||
|
|
||||||
<h2><a href="#Functions">Functions</a></h2>
|
<h2><a href="#Functions">Functions</a></h2>
|
||||||
<table class="function_list">
|
<table class="function_list">
|
||||||
<tr>
|
|
||||||
<td class="name" nowrap><a href="#register">register (name, componentClass)</a></td>
|
|
||||||
<td class="summary">Registers a ComponentClass.</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
<tr>
|
||||||
<td class="name" nowrap><a href="#has">has (name)</a></td>
|
<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>
|
<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>
|
||||||
<tr>
|
<tr>
|
||||||
<td class="name" nowrap><a href="#get">get (name)</a></td>
|
<td class="name" nowrap><a href="#get">get (name)</a></td>
|
||||||
|
@ -89,31 +86,6 @@
|
||||||
<h2 class="section-header "><a name="Functions"></a>Functions</h2>
|
<h2 class="section-header "><a name="Functions"></a>Functions</h2>
|
||||||
|
|
||||||
<dl class="function">
|
<dl class="function">
|
||||||
<dt>
|
|
||||||
<a name = "register"></a>
|
|
||||||
<strong>register (name, componentClass)</strong>
|
|
||||||
</dt>
|
|
||||||
<dd>
|
|
||||||
Registers a ComponentClass.
|
|
||||||
|
|
||||||
|
|
||||||
<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">componentClass</span>
|
|
||||||
<span class="types"><a class="type" href="../classes/Component.html#">Component</a></span>
|
|
||||||
ComponentClass to register
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</dd>
|
|
||||||
<dt>
|
<dt>
|
||||||
<a name = "has"></a>
|
<a name = "has"></a>
|
||||||
<strong>has (name)</strong>
|
<strong>has (name)</strong>
|
||||||
|
@ -140,6 +112,37 @@
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</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>
|
</dd>
|
||||||
<dt>
|
<dt>
|
||||||
<a name = "get"></a>
|
<a name = "get"></a>
|
||||||
|
@ -175,7 +178,7 @@
|
||||||
</div> <!-- id="main" -->
|
</div> <!-- id="main" -->
|
||||||
<div id="about">
|
<div id="about">
|
||||||
<i>generated by <a href="http://github.com/stevedonovan/LDoc">LDoc 1.4.6</a></i>
|
<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>
|
<i style="float:right;">Last updated 2020-08-18 15:20:32 </i>
|
||||||
</div> <!-- id="about" -->
|
</div> <!-- id="about" -->
|
||||||
</div> <!-- id="container" -->
|
</div> <!-- id="container" -->
|
||||||
</body>
|
</body>
|
||||||
|
|
|
@ -38,17 +38,13 @@
|
||||||
|
|
||||||
<h2>Modules</h2>
|
<h2>Modules</h2>
|
||||||
<ul class="nowrap">
|
<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/Components.html">Components</a></li>
|
||||||
<li><a href="../modules/Concord.html">Concord</a></li>
|
<li><a href="../modules/Concord.html">Concord</a></li>
|
||||||
<li><a href="../modules/Systems.html">Systems</a></li>
|
|
||||||
<li><strong>type</strong></li>
|
<li><strong>type</strong></li>
|
||||||
<li><a href="../modules/utils.html">utils</a></li>
|
<li><a href="../modules/utils.html">utils</a></li>
|
||||||
<li><a href="../modules/worlds.html">worlds</a></li>
|
|
||||||
</ul>
|
</ul>
|
||||||
<h2>Classes</h2>
|
<h2>Classes</h2>
|
||||||
<ul class="nowrap">
|
<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/Component.html">Component</a></li>
|
||||||
<li><a href="../classes/Entity.html">Entity</a></li>
|
<li><a href="../classes/Entity.html">Entity</a></li>
|
||||||
<li><a href="../classes/List.html">List</a></li>
|
<li><a href="../classes/List.html">List</a></li>
|
||||||
|
@ -93,10 +89,6 @@
|
||||||
<td class="name" nowrap><a href="#Type.isWorld">Type.isWorld (t)</a></td>
|
<td class="name" nowrap><a href="#Type.isWorld">Type.isWorld (t)</a></td>
|
||||||
<td class="summary">Returns if object is a World.</td>
|
<td class="summary">Returns if object is a World.</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
|
||||||
<td class="name" nowrap><a href="#Type.isAssemblage">Type.isAssemblage (t)</a></td>
|
|
||||||
<td class="summary">Returns if object is an Assemblage.</td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
<br/>
|
<br/>
|
||||||
|
@ -261,32 +253,6 @@
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</dd>
|
|
||||||
<dt>
|
|
||||||
<a name = "Type.isAssemblage"></a>
|
|
||||||
<strong>Type.isAssemblage (t)</strong>
|
|
||||||
</dt>
|
|
||||||
<dd>
|
|
||||||
Returns if object is an Assemblage.
|
|
||||||
|
|
||||||
|
|
||||||
<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>
|
</dd>
|
||||||
</dl>
|
</dl>
|
||||||
|
|
||||||
|
@ -295,7 +261,7 @@
|
||||||
</div> <!-- id="main" -->
|
</div> <!-- id="main" -->
|
||||||
<div id="about">
|
<div id="about">
|
||||||
<i>generated by <a href="http://github.com/stevedonovan/LDoc">LDoc 1.4.6</a></i>
|
<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>
|
<i style="float:right;">Last updated 2020-08-18 15:20:32 </i>
|
||||||
</div> <!-- id="about" -->
|
</div> <!-- id="about" -->
|
||||||
</div> <!-- id="container" -->
|
</div> <!-- id="container" -->
|
||||||
</body>
|
</body>
|
||||||
|
|
|
@ -38,17 +38,13 @@
|
||||||
|
|
||||||
<h2>Modules</h2>
|
<h2>Modules</h2>
|
||||||
<ul class="nowrap">
|
<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/Components.html">Components</a></li>
|
||||||
<li><a href="../modules/Concord.html">Concord</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/type.html">type</a></li>
|
||||||
<li><strong>utils</strong></li>
|
<li><strong>utils</strong></li>
|
||||||
<li><a href="../modules/worlds.html">worlds</a></li>
|
|
||||||
</ul>
|
</ul>
|
||||||
<h2>Classes</h2>
|
<h2>Classes</h2>
|
||||||
<ul class="nowrap">
|
<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/Component.html">Component</a></li>
|
||||||
<li><a href="../classes/Entity.html">Entity</a></li>
|
<li><a href="../classes/Entity.html">Entity</a></li>
|
||||||
<li><a href="../classes/List.html">List</a></li>
|
<li><a href="../classes/List.html">List</a></li>
|
||||||
|
@ -73,6 +69,10 @@
|
||||||
<td class="name" nowrap><a href="#Utils.shallowCopy">Utils.shallowCopy (orig, target)</a></td>
|
<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>
|
<td class="summary">Does a shallow copy of a table and appends it to a target table.</td>
|
||||||
</tr>
|
</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>
|
</table>
|
||||||
|
|
||||||
<br/>
|
<br/>
|
||||||
|
@ -104,6 +104,37 @@
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</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>
|
</dd>
|
||||||
</dl>
|
</dl>
|
||||||
|
|
||||||
|
@ -112,7 +143,7 @@
|
||||||
</div> <!-- id="main" -->
|
</div> <!-- id="main" -->
|
||||||
<div id="about">
|
<div id="about">
|
||||||
<i>generated by <a href="http://github.com/stevedonovan/LDoc">LDoc 1.4.6</a></i>
|
<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>
|
<i style="float:right;">Last updated 2020-08-18 15:20:32 </i>
|
||||||
</div> <!-- id="about" -->
|
</div> <!-- id="about" -->
|
||||||
</div> <!-- id="container" -->
|
</div> <!-- id="container" -->
|
||||||
</body>
|
</body>
|
||||||
|
|
|
@ -1,65 +0,0 @@
|
||||||
local Concord = require("src")
|
|
||||||
|
|
||||||
local Entity = Concord.entity
|
|
||||||
local Component = Concord.component
|
|
||||||
local System = Concord.system
|
|
||||||
local Assemblage = Concord.assemblage
|
|
||||||
|
|
||||||
local Game = Concord.context()
|
|
||||||
|
|
||||||
local Legs = Component(function(e, legCount)
|
|
||||||
e.legCount = legCount or 0
|
|
||||||
end)
|
|
||||||
|
|
||||||
local Instinct = Component(function(e) -- luacheck: ignore
|
|
||||||
end)
|
|
||||||
|
|
||||||
local Cool = Component(function(e, coolness)
|
|
||||||
e.coolness = coolness
|
|
||||||
end)
|
|
||||||
|
|
||||||
local Wings = Component(function(e)
|
|
||||||
e.wingCount = 2
|
|
||||||
end)
|
|
||||||
|
|
||||||
|
|
||||||
local Animal = Assemblage(function(e, legCount)
|
|
||||||
e
|
|
||||||
:give(Legs, legCount)
|
|
||||||
:give(Instinct)
|
|
||||||
|
|
||||||
print("Animal")
|
|
||||||
end)
|
|
||||||
|
|
||||||
local Lion = Assemblage(function(e, coolness)
|
|
||||||
e
|
|
||||||
:assemble(Animal, 4)
|
|
||||||
:give(Cool, coolness)
|
|
||||||
|
|
||||||
print("Lion")
|
|
||||||
end)
|
|
||||||
|
|
||||||
local Eagle = Assemblage(function(e)
|
|
||||||
e
|
|
||||||
:assemble(Animal, 2)
|
|
||||||
:give(Wings)
|
|
||||||
|
|
||||||
print("Eagle")
|
|
||||||
end)
|
|
||||||
|
|
||||||
local Griffin = Assemblage(function(e, coolness)
|
|
||||||
e
|
|
||||||
:assemble(Animal, 4)
|
|
||||||
:assemble(Lion, coolness * 2)
|
|
||||||
:assemble(Eagle)
|
|
||||||
end)
|
|
||||||
|
|
||||||
|
|
||||||
local myAnimal = Entity()
|
|
||||||
:assemble(Griffin, 5)
|
|
||||||
--:apply()
|
|
||||||
|
|
||||||
print(myAnimal:has(Legs))
|
|
||||||
print(myAnimal:has(Instinct))
|
|
||||||
print(myAnimal:has(Cool))
|
|
||||||
print(myAnimal:has(Wings))
|
|
|
@ -1,6 +0,0 @@
|
||||||
local PATH = (...):gsub('%.[^%.]+$', '')
|
|
||||||
|
|
||||||
local Concord = require("src")
|
|
||||||
|
|
||||||
local C = require(PATH..".src.components")
|
|
||||||
local S = require(PATH..".src.systems")
|
|
|
@ -1,5 +0,0 @@
|
||||||
local PATH = (...):gsub('%.init$', '')
|
|
||||||
|
|
||||||
return {
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,69 +0,0 @@
|
||||||
local Concord = require("concord")
|
|
||||||
|
|
||||||
local function display(t)
|
|
||||||
print("Table: " ..tostring(t))
|
|
||||||
for key, value in pairs(t) do
|
|
||||||
if type(value) == "table" then
|
|
||||||
display(value)
|
|
||||||
else
|
|
||||||
print(key, value)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local test_component_1 = Concord.component(function(e, x, y)
|
|
||||||
e.x = x or 0
|
|
||||||
e.y = y or 0
|
|
||||||
end)
|
|
||||||
Concord.components.register("test_component_1", test_component_1)
|
|
||||||
|
|
||||||
function test_component_1:serialize()
|
|
||||||
return {
|
|
||||||
x = self.x,
|
|
||||||
y = self.y,
|
|
||||||
}
|
|
||||||
end
|
|
||||||
|
|
||||||
function test_component_1:deserialize(data)
|
|
||||||
self.x = data.x or 0
|
|
||||||
self.y = data.y or 0
|
|
||||||
end
|
|
||||||
|
|
||||||
local test_component_2 = Concord.component(function(e, foo)
|
|
||||||
e.foo = foo
|
|
||||||
end)
|
|
||||||
Concord.components.register("test_component_2", test_component_2)
|
|
||||||
|
|
||||||
function test_component_2:serialize()
|
|
||||||
return {
|
|
||||||
foo = self.foo
|
|
||||||
}
|
|
||||||
end
|
|
||||||
|
|
||||||
function test_component_2:deserialize(data)
|
|
||||||
self.foo = data.foo
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Test worlds
|
|
||||||
local world_1 = Concord.world()
|
|
||||||
local world_2 = Concord.world()
|
|
||||||
|
|
||||||
-- Test Entity
|
|
||||||
Concord.entity(world_1)
|
|
||||||
:give(test_component_1, 100, 50)
|
|
||||||
:give(test_component_2, "Hello World!")
|
|
||||||
|
|
||||||
-- Serialize world
|
|
||||||
local data = world_1:serialize()
|
|
||||||
|
|
||||||
-- Deserialize world
|
|
||||||
world_2:deserialize(data)
|
|
||||||
|
|
||||||
-- Check result
|
|
||||||
local test_entity_copy = world_2:getEntities()[1]
|
|
||||||
|
|
||||||
local test_comp_1 = test_entity_copy[test_component_1]
|
|
||||||
local test_comp_2 = test_entity_copy[test_component_2]
|
|
||||||
|
|
||||||
print(test_comp_1.x, test_comp_1.y)
|
|
||||||
print(test_comp_2.foo)
|
|
|
@ -1,125 +0,0 @@
|
||||||
local Concord = require("src")
|
|
||||||
|
|
||||||
local Entity = Concord.entity
|
|
||||||
local Component = Concord.component
|
|
||||||
local System = Concord.system
|
|
||||||
|
|
||||||
local Game = Concord.world()
|
|
||||||
|
|
||||||
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()
|
|
||||||
for _, e in ipairs(self.pool) do
|
|
||||||
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:flush()
|
|
||||||
for _, e in ipairs(self.pool.removed) do
|
|
||||||
print(tostring(e).. " was removed from my pool D:")
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function CircleRenderer:draw()
|
|
||||||
for _, e in ipairs(self.pool) do
|
|
||||||
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.05 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 _ = 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 _ = 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
|
|
||||||
|
|
||||||
|
|
||||||
function love.update(dt)
|
|
||||||
Game:emit("update", dt)
|
|
||||||
end
|
|
||||||
|
|
||||||
function love.draw()
|
|
||||||
Game:emit("draw")
|
|
||||||
end
|
|
|
@ -1,5 +1,3 @@
|
||||||
local PATH = (...):gsub('%.init$', '')
|
local PATH = (...):gsub('%.init$', '')
|
||||||
|
|
||||||
return {
|
return require(PATH..".concord")
|
||||||
|
|
||||||
}
|
|
1
main.lua
1
main.lua
|
@ -1 +0,0 @@
|
||||||
require("examples.serialization")
|
|
Loading…
Add table
Add a link
Reference in a new issue