26 Sep, 2013, Sorressean wrote in the 1st comment:
Votes: 0
Hello all:

I've been tossing around the idea of cleaning up socketmud++–it's kind of messy and seeing stuff like comments to tell you what header files are included can be a bit rough.

Part of the cleanups though were less pedantic and more modern–to take advantage of some better coding:
  • Add more comments/documentation

  • Clean up use of iterators to use c++ 11's new ranged loops

  • General code cleanups (pass most std::strings as const std::string& for better performance, add const to method declarations that can obviously use const


On top of these changes, I had a question. when I started my own mud, one of the issues I had to deal with was serialization–I never really cared for the diku-style serialization and settled on XML. XML is kind of big now and it's going to take a lot of disk space–something I'm kind of regreting. Without adding any external libraries as dependencies, I'd like to find a good medium for serialization–thoughts?

I ask this because I'd like to take socketmud++ past a simple server and kind of make it do everything Socketmud2 does maybe with a few extra nifty features. The end result is that I'd like to give people a decent c++ base to start from rather than just totally barebones.

Thanks,
26 Sep, 2013, Sorressean wrote in the 2nd comment:
Votes: 0
I also created a github repo and started work:
https://github.com/sorressean/socketmud0...
26 Sep, 2013, quixadhal wrote in the 3rd comment:
Votes: 0
XML is evil. :)

I always suggest using JSON instead of XML, unless you really have some need for all the extra complexity… Most of XML is just bloat.

Also, while you can certainly just include a JSON parser in the package, what's the deal with not using external libraries or dependancies? This is 2013, not the stone ages where it was even slightly difficult to find or install a library. Re-inventing the wheel is a good way to ensure nothing ever gets done.
26 Sep, 2013, plamzi wrote in the 4th comment:
Votes: 0
quixadhal said:
XML is evil. :)

I always suggest using JSON instead of XML, unless you really have some need for all the extra complexity… Most of XML is just bloat.

Also, while you can certainly just include a JSON parser in the package, what's the deal with not using external libraries or dependancies? This is 2013, not the stone ages where it was even slightly difficult to find or install a library. Re-inventing the wheel is a good way to ensure nothing ever gets done.


I second quix's post, and would like to add that if disk space is a concern (equally strange in 2013), there's also the option of sticking to XML but compressing on the fly (e. g. a minimal zlib implementation). It would be nice to make that user-configurable though, so people who don't have space concerns can still edit their files easily in external apps.

On the general topic of making SocketMUD less barebones, are you planning to add big features? If so, which ones? Just curious.
26 Sep, 2013, Sorressean wrote in the 5th comment:
Votes: 0
Hello:
I don't mind including external libraries, but I don't like having to grab a library every time I grab a new mud engine. Maybe I can just bundle something small in. I've seen some JSON parsers that use boost::spirit, but I'd like to avoid that if possible since that adds another library to the chain. What options are there for something like this? I'm perfectly happy with sticking to json.
26 Sep, 2013, Kelvin wrote in the 6th comment:
Votes: 0
Or use sqlite. Freaking fast, runs on just about everything.
26 Sep, 2013, quixadhal wrote in the 7th comment:
Votes: 0
http://www.json.org/ lists 13 different C++ JSON implementations. libjson seems pretty simple and was updated a few months ago, and it works with either C or C++ (different interfaces to the same code).

JsonCpp also seems reasonable.

sqlite solves a different problem… I believe the idea here is to easily serialize data without having to write code to read and write it. An object interface to sqlite might do this, but AFAIK, you end up still having to write queries which defeats the purpose of serialization.
26 Sep, 2013, Kelvin wrote in the 8th comment:
Votes: 0
Why is it a different problem? Aren't we talking about storing rooms/objects/mobs/etc? I'm using SQL to do that right now and it's been pretty awesome.
26 Sep, 2013, Idealiad wrote in the 9th comment:
Votes: 0
I'd like to suggest trying something a bit different and packaging the base as a VM container. Maybe using Docker. Then all your dependencies are assured. If you use Docker it should be fairly lightweight as well.
27 Sep, 2013, quixadhal wrote in the 10th comment:
Votes: 0
Kelvin said:
Why is it a different problem? Aren't we talking about storing rooms/objects/mobs/etc? I'm using SQL to do that right now and it's been pretty awesome.


When you change your data structure, do you have to (by hand) change your schema and your loading/saving code? If so, then it's a different problem. Using a serializer, you push in a data structure and call "encode_json()" on it, that gives you a single string you can write to a file, push into a table, do whatever with…. and likewise, decode_json() will restore a data structure from such a string.

In most modern languages, decode_json() creates a proper object for you as well. In C, the best you can hope for is that it will automatically allocate memory for everything. But in any case, the point is you shouldn't have to fiddle with code just because you decided to add "eye color" to your NPC data structure.

Personally, I've grown to hate C++, and even C, because it makes things like this three times as hard as it should be.

I'm guessing Sorressean is probably using C++ from comfort, or a silly idea of it being more efficient (as if that matters for a text MUD on today's hardware), but I'd actually rewrite it in java. You'd keep the same basic "feel", but without all the memory management headaches, with a real string type, and with dynamic data types available.
27 Sep, 2013, plamzi wrote in the 11th comment:
Votes: 0
quixadhal said:
Using a serializer, you push in a data structure and call "encode_json()" on it, that gives you a single string you can write to a file, push into a table, do whatever with….


I think writing serialized objects to a database is an interesting option for MUDs because many objects just need to be stored and fetched as they are. Of course, for those you can just use a good ORM; I'm sure there are many for C++. It's more involved than using a JSON library and writing your own minimal read/write methods, but if the ORM is pro-grade, it may actually make your code more readable to enthusiasts: modifying data structures may be easier, not to mention the advantages you gain from being able to merge objects and query across them as needed.

Of course, all that means you have to add dependencies. As well you should :)

quixadhal said:
…I'd actually rewrite it in java. You'd keep the same basic "feel", but without all the memory management headaches, with a real string type, and with dynamic data types available.


This is offtopic, of course, but why Java? Aren't there several codebases written in Java already?

I would actually pick a scripting language (it's one of my secondary projects) because they also deal away with any need to re-compile.
27 Sep, 2013, quixadhal wrote in the 12th comment:
Votes: 0
plamzi said:
This is offtopic, of course, but why Java? Aren't there several codebases written in Java already?

I would actually pick a scripting language (it's one of my secondary projects) because they also deal away with any need to re-compile.


I was going to say Perl, but figured everyone would run away screaming. :)

There are other projects around, but one of the nice things about socketmud is how simple it is. Most of the other projects seem to be trying to be too much. There is "rocketmud", which is mostly a straight ruby port of socketmud. I could see perl, python, java, maybe even lua as reasonable languages to make a tiny mud base with.

Java has a couple of advantages, in that there are already nice IDE envionments to work with (Eclipse, IntelliJ, etc), and if you wanted to make an android client, you can reuse code that you might be using in your server.

Not sure compiling really matters much these days. Given JIT compilation and whatnot, there's not much difference between typing "ruby foo.rb" and "javac foo.java && java foo.class" or whatever… your interpreter is doing half the work as it parses your script anyways, and java seems to be able to recompile/extend itself on the fly as well.

Mostly I just hate C++ for working with text, and wish it would die in a fire. :)
27 Sep, 2013, Idealiad wrote in the 13th comment:
Votes: 0
Wait a minute, how does serializing objects to json save you from migrations? What happens when you change your classes and want to read in old version of objects? If you just serialize out data, why not just 'serialize' data to a database?
27 Sep, 2013, Runter wrote in the 14th comment:
Votes: 0
Idealiad said:
Wait a minute, how does serializing objects to json save you from migrations? What happens when you change your classes and want to read in old version of objects? If you just serialize out data, why not just 'serialize' data to a database?


Yeah, responsible devs are going to need database versioning regardless of the format.
27 Sep, 2013, quixadhal wrote in the 15th comment:
Votes: 0
It depends on the language, actually.

In perl/python/ruby, when you serialize an object it saves it to disk with named fields. When you deserialize it, it creates a new object with those fields filled out to their stored values. That means any NEW fields you added to that object type since saving will have their default values. As such, unless you change what the data means, you don't NEED to care about missing values. You might want to (depending on your data), but nothing is going to explode or stop working because of it.

C and C++ may be different, because they require you to fix data types at compile time. One would assume a good serialization library would still instantiate a class with "new", and thus still acquire default values for fields not present the saved data chunks… but I can't speak from experience on that.

The point is NOT to have to write code to write out data, nor to have to write more code to read it back in.

As Runter said, you might want to tag every object with a version identifier, because if you *DO* make changes that require translation from one version to the next, reading in an object and then querying the version can give you a hint to call a conversion/update routine on it to adjust the data according to the new model. But that's a different thing than constantly re-writing loading and saving routines.
28 Sep, 2013, Kelvin wrote in the 16th comment:
Votes: 0
quixadhal said:
When you change your data structure, do you have to (by hand) change your schema and your loading/saving code? If so, then it's a different problem. Using a serializer, you push in a data structure and call "encode_json()" on it, that gives you a single string you can write to a file, push into a table, do whatever with…. and likewise, decode_json() will restore a data structure from such a string.


This can actually end up being more of a mess, since you then need to start handling the different previous "versions" of the "schema" in your application, instead of just fixing it in one shot with a migration. Dealing with changing document structures in JSON dumps over time can be a pain. A lot of the time when you are schema-less, you end up doing a lot of parsing/enforcement in your application instead (which stinks).

Sorressean, give it a look. There are lots of easy SQLite and C++ tutorials out there. You may prefer it if you'd like to have the option to enforce certain things at a schema level, while still retaining the ability to store JSON or other structured data. I'm doing a project now where stuff like the room name, description, and other system level things are stored in columns, but free-form attributes are stored as JSON within another column. I like having the guaranteed structure on my core fields (name, description, etc), while mixing in stuff that doesn't need to follow a set layout.
28 Sep, 2013, Tyche wrote in the 17th comment:
Votes: 0
C and C++ can be just as runtime dynamic as any other language.
Just implement an interface using a similar indirection built into those languages.

For example:
typedef enum Type {INTEGER, STRING, LIST, MAP} Type;
typedef union {
int i;
std::string* s;
std::list* l;
std::map* m;
} Values;
class Value {
Type type;
Values v;
};
class SomeObject {
std::map<std:string, Value> attributes;
};


Attributes can be serialized to any backend storage that supports tuples.
You can add or delete schema at runtime and serialize with no need for versioning.
28 Sep, 2013, quixadhal wrote in the 18th comment:
Votes: 0
Yeah, because having to typecast a union into the desired type is something I really want to do for every line of code that touches it… I guess that's dynamic, kinda, for strange definitions of dynamic. :)

My favorite example of dynamic classes was in perl. A coworker and I came up with a database system, and we really wanted to use various database tables as class objects in perl ( IE: foreach ($customers->get({ last_name => "smith" })) { $_->salary *= 1.02; } ), but we really didn't want to have to muck with the code to make that work, every time somebody changed the schema.

So, we came up with a "Table" class that allowed you to do simple queries like that, as well as doing more complex queries by passing a full SQL select statement. It did updates in a similar fashion (you could just change the values in the hash, and it would push the changes to the DBI layer). Finally, you could change the schema by adding (or removing) hash elements and calling an update routine on the table object.

While not quite fully an ORM system, it gave me new respect for dynamic languages, and I'd hate to have to try to implement something like that in C++.
28 Sep, 2013, Tyche wrote in the 19th comment:
Votes: 0
I can't imagine doing that.
12 Nov, 2013, Nathan wrote in the 20th comment:
Votes: 0
quixadhal said:
Kelvin said:
Why is it a different problem? Aren't we talking about storing rooms/objects/mobs/etc? I'm using SQL to do that right now and it's been pretty awesome.


When you change your data structure, do you have to (by hand) change your schema and your loading/saving code? If so, then it's a different problem. Using a serializer, you push in a data structure and call "encode_json()" on it, that gives you a single string you can write to a file, push into a table, do whatever with…. and likewise, decode_json() will restore a data structure from such a string.

In most modern languages, decode_json() creates a proper object for you as well. In C, the best you can hope for is that it will automatically allocate memory for everything. But in any case, the point is you shouldn't have to fiddle with code just because you decided to add "eye color" to your NPC data structure.

Personally, I've grown to hate C++, and even C, because it makes things like this three times as hard as it should be.

I'm guessing Sorressean is probably using C++ from comfort, or a silly idea of it being more efficient (as if that matters for a text MUD on today's hardware), but I'd actually rewrite it in java. You'd keep the same basic "feel", but without all the memory management headaches, with a real string type, and with dynamic data types available.


There's already a JSocketMUD (SocketMUD in Java by the original author), but it's really barebones even compared to the C/C++ versions.
0.0/20