From 73b59a8254825b719656a2c239a4899308de754f Mon Sep 17 00:00:00 2001 From: Condorra Date: Fri, 1 Nov 2024 13:55:44 +1100 Subject: [PATCH] Connect to same host by default - and show message if closed. --- src/lua_engine.rs | 2 + src/lua_engine/muds.rs | 102 ++++++++++++++++++++++++++++++++++++++++- src/main.rs | 8 +++- src/websocket.rs | 11 ++--- 4 files changed, 114 insertions(+), 9 deletions(-) diff --git a/src/lua_engine.rs b/src/lua_engine.rs index aea8148..2d09f97 100644 --- a/src/lua_engine.rs +++ b/src/lua_engine.rs @@ -226,6 +226,7 @@ pub fn install_lua_globals( }; } register_handler!(mudoutput); + register_handler!(mudclose); let classes_table = Table::new(&ctx); ctx.set_global("classes", classes_table); @@ -279,6 +280,7 @@ pub fn install_lua_globals( register_class_function!(mud_class_table, mudoutput_dont); register_class_function!(mud_class_table, mudoutput_subnegotiation); register_class_function!(mud_class_table, mudinput_line); + register_class_function!(mud_class_table, "closed", mudclass_closed); register_stateless_class_function!(mud_class_table, "new", new_mud); macro_rules! register_class_nop { diff --git a/src/lua_engine/muds.rs b/src/lua_engine/muds.rs index e6950ed..ef3a374 100644 --- a/src/lua_engine/muds.rs +++ b/src/lua_engine/muds.rs @@ -5,11 +5,12 @@ use piccolo::{ SequenceReturn, StashedTable, StashedUserData, StashedValue, Table, UserData, Value, }; use wasm_bindgen::JsValue; -use web_sys::console; +use web_sys::{console, window}; use yew::UseStateSetter; use crate::{ command_handler::execute_queue, + echo_to_term_frame, id_intern::{intern_id, unintern_id}, logging::{start_deleting_logs, start_downloading_logs, start_listing_logs}, match_table::{create_match_table, match_table_add, match_table_remove}, @@ -68,6 +69,27 @@ pub fn handle_websocket_output( .map_err(|err| format!("{}", err)) } +pub(super) fn mudclose<'gc>(ctx: Context<'gc>, _global_memo: &GlobalMemoCell) -> Callback<'gc> { + Callback::from_fn(&ctx, move |ctx, _ex, mut stack| { + let mud: Value<'gc> = stack + .pop_front() + .ok_or_else(|| anyhow::Error::msg("Missing argument to mudclose"))?; + let conntab: Table<'gc> = Table::from_value( + ctx, + Table::from_value(ctx, ctx.get_global("muds")?)?.get_value(ctx, mud), + )?; + let seq = piccolo::async_sequence(&ctx, |locals, mut seq| { + let conntab = locals.stash(&ctx, conntab); + async move { + call_checking_metatable::(&mut seq, conntab.clone(), "closed", &[]) + .await?; + Ok(piccolo::SequenceReturn::Return) + } + }); + Ok(piccolo::CallbackReturn::Sequence(seq)) + }) +} + pub fn handle_websocket_output_log_err( socket: &WebSocketId, globals: &GlobalMemoCell, @@ -107,7 +129,7 @@ pub fn handle_websocket_close_log_err(socket: &WebSocketId, globals: &GlobalMemo match handle_websocket_close(socket, &mut globals.lua_engine.borrow_mut()) { Ok(()) => {} Err(e) => console::log_2( - &JsValue::from_str("An error occurred calling the WebSocket input handler"), + &JsValue::from_str("An error occurred calling the WebSocket close handler"), &JsValue::from_str(&e), ), } @@ -484,6 +506,31 @@ pub(super) fn mudinput_line<'gc>( }) } +pub(super) fn mudclass_closed<'gc>( + ctx: Context<'gc>, + global_memo: &GlobalMemoCell, +) -> Callback<'gc> { + let global_memo = global_memo.clone(); + Callback::from_fn(&ctx, move |ctx, _ex, mut stack| { + let mud: Table = stack.consume(ctx)?; + let frameroutes: Table = mud.get(ctx, "frameroutes")?; + let default_frame: Value = frameroutes + .iter() + .map(|(_k, v)| Ok::(Table::from_value(ctx, v)?)) + .next() + .unwrap_or_else(|| Ok(ctx.get_global::("frames")?.get(ctx, 1_i64)?))? + .get(ctx, "frame")?; + let default_frame: FrameId = try_unwrap_frame(ctx, &default_frame)?; + echo_to_term_frame( + &global_memo, + &default_frame, + &format!("Connection to {} lost.\r\n", name_mud(ctx, &mud)), + ) + .map_err(anyhow::Error::msg)?; + Ok(CallbackReturn::Return) + }) +} + pub(super) fn new_mud<'gc>(ctx: Context<'gc>) -> Callback<'gc> { Callback::from_fn(&ctx, move |ctx, _ex, mut stack| { let mud: Table = Table::from_value( @@ -633,6 +680,33 @@ pub(super) fn mud_untrigger(ctx: Context<'_>) -> Callback<'_> { }) } +fn name_mud<'gc>(ctx: Context<'gc>, mud: &Table<'gc>) -> String { + fn name_mud_internal<'gc>(ctx: Context<'gc>, mud: &Table<'gc>) -> anyhow::Result { + let socket: Value<'gc> = mud.get(ctx, "socket")?; + let socket: &'gc WebSocketId = + UserData::from_value(ctx, socket)?.downcast::]>()?; + for (k, v) in ctx.get_global::
("muds")?.iter() { + if let Ok(v) = UserData::from_value(ctx, v) + .map_err(anyhow::Error::from) + .and_then(|ud| { + ud.downcast::]>() + .map_err(anyhow::Error::from) + }) + { + if v.0 == socket.0 { + return Ok(piccolo::String::from_value(ctx, k)?.to_str()?.to_owned()); + } + } + } + Err(anyhow::Error::msg("No match")) + } + + match name_mud_internal(ctx, mud) { + Ok(name) => name, + Err(_) => "unknown MUD".to_owned(), + } +} + pub(super) fn mud_log<'gc>( ctx: Context<'gc>, global_memo: &GlobalMemoCell, @@ -795,3 +869,27 @@ pub(super) fn cmd_download_logs<'gc>( Ok(CallbackReturn::Return) }) } + +pub fn connect_default_mud(global_memo: &GlobalMemoCell) -> anyhow::Result<()> { + if let Some(window) = window() { + if let Ok(host) = window.location().host() { + let mut engine = global_memo.lua_engine.borrow_mut(); + let engine: &mut LuaState = &mut engine; + engine.try_set_current_frame(&FrameId(1))?; + engine.interp.try_enter(|ctx| { + let connect_function: Function = ctx + .get_global::
("commands")? + .get(ctx, "connect_mud")?; + ctx.fetch(&engine.exec).restart( + ctx, + connect_function, + ("-trust", "default", format!("wss://{}/ws", &host)), + ); + Ok(()) + })?; + engine.interp.execute::<()>(&engine.exec)?; + } + } + + Ok(()) +} diff --git a/src/main.rs b/src/main.rs index 3f571cf..3d1683a 100644 --- a/src/main.rs +++ b/src/main.rs @@ -24,7 +24,7 @@ pub mod timer_host; pub mod websocket; use crate::editor_view::try_run_script; use crate::frame_view::*; -use crate::lua_engine::{install_lua_globals, LuaState}; +use crate::lua_engine::{install_lua_globals, muds::connect_default_mud, LuaState}; use crate::split_panel::*; use crate::websocket::RegisteredWebSockets; @@ -90,6 +90,12 @@ fn app() -> Html { console::log_1(&format!("Error running init.lua: {}", e).into()); } } + match connect_default_mud(&global_memo) { + Ok(_) => {} + Err(e) => { + console::log_1(&format!("Error connecting to default MUD: {}", e).into()); + } + } }); html! { diff --git a/src/websocket.rs b/src/websocket.rs index ad8334d..eaf7306 100644 --- a/src/websocket.rs +++ b/src/websocket.rs @@ -117,6 +117,8 @@ pub fn connect_websocket( move || match close_globals.ws_registry.borrow_mut().get_mut(&close_id) { None => {} Some(closed_socket) => { + closed_socket.connection.set_onclose(None); + closed_socket.connection.set_onerror(None); closed_socket.closed = true; closed_socket.retained_closures = None; handle_websocket_close_log_err(&close_id, &close_globals); @@ -125,14 +127,11 @@ pub fn connect_websocket( ); data.connection - .add_event_listener_with_callback("message", data_closure.as_ref().unchecked_ref()) - .expect("Couldn't set message handler on WebSocket"); + .set_onmessage(Some(data_closure.as_ref().unchecked_ref())); data.connection - .add_event_listener_with_callback("close", close_closure.as_ref().unchecked_ref()) - .expect("Couldn't set close handler on WebSocket"); + .set_onclose(Some(close_closure.as_ref().unchecked_ref())); data.connection - .add_event_listener_with_callback("error", close_closure.as_ref().unchecked_ref()) - .expect("Couldn't set error handler on WebSocket"); + .set_onerror(Some(close_closure.as_ref().unchecked_ref())); data.retained_closures = Some((data_closure, close_closure)); sockets.insert(new_id.clone(), data); Ok(new_id)