Giter Site home page Giter Site logo

Mod architecture about citybound HOT 47 OPEN

citybound avatar citybound commented on April 28, 2024 2
Mod architecture

from citybound.

Comments (47)

aeplay avatar aeplay commented on April 28, 2024 7

Alright, I made up my mind. Here is my proposal and plan of action:

For now, we go with @martinrlilja's 2nd option:

Mods = Dynamic Rust Libraries

To reiterate and comment on pro's & cons:

Pros

  • Native performance
    • hugely important, since a lot of "high-level game logic" actually runs in very hot loops (especially in traffic simulation, pathfinding, road-planning - the same will be true for economy and other areas)
  • Existing interfaces should be possible to re-use / mod and mainline code will be compatible.
    • this would allow us to achieve moddability very soon, interfacing reasonably with a scripting language is really non-trivial and a lot of work to get right.
  • Should make odd things possible. (Running web servers, hooking up python scripts, etc.)
    • not sure yet how important that actually is

Cons

  • Not safe (same access to the system as the game has).
    • I was thinking about jailing the game process anyways using a helper "launcher" process. All the game could then do would be write savegames. But also not really an issue given proper education of the user & publicly visible mod reviewing
  • Relatively easy to mess up cross platform support. (Depends on what you are doing.)
    • I don't see where any game code would be platform dependent (except maybe odd stuff as defined above)
  • Rust can be a bit tricky to use.
    • that is probably the biggest gotcha, but most of the game code doesn't delve deeply at all into tricky stuff like generics + lifetimes, leaving something that is "almost a scripting language"

Plan of action

In separate repos, develop:

  1. A library for runtime discovery and binding of mod-dylibs
  • this should define the interface conventions and scaffolding around a mod
  • should allow for mods loading sub-mod-dylibs themselves (to achieve moddability at varying levels of granularity)
  • try to get hot-code-reload working
  1. A mod-compiler (probably a very thin layer on top of rustc) that can create dylibs from a source-form of a mod (that might be simpler than a full-blown cargo crate)

Then:

  • integrate the runtime-library into the main game and repackage all game code as mods, compile them manually
  • make the mod-compiler a mod itself (meta!!) that is downloaded on-demand once one made changes to the game source that ships with the game (since the mod-compiler will be at least as big as rust itself, so >100mb) that will automatically recompile changed mods, allowing local development of mods without having to setup a dev-environment.
  • somehow build cross-compilation-as-a-service based on the mod-compiler

Finally:

  • Create a webservice ("mod-store") for mod discovery, rating and registry.

Conclusion

The nice thing about this plan is that already the very first steps will be useful for the main game development as well and incrementally lead towards a pretty comfortable modding situation.

Let me know what you think! (Especially @mijgame, @martinrlilja)

from citybound.

mijgame avatar mijgame commented on April 28, 2024 2

@martinrlilja that's a good idea as well. In the long run, a official 'mod' could be made that integrates a scripting language with a standard API. This would allow for a lot of mods that want to add simple functionality, like interfaces / views with info about your city, extra buildings / zones and stuff like that. Mods that really want to change the core of the game could write in Rust.

from citybound.

chdudek avatar chdudek commented on April 28, 2024 2

Its maybe a bit late to add my two cents to the discussion (but will do it anyways :D)

I really like the idea of using a scripting language for modding, as long as there is a good api! The modding community would highly benefit from a easier to learn and/or widely used languag.

For me, I would be highly interested into modding, but I don't know if I will have enough time to learn Rust just for some modding (I've never heard of Rust before!). And I could imagine that stands for many other potential modders out there.

So, I think both variants, modding via libraries and modding with scripts would be greate. It would give an easier entry for interested modders. And if someone reaches the limits of scripting-mods, they may can switch to the rust libraries, if possible.

from citybound.

mijgame avatar mijgame commented on April 28, 2024 1

@aeickhoff I'm not very familiar with functional programming languages, so I'll try it out and learn some things about it before I give my opinion.

from citybound.

aeplay avatar aeplay commented on April 28, 2024 1

Yeah, Rust -> WebAssembly was the plan for that

from citybound.

aeplay avatar aeplay commented on April 28, 2024 1

That sounds pretty good, I'll consider it!

from citybound.

tsteinholz avatar tsteinholz commented on April 28, 2024

+1 for scripting - rust even has some scripting languages like Dyon, Ketos, and Rhai. I am also a fan of Lua which also has some rust bindings. Might be worth making an Engineering Style Decision Matrix to compare the different languages. Or maybe one even to pick between the dynamic libraries and scripting options.

from citybound.

nielsmh avatar nielsmh commented on April 28, 2024

Mods used must be stored in savegames. Active mods should definitely not be a global state. This can help prevent players load a saved game that requires a mod they don't have, and can let players keep multiple cities going with different mod sets without having to manually switch around.

With this approach, you would obviously need a mechanism for adding further mods to an existing save (making it a deliberate process for the player), and mods may need to have different behavior depending on whether they are loaded for a brand new city, or if they are being enabled for an existing city.
Additionally, mods should ideally support unloading/disabling them from a city. That may not be possible for some types of mods, they need to carry a flag for whether they support being taken out.

Lastly there can also be classes of mods that are never actually necessary for saved games to work, that could e.g. be a mod that affects what sound effects are played when, and those should be marked as optional in some way for savegames' mod dependency list.
Possibly there could even be a class of "presentation mods" that only affects UI and not simulation, that are loaded as globals and never listed in a saved game.

As for languages, I also like Lua a lot, and want to remind that LuaJit is a thing that exists, and it can give very good performance. It still has the limitations of having to develop a separate API for it, but that requirement is sort-of eliminated if the entirety of the game logic is written in it. (Then mods are no longer a special case but instead are the norm.)

from citybound.

tsteinholz avatar tsteinholz commented on April 28, 2024

What type of priority does the modding system have on this game? If we wanted this game to be very easily modifiable, then the best approach would be to make the game it's self a type of mod. Then extending the game's functionality would be as easy original implementation. Then the game would be a core system with a few base "mods" and a new way to factor in new mods. For example, the lanes and the cars would each be built the same way a mod would be. Unfortunately the game is already built in a way that if we were to implement this, we would either need to backtrack, or expand the concept of the core game. But if we expand the concept of what the core of the game is too much, then none of the components of the game would actually be build the same way a mod would be.

from citybound.

mijgame avatar mijgame commented on April 28, 2024

I thinks a game like Factorio is a nice example of how to do modding. The game itself is the 'Base mod' and extending the game is done using Lua. It works very nicely.

from citybound.

aeplay avatar aeplay commented on April 28, 2024

My initial plans for modding support were actually more radical, let me know what you think:

Given that CB is open-source...

  • A mod is just a fork with some modifications
  • There is a build-service that makes it easy to cross-compile the whole game for all three platforms on-demand
  • There is a UI-tool that (using the Github API or something) allows you to create combinations of mods by merging them - if there is no merge-conflicts, it will probably work
  • Very popular mod-combinations could be manually maintained by the authors of the individual mods to guarantee that they will work together
  • "Officially blessed" mods could be pulled into the Citybound Github organisation and thus marked as "probably not malicious" in contrast to completely unsupervised new mods

from citybound.

mijgame avatar mijgame commented on April 28, 2024

That sounds way, way too complicated for the average player. How many players actually know what a 'fork' even is? Or what compiling means? I know people who actually have difficulty installing mods because the can't find the right folder, because it is in AppData and they can't find that folder.

I think the only way to make mods and modding user-friendly and developer-friendly is to use a good, dynamic scripting language like Lua or JavaScript. Which would allow for users to just drag and drop files in order to install mods. What if you wanted to switch modpacks? That would require you to either have two (or more) installs of the game or recompile the game everytime you want to switch.

from citybound.

aeplay avatar aeplay commented on April 28, 2024

All this complexity would be hidden away from the player, a "launcher" UI could offer an app-store like interface for mods doing all of this in the background. You are right that it would make the transition from player->modder more difficult though. What makes me shy away a little from stuff like a modding API or a scripting language is that it imposes pretty strict limits on what is moddable and what isn't.

from citybound.

mijgame avatar mijgame commented on April 28, 2024

Does it though? I think you can make the game as moddable as you want to. Does every single part of the game have to be moddable? Do you want every part of the game to be moddable? I think a well-designed modding API (that is supported!) would be better than having to learn the internals of the game in order to mod it. Scripting languages are generally easier than Rust too, which makes making mods (or the base game) easier I'd say.

from citybound.

aeplay avatar aeplay commented on April 28, 2024

The more I think about it, the more I think your dynamic library idea seems feasible. I think the dissection line between core engine and mods can be exactly [kay + monet + some essentials like UI] vs. [game actor defintions]. In the long run I would love to actually develop my own scripting language on top of kay, but that's for later.

from citybound.

aeplay avatar aeplay commented on April 28, 2024

And if you look at files like src/game/lanes_and_cars/mod.rs or any other file containing an actor, you can already see my convention of having a setup function that just takes the actor system as a parameter and then registers its actors and messages. This could very well become the interface for dynamic libraries.

from citybound.

aeplay avatar aeplay commented on April 28, 2024

Could you elaborate on how you would handle mod combinations that affect the same dynamic library though?

from citybound.

mijgame avatar mijgame commented on April 28, 2024

Yep. Don't develop your own language for use as a scripting language for modding though. Using a language that is very accessible to people allows them to be more creative with mods.

from citybound.

mijgame avatar mijgame commented on April 28, 2024

How would mods affect the same dynamic library? If you are using Lua for example, the only thing the mod has access to is the modding API that you expose. I don't want to 'advertise' Factorio or something, I just know that there are very advanced mods for it that work really well. I recommend looking at their API (http://lua-api.factorio.com/latest/) in order to get an idea how they handle it.

from citybound.

aeplay avatar aeplay commented on April 28, 2024

Regarding scripting again:

I just really like about Rust how it's strict Type and Borrowing system saved me from all kinds of run-time bugs, and I would hate to not have that for the game logic.

Regarding mod API:

I really want mods to be able to completely replace behaviour, not just augment it. What if there are two mods, in one cars overtake more aggressively and in the other cars keep more distance in general. Both would have to completely replace the "micro-traffic"-library - how should I know which parts of my traffic simulation should be set in stone and which shouldn't be? And how to combine these two mods for example?

from citybound.

mijgame avatar mijgame commented on April 28, 2024

Scripting:

Core engine stuff should be Rust, as that should perform. Behaviour and game logic is generally defined in scripting languages because it is much easier to define complex behaviour in a dynamic language. If implemented well it can really help with your workflow too. You could make it that a Lua script that you are editing, is reloaded in the game in realtime on save. You can get realtime feedback on what you have written. I believe you have done web development, so you should know how important it is for your workflow to get direct feedback on what you have written. What kind of run-time bugs where you running in to, that were solved by having the Type and Borrowing system?

Mod API:

You don't make a mod completely replace the 'micro-traffic' library. You could make the micro-traffic library expose an API that you provide the default behaviour for. When mods initialize, they could override this behaviour. The last mod that overrides this behaviour 'wins'. You can't combine mods if they are inherently not compatible, the best you can do is generate a warning or error that alerts the user or modder about the conflicting mods. I'm not an expert on this by any means btw, so other people are free to correct me on this.

from citybound.

aeplay avatar aeplay commented on April 28, 2024

Scripting: yes, I would love to have hot-code reload. Mostly bugs like use-after-free or equivalent bugs as well as two parts of the code trying to write/write or write/read the same thing in an order that will produce unexpected results. If in theory I included the Rust compiler in the engine, I could get hot-code reload and use Rust as my "scripting language".

Mod API: I know what you mean, but just by looking at my existing code, I don't see where I would want to draw this line at all. Both small and drastic changes should be possible, and I don't know how to fit that into one "API". Or are we not actually talking about an API but more like a soup of modules which can have submodules, each of which can be overridden at any level of granularity (this seems to be what factory offers from having a quick look)?

from citybound.

aeplay avatar aeplay commented on April 28, 2024

Also, let me just add that I'm very happy about this discussion and that I have some people with relevant background knowledge to figure this out with! :)

I'd also love to hear @martinrlilja's thoughts about what we've covered so far, since he basically started it by laying out options.

from citybound.

mijgame avatar mijgame commented on April 28, 2024

Scripting: use after free and race conditions mean something is wrong with the code in the first place. Needing a other language to not have the problem is evading it, not solving it. 'Use after free' is also a lot less destructive in a scripting language because it would simply be nil / null / 0. Regarding Rust as a scripting language: personally, I don't know Rust super well. The language is very complicated after all. I would seriously consider modding Citybound if it used a scripting language like Lua, JavaScript, Python or C# (look at Mono it is amazing) or similar. If it used Rust I would not. I don't want to fight the compiler, I'd rather have dynamic feedback on runtime. That is very much a personal thing though.

And yes, basically making the game a bunch of 'modules' is how I look at it. That is oversimplification ofcourse. You know how you can override JavaScript functions that are provided by the browser? That would be a way of looking at it. You provide the default behaviour that works 99% of the time, but allow overriding it.

And yes, I love the discussions that are already going on. I think making Citybound open-source is an amazing decision and I'm very interested in the game (been following it for like 1.5 years now I believe?)

from citybound.

mijgame avatar mijgame commented on April 28, 2024

I agree with your plan. Native performance is a very good thing, especially given the nature of the game. But the following things are a must:

  • Runtime discovery, binding / compiling of mods. Allowing users to drag and drop mods into a directory is a good thing. You could even make it a convention to use the .cbmod extension or something, which could make it really clear.
  • Expose helper functions for various operations and things in the game to ease mod development. I think we should strive to not make the modder read the source code all the time in order to figure out what to do.
  • Documentation and / or helper scripts to get up and running.
  • Hot code reload should be a priority really, it speeds up development the moment you get it working smoothly!

Something you want to consider:

  • 100mb downloads on-demand are not a very good idea, since there are a lot of people that don't have good internet or have caps. This is also more of a detail, we should keep the plan straightforward and see to the details later.

The webservice is something that should not be a requirement and should currently have low priority. Modding in the game should not be dependend on the web service, but be enhanced by it. Which is something to keep in mind.

What do you think of this?

from citybound.

martinrlilja avatar martinrlilja commented on April 28, 2024

Sounds like a nice plan. Maybe it would be a good idea to implement a scripting language as an official mod as well? Or at least start debating over a language, as it's probably a bit too early for an implementation before the API's stabilise. Unless, of course, someone wants to go ahead either way. Maybe we could have a separate issue for this?

from citybound.

martinrlilja avatar martinrlilja commented on April 28, 2024

I could get started on the first point (A library for runtime discovery and binding of mod-dylibs), should I create another issue for this?

from citybound.

aeplay avatar aeplay commented on April 28, 2024

Yes please. And I'll leave it up to you if you want to do it in-tree in this repo (kinda like the kay crate) or in a completely new repo. Thank you very much, looking forward to it.

from citybound.

mijgame avatar mijgame commented on April 28, 2024

@chdudek it is never too late to add to the discussion 👍 . And I completely agree with what you say: Rust for the people that want to make complex / core changes, scripting with a good API for the general case.

from citybound.

aeplay avatar aeplay commented on April 28, 2024

I agree that scripting will be important, Rust mods are needed as a first step towards that anyways

from citybound.

tsteinholz avatar tsteinholz commented on April 28, 2024

With the proposed mod system, how do we prevent any operating system from being excluded from a mod? Are there any good cross platform rust compilers, capable of compiling a game that links with native binaries? And has this been tested with CB?

If not there could potentially be a huge mod (like DayZ for Arma) that wouldn't be supported on some platform thus making a cross platform game useless. Even with minor mods, this could inconvenience the player you would want a push and play experience.

from citybound.

chances avatar chances commented on April 28, 2024

@tsteinholz Your concerns are already being considered:

"I don't see where any game code would be platform dependent (except maybe odd stuff ...)"

"somehow build cross-compilation-as-a-service based on the mod-compiler"

from citybound.

aeplay avatar aeplay commented on April 28, 2024

What do you guys think about Gluon as a potential scripting language? I'll let you know what I think later (gotta get those sweet uninfluenced opinions).

from citybound.

chances avatar chances commented on April 28, 2024

I was casually perusing some recent updates to the WebAssembly website and an interesting point in their tooling docs piqued my interest with regard to modding/webservice integration for Citybound:

The tooling we expect to support includes:
...
Compilers for languages which can target WebAssembly (C/C++, Rust, Go, C#) should be able to run in WebAssembly themselves, emit a WebAssembly module that can then be executed.

(Emphasis added.)

I remember (like a year or more ago) @aeickhoff mentioning something about a potential embedded, smaller Citybound web client that users could place on web pages to share snapshots of their cities online. WebAssembly could help make that idea a reality in the future. If nothing else, I know I would be very interested in contributing something like it.

Perhaps a mod could be created that somehow serializes a city for this kind of embedding? But then there's the issue of trying to compile a Citybound WebAssembly/WebGL target...

Apologies if this is off topic.

from citybound.

chances avatar chances commented on April 28, 2024

As always, the genius of @aeickhoff is way ahead of me... 😜

from citybound.

martinrlilja avatar martinrlilja commented on April 28, 2024

I tried this, but with asm.js a couple of weeks ago, but got a lot of weird errors from glium (trying to resolve some function pointers to OpenGL). This is a good starting point if someone wants to take a stab at this: https://users.rust-lang.org/t/compiling-to-the-web-with-rust-and-emscripten/7627

from citybound.

aeplay avatar aeplay commented on April 28, 2024

The modstore proposal will also heavily depend on whatever we decide about mods here.

from citybound.

n1313 avatar n1313 commented on April 28, 2024

A few extra points for consideration:

  1. Are closed-source (precompiled) mods allowed?
  2. Assuming malicious intent of the mod author, is there a way to safely compile Rust code?
  3. Assuming malicious intent of the mod author, is there a way to safely run compiled Rust code?
  4. How will the mod load order be managed? Let's say you have two mods, one paints all cars red, another paints all trucks blue, so depending on their load order you might end with different results.

from citybound.

chances avatar chances commented on April 28, 2024

Expanding on @n1313's load order point:

Apart from conflicts, ensure dependencies are loaded before the mod that depends on them.

from citybound.

aeplay avatar aeplay commented on April 28, 2024

@n1313: regarding 2 & 3 my plan is just manual review of published mods in the official mod store + a disclaimer for users that a mod can in the worst case do whatever a virus can do + maybe sandboxing the whole game process

from citybound.

n1313 avatar n1313 commented on April 28, 2024

manual review

That's not scalable. Time spent on mod reviews won't be spent on main game development.

a disclaimer for users that a mod can in the worst case do whatever a virus can do

So essentially the security of users' machines will depend on Rust skill level of a mod reviewer? :(

from citybound.

aeplay avatar aeplay commented on April 28, 2024

what do you suggest? I can't think of anything that protects 100% from malicious intent

from citybound.

n1313 avatar n1313 commented on April 28, 2024

I'm afraid I do not have a constructive solution to this problem. We should look at how other games do this, but I suspect that the answer will be something like "don't treat mods as first-class citizens, have them crippled by default".

from citybound.

aeplay avatar aeplay commented on April 28, 2024

My suggestion with sandboxing was to basically cripple the whole game by default - the only interaction it needs with the outside world is reading and writing save games. Then, mods can be a first-class citizen again (the plan is to implement all game code as mods)

from citybound.

martinrlilja avatar martinrlilja commented on April 28, 2024

@n1313 Cities: Skylines, which also has mods which can do anything, solves this by not solving it. The game just contains a warning about potentially harmful effects of modding. There is also a reporting system in the Steam Workshop.

On sandboxing, at least on linux it's possible to use ptrace to override the functionality of system calls. It has been used to create sandboxed filesystems for processes. FreeBSD has proper sandboxing. I don't know if something similar exists for mac and windows though.

from citybound.

nickelc avatar nickelc commented on April 28, 2024

Hey, i would like to bring mod.io for mod hosting to the table. The api provides everything needed and i'm working on the modio crate for the rust bindings.

They are also working on an embeddable web app for browsing mods.

from citybound.

intenscia avatar intenscia commented on April 28, 2024

To join the conversation here, I'm founder of mod.io - happy to answer any questions you may have about our open cross-platform mod API. From a tech perspective though @nickelc is the rust expert and a great person to speak with. Looking forward to seeing if we can help the modstore reality come to life :D

from citybound.

Related Issues (20)

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.