Add 3D dice rolling with predetermined outcomes and character colors

- dice-box-threejs for physics-based 3D dice with @ notation for forced values
- Server rolls dice, all clients animate 3D dice landing on exact values
- Dice color matches rolling character's color (darkened HSL as die body)
- Roll log entry delayed until dice animation completes for suspense
- Red pulsing crit glow on damage buttons (visible on all themes)
- Nat 20 roll entries use proper theme background
- Themed scrollbar on main content area
- Stone texture + metal material with white numbers/outlines

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Aaron Wood 2026-04-09 21:01:05 -04:00
parent ff9203f754
commit 51ffb0033a
122 changed files with 435 additions and 38 deletions

View file

@ -6,6 +6,8 @@
"": {
"name": "shadowdark-client",
"dependencies": {
"@3d-dice/dice-box": "^1.1.4",
"@3d-dice/dice-box-threejs": "^0.0.12",
"react": "^18.3.1",
"react-dom": "^18.3.1",
"react-router-dom": "^7.1.1",
@ -19,6 +21,30 @@
"vite": "^6.0.0"
}
},
"node_modules/@3d-dice/dice-box": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/@3d-dice/dice-box/-/dice-box-1.1.4.tgz",
"integrity": "sha512-W8evh0LlCx/sorPS00cGZJO+/3I8g5eMfDqFAKAIUXF+/XVTP06bhgHSNFOCvLzWbdbEJX5za9QxB0ulDvfxyA==",
"hasInstallScript": true,
"license": "MIT",
"dependencies": {
"@babylonjs/core": "5.57.1",
"@babylonjs/loaders": "5.57.1",
"@babylonjs/materials": "5.57.1",
"copy-dir": "^1.3.0",
"node-abort-controller": "^3.1.1"
}
},
"node_modules/@3d-dice/dice-box-threejs": {
"version": "0.0.12",
"resolved": "https://registry.npmjs.org/@3d-dice/dice-box-threejs/-/dice-box-threejs-0.0.12.tgz",
"integrity": "sha512-Bau5UizUunZS9+A6zgGeZecEJotSLEI6YvmYTosvvdhRxv92xo89aIvKYQb6xqdx/AqjHdGENJmqBOadlFL9kA==",
"license": "MIT",
"dependencies": {
"cannon-es": "^0.20.0",
"three": "^0.143.0"
}
},
"node_modules/@babel/code-frame": {
"version": "7.29.0",
"resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.29.0.tgz",
@ -301,6 +327,31 @@
"node": ">=6.9.0"
}
},
"node_modules/@babylonjs/core": {
"version": "5.57.1",
"resolved": "https://registry.npmjs.org/@babylonjs/core/-/core-5.57.1.tgz",
"integrity": "sha512-k8U+SFPVGvHgeNr651nxZL26iVCmTzjmRrdbQa0BGas+lg8PIV/tfhN4uTeWWQeRFLvjbkcHA5qD8x/Xk3EpMQ==",
"license": "Apache-2.0"
},
"node_modules/@babylonjs/loaders": {
"version": "5.57.1",
"resolved": "https://registry.npmjs.org/@babylonjs/loaders/-/loaders-5.57.1.tgz",
"integrity": "sha512-DHk0iOwJgnTcj8vI+cQVzpiUvWGJvYqWyZxsf7nzhbeND+ZwNWSG0AelaGbGHpWTaDSd/DjUcoWVZuT4Cg6/Xg==",
"license": "Apache-2.0",
"peerDependencies": {
"@babylonjs/core": "^5.22.0",
"babylonjs-gltf2interface": "^5.22.0"
}
},
"node_modules/@babylonjs/materials": {
"version": "5.57.1",
"resolved": "https://registry.npmjs.org/@babylonjs/materials/-/materials-5.57.1.tgz",
"integrity": "sha512-NLdR6eGUr+wFqie937HRWsnaWPeECpjOrYDGvjjYDg08VAcIC3YyctAuQxv8rId7BoDttkUd8Ey/IZ5d/9H7GA==",
"license": "Apache-2.0",
"peerDependencies": {
"@babylonjs/core": "^5.22.0"
}
},
"node_modules/@esbuild/aix-ppc64": {
"version": "0.25.12",
"resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.12.tgz",
@ -1257,6 +1308,13 @@
"vite": "^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0"
}
},
"node_modules/babylonjs-gltf2interface": {
"version": "5.57.1",
"resolved": "https://registry.npmjs.org/babylonjs-gltf2interface/-/babylonjs-gltf2interface-5.57.1.tgz",
"integrity": "sha512-RZnaKfJ6Q/AYLdIjBYMRxCW/HPEC8jabAL1U8wJ0KVziw6NSbSV6S80S22fUCPTyaZ7nCekn1TYg1IPmJ/eA6w==",
"license": "Apache-2.0",
"peer": true
},
"node_modules/baseline-browser-mapping": {
"version": "2.10.16",
"resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.10.16.tgz",
@ -1325,6 +1383,12 @@
],
"license": "CC-BY-4.0"
},
"node_modules/cannon-es": {
"version": "0.20.0",
"resolved": "https://registry.npmjs.org/cannon-es/-/cannon-es-0.20.0.tgz",
"integrity": "sha512-eZhWTZIkFOnMAJOgfXJa9+b3kVlvG+FX4mdkpePev/w/rP5V8NRquGyEozcjPfEoXUlb+p7d9SUcmDSn14prOA==",
"license": "MIT"
},
"node_modules/convert-source-map": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz",
@ -1345,6 +1409,12 @@
"url": "https://opencollective.com/express"
}
},
"node_modules/copy-dir": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/copy-dir/-/copy-dir-1.3.0.tgz",
"integrity": "sha512-Q4+qBFnN4bwGwvtXXzbp4P/4iNk0MaiGAzvQ8OiMtlLjkIKjmNN689uVzShSM0908q7GoFHXIPx4zi75ocoaHw==",
"license": "MIT"
},
"node_modules/csstype": {
"version": "3.2.3",
"resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz",
@ -1572,6 +1642,12 @@
"node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
}
},
"node_modules/node-abort-controller": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/node-abort-controller/-/node-abort-controller-3.1.1.tgz",
"integrity": "sha512-AGK2yQKIjRuqnc6VkX2Xj5d+QW8xZ87pa1UK6yA6ouUyuxfHuMP6umE5QK7UmTeOAymo+Zx1Fxiuw9rVx8taHQ==",
"license": "MIT"
},
"node_modules/node-releases": {
"version": "2.0.37",
"resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.37.tgz",
@ -1809,6 +1885,12 @@
"node": ">=0.10.0"
}
},
"node_modules/three": {
"version": "0.143.0",
"resolved": "https://registry.npmjs.org/three/-/three-0.143.0.tgz",
"integrity": "sha512-oKcAGYHhJ46TGEuHjodo2n6TY2R6lbvrkp+feKZxqsUL/WkH7GKKaeu6RHeyb2Xjfk2dPLRKLsOP0KM2VgT8Zg==",
"license": "MIT"
},
"node_modules/tinyglobby": {
"version": "0.2.16",
"resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.16.tgz",

View file

@ -7,6 +7,8 @@
"preview": "vite preview"
},
"dependencies": {
"@3d-dice/dice-box": "^1.1.4",
"@3d-dice/dice-box-threejs": "^0.0.12",
"react": "^18.3.1",
"react-dom": "^18.3.1",
"react-router-dom": "^7.1.1",

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 197 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 165 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 190 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 182 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 140 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 184 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 49 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 51 KiB

Some files were not shown because too many files have changed in this diff Show more