3d-dice / dice-box Goto Github PK
View Code? Open in Web Editor NEW3D Game Dice for any JavaScript App
Home Page: https://fantasticdice.games/
License: MIT License
3D Game Dice for any JavaScript App
Home Page: https://fantasticdice.games/
License: MIT License
Before throwing the dice, I want to send values into it with my own random number generation method and the dice will turn out in accordance with these values. In this way, I can generate numbers in different ways and display the results to the user accordingly. I can also shorten the waiting time by starting the transactions I linked to the dice earlier. How do I send these values to the dice? How do I get these values to come up visually?
Would be nice to have a 1d3 option. Probably this shows a d6 with two times same numbers.
I recently integrated this library into my OSE Character Generator.
A couple of people have reached out indicating they are receiving a graphics error where dice look like the following:
user 1: iPhone 11, Chrome (Safari engine)
user 2: iPhone, Safari
I've also seen some delays when using the dice on Android, where sometimes it takes several seconds before the dice will show up.
Is this related to the browser compatibility for background Canvas? And any suggestions on how to fix this?
When trying to use Parser Interface + Dice Roller to do advanced parsing there is an error thrown when using.
const finalResults = DRP.parseFinalResults(results);
The function below works fine in Dicebox 1.0.5 but breaks in 1.0.7
This is the function that I have in a React hook
if (dicebox) {
// This method is triggered whenever dice are finished rolling
dicebox.onRollComplete = (results: unknown) => {
// handle any rerolls
const rerolls = DRP.handleRerolls(results);
if (rerolls.length) {
rerolls.forEach((roll: { groupId: unknown }) =>
dicebox.add(roll, roll.groupId)
);
return rerolls;
}
// if no rerolls needed then parse the final results
const finalResults = DRP.parseFinalResults(results);
setResult(finalResults);
};
In the add function, there is a check if groupId equals string then set the this.config.theme.
What relation does a groupID have to theme?
Why does this only apply when groupId is a string ?
It's possible for theme to be undefined here so if groupID is a string then this.config.theme could be undefined. Is that intended behavior ?
add(
notation,
groupId,
theme,
) {
if(typeof groupId === 'string' || theme) {
this.config.theme = theme
}
I have trying to rebuild my current JS implementation to typescript.
Now i have faced an issue on the world
If i am not mistaking this is referencing to the following line:
Line 369 in 759b885
I need to be honest that i wasn't able to understand the code at this place.
My hope was that you have an instant idea.
I have an existing 3D world built in react-three-fiber (so threejs under the hood). This wouldn't integrate into that, right? I don't know Babylon, but at a glance it seems entirely unrelated?
Currently, suspending the 3D simulation doesn't allow this library to work on mobile as it still tries to load the WebGL context and the WASM code. It would be ideal if this library provided a delicate fallback: "the world doesn't support fancy 3D things; let's just generate random numbers and return the expected result shape."
I've been seeing an interesting behaviour where the first die or array of dice that I roll does not return a result onRollComplete. Every roll after works as expected. dice-box seems like its completing init fine and I have a spinner to ensure the user isn't clicking roll button too soon. You can see in the image below that I'm getting one complete message for two rolls.
useEffect(() => {
setIsLoading( true )
const Box = new Dicebox("#dice-box", {
assetPath: '/dice-box/',
theme: pink,
})
Box.init().then(() => {
setDiceBox( Box )
setIsLoading( false )
} );
}, [])
I tried commenting out the diceBox.add and just using the diceBox.roll. This bug was the same here.
const diceRoll = async ( notation: string | string[], add = false ) => {
console.log("%c Clicked~", `color: orange; size 14px;`)
add ? await diceBox.add( notation ) : await diceBox.roll( notation )
if ( diceBox ) {
diceBox.onRollComplete = (resultsArray: resultsType[]) => {
console.log( resultsArray )
};
}
}
I think your work is so cool. So while I was working on a project with my colleagues, I wanted to apply your work to ours.
I don't know much about react yet, so I think it might be a problem.
But since it's a project with a deadline, I can't help it because I'm in a hurry.
My questions is, Can't you make it in a different place than at App.js?
When I tried to apply it to a different location, there was an error that seemed to be missing.
It's not accurate, but it was the error below
Uncaught Error: #dice-box is not a DOM element. ...
The example you posted worked well, but it didn't work well when I tried to apply it to mine.
If you have time, please reply.
Additionally, I don't think it's a version problem. It was executed even if I uploaded the version from yours in codeSandbox.
warning "@3d-dice/dice-box > @babylonjs/[email protected]" has incorrect peer dependency "babylonjs-gltf2interface@^5.22.0".
I am working on a dice game in which the user can randomly place(drag and drop) a solid box on the board and then roll the dice. The dice would collide with those solid boxes and it would affect the dice results. Can you help me building this module.
I don't know if this would be possible, but it would be awesome if the die roll outcomes could be set in advance.
That would support using random numbers generated from "true random" APIs like random.org, rather than relying on the physics engine for outcomes.
I followed the installation instructions, and I get a black box on my screen with javascript errors saying things like
wasm streaming compile failed: TypeError: Failed to execute 'compile' on 'WebAssembly': HTTP status code is not ok
and
failed to asynchronously prepare wasm: CompileError: WebAssembly.instantiate(): expected magic word 00 61 73 6d, found 3c 21 44 4f @+0
quick searches online don't reveal any way to fix these. what would you recommend as the best way to get this working?
InvalidStateError
Failed to execute 'transferControlToOffscreen' on 'HTMLCanvasElement': Cannot transfer control from a canvas for more than one time.
I've been running into this error since I started experimenting with the library. Do you have any experience with this error in your apps ?
error during build:
Error: Cannot find module 'rollup-plugin-delete'
'rollup-plugin-delete' is not in the devDependencies of package.json but is required in vite.config
If you hide the canvas by using hide()
and then resize the browser the world is resized with width and height 0 because of 'display: none'.
This can be fixed by resizing the world after calling .show()
Firstly, thanks for creating this project! It's exactly what I was looking for.
When I run npm install @3d-dice/dice-box
with the latest verison I get the following error (the rest of the lines are removed for brevity)
npm ERR! code 1
npm ERR! path /home/frank/Projects/ddtools-web/frontend/node_modules/@3d-dice/dice-box
npm ERR! command failed
npm ERR! command sh -c node copyAssets.js
npm ERR! node:internal/modules/cjs/loader:942
npm ERR! throw err;
npm ERR! ^
npm ERR!
npm ERR! Error: Cannot find module 'copy-dir'
npm ERR! Require stack:
npm ERR! - /home/frank/Projects/ddtools-web/frontend/node_modules/@3d-dice/dice-box/copyAssets.js
As far as I can tell, it undoes installing the whole package upon this error so I can't ignore it and simply copy over the file myself.
I experimented a bit by forking and moving copy-dir
from devDependencies
to dependencies
but then get another dependency error about node-abort-controller
.
Should these two packages be listed in dependencies
?
Using: node 16
Steps to Reproduce:
npm link @3d-dice/dice-box
in a directory with dice-box
as a dependencynpm ERR! code 1
npm ERR! path /home/arranf/projects/dice-box
npm ERR! command failed
npm ERR! command sh -c node copyAssets.js
npm ERR! node:internal/modules/cjs/loader:936
npm ERR! throw err;
npm ERR! ^
npm ERR!
npm ERR! Error: Cannot find module 'copy-dir'
npm ERR! Require stack:
npm ERR! - /home/arranf/projects/dice-box/copyAssets.js
npm ERR! at Function.Module._resolveFilename (node:internal/modules/cjs/loader:933:15)
npm ERR! at Function.Module._load (node:internal/modules/cjs/loader:778:27)
npm ERR! at Module.require (node:internal/modules/cjs/loader:1005:19)
npm ERR! at require (node:internal/modules/cjs/helpers:102:18)
npm ERR! at Object.<anonymous> (/home/arranf/projects/dice-box/copyAssets.js:3:17)
npm ERR! at Module._compile (node:internal/modules/cjs/loader:1101:14)
npm ERR! at Object.Module._extensions..js (node:internal/modules/cjs/loader:1153:10)
npm ERR! at Module.load (node:internal/modules/cjs/loader:981:32)
npm ERR! at Function.Module._load (node:internal/modules/cjs/loader:822:12)
npm ERR! at Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:81:12) {
npm ERR! code: 'MODULE_NOT_FOUND',
npm ERR! requireStack: [ '/home/arranf/projects/dice-box/copyAssets.js' ]
npm ERR! }
npm ERR! A complete log of this run can be found in:
npm ERR! /home/arranf/.npm/_logs/2022-09-11T11_05_17_823Z-debug.log
In world.offscreen.js, pendingThemPromises is declared as an array. The loadTheme function tries index the array with a string but arrays are index by numbers. Has this been working ?
pendingThemePromises: = []
async loadTheme(theme: string) {
const id = createUUID()
return new Promise((resolve, reject) => {
this.#OffscreenWorker.postMessage({action: "loadTheme", id, theme})
this.pendingThemePromises[id] = resolve
})
}
Hi Frank,
fantastic job so far. I tried to use your script in a nextjs scenario and i had issues regarding the type of module that you use. Maybe you can have a way to export the module in different rollup formats so that i can use them with nextjs :-)
I also saw that you are using location or document. This is probably also an issue with nextjs framework.
Cheers
When switching themes, I'm sometimes seeing "customColor" is not defined or "cannot read property of null (reading 'toArray'). This seems related to setting the customColor on the instanceBuffer
. For color based materials, themeColor is set and used by the instanceBuffer. For standard materials, an image texture is used and themeColor is set to null. There seems to be an async disconnect where color materials have null
for themeColor and texture materials do not have null
for themeColor. Need to find a better way to determine if themeColor is needed by a material instead of forcing the value to null
I hope you'll forgive another question.
At the end of the #makeRoll function there is an else that is potentially setting rollData without keys for value
, modifier
, and result
. The comment says the intent is to save this for later. Is this used later ?
getRollResults()
& this.#DiceWorld.onRollComplete
expects rollData entries to have value
, modifier
, and result
keys. Entries that lack these keys will break the expected behavior.
if ( hasGroupId ) {
Object.assign( this.rollData[groupId].rolls, rolls )
} else {
const index = this.#groupIndex
// save this roll group for later
const rollGroup = { ...notation, rolls }
this.rollData[index] = rollGroup
++this.#groupIndex
}
Hi!
Thanks for working on this amazing project. I am finding it super useful.
An issue: every time I set suspendSimulation to true, the "value" for each dice is always NaN. If default (false) there is absolutely no problem the values log just fine. I can provide more context about the code but I am simply changing the property of suspendSimulation.
Another question. Is there any way currently to have this interact with web sockets? I basically want to show to every player in the room the same roll that the user that rolls is seeing. Not the results, the actual 3D animation. Would that be any way to implement that? I am not sure what data I should have to pass to the socket.
Thanks again! Keep up the amazing work.
The recently updated roll
and add
methods now return a promise, but not all promises are being resolved correctly. I'm seeing issues when trying to add dice on a setInterval
timer. This needs some rework
Feature Request:
Roll only the % die. Currently you can roll d100 to get a 10s die and a percentile dice. For % games such as Call of Cthulhu you do not need the 10s die.
It has been requested that dice rolls be made with a pre-determined outcome. This way, numbers can be generated securely server side and the visual effect of the roll could then be triggered based on numbers passed over from the server.
I've looked into how this could be done by investigating Teal Dice, Dice so Nice and this thread on Reddit. Basically, the physics emulation is run once using preset vector inputs. The resulting faces are stored, then the dice are rotated to the desired start position and the 3d engine renders the dice using the same vector inputs again for the physics engine.
I was surprised at how quickly the physics engine can resolve the simulation when the time step is unrestricted. I think I'm able to speed up the AmmoJS simulation by increasing the stepSimulation
method's substeps
.
Overall this would be a pretty heavy lift because I would have to change out a lot of the randomness of the core system. Currently, random values are used for the dice start positions, the dice starting rotation, and the forces used to push the dice out into the box. I think I would have to forgo using an impulse to give the dice a linear velocity. I also have a sleepTimeout for the physics bodies (calculated in real time) which would have to be accounted for (time dilated) in the emulation. I also allow a config option to space out individual die generation (also calculated in real time), which is kind of a silly option. I had to add it early on so the dice were not generated right on top of each other which would cause them to forcefully explode away from one another.
Another big difference between my system and something like Teal, is that this library allows for different dice models with different textures. The faces of the models are variable. I would have to record the rotation of each dice face from the "up" position in order to calculate the desired starting rotation of a die.
In short, this is a big feature request, but probably doable with time.
Curious if anyone has gotten Jest testing working with this library. I'm trying to write tests for a feature that uses this library but always receive the error below. I've been trying to add ignore patters to my jest config without success.
SyntaxError: Unexpected token 'export'
> 1 | import Dicebox from "@3d-dice/dice-box";
| ^
2 | import {
3 | Context,
4 | ReactNode,
Hello!
I downloaded kitchen sink code from demo https://codesandbox.io/s/3d-dice-demo-2bily5
and I am trying to build it locally. I get this trouble, though.
Any solutions?
I'm on MAC
Hi, and thanks for creating this tool!
I was trying to implement it in a way for me to overlay on top of a live stream, without the shadows to match the aesthetics.
But after messing around with it for a while I realised that if I set the option "enableShadows: false:, I lose the shadow, but also the transparent background, meaning even if I don't want a background, or want an image, it gets replaced by a white fill.
When attempting to remove a die by passing in a die roll object I get .filter() is not a method
. I understand why this is happening. Internally, all the dice rolls are cached in an object, indexed by their rollId. This is so they can be easily looked up once their roll value has been calculated after the physic simulation. However, when outputting the final results, this multidimensional object is converted into an array of objects. The rolls are not an array internally, so there is no .filter method.
This has also uncovered some other issues around data mutation in this project. I'm looking into how to better manage the data internally.
Hi there! Love the library. Unfortunately, I'm unable to get anything to run.
I tried downloading a zip of the Getting Started demo, but when running npm start
I get
C:\Users\rufus\WebstormProjects\3d-dice-demo-v105\node_modules\@3d-dice\dice-box\dist\dice-box.es.js: Unknown browser query `not ie all`. Maybe you are using old Browserslist or made typo in query.
So I tried making my own simple app, see below for for code. It seems to compile fine, but then when running I get this issue:
Looks like Parcel isn't set up for serving pre-compile WASM files? I tried to find an answer, and looked through some other build system docs, but couldn't find anything. FWIW, I tried with esbuild
as well and got the same issue.
An example app that works out of the box would go a long way! let me know if I can help in any way. Thanks!
import DiceBox from '@3d-dice/dice-box'
document.addEventListener("DOMContentLoaded", async () => {
console.log('hello')
const diceBox = new DiceBox("#dice-box", {
assetPath: '/public/assets/dice-box/', // include the trailing backslash.
theme: 'default'
})
diceBox.init().then(()=>{
diceBox.roll('2d20')
})
})
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Test</title>
</head>
<body>
<h1>yooooo</h1>
<div id="dice-box">
<script type="module" src="index.js"></script>
</div>
</body>
</html>
{
{
"scripts": {
"start": "parcel src/index.html --open",
"build": "parcel build src/index.html"
},
"dependencies": {
"@3d-dice/dice-box": "^1.0.5"
},
"devDependencies": {
"parcel": "^2.6.2",
"@babel/core": "7.2.0",
"typescript": "4.4.4"
},
"resolutions": {
"@babel/preset-env": "7.13.8"
}
}
NB don't think I need all of those dependencies in there - was just adding extra dependencies from the examples to see if they were needed.
Hey @frankieali, is there any way to display dots on the dice, instead of digits ? I want a traditional style 6 sided dice with dots on it ๐ฒ Would this he achievable with a custom theme? Thanks in advance!
When rolling 1d100 on a result of 10 on the d10 it is added to the d100 result.
Using the code based on the React Demo. Includes dicebox + parser.
Percentile dice = consist of two d10s, one labeled with every single-digit number 0-9, (Ones dice - or unit die) the other labeled for the tens place, so 00-90 (Tens dice - or ten die).
Expected behavior is the d10 is treated as a 0 on a roll of 10 when rolled as part of a d100. So 10 + 60 = 60, not 70.
The team at Quest Portal have requested support for the Genesys game dice. They even sent over 3D models and vector images.
I've already started working on implementing this feature but wanted to add it here for tracking purposes. One thing that need reworked is identifying dice not by their number of sides, but by some other unique identifier. I'm also looking into creating a small parser that can be added as a plug-in. Then '3 green dice'(3dg
) could be written as ggg
which is more commonly used on Discord rollers. I'll probably add a new displayResults
module over at dice ui to ensure the final results are easy to parse.
This appears to be a fantastic lib. Amazing work.
We're trying to integrate it into our Babylonjs project, having having some difficulties.
Is the README up to date? Because looking at the code, the init signature appears to rely on a "World" object with a constructor of (selector, options) but the README has options as the first parameter. When we just passed in the selector, it appeared to get past the querySelector exception.
Once past the querySelector exception, the next obstacle was that it could not load the work thread code. It appears to expect the js files to be located relative to the root path, but when you try to run from, say... "https://somewhere.com/page1/page2"... it is trying to find the JS files at "https://somewhere.com/page1/page2/offscreenCanvas.worker.bc53e995.js"
Of course, we could be doing everything wrong.
Just so you know, we are the devs of SceneGrinder (https://www.scenegrinder.com) and would love to experiment with integrating your dice roller into our product.
Thanks... any insight is appreciated... and again, hats off to amazing work.
Jerry
When rolling 2d10ro<2
(which is the formula for Great Weapon Master damage), you'll see that dice results less than two will continue to reroll instead of stopping after one reroll. However, once the result is parsed the final results look correct. For instance, I rolled 2d10ro<2
. I saw a 9 and a 1. The 1 triggered a reroll which resulted in another 1. That triggered a reroll that resulted in an 8. The final results were "9,1,1 = 10". So the results are what's expected. The additional reroll was not. This indicated an issue with handling rerolls within https://github.com/3d-dice/FDP/blob/main/src/ParserInterface.js
Here is a short list of things I'm planning to implement for the next release
Note: I'm not planning to release a version 1.0 until BabylonJS 5 hits it's final release - due out this Spring sometime
d7
that would just return a random numberI created an experimental <roll-dice>
Web Component: https://jsfiddle.net/WebComponents/cmbvswq1/
It works; could be enhanced
display:inline-block
(see code)Failed to compile.
./node_modules/@3d-dice/dice-box/dist/world.onscreen.js 7870:47
Module parse failed: Unexpected token (7870:47)
File was processed with these loaders:
} else this._engine = r, this.defines = n ?? "", this._uniformsNames = i.concat(s), this._samplerList = s ? s.slice() : [], this._attributesNames = t, this._uniformBuffersNamesList = [], this._shaderLanguage = d, this.onError = h, this.onCompiled = o, this._indexParameters = l, this._fallbacks = a;
|
| this._attributeLocationByName = {}, this.uniqueId = De._UniqueIdSeed++;
The dice box needs a top wall. When gravity is low or restitution is very high, the dice can bounce out of the box and disappear.
When working with this package in a SvelteKit application, SvelteKit gives a nice warning at build time:
@3d-dice/dice-box doesn't appear to be written in CJS, but also doesn't appear to be a valid ES module (i.e. it doesn't have "type": "module" or an .mjs extension for the entry point). Please contact the package author to fix.
I would like it if you made either one of the suggested changes so that the package can be easily recognized as an ESM by tools.
When doing const result = await dicebox.roll(notation);
the result is an array of Individual Die Result Object but documentation would indicate it should be Roll Result Array Object. I believe previously it was an array of Roll Results.
I've written a bunch of code to work around this but was curious was the expected behaviour is.
Setting the scale in DiceBox configuration has no effect...
To replicate this issue, just use the kitchen sink demo you published to CodeSandbox, change the scale to something other than the default (e.g. 9) like so:
let Box = new DiceBox("#dice-box", {
assetPath: "/public/assets/dice-box/",
theme: "default",
offscreen: true,
scale: 9
});
Notice that the scale is NOT applied and there's no visual difference from the default of 6.
IF however you change the scale via the Box Controls to a value of 9 then you can clearly see the size difference.
It would appear therefore that the scale config parameter is ignored.
offscreenCanvas.worker.ts โ handleAsleep
world.onscreen.ts โ handleAsleep
// TODO: results are based on which mesh face is pointing up. Not all of them are mapped to number values such as edges (especially d10 and d100)
Could you elaborate more on this comment? I am curious to know more about how the mesh face is working.
I don't know if it is possible to achieve the replay function of the dice?
Some originally random values can be fixed, so that the results of the cast are also fixed.
Application scenarios such as multiplayer games, player 1's dice results can be reproduced in player 2.
Idea list for future features
d2
, d14
and d30
used in other systemsonCollision
callback eventHello! First, I would like to thank you for this module, it is awesome!
I am creating a Twitch bot for D&D campaigns and I would like to use the module to create an overlay displaying the dice roll when the chat type a command.
I installed the module and I am trying to import it into my node app, but I am getting some errors like:
Uncaught SyntaxError e:\Projetos\3Dice\node_modules\@3d-dice\dice-box\dist\dice-box.es.js:702
export { deepCopy as d, WorldFacade as default };
^^^^^^
SyntaxError: Unexpected token 'export'
I tried to add the "type": "module" in the package.json but it is not working.
Sorry if this is not the best place to ask it, but could you please give me some help to import and use the module in my node app?
Thanks in advance!
PS: Sorry about my English, this is not my first language lol
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.