more messageboxes on caught exceptions, update readme, bump to 0.2.2
This commit is contained in:
parent
7a294373c5
commit
9cf0de40cb
9 changed files with 57 additions and 49 deletions
10
README.md
10
README.md
|
@ -2,9 +2,11 @@
|
|||
|
||||
-- virtual tabletop for distributed cooperative storytelling --
|
||||
|
||||
![Screenshot of Felt showing a hexgrid map on which a party of 4 humans and an alien dog thing facing off against two giant centipedes. Various UI windows are overlayed, some of them collapsed, showing the dice roller with dice log, and admin windows showing map and token management interfaces.](./screenshot.jpg)
|
||||
|
||||
## about
|
||||
|
||||
Felt is a lightweight webapp written in Go and vanilla Javascript which provides an agnostic virtual tabletop for battle maps, visual puzzles, or any other situation you may need a shared map in a tabletop RPG over voice/video chat.
|
||||
Felt is a lightweight (~210KB frontend!) webapp written in Go and vanilla Javascript which provides an agnostic virtual tabletop for battle maps, visual puzzles, or any other situation you may need a shared map in a tabletop RPG over voice/video chat.
|
||||
|
||||
## usage
|
||||
|
||||
|
@ -20,7 +22,7 @@ The `status` panel is updated when the admin changes the table's status, and can
|
|||
|
||||
The `token select` panel provides a list of every existing token at the table. Clicking the name of the token shows a to-scale preview at the top of the list (with a button to dismiss it), which is resized according to the zoom level of the map. The button to the right of each token's name can place the token on or remove it from the map.
|
||||
|
||||
Any user can move any token on the map by dragging it around. The map is pannable and zoomable as well.
|
||||
Any user can move any token on the map by dragging it around. The map is pannable and zoomable as well. The UI theme is changeable from the drawer at bottom-left of the application, and it persists to `localStorage`.
|
||||
|
||||
### admin
|
||||
|
||||
|
@ -48,8 +50,8 @@ Creating or destroying tokens as well as changing the map causes updates to be s
|
|||
|
||||
Requirements:
|
||||
|
||||
- go
|
||||
- docker
|
||||
- go 1.19
|
||||
- docker (for the containerized database)
|
||||
|
||||
1. Clone this repository and `cd` into it.
|
||||
2. `go mod tidy`
|
||||
|
|
BIN
screenshot.jpg
Normal file
BIN
screenshot.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 266 KiB |
|
@ -65,7 +65,6 @@ async function loadAdmin(name, pass) {
|
|||
console.log(res.status);
|
||||
}
|
||||
} catch (err) {
|
||||
console.dir(err)
|
||||
setErr(`${err.name}: ${err.message}`);
|
||||
}
|
||||
}
|
||||
|
@ -162,26 +161,26 @@ function drawTokenOrigin() {
|
|||
if (dropdown && tokenWidth && tokenHeight && tokenCX && tokenCY && preview
|
||||
&& dropdown.selectedIndex >= 0) {
|
||||
|
||||
tokenCX.value = Math.floor(Number(tokenCX.value))
|
||||
tokenCY.value = Math.floor(Number(tokenCY.value))
|
||||
tokenCX.value = Math.floor(Number(tokenCX.value))
|
||||
tokenCY.value = Math.floor(Number(tokenCY.value))
|
||||
|
||||
const img = preview.children[0];
|
||||
const x = Number(tokenWidth.value) / Number(tokenCX.value);
|
||||
const y = Number(tokenHeight.value) / Number(tokenCY.value);
|
||||
const img = preview.children[0];
|
||||
const x = Number(tokenWidth.value) / Number(tokenCX.value);
|
||||
const y = Number(tokenHeight.value) / Number(tokenCY.value);
|
||||
|
||||
const origin = {x: img.width/x, y: img.height/y};
|
||||
const originImg = document.createElement("img");
|
||||
const origin = {x: img.width/x, y: img.height/y};
|
||||
const originImg = document.createElement("img");
|
||||
|
||||
originImg.src="/table/origin.png";
|
||||
originImg.style.position = "absolute";
|
||||
originImg.style.left = (origin.x - 2) + "px";
|
||||
originImg.style.top = (origin.y - 2) + "px";
|
||||
originImg.src="/table/origin.png";
|
||||
originImg.style.position = "absolute";
|
||||
originImg.style.left = (origin.x - 2) + "px";
|
||||
originImg.style.top = (origin.y - 2) + "px";
|
||||
|
||||
if (preview.children.length > 1) {
|
||||
preview.replaceChild(originImg, preview.children[1]);
|
||||
} else {
|
||||
preview.appendChild(originImg);
|
||||
}
|
||||
if (preview.children.length > 1) {
|
||||
preview.replaceChild(originImg, preview.children[1]);
|
||||
} else {
|
||||
preview.appendChild(originImg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -252,7 +251,9 @@ function createToken() {
|
|||
return;
|
||||
}
|
||||
setErr("All token fields are required");
|
||||
} catch {}
|
||||
} catch (err) {
|
||||
setErr(`${err.name}: ${err.message}`);
|
||||
}
|
||||
}
|
||||
|
||||
function destroyToken(id) {
|
||||
|
@ -270,7 +271,7 @@ function previewExistingToken(id) {
|
|||
try {
|
||||
const existing = tokens.find(t=>t.t.id == id);
|
||||
const dropdown = $("sprite_dropdown");
|
||||
if (existing) {
|
||||
if (existing && dropdown) {
|
||||
$("token_width").value = existing.t.w;
|
||||
$("token_height").value = existing.t.h;
|
||||
$("token_cx").value = existing.t.oX;
|
||||
|
@ -285,7 +286,7 @@ function previewExistingToken(id) {
|
|||
reinitializeSpritePreview(true);
|
||||
}
|
||||
} catch (err) {
|
||||
console.log(err);
|
||||
setErr(`${err.name}: ${err.message}`);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -486,7 +487,9 @@ function setTableCreateFormVisible(v) {
|
|||
$("new_table_name").value = "";
|
||||
$("new_table_pass").value = "";
|
||||
}
|
||||
} catch {}
|
||||
} catch (err) {
|
||||
setErr(`${err.name}: ${err.message}`);
|
||||
}
|
||||
}
|
||||
|
||||
function setTokenCreateFormVisible(v) {
|
||||
|
@ -502,7 +505,9 @@ function setTokenCreateFormVisible(v) {
|
|||
$("token_creation_form").style.display = v ? "block" : "none";
|
||||
$("token_list").style.display = v ? "none" : "block";
|
||||
$("token_admin_preview").innerHTML = "";
|
||||
} catch {}
|
||||
} catch (err) {
|
||||
setErr(`${err.name}: ${err.message}`);
|
||||
}
|
||||
}
|
||||
|
||||
async function createTable() {
|
||||
|
@ -538,8 +543,8 @@ async function createTable() {
|
|||
} else {
|
||||
setErr("Error creating table");
|
||||
}
|
||||
} catch {
|
||||
setErr("Error creating table");
|
||||
} catch (err) {
|
||||
setErr(`${err.name}: ${err.message}`);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -6,7 +6,7 @@
|
|||
<meta name="viewport" content="width=device-width" />
|
||||
<link rel="shortcut icon" href="./favicon.png"/>
|
||||
<link href="./leaflet.css?v=1.9.4" rel="stylesheet" />
|
||||
<link href="./style.css?v=0.2.0" rel="stylesheet" />
|
||||
<link href="./style.css?v=0.2.2" rel="stylesheet" />
|
||||
</head>
|
||||
<body>
|
||||
<noscript><div id="noscript_container">
|
||||
|
@ -146,13 +146,13 @@
|
|||
</form>
|
||||
</details>
|
||||
<div id="lag" style="display:none;">lag...</div>
|
||||
<div class="ui_win" id="felt_info"><a href="https://hacklab.nilfm.cc/felt">felt v0.2.1</a> (<a href="https://hacklab.nilfm.cc/felt/raw/main/LICENSE">license</a>) | built with <a href="https://leafletjs.com">leaflet</a> (<a href="https://hacklab.nilfm.cc/felt/raw/main/LEAFLET_LICENSE">license</a>) </div>
|
||||
<div class="ui_win" id="felt_info"><a href="https://hacklab.nilfm.cc/felt">felt v0.2.2</a> (<a href="https://hacklab.nilfm.cc/felt/raw/main/LICENSE">license</a>) | built with <a href="https://leafletjs.com">leaflet</a> (<a href="https://hacklab.nilfm.cc/felt/raw/main/LEAFLET_LICENSE">license</a>) </div>
|
||||
</nav>
|
||||
</body>
|
||||
<script src="./leaflet.js?v=1.9.4" type="text/javascript"></script>
|
||||
<script src="./util.js?v=0.2.1" type="text/javascript"></script>
|
||||
<script src="./map.js?v=0.2.1" type="text/javascript"></script>
|
||||
<script src="./socket.js?v=0.2.1" type="text/javascript"></script>
|
||||
<script src="./dice.js?v=0.2.1" type="text/javascript"></script>
|
||||
<script src="./admin.js?v=0.2.1" type="text/javascript"></script>
|
||||
<script src="./util.js?v=0.2.2" type="text/javascript"></script>
|
||||
<script src="./map.js?v=0.2.2" type="text/javascript"></script>
|
||||
<script src="./socket.js?v=0.2.2" type="text/javascript"></script>
|
||||
<script src="./dice.js?v=0.2.2" type="text/javascript"></script>
|
||||
<script src="./admin.js?v=0.2.2" type="text/javascript"></script>
|
||||
</html>
|
|
@ -57,6 +57,14 @@ function resizeMarkers() {
|
|||
|
||||
}
|
||||
|
||||
function sortByTokenName(a, b) {
|
||||
return (a.t.name < b.t.name)
|
||||
? -1
|
||||
: ((a.t.name > b.t.name)
|
||||
? 1
|
||||
: 0)
|
||||
}
|
||||
|
||||
function processTokens(tokenChanges) {
|
||||
for (const t of tokenChanges) {
|
||||
const i = tokens.findIndex(tk=>tk.t.id == t.id);
|
||||
|
@ -84,14 +92,7 @@ function processTokens(tokenChanges) {
|
|||
if (t.x != null && t.y != null) {
|
||||
const self = NewToken(t);
|
||||
tokens.push(self);
|
||||
tokens.sort((a,b)=>{
|
||||
if (a.t.name < b.t.name) {
|
||||
return -1;
|
||||
} else if (a.t.name > b.t.name) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
});
|
||||
tokens.sort(sortByTokenName);
|
||||
if (t.active) {
|
||||
self.m.addTo(map);
|
||||
}
|
||||
|
|
|
@ -171,7 +171,7 @@ a:hover, a:active {
|
|||
}
|
||||
|
||||
.ui_win ul {
|
||||
max-height: 10em;
|
||||
max-height: 16em;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
<title>Felt — Error</title>
|
||||
<meta name="viewport" content="width=device-width" />
|
||||
<link rel="shortcut icon" href="/table/favicon.png"/>
|
||||
<link href="/table/style.css?v=0.2.0" rel="stylesheet" />
|
||||
<link href="/table/style.css?v=0.2.2" rel="stylesheet" />
|
||||
</head>
|
||||
<body>
|
||||
<main id="registration">
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
<title>Felt — Admin Registration</title>
|
||||
<meta name="viewport" content="width=device-width" />
|
||||
<link rel="shortcut icon" href="/table/favicon.png"/>
|
||||
<link href="/table/style.css?v=0.2.0" rel="stylesheet" />
|
||||
<link href="/table/style.css?v=0.2.2" rel="stylesheet" />
|
||||
</head>
|
||||
<body>
|
||||
<main id="registration">
|
||||
|
@ -23,5 +23,5 @@
|
|||
{{end}}
|
||||
</main>
|
||||
</body>
|
||||
<script src="/table/util.js?v=0.2.1" type="text/javascript"></script>
|
||||
<script src="/table/util.js?v=0.2.2" type="text/javascript"></script>
|
||||
</html>
|
|
@ -6,7 +6,7 @@
|
|||
<title>Felt — Registration Complete</title>
|
||||
<meta name="viewport" content="width=device-width" />
|
||||
<link rel="shortcut icon" href="/table/favicon.png"/>
|
||||
<link href="/table/style.css?v=0.2.0" rel="stylesheet" />
|
||||
<link href="/table/style.css?v=0.2.2" rel="stylesheet" />
|
||||
</head>
|
||||
<body>
|
||||
<main id="registration">
|
||||
|
|
Loading…
Reference in a new issue