diff --git a/assets/web/index.html b/assets/web/index.html
index ce2730e..943f8ea 100644
--- a/assets/web/index.html
+++ b/assets/web/index.html
@@ -8,6 +8,7 @@
var mapScale = 1.0;
var mapOffsetX = 0.0;
var mapOffsetY = 0.0;
+ var draggedToken = { token: null, offX: 0, offY: 0 };
function init() {
let view = document.getElementById('game-view');
@@ -15,6 +16,7 @@
view.onclick = (e) => console.log('click', e);
view.onauxclick = (e) => console.log(e);
view.onmousemove = onGameMouseMove;
+ view.onmouseup = onGameMouseUp;
view.oncontextmenu = () => false;
// allow sending chat message using enter (and shift-enter for new line)
document.getElementById('newmsg-content').onkeypress = (e) => {
@@ -95,13 +97,20 @@
console.log(t);
let map = document.getElementById('map');
let token = document.createElement('div');
- token.className = 'token';
+ token.className = 'token token-transition';
token.style.top = `${t.y * GRID_SIZE}px`;
token.style.left = `${t.x * GRID_SIZE}px`;
token.token_id = t.token_id;
token.innerHTML = `
-
+
`
+ token.onmousedown = (e) => {
+ token.classList.remove('token-transition');
+ draggedToken.token = token;
+ draggedToken.offX = ((e.clientX - mapOffsetX) / mapScale) - parseInt(token.style.left);
+ draggedToken.offY = ((e.clientY - mapOffsetY) / mapScale) - parseInt(token.style.top);
+ token.children[0].style.cursor = 'grabbing';
+ }
map.append(token);
}
tavern.onmovetoken = (m) => {
@@ -136,6 +145,25 @@
map.style.left = `${mapOffsetX}px`;
map.style.top = `${mapOffsetY}px`;
}
+ else if(draggedToken.token != null && event.buttons == 1) {
+ let top = (event.clientY - mapOffsetY) / mapScale - draggedToken.offY;
+ let left = (event.clientX - mapOffsetX) / mapScale - draggedToken.offX;
+ console.log(event.clientX, event.clientY, draggedToken.offX, draggedToken.offY);
+ draggedToken.token.style.top = `${top}px`;
+ draggedToken.token.style.left = `${left}px`;
+ }
+ }
+ function onGameMouseUp() {
+ if(draggedToken.token != null) {
+ let t = draggedToken.token;
+ let x = Math.floor(0.5 + parseInt(t.style.left) / GRID_SIZE);
+ let y = Math.floor(0.5 + parseInt(t.style.top) / GRID_SIZE);
+ let id = t.token_id;
+ t.classList.add('token-transition');
+ t.children[0].style.cursor = '';
+ tavern.move_token(id, x, y);
+ draggedToken.token = null;
+ }
}
function sendChatMessage() {
let tb = document.getElementById('newmsg-content');
@@ -209,9 +237,11 @@
}
.token {
position: absolute;
+ }
+ .token-transition {
transition:
- top 0.5s ease-in,
- left 0.5s ease-in;
+ top 0.5s ease-in,
+ left 0.5s ease-in;
}
.token img {
cursor: grab;
@@ -248,7 +278,7 @@
floating
stuff
-
diff --git a/src/api/game_actions.rs b/src/api/game_actions.rs
index d6417c4..ebcf9b4 100644
--- a/src/api/game_actions.rs
+++ b/src/api/game_actions.rs
@@ -15,4 +15,21 @@ pub struct Ping {
pub struct ShowImage {
/// Which texture to show
pub texture: String
+}
+
+#[derive(Serialize, Deserialize, Clone)]
+pub struct SpawnToken {
+ pub token_id: usize,
+ pub x: i32,
+ pub y: i32,
+ pub img: String
+}
+impl std::fmt::Debug for SpawnToken {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ f.debug_struct("SpawnToken")
+ .field("token_id", &self.token_id)
+ .field("x", &self.x)
+ .field("y", &self.y)
+ .finish()
+ }
}
\ No newline at end of file
diff --git a/src/api/login.rs b/src/api/login.rs
index f7a28b7..beb702a 100644
--- a/src/api/login.rs
+++ b/src/api/login.rs
@@ -6,7 +6,7 @@ pub struct LoginRequest {
pub password: String,
}
-#[derive(Serialize, Clone)]
+#[derive(Serialize, Clone, Debug)]
pub struct LoginResult {
pub success: bool,
// TODO: Figure out what the user needs on successful login to reduce traffic
diff --git a/src/api/mod.rs b/src/api/mod.rs
index 2933afe..776b1a0 100644
--- a/src/api/mod.rs
+++ b/src/api/mod.rs
@@ -2,6 +2,7 @@ pub mod login;
pub mod game_actions;
pub mod map_actions;
+use game_actions::SpawnToken;
use serde::{Deserialize, Serialize};
use crate::game::chat_message::ChatMessage;
@@ -22,7 +23,7 @@ pub enum Request {
Kick(String),
Shutdown
}
-#[derive(Serialize, Clone)]
+#[derive(Serialize, Clone, Debug)]
#[serde(rename_all = "snake_case")]
pub enum Response {
Error(RequestError),
@@ -30,7 +31,7 @@ pub enum Response {
Message(ChatMessage),
GetChatHistory(Vec),
MoveToken { token_id: usize, x: i32, y: i32 },
- SpawnToken { token_id: usize, x: i32, y: i32, img: String },
+ SpawnToken(SpawnToken),
Quit { id: String },
Shutdown,
diff --git a/src/lib.rs b/src/lib.rs
index ca90497..2992d57 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -1,3 +1,4 @@
+use api::game_actions::SpawnToken;
use game::{chat_message::ChatMessage, Game, GameImpl};
use tokio::sync::{broadcast, mpsc};
@@ -87,7 +88,7 @@ impl GameServer {
for (i, (path, x, y)) in self.tokens.iter().enumerate() {
let bits = std::fs::read(path).expect("FAILED READING TOKEN IMAGE");
let img = base64::Engine::encode(&base64::prelude::BASE64_STANDARD, &bits);
- _ = broadcast.send((Some(id.clone()), api::Response::SpawnToken { token_id: i, x: *x, y: *y, img }));
+ _ = broadcast.send((Some(id.clone()), api::Response::SpawnToken(SpawnToken { token_id: i, x: *x, y: *y, img })));
}
},
api::Request::SpawnToken { x, y, img_path } => {
@@ -95,11 +96,15 @@ impl GameServer {
self.tokens.push((img_path.clone(), x, y));
let bits = std::fs::read(img_path).expect("FAILED READING TOKEN IMAGE");
let img = base64::Engine::encode(&base64::prelude::BASE64_STANDARD, &bits);
- _ = broadcast.send((Some(id.clone()), api::Response::SpawnToken { token_id, x, y, img }));
+ _ = broadcast.send((Some(id.clone()), api::Response::SpawnToken(SpawnToken { token_id, x, y, img })));
},
api::Request::MoveToken { token_id, x, y } => {
// TODO: add check to make sure the actor is authorized to move the token
- _ = broadcast.send((None, api::Response::MoveToken { token_id, x, y }));
+ if token_id < self.tokens.len() {
+ self.tokens[token_id].1 = x;
+ self.tokens[token_id].2 = y;
+ _ = broadcast.send((None, api::Response::MoveToken { token_id, x, y }));
+ }
},
api::Request::Quit => _ = broadcast.send((None, api::Response::Quit { id })),
api::Request::Kick(id) => _ = broadcast.send((Some(id), api::Response::Shutdown)),
diff --git a/src/main.rs b/src/main.rs
index a921bb6..ff5f1f9 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -54,6 +54,7 @@ async fn socket_receiver(mut recv: SplitStream, msend: mpsc::Send
async fn socket_sender(id: String, mut send: SplitSink, mut brecv: broadcast::Receiver<(Option, Response)>) {
while let Ok((to_id, msg)) = brecv.recv().await {
if to_id.is_none() || to_id.map(|t| t == id).unwrap_or(false) {
+ println!("Sending a message to {}: {:?}", &id, &msg);
let err = send.send(ws::Message::Text(serde_json::to_string(&msg).unwrap())).await.is_err();
if err || matches!(msg, Response::Shutdown) {
_ = send.close().await;