@quenty/loader 10.2.0 → 10.3.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 CHANGED
@@ -3,6 +3,19 @@
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
+ # [10.3.0](https://github.com/Quenty/NevermoreEngine/compare/@quenty/loader@10.2.0...@quenty/loader@10.3.0) (2024-05-09)
7
+
8
+
9
+ ### Bug Fixes
10
+
11
+ * Fix .package-lock.json replicating in packages ([75d0efe](https://github.com/Quenty/NevermoreEngine/commit/75d0efeef239f221d93352af71a5b3e930ec23c5))
12
+ * Fix hoarcekat asset addition logic ([89e2c18](https://github.com/Quenty/NevermoreEngine/commit/89e2c181f83f9bca4d659477702d695af6e7b0cd))
13
+ * Immediate replication mode for loader and ability to bootstrap stories faster ([43967ec](https://github.com/Quenty/NevermoreEngine/commit/43967ecf3947241138dd3a44ba23ffe05de6d2b0))
14
+
15
+
16
+
17
+
18
+
6
19
  # [10.2.0](https://github.com/Quenty/NevermoreEngine/compare/@quenty/loader@10.1.0...@quenty/loader@10.2.0) (2024-04-27)
7
20
 
8
21
  **Note:** Version bump only for package @quenty/loader
@@ -1,5 +1,6 @@
1
1
  {
2
2
  "name": "loader",
3
+ "globIgnorePaths": [ "**/.package-lock.json" ],
3
4
  "tree": {
4
5
  "$path": "src"
5
6
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@quenty/loader",
3
- "version": "10.2.0",
3
+ "version": "10.3.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": "5c9eab1eac73f0d54953cca5017b7be968182f72"
29
+ "gitHead": "3fd5cdca3128bf34c8d9dfae1e92d62533b6e6f5"
30
30
  }
@@ -427,7 +427,7 @@ function PackageTracker:_tryStorePackage(fullPackageName, packageInst)
427
427
  return function()
428
428
  local index = table.find(self._subpackagesTrackerList, packageTracker)
429
429
  if index then
430
- table.remove(self._subpackagesTrackerList, packageTracker)
430
+ table.remove(self._subpackagesTrackerList, index)
431
431
  end
432
432
 
433
433
  if self._subpackagesMap[fullPackageName] == packageInst then
@@ -22,4 +22,9 @@ local function waitForValue(objectValue)
22
22
  return objectValue.Changed:Wait()
23
23
  end
24
24
 
25
- return require(waitForValue(script:WaitForChild("LoaderLink")))
25
+ local loader = waitForValue(script:WaitForChild("LoaderLink"))
26
+ if not loader:IsDescendantOf(game) then
27
+ error("Cannot load loader that is unparented from game")
28
+ end
29
+
30
+ return require(loader)
@@ -29,9 +29,29 @@ function LoaderLinkCreator.new(root, references, isRoot)
29
29
  self._hasLoaderCount = self._maid:Add(Instance.new("IntValue"))
30
30
  self._hasLoaderCount.Value = 0
31
31
 
32
- self._needsLoader = self._maid:Add(Instance.new("BoolValue"))
33
- self._needsLoader.Value = false
32
+ self._provideLoader = self._maid:Add(Instance.new("BoolValue"))
33
+ self._provideLoader.Value = false
34
34
 
35
+ -- prevent frame delay
36
+ self:_setupEventTracking()
37
+ self:_setupRendering()
38
+
39
+ return self
40
+ end
41
+
42
+ function LoaderLinkCreator:_setupEventTracking()
43
+ self._maid:GiveTask(self._root.ChildAdded:Connect(function(child)
44
+ self:_handleChildAdded(child)
45
+ end))
46
+ self._maid:GiveTask(self._root.ChildRemoved:Connect(function(child)
47
+ self:_handleChildRemoved(child)
48
+ end))
49
+
50
+ for _, child in pairs(self._root:GetChildren()) do
51
+ self:_handleChildAdded(child)
52
+ end
53
+
54
+ -- Need to do this AFTER child added loop
35
55
  if self._references then
36
56
  self._maid:GiveTask(self._references:ObserveReferenceChanged(loader, function(replicatedLoader)
37
57
  if replicatedLoader and replicatedLoader ~= loader then
@@ -40,52 +60,49 @@ function LoaderLinkCreator.new(root, references, isRoot)
40
60
  self._maid._trackFakeLoader = nil
41
61
  end
42
62
  end))
63
+ else
64
+ self._maid:GiveTask(self:_countLoaderReferences(loader))
65
+ end
66
+
67
+ -- Update state
68
+ self._maid:GiveTask(self._childRequiresLoaderCount.Changed:Connect(function()
69
+ self:_updateProviderLoader()
70
+ end))
71
+ self._maid:GiveTask(self._hasLoaderCount.Changed:Connect(function()
72
+ self:_updateProviderLoader()
73
+ end))
74
+ self:_updateProviderLoader()
75
+ end
43
76
 
44
- self._maid:GiveTask(self._needsLoader.Changed:Connect(function()
45
- if self._needsLoader.Value then
77
+ function LoaderLinkCreator:_setupRendering()
78
+ if self._references then
79
+ local function renderLoader()
80
+ if self._provideLoader.Value then
46
81
  self._maid._loader = self:_renderLoaderWithReferences()
47
82
  else
48
83
  self._maid._loader = nil
49
84
  end
50
- end))
85
+ end
86
+
87
+ self._maid:GiveTask(self._provideLoader.Changed:Connect(renderLoader))
88
+ renderLoader()
51
89
  else
52
- -- No references, just render as needed
53
- self._maid:GiveTask(self._needsLoader.Changed:Connect(function()
54
- if self._needsLoader.Value then
90
+ local function renderLoader()
91
+ if self._provideLoader.Value then
55
92
  self._maid._loader = self:_doLoaderRender(loader)
56
93
  else
57
94
  self._maid._loader = nil
58
95
  end
59
- end))
60
-
61
- self._maid:GiveTask(self:_countLoaderReferences(loader))
62
- end
63
-
64
- -- Update state
65
- self._maid:GiveTask(self._childRequiresLoaderCount.Changed:Connect(function()
66
- self:_updateNeedsLoader()
67
- end))
68
- self._maid:GiveTask(self._hasLoaderCount.Changed:Connect(function()
69
- self:_updateNeedsLoader()
70
- end))
71
- self:_updateNeedsLoader()
96
+ end
72
97
 
73
- -- Do actual setup
74
- self._maid:GiveTask(self._root.ChildAdded:Connect(function(child)
75
- self:_handleChildAdded(child)
76
- end))
77
- self._maid:GiveTask(self._root.ChildRemoved:Connect(function(child)
78
- self:_handleChildRemoved(child)
79
- end))
80
- for _, child in pairs(self._root:GetChildren()) do
81
- self:_handleChildAdded(child)
98
+ -- No references, just render as needed
99
+ self._maid:GiveTask(self._provideLoader.Changed:Connect(renderLoader))
100
+ renderLoader()
82
101
  end
83
-
84
- return self
85
102
  end
86
103
 
87
- function LoaderLinkCreator:_updateNeedsLoader()
88
- self._needsLoader.Value = (self._childRequiresLoaderCount.Value > 0) and self._hasLoaderCount.Value <= 0
104
+ function LoaderLinkCreator:_updateProviderLoader()
105
+ self._provideLoader.Value = (self._childRequiresLoaderCount.Value > 0) and self._hasLoaderCount.Value <= 0
89
106
  end
90
107
 
91
108
  function LoaderLinkCreator:_handleChildRemoved(child)
@@ -96,7 +113,13 @@ function LoaderLinkCreator:_handleChildAdded(child)
96
113
  assert(typeof(child) == "Instance", "Bad child")
97
114
 
98
115
  if child:IsA("ModuleScript") then
99
- self._maid[child] = self:_incrementNeededLoader(1)
116
+ if child.Name ~= "loader" then
117
+ self._maid[child] = self:_incrementNeededLoader(1)
118
+ else
119
+ if child ~= self._lastProvidedLoader then
120
+ self._maid[child] = self:_addToHasLoaderCount(1)
121
+ end
122
+ end
100
123
  elseif child:IsA("Folder") then
101
124
  -- TODO: Maybe add to children with node_modules explicitly in its list.
102
125
  self._maid[child] = LoaderLinkCreator.new(child, self._references)
@@ -119,8 +142,11 @@ end
119
142
 
120
143
  function LoaderLinkCreator:_doLoaderRender(value)
121
144
  local loaderLink = LoaderLinkUtils.create(value, loader.Name)
145
+ self._lastProvidedLoader = loaderLink
146
+
122
147
  loaderLink.Parent = self._root
123
148
 
149
+
124
150
  return loaderLink
125
151
  end
126
152
 
@@ -133,7 +159,7 @@ function LoaderLinkCreator:_incrementNeededLoader(amount)
133
159
  end
134
160
  end
135
161
 
136
- function LoaderLinkCreator:_addToLoaderCount(amount)
162
+ function LoaderLinkCreator:_addToHasLoaderCount(amount)
137
163
  assert(type(amount) == "number", "Bad amount")
138
164
 
139
165
  self._hasLoaderCount.Value = self._hasLoaderCount.Value + amount
@@ -149,12 +175,12 @@ function LoaderLinkCreator:_countLoaderReferences(robloxInst)
149
175
 
150
176
  -- TODO: Maybe handle loader reparenting more elegantly? this seems deeply unlikely.
151
177
  if robloxInst.Parent == self._root then
152
- maid._current = self:_addToLoaderCount(1)
178
+ maid._current = self:_addToHasLoaderCount(1)
153
179
  end
154
180
 
155
181
  maid:GiveTask(robloxInst:GetPropertyChangedSignal("Parent"):Connect(function()
156
182
  if robloxInst.Parent == self._root then
157
- maid._current = self:_addToLoaderCount(1)
183
+ maid._current = self:_addToHasLoaderCount(1)
158
184
  else
159
185
  maid._current = nil
160
186
  end
@@ -48,6 +48,10 @@ function ReplicatorReferences:UnsetReference(orig, replicated)
48
48
  end
49
49
  end
50
50
 
51
+ function ReplicatorReferences:GetReference(orig)
52
+ return self._lookup[orig]
53
+ end
54
+
51
55
  function ReplicatorReferences:_fireSubs(orig, newValue)
52
56
  assert(typeof(orig) == "Instance", "Bad orig")
53
57
 
package/src/init.lua CHANGED
@@ -55,10 +55,6 @@ function Loader.bootstrapGame(packages)
55
55
 
56
56
  GLOBAL_PACKAGE_TRACKER:AddPackageRoot(packages)
57
57
 
58
- -- We need to wait here once we "populate" the loader so the Ancestry/query events can
59
- -- fire in Signal deferred mode.
60
- self:_waitForNextDeferFrame()
61
-
62
58
  return self
63
59
  end
64
60
 
@@ -71,9 +67,25 @@ function Loader.bootstrapPlugin(packages)
71
67
 
72
68
  GLOBAL_PACKAGE_TRACKER:AddPackageRoot(packages)
73
69
 
74
- -- We need to wait here once we "populate" the loader so the Ancestry/query events can
75
- -- fire in Signal deferred mode.
76
- self:_waitForNextDeferFrame()
70
+ return self
71
+ end
72
+
73
+ function Loader.bootstrapStory(storyScript)
74
+ assert(typeof(storyScript) == "Instance", "Bad storyScript")
75
+
76
+ -- Prepopulate global package roots
77
+ local topNodeModule = storyScript
78
+ for node_modules in DependencyUtils.iterNodeModules(storyScript) do
79
+ if not node_modules:IsDescendantOf(topNodeModule) then
80
+ topNodeModule = node_modules
81
+ end
82
+ end
83
+
84
+ local self = Loader.new(topNodeModule.Parent, ReplicationType.PLUGIN)
85
+
86
+ self:_setupLoaderPopulation()
87
+
88
+ GLOBAL_PACKAGE_TRACKER:AddPackageRoot(topNodeModule.Parent)
77
89
 
78
90
  return self
79
91
  end
@@ -103,15 +115,6 @@ function Loader:__call(request)
103
115
  end
104
116
  end
105
117
 
106
- function Loader:_waitForNextDeferFrame()
107
- local signal = Instance.new("BindableEvent")
108
- task.defer(function()
109
- signal:Fire()
110
- end)
111
- signal.Event:Wait()
112
- signal:Destroy()
113
- end
114
-
115
118
  function Loader:_findDependency(request)
116
119
  assert(type(request) == "string", "Bad request")
117
120
 
@@ -141,9 +144,7 @@ function Loader:_findDependency(request)
141
144
  -- Just standard dependency search
142
145
  local foundBackup = DependencyUtils.findDependency(self._packages, request, self._replicationType)
143
146
  if foundBackup then
144
- if RunService:IsRunning() then
145
- warn(string.format("[Loader] - Failed to find package %q in package tracker\n%s", request, debug.traceback()))
146
- end
147
+ warn(string.format("[Loader] - Failed to find package %q in package tracker\n%s", request, debug.traceback()))
147
148
 
148
149
  -- Ensure hoarcekat story has a link to use
149
150
  -- TODO: Maybe add to global package cache instead...