Bundle Guide

Bundles are the way you modify Ranvier's functionality without having to touch the core code. They let you modify basically everything about the game: how commands are interpreted, commands themselves, channels, items, rooms, NPCs, quests, login flow, spell effects, even the network layer of your game.

Bundles live under the bundles/ folder of your project. They can be a git submodule (as will happen when using the install-bundle command) or just a normal folder containing the files.

What's in a Bundle

A bundle can contain any or all of the following children though it's suggested that you keep your bundles as modular as possible, i.e., try to keep input events out of the same bundle you're building your areas.

areas/
Area definitions and their items, rooms, NPCs, and quests along with the scripts for those entities
behaviors/
Scripts that are shared between entities of the same type, e.g., a behavior to have an NPC wander around an area
commands/
What it says on the tin, commands to add to the game
effects/
Effects that can be applied to characters (NPCs/Players)
help/
Helpfiles for commands
skills/
Player skills (Spells are included, they're just skills with the SPELL type)
input-events/
Scripts attached to a connected socket, this involves things like handling login and parsing incoming data for commands
Warning: Because of input events' important role it is generally not advised to load more than one bundle with input events
server-events/
Scripts attached to the startup of Ranvier itself such as starting a telnet server
quest-goals/
Quest goal definitions that can be used by builders when writing quests
quest-rewards/
Quest reward definitions that can be used by builders when writing quests
channels.js
Communication channels
player-events.js
Scripts attached to the player such being hit, gaining experience, leveling, etc.
attributes.js
Definitions of available attributes to assign to NPCs or players

How bundles are loaded

Before writing your first bundle it's important to know how bundles work and how they are loaded into Ranvier so you are aware of how and when to access game data.

Initialization

Ranvier first reads the ranvier.json config to determine how data should get loaded into the game. By default game entities (NPCs, areas, rooms, items, and quests) are stored in YAML; Player data is stored in JSON files. This can be changed, however, by following the Entity Loaders guide.

Ranvier then looks at the enabled bundles and follows the steps described below for each bundle

Scripts

Ranvier starts loading Javascript files into classes called Managers and Factorys:

  • Quest goals/rewards to QuestGoalManager and QuestRewardManager respectively
  • Attributes definitions get loaded into the AttributeFactory
  • Entity behaviors to their respective BehaviorManager
  • Channels to the ChannelManager
  • Player class definitions to the ClassManager
  • Commands to the CommandManager
  • Effects to the EffectFactory
  • Input and Server events to their respective EventManager
  • Player events to the PlayerManager
  • and finally Skills to the SkillManager

Some of these Managers and Factorys are only used internally, the main ones you may interact with inside a script or command include: CommandManager for executing commands, EffectFactory for creating effects and adding them to players or NPCs, and the SkillManager for having players or NPCs perform skills.

Entities

Definitions for all game entities are loaded into their respective Factorys, e.g., AreaFactory, RoomFactory, etc. from the configured data source. At this point all the definitions are loaded but none of those entities actually exist in the game. The distribution step handles that after all the bundles have finished the initialization step.

Distribution

Once all the scripts and all the entity definitions from all bundles have been loaded:

  • Area instances are created from their definitions and added to the AreaManager
  • For each Area created the hydrate method is called. This will use all the entity definitions to create instances of rooms, npcs, and items and put them in their appropriate place

Startup

At this point Ranvier triggers the startup event, notifying any bundles with server-events that the server has started.

Installing a bundle

From a git repository

To install a bundle from a git repository there is a helper command which will install the repository as a git submodule. This is the recommended approach to install a bundle as it allows you to easily receive updates from the original author, or fork the bundle and do work on it without having all of the files live inside your project folder.

From the root of your project run

npm run install-bundle <git repository url>
# for example
npm run install-bundle https://github.com/RanvierMUD/progressive-respawn

The bundle is now installed but not enabled, see the next section for enabling/disabling bundles

From a plain folder

To install a bundle from a normal folder move or copy it into the bundles/ directory of your project.

Again, at this point the bundle is installed but not enabled.

Managing enabled bundles

To enable or disable a bundle simply add or remove it from the bundles array in ranvier.json in the root of the project.

Removing a bundle

It's not necessary to remove bundles as you can disable them instead. With that said if you really want to remove a bundle, for a submodule bundle you can use the helper command npm run remove-bundle <bundle name>. For a normal folder bundle you can just delete the folder.

Creating a bundle

To create a bundle make a folder under the bundles/ directory. The name should not contain spaces or special characters. If you are so inclined you may also create the bundle as a separate repository and use the aforementioned repository bundle installation commands to add it to the project. That should be used if you intend on sharing the bundle with others. If you intend to keep the bundle only in your project a normal folder will do just fine.

3rd party node libraries in bundles

Bundles are meant to be self-contained folders. With that in mind if your bundle relies on a node module not present the package.json that comes with Ranvier the suggested approach is the following:

  1. Inside your bundle folder run npm init and fill out the appropriate fields
  2. Now you can safely run npm install --save some-3rd-party-package while inside your bundle and that dependency will available inside the code of your bundle.

Requiring code from another bundle

It is a common case that you have a "lib" bundle that contains some shared code, as such it is entirely possible to require code from another bundle.

// Assuming we were in bundles/my-command-bundle/commands/somecommand.js
const SomeLib = require('../../some-lib-bundle/lib/SomeLib');

Working in a bundle

For a normal folder bundle you can edit/commit following your normal workflow.

If you are working in a submodule bundle you will need a cursory understanding of how git submodules work. The official git submodule guide is a good reference for this: https://git-scm.com/book/en/v2/Git-Tools-Submodules. If you installed someone else's shared bundle, for example progressive-respawn or one of the example bundles, and you wish to make changes the suggested approach is to remove the original bundle, fork that repository, and add your fork as the bundle. If you make and commit changes without forking you will likely not be able to push them to that remote, as such you will not be able to carry your changes with you if you clone your project onto another server.

Next steps

Now that you know how to install/create a bundle and enable it the next step is actually building your game.

If you are making your game from scratch, or have only installed a networking bundle follow the From Scratch guide.

If you used the starter kit mentioned in the Get Started guide you can go directly to the individual guides. The documentation is split into two parts: Building and Coding.

  • Building is for... builders: the people creating areas, npcs, items, etc. Little to no programming experience is needed.
  • Coding is for... coders: the people creating new commands, skills, effects, etc.

There is some overlap between the two; for example a coder will need to create the attribute definition for a builder to use that attribute on an NPC, or for a builder to create a quest a coder may need to create the goal and reward types for them to use. These may, in fact, be the same person but the guides are separated to illustrate which bundle content is stored in pure data and which is in Javascript files.