We have been working hard on the Beta road map we have also expanded the road map.
Progress
Enhanced search
The search for gob instances now include the ability to add & and | and () to your query. This allows you to narrow your view more effectively for working on subsets of data.
You could search say for all one handed weapons that do slashing damage
One Handed & Slashing
If you wanted one and two handed you could search
(One Handed | Two Handed) & Slashing
This will narrow your data view to items matching those criteria only and let you edit that narrow set in isolation.
Export configuration
We needed to be able to adjust the way exports work and for this a settings system was added. Here is a shot of the export settings available to change how the json file exports.
As is the goal all of this is done via scripts so it's configurable and customizable should there be something you need changed.
c# Unity classes for loading
The c# files requires the json export is configured in a specific way so a button was added to settings to configure your exports.
We have added the export to create both the data classes needed and the loading factory classes needed to load your Json export into Unity.
These class templates are also editable in the configuration system so you can make any changed you might want to those in the templates.
Once in unity you can add the loader class to an object set the json as it's data and it will load all the data on start.
The code looks as follows currently.
The Model
The model is the owner of all data it looks as follows.
We are using the Newtonsoft.Json for decoding the Json it's more suitable as we can decode on the fly and do not need to duplicate the whole model into memory and then decode.
Error handling is still to be decided upon as we are not 100% sure of a suitable way that will fit more developers. That will be completed with the full beta.
using System.IO; using System.Collections; using System.Collections.Generic; using UnityEngine; using Newtonsoft.Json; namespace InformancerForge { public class InformancerForgeModel : MonoBehaviour { private static InformancerForgeModel _instance = null; public static InformancerForgeModel instance { get { return _instance; } } public TextAsset jsonText; private Dictionary<string, Applications> dictionaryApplications = new Dictionary<string, Applications>(); private void ReadApplications(JsonReader reader) => dictionaryApplications.Add(reader.Value as string, new Applications(reader)); public Applications GetApplications(string key) {return dictionaryApplications[key];} private Dictionary<string, Datacenters> dictionaryDatacenters = new Dictionary<string, Datacenters>(); private void ReadDatacenters(JsonReader reader) => dictionaryDatacenters.Add(reader.Value as string, new Datacenters(reader)); public Datacenters GetDatacenters(string key) {return dictionaryDatacenters[key];} private Dictionary<string, Managers> dictionaryManagers = new Dictionary<string, Managers>(); private void ReadManagers(JsonReader reader) => dictionaryManagers.Add(reader.Value as string, new Managers(reader)); public Managers GetManagers(string key) {return dictionaryManagers[key];} private Dictionary<string, PhysicalMachines> dictionaryPhysicalMachines = new Dictionary<string, PhysicalMachines>(); private void ReadPhysicalMachines(JsonReader reader) => dictionaryPhysicalMachines.Add(reader.Value as string, new PhysicalMachines(reader)); public PhysicalMachines GetPhysicalMachines(string key) {return dictionaryPhysicalMachines[key];} private Dictionary<string, VirtualMachines> dictionaryVirtualMachines = new Dictionary<string, VirtualMachines>(); private void ReadVirtualMachines(JsonReader reader) => dictionaryVirtualMachines.Add(reader.Value as string, new VirtualMachines(reader)); public VirtualMachines GetVirtualMachines(string key) {return dictionaryVirtualMachines[key];} private Dictionary<string, Choice> dictionaryChoice = new Dictionary<string, Choice>(); private void ReadChoice(JsonReader reader) => dictionaryChoice.Add(reader.Value as string, new Choice(reader)); public Choice GetChoice(string key) {return dictionaryChoice[key];} private Dictionary<string, Conversation> dictionaryConversation = new Dictionary<string, Conversation>(); private void ReadConversation(JsonReader reader) => dictionaryConversation.Add(reader.Value as string, new Conversation(reader)); public Conversation GetConversation(string key) {return dictionaryConversation[key];} private Dictionary<string, Dialog> dictionaryDialog = new Dictionary<string, Dialog>(); private void ReadDialog(JsonReader reader) => dictionaryDialog.Add(reader.Value as string, new Dialog(reader)); public Dialog GetDialog(string key) {return dictionaryDialog[key];} private Dictionary<string, GameEvent> dictionaryGameEvent = new Dictionary<string, GameEvent>(); private void ReadGameEvent(JsonReader reader) => dictionaryGameEvent.Add(reader.Value as string, new GameEvent(reader)); public GameEvent GetGameEvent(string key) {return dictionaryGameEvent[key];} public delegate void ReadGOBInstance(JsonReader reader); void Start() { _instance = this; JsonTextReader reader = new JsonTextReader(new StringReader(jsonText.text)); reader.Read(); if (reader.TokenType == JsonToken.StartObject) { while (reader.Read()) { if (reader.TokenType == JsonToken.EndObject) { break; } if (reader.TokenType == JsonToken.PropertyName) { switch (reader.Value) { case "Applications": ReadGOBInstances(ReadApplications,reader); break; case "Datacenters": ReadGOBInstances(ReadDatacenters,reader); break; case "Managers": ReadGOBInstances(ReadManagers,reader); break; case "PhysicalMachines": ReadGOBInstances(ReadPhysicalMachines,reader); break; case "VirtualMachines": ReadGOBInstances(ReadVirtualMachines,reader); break; case "Choice": ReadGOBInstances(ReadChoice,reader); break; case "Conversation": ReadGOBInstances(ReadConversation,reader); break; case "Dialog": ReadGOBInstances(ReadDialog,reader); break; case "GameEvent": ReadGOBInstances(ReadGameEvent,reader); break; default: //error break; } } else { // error break; } } } else { // ERROR } } private void ReadGOBInstances(ReadGOBInstance gobReader,JsonReader reader) { reader.Read(); if (reader.TokenType == JsonToken.StartObject) { while (reader.Read()) { if (reader.TokenType == JsonToken.EndObject) { break; } if (reader.TokenType == JsonToken.PropertyName) { gobReader(reader); } else { // error break; } } } else { // error } } } }
To use this in your code you would need to write the following
Conversation fred=InformancerForgeModel.instance.GetConversation("Fred's Chat");
Data object
For each GOB there is an object created. Using c# polymorphism to match your classes as they polymorph each other.
Here is the sample of a Dialog object it's included because it has an array of embedded Choice objects. You won't see choice objects loadable from the Model class as they are embedded and only appear as such.
using System.Collections; using System.Collections.Generic; using UnityEngine; using Newtonsoft.Json; namespace InformancerForge { public class Dialog : GOBInstance { public readonly string text; public readonly Choice[] choices; public readonly string actionLua; public readonly bool fallThrough; public Dialog(JsonReader reader) { while (reader.Read()) { if (reader.TokenType == JsonToken.EndObject) { break; } if (reader.TokenType == JsonToken.PropertyName) { switch (reader.Value) { case "text": text = ReadString(reader); break; case "choices": List<Choice> arrayChoice = new List<Choice>(); for (reader.Read(); reader.TokenType != JsonToken.EndArray;) { reader.Read(); if (reader.TokenType == JsonToken.StartObject) { arrayChoice.Add(new Choice(reader)); }else { // error break; } } choices=arrayChoice.ToArray(); break; case "actionLua": actionLua = ReadString(reader); break; case "fallThrough": fallThrough = ReadBool(reader); break; default: //error break; } } } } } }
One this to node is all data has been made read only to prevent you from adjusting data that should be static.
We will write a more comprehensive guide on Exporting to Unity and perhaps a Video to make it a bit easier to follow and understand how to make your own adjustments.
New road map features
File refresh
We have realized that often you might want to edit files outside of the Forge and when you return have them reload. This is especially true for plugin development such a Lua it's unlikely we will be as feature rich for that aspect as some IDE's and want to leave you to use whatever you find most suitable for editing.
Enhanced LUA editing
Even though we plan to allow external editing of file we still want error reporting to be easier when building plugins. With that in mind we are planning to enhance the error feedback for lua scripts and better handle errors when they happen.
Plugin online catalogue
We are building an online catalogue of plugins there wont be many to start with but we feel it's the easiest way for us to facilitate them being separately version controlled and release more of them.
With that in mind we do have our very first one planned and in progress already.