progressing on tic-tac-toe-gui
This commit is contained in:
parent
0bd436cf45
commit
156cdfc295
|
@ -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"] }
|
||||||
|
|
||||||
|
|
|
@ -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(())
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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;
|
||||||
|
|
Loading…
Reference in New Issue