Code Monkey home page Code Monkey logo

moor's Introduction

Multiuser
 Online
  Objects &
   Relations

What is this?

"Moor" is:

  • A system for building shared, programmable, Internet-accessible virtual social spaces
  • A programming and authoring tool for shared environments.
  • Fully compatible with LambdaMOO 1.8.x

Moor provides (from the bottom layer up...)

  • A fast, durable, transactional database with object and relational characteristics
  • A runtime for securely live-authoring and hosting programs and content that run persistently on that database
  • An authentication and authorization system for controlling access to said programs ("verbs") and content.
  • A programming language for building objects and verbs, along with the ability to plug in other languages / runtimes.
  • Tools and user environments for interacting with the system and writing verbs and editing content.

And it is designed to be used for:

  • Collaborative virtual environments
  • Socializing
  • Multiuser games
  • Persistent agents
  • Interactive fiction
  • Your entertainment and delight

Background

Launching in the early 1990s LambdaMOO is an online social environment, as well as an open source software package for building such environments for yourself.

LambdaMOO -- the place -- still exists today, with an unbroken 30+ year history, and a small but dedicated community of users and developers continue to use it -- both LambdaMOO the place, and MOO the server software for other communities.

MOO predates "social media", predates Facebook, Twitter, MySpace, Friendster, Tumblr, GeoCities, and... everything else.

In fact, it predates the world-wide web itself, and offers a very different kind of interaction with the Internet, one that is synchronous and live, text-based, not graphical, and is based around an evolving narrative that the users themselves create.

It is a multiuser virtual world, a MUD, a narrative "game", a chat room, a virtual environment, a social network, a programming environment, and a platform for collaborative fiction -- all in one.

It is a place where people can meet, talk, and build things together. And it's kind of awesome.

LambdaMOO screenshot (for a longer description, see doc/lambda-background.md)

Back to the Future

But it some senses, the actual technology did not age well at all. It lacks multimedia of any kind, its interface is dated, it is not very accessible to new users, and the once active community of developers and participants has dwindled to a small but dedicated group of enthusiasts.

And the server itself is aged; it is written in C -- is single threaded, with some known architectural limitations, and is not very easy to extend or modify. While there are newer versions and forks (such as Stunt, ToastStunt, etc.) that address many of these issues, they are still based on the same original codebase and architecture -- remaining bound by the single-threaded, single-core model of the original.

Moor is an attempt to reimagine LambdaMOO for the modern world, while retaining the core concepts and ideas that made it so compelling in the first place. It is a ground-up rewrite (in Rust). And while it maintains full compatibility with existing LambdaMOO "cores" (databases, worlds), it also offers a new, more flexible and extensible architecture, and extensions to the runtime to make it more adaptable to modern use cases:

  • A web-native architecture which allows for richer clients than a standard text-based terminal, including graphical clients, web clients, and mobile clients. Images, videos, emojis, rich text are all feasible, while keeping the narrative metaphor and creative aspects of the system intact.
  • A multi-core, multi-threaded, runtime, with a transactional, multiversion concurrency model instead of a global lock on the database, as in MOO. This allows for theoretically greater scalability.
  • A flexible, pluggable virtual machine environment which allows "verbs" to be written in alternative languages, such as JavaScript or WebAssembly modules (WIP).

Why?

Socializing, authoring, and creating on the Internet is in many ways broken. We want to make it better, by giving people tools to create their own spaces, and to create their own tools within those spaces.

It should be fun, it should be easy, it should be accessible, it should be open, it should be collaborative, it should be programmable, it should be extensible, it should be secure, it should be private, it should be free.

How do I use it?

The primary audience at this time is developers and administrators of existing MOO environments, and people who are interested in building new MOO environments, or people who are interested in extending this system out along the vision described below (under "What's next?").

If you're an existing MOO administrator, you can run your existing MOO database on Moor, and it should work just fine, with the following caveats:

  • No external network connection support or builtins for that. (Web front ends and alternative protocols are done in the Rust server layer, not in the MOO core.)
  • No support for the extensions present in ToastStunt, Stunt, etc. (e.g. map type, WAIFs etc.). (Some of these may come in the future. Or not.)

The easiest way to get started is to run the docker compose setup. This will bring up a complete server with telnet and websocket interfaces. The server will be setup with an initial JaysHouseCore core import.

To run, take a look at the local docker-compose.yml file, instructions are there, but it really just amounts to:

    docker compose up

This setup is intended for development and testing. In particular, all binaries are compiled in (slower, fatter) debug mode, and any changes to the source code will cause a rebuild of the server, and a restart of the server. This is useful for development, but not for production.

However, the docker-compose.yml file is a good starting point for understanding how to run the server in a production environment. The server is composed of a number of services, including the moor-daemon binary, and various "host" services which provide the actual interfaces to the server.

How is this thing put together? What even is it?

The server is written in Rust, and is composed of a number of crates and running services. These services communicate with the main server process over an RPC system and message bus implemented on top of ZeroMQ.

For a high level architecture description plus a more detailed breakdown on how the server is put together, see the ARCHITECTURE.md document.

License?

Moor is licensed under the GNU General Public License, version 3.0. See the LICENSE file for details.

Why the GPL?

But "The GPL isn't very popular these days", "my employer forbids me to contribute to GPL projects" ...

  • LambdaMOO itself is licensed under the GPL (version 2). And while the question of whether Moor is a derived work of it is a matter of debate (I did read its source code while developing), I see it as ethical to keep the same license.
  • The GPL encourages sharing of upstream work and collaboration, and that's what we want to do.
  • I don't get paid to work on this, and while it's unlikely, I don't want to see it turned into a proprietary product that I can't use or contribute to. I want to see it used and improved by as many people as possible.

Who made this?

Most of the work on this has been done by myself, Ryan Daum [email protected]. Large chunks of the decompiler, and various other pieces of code including code cleanliness and testing contributions, were done by Norman Nunley.

And there's been plenty of inspiration and help from a community of fellow old-school MOO (and ColdMUD!) folks that I've known since the 90s.

Finally, LambdaMOO itself was primarily authored by Pavel Curtis, with the original LambdaMOO server being written by Stephen White. Successive versions and forks have been maintained by a number of people.

What's done?

At this point Moor is capable of executing the full LambdaMOO 1.8.x language, and is capable of running existing LambdaMOO databases. With some caveats:

  • Persistent tasks are not yet implemented.
  • Outbound network connections are not supported.
  • Extensions present in ToastStunt, Stunt, etc. including map types, WAIFs, etc. are not supported.

For a list of the status of the implementation of standard LambdaMOO builtin functions, see builtin_functions_status.md.

Moore screenshot

What's next?

There's a lot of work to do. We're looking for contributors, testers, and users. We're also looking for feedback, ideas, and use cases.

We're also looking for funding, and for partners who want to build things on top of Moor.

The immediate horizon is to get the initial release out, which will be a drop-in replacement for LambdaMOO, with some additional features. This will include a web-based client. To get there the following is still required

  • Robustness and stability work.
  • .... In particular around the custom in-memory database. This needs a lot of testing both in correctness and performance
  • Correctness testing using tools like Jepsen and Stateright to prove out the transactional model & scheduler
  • Performance testing to ensure that the system can handle a large number of users and objects.
  • Support for persistent tasks
  • And maybe outbound network connections, but that's a maybe.

The intent is to get to a 1.0 release after these are done. This 1.0 release will be fully compatible with existing LambdaMOO databases, and will be a drop-in replacement for LambdaMOO.

The roadmap for future features after the initial 1.0 release include:

  • A more modern, web-based client. The start of this has been sketched out in the web host repository, but it's still very early. The intent is to provide a more modern, graphical, and interactive experience, while still retaining the narrative and creative aspects of a MOO. It will additionally provide modern authoring tools like a syntax highlighting, auto-indenting editor, a Smalltalk-style object browser, and a debugger. Some work on this has already been done. Example browser screenshot
  • Support for alternative languages and runtimes for verbs. The initial plan is to support JavaScript as a verb authoring language in addition to MOO. Verbs written in other languages will have access to the same object environment as MOO verbs, and will be able to call MOO verbs and be called by MOO verbs. Lua, and WebAssembly are also potential candidates for the future.
  • Support for a richer data model which includes aspects of a logic programming language model. Programmers / authors will be able to declare first class relations between objects, and query them. The idea here is to take the grunt work out of building complex, multi-user, social systems, and to make it easier to build things that have complicated interactive behaviors.
  • Support for multimedia content, including images, videos, and audio. This will be done in a way that is consistent with the narrative metaphor of the system, and will be programmable and extensible.
  • A better permissions model, including support for more fine-grained access control, and a more modern, user-friendly interface for managing permissions. MOO-style fixed, knowable object numbers (#123 style) will be replaced or subsumed by object-capability references. The challenge being to maintain backwards compatibility with existing cores.

moor's People

Contributors

nnunley avatar rdaum avatar waywardmonkeys avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

moor's Issues

Add/trial a `FoundationDB` WorldState backend

Similar to #21 , I would like to see how this would perform and work out in code. I played with this in an earlier sketch of things, but didn't go far with it. In theory everything that is done via rocks can be done with FDB, but with distribution baked in (at the cost of performance and complexity)

They share a similar limitation though in that they're both optimized for a single-writer (per relation) but multiple reader workflow. Which may not describe the characteristics of what a transaction load is actually like in a working system.

Implement stable-backup db export.

Need a way to create a dump of the world state that can be used independent of the binary database, most especially useful for migration between versions of the DB format while things are still fairly unstable.

Does not necessarily have to be backwards compatible with LambdaMOO textdump

Missing feature: `huh` support

If command matching fails, the server should call huh on the current player object, if that verb exists.

LambdaCore and others use this to implement "feature" objects.

[rdaum] Check recursion down to see if all literal values, and if so reduce to a...

instead of concatenation with MkSingletonList.

// TODO(rdaum): Check recursion down to see if all literal values, and if so reduce to a Imm value with the full list,

    }

    fn generate_arg_list(&mut self, args: &Vec<Arg>) -> Result<(), CompileError> {
        // TODO(rdaum): Check recursion down to see if all literal values, and if so reduce to a Imm value with the full list,
        //  instead of concatenation with MkSingletonList.
        if args.is_empty() {
            self.emit(Op::ImmEmptyList);

[rdaum] change result of login to return this information, rather than just Obji...

we're not dependent on this.

// TODO(rdaum): change result of login to return this information, rather than just Objid, so

        args: Vec<String>,
        attach: bool,
    ) -> Result<RpcResponse, RpcRequestError> {
        // TODO(rdaum): change result of login to return this information, rather than just Objid, so
        //   we're not dependent on this.
        let connect_type = if args.first() == Some(&"create".to_string()) {
            ConnectType::Created

[rdaum] bitwise operators here (| 10, ^ XOR 9, & 8) if we ever get them.

7

Equality/inequality

// TODO(rdaum): bitwise operators here (| 10, ^ XOR 9, & 8) if we ever get them.

        .op(Op::infix(Rule::lor, Assoc::Left))
        // 11. Logical and.
        .op(Op::infix(Rule::land, Assoc::Left))
        // TODO(rdaum): bitwise operators here (| 10, ^ XOR 9, & 8) if we ever get them.
        // 7
        // Equality/inequality
        .op(Op::infix(Rule::eq, Assoc::Left) | Op::infix(Rule::neq, Assoc::Left))

[rdaum] "binaries" returned from the db should be SliceRefs, not Vecs.

// TODO(rdaum): "binaries" returned from the db should be SliceRefs, not Vecs.

    fn get_verbs(&self, obj: Objid) -> Result<VerbDefs, WorldStateError>;

    /// Get the binary of the given verb.
    // TODO(rdaum): "binaries" returned from the db should be SliceRefs, not Vecs.
    fn get_verb_binary(&self, obj: Objid, uuid: Uuid) -> Result<Vec<u8>, WorldStateError>;

    /// Find & get the verb with the given name on the given object.

[rdaum] this list is inconsistently used, and falls out of date. It's only used ...

the list of functions for the `function_info` built-in right now. It could be used for

validating arguments, and could be part of the registration process for the actual builtin

implementations.

// TODO(rdaum): this list is inconsistently used, and falls out of date. It's only used for generating

}

// Originally generated using ./generate_bf_list.py
// TODO(rdaum): this list is inconsistently used, and falls out of date. It's only used for generating
//  the list of functions for the `function_info` built-in right now. It could be used for
//  validating arguments, and could be part of the registration process for the actual builtin
//  implementations.

Jepsen and/or Stateright tests

I would like a suite of tests to check for correctness of concurrent behaviour; linearizability, consistency, serialization conflicts, etc.

Still very vague in my mind, but probably a suite of Jepsen tests and/or Stateright (https://github.com/stateright/stateright).

Essentially, instantiating kernel + db with a predefined simple set of objects and then perform concurrent evaluations of mutations to provoke serialization conflicts, retries, and verify correct behaviour under concurrent load.

This will be essential in the short run run for a) finishing the transactional layer (retries on conflict) and b) making sure the Rocks etc layer works as hopes and in the medium/long run for swapping in alternative world state storage models.

[Blocker] No External Networks Connection Verbs

Many games, and maybe all of them, require the ability to have verbs that open TCP sockets as listeners or to establish outgoing network connections at the verb level.

I understand this is contrary to your vision but it will present a significant if not insurmountable barrier of entry in limiting adoption of your server.

Games like Torchship use sockets to talk to external simulation layer services like our login server which uses TCP and not REST to communicate. Similarly, our space simulation server which is written in Rust also uses TCP to communicate with the game over a custom messaging protocol I wrote for that specific implementation. Which would be unideal to move to the server layer because it's iterated on so frequently it would result in significant service downtimes or stability issues during testing, which verbs offer in safety on the VM.

Other games use those connections to talk to things like mail forwarding agents.

Improve the authentication / sign-on story

LambdaMOO cores' connect function uses a variant of the Unix crypt function, ala old Unix passwd files, and stores the passwords in-db.

For compatibility with existing cores (and to make servicing existing telnet clients feasible), it's necessary to keep this process for now. But this isn't going to cut it as a security story.

Some kind of SSO story & auth token is going to be needed. For the latter, one option is JWT, another is PASETO, which sounds more promising.

Then the websocket connection (and any HTTP sessions generally) will need to be authenticated with this token before client connections can proceed.

The long-term future for the telnet modality will need to be thought about in this context.

Not a requirement for 1.0 (LambdaMOO compatible) release.

Implement `read` builtin

Performs a synchronous blocking read on the network connection. Will require some thought on how to do this right.

Write up an `architecture.md`

Now that I've pretty much de-cloaked on this project and there's some external people watching, it's probably best to document the decisions, vision, and architecture a bit.

Basically a couple diagrams breaking down the layers and components, thread and process and network boundaries, and a description of the why and how.

Community Growth and Health?

Hi, I'm Volund of the MUSH Community. Been looking into MOO on and off and I found this thanks to reddit... well, really I found it thanks to ToastStunt community talking about it and have a few things to say and suggest....

  1. SPECTACULAR JOB at getting this to where it is. I was thinking about doing something similar if I had infinite time - which I don't - and now I don't have to, I can learn from and possibly help out with this one instead. I can't wait to tear into this and learn from it. :D And see where it's going.

  2. Suggest a more careful rewording of the readme section that mentions why you'd use Moor instead of ToastStunt. It can be read to imply that ToastStunt doesn't have an active developer community, and it does.

  3. Please create a Discord or similar chat-server for the Moor community to meet up on and grow around. Evennia has one, RhostMUSH has one, ToastStunt has one, I think AresMUSH has one... projects like this need lots of cultivation from a community to grow and thrive, so let's get cracking. 😄

Questions about Docker usage

Hello! I have some questions about the specific way docker is being used in this project. I'd like some help understanding the purpose/usecase of having the whole project recompile itself with cargo watch while watching for changes.

In my experience with docker, this tends to make the image more bloated and run slower.

[rdaum] make sure that this doesn't fail with nested try/excepts?

// TODO(rdaum): make sure that this doesn't fail with nested try/excepts?

                }
                // Decompile the body.
                // Means decompiling until we hit EndExcept, so scan forward for that.
                // TODO(rdaum): make sure that this doesn't fail with nested try/excepts?
                let (body, end_except) =
                    self.decompile_statements_until_match(|_, o| matches!(o, Op::EndExcept(_)))?;
                let Op::EndExcept(end_label) = end_except else {

[rdaum] this is going to be not-at-all performant in the long run, and we'll nee...

cache this or index it better

// TODO(rdaum): this is going to be not-at-all performant in the long run, and we'll need a way to

    }

    fn get_players(&self) -> Result<ObjSet, WorldStateError> {
        // TODO(rdaum): this is going to be not-at-all performant in the long run, and we'll need a way to
        //   cache this or index it better
        get_all_object_keys_matching(
            &self.tx,

[rdaum] MOO has "return ptr - 2;" -- doing something with the iteration, that

I may not be able to do with the current structure. See if I need to

// TODO(rdaum): MOO has "return ptr - 2;" -- doing something with the iteration, that

            }
            Op::EndCatch(_) | Op::Continue | Op::EndExcept(_) | Op::EndFinally => {
                // Early exit; main logic is in TRY_FINALLY or CATCH etc case, above
                // TODO(rdaum): MOO has "return ptr - 2;"  -- doing something with the iteration, that
                //   I may not be able to do with the current structure. See if I need to
                unreachable!("should have been handled other decompilation branches")
            }

Decompilation error for scatter assignment to `$property`

>@list $mcp:session_for
Verb 9 on #213 -- E_RANGE
>;verbs($mcp)
=> {"create_session", "destroy_session", "initialize_connection", "finalize_connection", "parse_version", "compare_version_range", "compare_version", "unparse_version", "session_for", "user_created", "user_disconnected", "do_out_of_band_command", "package_name", "wait_for_package", "nominate_for_core", "handles_package", "init_for_core"}
>;verb_code($mcp, "session_for")
=> E_INVARG  (E_INVARG)

Either in decompilation, or in verb resolution.

Implement `memory_usage` and `db_disk_size`

For moor, these would be, most meaningfully:

memory_usage : Just grab process RSS for the daemon PID. Simpler and more accurate than manually summing up the DB buffer pools etc.

db_disk_size: This would be the the total byte count of all tuples in the DB. For now since I'm not yet LRU-paging out tuples, that's the exact same as the usage count of the primary buffer pool. This gets trickier to calc after paging gets supported.

[rdaum] drive Pratt and this from one common precedence table.

// TODO(rdaum): drive Pratt and this from one common precedence table.

        // directly on http://en.cppreference.com/w/cpp/language/operator_precedence
        // Should be kept in sync with the pratt parser in `parse.rs`
        // Starting from lowest to highest precedence...
        // TODO(rdaum): drive Pratt and this from one common precedence table.
        let cpp_ref_prep = match self {
            Expr::Scatter(_, _) | Expr::Assign { .. } => 14,
            Expr::Cond { .. } => 13,

[rdaum] manage this buffer better -- e.g. if it grows too big, for long-running ...

should be mmap'd to disk or something.

// TODO(rdaum): manage this buffer better -- e.g. if it grows too big, for long-running tasks, etc. it

    client_id: Uuid,
    rpc_server: Arc<RpcServer>,
    player: Objid,
    // TODO(rdaum): manage this buffer better -- e.g. if it grows too big, for long-running tasks, etc. it
    //  should be mmap'd to disk or something.
    // TODO(rdaum): We could also use Boxcar or other append-only lockless container for this, since we only
    //  ever append.
    session_buffer: Mutex<Vec<(Objid, NarrativeEvent)>>,
}

[rdaum] We could also use Boxcar or other append-only lockless container for thi...

ever append.

// TODO(rdaum): We could also use Boxcar or other append-only lockless container for this, since we only

    client_id: Uuid,
    rpc_server: Arc<RpcServer>,
    player: Objid,
    // TODO(rdaum): manage this buffer better -- e.g. if it grows too big, for long-running tasks, etc. it
    //  should be mmap'd to disk or something.
    // TODO(rdaum): We could also use Boxcar or other append-only lockless container for this, since we only
    //  ever append.
    session_buffer: Mutex<Vec<(Objid, NarrativeEvent)>>,
}

Bug: Compilation or Execution error found while running `QuestCore2.db`

Problem in stack unwinding related to error Catch handling.

Found while running:
help $scheduler

Doesn't happen for other :help_msg invocations it seems. Haven't tracked down what verb flow is causing this yet.

daemon log:

note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.
2023-09-24T21:59:30.157150364Z 2023-09-24T21:59:30.156994Z  WARN ThreadId(15) do_process: crates/kernel/src/tasks/scheduler.rs:787: Task sys-errored task=69 error=Disconnected
2023-09-24T22:00:42.543329425Z thread 'tokio-runtime-worker' panicked at 'TODO: CatchLabel where we didn't expect it...', crates/kernel/src/vm/vm_unwind.rs:367:25
2023-09-24T22:00:42.543368941Z stack backtrace:
2023-09-24T22:00:42.543373580Z    0: rust_begin_unwind
2023-09-24T22:00:42.543376937Z              at /rustc/eb26296b556cef10fb713a38f3d16b9886080f26/library/std/src/panicking.rs:593:5
2023-09-24T22:00:42.543380263Z    1: core::panicking::panic_fmt
2023-09-24T22:00:42.543383389Z              at /rustc/eb26296b556cef10fb713a38f3d16b9886080f26/library/core/src/panicking.rs:67:14
2023-09-24T22:00:42.543388429Z    2: moor_kernel::vm::vm_unwind::<impl moor_kernel::vm::VM>::unwind_stack
2023-09-24T22:00:42.543392156Z              at ./crates/kernel/src/vm/vm_unwind.rs:367:25
2023-09-24T22:00:42.543410261Z    3: moor_kernel::vm::vm_execute::<impl moor_kernel::vm::VM>::exec::{{closure}}
2023-09-24T22:00:42.543413777Z              at ./crates/kernel/src/vm/vm_execute.rs:502:28
2023-09-24T22:00:42.543446871Z    4: <moor_kernel::tasks::moo_vm_host::MooVmHost as moor_kernel::tasks::vm_host::VMHost<moor_kernel::vm::opcode::Program>>::exec_interpreter::{{closure}}
2023-09-24T22:00:42.543462882Z              at ./crates/kernel/src/tasks/moo_vm_host.rs:182:68

check_object_allows should take a BitEnum arg for `allows`

so we can check for multiple flags at once.

// TODO check_object_allows should take a BitEnum arg for `allows`

    ) -> Result<Objid, WorldStateError> {
        if parent != NOTHING {
            let (flags, parent_owner) = (self.flags_of(parent)?, self.owner_of(parent)?);
            // TODO check_object_allows should take a BitEnum arg for `allows`
            //   so we can check for multiple flags at once.
            self.perms(perms)?
                .check_object_allows(parent_owner, flags, ObjFlag::Read)?;
            self.perms(perms)?

Scheduler refactor: move transaction create/commit/rollback/retry up into scheduler?

Right now it's task.rs that does the logic with this.

With the command interpreter loop there's 2 separate transactions: one to match for parsing the command, and another to execute the command. And with support for $do_command there's a third, and once I fix missing huh handling, that's a fourth! Not a good situation. 3/4 of these transactions all occur within the scheduler, and so could be all subsumed under that one place.

I played with optionally passing an already-existing transaction into the task, but the problem with this is that to do the :huh support the transaction will already have been committed when the task completes with error.

So my proposal is to go through and clean things up potentially so that tasks always begin and end with an open transaction, and it's Scheduler that is responsible for the lifecycle of transactions -- passing ownership of them to the task, and getting them back again at completion.

[rdaum] we will need to verify that the player object id inside the token is val...

moor itself. And really only something with a WorldState can do that. So it's not

enough to have validated the auth token here, we will need to pepper the scheduler/task

code with checks to make sure that the player objid is valid before letting it go

// TODO(rdaum): we will need to verify that the player object id inside the token is valid inside

            }
        }

        // TODO(rdaum): we will need to verify that the player object id inside the token is valid inside
        //   moor itself. And really only something with a WorldState can do that. So it's not
        //   enough to have validated the auth token here, we will need to pepper the scheduler/task
        //   code with checks to make sure that the player objid is valid before letting it go

[rdaum] unprovoked output from the narrative stream screws up the prompt midstre...

but we have no real way to signal to this loop that it should newline for

cleanliness. Need to figure out something for this.

// TODO(rdaum): unprovoked output from the narrative stream screws up the prompt midstream,

    let mut rl = DefaultEditor::new().unwrap();
    loop {
        // TODO(rdaum): unprovoked output from the narrative stream screws up the prompt midstream,
        //   but we have no real way to signal to this loop that it should newline for
        //   cleanliness. Need to figure out something for this.
        let input_request_id = input_request_id.lock().unwrap().take();

Decompilation / unparse on "fork vectors" / fork blocks

This is both untested and mostly unimplemented. Forked tasks are unlikely to be currently doing any of the following properly:

  • @list / view of the verb code
  • disassemble builtin output
  • Reporting line numbers correctly in tracebacks

[rdaum] I may or may not keep this field around.

/ the line number spans in the bytecode.

/// TODO(rdaum): I may or may not keep this field around.

    /// Note that this is not necessarily the same as the line number that will be reported into
    /// codegen, and may not correspond to what shows as a result of `unparse`; that line number
    /// is derived from the AST, not the parser.
    /// TODO(rdaum): I may or may not keep this field around.
    pub parser_line_no: usize,
    /// This line number is generated during a second pass over the tree, and is used to generate
    /// the line number spans in the bytecode.

Persist background tasks in the database / restart background tasks on restart

The tasks in the scheduler are currently not persisted. Problem because:

  • Restarts of the daemon for upgrades, etc. will kill background tasks without recovery on restart, interrupting the user experience.
  • LambdaMOO does do this, so we should be doing it for compatibility.

scheduler.rs and task.rs will need some reworking to synchronize their state out to WorldState, which will need new interfaces for this.

And for compatibility, we might need to support the textdump'd background task set from LambdaMOO textdump imports.

`ctime()` builtin does not return expected formatting

LambdaMOO:
=> "Thu Sep 28 13:53:54 2023 PDT"
vs moor:
=> "Thu, 28 Sep 2023 20:53:39 +0000"

To be compliant with the MOO spec for ctime, this should a) return the timezone descriptor instead of offset and b) use the local timezone, not UTC.

Symptoms are that some internal core functions that parse the ctime don't work:

@shutdown
Do you really want to shut down the server in 2 minutes? [Enter `yes' or `no']
yes
#39:english_time (line 22): Range error
... called from #51:@shutdown (this == #2) (line 31)
(End of traceback)

Add/trial a SQL` WorldState` backend

It would be nice to try providing an alternative to the rocksdb db implementation that is based around a relational database.

When I first started, I used SQLite for this -- and in fact used SQL's transitive closure / recursive joins feature for inherited verb resolution even -- but it got awkward as I was hacking heavily, so it got pulled out.

But I'd like to maybe revisit this, with a Postgres (and maybe other) backend, In all likelihood it would need a caching layer in front, but in fact the Rocks stuff really needs this, too. (And the challenge at the caching layer remains transactional consistency, but that's a whole other kettle of fish).

In the end I'm interested in:

  • How awkward the generated relations and queries end up being
  • What the performance is like

Support quota / E_QUOTA

Requires at least estimating object sizes and tracking them per user / owner.
Need some hooks on the WorldState interface.

Detect "created" ConnectType in RPC daemon

Needs to dispatch properly to user_created rather than user_connected, and send "** Created " to the user instead of " Connected **".

LambdaMOO does this by comparing max_object() before and after login, but we will have to find a better way because that is bad in all sorts of ways.

[rdaum] ownership_quota support

If the intended owner of the new object has a property named `ownership_quota' and the value of that property is an integer, then `create()' treats that value

as a "quota". If the quota is less than or equal to zero, then the quota is considered to be exhausted and `create()' raises `E_QUOTA' instead of creating an

object. Otherwise, the quota is decremented and stored back into the `ownership_quota' property as a part of the creation of the new object.

// TODO(rdaum): ownership_quota support

        let owner = (owner != NOTHING).then_some(owner);

        // TODO(rdaum): ownership_quota support
        //    If the intended owner of the new object has a property named `ownership_quota' and the value of that property is an integer, then `create()' treats that value
        //    as a "quota".  If the quota is less than or equal to zero, then the quota is considered to be exhausted and `create()' raises `E_QUOTA' instead of creating an
        //    object.  Otherwise, the quota is decremented and stored back into the `ownership_quota' property as a part of the creation of the new object.
        let attrs = ObjAttrs {
            owner,
            name: None,

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.