[feat] use eti game.db, commit not working, something is wrong with game.id in the client/frontend
This commit is contained in:
@ -16,14 +16,14 @@ pub enum ClientEvent {
|
||||
#[derive(Debug)]
|
||||
pub enum ClientCommand {
|
||||
ListGames,
|
||||
GetGame(u64),
|
||||
GetGame(String),
|
||||
ServerAddr(SocketAddr),
|
||||
}
|
||||
|
||||
/// # Errors
|
||||
pub async fn run(
|
||||
mut rx_control: UnboundedReceiver<ClientCommand>,
|
||||
tx_event: UnboundedSender<ClientEvent>,
|
||||
tx_notify_ui: UnboundedSender<ClientEvent>,
|
||||
) -> eyre::Result<()> {
|
||||
// blocking wait for remote address
|
||||
log::debug!("waiting for server address");
|
||||
@ -75,7 +75,7 @@ pub async fn run(
|
||||
};
|
||||
|
||||
let data = request.encode();
|
||||
log::error!("encoded data: {}", String::from_utf8_lossy(&data));
|
||||
log::debug!("encoded data: {}", String::from_utf8_lossy(&data));
|
||||
|
||||
let stream = match conn.open_bidirectional_stream().await {
|
||||
Ok(stream) => stream,
|
||||
@ -91,104 +91,52 @@ pub async fn run(
|
||||
log::error!("failed to send request to server {:?}", e);
|
||||
}
|
||||
|
||||
if let Ok(Some(data)) = rx.receive().await {
|
||||
log::trace!("server response (raw): {}", String::from_utf8_lossy(&data));
|
||||
let mut all_data: Vec<u8> = Vec::new();
|
||||
while let Ok(Some(data)) = rx.receive().await {
|
||||
log::trace!("msg from server (raw): {}", String::from_utf8_lossy(&data));
|
||||
all_data.extend_from_slice(&data);
|
||||
}
|
||||
log::debug!("{} bytes received from server", all_data.len());
|
||||
log::trace!(
|
||||
"server response (RAW): {}",
|
||||
String::from_utf8_lossy(&all_data)
|
||||
);
|
||||
|
||||
let response = Response::decode(&data);
|
||||
log::trace!(
|
||||
"server response (decoded): {}",
|
||||
String::from_utf8_lossy(&data)
|
||||
);
|
||||
match response {
|
||||
Response::Games(games) => {
|
||||
for game in &games {
|
||||
log::debug!("{game:?}");
|
||||
}
|
||||
let response = Response::decode(&all_data);
|
||||
log::trace!("server response (DECODED): {response:?}");
|
||||
|
||||
if let Err(e) = tx_event.send(ClientEvent::ListGames(games)) {
|
||||
log::error!("failed to send ClientEvent::ListGames to client {e:?}");
|
||||
}
|
||||
match response {
|
||||
Response::Games(games) => {
|
||||
for game in &games {
|
||||
log::debug!("{game:?}");
|
||||
}
|
||||
Response::Game(game) => log::debug!("game received: {game:?}"),
|
||||
Response::GameNotFound(id) => log::debug!("game not found {id}"),
|
||||
Response::InvalidRequest(request_bytes, err) => log::error!(
|
||||
"server says our request was invalid (error: {}): {}",
|
||||
|
||||
if let Err(e) = tx_notify_ui.send(ClientEvent::ListGames(games)) {
|
||||
log::debug!("failed to send ClientEvent::ListGames to client {e:?}");
|
||||
}
|
||||
}
|
||||
Response::Game(game) => log::debug!("game received: {game:?}"),
|
||||
Response::GameNotFound(id) => log::debug!("game not found {id}"),
|
||||
Response::InvalidRequest(request_bytes, err) => log::error!(
|
||||
"server says our request was invalid (error: {}): {}",
|
||||
err,
|
||||
String::from_utf8_lossy(&request_bytes)
|
||||
),
|
||||
Response::EncodingError(err) => {
|
||||
log::error!("server encoding error: {err}");
|
||||
}
|
||||
Response::DecodingError(data, err) => {
|
||||
log::error!(
|
||||
"response decoding error: {} (data: {})",
|
||||
err,
|
||||
String::from_utf8_lossy(&request_bytes)
|
||||
),
|
||||
Response::EncodingError(err) => {
|
||||
log::error!("server encoding error: {err}");
|
||||
}
|
||||
Response::DecodingError(data, err) => {
|
||||
log::error!(
|
||||
"response decoding error: {} (data: {})",
|
||||
err,
|
||||
String::from_utf8_lossy(&data)
|
||||
);
|
||||
}
|
||||
String::from_utf8_lossy(&data)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if let Err(err) = tx.close().await {
|
||||
log::error!("failed to close stream: {err}");
|
||||
}
|
||||
if let Err(err) = tx.close().await {
|
||||
log::error!("failed to close stream: {err}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// log::info!("server closed connection");
|
||||
// Ok(())
|
||||
}
|
||||
|
||||
// #[derive(Debug, Parser)]
|
||||
// struct Cli {
|
||||
// /// Server IP address.
|
||||
// #[clap(long, default_value = "127.0.0.1")]
|
||||
// ip: IpAddr,
|
||||
// /// Server port.
|
||||
// #[clap(long, default_value = "13337")]
|
||||
// port: u16,
|
||||
// }
|
||||
|
||||
// #[tokio::main]
|
||||
// async fn main() -> eyre::Result<()> {
|
||||
// let cli = Cli::parse();
|
||||
|
||||
// let (tx_control, rx_control) = tokio::sync::mpsc::unbounded_channel::<ControlMessage>();
|
||||
|
||||
// // Spawn client in a separate task
|
||||
// let client_handle = tokio::spawn(async move {
|
||||
// let remote_addr = SocketAddr::from((cli.ip, cli.port));
|
||||
// Client::run(remote_addr, rx_control).await
|
||||
// });
|
||||
|
||||
// // Handle stdin commands in the main task
|
||||
// let mut stdin = BufReader::new(tokio::io::stdin());
|
||||
// let mut line = String::new();
|
||||
|
||||
// loop {
|
||||
// line.clear();
|
||||
// if stdin.read_line(&mut line).await? == 0 {
|
||||
// break; // EOF reached
|
||||
// }
|
||||
|
||||
// // Trim whitespace and handle commands
|
||||
// match line.trim() {
|
||||
// "list" => {
|
||||
// tx_control.send(ControlMessage::ListGames)?;
|
||||
// }
|
||||
// cmd if cmd.starts_with("get ") => {
|
||||
// if let Ok(id) = cmd[4..].trim().parse::<u64>() {
|
||||
// tx_control.send(ControlMessage::GetGame(id))?;
|
||||
// } else {
|
||||
// println!("Invalid game ID");
|
||||
// }
|
||||
// }
|
||||
// "quit" | "exit" => break,
|
||||
// "" => continue,
|
||||
// _ => println!("Unknown command. Available commands: list, get <id>, quit"),
|
||||
// }
|
||||
// }
|
||||
|
||||
// client_handle.await??;
|
||||
// Ok(())
|
||||
// }
|
||||
|
10
crates/lanspread-compat/Cargo.toml
Normal file
10
crates/lanspread-compat/Cargo.toml
Normal file
@ -0,0 +1,10 @@
|
||||
[package]
|
||||
name = "lanspread-compat"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
eyre = { workspace = true }
|
||||
sqlx = { version = "0.8", features = ["sqlite", "runtime-tokio"] }
|
||||
serde = { workspace = true }
|
||||
tracing = { workspace = true }
|
47
crates/lanspread-compat/src/eti.rs
Normal file
47
crates/lanspread-compat/src/eti.rs
Normal file
@ -0,0 +1,47 @@
|
||||
use std::path::Path;
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
use sqlx::sqlite::SqlitePool;
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize, sqlx::FromRow)]
|
||||
pub struct EtiGame {
|
||||
pub game_id: String,
|
||||
pub game_title: String,
|
||||
pub game_key: String,
|
||||
pub game_release: String,
|
||||
pub game_publisher: String,
|
||||
pub game_size: f64,
|
||||
pub game_readme_de: String,
|
||||
pub game_readme_en: String,
|
||||
pub game_readme_fr: String,
|
||||
pub game_maxplayers: u32,
|
||||
pub game_master_req: i32,
|
||||
pub genre_de: String,
|
||||
pub game_version: String,
|
||||
}
|
||||
|
||||
/// # Errors
|
||||
pub async fn get_games(db: &Path) -> eyre::Result<Vec<EtiGame>> {
|
||||
let pool = SqlitePool::connect(format!("sqlite:{}", db.to_string_lossy()).as_str()).await?;
|
||||
|
||||
let mut games = sqlx::query_as::<_, EtiGame>(
|
||||
"SELECT
|
||||
g.game_id, g.game_title, g.game_key, g.game_release,
|
||||
g.game_publisher, CAST(g.game_size AS REAL) as game_size, g.game_readme_de,
|
||||
g.game_readme_en, g.game_readme_fr, CAST(g.game_maxplayers AS INTEGER) as game_maxplayers,
|
||||
g.game_master_req, ge.genre_de, g.game_version
|
||||
FROM games g
|
||||
JOIN genre ge ON g.genre_id = ge.genre_id",
|
||||
)
|
||||
.fetch_all(&pool)
|
||||
.await?;
|
||||
|
||||
games.sort_by(|a, b| a.game_title.cmp(&b.game_title));
|
||||
|
||||
tracing::info!("Found {} games in game.db", games.len());
|
||||
for game in &games {
|
||||
tracing::debug!("{}: {}", game.game_id, game.game_title);
|
||||
}
|
||||
|
||||
Ok(games)
|
||||
}
|
1
crates/lanspread-compat/src/lib.rs
Normal file
1
crates/lanspread-compat/src/lib.rs
Normal file
@ -0,0 +1 @@
|
||||
pub mod eti;
|
@ -13,7 +13,8 @@ unwrap_used = "warn"
|
||||
|
||||
[dependencies]
|
||||
# external
|
||||
eyre = { workspace = true}
|
||||
semver = { workspace = true}
|
||||
serde = { workspace = true}
|
||||
serde_json = { workspace = true}
|
||||
eyre = { workspace = true }
|
||||
semver = { workspace = true }
|
||||
serde = { workspace = true }
|
||||
serde_json = { workspace = true }
|
||||
tracing = { workspace = true }
|
||||
|
@ -1,33 +1,30 @@
|
||||
#![allow(clippy::missing_errors_doc)]
|
||||
#![allow(clippy::doc_markdown)]
|
||||
|
||||
use std::{
|
||||
collections::HashMap,
|
||||
fmt,
|
||||
fs::{File, OpenOptions},
|
||||
path::Path,
|
||||
};
|
||||
use std::{collections::HashMap, fmt};
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::serialization::version_serde;
|
||||
|
||||
/// A game
|
||||
#[derive(Clone, Serialize, Deserialize)]
|
||||
pub struct Game {
|
||||
/// example: 1
|
||||
pub id: u64,
|
||||
/// example: Call of Duty 3
|
||||
/// example: aoe2
|
||||
pub id: String,
|
||||
/// example: Age of Empires 2
|
||||
pub name: String,
|
||||
/// example: A shooter game in war.
|
||||
/// example: Dieses Paket enthält die original AoE 2 Version,...
|
||||
pub description: String,
|
||||
/// example: `call_of_duty.tar.zst`
|
||||
pub install_archive: String,
|
||||
/// example: 1999
|
||||
pub release_year: String,
|
||||
/// Microsoft
|
||||
pub publisher: String,
|
||||
/// example: 8
|
||||
pub max_players: u32,
|
||||
/// example: 1.0.0
|
||||
#[serde(with = "version_serde")]
|
||||
pub version: semver::Version,
|
||||
/// size (bytes)
|
||||
/// example: 3.5
|
||||
pub version: String,
|
||||
/// example: Echtzeit-Strategie
|
||||
pub genre: String,
|
||||
/// size in bytes: example: 3455063152
|
||||
pub size: u64,
|
||||
}
|
||||
|
||||
@ -35,14 +32,10 @@ impl fmt::Debug for Game {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(
|
||||
f,
|
||||
"{}: {} {} ({} players) ({}: {} MB) {}",
|
||||
"{}: {} ({} MB)",
|
||||
self.id,
|
||||
self.name,
|
||||
self.version,
|
||||
self.max_players,
|
||||
self.install_archive,
|
||||
self.size,
|
||||
self.description,
|
||||
self.size / 1024 / 1024,
|
||||
)
|
||||
}
|
||||
}
|
||||
@ -75,8 +68,7 @@ impl Ord for Game {
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct GameDB {
|
||||
pub games: HashMap<u64, Game>,
|
||||
next_id: u64,
|
||||
pub games: HashMap<String, Game>,
|
||||
}
|
||||
|
||||
impl GameDB {
|
||||
@ -84,7 +76,6 @@ impl GameDB {
|
||||
pub fn new() -> Self {
|
||||
GameDB {
|
||||
games: HashMap::new(),
|
||||
next_id: 1,
|
||||
}
|
||||
}
|
||||
|
||||
@ -92,39 +83,17 @@ impl GameDB {
|
||||
pub fn from(games: Vec<Game>) -> Self {
|
||||
let mut db = GameDB::new();
|
||||
for game in games {
|
||||
let id = game.id;
|
||||
db.games.insert(game.id, game);
|
||||
db.next_id = db.next_id.max(id + 1);
|
||||
db.games.insert(game.id.clone(), game);
|
||||
}
|
||||
db
|
||||
}
|
||||
|
||||
pub fn add_game<S: Into<String>>(
|
||||
&mut self,
|
||||
name: S,
|
||||
description: S,
|
||||
install_archive: S,
|
||||
max_players: u32,
|
||||
version: semver::Version,
|
||||
) -> u64 {
|
||||
let id = self.next_id;
|
||||
self.next_id += 1;
|
||||
let game = Game {
|
||||
id,
|
||||
name: name.into(),
|
||||
description: description.into(),
|
||||
install_archive: install_archive.into(),
|
||||
max_players,
|
||||
version,
|
||||
size: 0,
|
||||
};
|
||||
self.games.insert(id, game);
|
||||
id
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn get_game_by_id(&self, id: u64) -> Option<&Game> {
|
||||
self.games.get(&id)
|
||||
pub fn get_game_by_id<S>(&self, id: S) -> Option<&Game>
|
||||
where
|
||||
S: AsRef<str>,
|
||||
{
|
||||
self.games.get(id.as_ref())
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
@ -132,56 +101,10 @@ impl GameDB {
|
||||
self.games.values().find(|game| game.name == name)
|
||||
}
|
||||
|
||||
pub fn update_game<S: Into<String>>(
|
||||
&mut self,
|
||||
id: u64,
|
||||
name: Option<S>,
|
||||
description: Option<S>,
|
||||
install_archive: Option<S>,
|
||||
) -> bool {
|
||||
if let Some(game) = self.games.get_mut(&id) {
|
||||
if let Some(new_name) = name {
|
||||
game.name = new_name.into();
|
||||
}
|
||||
if let Some(new_description) = description {
|
||||
game.description = new_description.into();
|
||||
}
|
||||
if let Some(archive) = install_archive {
|
||||
game.install_archive = archive.into();
|
||||
}
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
pub fn delete_game(&mut self, id: u64) -> bool {
|
||||
self.games.remove(&id).is_some()
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn all_games(&self) -> Vec<&Game> {
|
||||
self.games.values().collect()
|
||||
}
|
||||
|
||||
pub fn save_to_file(&self, path: &Path) -> eyre::Result<()> {
|
||||
let file = OpenOptions::new()
|
||||
.write(true)
|
||||
.create(true)
|
||||
.truncate(true)
|
||||
.open(path)?;
|
||||
|
||||
let games: Vec<&Game> = self.games.values().collect();
|
||||
serde_json::to_writer(file, &games)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn load_from_file(path: &Path) -> eyre::Result<Self> {
|
||||
let file = File::open(path)?;
|
||||
let games: Vec<Game> = serde_json::from_reader(file)?;
|
||||
let db = GameDB::from(games);
|
||||
Ok(db)
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for GameDB {
|
||||
|
@ -1,2 +1 @@
|
||||
pub mod db;
|
||||
mod serialization;
|
||||
|
@ -1,19 +0,0 @@
|
||||
pub(crate) mod version_serde {
|
||||
use semver::Version;
|
||||
use serde::{self, Deserialize, Deserializer, Serializer};
|
||||
|
||||
pub fn serialize<S>(version: &Version, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: Serializer,
|
||||
{
|
||||
serializer.serialize_str(&version.to_string())
|
||||
}
|
||||
|
||||
pub fn deserialize<'de, D>(deserializer: D) -> Result<Version, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
let s = String::deserialize(deserializer)?;
|
||||
Version::parse(&s).map_err(serde::de::Error::custom)
|
||||
}
|
||||
}
|
@ -6,7 +6,7 @@ use tracing::error;
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub enum Request {
|
||||
ListGames,
|
||||
GetGame { id: u64 },
|
||||
GetGame { id: String },
|
||||
Invalid(Vec<u8>, String),
|
||||
}
|
||||
|
||||
@ -14,7 +14,7 @@ pub enum Request {
|
||||
pub enum Response {
|
||||
Games(Vec<Game>),
|
||||
Game(Game),
|
||||
GameNotFound(u64),
|
||||
GameNotFound(String),
|
||||
InvalidRequest(Vec<u8>, String),
|
||||
EncodingError(String),
|
||||
DecodingError(Vec<u8>, String),
|
||||
|
@ -13,6 +13,7 @@ unwrap_used = "warn"
|
||||
|
||||
[dependencies]
|
||||
# local
|
||||
lanspread-compat = { path = "../lanspread-compat" }
|
||||
lanspread-db = { path = "../lanspread-db" }
|
||||
lanspread-mdns = { path = "../lanspread-mdns" }
|
||||
lanspread-proto = { path = "../lanspread-proto" }
|
||||
|
@ -1,11 +1,14 @@
|
||||
#![allow(clippy::doc_markdown)]
|
||||
|
||||
use std::{
|
||||
net::{IpAddr, SocketAddr},
|
||||
path::{Path, PathBuf},
|
||||
path::PathBuf,
|
||||
sync::Arc,
|
||||
};
|
||||
|
||||
use clap::Parser;
|
||||
use lanspread_db::db::GameDB;
|
||||
use lanspread_compat::eti::{self, EtiGame};
|
||||
use lanspread_db::db::{Game, GameDB};
|
||||
use lanspread_mdns::{
|
||||
DaemonEvent,
|
||||
MdnsAdvertiser,
|
||||
@ -15,18 +18,13 @@ use lanspread_mdns::{
|
||||
use lanspread_proto::{Message as _, Request, Response};
|
||||
use lanspread_utils::maybe_addr;
|
||||
use s2n_quic::Server as QuicServer;
|
||||
use testing::generate_test_db;
|
||||
use tokio::{io::AsyncWriteExt, sync::Mutex};
|
||||
use tracing_subscriber::EnvFilter;
|
||||
|
||||
mod testing;
|
||||
|
||||
static KEY_PEM: &str = include_str!(concat!(env!("CARGO_MANIFEST_DIR"), "/../../key.pem"));
|
||||
static CERT_PEM: &str = include_str!(concat!(env!("CARGO_MANIFEST_DIR"), "/../../cert.pem"));
|
||||
|
||||
pub(crate) struct Server {
|
||||
db_path: PathBuf,
|
||||
}
|
||||
pub(crate) struct Server;
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
struct ServerCtx {
|
||||
@ -40,20 +38,14 @@ struct ConnectionCtx {
|
||||
}
|
||||
|
||||
impl Server {
|
||||
fn new<S: Into<PathBuf>>(db_path: S) -> Self {
|
||||
Server {
|
||||
db_path: db_path.into(),
|
||||
}
|
||||
}
|
||||
|
||||
async fn run(&mut self, addr: SocketAddr) -> eyre::Result<()> {
|
||||
async fn run(addr: SocketAddr, db: GameDB) -> eyre::Result<()> {
|
||||
let mut server = QuicServer::builder()
|
||||
.with_tls((CERT_PEM, KEY_PEM))?
|
||||
.with_io(addr)?
|
||||
.start()?;
|
||||
|
||||
let server_ctx = Arc::new(ServerCtx {
|
||||
handler: RequestHandler::new(&self.db_path)?,
|
||||
handler: RequestHandler::new(db),
|
||||
});
|
||||
|
||||
while let Some(mut connection) = server.accept().await {
|
||||
@ -126,11 +118,10 @@ struct RequestHandler {
|
||||
}
|
||||
|
||||
impl RequestHandler {
|
||||
fn new(db_path: &Path) -> eyre::Result<Self> {
|
||||
let db = GameDB::load_from_file(db_path)?;
|
||||
Ok(RequestHandler {
|
||||
db: Arc::new(Mutex::new(db)),
|
||||
})
|
||||
fn new(games: GameDB) -> RequestHandler {
|
||||
RequestHandler {
|
||||
db: Arc::new(Mutex::new(games)),
|
||||
}
|
||||
}
|
||||
|
||||
async fn handle_request(&self, request: Request) -> Response {
|
||||
@ -141,7 +132,7 @@ impl RequestHandler {
|
||||
}
|
||||
Request::GetGame { id } => {
|
||||
let db = self.db.lock().await;
|
||||
match db.get_game_by_id(id) {
|
||||
match db.get_game_by_id(&id) {
|
||||
Some(game) => Response::Game(game.clone()),
|
||||
None => Response::GameNotFound(id),
|
||||
}
|
||||
@ -158,16 +149,33 @@ impl RequestHandler {
|
||||
}
|
||||
}
|
||||
|
||||
const GAME_DB_PATH: &str = "/home/pfs/shm/game.db";
|
||||
|
||||
#[derive(Debug, Parser)]
|
||||
struct Cli {
|
||||
/// The IP address to bind to.
|
||||
#[clap(long, default_value = "127.0.0.1")]
|
||||
/// IP address to bind to.
|
||||
#[clap(long)]
|
||||
ip: IpAddr,
|
||||
/// The listen port.
|
||||
#[clap(long, default_value = "13337")]
|
||||
/// Listen port.
|
||||
#[clap(long)]
|
||||
port: u16,
|
||||
/// Game database path (SQLite).
|
||||
#[clap(long)]
|
||||
db: PathBuf,
|
||||
}
|
||||
|
||||
fn eti_game_to_game(eti_game: EtiGame) -> Game {
|
||||
#[allow(clippy::cast_possible_truncation)]
|
||||
#[allow(clippy::cast_sign_loss)]
|
||||
Game {
|
||||
id: eti_game.game_id,
|
||||
name: eti_game.game_title,
|
||||
description: eti_game.game_readme_de,
|
||||
release_year: eti_game.game_release,
|
||||
publisher: eti_game.game_publisher,
|
||||
max_players: eti_game.game_maxplayers,
|
||||
version: eti_game.game_version,
|
||||
genre: eti_game.genre_de,
|
||||
size: (eti_game.game_size * 1024.0 * 1024.0 * 1024.0) as u64,
|
||||
}
|
||||
}
|
||||
|
||||
#[tokio::main]
|
||||
@ -178,7 +186,9 @@ async fn main() -> eyre::Result<()> {
|
||||
|
||||
let cli = Cli::parse();
|
||||
|
||||
generate_test_db(GAME_DB_PATH);
|
||||
let eti_games = eti::get_games(&cli.db).await?;
|
||||
let games: Vec<Game> = eti_games.into_iter().map(eti_game_to_game).collect();
|
||||
let game_db = GameDB::from(games);
|
||||
|
||||
let mdns = MdnsAdvertiser::new(
|
||||
LANSPREAD_SERVICE_TYPE,
|
||||
@ -190,7 +200,7 @@ async fn main() -> eyre::Result<()> {
|
||||
while let Ok(event) = mdns.monitor.recv() {
|
||||
tracing::info!("mDNS: {:?}", &event);
|
||||
if let DaemonEvent::Error(e) = event {
|
||||
tracing::info!("Failed: {e}");
|
||||
tracing::error!("mDNS: {e}");
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -198,6 +208,5 @@ async fn main() -> eyre::Result<()> {
|
||||
|
||||
tracing::info!("Server listening on {}:{}", cli.ip, cli.port);
|
||||
|
||||
let mut server = Server::new(GAME_DB_PATH);
|
||||
server.run(SocketAddr::from((cli.ip, cli.port))).await
|
||||
Server::run(SocketAddr::from((cli.ip, cli.port)), game_db).await
|
||||
}
|
||||
|
@ -1,35 +0,0 @@
|
||||
#![allow(clippy::unwrap_used)]
|
||||
|
||||
use std::path::PathBuf;
|
||||
|
||||
use lanspread_db::db::GameDB;
|
||||
|
||||
pub(crate) fn generate_test_db<P: Into<PathBuf>>(db_path: P) {
|
||||
let db_path = db_path.into();
|
||||
|
||||
let mut db = GameDB::new();
|
||||
db.add_game(
|
||||
"Call of Duty 3",
|
||||
"A shooter game in war.",
|
||||
"call_of_duty.tar.zst",
|
||||
64,
|
||||
semver::Version::new(1, 0, 0),
|
||||
);
|
||||
db.add_game(
|
||||
"Counter-Strike Source",
|
||||
"Valve's iconic shooter.",
|
||||
"cstrike.tar.zst",
|
||||
32,
|
||||
semver::Version::new(1, 0, 0),
|
||||
);
|
||||
db.add_game(
|
||||
"Factorio",
|
||||
"Best game of all time, seriously.",
|
||||
"factorio.tar.zst",
|
||||
128,
|
||||
semver::Version::new(1, 0, 0),
|
||||
);
|
||||
|
||||
db.update_game(1, Some("Call of Duty 4"), None, None);
|
||||
db.save_to_file(&db_path).unwrap();
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
use std::{net::SocketAddr, process::Command};
|
||||
use std::net::SocketAddr;
|
||||
|
||||
use lanspread_client::{ClientCommand, ClientEvent};
|
||||
use lanspread_mdns::{discover_service, LANSPREAD_INSTANCE_NAME, LANSPREAD_SERVICE_TYPE};
|
||||
@ -22,24 +22,26 @@ fn request_games(state: tauri::State<LanSpreadState>) {
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
fn run_game_backend(id: u64, state: tauri::State<LanSpreadState>) -> String {
|
||||
fn run_game_backend(id: String, state: tauri::State<LanSpreadState>) -> String {
|
||||
log::error!("Running game with id {id}");
|
||||
|
||||
let result = Command::new(r#"C:\Users\ddidderr\scoop\apps\mpv\0.39.0\mpv.exe"#).spawn();
|
||||
// let result = Command::new(r#"C:\Users\ddidderr\scoop\apps\mpv\0.39.0\mpv.exe"#).spawn();
|
||||
|
||||
if let Err(e) = state.inner().client_ctrl.send(ClientCommand::GetGame(id)) {
|
||||
log::error!("Failed to send message to client: {e:?}");
|
||||
}
|
||||
|
||||
if result.is_ok() {
|
||||
"Ok".to_string()
|
||||
} else {
|
||||
"Failed to run game".to_string()
|
||||
}
|
||||
"TODO".to_string()
|
||||
|
||||
// if result.is_ok() {
|
||||
// "Ok".to_string()
|
||||
// } else {
|
||||
// "Failed to run game".to_string()
|
||||
// }
|
||||
}
|
||||
|
||||
async fn find_server(app: AppHandle) {
|
||||
log::error!("Looking for server...");
|
||||
log::info!("Looking for server...");
|
||||
|
||||
loop {
|
||||
match discover_service(LANSPREAD_SERVICE_TYPE, Some(LANSPREAD_INSTANCE_NAME)) {
|
||||
@ -73,7 +75,7 @@ pub fn run() {
|
||||
tauri_plugin_log::TargetKind::Stdout,
|
||||
))
|
||||
.level(log::LevelFilter::Info)
|
||||
.level_for("lanspread_client", log::LevelFilter::Debug)
|
||||
.level_for("lanspread_client", log::LevelFilter::Trace)
|
||||
.level_for("lanspread_tauri_leptos_lib", log::LevelFilter::Debug)
|
||||
.level_for("mdns_sd::service_daemon", log::LevelFilter::Off);
|
||||
|
||||
@ -106,7 +108,7 @@ pub fn run() {
|
||||
let app_handle = app.handle().clone();
|
||||
tauri::async_runtime::spawn(async move {
|
||||
while let Some(event) = rx_client_event.recv().await {
|
||||
log::debug!("Received client event: {event:?}");
|
||||
log::debug!("Received client event");
|
||||
|
||||
match event {
|
||||
ClientEvent::ListGames(games) => {
|
||||
|
@ -16,7 +16,7 @@ extern "C" {
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
struct RunGameArgs {
|
||||
id: u64,
|
||||
id: String,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
@ -59,14 +59,14 @@ pub fn App() -> impl IntoView {
|
||||
});
|
||||
|
||||
// Call list_games on component mount
|
||||
create_effect(move |_| {
|
||||
spawn_local(async move {
|
||||
let args = serde_wasm_bindgen::to_value(&()).unwrap();
|
||||
invoke("request_games", args).await;
|
||||
});
|
||||
});
|
||||
// create_effect(move |_| {
|
||||
// spawn_local(async move {
|
||||
// let args = serde_wasm_bindgen::to_value(&()).unwrap();
|
||||
// invoke("request_games", args).await;
|
||||
// });
|
||||
// });
|
||||
|
||||
let run_game = move |id: u64| {
|
||||
let run_game = move |id: String| {
|
||||
log_1(&JsValue::from_str(format!("id={id}").as_str()));
|
||||
spawn_local(async move {
|
||||
let args = serde_wasm_bindgen::to_value(&RunGameArgs { id }).unwrap();
|
||||
@ -87,7 +87,7 @@ pub fn App() -> impl IntoView {
|
||||
{move || game_items.get().into_iter()
|
||||
.map(|item|
|
||||
view! {
|
||||
<div class="item" on:click=move |_| run_game(item.id)>
|
||||
<div class="item" on:click=move |_| run_game(item.id.clone())>
|
||||
<img src="https://via.placeholder.com/200x150" alt="Item Image" />
|
||||
<div class="item-name">{ &item.name }</div>
|
||||
<div class="description">
|
||||
|
Reference in New Issue
Block a user