Week of 7/21/2013

Your chance to hear me complain

Week of 7/21/2013

PostPosted by Railboy » Sun Jul 21, 2013 8:46 pm

Aaaaaand we're off! This will be a challenging week; we'll see how it goes.
Language is to the mind more than light is to the eye.
User avatar
Railboy
Developer
Developer
 
Posts: 1830
Joined: Mon Jul 15, 2013 10:46 pm
Location: Seattle, WA

Re: Week of 7/21/2013

PostPosted by Railboy » Mon Jul 22, 2013 4:28 am

Whew! Yesterday's big lore push gave the Bards enough momentum for me to step away and focus on code for the first time in a long time.

The topic of the day is mod support. There are two kinds of mod support in Unity - the kind where users can mess with configuration files, and the kind where users can actually write new scripts.

I'm all over the first kind. With the exception of terrain data (which I'll get to later) all the objects in a FRONTIERS scene* are just placeholders with instructions that the GameManager uses to load XML files, which are themselves just instructions for configuring game objects. Meshes and textures for structures, cities, characters and so on are either pulled in directly from Resources or are generated using prefabs / pieces of prefabs in Resources, then configured using the data from the XML file by a set manager classes.

*(I may just ditch Unity scenes altogether and save world configurations as XML too, though you'll still use the Unity Editor to create & edit them.)

Since assetbundles allow me to load scenes from outside the build players can muck about with configuration files for paths and structures and what have you using the Unity Editor, create a new scene where these objects are placed, lump it all into an asset bundle and voila, you've got a mod - everything from paths to cities to quests to dialog will be totally new.

I also think this will cover texture packs, though I haven't tested this yet. I will have to write a system that looks in a specified folder for texture pack bundles, resolves conflicts somehow, then dumps the textures into the appropriate materials. Loading new models is trickier because I have to load the data myself. But nothing I can't handle especially with all the great scripts out there.

TL;DR: Configuration modding is no problem. It just needs to be filled out. (Ha, 'just!')

The second kind of mod is trickier. If people want to write new scripts for WorldItems - and they will - then they've got to start dealing with managed .NET DLLS, and FRONTIERS has to be able to interface with them. Which isn't too difficult in theory, but like many things on this project I've never actually done it before. And when you start adding tricky restrictions like Unity apparently not permitting classes within a dll to be added to a GameObject unless they derive directly from Monobehavior - which they won't if they're a WorldItemScript - well... I start to sweat a little.

But I know it can be done - I've seen it done before. And what one man can do, another can do!
Language is to the mind more than light is to the eye.
User avatar
Railboy
Developer
Developer
 
Posts: 1830
Joined: Mon Jul 15, 2013 10:46 pm
Location: Seattle, WA

Re: Week of 7/21/2013

PostPosted by Railboy » Wed Jul 24, 2013 9:57 pm

Hooray for Reflection. Finally got a generic load/save system going on WorldItem scripts. Before now you were expected to override load / save functions, then manually add/find keys to/from the save state:

(GRR why does the forum make my tabs ugly. WHY.)
Code: Select all
public class Stackable : WorldItemScript
{
   public float         SquareScale = 1.0f;
   public Vector3         SquareOffset = Vector3.zero;
   public Vector3         SquareRotation = Vector3.zero;

   ...
      
   public override void          SaveToState (WorldItemState state)
   {
      WorldItemScriptState scriptState = new WorldItemScriptState (this);
      scriptState.AddScriptValue ("SquareScale", SquareScale);
      scriptState.AddScriptValue ("SquareOffset", SquareOffset);
      scriptState.AddScriptValue ("SquareRotation", SquareRotation);
      state.AddScriptState (scriptState);
   }
   
   public override void LoadFromState (WorldItemState state)
   {
      WorldItemScriptState scriptState = null;
      if (state.FindScriptState (out scriptState, this))
      {
         scriptState.GetScriptValue ("SquareScale", out SquareScale);
         scriptState.GetScriptValue ("SquareOffset", out SquareOffset);
         scriptState.GetScriptValue ("SquareRotation", out SquareRotation);
      }
   }
}


The rest of the system was automated but honestly who has time for that? And the potential for bugs, ugh. Now you can just check 'AutoSavePublicFields' and the WorldItem's base SaveToState function will look for public fields, convert them to one of the supported data types (bool, float, int, string, enum) and toss it in the WorldItem's XML dump. Same goes for loading. (Of course if your WorldItemScript is doing something weird you can still elect to store and unpack values manually.)

I suppose lists are next on the menu. So far I haven't encountered a WorldItem script that needs to actually store a list of values, aside from stack containers which are a special case. But I'd feel better knowing I could.
Language is to the mind more than light is to the eye.
User avatar
Railboy
Developer
Developer
 
Posts: 1830
Joined: Mon Jul 15, 2013 10:46 pm
Location: Seattle, WA


Return to Dev Logs

Who is online

Users browsing this forum: No registered users and 1 guest