Let's build a module
- 8 minutes read - 1561 words- Categories:
- Technical
If you are like me you like to spend time getting your setup “just so”. This often means using add-on modules to extend Foundry VTT. There are many modules available ranging from relatively simple interface changes (like My Tab) through sophisticated extensions to Foundry’s game management (like Midi Quality of Life Improvements).
Sooner or later one of three things will happen:
- One of the modules you want to use will not be updated to be compatible with your version of Foundry.
- You will find an existing module that almost does what you want, but not quite (or it does it in a way you think can be improved).
- You cannot find a module to do what you want.
In these cases (and assuming you have the time, energy, and know-how—or can learn how) you can:
Either way there are some barriers to doing this. Principal among these issues is the lack of coherent documentation for anyone coming new to Foundry development. There is plenty out there but it tends to be a bit out of date, or written with the assumption you already know a fair bit about how Foundry works. As for documentation of existing module code, well I’ve yet to stumble on any that is helpful to newbies. This series is aimed at addressing these shortcomings.
The Plan
I have two modules I want to develop.
- A control panel for Theatre of the Mind (TotM) style play.
- A way to embed macro triggers into journal entries.
Addressing the first. The existing module Theatre of the Mind Manager is fine but limited for what I want to do. The approach most GMs seem to take is using Monk’s Active Tile Triggers, placing “control tiles” on a scene and setting them to ‘invisible’ so they can be seem by the GM only. This approach works, but means the GM needs to find those control tiles, moving focus from the players. This may be okay for TotM, but I’d rather be able to set up a management console that I can choose to put it anywhere I please (or dismiss when it is not required).
There are many things one can do to embed game mechanics into a journal entry using enrichers. The module Dynamic Macro Links offers a generic way to extend these dynamic links using macros (pretty much exactly what I want), unfortunately there is a conflict between this module and Monk’s Enhanced Journal—and I like Monk’s Enhanced Journal—so let’s see if we can fix that. In addition Dynamic Macro Links seems limited to passing static parameters, perhaps we can improve this?
I am starting pretty much from scratch in terms of my knowledge of Foundry and my Javascript is pretty non-existent too. Not to worry, this will mean we can learn together.
Warning
Although I will try to explain things as I go my background is pretty technical (so I may assume too much of the reader, feel free to reach out (details at end of this post) if I do and I will try to clarify) and, in the interests of brevity, I will likely skip a lot of detail not directly related to Foundry module development. (Case in point, installing NodeJS
, Docker
, etc. are skipped assuming you will follow the instructions on the relevant websites.)
This is a series on developing modules for Foundry VTT, not a course on Javascript development. If you are new to writting code then I suggest you first master the basics of developing Javascript web products, then come back to this series.
Setting up a Development Environment
The main things we need are:
- A way to run Foundry VTT so we can see our module working.
- A way to view our Foundry VTT (this is simply a browser).
- A way to view our running code (we will use the developer tools in our browser—I will be using Chromium browsers, specifically Brave and Vivaldi).
- A way to version, build, and publish our module for others.
- A way to edit our module’s code.
Running Foundry VTT for development
You can run Foundry directly (see the FoundryVTT instructions—use the “Hosting a Dedicated Server with Node.js” instructions), or you can run it in a controlled “virtual” environment (this is basically the same as “Hosting a Dedicated Server with Node.js” but using nvm
—this method is not one I would encourage), or (and this is my preferred approach) you can use Docker
.
I will be using the Docker approach.
- It is the simplest to manage.
- It plays into later stages of development (stay tuned, it gets funky).
Install Docker
I’m going to assume you are working on a graphical interface (most likely Windows) so you will probably want to install the Docker Desktop using the instructions from the Docker website.
Running Foundry VTT in Docker
Fortunately Mark Fedhousen has done the heavy lifting for us. Once you have Docker installed just open a terminal window, create a directory to contain your Foundry data, and run up Docker.
mkdir myfoundry
docker run \
-d \
--name foundrydev \
--env FOUNDRY_USERNAME='<your_username>' \
--env FOUNDRY_PASSWORD='<your_password>' \
--publish 30000:30000/tcp \
--volume /the/full/path/to/myfoundry:/data \
felddy/foundryvtt:release
Replace <your_username>
and <your_pasword>
with your account username/password on https://foundryvtt.com where you purchased your Foundry license.3
The /the/full/path/to/myfoundry
should be the path to the myfoundry
directory you created to hold your Foundry data.
The -d
tells Docker to run Foundry in the background. Without this the terminal must remain open all the time Foundry is running.
Once you have run this you will be able to use your browser to visit http://localhost:30000
where you will find your new Foundry VTT running.
You can see your instance running in the Docker desktop. From the command line use docker ps
to view the running Docker containers (you will have only one unless you use Docker for other things—in which case this section is probably not for you).
docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
ff6b3bc2a3db felddy/foundryvtt:release "./entrypoint.sh res…" 6 seconds ago Up 6 seconds (health: starting) 0.0.0.0:30000->30000/tcp foundrydev
To stop the Foundry instance use docker stop
docker stop foundrydev
Bonus round. Install Python
, we’re going to need it to procees documentation very shortly.
- Python
Bonus round. Install Python
, we’re going to need it to procees documentation very shortly.
- Python
You can restart this instance of Foundry using docker start
docker start foundrydev
Using the browser for development
Okay, we have Foundry running and can see it with our browser at http://localhost:30000
. This is great for checking our module working as a user will see it but as a developer we want to see the code running, be able to stop the code, look at variable values, etc.
Fortunately the browser has “Developer Tools” built in. On Chromium based browsers press F12
or alt+ctl+I
or (on MacOS) alt+cmd+I
to open the developer tools. These are a suite of sophisticated tools we will use to monitor and debug our code. Covering anything but the basics of these tools is a whole series in itself, I recommend you browse the Chrome DevTools site to see what these tools can do.
Version control, build, and publish
This is another big topic. We will use git
so get that installed. I prefer the command line (CLI) but if you prefer a graphical interface there are plenty to choose from (that said, you will need to use the CLI a lot in this process, so probably best to learn it). Most modules are published through GitHub so go ahead and set up an account on there too.
We are going to be using GitHub workflows to build and publish our modules. This facility is free and comes along with GitHub, more on this later.
We will cover all the local tooling in the next few posts. Some will require local installations but so far as possible we will keep everything local to the project. Most of the development tooling we will use relies on a local NodeJS
installation. While we could use a Docker container to provide this, fankly it is easier for most purposes to install a local NodeJS (see above). Trust me, ngs can get complicated getting your IDE (say VSCode) to interact with NodeJS
running in a container to provide language server services. Okay, that may be word salad at the moment. Suffice to say, install NodeJS
locally, this will all make sense as we progress.
Editing the code
This one is a matter of personal preference. You will need to be able to edit text files, beyond that it is up to you. One popular choice is VSCode which has a lot of additional tooling to help you editing code.
FWIW, I use NeoVim.
Technology Stack Summary
Install this lot locally to get started (there will be more to come).
- NodeJS
- Docker
- A browser
- Git
- A GitHub account
Bonus round. Install Python
, we’re going to need it to procees documentation very shortly.
- Python
For help with this post please use the Discord channel and be sure to refer to this post’s link (https://mondarth.com/post/lets-build-a-module/ )
Assuming the license on the module allows for this. ↩︎
If you do this you may also want to contribute your change back to the original module. ↩︎
Foundry VTT licensing allows you to use your “play” license for package development (see FoundryVTT Software License). ↩︎
Choose Your Own Adventure
Follow (P)layer, (GM)Game Master, or (T)echnical thread.