lifetime_tracker.luau Coverage

Total Execution Hits: 1

Function Coverage Overview: 9.09%

Function Coverage:

FunctionHits
1
print_centered_entity:120
name:260
pad:300
lifetime_tracker_add:360
:480
:620
:890
:1350
:1640
:1750

Source Code:

>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
LineHitsCode
11local jecs = require("@jecs")
21local ECS_GENERATION = jecs.ECS_GENERATION
31local ECS_ID = jecs.ECS_ID
41local __ = jecs.Wildcard
51local pair = jecs.pair
6N/A
71local prettify = require("@tools/entity_visualiser").prettify
8N/A
91local pe = prettify
101local ansi = require("@tools/ansi")
11N/A
121function print_centered_entity(entity, width: number)
130local entity_str = tostring(entity)
140local entity_length = #entity_str
15N/A
160local padding_total = width - 2 - entity_length
17N/A
180local padding_left = math.floor(padding_total / 2)
190local padding_right = padding_total - padding_left
20N/A
210local centered_str = string.rep(" ", padding_left) .. entity_str .. string.rep(" ", padding_right)
22N/A
230print("|" .. centered_str .. "|")
24N/Aend
25N/A
261local function name(world, e)
270return world:get(world, e, jecs.Name) or pe(e)
28N/Aend
291local padding_enabled = false
301local function pad()
310if padding_enabled then
320print("")
33N/Aend
34N/Aend
35N/A
361local function lifetime_tracker_add(world: jecs.World, opt)
370local entity_index = world.entity_index
380local dense_array = entity_index.dense_array
390local component_index = world.component_index
40N/A
410local ENTITY_RANGE = (jecs.Rest :: any) + 1
42N/A
430local w = setmetatable({}, { __index = world })
44N/A
450padding_enabled = opt.padding_enabled
46N/A
470local world_entity = world.entity
480w.entity = function(self, entity)
490if entity then
500return world_entity(world, entity)
51N/Aend
520local will_recycle = entity_index.max_id ~= entity_index.alive_count
530local e = world_entity(world)
540if will_recycle then
550print(`*recycled {pe(e)}`)
560else
570print(`*created {pe(e)}`)
58N/Aend
590pad()
600return e
61N/Aend
620w.print_entity_index = function(self)
630local max_id = entity_index.max_id
640local alive_count = entity_index.alive_count
650local alive = table.move(dense_array, 1 + jecs.Rest :: any, alive_count, 1, {})
660local dead = table.move(dense_array, alive_count + 1, max_id, 1, {})
67N/A
680local sep = "|--------|"
690if #alive > 0 then
700print("|-alive--|")
710for i = 1, #alive do
720local e = pe(alive[i])
730print_centered_entity(e, 32)
740print(sep)
75N/Aend
760print("\n")
77N/Aend
78N/A
790if #dead > 0 then
800print("|--dead--|")
810for i = 1, #dead do
820print_centered_entity(pe(dead[i]), 32)
830print(sep)
84N/Aend
85N/Aend
860pad()
87N/Aend
880local timelines = {}
890w.print_snapshot = function(self)
900local timeline = #timelines + 1
910local entity_column_width = 10
920local status_column_width = 8
93N/A
940local header = string.format("| %-" .. entity_column_width .. "s |", "Entity")
950for i = 1, timeline do
960header = header .. string.format(" %-" .. status_column_width .. "s |", string.format("T%d", i))
97N/Aend
98N/A
990local max_id = entity_index.max_id
1000local alive_count = entity_index.alive_count
1010local alive = table.move(dense_array, 1 + jecs.Rest :: any, alive_count, 1, {})
1020local dead = table.move(dense_array, alive_count + 1, max_id, 1, {})
103N/A
1040local data = {}
1050print("-------------------------------------------------------------------")
1060print(header)
107N/A
108N/A-- Store the snapshot data for this timeline
1090for i = ENTITY_RANGE, max_id do
1100if dense_array[i] then
1110local entity = dense_array[i]
1120local id = ECS_ID(entity)
1130local status = "alive"
1140if not world:contains(entity) then
1150status = "dead"
116N/Aend
1170data[id] = status
118N/Aend
119N/Aend
120N/A
1210table.insert(timelines, data)
122N/A
123N/A-- Create a table to hold entity data for sorting
1240local entities = {}
1250for i = ENTITY_RANGE, max_id do
1260if dense_array[i] then
1270local entity = dense_array[i]
1280local id = ECS_ID(entity)
129N/A-- Push entity and id into the new `entities` table
1300table.insert(entities, { entity = entity, id = id })
131N/Aend
132N/Aend
133N/A
134N/A-- Sort the entities by ECS_ID
1350table.sort(entities, function(a, b)
1360return a.id < b.id
137N/Aend)
138N/A
139N/A-- Print the sorted rows
1400for _, entity_data in ipairs(entities) do
1410local entity = entity_data.entity
1420local id = entity_data.id
1430local status = "alive"
1440if id > alive_count then
1450status = "dead"
146N/Aend
1470local row = string.format("| %-" .. entity_column_width .. "s |", pe(entity))
1480for j = 1, timeline do
1490local timeline_data = timelines[j]
1500local entity_data = timeline_data[id]
1510if entity_data then
1520row = row .. string.format(" %-" .. status_column_width .. "s |", entity_data)
1530else
1540row = row .. string.format(" %-" .. status_column_width .. "s |", "-")
155N/Aend
156N/Aend
1570print(row)
158N/Aend
1590print("-------------------------------------------------------------------")
1600pad()
161N/Aend
1620local world_add = world.add
1630local relations = {}
1640w.add = function(self, entity: any, component: any)
1650world_add(world, entity, component)
1660if jecs.IS_PAIR(component) then
1670local relation = jecs.pair_first(world, component)
1680local target = jecs.pair_second(world, component)
1690print(`*added ({pe(relation)}, {pe(target)}) to {pe(entity)}`)
1700pad()
171N/Aend
172N/Aend
173N/A
1740local world_delete = world.delete
1750w.delete = function(self, e)
1760world_delete(world, e)
177N/A
1780local idr_t = component_index[pair(__, e)]
1790if idr_t then
1800for archetype_id in idr_t.cache do
1810local archetype = world.archetypes[archetype_id]
1820for _, id in archetype.types do
1830if not jecs.IS_PAIR(id) then
1840continue
185N/Aend
1860local object = jecs.pair_second(world, id)
1870if object ~= e then
1880continue
189N/Aend
1900local id_record = component_index[id]
1910local flags = id_record.flags
1920local flags_delete_mask: number = bit32.band(flags, jecs.ECS_ID_DELETE)
1930if flags_delete_mask ~= 0 then
1940for _, entity in archetype.entities do
1950print(`*deleted dependant {pe(entity)} of {pe(e)}`)
1960pad()
197N/Aend
1980break
1990else
2000for _, entity in archetype.entities do
2010print(
2020`*removed dependency ({pe(jecs.pair_first(world, id))}, {pe(object)}) from {pe(entity)}`
2030)
204N/Aend
205N/Aend
206N/Aend
207N/Aend
208N/Aend
209N/A
2100print(`*deleted {pe(e)}`)
2110pad()
212N/Aend
2130return w
214N/Aend
215N/A
2161return lifetime_tracker_add