@quenty/loader
Advanced tools
Comparing version 1.2.0 to 1.3.0-canary.209.c61f821.0
@@ -6,2 +6,13 @@ # Change Log | ||
# [1.3.0-canary.209.c61f821.0](https://github.com/Quenty/NevermoreEngine/compare/@quenty/loader@1.2.0...@quenty/loader@1.3.0-canary.209.c61f821.0) (2021-09-03) | ||
### Features | ||
* Add new loader to Nevermore ([c61f821](https://github.com/Quenty/NevermoreEngine/commit/c61f821d209ee35e2e50dec4086a938cecb9300a)) | ||
# 1.2.0 (2021-07-31) | ||
@@ -8,0 +19,0 @@ |
{ | ||
"name": "Nevermore", | ||
"name": "loader", | ||
"tree": { | ||
@@ -4,0 +4,0 @@ "$path": "src" |
@@ -0,0 +0,0 @@ MIT License |
{ | ||
"name": "@quenty/loader", | ||
"version": "1.2.0", | ||
"version": "1.3.0-canary.209.c61f821.0", | ||
"description": "A simple module loader for Roblox", | ||
@@ -10,10 +10,5 @@ "keywords": [ | ||
], | ||
"contributors": [ | ||
"Quenty" | ||
], | ||
"funding": { | ||
"type": "patreon", | ||
"url": "https://www.patreon.com/quenty" | ||
"bugs": { | ||
"url": "https://github.com/Quenty/NevermoreEngine/issues" | ||
}, | ||
"license": "MIT", | ||
"repository": { | ||
@@ -24,9 +19,14 @@ "type": "git", | ||
}, | ||
"bugs": { | ||
"url": "https://github.com/Quenty/NevermoreEngine/issues" | ||
"funding": { | ||
"type": "patreon", | ||
"url": "https://www.patreon.com/quenty" | ||
}, | ||
"license": "MIT", | ||
"contributors": [ | ||
"Quenty" | ||
], | ||
"publishConfig": { | ||
"access": "public" | ||
}, | ||
"gitHead": "d06e276dc6111e17c3c25d3e58768eb4e6bdc333" | ||
"gitHead": "c61f821d209ee35e2e50dec4086a938cecb9300a" | ||
} |
170
README.md
@@ -28,146 +28,58 @@ # Nevermore Loader | ||
And then we need to specifically map this loader | ||
## New features and requirements | ||
## Features | ||
* Load by name instead of instance (i.e. `require("MyModuleName")`) | ||
* Detects cyclical requirements in module scripts | ||
* Can also load by indexing (i.e. `require["MyModuleName"]`) | ||
* Can be stored in `_G` or `shared` to support legacy require systems so you can do `_G.Modules["MyModuleName"]` | ||
* Lets all modules be stored in one folder and replicates them based upon parent name | ||
* Server/Client/Shared code gets replicated properly | ||
* Does not load in submodules so libraries can be used | ||
* Allows you to load in other modules after initialization! | ||
1. Convert between NPM and Wally format | ||
1. Replicate/build out correct models | ||
2. Preserve single script instance for debugging | ||
3. Create bounces | ||
2. Convert between Wally format and Nevermore original format | ||
3. Understand object values at the NPM level -> Wally format | ||
## Using Nevermore's library loader | ||
## Bootstrapping | ||
Using Nevermore is really simple. You can either keep the name Nevermore, or customize components here. | ||
Using this loader does not require the large amount of libraries associated with it. | ||
1) Put this script, and all of its children in ReplicatedStorage.Nevermore (or your preferred parent) | ||
2) Put a uniquely named module in appropriate parent | ||
* By default `ServerScriptService.Modules` and all submodules is loaded | ||
* Modules in folders named "Client" or "Server" will only be available on the Client or Server | ||
* Modules parented to other modules will not be moved or loadable by name | ||
3) Use the module loader | ||
```lua | ||
local require = require(game:GetService("ReplicatedStorage"):WaitForChild("Nevermore")) | ||
local LoaderUtils = require(ServerScriptService.Modules:FindFirstChild("LoaderUtils", true)) | ||
LoaderUtils.toWallyFormat(ServerScriptService.Modules, { | ||
Client = ReplicatedStorage; | ||
Shared = ReplicatedStorage; | ||
Server = ServerScriptService; | ||
}) | ||
``` | ||
4) Require by name or instance. This will detect auto-cyclic issues | ||
```lua | ||
local MyModule = require("MyModule") | ||
local MyOtherModule = require(script.MyOtherModule) | ||
``` | ||
## Algorithm | ||
We assume is a folder is a package if it contains a "dependencies" folder. | ||
For a given package folder, all packages underneath it shall have... | ||
## Loading the loader | ||
1. Access to every other package that is not in the dependencies folder | ||
2. Access to every package in the dependency folder at the 1st level of recursion | ||
3. Access to every package in the dependency folder at each ancestor level at the 1st level of recursion | ||
4. Access to every sibling package (this is because we expect to be installed at a uniform level) | ||
You will need to require the module. I use this code to require it. You can rename Nevermore, but all the | ||
references to it will need to be renamed. | ||
We will | ||
```lua | ||
-- Grab the require from the ModuleScript | ||
local require = require(game:GetService("ReplicatedStorage"):WaitForChild("Nevermore")) | ||
``` | ||
I know some people have legacy loading systems that use `_G` or `_shared`. You may easily replace | ||
these systems by storing Nevermore in `_G` or `_shared`. | ||
```lua | ||
_G.myModuleLoader = require(game:GetService("ReplicatedStorage"):WaitForChild("Nevermore")) | ||
------- | ||
_G.myModuleLoader["MyModule"] -- Loads module | ||
``` | ||
- A module will be defined by a module script | ||
- A junction will be defined by a place with a "Dependencies" folder and will have access to its dependency folder, and all ancestors, but not siblings | ||
- A junction will give all modules underneath it access | ||
## Loading modules | ||
- Modules expect external dependencies to be at script.Parent | ||
- Modules will be split between client/server/shared based upon their parent | ||
- Dependencies will be any modules up to the root | ||
- For conflicts, the first copy available will be used (Start at a tree, go up one node, and look all the way down for a copy) | ||
- Modules will prefer to be parented directly, at a top level, without a bouncer | ||
- However, if a requirement is needed at a separate version, the module will be parented to its own folder, and a bounce script will point to it. | ||
- All required modules that it may need will point back to this module. | ||
You can then load modules from the default area as such: | ||
1. Discover junctions and | ||
2. If there are no conflicts, then just link the shared modules for the server to consume, and we're done. | ||
3. If there are conflicts, than we need to build 2 trees for each conflict. | ||
1. Identify junction | ||
### Loading by reference | ||
You can still load by reference, like Roblox functions | ||
```lua | ||
local require = require(game:GetService("ReplicatedStorage"):WaitForChild("Nevermore")) | ||
require(script.Parent.MyModule) | ||
``` | ||
### Loading by name | ||
Loading by name is the main feature. | ||
```lua | ||
local require = require(game:GetService("ReplicatedStorage"):WaitForChild("Nevermore")) | ||
local MyModule = require("MyModule") | ||
``` | ||
### Loading by indexing the require table | ||
You can also load libraries by name. If they aren't there, it will error. | ||
```lua | ||
local require = require(game:GetService("ReplicatedStorage"):WaitForChild("Nevermore")) | ||
local MyModule = require.MyModule | ||
``` | ||
You can also use this syntax if you want | ||
```lua | ||
local require = require(game:GetService("ReplicatedStorage"):WaitForChild("Nevermore")) | ||
local MyModule = require["MyModule"] | ||
``` | ||
By default, modules parented in ServerScriptService.Modules will be loaded. | ||
## Cyclic detection | ||
As long as you load all modules through Nevermore's require() function, even if | ||
you don't use the require-by-name function, you will recieve cyclic detection of | ||
modules being loaded. | ||
## Automatic replication of modules | ||
Nevermore contains a special replication model along with its require-by-name | ||
system. Modules will are classified as the following types, and behavior changes | ||
based upon where you require it | ||
* Server: Any script with a folder parent named "Server" (up to the top parent) | ||
* Default behavior: Only requirable by name on serves | ||
* Client: Any script with a folder parent named "Server" (up to the top parent) | ||
* Default behavior: Only requirable by name on client | ||
* Shared: Any other script, these are shared on the client and server | ||
* Default beahvior: Only requirable by name on the script | ||
* Submodule: Any script with a parent of a submodule (up to the top parent) | ||
* Default behavior: Not requirable by name at all. This helps keep the submodules | ||
from having name-space collisions. | ||
The top parent is the parent passed in with the `AddModulesFromParent` | ||
## Adding new modules to Nevermore | ||
You can also add new repositories to Nevermore, to require by name! | ||
### Adding from parent | ||
You can add modules by parent like this: | ||
```lua | ||
local require = require(game:GetService("ReplicatedStorage"):WaitForChild("Nevermore")) | ||
require:AddModulesFromParent(ReplicatedStorage:WaitForChild("ClientModules")) | ||
``` | ||
Note that until you add this, the loader will error if you try to load these modules! Note that | ||
this system follows the replication behavior! So server modules will not be available on the client, | ||
and submodules will not be loaded. Also, on the server, client/shared modules will be replicated. | ||
### Adding individual modules | ||
```lua | ||
local require = require(game:GetService("ReplicatedStorage"):WaitForChild("Nevermore")) | ||
require:AddModulesFromParent(ReplicatedStorage:WaitForChild("ClientModules")) | ||
``` | ||
A | ||
B C | ||
Maid1 Other Maid2 | ||
``` |
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
No v1
QualityPackage is not semver >=1. This means it is not stable and does not support ^ ranges.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
45596
17
2
84