mirror of
				https://github.com/Ukendio/jecs.git
				synced 2025-11-03 18:39:19 +00:00 
			
		
		
		
	Replace OnSet hook with OnChange
This commit is contained in:
		
							parent
							
								
									a466ab151b
								
							
						
					
					
						commit
						cf88c259f8
					
				
					 3 changed files with 209 additions and 25 deletions
				
			
		
							
								
								
									
										42
									
								
								jecs.luau
									
									
									
									
									
								
							
							
						
						
									
										42
									
								
								jecs.luau
									
									
									
									
									
								
							| 
						 | 
					@ -61,8 +61,8 @@ type ecs_id_record_t = {
 | 
				
			||||||
	flags: number,
 | 
						flags: number,
 | 
				
			||||||
	size: number,
 | 
						size: number,
 | 
				
			||||||
	hooks: {
 | 
						hooks: {
 | 
				
			||||||
		on_add: ((entity: i53) -> ())?,
 | 
							on_add: ((entity: i53, data: any?) -> ())?,
 | 
				
			||||||
		on_set: ((entity: i53, data: any) -> ())?,
 | 
							on_change: ((entity: i53, data: any) -> ())?,
 | 
				
			||||||
		on_remove: ((entity: i53) -> ())?,
 | 
							on_remove: ((entity: i53) -> ())?,
 | 
				
			||||||
	},
 | 
						},
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -111,7 +111,7 @@ local HI_COMPONENT_ID = _G.__JECS_HI_COMPONENT_ID or 256
 | 
				
			||||||
-- stylua: ignore start
 | 
					-- stylua: ignore start
 | 
				
			||||||
local EcsOnAdd =                    HI_COMPONENT_ID +  1
 | 
					local EcsOnAdd =                    HI_COMPONENT_ID +  1
 | 
				
			||||||
local EcsOnRemove =                 HI_COMPONENT_ID +  2
 | 
					local EcsOnRemove =                 HI_COMPONENT_ID +  2
 | 
				
			||||||
local EcsOnSet =                    HI_COMPONENT_ID +  3
 | 
					local EcsOnChange =                 HI_COMPONENT_ID +  3
 | 
				
			||||||
local EcsWildcard =                 HI_COMPONENT_ID +  4
 | 
					local EcsWildcard =                 HI_COMPONENT_ID +  4
 | 
				
			||||||
local EcsChildOf =                  HI_COMPONENT_ID +  5
 | 
					local EcsChildOf =                  HI_COMPONENT_ID +  5
 | 
				
			||||||
local EcsComponent =                HI_COMPONENT_ID +  6
 | 
					local EcsComponent =                HI_COMPONENT_ID +  6
 | 
				
			||||||
| 
						 | 
					@ -572,9 +572,11 @@ local function id_record_ensure(world: ecs_world_t, id: number): ecs_id_record_t
 | 
				
			||||||
			has_delete = true
 | 
								has_delete = true
 | 
				
			||||||
		end
 | 
							end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		local on_add, on_set, on_remove = world_get(world, relation, EcsOnAdd, EcsOnSet, EcsOnRemove)
 | 
							local on_add, on_change, on_remove = world_get(world,
 | 
				
			||||||
 | 
								relation, EcsOnAdd, EcsOnChange, EcsOnRemove)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		local is_tag = not world_has_one_inline(world, relation, EcsComponent)
 | 
							local is_tag = not world_has_one_inline(world,
 | 
				
			||||||
 | 
								relation, EcsComponent)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if is_tag and is_pair then
 | 
							if is_tag and is_pair then
 | 
				
			||||||
			is_tag = not world_has_one_inline(world, target, EcsComponent)
 | 
								is_tag = not world_has_one_inline(world, target, EcsComponent)
 | 
				
			||||||
| 
						 | 
					@ -582,9 +584,6 @@ local function id_record_ensure(world: ecs_world_t, id: number): ecs_id_record_t
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		flags = bit32.bor(
 | 
							flags = bit32.bor(
 | 
				
			||||||
			flags,
 | 
								flags,
 | 
				
			||||||
			if on_add then ECS_ID_HAS_ON_ADD else 0,
 | 
					 | 
				
			||||||
			if on_remove then ECS_ID_HAS_ON_REMOVE else 0,
 | 
					 | 
				
			||||||
			if on_set then ECS_ID_HAS_ON_SET else 0,
 | 
					 | 
				
			||||||
			if has_delete then ECS_ID_DELETE else 0,
 | 
								if has_delete then ECS_ID_DELETE else 0,
 | 
				
			||||||
			if is_tag then ECS_ID_IS_TAG else 0
 | 
								if is_tag then ECS_ID_IS_TAG else 0
 | 
				
			||||||
		)
 | 
							)
 | 
				
			||||||
| 
						 | 
					@ -596,7 +595,7 @@ local function id_record_ensure(world: ecs_world_t, id: number): ecs_id_record_t
 | 
				
			||||||
			flags = flags,
 | 
								flags = flags,
 | 
				
			||||||
			hooks = {
 | 
								hooks = {
 | 
				
			||||||
				on_add = on_add,
 | 
									on_add = on_add,
 | 
				
			||||||
				on_set = on_set,
 | 
									on_change = on_change,
 | 
				
			||||||
				on_remove = on_remove,
 | 
									on_remove = on_remove,
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
| 
						 | 
					@ -737,13 +736,13 @@ local function find_archetype_with(world: ecs_world_t, node: ecs_archetype_t, id
 | 
				
			||||||
	-- them each time would be expensive. Instead this insertion sort can find the insertion
 | 
						-- them each time would be expensive. Instead this insertion sort can find the insertion
 | 
				
			||||||
	-- point in the types array.
 | 
						-- point in the types array.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						local dst = table.clone(node.types) :: { i53 }
 | 
				
			||||||
	local at = find_insert(id_types, id)
 | 
						local at = find_insert(id_types, id)
 | 
				
			||||||
	if at == -1 then
 | 
						if at == -1 then
 | 
				
			||||||
		-- If it finds a duplicate, it just means it is the same archetype so it can return it
 | 
							-- If it finds a duplicate, it just means it is the same archetype so it can return it
 | 
				
			||||||
		-- directly instead of needing to hash types for a lookup to the archetype.
 | 
							-- directly instead of needing to hash types for a lookup to the archetype.
 | 
				
			||||||
		return node
 | 
							return node
 | 
				
			||||||
	end
 | 
						end
 | 
				
			||||||
	local dst = table.clone(id_types) :: { i53 }
 | 
					 | 
				
			||||||
	table.insert(dst, at, id)
 | 
						table.insert(dst, at, id)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return archetype_ensure(world, dst)
 | 
						return archetype_ensure(world, dst)
 | 
				
			||||||
| 
						 | 
					@ -933,14 +932,14 @@ local function world_set(world: ecs_world_t, entity: i53, id: i53, data: unknown
 | 
				
			||||||
	if from == to then
 | 
						if from == to then
 | 
				
			||||||
		-- If the archetypes are the same it can avoid moving the entity
 | 
							-- If the archetypes are the same it can avoid moving the entity
 | 
				
			||||||
		-- and just set the data directly.
 | 
							-- and just set the data directly.
 | 
				
			||||||
 | 
							local on_change = idr_hooks.on_change
 | 
				
			||||||
 | 
							if on_change then
 | 
				
			||||||
 | 
								on_change(entity, data)
 | 
				
			||||||
 | 
							end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		local tr = to.records[id]
 | 
							local tr = to.records[id]
 | 
				
			||||||
		local column = from.columns[tr]
 | 
							local column = from.columns[tr]
 | 
				
			||||||
		column[record.row] = data
 | 
							column[record.row] = data
 | 
				
			||||||
		local on_set = idr_hooks.on_set
 | 
					 | 
				
			||||||
		if on_set then
 | 
					 | 
				
			||||||
			on_set(entity, data)
 | 
					 | 
				
			||||||
		end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		return
 | 
							return
 | 
				
			||||||
	end
 | 
						end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -961,13 +960,10 @@ local function world_set(world: ecs_world_t, entity: i53, id: i53, data: unknown
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	local on_add = idr_hooks.on_add
 | 
						local on_add = idr_hooks.on_add
 | 
				
			||||||
	if on_add then
 | 
						if on_add then
 | 
				
			||||||
		on_add(entity)
 | 
							on_add(entity, data)
 | 
				
			||||||
	end
 | 
						end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	local on_set = idr_hooks.on_set
 | 
					
 | 
				
			||||||
	if on_set then
 | 
					 | 
				
			||||||
		on_set(entity, data)
 | 
					 | 
				
			||||||
	end
 | 
					 | 
				
			||||||
end
 | 
					end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
local function world_component(world: World): i53
 | 
					local function world_component(world: World): i53
 | 
				
			||||||
| 
						 | 
					@ -2471,7 +2467,7 @@ local function world_new()
 | 
				
			||||||
	end
 | 
						end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	world_add(self, EcsName, EcsComponent)
 | 
						world_add(self, EcsName, EcsComponent)
 | 
				
			||||||
	world_add(self, EcsOnSet, EcsComponent)
 | 
						world_add(self, EcsOnChange, EcsComponent)
 | 
				
			||||||
	world_add(self, EcsOnAdd, EcsComponent)
 | 
						world_add(self, EcsOnAdd, EcsComponent)
 | 
				
			||||||
	world_add(self, EcsOnRemove, EcsComponent)
 | 
						world_add(self, EcsOnRemove, EcsComponent)
 | 
				
			||||||
	world_add(self, EcsWildcard, EcsComponent)
 | 
						world_add(self, EcsWildcard, EcsComponent)
 | 
				
			||||||
| 
						 | 
					@ -2479,7 +2475,7 @@ local function world_new()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	world_set(self, EcsOnAdd, EcsName, "jecs.OnAdd")
 | 
						world_set(self, EcsOnAdd, EcsName, "jecs.OnAdd")
 | 
				
			||||||
	world_set(self, EcsOnRemove, EcsName, "jecs.OnRemove")
 | 
						world_set(self, EcsOnRemove, EcsName, "jecs.OnRemove")
 | 
				
			||||||
	world_set(self, EcsOnSet, EcsName, "jecs.OnSet")
 | 
						world_set(self, EcsOnChange, EcsName, "jecs.OnChange")
 | 
				
			||||||
	world_set(self, EcsWildcard, EcsName, "jecs.Wildcard")
 | 
						world_set(self, EcsWildcard, EcsName, "jecs.Wildcard")
 | 
				
			||||||
	world_set(self, EcsChildOf, EcsName, "jecs.ChildOf")
 | 
						world_set(self, EcsChildOf, EcsName, "jecs.ChildOf")
 | 
				
			||||||
	world_set(self, EcsComponent, EcsName, "jecs.Component")
 | 
						world_set(self, EcsComponent, EcsName, "jecs.Component")
 | 
				
			||||||
| 
						 | 
					@ -2612,7 +2608,7 @@ return {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	OnAdd = EcsOnAdd :: Entity<(entity: Entity) -> ()>,
 | 
						OnAdd = EcsOnAdd :: Entity<(entity: Entity) -> ()>,
 | 
				
			||||||
	OnRemove = EcsOnRemove :: Entity<(entity: Entity) -> ()>,
 | 
						OnRemove = EcsOnRemove :: Entity<(entity: Entity) -> ()>,
 | 
				
			||||||
	OnSet = EcsOnSet :: Entity<(entity: Entity, data: any) -> ()>,
 | 
						OnChange = EcsOnChange :: Entity<(entity: Entity, data: any) -> ()>,
 | 
				
			||||||
	ChildOf = EcsChildOf :: Entity,
 | 
						ChildOf = EcsChildOf :: Entity,
 | 
				
			||||||
	Component = EcsComponent :: Entity,
 | 
						Component = EcsComponent :: Entity,
 | 
				
			||||||
	Wildcard = EcsWildcard :: Entity,
 | 
						Wildcard = EcsWildcard :: Entity,
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1664,9 +1664,9 @@ TEST("Hooks", function()
 | 
				
			||||||
		local Number = world:component()
 | 
							local Number = world:component()
 | 
				
			||||||
		local e1 = world:entity()
 | 
							local e1 = world:entity()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		world:set(Number, jecs.OnSet, function(entity, data)
 | 
							world:set(Number, jecs.OnChange, function(entity, data)
 | 
				
			||||||
			CHECK(e1 == entity)
 | 
								CHECK(e1 == entity)
 | 
				
			||||||
			CHECK(data == world:get(entity, Number))
 | 
								CHECK(world:get(entity, Number) == nil)
 | 
				
			||||||
			CHECK(data == 1)
 | 
								CHECK(data == 1)
 | 
				
			||||||
		end)
 | 
							end)
 | 
				
			||||||
		world:set(e1, Number, 1)
 | 
							world:set(e1, Number, 1)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										188
									
								
								tools/observers.luau
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										188
									
								
								tools/observers.luau
									
									
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,188 @@
 | 
				
			||||||
 | 
					local jecs = require("@jecs")
 | 
				
			||||||
 | 
					local testkit = require("@testkit")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					local function observers_new(description)
 | 
				
			||||||
 | 
						local event = description.event
 | 
				
			||||||
 | 
						local query = description.query
 | 
				
			||||||
 | 
						local callback = description.callback
 | 
				
			||||||
 | 
						local world = query.world
 | 
				
			||||||
 | 
						local terms = query.filter_with
 | 
				
			||||||
 | 
						if not terms then
 | 
				
			||||||
 | 
							local ids = query.ids
 | 
				
			||||||
 | 
							query.filter_with = ids
 | 
				
			||||||
 | 
							terms = ids
 | 
				
			||||||
 | 
						end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						local entity_index = world.entity_index
 | 
				
			||||||
 | 
						local function emplaced(entity)
 | 
				
			||||||
 | 
							local r = jecs.entity_index_try_get_fast(
 | 
				
			||||||
 | 
								entity_index, entity)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							local archetype = r.archetype
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if jecs.query_match(query, archetype) then
 | 
				
			||||||
 | 
								callback(entity)
 | 
				
			||||||
 | 
							end
 | 
				
			||||||
 | 
						end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for _, term in terms do
 | 
				
			||||||
 | 
							if event == jecs.OnAdd then
 | 
				
			||||||
 | 
								world:added(term, emplaced)
 | 
				
			||||||
 | 
							elseif event == jecs.OnSet then
 | 
				
			||||||
 | 
								world:emplaced(term, emplaced)
 | 
				
			||||||
 | 
							end
 | 
				
			||||||
 | 
					 	end
 | 
				
			||||||
 | 
					end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					local function world_track(world, ...)
 | 
				
			||||||
 | 
						local entity_index = world.entity_index
 | 
				
			||||||
 | 
						local terms = { ... }
 | 
				
			||||||
 | 
						local q_shim = { filter_with = terms }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						local n = 0
 | 
				
			||||||
 | 
						local dense_array = {}
 | 
				
			||||||
 | 
						local sparse_array = {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						local function emplaced(entity)
 | 
				
			||||||
 | 
							local r = jecs.entity_index_try_get_fast(
 | 
				
			||||||
 | 
								entity_index, entity)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							local archetype = r.archetype
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if jecs.query_match(q_shim, archetype) then
 | 
				
			||||||
 | 
								n += 1
 | 
				
			||||||
 | 
								dense_array[n] = entity
 | 
				
			||||||
 | 
								sparse_array[entity] = n
 | 
				
			||||||
 | 
							end
 | 
				
			||||||
 | 
						end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						local function removed(entity)
 | 
				
			||||||
 | 
							local i = sparse_array[entity]
 | 
				
			||||||
 | 
							if i ~= n then
 | 
				
			||||||
 | 
								dense_array[i] = dense_array[n]
 | 
				
			||||||
 | 
							end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							dense_array[n] = nil
 | 
				
			||||||
 | 
						end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for _, term in terms do
 | 
				
			||||||
 | 
							world:added(term, emplaced)
 | 
				
			||||||
 | 
							world:emplaced(term, emplaced)
 | 
				
			||||||
 | 
					 	end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						local function iter()
 | 
				
			||||||
 | 
							local i = n
 | 
				
			||||||
 | 
							print(i, "i")
 | 
				
			||||||
 | 
							return function()
 | 
				
			||||||
 | 
								local row = i
 | 
				
			||||||
 | 
								if row == 0 then
 | 
				
			||||||
 | 
									return nil
 | 
				
			||||||
 | 
								end
 | 
				
			||||||
 | 
								i -= 1
 | 
				
			||||||
 | 
								return dense_array[row]
 | 
				
			||||||
 | 
							end
 | 
				
			||||||
 | 
						end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						local it = {
 | 
				
			||||||
 | 
							__iter = iter
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return setmetatable(it, it)
 | 
				
			||||||
 | 
					end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					local function observers_init(world)
 | 
				
			||||||
 | 
						local signals = {
 | 
				
			||||||
 | 
							added = {},
 | 
				
			||||||
 | 
							emplaced = {},
 | 
				
			||||||
 | 
							removed = {}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						world.added = function(_, component, fn)
 | 
				
			||||||
 | 
							local listeners = signals.added[component]
 | 
				
			||||||
 | 
							if not listeners then
 | 
				
			||||||
 | 
								listeners = {}
 | 
				
			||||||
 | 
								signals.added[component] = listeners
 | 
				
			||||||
 | 
								local idr = jecs.id_record_ensure(world, component)
 | 
				
			||||||
 | 
								idr.hooks.on_add = function(entity)
 | 
				
			||||||
 | 
									for _, listener in listeners do
 | 
				
			||||||
 | 
										listener(entity)
 | 
				
			||||||
 | 
									end
 | 
				
			||||||
 | 
								end
 | 
				
			||||||
 | 
							end
 | 
				
			||||||
 | 
							table.insert(listeners, fn)
 | 
				
			||||||
 | 
						end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						world.emplaced = function(_, component, fn)
 | 
				
			||||||
 | 
							local listeners = signals.emplaced[component]
 | 
				
			||||||
 | 
							if not listeners then
 | 
				
			||||||
 | 
								listeners = {}
 | 
				
			||||||
 | 
								signals.emplaced[component] = listeners
 | 
				
			||||||
 | 
								local idr = jecs.id_record_ensure(world, component)
 | 
				
			||||||
 | 
								idr.hooks.on_set = function(entity, value)
 | 
				
			||||||
 | 
									for _, listener in listeners do
 | 
				
			||||||
 | 
										listener(entity, value)
 | 
				
			||||||
 | 
									end
 | 
				
			||||||
 | 
								end
 | 
				
			||||||
 | 
							end
 | 
				
			||||||
 | 
							table.insert(listeners, fn)
 | 
				
			||||||
 | 
						end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						world.removed = function(_, component, fn)
 | 
				
			||||||
 | 
							local listeners = signals.removed[component]
 | 
				
			||||||
 | 
							if not listeners then
 | 
				
			||||||
 | 
								listeners = {}
 | 
				
			||||||
 | 
								signals.removed[component] = listeners
 | 
				
			||||||
 | 
								local idr = jecs.id_record_ensure(world, component)
 | 
				
			||||||
 | 
								idr.hooks.on_remove = function(entity)
 | 
				
			||||||
 | 
									for _, listener in listeners do
 | 
				
			||||||
 | 
										listener(entity)
 | 
				
			||||||
 | 
									end
 | 
				
			||||||
 | 
								end
 | 
				
			||||||
 | 
							end
 | 
				
			||||||
 | 
							table.insert(listeners, fn)
 | 
				
			||||||
 | 
						end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						world.signals = signals
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						world.track = world_track
 | 
				
			||||||
 | 
						return
 | 
				
			||||||
 | 
					end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					local world = jecs.world()
 | 
				
			||||||
 | 
					observers_init(world)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					local A = world:component()
 | 
				
			||||||
 | 
					local B = world:component()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					world:added(A, print)
 | 
				
			||||||
 | 
					world:added(A, function(entity)
 | 
				
			||||||
 | 
						print(entity, 2)
 | 
				
			||||||
 | 
					end)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					local observer = observers_new({
 | 
				
			||||||
 | 
						event = jecs.OnAdd,
 | 
				
			||||||
 | 
						query = world:query(A, B),
 | 
				
			||||||
 | 
						callback = function(entity)
 | 
				
			||||||
 | 
							print(entity, 3)
 | 
				
			||||||
 | 
						end
 | 
				
			||||||
 | 
					})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					local e = world:entity()
 | 
				
			||||||
 | 
					local Test = world:track(A, B)
 | 
				
			||||||
 | 
					for a in Test do
 | 
				
			||||||
 | 
						print(a)
 | 
				
			||||||
 | 
						assert(false)
 | 
				
			||||||
 | 
					end
 | 
				
			||||||
 | 
					world:add(e, A)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					-- Output:
 | 
				
			||||||
 | 
					--  271
 | 
				
			||||||
 | 
					--  271, 2
 | 
				
			||||||
 | 
					for _ in Test do
 | 
				
			||||||
 | 
						assert(false)
 | 
				
			||||||
 | 
					end
 | 
				
			||||||
 | 
					world:add(e, B)
 | 
				
			||||||
 | 
					for a in Test do
 | 
				
			||||||
 | 
						print("lol")
 | 
				
			||||||
 | 
						assert(true)
 | 
				
			||||||
 | 
					end
 | 
				
			||||||
 | 
					-- Output:
 | 
				
			||||||
 | 
					--  271, 3
 | 
				
			||||||
		Loading…
	
		Reference in a new issue