allow texture streaming(png, jpeg for now) and use texture url instead of passing textures in base64
This commit is contained in:
parent
1d63e3d983
commit
d29a2a8590
5 changed files with 47 additions and 17 deletions
15
Cargo.lock
generated
15
Cargo.lock
generated
|
@ -978,13 +978,13 @@ name = "open_tavern"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"axum",
|
"axum",
|
||||||
"base64",
|
|
||||||
"futures-util",
|
"futures-util",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
"sqlx",
|
"sqlx",
|
||||||
"tavern_macros",
|
"tavern_macros",
|
||||||
"tokio",
|
"tokio",
|
||||||
|
"tokio-util",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -1751,6 +1751,19 @@ dependencies = [
|
||||||
"tungstenite",
|
"tungstenite",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tokio-util"
|
||||||
|
version = "0.7.15"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "66a539a9ad6d5d281510d5bd368c973d636c02dbf8a67300bfb6b950696ad7df"
|
||||||
|
dependencies = [
|
||||||
|
"bytes",
|
||||||
|
"futures-core",
|
||||||
|
"futures-sink",
|
||||||
|
"pin-project-lite",
|
||||||
|
"tokio",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tower"
|
name = "tower"
|
||||||
version = "0.4.13"
|
version = "0.4.13"
|
||||||
|
|
|
@ -8,7 +8,7 @@ axum = { version = "0.8.4", features = ["ws"] }
|
||||||
serde = "1.*.*"
|
serde = "1.*.*"
|
||||||
serde_json = "1.*.*"
|
serde_json = "1.*.*"
|
||||||
tokio = { version = "1.*.*", features = ["full"] }
|
tokio = { version = "1.*.*", features = ["full"] }
|
||||||
|
tokio-util = { version = "0.7.15", features = ["io"] }
|
||||||
sqlx = { version = "0.8.6", features = ["runtime-tokio", "sqlite"] }
|
sqlx = { version = "0.8.6", features = ["runtime-tokio", "sqlite"] }
|
||||||
tavern_macros = { version = "0.1.0", path = "tavern_macros" }
|
tavern_macros = { version = "0.1.0", path = "tavern_macros" }
|
||||||
futures-util = "0.3.31"
|
futures-util = "0.3.31"
|
||||||
base64 = "0.22.1"
|
|
||||||
|
|
|
@ -145,7 +145,7 @@ tavern.onspawntoken = (t) => {
|
||||||
token.style.left = `${t.x * GRID_SIZE}px`;
|
token.style.left = `${t.x * GRID_SIZE}px`;
|
||||||
token.token_id = t.token_id;
|
token.token_id = t.token_id;
|
||||||
token.innerHTML = `
|
token.innerHTML = `
|
||||||
<img src='data:image/jpg;base64,${t.img}' ondragstart='return false;'>
|
<img src='${t.img}' ondragstart='return false;'>
|
||||||
`
|
`
|
||||||
token.onmousedown = (e) => {
|
token.onmousedown = (e) => {
|
||||||
token.classList.remove('token-transition');
|
token.classList.remove('token-transition');
|
||||||
|
|
14
src/lib.rs
14
src/lib.rs
|
@ -144,15 +144,13 @@ impl GameServer {
|
||||||
api::Request::GetTokens { scene } => {
|
api::Request::GetTokens { scene } => {
|
||||||
for token_id in self.game.available_tokens(scene) {
|
for token_id in self.game.available_tokens(scene) {
|
||||||
if let Some(ti) = self.game.token_info(0, token_id) {
|
if let Some(ti) = self.game.token_info(0, token_id) {
|
||||||
let bits = std::fs::read(&ti.img_source).expect("FAILED READING TOKEN IMAGE");
|
|
||||||
let img = base64::Engine::encode(&base64::prelude::BASE64_STANDARD, &bits);
|
|
||||||
_ = broadcast.send((
|
_ = broadcast.send((
|
||||||
Some(id.clone()),
|
Some(id.clone()),
|
||||||
api::Response::SpawnToken(SpawnToken {
|
api::Response::SpawnToken(SpawnToken {
|
||||||
token_id: token_id,
|
token_id: token_id,
|
||||||
x: ti.x,
|
x: ti.x,
|
||||||
y: ti.y,
|
y: ti.y,
|
||||||
img,
|
img: ti.img_source.clone(),
|
||||||
}),
|
}),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
@ -160,7 +158,7 @@ impl GameServer {
|
||||||
}
|
}
|
||||||
api::Request::GetCurrentScene => {
|
api::Request::GetCurrentScene => {
|
||||||
let scene = self.game.current_scene();
|
let scene = self.game.current_scene();
|
||||||
let mut scene_tokens = self
|
let scene_tokens = self
|
||||||
.game
|
.game
|
||||||
.available_tokens(scene)
|
.available_tokens(scene)
|
||||||
.iter()
|
.iter()
|
||||||
|
@ -173,10 +171,6 @@ impl GameServer {
|
||||||
img: info.img_source.clone(),
|
img: info.img_source.clone(),
|
||||||
})
|
})
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
for spawn in scene_tokens.iter_mut() {
|
|
||||||
let bits = std::fs::read(&spawn.img).expect("FAILED READING TOKEN IMAGE");
|
|
||||||
spawn.img = base64::Engine::encode(&base64::prelude::BASE64_STANDARD, &bits);
|
|
||||||
}
|
|
||||||
_ = broadcast.send((
|
_ = broadcast.send((
|
||||||
Some(id.clone()),
|
Some(id.clone()),
|
||||||
api::Response::ShowScene {
|
api::Response::ShowScene {
|
||||||
|
@ -193,11 +187,9 @@ impl GameServer {
|
||||||
img_path,
|
img_path,
|
||||||
} => {
|
} => {
|
||||||
let token_id = self.game.create_token(map_id, character, img_path.clone(), x, y);
|
let token_id = self.game.create_token(map_id, character, 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((
|
_ = broadcast.send((
|
||||||
Some(id.clone()),
|
Some(id.clone()),
|
||||||
api::Response::SpawnToken(SpawnToken { token_id, x, y, img }),
|
api::Response::SpawnToken(SpawnToken { token_id, x, y, img: img_path.clone() }),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
api::Request::MoveToken { token_id, x, y } => {
|
api::Request::MoveToken { token_id, x, y } => {
|
||||||
|
|
31
src/main.rs
31
src/main.rs
|
@ -1,7 +1,5 @@
|
||||||
use axum::{
|
use axum::{
|
||||||
Router,
|
extract::ws::{self, Message}, http::StatusCode, response::{self, IntoResponse}, routing, Router
|
||||||
extract::ws::{self, Message},
|
|
||||||
response, routing,
|
|
||||||
};
|
};
|
||||||
use futures_util::{
|
use futures_util::{
|
||||||
SinkExt, StreamExt,
|
SinkExt, StreamExt,
|
||||||
|
@ -9,6 +7,7 @@ use futures_util::{
|
||||||
};
|
};
|
||||||
use open_tavern::api::{Request, RequestError, Response};
|
use open_tavern::api::{Request, RequestError, Response};
|
||||||
use tokio::sync::{broadcast, mpsc};
|
use tokio::sync::{broadcast, mpsc};
|
||||||
|
use tokio_util::io::ReaderStream;
|
||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
async fn main() {
|
async fn main() {
|
||||||
|
@ -20,6 +19,7 @@ async fn main() {
|
||||||
.route("/tavern.js", routing::get(socket))
|
.route("/tavern.js", routing::get(socket))
|
||||||
.route("/app.js", routing::get(app_js))
|
.route("/app.js", routing::get(app_js))
|
||||||
.route("/style.css", routing::get(style))
|
.route("/style.css", routing::get(style))
|
||||||
|
.route("/assets/{*asset}", routing::get(get_asset))
|
||||||
.route(
|
.route(
|
||||||
"/ws",
|
"/ws",
|
||||||
routing::get(move |w| ws_handler(w, msend, bsend2.clone().subscribe())),
|
routing::get(move |w| ws_handler(w, msend, bsend2.clone().subscribe())),
|
||||||
|
@ -191,3 +191,28 @@ async fn style() -> impl response::IntoResponse {
|
||||||
std::fs::read_to_string("./assets/web/style.css").unwrap(),
|
std::fs::read_to_string("./assets/web/style.css").unwrap(),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async fn get_asset(asset: axum::extract::Path<String>) -> impl IntoResponse {
|
||||||
|
println!("Asset requested: {}", asset.0);
|
||||||
|
let supported_file_types = [
|
||||||
|
(".jpg", "image/jpeg"), (".jpeg", "image/jpeg"), (".png", "image/png")
|
||||||
|
];
|
||||||
|
let mime = match supported_file_types.iter()
|
||||||
|
.filter(|t| asset.0.ends_with(t.0))
|
||||||
|
.map(|t| t.1)
|
||||||
|
.next() {
|
||||||
|
Some(t) => t,
|
||||||
|
None => return Err((StatusCode::UNSUPPORTED_MEDIA_TYPE, "Unsupported file type".to_string())),
|
||||||
|
};
|
||||||
|
let file = match tokio::fs::File::open(format!("assets/{}", asset.0)).await {
|
||||||
|
Ok(f) => f,
|
||||||
|
Err(err) => return Err((StatusCode::NOT_FOUND, format!("File not found: {}", err))),
|
||||||
|
};
|
||||||
|
let stream = ReaderStream::new(file);
|
||||||
|
let body = axum::body::Body::from_stream(stream);
|
||||||
|
|
||||||
|
let headers = [
|
||||||
|
(axum::http::header::CONTENT_TYPE, mime)
|
||||||
|
];
|
||||||
|
Ok((headers, body))
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue