Jump to content
Sign in to follow this  
  • entries
    191
  • comments
    861
  • views
    117734

Two Things

Sign in to follow this  
Mithrandir

94 views

First, I've solved my XML dillemma, I think. This format seems to be the best mix of data minimalization mixed with a proper standard formatting:



"1">

"name">MITHRANDURDUR
"password">72B3F57E935DADD36ECA5207C34D91B05590325252C63DAEF2083051C62311B79089C300A1BFA3F80EB620F105A3730C70BC493C10AFCF46F94725F58DC2BA40
"lastlogin">2006-02-12 5:46:38 PM
"allowedcharacters">2
"banned">True
"canaddscripts">False
"canadddata">True
"canmodifyaccounts">False
"lol">LOL
<Double name="this is a really long ass data variable name lol">3.14158Double>


"2">

"name">Homer Jay Simpson
"room">0
"account">1
"dormant">True
"template">20
"snarky">True
"hp">80
"max hp">100
"mana">20
"max mana">20
"resting">True










The rules are:

The tag names will be type names, so we know how to decode everything under the tag, be it simple data, or an entire tree of sub-tags. This will eventually be integrated into my engine by way of a registry.

ie:

XmlDecoderRegistry.Register( "Account", new XmlDecoderDelegate( AccountDecoder ) );

or something like that.

The second rule is that attributes are to be used for figuring out how to create the data element. IE: entities will have ID attributes, because they are required by the entity constructors. Base data elements will have the name of the element in the attributes, because we need to know where to put that element when it's read.

I like it, it's smaller than the previous version, and it seems to work well.




Secondly

Another big development over the weekend is the scripting engine. It's freaking cool.


CodeLoader loader = new CodeLoader();
loader.LoadCode( "hello.cs" );
MessageScriptAdapter h = loader.CreateScript( "BetterMUDScript.Hello" );
MessageScriptAdapter g = loader.CreateScript( "BetterMUDScript.GoodBye" );

string message;
message = h.Message(); // "Hello!"
message = g.Message(); // "Good Bye!"

loader.LoadCode( "hello2.cs" );
message = h.Message(); // "Hello, dudes!"





This simple example demonstrates the ease of the engine. Firstly, all you need to do is send it a file to load, and it will load the file for you. At the moment, there is no mechanism for reporting errors or other fancy things.

The engine will load the .cs file, and put it in its very own assembly (in memory). It goes through every exported type in the script, and takes note of every class that inherits from "Script", and puts them into a registry. The code engine will only allow you to instantiate classes that inherit from "Script", though it will still compile classes that aren't scripts.

The scripting engine works using an adapter pattern for each script. When you request a script from the engine, it instantiates a new script, and packages that script up into an adapter object (MessageAdapter in this example). For all intents and purposes, you will interface with that adapter object.

Now here's the cool part.

See the last two lines? It loads a file "hello2.cs", which contains a newly updated version of the BetterMUDScript.Hello class, which returns a different string.

When the code engine loads that file, it notices that the class "Hello" has been loaded before, so it looks to see if there were any adapters registered for the old version. If so, it goes through every adapter and updates its script object, so the next time you use the adapter, it will use the newly updated version.

Another cool thing is that when a new script is loaded, the engine will go through the old script and copy over any data that may exist.

This was an issue that was never resolved in BetterMUD 1.0. I use reflection to do this, which can be slow, but I'm not that concerned, because loading new versions of scripts isn't going to be something that is going to be happening often.


The coolest part is that it even tries to coerce data into a new type if the type changes.

For example, if the old version of Hello has an int named "x", and the new version has a float named "x", it will copy the int value of x into the float x. It works the other way around too, but you'll lose precision.

At the moment, the engine only copies datatypes that are considered "basic types", which include all integral types, chars, floats, doubles, decimals, strings, datetimes, and timespans. For some odd reason, .NET doesn't think a TimeSpan is a basic type, so I had to go through some trouble to create a flexible converter class, which essentially does everything that System.Convert does, except it works with TimeSpans too.

On the plus side, Tangential.Utilities.Converter is extensible. You can add custom converters to it as you see fit:


Converter.RegisterConverter( typeof( string ), typeof( TimeSpan ), new Converter.ConvertDelegate( StringToTimeSpan );
Converter.RegisterConverter( typeof( DateTime ), typeof( TimeSpan ), new Converter.ConvertDelegate( DateTimeToTimeSpan ) );
Converter.RegisterConverter( typeof( TimeSpan ), typeof( TimeSpan ), new ConverterConvertDelegate( Identity ) );



TimeSpan ts;

ts = (TimeSpan)Converter.Convert( "00:10:15", typeof( TimeSpan ) );
ts = (TimeSpan)Converter.Convert( "01:10:00", "TimeSpan" );
ts = Converter.ConvertTo( "20:20:06" );






The system automatically handles ways to convert types based on
1) dynamic typing
2) dynamic typing based on a string name (grin)
3) static typing using generics at compile-time

So it's pretty cool.

And it works.




The only caveat with the system that I have is that coding adapters for each script type could be a pain in the butt. I can't think of any simple way to generate an adapter class in C# that automatically wraps around another class with the same interface. I could use reflection, I suppose, but I think that's a little overkill.
Sign in to follow this  


2 Comments


Recommended Comments

That's pretty neat....

I haven't really had time to check it out yet, but this also looks interesting.

Quote:
The only caveat with the system that I have is that coding adapters for each script type could be a pain in the butt. I can't think of any simple way to generate an adapter class in C# that automatically wraps around another class with the same interface. I could use reflection, I suppose, but I think that's a little overkill.
Something like this might work:
// hello.cs

using System;
public class Hello : IAdapter // IAdapter is your crazy adapter interface
{
public string Message
{
get
{
return "Yo holmes, what's up?!!!! I like caek.";
}
}
}

Share this comment


Link to comment
Cool. Graft an isometric Flash interface on the front-end (ala Penguin Chat), and you have an MMORPG.

Share this comment


Link to comment

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!