Compare commits
1 Commits
1.2.5
...
2077bf7cbb
| Author | SHA1 | Date | |
|---|---|---|---|
| 2077bf7cbb |
@@ -16,7 +16,6 @@
|
||||
<p align="center">
|
||||
<img src=".github/media/preview.gif" />
|
||||
</p>
|
||||
|
||||
---
|
||||
|
||||
## Key Features
|
||||
@@ -28,7 +27,6 @@
|
||||
* Watch roll results (also available as Browser Source in OBS)
|
||||
|
||||
---
|
||||
|
||||
## Start Container
|
||||
|
||||
You can start dice-tower with docker compose
|
||||
@@ -42,8 +40,6 @@ services:
|
||||
restart: always
|
||||
ports:
|
||||
- "8080:8080"
|
||||
environment:
|
||||
DICE_LIMIT: 30 # OPTIONAL: amount of dice allowed to roll (default: 30)
|
||||
```
|
||||
Run the container with:
|
||||
```bash
|
||||
|
||||
2
pom.xml
2
pom.xml
@@ -4,7 +4,7 @@
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>de.arindy</groupId>
|
||||
<artifactId>dice-tower</artifactId>
|
||||
<version>1.2.5</version>
|
||||
<version>1.2.0-SNAPSHOT</version>
|
||||
|
||||
<properties>
|
||||
<compiler-plugin.version>3.13.0</compiler-plugin.version>
|
||||
|
||||
@@ -14,19 +14,12 @@ import jakarta.ws.rs.sse.OutboundSseEvent
|
||||
import jakarta.ws.rs.sse.Sse
|
||||
import jakarta.ws.rs.sse.SseBroadcaster
|
||||
import jakarta.ws.rs.sse.SseEventSink
|
||||
import org.eclipse.microprofile.config.inject.ConfigProperty
|
||||
import java.util.Optional
|
||||
import java.util.UUID
|
||||
|
||||
private const val LIMIT = 30
|
||||
|
||||
@Path("/dice/{id}")
|
||||
@ApplicationScoped
|
||||
final class DiceResource(@Context val sse: Sse) {
|
||||
|
||||
@ConfigProperty(name = "dice.limit")
|
||||
private lateinit var diceLimit: Optional<Int>
|
||||
|
||||
private var eventBuilder: OutboundSseEvent.Builder = sse.newEventBuilder()
|
||||
private var sseBroadcasters: MutableMap<String, SseBroadcaster> = HashMap()
|
||||
|
||||
@@ -37,24 +30,15 @@ final class DiceResource(@Context val sse: Sse) {
|
||||
data.user = id.split(":")[1]
|
||||
|
||||
val results = ArrayList<Results>()
|
||||
var numberOfDice = 0
|
||||
data.command.split(" ", "&", "and").filter { it.isNotEmpty() }.map { it.trim() }.toTypedArray<String>().forEach { command ->
|
||||
val dice = command.split("d")
|
||||
var amount = dice[0].toInt()
|
||||
val limit = diceLimit.orElse(LIMIT)
|
||||
if (limit < numberOfDice + amount) {
|
||||
amount = limit - numberOfDice
|
||||
}
|
||||
numberOfDice += amount
|
||||
if (amount > 0) {
|
||||
val result = IntArray(amount)
|
||||
val sides = dice[1].split("+", "-")
|
||||
val modifier = if (dice[1].contains("+")) sides[1].toInt() else if (dice[1].contains("+")) -1 * sides[1].toInt() else 0
|
||||
repeat(amount) { index ->
|
||||
result[index] = (Math.random() * sides[0].toInt() + 1).toInt()
|
||||
}
|
||||
results.add(Results(sides[0].toInt(), modifier, result.sum() + modifier, result.map { Roll(it) }.toTypedArray()))
|
||||
val result = IntArray(dice[0].toInt())
|
||||
val sides = dice[1].split("+", "-")
|
||||
val modifier = if (dice[1].contains("+")) sides[1].toInt() else if (dice[1].contains("+")) -1 * sides[1].toInt() else 0
|
||||
repeat(dice[0].toInt()) { index ->
|
||||
result[index] = (Math.random() * sides[0].toInt() + 1).toInt()
|
||||
}
|
||||
results.add(Results(sides[0].toInt(), modifier, result.sum() + modifier, result.map { Roll(it) }.toTypedArray()))
|
||||
}
|
||||
val map = results.map { r ->
|
||||
"${r.rolls.size}d${r.sides}@${
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 26 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 76 KiB |
@@ -14,17 +14,6 @@ function url() {
|
||||
return window.location.protocol + '//' + window.location.hostname + (window.location.port?.length > 0 ? ':' + window.location.port : '');
|
||||
}
|
||||
|
||||
function register() {
|
||||
let httpRequest = new XMLHttpRequest();
|
||||
httpRequest.open('POST', url() + '/dice/' + document.getElementById('room').value + '/register')
|
||||
httpRequest.setRequestHeader('Content-Type', 'application/json')
|
||||
httpRequest.send(JSON.stringify({
|
||||
name: document.getElementById('name').value,
|
||||
overlay: document.getElementById('overlayId').value,
|
||||
id: document.getElementById('room').value + ':' + localStorage.getItem('userId')
|
||||
}))
|
||||
}
|
||||
|
||||
function start(event = undefined) {
|
||||
if ((!event || event.keyCode === 13) && document.getElementById('name').value.length > 0 && document.getElementById('room').value.length > 0) {
|
||||
document.getElementById('overlayId').value = url() + '/overlay/' + document.getElementById('room').value + ':' + localStorage.getItem('userId') + '?scale=10&clearAfter=30';
|
||||
@@ -72,7 +61,14 @@ function start(event = undefined) {
|
||||
|
||||
localStorage.setItem(document.getElementById('name').value + '-started', "true")
|
||||
|
||||
register();
|
||||
let httpRequest = new XMLHttpRequest();
|
||||
httpRequest.open('POST', url() + '/dice/' + document.getElementById('room').value + '/register')
|
||||
httpRequest.setRequestHeader('Content-Type', 'application/json')
|
||||
httpRequest.send(JSON.stringify({
|
||||
name: document.getElementById('name').value,
|
||||
overlay: document.getElementById('overlayId').value,
|
||||
id: document.getElementById('room').value + ':' + localStorage.getItem('userId')
|
||||
}))
|
||||
if (document.getElementById('gm').checked) {
|
||||
document.getElementById('resultSwitch').checked = true;
|
||||
document.getElementById('resultFrame').src = document.getElementById('resultsId').value;
|
||||
@@ -102,21 +98,18 @@ function start(event = undefined) {
|
||||
newOverlay.appendChild(newInput);
|
||||
overlays.appendChild(newOverlay);
|
||||
|
||||
if (!document.getElementById(data.id + '-diceFrame')) {
|
||||
let dice = document.createElement('iframe');
|
||||
dice.id = data.id + '-diceFrame'
|
||||
dice.style.width = "50%";
|
||||
dice.style.height = "100%";
|
||||
dice.style.overflow = "hidden";
|
||||
dice.style.border = "0";
|
||||
dice.style.zIndex = "4";
|
||||
dice.style.position = "absolute";
|
||||
dice.style.top = "0";
|
||||
dice.style.left = "50%";
|
||||
dice.src = data.overlay;
|
||||
document.getElementById('results-dice').appendChild(dice)
|
||||
|
||||
}
|
||||
let dice = document.createElement('iframe');
|
||||
dice.id = data.id + '-diceFrame'
|
||||
dice.style.width = "50%";
|
||||
dice.style.height = "100%";
|
||||
dice.style.overflow = "hidden";
|
||||
dice.style.border = "0";
|
||||
dice.style.zIndex = "4";
|
||||
dice.style.position = "absolute";
|
||||
dice.style.top = "0";
|
||||
dice.style.left = "50%";
|
||||
dice.src = data.overlay;
|
||||
document.getElementById('results-dice').appendChild(dice)
|
||||
}
|
||||
|
||||
configurePopover();
|
||||
@@ -132,7 +125,6 @@ function rollEasy(dice) {
|
||||
|
||||
function roll(event) {
|
||||
if ((!event || event.keyCode === 13) && document.getElementById('command').value?.length > 0) {
|
||||
register()
|
||||
let httpRequest = new XMLHttpRequest();
|
||||
httpRequest.open('POST', url() + '/dice/' + document.getElementById('room').value + ':' + localStorage.getItem(`userId`))
|
||||
httpRequest.setRequestHeader('Content-Type', 'application/json')
|
||||
@@ -215,7 +207,11 @@ document.addEventListener("DOMContentLoaded", async () => {
|
||||
})
|
||||
|
||||
document.getElementById('resultDiceSwitch').addEventListener('change', function () {
|
||||
document.getElementById('results-dice').hidden = !this.checked;
|
||||
if (!this.checked) {
|
||||
document.getElementById('results-dice').hidden = true
|
||||
} else {
|
||||
document.getElementById('results-dice').hidden = false
|
||||
}
|
||||
})
|
||||
|
||||
document.getElementById('chatOverlayLink').href = url() + '/chatoverlay'
|
||||
|
||||
@@ -1,18 +0,0 @@
|
||||
{
|
||||
"name": "Dice-Tower",
|
||||
"icons": [
|
||||
{
|
||||
"src": "192.png",
|
||||
"type": "image/png",
|
||||
"sizes": "192x192"
|
||||
},
|
||||
{
|
||||
"src": "512.png",
|
||||
"type": "image/png",
|
||||
"sizes": "512x512"
|
||||
}
|
||||
],
|
||||
"start_url": "/",
|
||||
"display_override": ["window-controls-overlay", "minimal-ui"],
|
||||
"display": "standalone"
|
||||
}
|
||||
@@ -32,22 +32,6 @@ button:active {
|
||||
background: #222222;
|
||||
}
|
||||
|
||||
#install {
|
||||
padding: 10px;
|
||||
border: #666666 3px solid;
|
||||
border-radius: 10px;
|
||||
background: #666666;
|
||||
color: #fff
|
||||
}
|
||||
|
||||
#install:hover {
|
||||
background: #444444;
|
||||
}
|
||||
|
||||
#install:active {
|
||||
background: #222222;
|
||||
}
|
||||
|
||||
input {
|
||||
margin: 10px;
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<meta charset="UTF-8">
|
||||
<title>Dice-Tower</title>
|
||||
<meta name="version" content="{version}">
|
||||
<link rel="manifest" href="manifest.json" />
|
||||
|
||||
<link rel="stylesheet" href="/vendor/w3css/4/w3.css">
|
||||
<link rel="stylesheet" href="/vendor/font-awesome/css/fontawesome.css">
|
||||
<link rel="stylesheet" href="/vendor/font-awesome/css/all.css">
|
||||
@@ -33,17 +33,6 @@
|
||||
if (!localStorage.getItem("userId")) {
|
||||
localStorage.setItem("userId", self.crypto.randomUUID());
|
||||
}
|
||||
addEventListener("beforeinstallprompt", (event) => {
|
||||
event.preventDefault()
|
||||
let install = document.createElement('button');
|
||||
install.id = 'install'
|
||||
install.style.position = 'absolute'
|
||||
install.style.top = '25px'
|
||||
install.style.right = '25px'
|
||||
install.innerHTML = 'Install Dice-Tower'
|
||||
install.onclick = () => event.prompt()
|
||||
document.body.appendChild(install)
|
||||
});
|
||||
</script>
|
||||
<div class="w3-container w3-content"
|
||||
style="height: 95vh; display: flex; flex-direction: column; justify-content: space-between; padding: 25px">
|
||||
@@ -89,7 +78,6 @@
|
||||
<button style="border: transparent; border-radius: 100%; font-size: large; font-weight: bold; height: 50px; width: 50px"
|
||||
onclick="addDice()">+
|
||||
</button>
|
||||
<!--<button style="font-size: large; font-weight: bold;" onclick="rollEasy('d2')">D2</button><-->
|
||||
<button style="font-size: large; font-weight: bold;" onclick="rollEasy('d4')">D4</button>
|
||||
<button style="font-size: large; font-weight: bold;" onclick="rollEasy('d6')">D6</button>
|
||||
<button style="font-size: large; font-weight: bold;" onclick="rollEasy('d8')">D8</button>
|
||||
@@ -150,10 +138,10 @@
|
||||
</div>
|
||||
<div style="display: flex; flex-direction: row; justify-content: space-between; align-items: baseline">
|
||||
<div style="flex-grow: 1; padding: 0 10px">
|
||||
<color-picker id="faceColor" name="Face" value="#8d8981"></color-picker>
|
||||
<color-picker id="faceColor" name="Face"></color-picker>
|
||||
</div>
|
||||
<div style="flex-grow: 1; padding: 10px 0">
|
||||
<color-picker id="numberColor" name="Numbers" value="black"></color-picker>
|
||||
<color-picker id="numberColor" name="Numbers"></color-picker>
|
||||
</div>
|
||||
</div>
|
||||
<div id="dice-box">
|
||||
@@ -202,8 +190,11 @@
|
||||
<h2 style="text-align: center">How-To</h2>
|
||||
<ul>
|
||||
<li>
|
||||
Join a room by entering your character name and the name of the room
|
||||
Join a room by entering your character name and the name of the room.<br/>
|
||||
<strong>If you are a GM, make sure to join the room first or let all other players rejoin to get all
|
||||
Overlay-URLs.</strong>
|
||||
</li>
|
||||
|
||||
<li>Open your Dice-Overlay either in a new Tab or as a browser source in OBS</li>
|
||||
<ul>
|
||||
<li>You can configure your Overlay with query parameters (for more information hover over the link)
|
||||
|
||||
@@ -40,7 +40,7 @@
|
||||
foreground: data.numberColor
|
||||
}
|
||||
}).then(() => {
|
||||
diceBox.roll(data.roll.filter(it => it.split('@')[0].split('d')[1] !== "2").join('&'));
|
||||
diceBox.roll(data.roll.join('&'));
|
||||
})
|
||||
})
|
||||
</script>
|
||||
|
||||
Reference in New Issue
Block a user