Introducing: Modules

                 Modules-256 Modules-256-black

Introducing Modules, a simple dependency loader for Roblox!

Download Model Documentation GitHub

Quick Start – What does it do?

Modules wraps the built-in require function. This lets you use a string to find your modules intelligently – while also retaining all its existing functionality!

-- Overwrite require to get a bunch of cool features:
local require = require(game:GetService("ReplicatedStorage"):WaitForChild("Modules"))
-- Searches for namespace "MyNamespace", then for module "MyModule":
local MyModule = require("MyNamespace:MyModule")
-- Requires the module at:
--  ServerScriptService.MyNamespace.MyModule
-- or ReplicatedStorage.MyNamespace.MyModule

-- You can also use a built-in module like this:
local Event = require("Event")

Modules uses namespaces to look for code. This is just a Folder in ReplicatedStorage or ServerScriptService.

Check out the Getting Started guide →

Features

:battery: Some Batteries Included: A few commonly-used utilities and patterns are built-in: class, Event, Maid, StateMachine. These can be required using require("Event"), etc!

:pizza: Sharing is Caring: In shared modules, require.server(...) and require.client(...) allow you to skip requires if not on a certain network peer.

:package: Easy to Package: With Modules, you can bundle server and client code simply into a single Folder (the namespace) in ServerScriptService, then put client code in a “Replicated” folder. It’s great for Roblox packages!

Download

Version Download Model Changes
latest ↓ 36.7 KB Get
1.1.1 ↓ 36.7 KB Get Linting
1.1.0 ↓ 36.7 KB Get Exclude tests
1.0.0 ↓ 48.8 KB Get Initial release

Docs: docs.ozzypig.com/Modules

Modules is fully documented from doc comments in-code! You can read these directly in Roblox Studio, or check out the documentation website which is built from these comments using a pretty involved toolchain. (.lua → LDoc → ldoc2mkdocs (custom Python tool) → MkDocs → .html)

GitHub: Ozzypig/Modules

The project is built using Rojo 0.5.4, although later versions will work as well :+1:t3:

See also

Feedback

In order of preference, here’s the ways I’d like your feedback on Modules:

Enjoy, and please let me know if you made something cool!

37 Likes

Just a quick note for this thread: If you have questions, comments, or issues, please consider posting a GitHub Issue on the repository instead of posting here. It helps me keep track of issues individually and is generally a better workflow :slight_smile:

image

I’ll still keep an eye out on this thread, but you can help streamline development of Modules if you post issues there instead of here :+1:

6 Likes

The StateMachine link is broken on the Getting Started guide. Edit: apologies for not making this as a GitHub issue initially - wasn’t sure if you wanted docs issues there too.

I could’ve really done with this module sooner! I’ve created two iterations of my own state machine for two games I’m working on at the moment, and they work fine, but they sure aren’t as neat as this. You’ve implemented the transitions and the cleanup just that little bit more elegantly and I hope this gets more people on the state machine train.

3 Likes

Thanks for catching that! I’ve made a GitHub issue to track the fix for this typo, which I’ll do ASAP. Update: It’s been fixed

Glad you like it! I don’t see StateMachines getting enough love nowadays. I like to think this module caters to both a normal event-based usage and a subclass-based usage. I’ve used the sub-machine pattern in a lot of my UI in the past :slight_smile:

3 Likes

Awesome stuff! Really cool.

One thing I’m wondering is why use this over a module loader like Nevermore? From what I can tell Nevermore does the same thing and comes with more modules?

Good question. The short answer is scope, but the longer more involved answer is a bit more complicated. Modules is a lightweight loader with just a few goodies, and will stay that way. Stuff that helps bridge the Lua ↔ Roblox gap, along with data structures you might use in many libraries. In the future, I plan to add Promises and Binders. Basically, if you’ve asked yourself “why isn’t library-so-and-so built in to Roblox itself?”, then I probably will want to add it.

The main difference is that Nevermore is a full-fledged engine, with an armful of bells and whistles. For simple projects, you’ll very likely not use a large majority of its features. This isn’t inherently a problem with its design; you might actually end up using the features in a project eventually - it’s very simply a matter of scope.

Modules makes it easy to scope out what your project will need. Going to need a Ragdoll library? A Markdown parser? Maybe even a debug drawing library? These can all be in their own namespaces, only included where they are needed.

3 Likes

Thanks for clearing that up! I’ll be sure to check it out :slight_smile:

2 Likes

A quick update to this post! Since release, I’ve updated to Modules 1.1.1. Test code is no longer included in the main module, and the code passes the selene linter. I’ve also fixed a number of documentation typos. No new features, but everything’s much tidier.

The OP is also updated with a table of links to downloads on the devforum as well as Roblox models. I’ve also made the whole thing easier to read.

1 Like

How does this accommodate for cyclic requiring?

Cyclic requiring causes scripts to hang indefinitely. Although there’s no way good way to work around this*, Modules will emit a warning displaying which requires are taking too long. For example “A -> B is taking too long”. Using that, you’d be able to figure out where your cycle is.

*

Current plan to improve the debugging experience is to run a topological sort on a require call graph in order to figure out what the actual cycle is, but only after the timeout is reached to maintain performance. Again, this is all a matter of assuming a halt is due to a cycle and not necessarily due to a module taking a long time to load. I’m not entirely sure I like this solution, but it might help in some cases.