Using Mono to avoid depending on the .NET Framework on Windows

At GDC I remember seeing Brendon Chung’s talk about Atom Zombie Smasher, where he mentioned how it runs on Mono, even on Windows. Besides making the game’s behavior more consistent between Windows, Linux and Mac, it also allowed him to remove the need to install the .NET framework before running the game, since he can just bundle Mono with his game.

This is attractive to me for a few reasons:

  • It means all Windows players could play my game just by unzipping it — no separate step to install the .NET framework, no need for an installer to do it for them
  • It means I don’t have to target .NET 2.0 to try to keep Vista/Win7 users from needing to install the .NET framework — I can use nice 4.0 features
  • If I can get my game running on Mono, I can probably run on Linux and Mac as well

So I started looking into Mono. It turns out they have a utility called mkbundle that bundles your app, and all of the assemblies it depends upon, into a single executable, and the only thing it needs to run is a mono DLL you can distribute along with it. The .NET assemblies provided by Mono are MIT/X11 licensed, but the runtime is LGPL, so while you can embed Mono’s System.dll into your executable, you have to either dynamically link to the runtime DLL or otherwise provide your program to users in such a way that they could use a different Mono runtime if they wanted.

Unfortunately mkbundle is kind of broken on Windows right now, a lot of which is due to Cygwin drift since the tool was written. Luckily, it’s not so broken that you can’t fix it yourself. I mostly followed this StackOverflow answer — but there are a few changes I made to make it a lot simpler!

The procedure

  1. First, make sure your app works under Mono on Windows. If it doesn’t, none of this will be any use to you.
  2. Install Mono for Windows from here. Click the Windows button in the top row (the stable release) and choose “Mono for Windows, Gtk#, and XSP.” I used version 2.10.8, I can’t guarantee that anything else will work exactly as described. You can install to the normal directory.
  3. Install Cygwin (UNIX-like environment for Windows.) Make sure you have selected the packages gcc-mingw, mingw-zlib1, mingw-zlib-devel, and pkg-config.
  4. Launch a Cygwin Terminal using the shortcut created by the Cygwin installer.
  5. Navigate to the directory your game assemblies are (e.g. your bin/Release folder.) Note that in cygwin, a path like C:\some\path is expressed as /cygdrive/c/some/path — note the slash direction and the way drive letters work! Backslashes are escape characters in bash so if you just type \cygdrive\c\Foo it thinks you meant cygdrivecFoo.
  6. Create an environment variable $MONO pointing to the Mono installation. On 64-bit Windows use this:
    MONO=/cygdrive/c/progra~2/Mono-2.10.8

    On 32-bit:

    MONO=/cygdrive/c/progra~1/Mono-2.10.8

    The point here is to use the DOS short filename compatibility feature to point to the right Program Files (or Program Files (x86)) directory without creating a path with spaces in it, which mkbundle doesn’t like.

  7. Add Mono’s bin directory to your $PATH so you can run mkbundle:
    export PATH=$PATH:$MONO/bin
  8. Add Mono’s lib/pkgconfig directory to your $PKG_CONFIG_PATH environment variable. Usually this starts out empty so just do:
    export PKG_CONFIG_PATH=$MONO/lib/pkgconfig
  9. Now here is the magic part that makes this far less laborious — specify a value for $CC that invokes the mingw32 version of GCC:
    export CC="i686-pc-mingw32-gcc -U _WIN32"

    See, Cygwin used to bundle a version of GCC that supported the -mno-cygwin flag to produce executables that didn’t need cygwin1.dll. The GCC 4.x it includes does not support it any longer. That is why you have to install the gcc-mingw package. Since some people may also have normal gcc installed in Cygwin, I want to unambiguously refer to the mingw32 version of GCC.

    The -U _WIN32 basically removes the predefined _WIN32 preprocessor definition before GCC compiles the C code that mkbundle generates. The Win32 code path in that generated code is broken right now (it uses an undefined function g_utf16_to_utf8 that looks like it comes from glib.) Luckily it works if you turn off that code path — the only thing you will miss is supporting Unicode command line arguments. If this is a problem you can use the more complicated procedure from this StackOverflow post to intercept the C code before it is compiled & fix it yourself. That post doesn’t describe how to fix the UTF thing, but it lets you edit the generated C code before recompiling it.

  10. Now you can finally run mkbundle. Replace the assembly names as necessary:
    mkbundle YourGame.exe OpenTK.dll --deps -o Output.exe
  11. Copy mono-2.0.dll into the current directory since the resulting EXE you just created depends on it:
    cp $MONO/bin/mono-2.0.dll .
  12. Now hopefully your app will run!
    ./Output.exe

    You just have to distribute the output EXE file alongside mono-2.0.dll and it should just magically work on any Windows PC.

Making a reusable script

I have combined all of these steps into a shell script here: https://gist.github.com/3005371. Once you have this as a script, you can recreate the bundle in one step whenever you want. Note that you will have to customize the script a little for it to work for your exact case.

How big is it?

You may be wondering how big your Output.exe and mono-2.0.dll are, seeing as it’s pulling in a Mono runtime and a bunch of System assemblies and so on.

Well, in my test app, which just uses OpenTK to do some OpenGL drawing, the file sizes are as follows:

Output EXE: 13.4 MB
mono-2.0.dll: 2.6 MB
Both of the above, zipped at highest compression: 5.6 MB

5.6 MB is not bad at all compared to the size of textures and music you are likely to include in a game!

Making it even smaller

If you want the EXE file to be smaller even after it is unzipped, you can pass the -z flag to mkbundle and it will compress the embedded assemblies. (That is what the mingw-zlib* Cygwin packages are for.) This will make the EXE file smaller, although it may make startup times a little slower. That took my example EXE from 13.4 MB to 4.6 MB. Of course, now it won’t compress as much when you zip it.

There are also “linker” tools, like monolinker, that can strip assemblies so only referenced code is used. For example, if I only used OpenGL and not the OpenAL functionality of OpenTK, it could theoretically remove the OpenAL stuff from the OpenTK assembly automatically. In practice, it’s not so simple. I tried using monolinker and could not get it to work — it just made an OpenTK assembly that crashed when you tried to use it. I suspect monolinker got a little overzealous and removed something that was necessary. If I could get this to work it would reduce the executable size even further.

But, honestly, I think the executable is small enough already. Any further compression would be nice, but is not necessary.

Extra DLLs required sometimes?

The TODO file in the mkbundle source suggests that these DLLs may also need to be distributed with your program:

  • libglib*.dll
  • libgmodule*.dll
  • libgthread*.dll
  • iconv.dll
  • intl.dll
  • zlib1.dll

My program does not seem to require them, but if you use more framework functionality they may be required. I can see Atom Zombie Smasher includes some of them (specifically libglib and libgthread.) These libraries appear to all be either LGPL, X11 or zlib licensed. You may want to double check the exact terms of the licenses yourself, but it seems like it will just be fine to copy them out of the Mono bin directory and include them with your app.

Next steps

The mkbundle tool works out of the box on Ubuntu for me, and I am going to investigate the options for making a native-looking OS X application eventually as well.

If I have time I will try to submit a patch to Mono so mkbundle “just works” on Windows (provided a Cygwin install.)

Instantly distracted

So I haven’t worked on Platformer (directly) in a couple days. Spent the past several days working on a C# networking library (something like the basics of Twisted for handling TCP and UDP sockets in an event-based way, so I don’t have to think about threading.)  The plan is ultimately to make a fancy-pants networked debug console for Platformer or other future games.

It’s a somewhat vague idea, but the general concept is that the game could expose a tree of objects with associated properties and commands. The console would be a separate process that connects and lets you browse the tree, view and edit properties, execute commands, and present the game’s log. This would be a more comprehensive version of the debug menu that’s present in Platformer right now, and would allow me to have a richer UI like sliders, color pickers, etc.

Wow, that sounds completely vague and tangential. Way to get distracted, self.

Well hello there

Once again I have forgotten to update this blog in months. Some of you may have noticed that shilbert.com was entirely down for a couple months. What happened was that my web host decided to disappear off the face of the planet; luckily, I was able to get backups from the datacenter the host was using, LiquidWeb. They had my data back to me the night I asked. Classy service.

Anyway.

I have not done an awful lot more with Platformer. The Portal Turret project has been resurrected, and I spent this weekend making my own programmer for the dsPIC33f MCU I am going to use, rather than paying $60 or more for a programming device. I might publish the circuit schematics/Arduino sketch/Python program I made at some later date. I also reverse-engineered the audio-based level transfer system for Bangai-O Spirits for DS, and made a receiver program in C#. This could let people develop PC-based level editors, and also to pass around levels in binary format instead of as MP3′s or YouTube videos. So, some stuff has gotten done, although I want to get back to working on Platformer soon.

void SHilbert::Update(float delta) {

Okay, so the semester started again and now I don’t have as much free time anymore. Which is not great, because when I had free time over winter break I didn’t get much of anything done. Current project statuses follow:

PLATFORMER.

I didn’t work much on this over the break. My laptop is running Linux now because the poor thing is dying and somehow it seems to work alright with Ubuntu (as in, it only freezes intermittently, as opposed to Windows which can’t get through the installer without bluescreening.) So, being that I was away for the majority of my break, and thus using my laptop, which runs Linux, I didn’t get much done on a game that uses XNA. I have done a little more design work but it’s mostly on the silly kinds of details I worry about that noone else is interested in. I’m hoping that eventually I’ll get to a point where I can release a demo (or at least a video) every month or two of the progress, it’ll depend on how classes go.

PORTAL TURRET.

Not a whole lot since the last update. I have some more details worked out for motor control but it’s still all basically resting on fabricating the body at this point. I am going to talk to someone at NCSU about using the school of design’s CNC router to do this. I am also still unsure about how the thing should be controlled – complete autonomy is sort of boring, and adding a proper remote control unit would be a giant pain because I’m not that great at electronics. Besides that, the rest of it is just details, hopefully.

SHILSCRIPT++

I got some work done on this over the break. I’m working on static checking for expressions right now. Basically I need to clean up the classes used for types and implement some kind of overload resolution function. I haven’t implemented overloads yet, as expression static checking isn’t even done yet, but the C# spec defines the available builtin operators in terms of function overloads, and that seems like a clean way to do it. Hopefully I’ll get to codegen sometime this century. Other things that are outstanding are storing location information on AST nodes for error messages with actual locations, and adding memory tracking so I can make sure there aren’t any leaks.

So, that’s the project status. I am feeling kind of crappy recently because I haven’t gotten much of anything done and I feel like I’m atrophying just sitting here not coding anything. Usually when that happens I open up SS++ a little or think about tinkering with FE or low-level rendering, but never get around to it.

HOLIDAY STUFF

I got to see Tim while I was in California. He’s pretty much always up to something and this time was no exception. Here is a brief list of things we did:

  • Spent forever trying to get Defcon netplay to work on a hotel wireless network. Once we finally did get it to work we found out my laptop hard freezes a few minutes into the Defcon stage, so that was kind of lame. Next time I am going to just bring a wired switch so I don’t have to start considering scavenging a hotel ethernet cable to make a crossover cable. Oh, and get a new laptop that isn’t subtly broken.
  • Watched Tim do some parkour crap in public places. I am pretty sure somewhere there is a little kid jumping off his roof because he saw a little Asian man do it at the park.
  • Walked around in downtown Pasadena while everyone was sitting on the roadside claiming spots for the Rose Parade. We were looking for some bizarre kind of shoes Tim wanted but the closest he could find were freeking expensive.
  • Played Megaman X ‘together’ by exchanging the controller. I totally beat Sigma on the first try. I wasn’t so hot at Mega Man X2, though, I had to actually use the boss’s weaknesses against them. :(

The whole thing made me really want to work on FE more, despite already having too many projects and not getting any work done on any of them.

Also, apparently captchas (or the captcha I added) aren’t good enough for comment spam protection, let alone trackback spa protection. I am really getting tired of this.

Fallen Elements & SS++ update

OK, let’s see, what’s new in FE…

  • The type system used for throwing around basic values (ints, floats, pointers, etc.) in the reflection code is much improved. To summarize, StaticType(T) (WordPress is eating my angle brackets, bear with me) implements traits and traits functions for certain basic types, and you can create a DynamicType ‘binding’ of the static type information to pass around at runtime. (StaticType(T)::Alignment becomes dynTyp->getAlignment() where dynTyp is a DynamicType*.) Information about whether types need constructors/destructors/copy operations is included, so you can do things like create properly aligned struct layouts in memory based on purely dynamic information.
  • Implemented a function call system that works off of this, so it’s fairly easy to pass parameters to a function dynamically but also generally without ANY heap allocations — no boxing, pretty darn fast.
  • PyBind (the new binding system works entirely off dynamic reflection info rather than SWIG) is getting pretty functional. Unfortunately most of the classes aren’t currently marked up or designed to work with the reflection system, so that’s an issue ;)
  • Finally shoveled all the C++ reflection-related stuff into a subnamespace (Common::Reflect), which is a lot nicer cognitively I think.
  • Working on a system that should supercede making *actual* scripts for many cases where it’s just value fill-in, and also allow a common base for serializing non-binary data. I could have gone with XML for the format but I ended up writing a parser for what I’m currently calling “def files”, which look very similar to OGRE scripts. It’s much easier on the wrists to write than XML, and simpler to read, but of course the parser isn’t as well-tested as TinyXML yet ;) The reason this is neat is because 99% of the entity definitions Tim wrote in Python were actually just filling in properties, so I’m going to try to direct things towards more of a “property-fill-in” approach than a script subclass approach. (In fact, it would be really simplifying to just throw out scripts entirely — not sure if that’s doable though.) Anyway, we can do several things with a ‘centralized’ definition file system:
    • For named “resource objects”, i.e. things that represent individual, named, unchanging object instances (physics materials, map information), it will use a cache so you can basically go “get me object “, and it will try to locate and deserialize it if necessary, or just return the already-loaded object if it’s in the cache.
    • For “templates”, i.e. object definitions that end up being used to initialize multiple instances throughout the process’s lifetime (ragdolls, UI, entities), you can go “make me an object “, and it should deserialize and fill it in for you.
    • For miscellaneous configuration information (keybinds, highscore, etc.) it should be possible to represent these as normal reflection-enabled Objects and serialize/deserialize to specific filenames directly without having to write any load/save code, just mark up what properties exist.

I’ve also been doing some preliminary work on SHilScript++, and have a small prototype (VERY small — don’t get excited) started in C#. So far the current plan is:

  • ANTLR-generated frontend (grammar almost finalized)
  • Stack-based safe bytecode (like JVM or .NET — compact, easy to generate)
    • Bytecode packages represent an entire group of classes, more like a .NET assembly than a Java .class file
  • Eventually an LLVM-based backend. I might mess around with generating CIL from C#, which might end up being fairly easy because of the similarity between CIL and SS bytecode. (You might ask what the purpose of SS bytecode existing separate from CIL would be in this situation, and the reason is that eventually I’m gonna do this in C++ and won’t have the luxury of .NET just sitting there for me to use. So it has prototyping value, basically.)
  • It’s also pretty easy to implement a “reference” VM for stack-based bytecode, even though it’d probably be hilariously slow.

I’ve been looking at the mcs (Mono C# compiler) implementation some to get a feel for how they organize things, because C#/.NET and SS are “similar” as far as syntax and runtime model. I’ve also been brushing up on my optimization/machine code/compiler building/grammar building skills, which is fun because you get to feel much more smug than normal if you have a reason to talk about pipeline stalls or register allocation or branch prediction.

I’m still in the process of absorbing a minor epiphany I had earlier this month about data-drivenness. You’d think I’d have all of these types of epiphanies out of my system by now, but I suppose I missed this one because it tends to go against certain OO/minimalism ideas. Anyway, the thing I noticed was, it’s way easier to to add a few more properties to a base class and complicate that class’s code a bit rather than than deal with lots of base classes or strategy objects. Another component of it is that it’s kind of an un-mentioned pattern in gamecode to have LOTS of these kinds of properties. A year ago, if I saw that a certain game object in an engine had 50 or 100 properties, I’d have thought someone was just not trying hard enough to get it down to a set of classes with each around 10 or so. However, in the long run, it’s much easier to have one moderately complex class and be able to make 95% of the behavior variations you need by just changing values — no actual “scripting” or subclassing or anything involved — than to go and treat everything that COULD be an object hierarchy as an actual object hierarchy. This also has benefits because if you work on a team with dedicated, non-programmer designers, it’s way easier to comprehend setting values to change behavior than defining logic. In summary: when you see “data driven”, think property/value settings in files before actual logic scripts in files. And when you think of class customization, think small, shallow hierarchy that can allow for most of the detailed variations just by changing properties, not by doing virtual function overrides. I’m not sure if that makes sense to anyone, but it’s an idiom I seem to have zoned out on and now I’m happy I found it, because it makes a whole lot of things I see somewhat more rational.

Complexity is getting to me

At the moment, FE is something like 30,000 lines of C++ with some extra MaxScript, Python and SWIG interface scripts. I think we’re using about a dozen file formats for resources, and if we’re not now we will be soon easily. (Let me count for a moment: .mesh, .material, .program, .compositor, .particle, .cg, .png, .tga, .fnt, .py(c), .femap, .femap.xml, .physics, .cfg (OGRE’s), .cfg (ours), .con, logfiles… okay, so that’s about 16.) That’s easily gonna be in the low to mid 20′s by the time things are done. (We’re going to have a package manifest, separate map metadata/rendering/collision/entity layers, cinematics, savegames…) The point is, there’s a bunch of shit going on and you can get design vertigo if you try to think about it all at once instead of adding things one-at-a-time until it’s complete.

I also noticed that we’re ending up with several separate file hierarchies that I’m gonna have to document… 1) the source tree layout; 2) the installation layout; 3) the user profile layout; 4) the package “pattern” layout (standard subdirectories etc. for resources in packages.) If you take into account that the installation layout might end up with a Linux and an OS X variant, and that the source tree would have to have build scripts for both of those cases, that alone is gonna be a few days of work for each case to set up build & install behaviors.
I guess I’m just feeling scattered from not being on a real overall plan at the moment. There’s a goal to get the engine ready to do some kind of a demo by December but that’s very vague and leaves me with a lot of flexibility as far as what needs to be in place by then. I think the most prudent plan would probably involve getting the entity system improvements done (adding nice light & camera support, cinematic animation, trigger/raycast-only collision volumes, and rudimentary load/save and possibly network ability) whilst actually using them to implement some basic behaviors in test maps so they can be proved to actually work.

I do still need to make several decisions regarding the entity system, such as how to actually set up cinematics (the current plan is to allow assignment of controllers to property slots, and use this to hook entities up to sampled movement curves from 3DS), how to organize the volume system (some volumes, like the hit-volumes for limb parts on entities, will actually change from raycast-only volumes to physics bodies, which ight mean the collision volume can be in a “physics” or “raycast-only” state, which is very weird), how to set it up so you can set up complicated, animating entity groups that only save the minimum amount of data when serializing to file/network (I have a few ideas on this, but I’ve not gotten to implementing them yet), and how to actually interface this with Python scripting. I also need to add more UI element types and improve UI scripting ability so scripts can actually create proper HUDs.

On the plus side, in the past week I’ve done some overhauls that were long overdue, such as adding a proper ingame console, adding proper keybind support (which also means player movement is driven by changes to cvars), adding a less primitive (and not Python-bound) configuration system, and moving all of the user profile files to a user directory instead of splattering them in various places in the installation tree. (This also means that theoretically Tim and I can make personal configuration changes without them ending up in SVN and resulting in a ping-pong config tweaking effect. This happens quite a lot with the default map setting and things of that nature.) The OGRE configuration dialog, which I intend to remove entirely in favor of our own in-game UI, can now be disabled if you don’t want to change config on startup by passing +ogreconfig 0 on the commandline (the commandline more or less works like Quake 3, and is basically just an interface to the console.)

I haven’t done much extra work on the LLVM-backed scripting engine concept. I’ve got more pressing stuff to work on with FE. I also haven’t submitted a patch for LLVM to compile properly on VS7.1 either :P Nor have I done anything on EL with Pouya for a good month, I think.

I think one of the things that’s bugging me about FE is the lack of visual changes recently. I’ve been making big, important changes to the engine side, but it’s still just the same handful of maps with enemies that are dumb that don’t have collision so you can’t shoot them. I spend a lot of my time wishing I was making something more visually impressive (or making tools to make more visually impressive things, which is more classic SHilbert.) I think FE definitely has the capability to be impressive, but of course it’s all C++ and any effects I’d want to do have to be possible within OGRE’s framework, which isn’t always the case. I still need to add a proper lighting system and set up a set of shaders for characters and map geometry that look nice and allow for all the different effects I’m likely to need.

October is starting soon, so the whole Halloween atmosphere is starting to creep into grocery stores and newspaper ads around here. If I didn’t have experience showing that it’s incredibly unlikely for such a thing to work *cough*, I’d make a small game for Halloween… I’m still toying with the idea, but I’ll probably be too lazy to actually do it. Plus I’ve got way too many other games I’m supposed to be working on anyway. Maybe I’ll just make some kind of pumpkin-head mod for FE or something.

Homebrew LLVM 1.8 VC8 patch (for a quick-fix moderately up-to-date LLVM)

I spent an evening a few days ago getting LLVM 1.8 to build and run properly with VC8, because that’s pretty much my target platform at the moment. (See this thread on LLVMdev.) Some of the things I fixed are already fixed in CVS according to Chris Lattner, but I haven’t submitted any patches for the other fixes yet. I’d like to make that patch the ‘proper’ way and get a machine with VC 7.1 set up so the projects are still VC 7.1 and you can just upgrate to use them in VC8, but I haven’t gotten around to that yet… anyway, if you just want it to build on VC8, download this patch and apply it.

If you have Cygwin, the way I suggest doing this is:

1) Download the LLVM-1.8 source from llvm.org & extract
2) Extract llvm-vc8.diff and move it in the parent directory of the ‘llvm’ directory
3) cd llvm
4) patch -p1 -i ../llvm-vc8.diff
5) Download Flex and Bison from gnuwin32 and add the directory they’re in to VC8′s directories list (I downloaded the zipfiles and extracted them under win32/tools/, so you have win32/tools/bin/bison.exe, etc.)
6) Open win32/llvm.sln and build it (if any errors occur, try building again in case it’s a dependency ordering issue)

Theoretically this is all that you need to build; I haven’t had time to test it from scratch, please send me a comment if it doesn’t work.

Revenge of SHilScript?

Okay, so, every now and then I get a weird idea in my head and I sort of start testing the waters on a new project. This month’s crazy idea appears to be a JIT-ed scripting language similar to UnrealScript. The recent development on FE’s entity system has been fairly majorly influenced by Unreal; I’ve done a lot of reading of the Unreal Wiki. But it would be very nice to have a clean, fast, safe language with builtin persistence and network replication capabilities, rather than having to kind of ‘bend’ C++ and Python to work with me on those points. (Believe me, there is a lot of bending involved.)

Of course, the problem is that it would take freaking forever to actually make something like that, let alone test it properly and hook it up to any kind of game engine. Luckily for me there are some pretty good tools like ANTLR (which is basically similar in purpose to Flex and Bison all in one) and LLVM (a ‘compiler infrastructure’ that basically means I get JIT for nearly free.) So really I just need to write the “middle end” of the compiler — turning a syntax-tree-like structure into an intermediate representation to send to LLVM. Then, of course, there’s the need for a basic standard library for the thing, and some way of connecting it to existing C++ code… oh well, I don’t expect it to be finished anytime soon anyway.

As for the language itself, the current plan is to lean towards the static rather than the dynamic. This lets it make use of JIT fairly well and means scripts can be very fast; think along the lines of C# or Java for a basis. LLVM even supports SIMD code generation (although I haven’t tried it yet), so potentially vectors and quaternions and matrices and so on could be quite quick to compute with. Additionally, I would like to try to take a whack at solving some of the common issues with creating a game from the language-level. The list of potential candidates is pretty long, but it includes things like:

  • Objects are persistable “by default” — e.g., you would mark a class member variable to NOT save it, rather than have to mark it for saving. Same goes for networking exposure. The language runtime would have builtin support for saving whole trees of objects to and from file or replicating over the network live (probably using enet.)
  • Powerful concept of “defaults” for a class, so as to avoid needing to save or replicate most of the information in any class instance. Ideally, this includes “owned” class instances as well, so you could build fairly complex entities and only have to serialize a small amount of data to describe it. Additionally, a controller system for linking values to value-sources could be tied into this so values that are really generated anew each frame don’t need any kind of serialization.
  • An event system that’s easy to use and interacts well with persistence & code modification. Basically, this means that the “normal way” of listening for an event is to create a block in the class body that specifies an event name and a member variable name. This means that you don’t have to explicitly add listeners for when you modify object references (it would do it for you), and you don’t have to serialize a list of listener objects like you would if the listener system was totally dynamic. You could change the code to listen for a totally different event from a member, and it would magically work when you reload a savegame.
  • Sandboxing. Scripts should not only be isolated from causing any real damage, but they should also be instrumented to avoid code-bombs like infinite loops, huge memory use, malformed scripts that blow up the parser, etc. This means you’re safe to download code from a server for multiplayer, which is very useful.
  • An API for reflecting script code from C++. This would allow map editors to display the list of properties some type of class has for when you’re placing entities, or overlaying editing or statistics screens in realtime while playing the game.
  • A code reloading system. Currently the plan for this is to do an in-memory ‘save point’, dump the old code, load the new code, and restore the save point. If the load/save behavior is sane, then you could theoretically edit your code pretty close to on-the-fly as the game is running. Given that modern games usually have moderately annoying load-times, this could remove a big psychological barrier to debugging and testing.
  • Ability to mark class member variables as “localizable” (like UnrealScript *whistle*.) Basically, this means that a certain variable would show up in a localization editor automatically. I would anticipate this would mostly get used for strings, but I suppose one could localize all sorts of things.
  • Another UnrealScript copycat: config variables, which act like static class variables whose values are tied to configuration files.
  • Unicode strings from the get-go. This is a giant pain in the ass to change if your code doesn’t start off with it.
  • “First-class” vectors, quaternions, matrices, and a nice standard math library. This stuff is so common that there’s no reason for it to keep getting re-coded.
  • A source-level debugger would be nice, but that is a big project in and of itself.

So, yeah, I’m pretty much insane. I’m planning on slowly attacking it in stages — such as getting basic classes / functions / expressions done, and then moving on to adding the more cushy features like persistence, replication, events, code reloading, etc. And of course the real trick is remembering to focus on the more immediate things like school and Fallen Elements in the meantime.