@quenty/loader 5.0.1 → 5.0.2-canary.d7ea97f.0
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/CHANGELOG.md +16 -0
- package/package.json +2 -2
- package/src/LoaderUtils.lua +2 -2
- package/src/PackageInfoUtils.lua +1 -1
- package/src/ScriptInfoUtils.lua +2 -2
- package/src/StaticLegacyLoader.lua +2 -2
- package/src2/Bounce/BounceTemplate.lua +17 -0
- package/src2/Bounce/BounceTemplateUtils.lua +51 -0
- package/src2/Dependencies/DependencyUtils.lua +133 -0
- package/src2/Loader/LoaderAdder.lua +181 -0
- package/src2/LoaderUtils.lua +0 -0
- package/src2/Maid.lua +222 -0
- package/src2/PathUtils.lua +15 -0
- package/src2/Replication/ReplicationType.lua +13 -0
- package/src2/Replication/ReplicationTypeUtils.lua +37 -0
- package/src2/Replication/Replicator.lua +549 -0
- package/src2/Replication/ReplicatorReferences.lua +103 -0
- package/src2/Replication/ReplicatorUtils.lua +24 -0
- package/src2/Utils.lua +114 -0
- package/src2/init.lua +68 -0
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,22 @@
|
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
|
4
4
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
|
5
5
|
|
|
6
|
+
## [5.0.2-canary.d7ea97f.0](https://github.com/Quenty/NevermoreEngine/compare/@quenty/loader@5.0.1...@quenty/loader@5.0.2-canary.d7ea97f.0) (2022-09-27)
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
### Bug Fixes
|
|
10
|
+
|
|
11
|
+
* Add untested hot reloading loader replication logic ([384a8f1](https://github.com/Quenty/NevermoreEngine/commit/384a8f166c781a6d67485d8cee1269915ba2a5ad))
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
### Features
|
|
15
|
+
|
|
16
|
+
* Support hiding server code behind the camera ([afc0e0a](https://github.com/Quenty/NevermoreEngine/commit/afc0e0a35592f68397d6db8108e7955b737ecfe0))
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
|
|
6
22
|
## [5.0.1](https://github.com/Quenty/NevermoreEngine/compare/@quenty/loader@5.0.0...@quenty/loader@5.0.1) (2022-08-16)
|
|
7
23
|
|
|
8
24
|
**Note:** Version bump only for package @quenty/loader
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@quenty/loader",
|
|
3
|
-
"version": "5.0.
|
|
3
|
+
"version": "5.0.2-canary.d7ea97f.0",
|
|
4
4
|
"description": "A simple module loader for Roblox",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"Roblox",
|
|
@@ -26,5 +26,5 @@
|
|
|
26
26
|
"publishConfig": {
|
|
27
27
|
"access": "public"
|
|
28
28
|
},
|
|
29
|
-
"gitHead": "
|
|
29
|
+
"gitHead": "d7ea97f676c9246d2350b7582d5ab3ff6c44e42f"
|
|
30
30
|
}
|
package/src/LoaderUtils.lua
CHANGED
|
@@ -87,7 +87,7 @@ function LoaderUtils.isPackage(folder)
|
|
|
87
87
|
assert(typeof(folder) == "Instance", "Bad instance")
|
|
88
88
|
|
|
89
89
|
for _, item in pairs(folder:GetChildren()) do
|
|
90
|
-
if item:IsA("Folder") then
|
|
90
|
+
if item:IsA("Folder") or item:IsA("Camera") then
|
|
91
91
|
if item.Name == "Server"
|
|
92
92
|
or item.Name == "Client"
|
|
93
93
|
or item.Name == "Shared"
|
|
@@ -126,7 +126,7 @@ function LoaderUtils.discoverTopLevelPackages(packages, instance)
|
|
|
126
126
|
else
|
|
127
127
|
-- Loop through all folders
|
|
128
128
|
for _, item in pairs(instance:GetChildren()) do
|
|
129
|
-
if item:IsA("Folder") then
|
|
129
|
+
if item:IsA("Folder") or item:IsA("Camera") then
|
|
130
130
|
LoaderUtils.discoverTopLevelPackages(packages, item)
|
|
131
131
|
elseif item:IsA("ObjectValue") then
|
|
132
132
|
local linkedValue = item.Value
|
package/src/PackageInfoUtils.lua
CHANGED
|
@@ -212,7 +212,7 @@ function PackageInfoUtils.fillExplicitPackageDependencySet(
|
|
|
212
212
|
assert(defaultReplicationType, "No defaultReplicationType")
|
|
213
213
|
|
|
214
214
|
for _, item in pairs(packageFolder:GetChildren()) do
|
|
215
|
-
if item:IsA("Folder") and item.Name == ScriptInfoUtils.DEPENDENCY_FOLDER_NAME then
|
|
215
|
+
if (item:IsA("Folder") or item:IsA("Camera")) and item.Name == ScriptInfoUtils.DEPENDENCY_FOLDER_NAME then
|
|
216
216
|
local packageInfoList = PackageInfoUtils.getPackageInfoListFromDependencyFolder(
|
|
217
217
|
item,
|
|
218
218
|
packageInfoMap,
|
package/src/ScriptInfoUtils.lua
CHANGED
|
@@ -54,12 +54,12 @@ function ScriptInfoUtils.populateScriptInfoLookup(instance, scriptInfoLookup, la
|
|
|
54
54
|
assert(type(scriptInfoLookup) == "table", "Bad scriptInfoLookup")
|
|
55
55
|
assert(type(lastReplicationMode) == "string", "Bad lastReplicationMode")
|
|
56
56
|
|
|
57
|
-
if instance:IsA("Folder") then
|
|
57
|
+
if instance:IsA("Folder") or instance:IsA("Camera") then
|
|
58
58
|
local replicationMode = ScriptInfoUtils.getFolderReplicationMode(instance.Name, lastReplicationMode)
|
|
59
59
|
if replicationMode ~= ScriptInfoUtils.ModuleReplicationTypes.IGNORE then
|
|
60
60
|
for _, item in pairs(instance:GetChildren()) do
|
|
61
61
|
if not BounceTemplateUtils.isBounceTemplate(item) then
|
|
62
|
-
if item:IsA("Folder") then
|
|
62
|
+
if item:IsA("Folder") or item:IsA("Camera") then
|
|
63
63
|
ScriptInfoUtils.populateScriptInfoLookup(item, scriptInfoLookup, replicationMode)
|
|
64
64
|
elseif item:IsA("ModuleScript") then
|
|
65
65
|
ScriptInfoUtils.addToInfoMap(scriptInfoLookup,
|
|
@@ -109,7 +109,7 @@ function StaticLegacyLoader:_getPackageFolderLookup(instance)
|
|
|
109
109
|
warn("[StaticLegacyLoader] - Bad link in packageFolder")
|
|
110
110
|
return {}
|
|
111
111
|
end
|
|
112
|
-
elseif instance:IsA("Folder") then
|
|
112
|
+
elseif instance:IsA("Folder") or instance:IsA("Camera") then
|
|
113
113
|
return self:_getOrCreateLookup(instance)
|
|
114
114
|
elseif instance:IsA("ModuleScript") then
|
|
115
115
|
return self:_getOrCreateLookup(instance)
|
|
@@ -136,7 +136,7 @@ function StaticLegacyLoader:_getOrCreateLookup(packageFolderOrModuleScript)
|
|
|
136
136
|
end
|
|
137
137
|
|
|
138
138
|
function StaticLegacyLoader:_buildLookup(lookup, instance)
|
|
139
|
-
if instance:IsA("Folder") then
|
|
139
|
+
if instance:IsA("Folder") or instance:IsA("Camera") then
|
|
140
140
|
if instance.Name ~= ScriptInfoUtils.DEPENDENCY_FOLDER_NAME then
|
|
141
141
|
for _, item in pairs(instance:GetChildren()) do
|
|
142
142
|
self:_buildLookup(lookup, item)
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
--[=[
|
|
2
|
+
Bounces the current named script to the expected version of this module
|
|
3
|
+
|
|
4
|
+
@private
|
|
5
|
+
@class BounceTemplate
|
|
6
|
+
]=]
|
|
7
|
+
|
|
8
|
+
local function waitForValue(objectValue)
|
|
9
|
+
local value = objectValue.Value
|
|
10
|
+
if value then
|
|
11
|
+
return value
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
return objectValue.Changed:Wait()
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
return require(waitForValue(script:WaitForChild("BounceTarget")))
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
--[=[
|
|
2
|
+
@class BounceTemplateUtils
|
|
3
|
+
@private
|
|
4
|
+
]=]
|
|
5
|
+
|
|
6
|
+
local BounceTemplate = script.Parent.BounceTemplate
|
|
7
|
+
|
|
8
|
+
local BounceTemplateUtils = {}
|
|
9
|
+
|
|
10
|
+
function BounceTemplateUtils.isBounceTemplate(instance)
|
|
11
|
+
return instance:GetAttribute("IsBounceTemplate", true) == true
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
function BounceTemplateUtils.getTarget(instance)
|
|
15
|
+
if not BounceTemplateUtils.isBounceTemplate(instance) then
|
|
16
|
+
return nil
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
if instance:IsA("ObjectValue") then
|
|
20
|
+
return instance.Value
|
|
21
|
+
else
|
|
22
|
+
local found = instance:FindFirstChild("BounceTarget")
|
|
23
|
+
if found then
|
|
24
|
+
return found.Value
|
|
25
|
+
else
|
|
26
|
+
warn("[BounceTemplateUtils.getTarget] - Bounce template without BounceTarget")
|
|
27
|
+
return nil
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
function BounceTemplateUtils.create(target, linkName)
|
|
33
|
+
assert(typeof(target) == "Instance", "Bad target")
|
|
34
|
+
assert(type(linkName) == "string", "Bad linkName")
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
local copy = BounceTemplate:Clone()
|
|
38
|
+
copy:SetAttribute("IsBounceTemplate", true)
|
|
39
|
+
copy.Name = linkName
|
|
40
|
+
copy.Archivable = false
|
|
41
|
+
|
|
42
|
+
local objectValue = Instance.new("ObjectValue")
|
|
43
|
+
objectValue.Name = "BounceTarget"
|
|
44
|
+
objectValue.Value = target
|
|
45
|
+
objectValue.Parent = copy
|
|
46
|
+
objectValue.Archivable = false
|
|
47
|
+
|
|
48
|
+
return copy
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
return BounceTemplateUtils
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
--[=[
|
|
2
|
+
Very inefficient search utility function to find dependencies
|
|
3
|
+
organized in node_modules structure.
|
|
4
|
+
|
|
5
|
+
@class DependencyUtils
|
|
6
|
+
]=]
|
|
7
|
+
|
|
8
|
+
local DependencyUtils = {}
|
|
9
|
+
|
|
10
|
+
--[=[
|
|
11
|
+
Iteratively searches for a dependency based upon packages and current modules using the node_modules
|
|
12
|
+
dependency resolution algorithm.
|
|
13
|
+
|
|
14
|
+
@param requester Instance
|
|
15
|
+
@param moduleName string
|
|
16
|
+
@return ModuleScript?
|
|
17
|
+
]=]
|
|
18
|
+
function DependencyUtils.findDependency(requester, moduleName)
|
|
19
|
+
assert(typeof(requester) == "Instance", "Bad requester")
|
|
20
|
+
assert(type(moduleName) == "string", "Bad moduleName")
|
|
21
|
+
|
|
22
|
+
for packageInst in DependencyUtils.iterPackages(requester) do
|
|
23
|
+
for module in DependencyUtils.iterModules(packageInst) do
|
|
24
|
+
if module.Name == moduleName then
|
|
25
|
+
return module
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
return nil
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
function DependencyUtils.iterModules(packageInst)
|
|
34
|
+
assert(typeof(packageInst) == "Instance", "Bad packageInst")
|
|
35
|
+
|
|
36
|
+
return coroutine.wrap(function()
|
|
37
|
+
if packageInst:IsA("ModuleScript") then
|
|
38
|
+
coroutine.yield(packageInst)
|
|
39
|
+
return
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
-- Iterate over the package contents
|
|
43
|
+
for _, item in pairs(packageInst:GetChildren()) do
|
|
44
|
+
if item.Name ~= "node_modules" then
|
|
45
|
+
for result in DependencyUtils.iterModules(item) do
|
|
46
|
+
coroutine.yield(result)
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
end)
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
function DependencyUtils.iterPackages(requester)
|
|
54
|
+
assert(typeof(requester) == "Instance", "Bad requester")
|
|
55
|
+
|
|
56
|
+
return coroutine.wrap(function()
|
|
57
|
+
for nodeModules in DependencyUtils.iterNodeModules(requester) do
|
|
58
|
+
coroutine.yield(nodeModules.Parent)
|
|
59
|
+
|
|
60
|
+
for packageInst in DependencyUtils.iterPackagesInModuleModules(nodeModules) do
|
|
61
|
+
coroutine.yield(packageInst)
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
end)
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
function DependencyUtils.iterNodeModules(module)
|
|
68
|
+
assert(typeof(module) == "Instance", "Bad module")
|
|
69
|
+
|
|
70
|
+
return coroutine.wrap(function()
|
|
71
|
+
local found = module:FindFirstChild("node_modules")
|
|
72
|
+
if found and found:IsA("Folder") then
|
|
73
|
+
coroutine.yield(found)
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
local current = module.Parent
|
|
77
|
+
while current do
|
|
78
|
+
found = current:FindFirstChild("node_modules")
|
|
79
|
+
if found and found:IsA("Folder") then
|
|
80
|
+
coroutine.yield(found)
|
|
81
|
+
end
|
|
82
|
+
current = current.Parent
|
|
83
|
+
end
|
|
84
|
+
end)
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
function DependencyUtils.iterPackagesInModuleModules(nodeModules)
|
|
88
|
+
return coroutine.wrap(function()
|
|
89
|
+
for _, item in pairs(nodeModules:GetChildren()) do
|
|
90
|
+
if item:IsA("Folder") then
|
|
91
|
+
if DependencyUtils.isPackageGroup(item.Name) then
|
|
92
|
+
for _, child in pairs(item:GetChildren()) do
|
|
93
|
+
if child:IsA("ModuleScript") or child:IsA("Folder") then
|
|
94
|
+
coroutine.yield(child)
|
|
95
|
+
elseif child:IsA("ObjectValue") then
|
|
96
|
+
local linked = child.Value
|
|
97
|
+
if linked then
|
|
98
|
+
if linked:IsA("ModuleScript") or linked:IsA("Folder") then
|
|
99
|
+
coroutine.yield(linked)
|
|
100
|
+
else
|
|
101
|
+
warn("Bad link value type")
|
|
102
|
+
end
|
|
103
|
+
else
|
|
104
|
+
warn("Nothing linked")
|
|
105
|
+
end
|
|
106
|
+
end
|
|
107
|
+
end
|
|
108
|
+
else
|
|
109
|
+
coroutine.yield(item)
|
|
110
|
+
end
|
|
111
|
+
elseif item:IsA("ModuleScript") then
|
|
112
|
+
coroutine.yield(item)
|
|
113
|
+
elseif item:IsA("ObjectValue") then
|
|
114
|
+
local linked = item.Value
|
|
115
|
+
if linked then
|
|
116
|
+
if linked:IsA("ModuleScript") or linked:IsA("Folder") then
|
|
117
|
+
coroutine.yield(linked)
|
|
118
|
+
else
|
|
119
|
+
warn("Bad link value type")
|
|
120
|
+
end
|
|
121
|
+
else
|
|
122
|
+
warn("Nothing linked")
|
|
123
|
+
end
|
|
124
|
+
end
|
|
125
|
+
end
|
|
126
|
+
end)
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
function DependencyUtils.isPackageGroup(itemName)
|
|
130
|
+
return itemName:sub(1, 1) == "@"
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
return DependencyUtils
|
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
--[=[
|
|
2
|
+
Adds the loader instance so script.Parent.loader works.
|
|
3
|
+
@class LoaderAdder
|
|
4
|
+
]=]
|
|
5
|
+
|
|
6
|
+
local loader = script.Parent.Parent
|
|
7
|
+
local BounceTemplateUtils = require(script.Parent.Parent.Bounce.BounceTemplateUtils)
|
|
8
|
+
local ReplicatorReferences = require(script.Parent.Parent.Replication.ReplicatorReferences)
|
|
9
|
+
local Maid = require(script.Parent.Parent.Maid)
|
|
10
|
+
local ReplicationType = require(script.Parent.Parent.Replication.ReplicationType)
|
|
11
|
+
local ReplicationTypeUtils = require(script.Parent.Parent.Replication.ReplicationTypeUtils)
|
|
12
|
+
|
|
13
|
+
local LoaderAdder = {}
|
|
14
|
+
LoaderAdder.ClassName = "LoaderAdder"
|
|
15
|
+
LoaderAdder.__index = LoaderAdder
|
|
16
|
+
|
|
17
|
+
function LoaderAdder.new(references, root, replicationType)
|
|
18
|
+
local self = setmetatable({}, LoaderAdder)
|
|
19
|
+
|
|
20
|
+
assert(typeof(root) == "Instance", "Bad root")
|
|
21
|
+
assert(ReplicatorReferences.isReplicatorReferences(references), "Bad references")
|
|
22
|
+
assert(ReplicationTypeUtils.isReplicationType(replicationType), "Bad replicationType")
|
|
23
|
+
|
|
24
|
+
self._references = references
|
|
25
|
+
self._root = root
|
|
26
|
+
self._replicationType = replicationType
|
|
27
|
+
|
|
28
|
+
self._maid = Maid.new()
|
|
29
|
+
|
|
30
|
+
self._needsLoaderCount = Instance.new("IntValue")
|
|
31
|
+
self._needsLoaderCount.Value = 0
|
|
32
|
+
self._maid:GiveTask(self._needsLoaderCount)
|
|
33
|
+
|
|
34
|
+
self._hasLoaderCount = Instance.new("IntValue")
|
|
35
|
+
self._hasLoaderCount.Value = 0
|
|
36
|
+
self._maid:GiveTask(self._hasLoaderCount)
|
|
37
|
+
|
|
38
|
+
self._needsLoader = Instance.new("BoolValue")
|
|
39
|
+
self._needsLoader.Value = false
|
|
40
|
+
self._maid:GiveTask(self._needsLoader)
|
|
41
|
+
|
|
42
|
+
self._maid:GiveTask(self._needsLoaderCount.Changed:Connect(function()
|
|
43
|
+
self:_updateNeedsLoader()
|
|
44
|
+
end))
|
|
45
|
+
self._maid:GiveTask(self._hasLoaderCount.Changed:Connect(function()
|
|
46
|
+
self:_updateNeedsLoader()
|
|
47
|
+
end))
|
|
48
|
+
|
|
49
|
+
self._maid:GiveTask(self._needsLoader.Changed:Connect(function()
|
|
50
|
+
if self._needsLoader.Value then
|
|
51
|
+
self._maid._loader = self:_renderLoader()
|
|
52
|
+
else
|
|
53
|
+
self._maid._loader = nil
|
|
54
|
+
end
|
|
55
|
+
end))
|
|
56
|
+
|
|
57
|
+
self:_updateNeedsLoader()
|
|
58
|
+
|
|
59
|
+
if self._replicationType ~= ReplicationType.SERVER then
|
|
60
|
+
self._maid:GiveTask(self._references:ObserveReferenceChanged(loader, function(value)
|
|
61
|
+
if value and value ~= loader then
|
|
62
|
+
self._maid._trackFakeLoader = self:_trackLoaderReference(value)
|
|
63
|
+
else
|
|
64
|
+
self._maid._trackFakeLoader = nil
|
|
65
|
+
end
|
|
66
|
+
end))
|
|
67
|
+
end
|
|
68
|
+
self._maid:GiveTask(self:_trackLoaderReference(loader))
|
|
69
|
+
|
|
70
|
+
-- Do actual setup
|
|
71
|
+
self._maid:GiveTask(root.ChildAdded:Connect(function(child)
|
|
72
|
+
self:_handleChildAdded(child)
|
|
73
|
+
end))
|
|
74
|
+
self._maid:GiveTask(root.ChildRemoved:Connect(function(child)
|
|
75
|
+
self:_handleChildRemoved(child)
|
|
76
|
+
end))
|
|
77
|
+
for _, child in pairs(root:GetChildren()) do
|
|
78
|
+
self:_handleChildAdded(child)
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
return self
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
function LoaderAdder:_updateNeedsLoader()
|
|
85
|
+
self._needsLoader.Value = (self._needsLoaderCount.Value > 0) and self._hasLoaderCount.Value <= 0
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
function LoaderAdder:_handleChildRemoved(child)
|
|
89
|
+
self._maid[child] = nil
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
function LoaderAdder:_handleChildAdded(child)
|
|
93
|
+
assert(typeof(child) == "Instance", "Bad child")
|
|
94
|
+
|
|
95
|
+
local maid = Maid.new()
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
if child:IsA("ModuleScript") then
|
|
99
|
+
self:_setupNeedsLoaderCountAdd(maid, 1)
|
|
100
|
+
else
|
|
101
|
+
-- TODO: Maybe add to children with node_modules explicitly in its list.
|
|
102
|
+
local loaderAdder = LoaderAdder.new(self._references, child, self._replicationType)
|
|
103
|
+
maid:GiveTask(loaderAdder)
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
self._maid[child] = maid
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
function LoaderAdder:_renderLoader()
|
|
110
|
+
local maid = Maid.new()
|
|
111
|
+
|
|
112
|
+
if self._replicationType == ReplicationType.SERVER then
|
|
113
|
+
maid._current = self:_doLoaderRender(loader)
|
|
114
|
+
else
|
|
115
|
+
maid:GiveTask(self._references:ObserveReferenceChanged(loader, function(value)
|
|
116
|
+
if value then
|
|
117
|
+
maid._current = self:_doLoaderRender(value)
|
|
118
|
+
else
|
|
119
|
+
maid._current = nil
|
|
120
|
+
end
|
|
121
|
+
end))
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
return maid
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
function LoaderAdder:_doLoaderRender(value)
|
|
128
|
+
local loaderLink = BounceTemplateUtils.create(value, loader.Name)
|
|
129
|
+
loaderLink.Parent = self._root
|
|
130
|
+
|
|
131
|
+
return loaderLink
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
function LoaderAdder:_setupNeedsLoaderCountAdd(maid, amount)
|
|
135
|
+
assert(Maid.isMaid(maid), "Bad maid")
|
|
136
|
+
assert(type(amount) == "number", "Bad amount")
|
|
137
|
+
|
|
138
|
+
self._needsLoaderCount.Value = self._needsLoaderCount.Value + amount
|
|
139
|
+
maid:GiveTask(function()
|
|
140
|
+
self._needsLoaderCount.Value = self._needsLoaderCount.Value - amount
|
|
141
|
+
end)
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
function LoaderAdder:_addToLoaderCount(amount)
|
|
145
|
+
assert(type(amount) == "number", "Bad amount")
|
|
146
|
+
|
|
147
|
+
self._hasLoaderCount.Value = self._hasLoaderCount.Value + amount
|
|
148
|
+
return function()
|
|
149
|
+
self._hasLoaderCount.Value = self._hasLoaderCount.Value - amount
|
|
150
|
+
end
|
|
151
|
+
end
|
|
152
|
+
|
|
153
|
+
function LoaderAdder:_trackLoaderReference(ref)
|
|
154
|
+
local maid = Maid.new()
|
|
155
|
+
|
|
156
|
+
-- TODO: Maybe handle loader reparenting more elegantly? this seems deeply unlikely.
|
|
157
|
+
if ref.Parent == self._root then
|
|
158
|
+
maid._current = self:_addToLoaderCount(1)
|
|
159
|
+
end
|
|
160
|
+
|
|
161
|
+
maid:GiveTask(ref:GetPropertyChangedSignal("Parent"):Connect(function()
|
|
162
|
+
if ref.Parent == self._root then
|
|
163
|
+
maid._current = self:_addToLoaderCount(1)
|
|
164
|
+
else
|
|
165
|
+
maid._current = nil
|
|
166
|
+
end
|
|
167
|
+
end))
|
|
168
|
+
|
|
169
|
+
return maid
|
|
170
|
+
end
|
|
171
|
+
|
|
172
|
+
--[=[
|
|
173
|
+
Cleans up the replicator disconnecting all events and cleaning up
|
|
174
|
+
created instances.
|
|
175
|
+
]=]
|
|
176
|
+
function LoaderAdder:Destroy()
|
|
177
|
+
self._maid:DoCleaning()
|
|
178
|
+
setmetatable(self, nil)
|
|
179
|
+
end
|
|
180
|
+
|
|
181
|
+
return LoaderAdder
|
|
File without changes
|