tkrajcar / carbonmu

CarbonMU was experiments towards a general-purpose, extendable MUD/MUSH server written in Ruby.
MIT License
13 stars 5 forks source link

Primitives discussion #8

Closed tkrajcar closed 9 years ago

tkrajcar commented 10 years ago

I'd like to get some thoughts from those who might be interested about the 'primitives' that should be supported out of the box - these are the data types that every game should have. For example, MUSH/MUX use 'Player', 'Thing', 'Room', and 'Exit' - with players and things being pretty damn similar. MUDs have items, NPCs, players, rooms, etc. Some MUD drivers also have 'blueprint items' which are interacted with slightly differently than regular items, and so on.

Obviously, as a fresh engine, we have the power to completely rethink this. I don't want to put more datatypes than we need to in CarbonMU core since part of the focus of this project is to build something modular - something like 'weapon' is too game-style-specific IMO - but I've also been building exclusively MUSH/MUX/MUSE games for 20 years, so I could use some input on what other core primitives we should support.

It feels to me like the traditional four (Player/Thing/Room/Exit) are a lock, but I'm open to disagreement, and also any new ideas. Just comment.

tkrajcar commented 10 years ago

tagging @nevern02, @marsol0x, @gtaylor, @wedgemartin

two-first-names commented 10 years ago

One thing that I would suggest you think about is using the Entity-Component model. I.e. all your MUD objects just basis 'entity' objects in code, with a set of components added to them. Components can be as simple as a Stat object, which holds a min and max value along with the stat's name.

Language agnostic OO code to follow: Entity e = new Entity e.addComponent("health", new StatComponent(max, max)) e.getComponent("health").current-- etc...

Other ideas for components could be for storing a player's socket or specifying that it has an inventory and holding the list of other entities the entity holds. This model allows for much quicker prototyping of MUD entities than a typical inheritance or primitive system would.

gtaylor commented 10 years ago

FWIW, Evennia has great success with the traditional four, despite not catering to MUX/MUSH admins, and not being a MUX/MUSH itself. While it'd be possible to get more granular and more flexible, we have found that simplicity is a huge feature in itself. If it takes more than a paragraph or two to describe your object model, it's probably too purpose-specific for a general-purpose codebase (assuming that's what you are building). In our case, giving them the basic four types and letting them create sub-classes has covered pretty much all of the usage cases.

The only weird case that is part of our "batteries included" is comsys channels. They have their own separate table in the DB, but aren't represented with in-game objects. We don't have MUX/Penn's notion of an optional channel object for locks and stuff. That always seemed clunky to me, so I opted for a different approach.

As a final general note, you'll be competing with a ton of other Ruby/Python/interpreted codebases that have sprung up. You already know this, but simplicity, ease of use, and excellent documentation are the only way to get any kind of adoption. Even with those things, it took well over two years for Evennia to grow into the success it is today (I think we are on year four or five now?). Conceptual and technical simplicity are two of the most important features for a general-purpose codebase.

tkrajcar commented 10 years ago

Thanks for the suggestion, @jrobertsgb. The more I'm reading about the entity-component model, the more it seems like a natural fit for how many MU*s structure their data, and I really like the amount of material I've been able to find on how it's used by other game developers, including complex MMOs. I can see how a light framework that provides some basic functionality (templates, aspects/classification indexes, etc) could be very workable. Definitely something to continue to investigate.

I do also agree with @gtaylor that ease of use can be a very strong differentiator, but there's also something to be said for solving the same problems in different and new ways to grab market share, especially since my primary motivation with this is self-use (dogfooding) and education, not just trying to make something that everyone else in the world wants to use immediately.

openmailbox commented 10 years ago

Components are always good, but I also vote for a good type object implementation. If I fork your codebase to make my own game, I want to create my weapon class, and then use json or some other nice exchange format to describe the stats of my weapons which are then loaded into memory when the server starts. Using type objects allows for this at a very general level. And you can use them yourself for the most generic of objects. A room is a thing. A player is also a thing. Thing is your type object. Room and Player are your implementations of the type. This also lets you avoid the slippery slope of using inheritance for game types.

There's a great chapter on implementing this in a game here: http://gameprogrammingpatterns.com/type-object.html

tkrajcar commented 9 years ago

Thanks to everyone who weighed in on this discussion. I'm back working on advancing CarbonMU again and am turning my attentions to data modeling. After quite a bit of thought, I've come up with a couple decisions, some of which contradict previous information and some of which align well. Consider these an open RFC if you're interested in weighing in, but I'm feeling fairly good about these so far.

openmailbox commented 9 years ago

:thumbsup: for picking one thing to standardize on. Don't try to be All The Things.

tkrajcar commented 9 years ago

OK, the basic primitive classes along with their relations to each other were implemented in 048a10f271dd4b0ce28d87e21e28b3579d64ccc4, so closing this discussion issue out.