This commit is contained in:
HowManySmall 2024-05-04 14:10:59 -06:00
parent cda04ce5a9
commit b3f8e2504e
8 changed files with 19491 additions and 178 deletions

2
.gitignore vendored
View file

@ -50,3 +50,5 @@ WallyPatches
roblox.toml
sourcemap.json
drafts/*.lua
*.code-workspace

73
lib/Types.luau Normal file
View file

@ -0,0 +1,73 @@
--!native
--!optimize 2
--!strict
export type i53 = number
export type i24 = number
export type Ty = {i53}
export type ArchetypeId = number
export type Column = {any}
export type Archetype = {
id: number,
edges: {
[i24]: {
add: Archetype,
remove: Archetype,
},
},
types: Ty,
type: string | number,
entities: {number},
columns: {Column},
records: {},
}
export type Record = {
archetype: Archetype,
row: number,
}
export type EntityIndex = {[i24]: Record}
export type ComponentIndex = {[i24]: ArchetypeMap}
export type ArchetypeRecord = number
export type ArchetypeMap = {sparse: {[ArchetypeId]: ArchetypeRecord}, size: number}
export type Archetypes = {[ArchetypeId]: Archetype}
export type ArchetypeDiff = {
added: Ty,
removed: Ty,
}
export type Hook = {
ids: Ty,
archetype: Archetype,
otherArchetype: Archetype,
offset: number,
}
export type EventDescription = Hook & {
event: number,
}
export type World = {
archetypeIndex: {[number | string]: Archetype},
archetypes: {[number]: Archetype},
componentIndex: {[i24]: ArchetypeMap},
entityIndex: {[i53]: Record},
hooks: {[number]: {Hook}},
nextComponentId: number,
nextEntityId: number,
ROOT_ARCHETYPE: Archetype,
get: (self: World) -> (),
}
export type WorldStatic = {
new: () -> World,
}
return false

View file

@ -3,45 +3,29 @@
--!strict
--draft 4
type i53 = number
type i24 = number
local Types = require(script.Types)
type Ty = { i53 }
type ArchetypeId = number
type i53 = Types.i53
type i24 = Types.i24
type Column = { any }
type Ty = Types.Ty
type ArchetypeId = Types.ArchetypeId
type Archetype = {
id: number,
edges: {
[i24]: {
add: Archetype,
remove: Archetype,
},
},
types: Ty,
type: string | number,
entities: { number },
columns: { Column },
records: {},
}
type Column = Types.Column
type Record = {
archetype: Archetype,
row: number,
}
type Archetype = Types.Archetype
type Record = Types.Record
type EntityIndex = { [i24]: Record }
type ComponentIndex = { [i24]: ArchetypeMap}
type EntityIndex = Types.EntityIndex
type ComponentIndex = Types.ComponentIndex
type ArchetypeRecord = number
type ArchetypeMap = { sparse: { [ArchetypeId]: ArchetypeRecord } , size: number }
type Archetypes = { [ArchetypeId]: Archetype }
type ArchetypeRecord = Types.ArchetypeRecord
type ArchetypeMap = Types.ArchetypeMap
type Archetypes = Types.Archetypes
type ArchetypeDiff = {
added: Ty,
removed: Ty,
}
type ArchetypeDiff = Types.ArchetypeDiff
-- type World = Types.World
local HI_COMPONENT_ID = 256
local ON_ADD = HI_COMPONENT_ID + 1
@ -152,13 +136,13 @@ local function archetypeOf(world: World, types: { i24 }, prev: Archetype?): Arch
end
local archetype = {
id = id,
types = types,
type = ty,
columns = columns,
entities = {},
edges = {},
records = {},
id = id;
types = types;
type = ty;
columns = columns;
entities = {};
edges = {};
records = {};
}
world.archetypeIndex[ty] = archetype
world.archetypes[id] = archetype
@ -173,17 +157,17 @@ local World = {}
World.__index = World
function World.new()
local self = setmetatable({
entityIndex = {},
componentIndex = {},
archetypes = {},
archetypeIndex = {},
ROOT_ARCHETYPE = (nil :: any) :: Archetype,
nextEntityId = 0,
nextComponentId = 0,
nextArchetypeId = 0,
entityIndex = {};
componentIndex = {};
archetypes = {};
archetypeIndex = {};
ROOT_ARCHETYPE = (nil :: any) :: Archetype;
nextEntityId = 0;
nextComponentId = 0;
nextArchetypeId = 0;
hooks = {
[ON_ADD] = {}
}
[ON_ADD] = {};
};
}, World)
return self
end
@ -192,21 +176,21 @@ local function emit(world, eventDescription)
local event = eventDescription.event
table.insert(world.hooks[event], {
ids = eventDescription.ids,
archetype = eventDescription.archetype,
otherArchetype = eventDescription.otherArchetype,
offset = eventDescription.offset
ids = eventDescription.ids;
archetype = eventDescription.archetype;
otherArchetype = eventDescription.otherArchetype;
offset = eventDescription.offset;
})
end
local function onNotifyAdd(world, archetype, otherArchetype, row: number, added: Ty)
if #added > 0 then
emit(world, {
event = ON_ADD,
ids = added,
archetype = archetype,
otherArchetype = otherArchetype,
offset = row,
event = ON_ADD;
ids = added;
archetype = archetype;
otherArchetype = otherArchetype;
offset = row;
})
end
end
@ -326,7 +310,6 @@ local function archetypeTraverseRemove(world: World, componentId: i53, archetype
local from = (archetype or world.ROOT_ARCHETYPE) :: Archetype
local edge = ensureEdge(from, componentId)
if not edge.remove then
local to = table.clone(from.types)
table.remove(to, table.find(to, componentId))
@ -347,7 +330,7 @@ function World.remove(world: World, entityId: i53, componentId: i53)
end
-- Keeping the function as small as possible to enable inlining
local function get(componentIndex: { [i24]: ArchetypeMap }, record: Record, componentId: i24)
local function get(componentIndex: {[i24]: ArchetypeMap}, record: Record, componentId: i24): number?
local archetype = record.archetype
local archetypeRecord = archetype.records[componentId]
@ -382,13 +365,12 @@ function World.get(world: World, entityId: i53, a: i53, b: i53?, c: i53?, d: i53
end
local function noop(self: Query, ...: i53): () -> (number, ...any)
return function()
end :: any
return function() end :: any
end
local EmptyQuery = {
__iter = noop,
without = noop
__iter = noop;
without = noop;
}
EmptyQuery.__index = EmptyQuery
setmetatable(EmptyQuery, EmptyQuery)
@ -475,7 +457,6 @@ function World.query(world: World, ...: i53): Query
local lastRow
local queryOutput = {}
function preparedQuery:__iter()
return function()
local archetype = compatibleArchetype[1]
@ -499,16 +480,9 @@ function World.query(world: World, ...: i53): Query
elseif queryLength == 2 then
return entityId, columns[tr[1]][row], columns[tr[2]][row]
elseif queryLength == 3 then
return entityId,
columns[tr[1]][row],
columns[tr[2]][row],
columns[tr[3]][row]
return entityId, columns[tr[1]][row], columns[tr[2]][row], columns[tr[3]][row]
elseif queryLength == 4 then
return entityId,
columns[tr[1]][row],
columns[tr[2]][row],
columns[tr[3]][row],
columns[tr[4]][row]
return entityId, columns[tr[1]][row], columns[tr[2]][row], columns[tr[3]][row], columns[tr[4]][row]
elseif queryLength == 5 then
return entityId,
columns[tr[1]][row],
@ -628,13 +602,13 @@ function World.observer(world: World, ...)
return archetype.entities[row], unpack(queryOutput, 1, #queryOutput)
end
end
end;
}
end
return table.freeze({
World = World,
ON_ADD = ON_ADD,
ON_REMOVE = ON_REMOVE,
ON_SET = ON_SET
World = World;
ON_ADD = ON_ADD;
ON_REMOVE = ON_REMOVE;
ON_SET = ON_SET;
})

19255
roblox.yml Normal file

File diff suppressed because it is too large Load diff

4
selene.toml Normal file
View file

@ -0,0 +1,4 @@
std = "roblox"
[lints]
global_usage = "allow"

5
stylua.toml Normal file
View file

@ -0,0 +1,5 @@
column_width = 120
quote_style = "ForceDouble"
[sort_requires]
enabled = true

3
testez-companion.toml Normal file
View file

@ -0,0 +1,3 @@
roots = ["ServerStorage"]
[extraOptions]

View file

@ -10,6 +10,3 @@ include = ["default.project.json", "lib", "wally.toml", "README.md"]
TestEZ = "roblox/testez@0.4.1"
Matter = "matter-ecs/matter@0.8.0"
ecr = "centau/ecr@0.8.0"