Implement mudinput (sending to MUD from terminal)
This commit is contained in:
		
							parent
							
								
									ff0411b040
								
							
						
					
					
						commit
						8816d76c53
					
				@ -1,8 +1,7 @@
 | 
				
			|||||||
use itertools::join;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
use crate::{
 | 
					use crate::{
 | 
				
			||||||
    echo_to_term_frame, lua_engine::LuaState, parsing::parse_commands, GlobalMemoCell, TermFrame,
 | 
					    echo_to_term_frame, lua_engine::LuaState, parsing::parse_commands, GlobalMemoCell, TermFrame,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					use itertools::{join, Itertools};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pub fn debrace(inp: &str) -> &str {
 | 
					pub fn debrace(inp: &str) -> &str {
 | 
				
			||||||
    let v = inp.trim();
 | 
					    let v = inp.trim();
 | 
				
			||||||
@ -52,6 +51,17 @@ fn reentrant_command_handler(
 | 
				
			|||||||
                            }
 | 
					                            }
 | 
				
			||||||
                        }
 | 
					                        }
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
 | 
					                } else {
 | 
				
			||||||
 | 
					                    // A normal command. Try dispatching it to the frame object in Lua...
 | 
				
			||||||
 | 
					                    match lua_state
 | 
				
			||||||
 | 
					                        .dispatch_normal_command(term_frame, &command.arguments.iter().join(" "))
 | 
				
			||||||
 | 
					                    {
 | 
				
			||||||
 | 
					                        Ok(()) => (),
 | 
				
			||||||
 | 
					                        Err(msg) => {
 | 
				
			||||||
 | 
					                            echo_to_term_frame(globals, term_frame, &format!("{}\r\n", msg))
 | 
				
			||||||
 | 
					                                .unwrap_or(())
 | 
				
			||||||
 | 
					                        }
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
				
			|||||||
@ -90,6 +90,30 @@ impl LuaState {
 | 
				
			|||||||
            .execute::<()>(&self.exec)
 | 
					            .execute::<()>(&self.exec)
 | 
				
			||||||
            .map_err(|err| format!("{}", err))
 | 
					            .map_err(|err| format!("{}", err))
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    pub(crate) fn dispatch_normal_command(
 | 
				
			||||||
 | 
					        &mut self,
 | 
				
			||||||
 | 
					        frame: &TermFrame,
 | 
				
			||||||
 | 
					        command: &str,
 | 
				
			||||||
 | 
					    ) -> anyhow::Result<()> {
 | 
				
			||||||
 | 
					        self.interp.try_enter(|ctx| {
 | 
				
			||||||
 | 
					            let frames: Table = ctx.get_global("frames")?;
 | 
				
			||||||
 | 
					            let frame_tab: Value = frames.get(ctx, frame.0 as i64)?;
 | 
				
			||||||
 | 
					            if frame_tab.is_nil() {
 | 
				
			||||||
 | 
					                Err(anyhow::Error::msg(
 | 
				
			||||||
 | 
					                    "Dispatching command to frame missing in Lua frames.",
 | 
				
			||||||
 | 
					                ))?;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            ctx.fetch(&self.exec).restart(
 | 
				
			||||||
 | 
					                ctx,
 | 
				
			||||||
 | 
					                Function::Callback(send_command_to_frame(ctx)),
 | 
				
			||||||
 | 
					                (frame_tab, ctx.intern(command.as_bytes())),
 | 
				
			||||||
 | 
					            );
 | 
				
			||||||
 | 
					            Ok(())
 | 
				
			||||||
 | 
					        })?;
 | 
				
			||||||
 | 
					        self.interp.execute(&self.exec)?;
 | 
				
			||||||
 | 
					        Ok(())
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pub fn install_lua_globals(
 | 
					pub fn install_lua_globals(
 | 
				
			||||||
@ -129,6 +153,8 @@ pub fn install_lua_globals(
 | 
				
			|||||||
            ctx.set_global("info", info_table);
 | 
					            ctx.set_global("info", info_table);
 | 
				
			||||||
            let muds_table = Table::new(&ctx);
 | 
					            let muds_table = Table::new(&ctx);
 | 
				
			||||||
            ctx.set_global("muds", muds_table);
 | 
					            ctx.set_global("muds", muds_table);
 | 
				
			||||||
 | 
					            let frames_table = Table::new(&ctx);
 | 
				
			||||||
 | 
					            ctx.set_global("frames", frames_table);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            let handlers_table = Table::new(&ctx);
 | 
					            let handlers_table = Table::new(&ctx);
 | 
				
			||||||
            ctx.set_global("handlers", handlers_table);
 | 
					            ctx.set_global("handlers", handlers_table);
 | 
				
			||||||
@ -180,6 +206,7 @@ pub fn install_lua_globals(
 | 
				
			|||||||
            register_class_function!(mud_class_table, mudoutput_do);
 | 
					            register_class_function!(mud_class_table, mudoutput_do);
 | 
				
			||||||
            register_class_function!(mud_class_table, mudoutput_dont);
 | 
					            register_class_function!(mud_class_table, mudoutput_dont);
 | 
				
			||||||
            register_class_function!(mud_class_table, mudoutput_subnegotiation);
 | 
					            register_class_function!(mud_class_table, mudoutput_subnegotiation);
 | 
				
			||||||
 | 
					            register_class_function!(mud_class_table, mudinput_line);
 | 
				
			||||||
            register_class_function!(mud_class_table, "new", new_mud);
 | 
					            register_class_function!(mud_class_table, "new", new_mud);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            macro_rules! register_class_nop {
 | 
					            macro_rules! register_class_nop {
 | 
				
			||||||
@ -200,6 +227,12 @@ pub fn install_lua_globals(
 | 
				
			|||||||
            register_class_nop!(mud_class_table, mudoutput_abort_output);
 | 
					            register_class_nop!(mud_class_table, mudoutput_abort_output);
 | 
				
			||||||
            register_class_nop!(mud_class_table, mudoutput_areyouthere);
 | 
					            register_class_nop!(mud_class_table, mudoutput_areyouthere);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            let frame_class_table = Table::new(&ctx);
 | 
				
			||||||
 | 
					            classes_table.set(ctx, "frame", frame_class_table)?;
 | 
				
			||||||
 | 
					            frame_class_table.set(ctx, MetaMethod::Index, frame_class_table)?;
 | 
				
			||||||
 | 
					            register_class_function!(frame_class_table, "new", new_frame);
 | 
				
			||||||
 | 
					            register_class_function!(frame_class_table, "input", frame_input);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            let frameroute_class_table = Table::new(&ctx);
 | 
					            let frameroute_class_table = Table::new(&ctx);
 | 
				
			||||||
            classes_table.set(ctx, "frameroute", frameroute_class_table)?;
 | 
					            classes_table.set(ctx, "frameroute", frameroute_class_table)?;
 | 
				
			||||||
            frameroute_class_table.set(ctx, MetaMethod::Index, frameroute_class_table)?;
 | 
					            frameroute_class_table.set(ctx, MetaMethod::Index, frameroute_class_table)?;
 | 
				
			||||||
@ -210,9 +243,26 @@ pub fn install_lua_globals(
 | 
				
			|||||||
        })
 | 
					        })
 | 
				
			||||||
        .map_err(|e| e.to_string())?;
 | 
					        .map_err(|e| e.to_string())?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    lua_global_initialisation(global_memo)?;
 | 
				
			||||||
    Ok(())
 | 
					    Ok(())
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					fn lua_global_initialisation(global_memo: &GlobalMemoCell) -> Result<(), String> {
 | 
				
			||||||
 | 
					    let mut lua_engine = global_memo.lua_engine.borrow_mut();
 | 
				
			||||||
 | 
					    let lua_engine_ref: &mut LuaState = &mut lua_engine;
 | 
				
			||||||
 | 
					    lua_engine_ref.interp.enter(|ctx| {
 | 
				
			||||||
 | 
					        ctx.fetch(&lua_engine_ref.exec).restart(
 | 
				
			||||||
 | 
					            ctx,
 | 
				
			||||||
 | 
					            Function::Callback(ensure_frame_instance(ctx, &TermFrame(1))),
 | 
				
			||||||
 | 
					            (),
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					    lua_engine_ref
 | 
				
			||||||
 | 
					        .interp
 | 
				
			||||||
 | 
					        .execute(&lua_engine_ref.exec)
 | 
				
			||||||
 | 
					        .map_err(|e| e.to_string())
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pub fn lua_nop(ctx: Context<'_>) -> Callback<'_> {
 | 
					pub fn lua_nop(ctx: Context<'_>) -> Callback<'_> {
 | 
				
			||||||
    Callback::from_fn(&ctx, |_ctx, _ex, _stack| {
 | 
					    Callback::from_fn(&ctx, |_ctx, _ex, _stack| {
 | 
				
			||||||
        Ok(piccolo::CallbackReturn::Return)
 | 
					        Ok(piccolo::CallbackReturn::Return)
 | 
				
			||||||
 | 
				
			|||||||
@ -1,14 +1,17 @@
 | 
				
			|||||||
use crate::{
 | 
					use crate::{
 | 
				
			||||||
    command_handler::debrace, echo_to_term_frame, GlobalLayoutCell, GlobalLayoutState,
 | 
					    command_handler::debrace, echo_to_term_frame, id_intern::intern_id, GlobalLayoutCell,
 | 
				
			||||||
    GlobalMemoCell, TermFrame,
 | 
					    GlobalLayoutState, GlobalMemoCell, TermFrame,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
use gc_arena::{Gc, Rootable};
 | 
					use gc_arena::{Gc, Rootable};
 | 
				
			||||||
use piccolo::{
 | 
					use piccolo::{
 | 
				
			||||||
    self, Callback, Context, FromValue, Function, IntoValue, Table, UserData, Value, Variadic,
 | 
					    self, async_sequence, meta_ops, Callback, CallbackReturn, Context, FromValue, Function,
 | 
				
			||||||
 | 
					    IntoValue, SequenceReturn, Table, UserData, Value, Variadic,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
use std::{rc::Rc, str};
 | 
					use std::{rc::Rc, str};
 | 
				
			||||||
use yew::UseStateSetter;
 | 
					use yew::UseStateSetter;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					use super::prep_metaop_call;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pub fn echo_frame_raw<'gc, 'a>(
 | 
					pub fn echo_frame_raw<'gc, 'a>(
 | 
				
			||||||
    ctx: Context<'gc>,
 | 
					    ctx: Context<'gc>,
 | 
				
			||||||
    global_memo: &'a GlobalMemoCell,
 | 
					    global_memo: &'a GlobalMemoCell,
 | 
				
			||||||
@ -84,19 +87,22 @@ pub fn vsplit<'gc>(
 | 
				
			|||||||
    Callback::from_fn(&ctx, move |ctx, _ex, mut stack| {
 | 
					    Callback::from_fn(&ctx, move |ctx, _ex, mut stack| {
 | 
				
			||||||
        let path: String = stack.from_front(ctx)?;
 | 
					        let path: String = stack.from_front(ctx)?;
 | 
				
			||||||
        let path: &str = debrace(&path);
 | 
					        let path: &str = debrace(&path);
 | 
				
			||||||
        let frame: u64 = stack.from_front(ctx)?;
 | 
					        let frame: TermFrame = TermFrame(stack.from_front(ctx)?);
 | 
				
			||||||
        let new_splits = global_memo
 | 
					        let new_splits = global_memo
 | 
				
			||||||
            .layout
 | 
					            .layout
 | 
				
			||||||
            .borrow()
 | 
					            .borrow()
 | 
				
			||||||
            .term_splits
 | 
					            .term_splits
 | 
				
			||||||
            .vsplit(path, TermFrame(frame))
 | 
					            .vsplit(path, frame.clone())
 | 
				
			||||||
            .map_err(|e| e.into_value(ctx))?;
 | 
					            .map_err(|e| e.into_value(ctx))?;
 | 
				
			||||||
        let new_layout = Rc::new(GlobalLayoutState {
 | 
					        let new_layout = Rc::new(GlobalLayoutState {
 | 
				
			||||||
            term_splits: new_splits.clone(),
 | 
					            term_splits: new_splits.clone(),
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
        global_layout.set(new_layout.clone());
 | 
					        global_layout.set(new_layout.clone());
 | 
				
			||||||
        *(global_memo.layout.borrow_mut()) = new_layout;
 | 
					        *(global_memo.layout.borrow_mut()) = new_layout;
 | 
				
			||||||
        Ok(piccolo::CallbackReturn::Return)
 | 
					        Ok(CallbackReturn::Call {
 | 
				
			||||||
 | 
					            function: Function::Callback(ensure_frame_instance(ctx, &frame)),
 | 
				
			||||||
 | 
					            then: None,
 | 
				
			||||||
 | 
					        })
 | 
				
			||||||
    })
 | 
					    })
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -110,19 +116,22 @@ pub fn hsplit<'gc>(
 | 
				
			|||||||
    Callback::from_fn(&ctx, move |ctx, _ex, mut stack| {
 | 
					    Callback::from_fn(&ctx, move |ctx, _ex, mut stack| {
 | 
				
			||||||
        let path: String = stack.from_front(ctx)?;
 | 
					        let path: String = stack.from_front(ctx)?;
 | 
				
			||||||
        let path: &str = debrace(&path);
 | 
					        let path: &str = debrace(&path);
 | 
				
			||||||
        let frame: u64 = stack.from_front(ctx)?;
 | 
					        let frame: TermFrame = TermFrame(stack.from_front(ctx)?);
 | 
				
			||||||
        let new_splits = global_memo
 | 
					        let new_splits = global_memo
 | 
				
			||||||
            .layout
 | 
					            .layout
 | 
				
			||||||
            .borrow()
 | 
					            .borrow()
 | 
				
			||||||
            .term_splits
 | 
					            .term_splits
 | 
				
			||||||
            .hsplit(path, TermFrame(frame))
 | 
					            .hsplit(path, frame.clone())
 | 
				
			||||||
            .map_err(|e| e.into_value(ctx))?;
 | 
					            .map_err(|e| e.into_value(ctx))?;
 | 
				
			||||||
        let new_layout = Rc::new(GlobalLayoutState {
 | 
					        let new_layout = Rc::new(GlobalLayoutState {
 | 
				
			||||||
            term_splits: new_splits.clone(),
 | 
					            term_splits: new_splits.clone(),
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
        global_layout.set(new_layout.clone());
 | 
					        global_layout.set(new_layout.clone());
 | 
				
			||||||
        *(global_memo.layout.borrow_mut()) = new_layout;
 | 
					        *(global_memo.layout.borrow_mut()) = new_layout;
 | 
				
			||||||
        Ok(piccolo::CallbackReturn::Return)
 | 
					        Ok(CallbackReturn::Call {
 | 
				
			||||||
 | 
					            function: Function::Callback(ensure_frame_instance(ctx, &frame)),
 | 
				
			||||||
 | 
					            then: None,
 | 
				
			||||||
 | 
					        })
 | 
				
			||||||
    })
 | 
					    })
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -163,3 +172,178 @@ pub fn try_unwrap_frame<'gc>(
 | 
				
			|||||||
            .clone()),
 | 
					            .clone()),
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					pub fn ensure_frame_instance<'gc>(ctx: Context<'gc>, frame: &TermFrame) -> Callback<'gc> {
 | 
				
			||||||
 | 
					    let frame = frame.clone();
 | 
				
			||||||
 | 
					    Callback::from_fn(&ctx, move |ctx, _ex, _stack| {
 | 
				
			||||||
 | 
					        let frames: Table = ctx.get_global("frames")?;
 | 
				
			||||||
 | 
					        let frame_value: Value = frames.get(ctx, frame.0 as i64)?;
 | 
				
			||||||
 | 
					        if !frame_value.is_nil() {
 | 
				
			||||||
 | 
					            return Ok(CallbackReturn::Return);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        let frame_tab = Table::new(&ctx);
 | 
				
			||||||
 | 
					        let classes: Table = ctx.get_global("classes")?;
 | 
				
			||||||
 | 
					        frame_tab.set_metatable(&ctx, Some(classes.get(ctx, "frame")?));
 | 
				
			||||||
 | 
					        frames.set(ctx, frame.0 as i64, frame_tab)?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Call frame_tab:new(frame) to setup.
 | 
				
			||||||
 | 
					        let frame = frame.clone();
 | 
				
			||||||
 | 
					        let seq = async_sequence(&ctx, move |locals, mut seq| {
 | 
				
			||||||
 | 
					            let frame_tab = locals.stash(&ctx, frame_tab);
 | 
				
			||||||
 | 
					            async move {
 | 
				
			||||||
 | 
					                let call = seq.try_enter(|ctx, locals, _execution, mut stack| {
 | 
				
			||||||
 | 
					                    let frame_tab = locals.fetch(&frame_tab);
 | 
				
			||||||
 | 
					                    stack.consume(ctx)?;
 | 
				
			||||||
 | 
					                    Ok(prep_metaop_call(
 | 
				
			||||||
 | 
					                        ctx,
 | 
				
			||||||
 | 
					                        stack,
 | 
				
			||||||
 | 
					                        locals,
 | 
				
			||||||
 | 
					                        meta_ops::index(
 | 
				
			||||||
 | 
					                            ctx,
 | 
				
			||||||
 | 
					                            frame_tab.into_value(ctx),
 | 
				
			||||||
 | 
					                            ctx.intern_static(b"new").into_value(ctx),
 | 
				
			||||||
 | 
					                        )?,
 | 
				
			||||||
 | 
					                    ))
 | 
				
			||||||
 | 
					                })?;
 | 
				
			||||||
 | 
					                if let Some(call) = call {
 | 
				
			||||||
 | 
					                    seq.call(&call, 0).await?;
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                let call = seq.try_enter(|ctx, locals, _, mut stack| {
 | 
				
			||||||
 | 
					                    let value = stack
 | 
				
			||||||
 | 
					                        .pop_back()
 | 
				
			||||||
 | 
					                        .ok_or_else(|| anyhow::Error::msg("Index didn't return value"))?;
 | 
				
			||||||
 | 
					                    stack.consume(ctx)?;
 | 
				
			||||||
 | 
					                    stack.push_back(locals.fetch(&frame_tab).into_value(ctx));
 | 
				
			||||||
 | 
					                    stack.push_back(intern_id::<TermFrame>(ctx, frame.clone()));
 | 
				
			||||||
 | 
					                    Ok(locals.stash(&ctx, Function::from_value(ctx, value)?))
 | 
				
			||||||
 | 
					                })?;
 | 
				
			||||||
 | 
					                seq.call(&call, 0).await?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                Ok(SequenceReturn::Return)
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					        Ok(CallbackReturn::Sequence(seq))
 | 
				
			||||||
 | 
					    })
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					pub(super) fn new_frame<'gc>(ctx: Context<'gc>, _global_memo: &GlobalMemoCell) -> Callback<'gc> {
 | 
				
			||||||
 | 
					    Callback::from_fn(&ctx, move |ctx, _ex, mut stack| {
 | 
				
			||||||
 | 
					        let frame_tab: Table = Table::from_value(
 | 
				
			||||||
 | 
					            ctx,
 | 
				
			||||||
 | 
					            stack
 | 
				
			||||||
 | 
					                .pop_front()
 | 
				
			||||||
 | 
					                .ok_or_else(|| anyhow::Error::msg("classes.frame:new missing object!"))?,
 | 
				
			||||||
 | 
					        )?;
 | 
				
			||||||
 | 
					        let frame: Value = stack
 | 
				
			||||||
 | 
					            .pop_front()
 | 
				
			||||||
 | 
					            .ok_or_else(|| anyhow::Error::msg("classes.frame:new missing frame!"))?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        frame_tab.set(ctx, ctx.intern_static(b"frame"), frame)?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Ok(piccolo::CallbackReturn::Return)
 | 
				
			||||||
 | 
					    })
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Note: send_command_to_frame is called from the command parser, and can't be overriden (or even
 | 
				
			||||||
 | 
					// called) by the user.
 | 
				
			||||||
 | 
					// It will normally result in a call into frame_input, but that can be overriden by scripts.
 | 
				
			||||||
 | 
					pub(super) fn send_command_to_frame<'gc>(ctx: Context<'gc>) -> Callback<'gc> {
 | 
				
			||||||
 | 
					    Callback::from_fn(&ctx, move |ctx, _ex, mut stack| {
 | 
				
			||||||
 | 
					        let (frame, line): (Table, piccolo::String) = stack.consume(ctx)?;
 | 
				
			||||||
 | 
					        let seq = async_sequence(&ctx, |locals, mut seq| {
 | 
				
			||||||
 | 
					            let frame = locals.stash(&ctx, frame);
 | 
				
			||||||
 | 
					            let line = locals.stash(&ctx, line);
 | 
				
			||||||
 | 
					            async move {
 | 
				
			||||||
 | 
					                let call = seq.try_enter(|ctx, locals, _execution, stack| {
 | 
				
			||||||
 | 
					                    let frame = locals.fetch(&frame);
 | 
				
			||||||
 | 
					                    Ok(prep_metaop_call(
 | 
				
			||||||
 | 
					                        ctx,
 | 
				
			||||||
 | 
					                        stack,
 | 
				
			||||||
 | 
					                        locals,
 | 
				
			||||||
 | 
					                        meta_ops::index(
 | 
				
			||||||
 | 
					                            ctx,
 | 
				
			||||||
 | 
					                            frame.into_value(ctx),
 | 
				
			||||||
 | 
					                            ctx.intern_static(b"input").into_value(ctx),
 | 
				
			||||||
 | 
					                        )?,
 | 
				
			||||||
 | 
					                    ))
 | 
				
			||||||
 | 
					                })?;
 | 
				
			||||||
 | 
					                if let Some(call) = call {
 | 
				
			||||||
 | 
					                    seq.call(&call, 0).await?;
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                let call = seq.try_enter(|ctx, locals, _, mut stack| {
 | 
				
			||||||
 | 
					                    let value = stack
 | 
				
			||||||
 | 
					                        .pop_back()
 | 
				
			||||||
 | 
					                        .ok_or_else(|| anyhow::Error::msg("Index didn't return value"))?;
 | 
				
			||||||
 | 
					                    stack.consume(ctx)?;
 | 
				
			||||||
 | 
					                    stack.push_back(locals.fetch(&frame).into_value(ctx));
 | 
				
			||||||
 | 
					                    stack.push_back(locals.fetch(&line).into_value(ctx));
 | 
				
			||||||
 | 
					                    Ok(locals.stash(&ctx, Function::from_value(ctx, value)?))
 | 
				
			||||||
 | 
					                })?;
 | 
				
			||||||
 | 
					                seq.call(&call, 0).await?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                Ok(SequenceReturn::Return)
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					        Ok(CallbackReturn::Sequence(seq))
 | 
				
			||||||
 | 
					    })
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					pub(super) fn frame_input<'gc>(ctx: Context<'gc>, _global_memo: &GlobalMemoCell) -> Callback<'gc> {
 | 
				
			||||||
 | 
					    Callback::from_fn(&ctx, move |ctx, _ex, mut stack| {
 | 
				
			||||||
 | 
					        let frame_tab: Table = Table::from_value(
 | 
				
			||||||
 | 
					            ctx,
 | 
				
			||||||
 | 
					            stack
 | 
				
			||||||
 | 
					                .pop_front()
 | 
				
			||||||
 | 
					                .ok_or_else(|| anyhow::Error::msg("classes.frame:new missing object!"))?,
 | 
				
			||||||
 | 
					        )?;
 | 
				
			||||||
 | 
					        let line: Value = stack
 | 
				
			||||||
 | 
					            .pop_front()
 | 
				
			||||||
 | 
					            .ok_or_else(|| anyhow::Error::msg("classes.frame:new missing line!"))?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        let linked_mud = frame_tab.get_value(ctx, ctx.intern_static(b"linked_mud"));
 | 
				
			||||||
 | 
					        if linked_mud.is_nil() {
 | 
				
			||||||
 | 
					            return Ok(piccolo::CallbackReturn::Return);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        let linked_mud: Table = Table::from_value(ctx, linked_mud)?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // linked_mud:mudinput_line(line)
 | 
				
			||||||
 | 
					        let seq = async_sequence(&ctx, |locals, mut seq| {
 | 
				
			||||||
 | 
					            let linked_mud = locals.stash(&ctx, linked_mud);
 | 
				
			||||||
 | 
					            let line = locals.stash(&ctx, line);
 | 
				
			||||||
 | 
					            async move {
 | 
				
			||||||
 | 
					                let call = seq.try_enter(|ctx, locals, _execution, mut stack| {
 | 
				
			||||||
 | 
					                    let linked_mud = locals.fetch(&linked_mud);
 | 
				
			||||||
 | 
					                    stack.consume(ctx)?;
 | 
				
			||||||
 | 
					                    Ok(prep_metaop_call(
 | 
				
			||||||
 | 
					                        ctx,
 | 
				
			||||||
 | 
					                        stack,
 | 
				
			||||||
 | 
					                        locals,
 | 
				
			||||||
 | 
					                        meta_ops::index(
 | 
				
			||||||
 | 
					                            ctx,
 | 
				
			||||||
 | 
					                            linked_mud.into_value(ctx),
 | 
				
			||||||
 | 
					                            ctx.intern_static(b"mudinput_line").into_value(ctx),
 | 
				
			||||||
 | 
					                        )?,
 | 
				
			||||||
 | 
					                    ))
 | 
				
			||||||
 | 
					                })?;
 | 
				
			||||||
 | 
					                if let Some(call) = call {
 | 
				
			||||||
 | 
					                    seq.call(&call, 0).await?;
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                let call = seq.try_enter(|ctx, locals, _, mut stack| {
 | 
				
			||||||
 | 
					                    let value = stack
 | 
				
			||||||
 | 
					                        .pop_back()
 | 
				
			||||||
 | 
					                        .ok_or_else(|| anyhow::Error::msg("Index didn't return value"))?;
 | 
				
			||||||
 | 
					                    stack.consume(ctx)?;
 | 
				
			||||||
 | 
					                    stack.push_back(locals.fetch(&linked_mud).into_value(ctx));
 | 
				
			||||||
 | 
					                    stack.push_back(locals.fetch(&line));
 | 
				
			||||||
 | 
					                    Ok(locals.stash(&ctx, Function::from_value(ctx, value)?))
 | 
				
			||||||
 | 
					                })?;
 | 
				
			||||||
 | 
					                seq.call(&call, 0).await?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                Ok(SequenceReturn::Return)
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Ok(piccolo::CallbackReturn::Sequence(seq))
 | 
				
			||||||
 | 
					    })
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -2,7 +2,7 @@ use anyhow::Error;
 | 
				
			|||||||
use gc_arena::{Gc, Rootable};
 | 
					use gc_arena::{Gc, Rootable};
 | 
				
			||||||
use piccolo::{
 | 
					use piccolo::{
 | 
				
			||||||
    self, async_sequence, meta_ops, Callback, CallbackReturn, Context, FromValue, Function,
 | 
					    self, async_sequence, meta_ops, Callback, CallbackReturn, Context, FromValue, Function,
 | 
				
			||||||
    IntoValue, MetaMethod, SequenceReturn, StashedValue, Table, UserData, Value,
 | 
					    IntoValue, SequenceReturn, StashedValue, Table, UserData, Value,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
use wasm_bindgen::JsValue;
 | 
					use wasm_bindgen::JsValue;
 | 
				
			||||||
use web_sys::console;
 | 
					use web_sys::console;
 | 
				
			||||||
@ -16,7 +16,7 @@ use crate::{
 | 
				
			|||||||
    GlobalLayoutCell, GlobalMemoCell,
 | 
					    GlobalLayoutCell, GlobalMemoCell,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
use super::{prep_metaop_call, LuaState};
 | 
					use super::{prep_metaop_call, try_unwrap_frame, LuaState};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
fn try_unwrap_socketid<'gc>(
 | 
					fn try_unwrap_socketid<'gc>(
 | 
				
			||||||
    ctx: Context<'gc>,
 | 
					    ctx: Context<'gc>,
 | 
				
			||||||
@ -171,10 +171,25 @@ pub(super) fn connect_mud<'gc>(
 | 
				
			|||||||
        muds.set(ctx, new_socket, conntab)?;
 | 
					        muds.set(ctx, new_socket, conntab)?;
 | 
				
			||||||
        conntab.set(ctx, ctx.intern_static(b"socket"), new_socket)?;
 | 
					        conntab.set(ctx, ctx.intern_static(b"socket"), new_socket)?;
 | 
				
			||||||
        conntab.set(ctx, ctx.intern_static(b"buffer"), ctx.intern_static(b""))?;
 | 
					        conntab.set(ctx, ctx.intern_static(b"buffer"), ctx.intern_static(b""))?;
 | 
				
			||||||
        let conntab_meta = Table::new(&ctx);
 | 
					        conntab.set_metatable(&ctx, Some(mud_class));
 | 
				
			||||||
        conntab_meta.set(ctx, MetaMethod::Index, mud_class)?;
 | 
					        let curframe: Value = ctx
 | 
				
			||||||
        conntab.set_metatable(&ctx, Some(conntab_meta));
 | 
					            .get_global::<Table>("info")?
 | 
				
			||||||
 | 
					            .get(ctx, ctx.intern_static(b"current_frame"))?;
 | 
				
			||||||
 | 
					        if let Ok(curframe) = try_unwrap_frame(ctx, &curframe) {
 | 
				
			||||||
 | 
					            if let Ok(frame) = ctx
 | 
				
			||||||
 | 
					                .get_global::<Table>("frames")?
 | 
				
			||||||
 | 
					                .get::<i64, Value>(ctx, curframe.0 as i64)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                if !frame.is_nil() {
 | 
				
			||||||
 | 
					                    Table::from_value(ctx, frame)?.set(
 | 
				
			||||||
 | 
					                        ctx,
 | 
				
			||||||
 | 
					                        ctx.intern_static(b"linked_mud"),
 | 
				
			||||||
 | 
					                        conntab,
 | 
				
			||||||
 | 
					                    )?;
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        // Call conntab:new...
 | 
				
			||||||
        let seq = async_sequence(&ctx, |locals, mut seq| {
 | 
					        let seq = async_sequence(&ctx, |locals, mut seq| {
 | 
				
			||||||
            let conntab = locals.stash(&ctx, conntab);
 | 
					            let conntab = locals.stash(&ctx, conntab);
 | 
				
			||||||
            async move {
 | 
					            async move {
 | 
				
			||||||
@ -483,6 +498,27 @@ pub(super) fn mudoutput_subnegotiation<'gc>(
 | 
				
			|||||||
    Callback::from_fn(&ctx, move |_ctx, _ex, _stack| Ok(CallbackReturn::Return))
 | 
					    Callback::from_fn(&ctx, move |_ctx, _ex, _stack| Ok(CallbackReturn::Return))
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					pub(super) fn mudinput_line<'gc>(
 | 
				
			||||||
 | 
					    ctx: Context<'gc>,
 | 
				
			||||||
 | 
					    _global_memo: &GlobalMemoCell,
 | 
				
			||||||
 | 
					) -> Callback<'gc> {
 | 
				
			||||||
 | 
					    Callback::from_fn(&ctx, move |ctx, _ex, mut stack| {
 | 
				
			||||||
 | 
					        let (mud, line): (Table, piccolo::String) = stack.consume(ctx)?;
 | 
				
			||||||
 | 
					        stack.push_back(mud.get::<piccolo::String, Value>(ctx, ctx.intern_static(b"socket"))?);
 | 
				
			||||||
 | 
					        let line = [line.as_bytes(), b"\r\n"].concat();
 | 
				
			||||||
 | 
					        stack.push_back(ctx.intern(&line).into_value(ctx));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        let func = ctx
 | 
				
			||||||
 | 
					            .get_global::<Table>("commands")?
 | 
				
			||||||
 | 
					            .get::<piccolo::String, Function>(ctx, ctx.intern_static(b"sendmud_raw"))?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Ok(CallbackReturn::Call {
 | 
				
			||||||
 | 
					            function: func,
 | 
				
			||||||
 | 
					            then: None,
 | 
				
			||||||
 | 
					        })
 | 
				
			||||||
 | 
					    })
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pub(super) fn new_mud<'gc>(ctx: Context<'gc>, _global_memo: &GlobalMemoCell) -> Callback<'gc> {
 | 
					pub(super) fn new_mud<'gc>(ctx: Context<'gc>, _global_memo: &GlobalMemoCell) -> Callback<'gc> {
 | 
				
			||||||
    Callback::from_fn(&ctx, move |ctx, _ex, mut stack| {
 | 
					    Callback::from_fn(&ctx, move |ctx, _ex, mut stack| {
 | 
				
			||||||
        let mud: Table = Table::from_value(
 | 
					        let mud: Table = Table::from_value(
 | 
				
			||||||
 | 
				
			|||||||
@ -70,7 +70,7 @@ fn app() -> Html {
 | 
				
			|||||||
    });
 | 
					    });
 | 
				
			||||||
    use_memo((), |_| {
 | 
					    use_memo((), |_| {
 | 
				
			||||||
        install_lua_globals(&global_memo, global_layout.setter())
 | 
					        install_lua_globals(&global_memo, global_layout.setter())
 | 
				
			||||||
            .expect("Couldn't install Lua globals")
 | 
					            .expect("Couldn't install Lua globals");
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    html! {
 | 
					    html! {
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
		Reference in New Issue
	
	Block a user