@ecsframework/core 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/out/framework/base-system.d.ts +279 -0
- package/out/framework/base-system.luau +170 -0
- package/out/framework/components/destroyed-component.d.ts +3 -0
- package/out/framework/components/destroyed-component.luau +2 -0
- package/out/framework/components/roblox-instance-component.d.ts +3 -0
- package/out/framework/components/roblox-instance-component.luau +27 -0
- package/out/framework/decorators/component.d.ts +6 -0
- package/out/framework/decorators/component.luau +28 -0
- package/out/framework/decorators/inject-type.d.ts +15 -0
- package/out/framework/decorators/inject-type.luau +48 -0
- package/out/framework/decorators/system.d.ts +9 -0
- package/out/framework/decorators/system.luau +20 -0
- package/out/framework/decorators/tagged.d.ts +11 -0
- package/out/framework/decorators/tagged.luau +11 -0
- package/out/framework/decorators/unaffectable.d.ts +1 -0
- package/out/framework/decorators/unaffectable.luau +11 -0
- package/out/framework/dependencies-container.d.ts +21 -0
- package/out/framework/dependencies-container.luau +169 -0
- package/out/framework/flamecs/index.d.ts +4 -0
- package/out/framework/flamecs/init.luau +13 -0
- package/out/framework/flamecs/query.d.ts +55 -0
- package/out/framework/flamecs/query.luau +114 -0
- package/out/framework/flamecs/registry.d.ts +315 -0
- package/out/framework/flamecs/registry.luau +567 -0
- package/out/framework/flamecs/signal.d.ts +5 -0
- package/out/framework/flamecs/signal.luau +24 -0
- package/out/framework/flamecs/topo.d.ts +32 -0
- package/out/framework/flamecs/topo.luau +96 -0
- package/out/framework/hooks/query-change.d.ts +11 -0
- package/out/framework/hooks/query-change.luau +109 -0
- package/out/framework/hooks/use-added.d.ts +17 -0
- package/out/framework/hooks/use-added.luau +54 -0
- package/out/framework/hooks/use-changed.d.ts +17 -0
- package/out/framework/hooks/use-changed.luau +54 -0
- package/out/framework/hooks/use-event.d.ts +30 -0
- package/out/framework/hooks/use-event.luau +92 -0
- package/out/framework/hooks/use-removed.d.ts +13 -0
- package/out/framework/hooks/use-removed.luau +52 -0
- package/out/framework/hooks/use-throttle.d.ts +14 -0
- package/out/framework/hooks/use-throttle.luau +33 -0
- package/out/framework/index.d.ts +28 -0
- package/out/framework/init.luau +295 -0
- package/out/framework/systems/roblox-instance-system.d.ts +7 -0
- package/out/framework/systems/roblox-instance-system.luau +112 -0
- package/out/framework/utilities.d.ts +17 -0
- package/out/framework/utilities.luau +69 -0
- package/out/index.d.ts +19 -0
- package/out/init.luau +30 -0
- package/package.json +48 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { Modding } from "@flamework/core";
|
|
2
|
+
import { Constructor } from "@flamework/core/out/utility";
|
|
3
|
+
export declare class DependenciesContainer {
|
|
4
|
+
private factories;
|
|
5
|
+
private instances;
|
|
6
|
+
private wrapConstructorInFactory;
|
|
7
|
+
/** @metadata macro */
|
|
8
|
+
Register<T extends object>(ctor: Constructor<T>, spec?: Modding.Intrinsic<"symbol-id", [T], string>): void;
|
|
9
|
+
/** @metadata macro */
|
|
10
|
+
Register<T>(factory: () => T, spec?: Modding.Intrinsic<"symbol-id", [T], string>): void;
|
|
11
|
+
/** @metadata macro */
|
|
12
|
+
Unregister<T>(spec?: Modding.Generic<T, "id">): void;
|
|
13
|
+
private resolve;
|
|
14
|
+
/** @metadata macro */
|
|
15
|
+
Resolve<T>(spec?: Modding.Generic<T, "id">): {};
|
|
16
|
+
Inject(instance: object, handle?: (injecting: unknown) => void): void;
|
|
17
|
+
Instantiate<T extends object>(ctor: Constructor<T>, ...args: ConstructorParameters<Constructor<T>>): T;
|
|
18
|
+
InstantiateGroup(ctors: Constructor[], isRegister?: boolean): object[];
|
|
19
|
+
InstantiateWithoutConstruct<T extends object>(ctor: Constructor<T>): readonly [T, (...args: ConstructorParameters<Constructor<T>>) => void, () => void];
|
|
20
|
+
Clear(): void;
|
|
21
|
+
}
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
-- Compiled with roblox-ts v3.0.0
|
|
2
|
+
local TS = _G[script]
|
|
3
|
+
local _utilities = TS.import(script, script.Parent, "utilities")
|
|
4
|
+
local GetClassName = _utilities.GetClassName
|
|
5
|
+
local getDeferredConstructor = _utilities.getDeferredConstructor
|
|
6
|
+
local GetIdentifier = _utilities.GetIdentifier
|
|
7
|
+
local GetInjectTypes = TS.import(script, script.Parent, "decorators", "inject-type").GetInjectTypes
|
|
8
|
+
local DependenciesContainer
|
|
9
|
+
do
|
|
10
|
+
DependenciesContainer = setmetatable({}, {
|
|
11
|
+
__tostring = function()
|
|
12
|
+
return "DependenciesContainer"
|
|
13
|
+
end,
|
|
14
|
+
})
|
|
15
|
+
DependenciesContainer.__index = DependenciesContainer
|
|
16
|
+
function DependenciesContainer.new(...)
|
|
17
|
+
local self = setmetatable({}, DependenciesContainer)
|
|
18
|
+
return self:constructor(...) or self
|
|
19
|
+
end
|
|
20
|
+
function DependenciesContainer:constructor()
|
|
21
|
+
self.factories = {}
|
|
22
|
+
self.instances = {}
|
|
23
|
+
end
|
|
24
|
+
function DependenciesContainer:wrapConstructorInFactory(ctor)
|
|
25
|
+
return function()
|
|
26
|
+
local _instances = self.instances
|
|
27
|
+
local _ctor = ctor
|
|
28
|
+
if _instances[_ctor] ~= nil then
|
|
29
|
+
local _instances_1 = self.instances
|
|
30
|
+
local _ctor_1 = ctor
|
|
31
|
+
return _instances_1[_ctor_1]
|
|
32
|
+
end
|
|
33
|
+
local instance = self:Instantiate(ctor)
|
|
34
|
+
local _instances_1 = self.instances
|
|
35
|
+
local _ctor_1 = ctor
|
|
36
|
+
_instances_1[_ctor_1] = instance
|
|
37
|
+
return instance
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
function DependenciesContainer:Register(factoryOrCtor, spec)
|
|
41
|
+
local _spec = spec
|
|
42
|
+
assert(_spec ~= "" and _spec)
|
|
43
|
+
local _factoryOrCtor = factoryOrCtor
|
|
44
|
+
local factory = if type(_factoryOrCtor) == "function" then factoryOrCtor else self:wrapConstructorInFactory(factoryOrCtor)
|
|
45
|
+
local _factories = self.factories
|
|
46
|
+
local _arg0 = `{spec}`
|
|
47
|
+
_factories[_arg0] = factory
|
|
48
|
+
end
|
|
49
|
+
function DependenciesContainer:Unregister(spec)
|
|
50
|
+
local _spec = spec
|
|
51
|
+
assert(_spec ~= "" and _spec)
|
|
52
|
+
local _factories = self.factories
|
|
53
|
+
local _spec_1 = spec
|
|
54
|
+
_factories[_spec_1] = nil
|
|
55
|
+
end
|
|
56
|
+
function DependenciesContainer:resolve(spec, ctor)
|
|
57
|
+
local _factories = self.factories
|
|
58
|
+
local _spec = spec
|
|
59
|
+
local _result = _factories[_spec]
|
|
60
|
+
if _result ~= nil then
|
|
61
|
+
_result = _result()
|
|
62
|
+
end
|
|
63
|
+
local result = _result
|
|
64
|
+
local _result_1 = result
|
|
65
|
+
local _arg1 = `No factory for {spec}`
|
|
66
|
+
assert(_result_1 ~= 0 and _result_1 == _result_1 and _result_1 ~= "" and _result_1, _arg1)
|
|
67
|
+
return result
|
|
68
|
+
end
|
|
69
|
+
function DependenciesContainer:Resolve(spec)
|
|
70
|
+
return self:resolve(spec)
|
|
71
|
+
end
|
|
72
|
+
function DependenciesContainer:Inject(instance, handle)
|
|
73
|
+
local injectedTypes = GetInjectTypes(instance)
|
|
74
|
+
if not injectedTypes then
|
|
75
|
+
return nil
|
|
76
|
+
end
|
|
77
|
+
-- ▼ ReadonlyMap.forEach ▼
|
|
78
|
+
local _callback = function(specType, fieldName)
|
|
79
|
+
local injectedType = self:resolve(specType, getmetatable(instance))
|
|
80
|
+
local _result = handle
|
|
81
|
+
if _result ~= nil then
|
|
82
|
+
_result(injectedType)
|
|
83
|
+
end
|
|
84
|
+
instance[fieldName] = injectedType
|
|
85
|
+
end
|
|
86
|
+
for _k, _v in injectedTypes do
|
|
87
|
+
_callback(_v, _k, injectedTypes)
|
|
88
|
+
end
|
|
89
|
+
-- ▲ ReadonlyMap.forEach ▲
|
|
90
|
+
end
|
|
91
|
+
function DependenciesContainer:Instantiate(ctor, ...)
|
|
92
|
+
local args = { ... }
|
|
93
|
+
local _binding = getDeferredConstructor(ctor)
|
|
94
|
+
local instance = _binding[1]
|
|
95
|
+
local construct = _binding[2]
|
|
96
|
+
self:Inject(instance)
|
|
97
|
+
construct(unpack(args))
|
|
98
|
+
return instance
|
|
99
|
+
end
|
|
100
|
+
function DependenciesContainer:InstantiateGroup(ctors, isRegister)
|
|
101
|
+
if isRegister == nil then
|
|
102
|
+
isRegister = false
|
|
103
|
+
end
|
|
104
|
+
local injects = {}
|
|
105
|
+
local constructructs = {}
|
|
106
|
+
local instances = {}
|
|
107
|
+
-- ▼ ReadonlyArray.forEach ▼
|
|
108
|
+
local _callback = function(ctor)
|
|
109
|
+
local _binding = self:InstantiateWithoutConstruct(ctor)
|
|
110
|
+
local instance = _binding[1]
|
|
111
|
+
local construct = _binding[2]
|
|
112
|
+
local inject = _binding[3]
|
|
113
|
+
table.insert(instances, instance)
|
|
114
|
+
table.insert(injects, inject)
|
|
115
|
+
table.insert(constructructs, construct)
|
|
116
|
+
end
|
|
117
|
+
for _k, _v in ctors do
|
|
118
|
+
_callback(_v, _k - 1, ctors)
|
|
119
|
+
end
|
|
120
|
+
-- ▲ ReadonlyArray.forEach ▲
|
|
121
|
+
if isRegister then
|
|
122
|
+
-- ▼ ReadonlyArray.forEach ▼
|
|
123
|
+
local _callback_1 = function(instance)
|
|
124
|
+
local id = GetIdentifier(instance)
|
|
125
|
+
local _arg1 = `No identifier for {GetClassName(instance)}`
|
|
126
|
+
assert(id ~= "" and id, _arg1)
|
|
127
|
+
self:Register(function()
|
|
128
|
+
return instance
|
|
129
|
+
end, id)
|
|
130
|
+
end
|
|
131
|
+
for _k, _v in instances do
|
|
132
|
+
_callback_1(_v, _k - 1, instances)
|
|
133
|
+
end
|
|
134
|
+
-- ▲ ReadonlyArray.forEach ▲
|
|
135
|
+
end
|
|
136
|
+
-- ▼ ReadonlyArray.forEach ▼
|
|
137
|
+
local _callback_1 = function(inject)
|
|
138
|
+
return inject()
|
|
139
|
+
end
|
|
140
|
+
for _k, _v in injects do
|
|
141
|
+
_callback_1(_v, _k - 1, injects)
|
|
142
|
+
end
|
|
143
|
+
-- ▲ ReadonlyArray.forEach ▲
|
|
144
|
+
-- ▼ ReadonlyArray.forEach ▼
|
|
145
|
+
local _callback_2 = function(construct)
|
|
146
|
+
return construct()
|
|
147
|
+
end
|
|
148
|
+
for _k, _v in constructructs do
|
|
149
|
+
_callback_2(_v, _k - 1, constructructs)
|
|
150
|
+
end
|
|
151
|
+
-- ▲ ReadonlyArray.forEach ▲
|
|
152
|
+
return instances
|
|
153
|
+
end
|
|
154
|
+
function DependenciesContainer:InstantiateWithoutConstruct(ctor)
|
|
155
|
+
local _binding = getDeferredConstructor(ctor)
|
|
156
|
+
local instance = _binding[1]
|
|
157
|
+
local construct = _binding[2]
|
|
158
|
+
return { instance, construct, function()
|
|
159
|
+
return self:Inject(instance)
|
|
160
|
+
end }
|
|
161
|
+
end
|
|
162
|
+
function DependenciesContainer:Clear()
|
|
163
|
+
table.clear(self.factories)
|
|
164
|
+
table.clear(self.instances)
|
|
165
|
+
end
|
|
166
|
+
end
|
|
167
|
+
return {
|
|
168
|
+
DependenciesContainer = DependenciesContainer,
|
|
169
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
-- Compiled with roblox-ts v3.0.0
|
|
2
|
+
local TS = _G[script]
|
|
3
|
+
local exports = {}
|
|
4
|
+
for _k, _v in TS.import(script, script, "query") or {} do
|
|
5
|
+
exports[_k] = _v
|
|
6
|
+
end
|
|
7
|
+
for _k, _v in TS.import(script, script, "registry") or {} do
|
|
8
|
+
exports[_k] = _v
|
|
9
|
+
end
|
|
10
|
+
for _k, _v in TS.import(script, script, "topo") or {} do
|
|
11
|
+
exports[_k] = _v
|
|
12
|
+
end
|
|
13
|
+
return exports
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import * as ecs from "@rbxts/jecs";
|
|
2
|
+
import type { ComponentKey, Entity, Id, ResolveKeys, ResolveValues, Unwrap } from "./registry";
|
|
3
|
+
export interface Without<T> {
|
|
4
|
+
_flamecs_without: T;
|
|
5
|
+
}
|
|
6
|
+
export interface With<T> {
|
|
7
|
+
_flamecs_with: T;
|
|
8
|
+
}
|
|
9
|
+
export type Skip<T extends Array<unknown>> = T extends [unknown, ...infer R] ? R : [];
|
|
10
|
+
export interface Bounds {
|
|
11
|
+
query: Array<unknown>;
|
|
12
|
+
with: Array<unknown>;
|
|
13
|
+
without: Array<unknown>;
|
|
14
|
+
}
|
|
15
|
+
export type BoundsTuple<T> = T extends {
|
|
16
|
+
length: number;
|
|
17
|
+
} & ReadonlyArray<unknown> ? T : [];
|
|
18
|
+
export type PushBound<B extends Bounds, K extends keyof B, V> = Omit<B, K> & Record<K, V extends ReadonlyArray<unknown> ? [...BoundsTuple<B[K]>, ...V] : [...BoundsTuple<B[K]>, V]>;
|
|
19
|
+
export type Calculate<T extends Array<unknown>, B extends Bounds = Bounds> = T extends [] ? {
|
|
20
|
+
[k in keyof B]: BoundsTuple<B[k]>;
|
|
21
|
+
} : T[0] extends Without<infer V> ? Calculate<Skip<T>, PushBound<B, "without", V>> : T[0] extends With<infer V> ? Calculate<Skip<T>, PushBound<B, "with", V>> : Calculate<Skip<T>, PushBound<B, "query", T[0]>>;
|
|
22
|
+
export type ToIds<T> = T extends [] ? undefined : ResolveKeys<T>;
|
|
23
|
+
export type ExtractQueryTypes<T extends Array<unknown>> = Reconstruct<ResolveValues<Calculate<T>["query"]>>;
|
|
24
|
+
export type QueryHandle<T extends Array<unknown>> = {
|
|
25
|
+
__iter(): IterableFunction<LuaTuple<[Entity, ...T]>>;
|
|
26
|
+
registry: ecs.World;
|
|
27
|
+
filterWith?: Array<Id>;
|
|
28
|
+
filterWithout?: Array<Id>;
|
|
29
|
+
/**
|
|
30
|
+
* Adds a pair with a runtime entity id to the query. The value of the
|
|
31
|
+
* relationship is appended to the end of the iterator tuple.
|
|
32
|
+
*
|
|
33
|
+
* @template P - The type of the predicate component.
|
|
34
|
+
* @param object - The object component ID to filter.
|
|
35
|
+
* @param predicate - The optional predicate component key to filter.
|
|
36
|
+
* @returns A new QueryHandle with the pair filter added.
|
|
37
|
+
* @metadata macro
|
|
38
|
+
*/
|
|
39
|
+
pair<P>(object: Entity, predicate?: ComponentKey<P>): QueryHandle<[...T, Unwrap<P>]>;
|
|
40
|
+
terms?: Array<Id>;
|
|
41
|
+
} & IterableFunction<LuaTuple<[Entity, ...T]>>;
|
|
42
|
+
/**
|
|
43
|
+
* A world contains entities associated with some components. This function
|
|
44
|
+
* creates a query handle for retrieving entities that match the specified
|
|
45
|
+
* components and filters.
|
|
46
|
+
*
|
|
47
|
+
* @template T - The types of the components involved in the query.
|
|
48
|
+
* @param terms - The component IDs to be queried.
|
|
49
|
+
* @param filterWithout - The component IDs that entities must not have.
|
|
50
|
+
* @param filterWith - The component IDs that entities must have.
|
|
51
|
+
* @returns A QueryHandle for chaining additional filters or executing the
|
|
52
|
+
* query.
|
|
53
|
+
* @metadata macro
|
|
54
|
+
*/
|
|
55
|
+
export declare function query<T extends Array<unknown> = []>(registry: ecs.World, terms?: ToIds<Calculate<T>["query"]>, filterWithout?: ToIds<Calculate<T>["without"]>, filterWith?: ToIds<Calculate<T>["with"]>): QueryHandle<ExtractQueryTypes<T>>;
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
-- Compiled with roblox-ts v3.0.0
|
|
2
|
+
local TS = _G[script]
|
|
3
|
+
local ecs = TS.import(script, TS.getModule(script, "@rbxts", "jecs").jecs)
|
|
4
|
+
local _registry = TS.import(script, script.Parent, "registry")
|
|
5
|
+
local component = _registry.component
|
|
6
|
+
local getId = _registry.getId
|
|
7
|
+
-- Almost full credits to @fireboltofdeath for all of these types.
|
|
8
|
+
local function queryPair(self, object, predicate)
|
|
9
|
+
local _predicate = predicate
|
|
10
|
+
assert(_predicate ~= "" and _predicate)
|
|
11
|
+
local id = ecs.pair(component(self.registry, predicate), object)
|
|
12
|
+
local _result
|
|
13
|
+
if self.terms then
|
|
14
|
+
local _array = {}
|
|
15
|
+
local _length = #_array
|
|
16
|
+
local _array_1 = self.terms
|
|
17
|
+
local _Length = #_array_1
|
|
18
|
+
table.move(_array_1, 1, _Length, _length + 1, _array)
|
|
19
|
+
_length += _Length
|
|
20
|
+
_array[_length + 1] = id
|
|
21
|
+
_result = _array
|
|
22
|
+
else
|
|
23
|
+
_result = { id }
|
|
24
|
+
end
|
|
25
|
+
self.terms = _result
|
|
26
|
+
return self
|
|
27
|
+
end
|
|
28
|
+
local function queryIter(self)
|
|
29
|
+
if self.terms then
|
|
30
|
+
local ecsQuery = self.registry:query(unpack(self.terms))
|
|
31
|
+
if self.filterWithout then
|
|
32
|
+
ecsQuery = ecsQuery:without(unpack(self.filterWithout))
|
|
33
|
+
end
|
|
34
|
+
if self.filterWith then
|
|
35
|
+
ecsQuery = ecsQuery:with(unpack(self.filterWith))
|
|
36
|
+
end
|
|
37
|
+
return ecsQuery:iter()
|
|
38
|
+
end
|
|
39
|
+
return function()
|
|
40
|
+
-- Do nothing.
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
--[[
|
|
44
|
+
*
|
|
45
|
+
* A world contains entities associated with some components. This function
|
|
46
|
+
* creates a query handle for retrieving entities that match the specified
|
|
47
|
+
* components and filters.
|
|
48
|
+
*
|
|
49
|
+
* @template T - The types of the components involved in the query.
|
|
50
|
+
* @param terms - The component IDs to be queried.
|
|
51
|
+
* @param filterWithout - The component IDs that entities must not have.
|
|
52
|
+
* @param filterWith - The component IDs that entities must have.
|
|
53
|
+
* @returns A QueryHandle for chaining additional filters or executing the
|
|
54
|
+
* query.
|
|
55
|
+
* @metadata macro
|
|
56
|
+
|
|
57
|
+
]]
|
|
58
|
+
local function query(registry, terms, filterWithout, filterWith)
|
|
59
|
+
local _processedTerms = terms
|
|
60
|
+
if _processedTerms ~= nil then
|
|
61
|
+
-- ▼ ReadonlyArray.map ▼
|
|
62
|
+
local _newValue = table.create(#_processedTerms)
|
|
63
|
+
local _callback = function(v)
|
|
64
|
+
return getId(registry, v)
|
|
65
|
+
end
|
|
66
|
+
for _k, _v in _processedTerms do
|
|
67
|
+
_newValue[_k] = _callback(_v, _k - 1, _processedTerms)
|
|
68
|
+
end
|
|
69
|
+
-- ▲ ReadonlyArray.map ▲
|
|
70
|
+
_processedTerms = _newValue
|
|
71
|
+
end
|
|
72
|
+
local processedTerms = _processedTerms
|
|
73
|
+
local _processedFilterWithout = filterWithout
|
|
74
|
+
if _processedFilterWithout ~= nil then
|
|
75
|
+
-- ▼ ReadonlyArray.map ▼
|
|
76
|
+
local _newValue = table.create(#_processedFilterWithout)
|
|
77
|
+
local _callback = function(v)
|
|
78
|
+
return getId(registry, v)
|
|
79
|
+
end
|
|
80
|
+
for _k, _v in _processedFilterWithout do
|
|
81
|
+
_newValue[_k] = _callback(_v, _k - 1, _processedFilterWithout)
|
|
82
|
+
end
|
|
83
|
+
-- ▲ ReadonlyArray.map ▲
|
|
84
|
+
_processedFilterWithout = _newValue
|
|
85
|
+
end
|
|
86
|
+
local processedFilterWithout = _processedFilterWithout
|
|
87
|
+
local _processedFilterWith = filterWith
|
|
88
|
+
if _processedFilterWith ~= nil then
|
|
89
|
+
-- ▼ ReadonlyArray.map ▼
|
|
90
|
+
local _newValue = table.create(#_processedFilterWith)
|
|
91
|
+
local _callback = function(v)
|
|
92
|
+
return getId(registry, v)
|
|
93
|
+
end
|
|
94
|
+
for _k, _v in _processedFilterWith do
|
|
95
|
+
_newValue[_k] = _callback(_v, _k - 1, _processedFilterWith)
|
|
96
|
+
end
|
|
97
|
+
-- ▲ ReadonlyArray.map ▲
|
|
98
|
+
_processedFilterWith = _newValue
|
|
99
|
+
end
|
|
100
|
+
local processedFilterWith = _processedFilterWith
|
|
101
|
+
local queryHandle = {
|
|
102
|
+
registry = registry,
|
|
103
|
+
__iter = queryIter,
|
|
104
|
+
filterWith = processedFilterWith,
|
|
105
|
+
filterWithout = processedFilterWithout,
|
|
106
|
+
pair = queryPair,
|
|
107
|
+
terms = processedTerms,
|
|
108
|
+
}
|
|
109
|
+
setmetatable(queryHandle, queryHandle)
|
|
110
|
+
return queryHandle
|
|
111
|
+
end
|
|
112
|
+
return {
|
|
113
|
+
query = query,
|
|
114
|
+
}
|