progressing on tic-tac-toe-gui

This commit is contained in:
Ivan Folgueira Bande 2024-11-14 01:15:28 +07:00
parent 0bd436cf45
commit 156cdfc295
No known key found for this signature in database
GPG Key ID: 3C117481F89E24A7
4 changed files with 92 additions and 101 deletions

View File

@ -13,4 +13,5 @@ tokio = { version = "1", features = ["full"] }
tokio-util = "0.6" # for utility functions if needed tokio-util = "0.6" # for utility functions if needed
egui = "0.22" egui = "0.22"
eframe = "0.22" eframe = "0.22"
secp256k1 = { version = "0.26", features = ["rand", "recovery", "serde"] }

View File

@ -1,10 +1,14 @@
use eframe::egui; use eframe::egui;
use secp256k1::SecretKey;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use std::cell::OnceCell; use std::cell::OnceCell;
use std::str::from_utf8; use std::str::from_utf8;
use std::sync::Arc; use std::sync::Arc;
use std::sync::Mutex; use std::sync::Mutex;
use std::str::FromStr;
use std::time::SystemTime; use std::time::SystemTime;
use std::time::{Duration, Instant};
use tokio::sync::mpsc; use tokio::sync::mpsc;
use waku::{ use waku::{
waku_new, Encoding, Event, Initialized, LibwakuResponse, Multiaddr, Running, WakuContentTopic, waku_new, Encoding, Event, Initialized, LibwakuResponse, Multiaddr, Running, WakuContentTopic,
@ -33,28 +37,23 @@ struct MoveMessage {
struct TicTacToeApp { struct TicTacToeApp {
game_state: Arc<Mutex<GameState>>, game_state: Arc<Mutex<GameState>>,
val: Arc<Mutex<String>>,
waku: WakuNodeHandle, waku: WakuNodeHandle,
game_topic: &'static str, game_topic: &'static str,
tx: Arc<Mutex<mpsc::Sender<String>>>, // Sender to send `msg` to main thread tx: mpsc::Sender<String>, // Sender to send `msg` to main thread
} }
impl TicTacToeApp { impl TicTacToeApp {
fn new( fn new(
waku: WakuNodeHandle, waku: WakuNodeHandle,
game_topic: &'static str, game_topic: &'static str,
tx: Arc<Mutex<mpsc::Sender<String>>>, game_state: Arc<Mutex<GameState>>,
tx: mpsc::Sender<String>,
) -> Self { ) -> Self {
Self { Self {
game_state: Arc::new(Mutex::new(GameState { game_state,
board: [[None; 3]; 3],
current_turn: Player::X,
moves_left: 9,
})),
val: Arc::new(Mutex::new("".to_string())),
waku, waku,
game_topic, game_topic,
tx: tx, tx,
} }
} }
@ -62,94 +61,24 @@ impl TicTacToeApp {
// Start the waku node // Start the waku node
self.waku.start().expect("waku should start"); self.waku.start().expect("waku should start");
// let default_pubsub_topic = Arc::new(Mutex::new("".to_string()));
// let shared_data_clone = Arc::clone(&default_pubsub_topic);
// // Establish a closure that handles the incoming messages
// self.waku.ctx.waku_set_event_callback(|response| {
// let mut data = shared_data_clone.lock().unwrap();
// *data = "Updated from another thread".to_string(); // Write access
// println!("funciona ?");
// let mut cloned = Arc::clone(&self.val);
let tx_clone = self.tx.clone(); let tx_clone = self.tx.clone();
let my_closure = move |response| { let my_closure = move |response| {
// if let Ok(mut tx) = tx_clone.try_lock() {
// // Lock succeeded, proceed to send the message
// if tx.try_send(msg.to_string()).is_err() {
// eprintln!("Failed to send message to async task");
// }
// } else {
// eprintln!("Failed to acquire lock on tx_clone");
// }
// if let Ok(mut aa) = cloned.try_lock() {
// }
// match cloned.lock() {
// Ok(mut data) => {
// *data = "Modified Value".to_string();
// println!("Thread updated value to: {}", data);
// },
// Err(e) => {
// eprintln!("Failed to lock the mutex in thread: {}", e);
// }
// }
if let LibwakuResponse::Success(v) = response { if let LibwakuResponse::Success(v) = response {
let event: Event = let event: Event =
serde_json::from_str(v.unwrap().as_str()).expect("Parsing event to succeed"); serde_json::from_str(v.unwrap().as_str()).expect("Parsing event to succeed");
// let mut game_state = self.game_state.lock().unwrap();
match event { match event {
Event::WakuMessage(evt) => { Event::WakuMessage(evt) => {
// println!("WakuMessage event received: {:?}", evt.waku_message); // println!("WakuMessage event received: {:?}", evt.waku_message);
let message = evt.waku_message; let message = evt.waku_message;
let payload = message.payload.to_vec().clone(); let payload = message.payload.to_vec();
match from_utf8(&payload) { match from_utf8(&payload) {
Ok(msg) => { Ok(msg) => {
println!("::::::::::::::::::::::::::::::::::::::::::::::::::::"); // Lock succeeded, proceed to send the message
println!("Message Received: {}", msg); if tx_clone.blocking_send(msg.to_string()).is_err() {
println!("::::::::::::::::::::::::::::::::::::::::::::::::::::"); eprintln!("Failed to send message to async task");
// Send the message to the main thread
if let Ok(mut tx) = tx_clone.try_lock() {
// Lock succeeded, proceed to send the message
if tx.blocking_send(msg.to_string()).is_err() {
eprintln!("Failed to send message to async task");
} else {
eprintln!("Sent!!!!");
}
} else {
eprintln!("Failed to acquire lock on tx_clone");
} }
// Deserialize the JSON into the GameState struct
// Lock the game_state and update it
// match serde_json::from_str::<GameState>(msg) {
// Ok(parsed_value) => {
// // Handle the parsed value here
// // self.game_state = parsed_value;
// println!("Parsed correctly");
// }
// Err(e) => {
// eprintln!("Failed to parse JSON: {}", e);
// // Handle the error as needed, such as retrying, defaulting, etc.
// }
// }
// *game_state = serde_json::from_str(msg).expect("Failed to deserialize JSON");
// let tx_inner = tx_cloned.clone();
// let msg_inner = msg.to_string();
// tokio::spawn(async move {
// println!("do nothing");
// if tx_inner.send(msg_inner.to_string()).await.is_err() {
// eprintln!("Failed to send message");
// }
// });
} }
Err(e) => { Err(e) => {
eprintln!("Failed to decode payload as UTF-8: {}", e); eprintln!("Failed to decode payload as UTF-8: {}", e);
@ -170,12 +99,14 @@ impl TicTacToeApp {
self.waku.relay_subscribe(&self.game_topic.to_string()).expect("waku should subscribe"); self.waku.relay_subscribe(&self.game_topic.to_string()).expect("waku should subscribe");
// Connect to hard-coded node // Connect to hard-coded node
let target_node_multi_addr = // let target_node_multi_addr =
"/ip4/24.144.78.119/tcp/30303/p2p/16Uiu2HAm3xVDaz6SRJ6kErwC21zBJEZjavVXg7VSkoWzaV1aMA3F" // "/ip4/159.223.242.94/tcp/30303/p2p/16Uiu2HAmAUdrQ3uwzuE4Gy4D56hX6uLKEeerJAnhKEHZ3DxF1EfT"
.parse::<Multiaddr>().expect("parse multiaddress"); // // "/dns4/store-01.do-ams3.status.prod.status.im/tcp/30303/p2p/16Uiu2HAmAUdrQ3uwzuE4Gy4D56hX6uLKEeerJAnhKEHZ3DxF1EfT"
// // "/ip4/24.144.78.119/tcp/30303/p2p/16Uiu2HAm3xVDaz6SRJ6kErwC21zBJEZjavVXg7VSkoWzaV1aMA3F"
// .parse::<Multiaddr>().expect("parse multiaddress");
self.waku.connect(&target_node_multi_addr, None) // self.waku.connect(&target_node_multi_addr, None)
.expect("waku should connect to other node"); // .expect("waku should connect to other node");
} }
fn send_game_state(&self, game_state: &GameState) { fn send_game_state(&self, game_state: &GameState) {
@ -263,6 +194,10 @@ impl TicTacToeApp {
impl eframe::App for TicTacToeApp { impl eframe::App for TicTacToeApp {
fn update(&mut self, ctx: &egui::Context, _frame: &mut eframe::Frame) { fn update(&mut self, ctx: &egui::Context, _frame: &mut eframe::Frame) {
// Request a repaint every second
ctx.request_repaint_after(Duration::from_secs(1));
egui::CentralPanel::default().show(ctx, |ui| { egui::CentralPanel::default().show(ctx, |ui| {
ui.heading("Tic-Tac-Toe"); ui.heading("Tic-Tac-Toe");
@ -334,20 +269,61 @@ impl eframe::App for TicTacToeApp {
async fn main() -> eframe::Result<()> { async fn main() -> eframe::Result<()> {
let (tx, mut rx) = mpsc::channel::<String>(3200); // Channel to communicate between threads let (tx, mut rx) = mpsc::channel::<String>(3200); // Channel to communicate between threads
let game_topic = "/waku/2/rs/16/32";
// Create a Waku instance // Create a Waku instance
let waku = waku_new(Some(WakuNodeConfig { let waku = waku_new(Some(WakuNodeConfig {
port: Some(60010), port: Some(60010),
cluster_id: Some(16), cluster_id: Some(16),
shards: vec![1, 32, 64, 128, 256],
// node_key: Some(SecretKey::from_str("2fc0515879e52b7b73297cfd6ab3abf7c344ef84b7a90ff6f4cc19e05a198027").unwrap()),
max_message_size: Some("1024KiB".to_string()),
relay_topics: vec![game_topic.to_string()],
log_level: Some("DEBUG"), // Supported: TRACE, DEBUG, INFO, NOTICE, WARN, ERROR or FATAL log_level: Some("DEBUG"), // Supported: TRACE, DEBUG, INFO, NOTICE, WARN, ERROR or FATAL
keep_alive: Some(true),
// Discovery
dns_discovery: Some(true),
dns_discovery_url: Some("enrtree://AMOJVZX4V6EXP7NTJPMAYJYST2QP6AJXYW76IU6VGJS7UVSNDYZG4@boot.prod.status.nodes.status.im"),
discv5_discovery: Some(true),
discv5_udp_port: Some(9000),
discv5_enr_auto_update: Some(false),
..Default::default() ..Default::default()
})) }))
.expect("should instantiate"); .expect("should instantiate");
// Initialize Waku // Initialize Waku
let game_topic = "/waku/2/rs/16/64";
let mut app = TicTacToeApp::new(waku, game_topic, Arc::new(Mutex::new(tx))); let game_state = GameState {
board: [[None; 3]; 3],
current_turn: Player::X,
moves_left: 9,
};
let shared_state = Arc::new(Mutex::new(game_state));
let clone = shared_state.clone();
let mut app = TicTacToeApp::new(waku, game_topic, clone, tx);
app.start(); app.start();
let clone = shared_state.clone();
// Listen for messages in the main thread
tokio::spawn(async move {
while let Some(msg) = rx.recv().await {
println!("MSG received: {}", msg);
// Handle the received message, e.g., update the UI or game state
if let Ok(parsed_value) = serde_json::from_str::<GameState>(&msg)
{
if let Ok(mut unclocked_game_state) = clone.lock(){
*unclocked_game_state = parsed_value;
}
}
else {
eprintln!("Failed to parse JSON: ");
}
}
});
eframe::run_native( eframe::run_native(
"Tic-Tac-Toe Multiplayer via Waku", "Tic-Tac-Toe Multiplayer via Waku",
eframe::NativeOptions { eframe::NativeOptions {
@ -357,13 +333,6 @@ async fn main() -> eframe::Result<()> {
Box::new(|_cc| Box::new(app)), Box::new(|_cc| Box::new(app)),
)?; )?;
// Listen for messages in the main thread
tokio::spawn(async move {
while let Some(msg) = rx.recv().await {
println!("Main thread received: {}", msg);
// Handle the received message, e.g., update the UI or game state
}
});
Ok(()) Ok(())
} }

View File

@ -23,16 +23,37 @@ pub struct WakuNodeConfig {
/// Cluster id that the node is running in /// Cluster id that the node is running in
#[default(Some(0))] #[default(Some(0))]
pub cluster_id: Option<usize>, pub cluster_id: Option<usize>,
/// Enable relay protocol. Default `true`
/// Relay protocol
#[default(Some(true))] #[default(Some(true))]
pub relay: Option<bool>, pub relay: Option<bool>,
pub relay_topics: Vec<String>, pub relay_topics: Vec<String>,
pub shards: Vec<usize>,
#[serde(skip_serializing_if = "Option::is_none")]
pub max_message_size: Option<String>,
/// RLN configuration /// RLN configuration
#[serde(skip_serializing_if = "Option::is_none")] #[serde(skip_serializing_if = "Option::is_none")]
pub rln_relay: Option<RLNConfig>, pub rln_relay: Option<RLNConfig>,
// Discovery
#[default(Some(false))]
pub dns_discovery: Option<bool>,
#[serde(skip_serializing_if = "Option::is_none")]
pub dns_discovery_url: Option<&'static str>,
#[default(Some(false))]
pub discv5_discovery: Option<bool>,
#[serde(skip_serializing_if = "Option::is_none")]
pub discv5_udp_port: Option<usize>,
#[default(Some(false))]
pub discv5_enr_auto_update: Option<bool>,
// other settings // other settings
#[serde(skip_serializing_if = "Option::is_none")] #[serde(skip_serializing_if = "Option::is_none")]
pub log_level: Option<&'static str>, pub log_level: Option<&'static str>,
#[serde(skip_serializing_if = "Option::is_none")]
pub keep_alive: Option<bool>,
} }
/// RLN Relay configuration /// RLN Relay configuration

View File

@ -5,14 +5,14 @@
//! When an event is emitted, this callback will be triggered receiving an [`Event`] //! When an event is emitted, this callback will be triggered receiving an [`Event`]
// std // std
use std::ffi::{c_char, c_int, c_void, CStr}; use std::ffi::c_void;
// crates // crates
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
// internal // internal
use crate::general::WakuMessage; use crate::general::WakuMessage;
use std::{slice, str}; use std::{slice, str};
use crate::utils::{get_trampoline, LibwakuResponse}; use crate::utils::LibwakuResponse;
use crate::MessageHash; use crate::MessageHash;
use std::ops::Deref; use std::ops::Deref;
use std::sync::Mutex; use std::sync::Mutex;