This project aims to integrate the Pixels electronic dice (https://www.gamewithpixels.com/) with Demiplanes character sheets for TTRPGs.
Demiplane offers character sheets for a range of TTRPG system, including the option to roll simulated dice on those character sheets.
Pixels electronic dice are physical dice that can (among other things) establish a Bluetooth LE connection to an application running on a computer, tablet, or smartphone. When that connection is established, they can send roll results to whatever application they are connected to.
By combining the two projects, we can have digital character sheets for a number of TTRPG systems, roll physical dice for whatever roll is happening and the character sheet will handle any calculations required for the roll.
This integration has a few requirements to work.
The following browsers are supported by the integration:
-
Kiwi Browser (for Android)
Note
|
The integration will not work on Firefox or Safari, since neither of those support the experimental Web Bluetooth API. This isn’t likely to change any time soon. The specification draft is handled by the W3C Web Bluetooth Community Group and a number of concerns have been raised about it over the years. Specifically, Mozilla has decided not to implement Web Bluetooth in Firefox (see a discussion about the issue here, a statement about their position here) and Apple has decided against implementing in WebKit (which powers Safari) for security reasons (see a discussion about it here their stance on Anti-Fingerprinting). |
The integration has been tested on the following operating systems:
-
macOS
-
Ubuntu Linux
-
Windows
-
Android (with the Kiwi Browser on a tablet, in Desktop mode)
Warning
|
The integration does not work on iOS at this time. This is due to Apple (currently) requiring that all browsers use the WebKit engine, which does not support Web Bluetooth. This may change in the future, but right now that’s the way things are. |
To use Demiplane Nexus, you must register for an account with them. Both free and paid accounts are supported by this integration.
To use the integration, you should have at least one Pixels die. Pixels dice are available as:
-
d4
-
d6 (both with number and pipped)
-
d8
-
d10
-
d00 (also sometimes called D%s or percentile dice)
-
d12
-
d20
-
Fudge Dice (sometimes called dF for short)
The integration is built as a so called userscript.
This means that you need a browser extension such as Tampermonkey, which will inject the userscript into a suitable website (in this case: a character sheet on Demiplane Nexus).
The integration has built to be usable for any game system offered by Demiplane. It has been successfully tested with the following systems:
-
Alien RPG
-
Avatar Legends
-
Daggerheart (including limited critical roll handling)
-
Pathfinder 2E (including limited critical roll handling)
If you’re new to using this integration, here is some (hopefully) useful information to get you started.
Open the URL https://github.com/blalasaadri/pixels-demiplane-nexus-integration/raw/main/userscripts/index.prod.user.js in a supported browser with a plugin such as Tampermonkey installed. You will be prompted to install the userscript in Tampermonkey.
Important
|
If you had a character sheet open on Demiplane, you will have to reload that page after installing the userscript. |
Depending on your operating system, you may have to enable some functions in your browser before you can start using the integration.
On Linux, you will have to open the supported browser you want to use and go to chrome://flags/#enable-web-bluetooth.
Here make sure, that the value is set to Enabled
.
The integration supports reconnecting to dice when a character sheet is reloaded (within reason).
To allow for this, go to chrome://flags/#enable-web-bluetooth-new-permissions-backend and ensure that the value is set to Enabled
.
Note
|
This does not work in the Kiwi Browser for Android, it seems that the configuration flag does not exist there. Other mobile browsers that support userscripts may work. |
If this is enabled, when a character sheet is loaded the integration will try to find any dice that were connected the previous time it was used.
Once Bluetooth is set up and the integration is installed, open the character sheet you want to use the integration with on Demiplane Nexus.
In many cases, a menu entry called Pixels Dice [caret down] should appear at in the top bar.
If this entry does not appear, you may have to reload the character sheet.
In the Pixels Menu, click on the button Connect Pixels die in the Dice Settings area to start connecting your pixels dice.
A window will open which will scan for and then show all Pixels dice it can find.
Tip
|
If your die is not showing up in this window, please ensure the following:
|
Once you have connected (at least) one die, a few things in the Pixels Menu will change.
-
Under Dice Settings, the checkbox for enable for character is automatically enabled. (See Enabling and disabling the integration for specific characters for more about this.)
-
The icons of the type of dice you have connected will switch from a white logo to a rainbow logo. (See Enabling and disabling the integration for certain dice sizes for more about this.)
-
Under the icon for the die type you just connected, it will list the name of the connected die. That way you can always see, which dice are currently connected.
In the following two sections, options for enabling and disabling either the complete integration or parts of it will be discussed.
Enabled in this context means, that the integration will expect rolls (either all rolls or those of a certain die size) to be made with Pixels dice.
Disabled means the opposite, so rolls (either all rolls or those of a certain die size) will be made by the Demiplane virtual dice.
Since Demiplane Nexus supports a number of different game systems that use a variety of dice, it may not make sense to enable the integration for every character you have.
For this reason, there is the enable for character checkbox in the Dice Settings area of the Pixels Menu.
The checkbox will automatically be enabled for the current character once you connect a die while on the character sheet. You can however enable or disable it manually at any time.
In addition to enabling and disabling the whole integration, you can also enable or disable certain die types. When both the integration and a certain die type are enabled, the integration will expect all rolls of that die type to be made with Pixels dice.
Whether a die type is currently enabled or disabled can be seen with by the icon used.
Die type is inactive |
Die type is active |
Whenever you connect a die, that die type will automatically be enabled. By clicking on the icon (which is on a button), you can manually enable or disable the die type in question.
For this example, say you have enabled d20s and connected at least one d20 Pixel.
You then are required to make a roll of 1d20 + 1d4 + 2
.
The pixels integration will ask you to roll the connected d20 and will roll the d4 with the Demiplane virtual dice. Once both has happened, it will show you the combined result of your roll.
When the integration is waiting for a Pixels roll (in a supported game system), a notification will show up.
The exact design of the notification will depend on the game system, but it will look something like this:
Note
|
If you have not made any rolls with this character in this browser yet (or have cleared the data for this website), no popup will show up. This is because to be as consistent as possible with the design of the game, the integration copies and modifies an existing notification. If there is no existing notification to copy, that won’t work. The integration will still be waiting for the roll, it just has no way of telling you what it is waiting for. It is therefore recommended, that if you have such a character, you roll any selection of dice before enabling the integration. |
Once the roll has been made, the roll request notification will be replaced with the regular Demiplane Nexus roll information notification.
For most users, the above explanation should be everything they need to use the integration.
The following is for those of you, who want to test the integration, possibly without having all necessary Pixels dice at hand.
The integration comes with a number of commands available in the browsers DevTools. To use them, open the DevTools in the browser tab in which you have your character sheet open.
Then select the tab Console
in the DevTools.
Tip
|
All of the commands provided by the integration start with |
The integration has a debug mode, which when active will cause a lot of information to be logged to the console. This does not change the behaviour of the integration.
pixelsIntegration.isDebugModeEnabled()
|
Will return |
pixelsIntegration.enableDebugMode()
|
Will switch the integration’s debug on and then return |
pixelsIntegration.disableDebugMode()
|
Will switch the integration’s debug off and then return |
pixelsIntegration.toggleDebugMode()
|
Will switch the integration’s debug mode on or off. Will return |
You can trigger the connection to a Pixels die via a command. The result will be the same as when using the button in the Pixels Menu.
pixelsIntegration.connectToPixelsDie()
|
Start the connection process of a Pixels die. |
The integration can be enabled and disabled via console commands. This does the same as explained in Enabling and disabling the integration for specific characters.
You have the following related commands available to you in the browser console:
pixelsIntegration.isEnabledForCharacter(<characterId>)
|
Will return |
pixelsIntegration.enableForCharacter(<characterId>)
|
Will enable the integration for the provided character. Always returns |
pixelsIntegration.disableForCharacter(<characterId>)
|
Will disable the integration for the provided character. Always returns |
pixelsIntegration.toggleEnabledForCharacter(<characterId>)
|
Will switch the integration on or off. Returns |
The <characterId>
parameter is an optional string for all of these functions.
It refers to the last part of the URL, e.g. 1234abcd-56ef-01ab-23cd-456789efabcde
.
If not provided by the user, the currently opened character sheet will be used.
// Enable the integration for the current character
pixelsIntegration.enableForCharacter()
// Output
true
// Enable the integration for a specific character
pixelsIntegration.enableForCharacter('1234abcd-56ef-01ab-23cd-456789efabcde');
// Output
true
// Check whether the integration is active for the current character
pixelsIntegration.isEnabledForCharacter()
// Output
true
// Toggle whether the integration is enabled for a specific character
pixelsIntegration.toggleEnabledForCharacter('1234abcd-56ef-01ab-23cd-456789efabcde');
// Output
false
// Check whether the integration is active for a specific character
pixelsIntegration.isEnabledForCharacter('1234abcd-56ef-01ab-23cd-456789efabcde')
// Output
false
The integration can be enabled and disabled for specific die types, as explained in Enabling and disabling the integration for certain dice sizes.
Note
|
Disabling the integration per character always has priority over enabling it per die type. So the integration may be enabled for certain die types but will not wait for Pixels to be rolled, if the integration is disabled for a character. |
You have the following related commands available to you in the browser console:
pixelsIntegration.isEnabledForDieType(<dieType>)
|
Will return |
pixelsIntegration.enableForDieType(<dieType>)
|
Will enable the integration for the provided die type. Always returns |
pixelsIntegration.disableForDieType(<dieType>)
|
Will disable the integration for the provided die type. Always returns |
pixelsIntegration.toggleForDieType(<dieType>)
|
Will switch the integration on or off for the give die type . Returns |
The <dieType>
parameter is required, and can be one of the following:
The possible types are:
'd4'`
|
for d4s |
'd6' or 'd6pipped'
|
for d6s (both enable both numbered and pipped d6s) |
'd8'
|
for d8s |
'd10'
|
for d10s |
'd00'
|
for d00s |
'd20'
|
for d20s |
'dF' or 'd6fudge'
|
for fudge dice |
// Check, whether the integration is enabled for d20s
pixelsIntegration.isEnabledForDieType('d20')
// Output
false
// Enable the integration for d20s
pixelsIntegration.enableForDieType('d20')
// Output
true
// Check, whether the integration is enabled for fudge dice
pixelsIntegration.isEnabledForDieType('dF')
// Output
false
// Try to disable the integration for fudge dice (even though it already is)
pixelsIntegration.disableForDieType('dF')
// Output
false
// Toggle the integration for d6s
pixelsIntegration.toggleForDieType('d6')
// Output
true
When the pixels integration is active for both a character and a die type, and a roll with that die type is requested by Demiplane Nexus, you can check which rolls are currently expected as follows:
pixelsIntegration.listExpectedRolls()
|
List the rolls that are currently expected. |
// Request the currently requested rolls, after a d4 and a d20 have been requested
pixelsIntegration.listExpectedRolls()
// Output
{
"d4": 1,
"d6": 0,
"d8": 0,
"d10": 0,
"d00": 0,
"d12": 0,
"d20": 1,
"dF": 0
}
// After rolling a d20, the output will change
pixelsIntegration.listExpectedRolls()
// Output
{
"d4": 1,
"d6": 0,
"d8": 0,
"d10": 0,
"d00": 0,
"d12": 0,
"d20": 0,
"dF": 0
}
If you don’t (yet) have (enough) Pixels dice but want to test the integration nevertheless, there is a way to roll so called virtual dice instead. These don’t rely on the Demiplane rolling mechanism but instead do the same thing an actual Pixels die would do.
You have the following related commands available to you in the browser console:
pixelsIntegration.rollVirtualD4(<count>)
|
Used to roll a single d4. |
pixelsIntegration.rollVirtualD6(<count>)
|
Used to roll a single d6. |
pixelsIntegration.rollVirtualD8(<count>)
|
Used to roll a single d8. |
pixelsIntegration.rollVirtualD10(<count>)
|
Used to roll a single d10. |
pixelsIntegration.rollVirtualD00(<count>)
|
Used to roll a single d00 (percentile die). |
pixelsIntegration.rollVirtualD12(<count>)
|
Used to roll a single d12. |
pixelsIntegration.rollVirtualD20(<count>)
|
Used to roll a single d20. |
pixelsIntegration.rollVirtualDF(<count>)
|
Used to roll a single dF (fudge die). |
The <count>
parameter is optional and can be used to define the number of dice of that type to be rolled.
By default (if no value or a value smaller than 1 is given) a single die is rolled.
// Roll 1d6
pixelsIntegration.rollVirtualD6()
// Output:
[
{
"success": true,
"diceSize": 6,
"face": 2,
"dieType": "d6",
"dieColorway": "virtual",
"dieName": "Virtual d6",
"dieId": -6
}
]
// Roll 2d20
pixelsIntegration.rollVirtualD20(2)
// Output:
[{
"success": true,
"diceSize": 20,
"face": 4,
"dieType": "d20",
"dieColorway": "virtual",
"dieName": "Virtual d20",
"dieId": -20
},
{
"success": true,
"diceSize": 20,
"face": 2,
"dieType": "d20",
"dieColorway": "virtual",
"dieName": "Virtual d20",
"dieId": -20
}
]
In the SVG images, the font Barlow by Jeremy Tribby is used. This font is licensed under the Open Font License.
The brands "Demiplane" and "Demiplane Nexus" are trademarks of the Demiplane Corporation.
Pixels electronic dice are produced by Systemic Games, who hold all related rights.