@quenty/loader 10.0.0 → 10.1.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 +8 -0
- package/default.project.json +1 -1
- package/package.json +2 -2
- package/src/LoaderUtils.lua +2 -235
- package/src/Utils.lua +1 -1
- package/src/init.lua +154 -103
- package/src/BounceTemplate.lua +0 -17
- package/src/BounceTemplateUtils.lua +0 -66
- package/src/GroupInfoUtils.lua +0 -167
- package/src/LegacyLoader.lua +0 -131
- package/src/Loader.lua +0 -52
- package/src/LoaderConstants.lua +0 -12
- package/src/PackageInfoUtils.lua +0 -232
- package/src/Queue.lua +0 -109
- package/src/ScriptInfoUtils.lua +0 -153
- package/src/StaticLegacyLoader.lua +0 -211
- package/src2/LoaderUtils.lua +0 -3
- package/src2/Utils.lua +0 -106
- package/src2/init.lua +0 -171
- /package/{src2 → src}/Dependencies/DependencyUtils.lua +0 -0
- /package/{src2 → src}/Dependencies/PackageTracker.lua +0 -0
- /package/{src2 → src}/Dependencies/PackageTrackerProvider.lua +0 -0
- /package/{src2 → src}/LoaderLink/LoaderLink.lua +0 -0
- /package/{src2 → src}/LoaderLink/LoaderLinkCreator.lua +0 -0
- /package/{src2 → src}/LoaderLink/LoaderLinkUtils.lua +0 -0
- /package/{src2 → src}/Maid.lua +0 -0
- /package/{src2 → src}/Replication/ReplicationType.lua +0 -0
- /package/{src2 → src}/Replication/ReplicationTypeUtils.lua +0 -0
- /package/{src2 → src}/Replication/Replicator.lua +0 -0
- /package/{src2 → src}/Replication/ReplicatorReferences.lua +0 -0
- /package/{src2 → src}/Replication/ReplicatorUtils.lua +0 -0
package/src/GroupInfoUtils.lua
DELETED
|
@@ -1,167 +0,0 @@
|
|
|
1
|
-
--[=[
|
|
2
|
-
Nevermore loader utility library
|
|
3
|
-
@private
|
|
4
|
-
@class GroupInfoUtils
|
|
5
|
-
]=]
|
|
6
|
-
|
|
7
|
-
local Utils = require(script.Parent.Utils)
|
|
8
|
-
local Queue = require(script.Parent.Queue)
|
|
9
|
-
local LoaderConstants = require(script.Parent.LoaderConstants)
|
|
10
|
-
|
|
11
|
-
local GroupInfoUtils = {}
|
|
12
|
-
|
|
13
|
-
function GroupInfoUtils.createGroupInfo()
|
|
14
|
-
return Utils.readonly({
|
|
15
|
-
scriptInfoMap = {}; -- [name] = scriptInfo (required link packages)
|
|
16
|
-
packageScriptInfoMap = {};
|
|
17
|
-
packageSet = {}; -- [packageInfo] = true (actually included packages)
|
|
18
|
-
})
|
|
19
|
-
end
|
|
20
|
-
|
|
21
|
-
function GroupInfoUtils.groupPackageInfos(packageInfoList, replicationMode)
|
|
22
|
-
assert(type(packageInfoList) == "table", "Bad packageInfoList")
|
|
23
|
-
assert(type(replicationMode) == "string", "Bad replicationMode")
|
|
24
|
-
|
|
25
|
-
local queue = Queue.new()
|
|
26
|
-
local seen = {}
|
|
27
|
-
|
|
28
|
-
for _, packageInfo in pairs(packageInfoList) do
|
|
29
|
-
if not seen[packageInfo] then
|
|
30
|
-
seen[packageInfo] = true
|
|
31
|
-
queue:PushRight(packageInfo)
|
|
32
|
-
end
|
|
33
|
-
end
|
|
34
|
-
|
|
35
|
-
local built = {}
|
|
36
|
-
local current = GroupInfoUtils.createGroupInfo()
|
|
37
|
-
while not queue:IsEmpty() do
|
|
38
|
-
local packageInfo = queue:PopLeft()
|
|
39
|
-
if GroupInfoUtils.hasAnythingToReplicate(packageInfo, replicationMode) then
|
|
40
|
-
if GroupInfoUtils.canAddPackageInfoToGroup(current, packageInfo, replicationMode) then
|
|
41
|
-
GroupInfoUtils.addPackageInfoToGroup(current, packageInfo, replicationMode)
|
|
42
|
-
|
|
43
|
-
if LoaderConstants.GROUP_EACH_PACKAGE_INDIVIDUALLY then
|
|
44
|
-
table.insert(built, current)
|
|
45
|
-
current = GroupInfoUtils.createGroupInfo()
|
|
46
|
-
end
|
|
47
|
-
elseif LoaderConstants.ALLOW_MULTIPLE_GROUPS then
|
|
48
|
-
-- Create a new group
|
|
49
|
-
table.insert(built, current)
|
|
50
|
-
current = GroupInfoUtils.createGroupInfo()
|
|
51
|
-
GroupInfoUtils.addPackageInfoToGroup(current, packageInfo, replicationMode)
|
|
52
|
-
else
|
|
53
|
-
-- Force generate error
|
|
54
|
-
GroupInfoUtils.addPackageInfoToGroup(current, packageInfo, replicationMode)
|
|
55
|
-
|
|
56
|
-
error("Cannot add package to group")
|
|
57
|
-
end
|
|
58
|
-
end
|
|
59
|
-
|
|
60
|
-
for dependentPackageInfo, _ in pairs(packageInfo.dependencySet) do
|
|
61
|
-
if not seen[dependentPackageInfo] then
|
|
62
|
-
seen[dependentPackageInfo] = true
|
|
63
|
-
queue:PushRight(dependentPackageInfo)
|
|
64
|
-
end
|
|
65
|
-
end
|
|
66
|
-
end
|
|
67
|
-
|
|
68
|
-
if next(current.packageSet) then
|
|
69
|
-
table.insert(built, current)
|
|
70
|
-
end
|
|
71
|
-
|
|
72
|
-
return built
|
|
73
|
-
end
|
|
74
|
-
|
|
75
|
-
function GroupInfoUtils.hasAnythingToReplicate(packageInfo, replicationMode)
|
|
76
|
-
return next(packageInfo.scriptInfoLookup[replicationMode]) ~= nil
|
|
77
|
-
end
|
|
78
|
-
|
|
79
|
-
function GroupInfoUtils.canAddScriptInfoToGroup(groupInfo, scriptInfo, scriptName, tempScriptInfoMap)
|
|
80
|
-
assert(type(groupInfo) == "table", "Bad groupInfo")
|
|
81
|
-
assert(type(scriptInfo) == "table", "Bad scriptInfo")
|
|
82
|
-
assert(type(scriptName) == "string", "Bad scriptName")
|
|
83
|
-
assert(type(tempScriptInfoMap) == "table", "Bad tempScriptInfoMap")
|
|
84
|
-
|
|
85
|
-
local wouldHaveInfo = tempScriptInfoMap[scriptName]
|
|
86
|
-
if wouldHaveInfo and wouldHaveInfo ~= scriptInfo then
|
|
87
|
-
return false
|
|
88
|
-
end
|
|
89
|
-
|
|
90
|
-
local currentScriptInfo = groupInfo.scriptInfoMap[scriptName]
|
|
91
|
-
if currentScriptInfo and currentScriptInfo ~= scriptInfo then
|
|
92
|
-
return false
|
|
93
|
-
end
|
|
94
|
-
|
|
95
|
-
return true
|
|
96
|
-
end
|
|
97
|
-
|
|
98
|
-
function GroupInfoUtils.canAddPackageInfoToGroup(groupInfo, packageInfo, replicationMode)
|
|
99
|
-
assert(type(groupInfo) == "table", "Bad groupInfo")
|
|
100
|
-
assert(type(packageInfo) == "table", "Bad packageInfo")
|
|
101
|
-
assert(type(replicationMode) == "string", "Bad replicationMode")
|
|
102
|
-
|
|
103
|
-
local tempScriptInfoMap = {}
|
|
104
|
-
|
|
105
|
-
-- Existing scripts must be added
|
|
106
|
-
for scriptName, scriptInfo in pairs(packageInfo.scriptInfoLookup[replicationMode]) do
|
|
107
|
-
if GroupInfoUtils.canAddScriptInfoToGroup(groupInfo, scriptInfo, scriptName, tempScriptInfoMap) then
|
|
108
|
-
tempScriptInfoMap[scriptName] = scriptInfo
|
|
109
|
-
else
|
|
110
|
-
return false
|
|
111
|
-
end
|
|
112
|
-
end
|
|
113
|
-
|
|
114
|
-
-- Dependencies are expected at parent level
|
|
115
|
-
for dependencyPackageInfo, _ in pairs(packageInfo.dependencySet) do
|
|
116
|
-
if not groupInfo.packageSet[dependencyPackageInfo] then
|
|
117
|
-
-- Lookup dependencies and try to merge them
|
|
118
|
-
-- O(p*d*s)
|
|
119
|
-
for scriptName, scriptInfo in pairs(dependencyPackageInfo.scriptInfoLookup[replicationMode]) do
|
|
120
|
-
if GroupInfoUtils.canAddScriptInfoToGroup(groupInfo, scriptInfo, scriptName, tempScriptInfoMap) then
|
|
121
|
-
tempScriptInfoMap[scriptName] = scriptInfo
|
|
122
|
-
else
|
|
123
|
-
return false
|
|
124
|
-
end
|
|
125
|
-
end
|
|
126
|
-
end
|
|
127
|
-
end
|
|
128
|
-
|
|
129
|
-
return true
|
|
130
|
-
end
|
|
131
|
-
|
|
132
|
-
function GroupInfoUtils.addScriptToGroup(groupInfo, scriptName, scriptInfo)
|
|
133
|
-
assert(type(groupInfo) == "table", "Bad groupInfo")
|
|
134
|
-
assert(type(scriptInfo) == "table", "Bad scriptInfo")
|
|
135
|
-
assert(type(scriptName) == "string", "Bad scriptName")
|
|
136
|
-
|
|
137
|
-
local currentScriptInfo = groupInfo.scriptInfoMap[scriptName]
|
|
138
|
-
if currentScriptInfo and currentScriptInfo ~= scriptInfo then
|
|
139
|
-
error(("Cannot add to package group, conflicting scriptInfo for %q already there")
|
|
140
|
-
:format(scriptName))
|
|
141
|
-
end
|
|
142
|
-
|
|
143
|
-
groupInfo.scriptInfoMap[scriptName] = scriptInfo
|
|
144
|
-
end
|
|
145
|
-
|
|
146
|
-
function GroupInfoUtils.addPackageInfoToGroup(groupInfo, packageInfo, replicationMode)
|
|
147
|
-
groupInfo.packageSet[packageInfo] = true
|
|
148
|
-
|
|
149
|
-
-- Existing scripts must be added
|
|
150
|
-
for scriptName, scriptInfo in pairs(packageInfo.scriptInfoLookup[replicationMode]) do
|
|
151
|
-
GroupInfoUtils.addScriptToGroup(groupInfo, scriptName, scriptInfo)
|
|
152
|
-
groupInfo.packageScriptInfoMap[scriptName] = scriptInfo
|
|
153
|
-
end
|
|
154
|
-
|
|
155
|
-
-- Dependencies are expected at parent level
|
|
156
|
-
for dependencyPackageInfo, _ in pairs(packageInfo.dependencySet) do
|
|
157
|
-
if not groupInfo.packageSet[dependencyPackageInfo] then
|
|
158
|
-
-- Lookup dependencies and try to merge them
|
|
159
|
-
-- O(p*d*s)
|
|
160
|
-
for scriptName, scriptInfo in pairs(dependencyPackageInfo.scriptInfoLookup[replicationMode]) do
|
|
161
|
-
GroupInfoUtils.addScriptToGroup(groupInfo, scriptName, scriptInfo)
|
|
162
|
-
end
|
|
163
|
-
end
|
|
164
|
-
end
|
|
165
|
-
end
|
|
166
|
-
|
|
167
|
-
return GroupInfoUtils
|
package/src/LegacyLoader.lua
DELETED
|
@@ -1,131 +0,0 @@
|
|
|
1
|
-
--[=[
|
|
2
|
-
Legacy loading logic
|
|
3
|
-
|
|
4
|
-
@private
|
|
5
|
-
@class LegacyLoader
|
|
6
|
-
]=]
|
|
7
|
-
|
|
8
|
-
local RunService = game:GetService("RunService")
|
|
9
|
-
local ReplicatedStorage = game:GetService("ReplicatedStorage")
|
|
10
|
-
local ServerScriptService = game:GetService("ServerScriptService")
|
|
11
|
-
|
|
12
|
-
local LoaderUtils = require(script.Parent.LoaderUtils)
|
|
13
|
-
local BounceTemplateUtils = require(script.Parent.BounceTemplateUtils)
|
|
14
|
-
local Loader = require(script.Parent.Loader)
|
|
15
|
-
|
|
16
|
-
local LegacyLoader = {}
|
|
17
|
-
LegacyLoader.ClassName = "LegacyLoader"
|
|
18
|
-
LegacyLoader.__index = LegacyLoader
|
|
19
|
-
|
|
20
|
-
function LegacyLoader.new(script)
|
|
21
|
-
return setmetatable({
|
|
22
|
-
_script = assert(script, "No script");
|
|
23
|
-
_container = false;
|
|
24
|
-
_locked = false;
|
|
25
|
-
_lookupMap = {};
|
|
26
|
-
}, LegacyLoader)
|
|
27
|
-
end
|
|
28
|
-
|
|
29
|
-
function LegacyLoader:Lock()
|
|
30
|
-
assert(not self._container, "Cannot bootstrap game when legacy loader was already used")
|
|
31
|
-
self._locked = true
|
|
32
|
-
end
|
|
33
|
-
|
|
34
|
-
function LegacyLoader:GetLoader(moduleScript)
|
|
35
|
-
return Loader.new(moduleScript)
|
|
36
|
-
end
|
|
37
|
-
|
|
38
|
-
function LegacyLoader:Require(value)
|
|
39
|
-
assert(not self._locked, "Cannot use legacy loader after already transformed")
|
|
40
|
-
|
|
41
|
-
self:_setupIfNeeded()
|
|
42
|
-
|
|
43
|
-
if type(value) == "number" then
|
|
44
|
-
return require(value)
|
|
45
|
-
elseif type(value) == "string" then
|
|
46
|
-
local existing = self._lookupMap[value]
|
|
47
|
-
if existing then
|
|
48
|
-
return require(existing)
|
|
49
|
-
else
|
|
50
|
-
error("Error: Library '" .. tostring(value) .. "' does not exist.", 2)
|
|
51
|
-
end
|
|
52
|
-
elseif typeof(value) == "Instance" and value:IsA("ModuleScript") then
|
|
53
|
-
return require(value)
|
|
54
|
-
else
|
|
55
|
-
error(("Error: module must be a string or ModuleScript, got '%s' for '%s'")
|
|
56
|
-
:format(typeof(value), tostring(value)))
|
|
57
|
-
end
|
|
58
|
-
end
|
|
59
|
-
|
|
60
|
-
function LegacyLoader:_buildLookupContainer()
|
|
61
|
-
for _, instance in pairs(self._container:GetDescendants()) do
|
|
62
|
-
if instance:IsA("ModuleScript")
|
|
63
|
-
and not instance:FindFirstAncestorWhichIsA("ModuleScript") then
|
|
64
|
-
local target = instance
|
|
65
|
-
if BounceTemplateUtils.isBounceTemplate(instance) then
|
|
66
|
-
target = BounceTemplateUtils.getTarget(instance) or instance
|
|
67
|
-
end
|
|
68
|
-
|
|
69
|
-
local existing = self._lookupMap[instance.Name]
|
|
70
|
-
if existing then
|
|
71
|
-
if target ~= existing then
|
|
72
|
-
warn(("[LegacyLoader] - Duplicate module %q found, using first found\n\t(1) %s (used)\n\t(2) %s")
|
|
73
|
-
:format(
|
|
74
|
-
instance.Name,
|
|
75
|
-
self._lookupMap[instance.Name]:GetFullName(),
|
|
76
|
-
instance:GetFullName()))
|
|
77
|
-
end
|
|
78
|
-
else
|
|
79
|
-
self._lookupMap[instance.Name] = target
|
|
80
|
-
end
|
|
81
|
-
end
|
|
82
|
-
end
|
|
83
|
-
end
|
|
84
|
-
|
|
85
|
-
function LegacyLoader:_setupIfNeeded()
|
|
86
|
-
local existingContainer = rawget(self, "_container")
|
|
87
|
-
if existingContainer then
|
|
88
|
-
return existingContainer
|
|
89
|
-
end
|
|
90
|
-
|
|
91
|
-
-- TODO: Handle setup by manual process
|
|
92
|
-
assert(self._script.Name == "Nevermore", "Cannot invoke legacy mode if not at ReplicatedStorage.Nevermore")
|
|
93
|
-
assert(self._script.Parent == ReplicatedStorage, "Cannot invoke legacy mode if not at ReplicatedStorage.Nevermore")
|
|
94
|
-
|
|
95
|
-
if not RunService:IsRunning() then
|
|
96
|
-
error("Test mode not supported")
|
|
97
|
-
elseif RunService:IsServer() and RunService:IsClient() or (not RunService:IsRunning()) then
|
|
98
|
-
if RunService:IsRunning() then
|
|
99
|
-
error("Warning: Loading all modules in PlaySolo. It's recommended you use accurate play solo.")
|
|
100
|
-
end
|
|
101
|
-
elseif RunService:IsServer() then
|
|
102
|
-
local container = ServerScriptService:FindFirstChild("Nevermore") or error("No ServerScriptService.Nevermore folder")
|
|
103
|
-
local clientFolder, serverFolder, sharedFolder = LoaderUtils.toWallyFormat(container)
|
|
104
|
-
|
|
105
|
-
clientFolder.Name = "_nevermoreClient"
|
|
106
|
-
clientFolder.Parent = ReplicatedStorage
|
|
107
|
-
|
|
108
|
-
sharedFolder.Name = "_nevermoreShared"
|
|
109
|
-
sharedFolder.Parent = ReplicatedStorage
|
|
110
|
-
|
|
111
|
-
serverFolder.Name = "_nevermoreServer"
|
|
112
|
-
serverFolder.Parent = ServerScriptService
|
|
113
|
-
|
|
114
|
-
rawset(self, "_container", serverFolder)
|
|
115
|
-
self:_buildLookupContainer()
|
|
116
|
-
elseif RunService:IsClient() then
|
|
117
|
-
local container = ReplicatedStorage:WaitForChild("_nevermoreClient", 2)
|
|
118
|
-
|
|
119
|
-
if not container then
|
|
120
|
-
warn("[Nevermore] - Be sure to call require(ServerScriptService.Nevermore) on the server to replicate nevermore")
|
|
121
|
-
container = ReplicatedStorage:WaitForChild("_nevermoreClient")
|
|
122
|
-
end
|
|
123
|
-
|
|
124
|
-
rawset(self, "_container", container)
|
|
125
|
-
self:_buildLookupContainer()
|
|
126
|
-
else
|
|
127
|
-
error("Error: Unknown RunService state (Not client/server/test mode)")
|
|
128
|
-
end
|
|
129
|
-
end
|
|
130
|
-
|
|
131
|
-
return LegacyLoader
|
package/src/Loader.lua
DELETED
|
@@ -1,52 +0,0 @@
|
|
|
1
|
-
--[=[
|
|
2
|
-
Loading logic for Nevermore
|
|
3
|
-
|
|
4
|
-
@private
|
|
5
|
-
@class LoaderClass
|
|
6
|
-
]=]
|
|
7
|
-
|
|
8
|
-
local Loader = {}
|
|
9
|
-
Loader.ClassName = "Loader"
|
|
10
|
-
Loader.__index = Loader
|
|
11
|
-
|
|
12
|
-
function Loader.new(script)
|
|
13
|
-
return setmetatable({
|
|
14
|
-
_script = script;
|
|
15
|
-
_cache = {}
|
|
16
|
-
}, Loader)
|
|
17
|
-
end
|
|
18
|
-
|
|
19
|
-
local function waitForValue(objectValue)
|
|
20
|
-
local value = objectValue.Value
|
|
21
|
-
if value then
|
|
22
|
-
return value
|
|
23
|
-
end
|
|
24
|
-
|
|
25
|
-
return objectValue.Changed:Wait()
|
|
26
|
-
end
|
|
27
|
-
|
|
28
|
-
function Loader:__call(value)
|
|
29
|
-
if type(value) == "string" then
|
|
30
|
-
local cache = rawget(self, "_cache")
|
|
31
|
-
if cache[value] ~= nil then
|
|
32
|
-
return cache[value]
|
|
33
|
-
end
|
|
34
|
-
|
|
35
|
-
local object = self._script.Parent[value]
|
|
36
|
-
if object:IsA("ObjectValue") then
|
|
37
|
-
local result = require(waitForValue(object))
|
|
38
|
-
cache[value] = result
|
|
39
|
-
return result
|
|
40
|
-
else
|
|
41
|
-
local result = require(object)
|
|
42
|
-
cache[value] = result
|
|
43
|
-
return result
|
|
44
|
-
end
|
|
45
|
-
else
|
|
46
|
-
return require(value)
|
|
47
|
-
end
|
|
48
|
-
end
|
|
49
|
-
|
|
50
|
-
Loader.__index = Loader.__call
|
|
51
|
-
|
|
52
|
-
return Loader
|
package/src/LoaderConstants.lua
DELETED
package/src/PackageInfoUtils.lua
DELETED
|
@@ -1,232 +0,0 @@
|
|
|
1
|
-
--[=[
|
|
2
|
-
Utility methods to build a virtual graph of the existing package information set
|
|
3
|
-
@private
|
|
4
|
-
@class PackageInfoUtils
|
|
5
|
-
]=]
|
|
6
|
-
|
|
7
|
-
local BounceTemplateUtils = require(script.Parent.BounceTemplateUtils)
|
|
8
|
-
local LoaderConstants = require(script.Parent.LoaderConstants)
|
|
9
|
-
local Queue = require(script.Parent.Queue)
|
|
10
|
-
local ScriptInfoUtils = require(script.Parent.ScriptInfoUtils)
|
|
11
|
-
local Utils = require(script.Parent.Utils)
|
|
12
|
-
|
|
13
|
-
local PackageInfoUtils = {}
|
|
14
|
-
|
|
15
|
-
function PackageInfoUtils.createPackageInfo(packageFolder, explicitDependencySet, scriptInfoLookup, fullName)
|
|
16
|
-
assert(typeof(packageFolder) == "Instance", "Bad packageFolder")
|
|
17
|
-
assert(type(explicitDependencySet) == "table", "Bad explicitDependencySet")
|
|
18
|
-
assert(type(scriptInfoLookup) == "table", "Bad scriptInfoLookup")
|
|
19
|
-
assert(type(fullName) == "string", "Bad fullName")
|
|
20
|
-
|
|
21
|
-
return Utils.readonly({
|
|
22
|
-
name = packageFolder.Name;
|
|
23
|
-
fullName = fullName;
|
|
24
|
-
instance = packageFolder;
|
|
25
|
-
explicitDependencySet = explicitDependencySet;
|
|
26
|
-
dependencySet = false; -- will be filled in later, contains ALL expected dependencies
|
|
27
|
-
scriptInfoLookup = scriptInfoLookup;
|
|
28
|
-
})
|
|
29
|
-
end
|
|
30
|
-
|
|
31
|
-
function PackageInfoUtils.createDependencyQueueInfo(packageInfo, implicitDependencySet)
|
|
32
|
-
assert(type(packageInfo) == "table", "Bad packageInfo")
|
|
33
|
-
assert(type(implicitDependencySet) == "table", "Bad implicitDependencySet")
|
|
34
|
-
|
|
35
|
-
return Utils.readonly({
|
|
36
|
-
packageInfo = packageInfo;
|
|
37
|
-
implicitDependencySet = implicitDependencySet;
|
|
38
|
-
})
|
|
39
|
-
end
|
|
40
|
-
|
|
41
|
-
function PackageInfoUtils.fillDependencySet(packageInfoList)
|
|
42
|
-
assert(type(packageInfoList) == "table", "Bad packageInfoList")
|
|
43
|
-
|
|
44
|
-
local queue = Queue.new()
|
|
45
|
-
local seen = {}
|
|
46
|
-
|
|
47
|
-
do
|
|
48
|
-
local topDependencySet = {}
|
|
49
|
-
for _, packageInfo in pairs(packageInfoList) do
|
|
50
|
-
if not seen[packageInfo] then
|
|
51
|
-
topDependencySet[packageInfo] = packageInfo
|
|
52
|
-
seen[packageInfo] = true
|
|
53
|
-
queue:PushRight(PackageInfoUtils.createDependencyQueueInfo(packageInfo, topDependencySet))
|
|
54
|
-
end
|
|
55
|
-
end
|
|
56
|
-
end
|
|
57
|
-
|
|
58
|
-
-- Flaw: We can enter this dependency chain from multiple paths (we're a cyclic directed graph, not a tree)
|
|
59
|
-
-- TODO: Determine node_modules behavior and copy it (hopefully any link upwards words)
|
|
60
|
-
-- For now we do breadth first resolution of this to ensure minimal dependencies are accumulated for deep trees
|
|
61
|
-
while not queue:IsEmpty() do
|
|
62
|
-
local queueInfo = queue:PopLeft()
|
|
63
|
-
assert(not queueInfo.packageInfo.dependencySet, "Already wrote dependencySet")
|
|
64
|
-
|
|
65
|
-
local dependencySet = PackageInfoUtils
|
|
66
|
-
.computePackageDependencySet(queueInfo.packageInfo, queueInfo.implicitDependencySet)
|
|
67
|
-
queueInfo.packageInfo.dependencySet = dependencySet
|
|
68
|
-
|
|
69
|
-
-- Process all explicit dependencies for the next level
|
|
70
|
-
for packageInfo, _ in pairs(queueInfo.packageInfo.explicitDependencySet) do
|
|
71
|
-
if not seen[packageInfo] then
|
|
72
|
-
seen[packageInfo] = true
|
|
73
|
-
queue:PushRight(PackageInfoUtils.createDependencyQueueInfo(packageInfo, dependencySet))
|
|
74
|
-
end
|
|
75
|
-
end
|
|
76
|
-
end
|
|
77
|
-
end
|
|
78
|
-
|
|
79
|
-
function PackageInfoUtils.computePackageDependencySet(packageInfo, implicitDependencySet)
|
|
80
|
-
assert(type(packageInfo) == "table", "Bad packageInfo")
|
|
81
|
-
assert(type(implicitDependencySet) == "table", "Bad implicitDependencySet")
|
|
82
|
-
|
|
83
|
-
-- assume folders with the same name are the same module
|
|
84
|
-
local dependencyNameMap = {}
|
|
85
|
-
|
|
86
|
-
-- Set implicit dependencies
|
|
87
|
-
if LoaderConstants.INCLUDE_IMPLICIT_DEPENDENCIES then
|
|
88
|
-
for entry, _ in pairs(implicitDependencySet) do
|
|
89
|
-
dependencyNameMap[entry.name] = entry
|
|
90
|
-
end
|
|
91
|
-
end
|
|
92
|
-
|
|
93
|
-
-- These override implicit ones
|
|
94
|
-
for entry, _ in pairs(packageInfo.explicitDependencySet) do
|
|
95
|
-
dependencyNameMap[entry.name] = entry
|
|
96
|
-
end
|
|
97
|
-
|
|
98
|
-
-- clear ourself as a dependency
|
|
99
|
-
dependencyNameMap[packageInfo.name] = nil
|
|
100
|
-
|
|
101
|
-
-- Note we leave conflicting scripts here as unresolved. This will output an error later.
|
|
102
|
-
local dependencySet = {}
|
|
103
|
-
for _, entry in pairs(dependencyNameMap) do
|
|
104
|
-
dependencySet[entry] = true
|
|
105
|
-
end
|
|
106
|
-
|
|
107
|
-
return dependencySet
|
|
108
|
-
end
|
|
109
|
-
|
|
110
|
-
function PackageInfoUtils.getOrCreatePackageInfo(packageFolder, packageInfoMap, scope, defaultReplicationType)
|
|
111
|
-
assert(typeof(packageFolder) == "Instance", "Bad packageFolder")
|
|
112
|
-
assert(type(packageInfoMap) == "table", "Bad packageInfoMap")
|
|
113
|
-
assert(type(scope) == "string", "Bad scope")
|
|
114
|
-
assert(defaultReplicationType, "No defaultReplicationType")
|
|
115
|
-
|
|
116
|
-
if packageInfoMap[packageFolder] then
|
|
117
|
-
return packageInfoMap[packageFolder]
|
|
118
|
-
end
|
|
119
|
-
|
|
120
|
-
local scriptInfoLookup = ScriptInfoUtils.createScriptInfoLookup()
|
|
121
|
-
ScriptInfoUtils.populateScriptInfoLookup(
|
|
122
|
-
packageFolder,
|
|
123
|
-
scriptInfoLookup,
|
|
124
|
-
defaultReplicationType)
|
|
125
|
-
|
|
126
|
-
local explicitDependencySet = {}
|
|
127
|
-
local fullName
|
|
128
|
-
if scope == "" then
|
|
129
|
-
fullName = packageFolder.Name
|
|
130
|
-
else
|
|
131
|
-
fullName = scope .. "/" .. packageFolder.Name
|
|
132
|
-
end
|
|
133
|
-
|
|
134
|
-
local packageInfo = PackageInfoUtils
|
|
135
|
-
.createPackageInfo(packageFolder, explicitDependencySet, scriptInfoLookup, fullName)
|
|
136
|
-
packageInfoMap[packageFolder] = packageInfo
|
|
137
|
-
|
|
138
|
-
-- Fill this after we've registered ourselves, in case we're somehow in a recursive dependency set
|
|
139
|
-
PackageInfoUtils.fillExplicitPackageDependencySet(
|
|
140
|
-
explicitDependencySet,
|
|
141
|
-
packageFolder,
|
|
142
|
-
packageInfoMap,
|
|
143
|
-
defaultReplicationType)
|
|
144
|
-
|
|
145
|
-
return packageInfo
|
|
146
|
-
end
|
|
147
|
-
|
|
148
|
-
function PackageInfoUtils.getPackageInfoListFromDependencyFolder(folder, packageInfoMap, defaultReplicationType)
|
|
149
|
-
assert(typeof(folder) == "Instance" and folder:IsA("Folder"), "Bad folder")
|
|
150
|
-
assert(type(packageInfoMap) == "table", "Bad packageInfoMap")
|
|
151
|
-
assert(defaultReplicationType, "No defaultReplicationType")
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
local packageInfoList = {}
|
|
155
|
-
|
|
156
|
-
-- Assume we are at the dependency level
|
|
157
|
-
for _, instance in pairs(folder:GetChildren()) do
|
|
158
|
-
if instance:IsA("Folder") then
|
|
159
|
-
-- We loop through each "@quenty" or "@blah" and convert to a package
|
|
160
|
-
if instance.Name:sub(1, 1) == "@" then
|
|
161
|
-
local scope = instance.Name
|
|
162
|
-
for _, child in pairs(instance:GetChildren()) do
|
|
163
|
-
PackageInfoUtils.tryLoadPackageFromInstance(packageInfoList, packageInfoMap, child, scope, defaultReplicationType)
|
|
164
|
-
end
|
|
165
|
-
else
|
|
166
|
-
PackageInfoUtils.tryLoadPackageFromInstance(packageInfoList, packageInfoMap, instance, "", defaultReplicationType)
|
|
167
|
-
end
|
|
168
|
-
else
|
|
169
|
-
warn(("Unknown instance in dependencyFolder - %q"):format(instance:GetFullName()))
|
|
170
|
-
end
|
|
171
|
-
end
|
|
172
|
-
|
|
173
|
-
return packageInfoList
|
|
174
|
-
end
|
|
175
|
-
|
|
176
|
-
function PackageInfoUtils.tryLoadPackageFromInstance(
|
|
177
|
-
packageInfoList, packageInfoMap, instance, scope, defaultReplicationType)
|
|
178
|
-
|
|
179
|
-
assert(type(packageInfoList) == "table", "Bad packageInfoList")
|
|
180
|
-
assert(type(packageInfoMap) == "table", "Bad packageInfoMap")
|
|
181
|
-
assert(typeof(instance) == "Instance", "Bad instance")
|
|
182
|
-
assert(type(scope) == "string", "Bad scope")
|
|
183
|
-
assert(defaultReplicationType, "No defaultReplicationType")
|
|
184
|
-
|
|
185
|
-
if BounceTemplateUtils.isBounceTemplate(instance) then
|
|
186
|
-
return
|
|
187
|
-
end
|
|
188
|
-
|
|
189
|
-
if instance:IsA("Folder") or instance:IsA("ModuleScript") then
|
|
190
|
-
table.insert(packageInfoList, PackageInfoUtils.getOrCreatePackageInfo(
|
|
191
|
-
instance, packageInfoMap, scope, defaultReplicationType))
|
|
192
|
-
elseif instance:IsA("ObjectValue") then
|
|
193
|
-
local value = instance.Value
|
|
194
|
-
if value and (value:IsA("Folder") or value:IsA("ModuleScript")) then
|
|
195
|
-
table.insert(packageInfoList, PackageInfoUtils.getOrCreatePackageInfo(
|
|
196
|
-
value, packageInfoMap, scope, defaultReplicationType))
|
|
197
|
-
else
|
|
198
|
-
local message = string.format("Invalid %q ObjectValue in package linking to nothing cannot be resolved into package dependency\n\t-> %s",
|
|
199
|
-
instance.Name,
|
|
200
|
-
instance:GetFullName())
|
|
201
|
-
message = message .. "\n\tTIP: This happens when Rojo fails to clean out an object value. Try disconnecting Rojo and reconnecting"
|
|
202
|
-
|
|
203
|
-
error(message)
|
|
204
|
-
end
|
|
205
|
-
end
|
|
206
|
-
end
|
|
207
|
-
|
|
208
|
-
-- Explicit dependencies are dependencies that are are explicitly listed.
|
|
209
|
-
-- These dependencies are available to this package and ANY dependent packages below
|
|
210
|
-
function PackageInfoUtils.fillExplicitPackageDependencySet(
|
|
211
|
-
explicitDependencySet, packageFolder, packageInfoMap, defaultReplicationType)
|
|
212
|
-
|
|
213
|
-
assert(type(explicitDependencySet) == "table", "Bad explicitDependencySet")
|
|
214
|
-
assert(typeof(packageFolder) == "Instance", "Bad packageFolder")
|
|
215
|
-
assert(type(packageInfoMap) == "table", "Bad packageInfoMap")
|
|
216
|
-
assert(defaultReplicationType, "No defaultReplicationType")
|
|
217
|
-
|
|
218
|
-
for _, item in pairs(packageFolder:GetChildren()) do
|
|
219
|
-
if (item:IsA("Folder") or item:IsA("Camera")) and item.Name == ScriptInfoUtils.DEPENDENCY_FOLDER_NAME then
|
|
220
|
-
local packageInfoList = PackageInfoUtils.getPackageInfoListFromDependencyFolder(
|
|
221
|
-
item,
|
|
222
|
-
packageInfoMap,
|
|
223
|
-
defaultReplicationType)
|
|
224
|
-
|
|
225
|
-
for _, packageInfo in pairs(packageInfoList) do
|
|
226
|
-
explicitDependencySet[packageInfo] = true
|
|
227
|
-
end
|
|
228
|
-
end
|
|
229
|
-
end
|
|
230
|
-
end
|
|
231
|
-
|
|
232
|
-
return PackageInfoUtils
|
package/src/Queue.lua
DELETED
|
@@ -1,109 +0,0 @@
|
|
|
1
|
-
--[=[
|
|
2
|
-
Queue class with better performance characteristics than table.remove()
|
|
3
|
-
|
|
4
|
-
```lua
|
|
5
|
-
local queue = Queue.new()
|
|
6
|
-
queue:PushRight("a")
|
|
7
|
-
queue:PushRight("b")
|
|
8
|
-
queue:PushRight("c")
|
|
9
|
-
|
|
10
|
-
while not queue:IsEmpty() do
|
|
11
|
-
local entry = queue:PopLeft()
|
|
12
|
-
print(entry) --> a, b, c
|
|
13
|
-
end
|
|
14
|
-
```
|
|
15
|
-
|
|
16
|
-
@class Queue
|
|
17
|
-
]=]
|
|
18
|
-
|
|
19
|
-
local Queue = {}
|
|
20
|
-
Queue.ClassName = "Queue"
|
|
21
|
-
Queue.__index = Queue
|
|
22
|
-
|
|
23
|
-
--[=[
|
|
24
|
-
Constructs a new queue
|
|
25
|
-
@return Queue<T>
|
|
26
|
-
]=]
|
|
27
|
-
function Queue.new()
|
|
28
|
-
return setmetatable({
|
|
29
|
-
_first = 0;
|
|
30
|
-
_last = -1;
|
|
31
|
-
}, Queue)
|
|
32
|
-
end
|
|
33
|
-
|
|
34
|
-
--[=[
|
|
35
|
-
Gets the queues length
|
|
36
|
-
@return number
|
|
37
|
-
]=]
|
|
38
|
-
function Queue:__len()
|
|
39
|
-
return self._last + 1 - self._first
|
|
40
|
-
end
|
|
41
|
-
|
|
42
|
-
--[=[
|
|
43
|
-
Returns the count of the queue
|
|
44
|
-
|
|
45
|
-
@return number
|
|
46
|
-
]=]
|
|
47
|
-
function Queue:GetCount()
|
|
48
|
-
return self._last + 1 - self._first
|
|
49
|
-
end
|
|
50
|
-
|
|
51
|
-
--[=[
|
|
52
|
-
Pushes an entry to the left of the queue
|
|
53
|
-
@param value T
|
|
54
|
-
]=]
|
|
55
|
-
function Queue:PushLeft(value)
|
|
56
|
-
self._first = self._first - 1
|
|
57
|
-
self[self._first] = value
|
|
58
|
-
end
|
|
59
|
-
|
|
60
|
-
--[=[
|
|
61
|
-
Pushes an entry to the right of the queue
|
|
62
|
-
@param value T
|
|
63
|
-
]=]
|
|
64
|
-
function Queue:PushRight(value)
|
|
65
|
-
self._last = self._last + 1
|
|
66
|
-
self[self._last] = value
|
|
67
|
-
end
|
|
68
|
-
|
|
69
|
-
--[=[
|
|
70
|
-
Pops an entry from the left of the queue
|
|
71
|
-
@return T
|
|
72
|
-
]=]
|
|
73
|
-
function Queue:PopLeft()
|
|
74
|
-
if self._first > self._last then
|
|
75
|
-
error("Queue is empty")
|
|
76
|
-
end
|
|
77
|
-
|
|
78
|
-
local value = self[self._first]
|
|
79
|
-
self[self._first] = nil
|
|
80
|
-
self._first = self._first + 1
|
|
81
|
-
|
|
82
|
-
return value
|
|
83
|
-
end
|
|
84
|
-
|
|
85
|
-
--[=[
|
|
86
|
-
Pops an entry from the right of the queue
|
|
87
|
-
@return T
|
|
88
|
-
]=]
|
|
89
|
-
function Queue:PopRight()
|
|
90
|
-
if self._first > self._last then
|
|
91
|
-
error("Queue is empty")
|
|
92
|
-
end
|
|
93
|
-
|
|
94
|
-
local value = self[self._last]
|
|
95
|
-
self[self._last] = nil
|
|
96
|
-
self._last = self._last - 1
|
|
97
|
-
|
|
98
|
-
return value
|
|
99
|
-
end
|
|
100
|
-
|
|
101
|
-
--[=[
|
|
102
|
-
Returns true if the queue is empty
|
|
103
|
-
@return boolean
|
|
104
|
-
]=]
|
|
105
|
-
function Queue:IsEmpty()
|
|
106
|
-
return self._first > self._last
|
|
107
|
-
end
|
|
108
|
-
|
|
109
|
-
return Queue
|