TeamPorcupine / ProjectPorcupine

Project Porcupine: A Base-Building Game...in Space!
GNU General Public License v3.0
484 stars 279 forks source link

[Discussion] JSON Formatting for files #1794

Open BraedonWooding opened 7 years ago

BraedonWooding commented 7 years ago

Information

This is purely design, and doesn't contain the full document. Some of the names are capitalized (maybe incorrectly but again this is more the layout then specifics).

Structure?

The structure follows a more modern and cleaner json style, instead of an array of objects we just define it as a single object with the top level property names often being the 'type' or 'name' of the object, i.e. { "power_cable": {...} }. This means that iterating through every property which while is a little more work on our side, makes the modders job easier and makes documents actually readable. Every document is valid JSON also (obviously).

Examples

This

<?xml version="1.0" encoding="utf-8" ?>
<Inventories>
    <Inventory type="raw_iron" maxStackSize="50" basePrice="0.8" category="inv_cat_raw" localizationName="inv_raw_iron" localizationDesc="inv_raw_iron_desc"/>
    <Inventory type="ice" maxStackSize="10" basePrice="1.2" category="inv_cat_raw" localizationName="inv_ice" localizationDesc="inv_ice_desc"/>
    <Inventory type="raw_copper" maxStackSize="50" basePrice="0.8" category="inv_cat_raw" localizationName="inv_raw_copper" localizationDesc="inv_raw_copper_desc"/>
</Inventories>

To

{
    "raw_iron": {
        "MaxStackSize": 50,
        "BasePrice": 0.8,
        "Category": "inv_cat_raw",
        "LocalizationName": "inv_raw_iron",
        "LocalizationDesc": "inv_raw_iron_desc"
    },
    "ice": {
        "MaxStackSize": 10,
        "BasePrice": 1.2,
        "Category": "inv_cat_raw",
        "LocalizationName": "inv_ice",
        "LocalizationDesc": "inv_ice_desc"
    },
    "raw_copper": {
        "MaxStackSize": 50,
        "BasePrice": 0.8,
        "Category": "inv_cat_raw",
        "LocalizationName": "inv_raw_copper",
        "LocalizationDesc": "inv_raw_copper_desc"
    }
}

This

<?xml version="1.0" encoding="utf-8"?>
<Overlays>
    <Overlay type="oxygen" min="0" max="1" colorMap="Jet">oxygenValueAt</Overlay>
    <Overlay type="room" min="0" max="1" colorMap="Random">roomNumberValueAt</Overlay>
</Overlays>

To

{
    "oxygen": {
        "min": 0,
        "max": 1,
        "colorMap": "Jet",
        "functionName": "oxygenValueAt"
    },
    "room": {
        "min": 0,
        "max": 1,
        "colorMap": "Random",
        "functionName": "roomNumberAtValueAt"
    }
}

Files

Below are all the files. They are in .txt cause that is the only format that github allows for text. Overlay.txt PerformanceHUDTemplate.txt Quest.txt RoomBehavior.txt SettingsTemplate.txt SheduledEvents.txt Ships.txt Stats.txt Tiles.txt Trader.txt Utility.txt ConsoleCommands.txt Currency.txt Furniture.txt GameEvents.txt Headlines.txt Inventory.txt Need.txt

koosemose commented 7 years ago

At a glance it looks good. (will look into it further at a later point, as I get time).

As Furniture is the first I looked at, I will make a few comments on that for the time being (that may be applicable to others).

The most notable concern (perhaps the only one that jumps out to me at the moment.) is that some things seem to have more nesting than strictly needed.

For Job, if Time is the only descendant, it seems that it could be simpler (and no less readable, possibly more readable) as simply a JobTime property. Similarly with the Inventory amounts, having the type as property name, and the amount as the value (though perhaps this loses some amount of readability). Others that could potentially benefit from the same treatment are: DefaultSpriteName and Usename, and Provides and Rate in PowerConnection.

So a proposed alternate version for Furniture:

{
    "steel_wall" : {
        "TypeTag": "Wall",
        "Width": 1,
        "Height": 1,
        "Health": 1000,
        "LinksToNeighbours": "wall",
        "EnclosesRooms": true,
        "DragType": "path",

        "OrderActions": {
            "Build": {
                "JobTime": 1,
                "Inventory": {
                    "steel_plate": 5
                }
            },

            "Deconstruct": {
                "JobTime": 1,
                "Inventory": {
                    "steel_plate": 3
                }
            }
        },

        "Parameters": {
            "thermal_diffusivity": 0.2
        },

        "Components": {
            "Visuals": {
                "DefaultSpriteName" : "steel_wall_"
            }
        },

        "LocalisationCode": "furn_steel_wall",
        "UnlocalizedDescription": "furn_steel_wall_desc"
    },

    "rtg" : {
        "TypeTag": "Temperature",
        "MovementCost": 2,
        "PathfindingModifier": 0,
        "PathfindingWeight": 2,
        "Width": 1,
        "Height": 1,

        "OrderActions": {
            "Build": {
                "JobTime": 2,
                "Inventory": {
                    "steel_plate": 2,
                    "raw_uranium": 2
                }
            },

            "Deconstruct": {
                "JobTime": 1,
                "Inventory": {
                    "raw_uranium": 1
                }
            },

            "Uninstall": {
                "JobTime": 1
            }
        },

        "Actions": {
            "OnInstall": "Rtg_InstallAction",
            "OnUninstall": "Rtg_UninstallAction",
            "OnUpdateTemperature": "Rtg_UpdateTemperature"
        },

        "Parameters": {
            "base_heating": 500,
            "pressure_threshold": 0.2
        },

        "Components": {
            "PowerConnection": {
                "Provides" : 2
            }
        },

        "LocalisationCode": "furn_rtg",
        "UnlocalizedDescription": "furn_rtg_desc"
    }
}
BraedonWooding commented 7 years ago

Sadly I wish that could be carried out, the only problem is all of those have multiple other children parameters, such as Visuals.DefaultSpriteName having a function way of getting the name. Same deal with job which as Time and FromFunction. Note: though this does allow for in the future those things to occur if we remove the FromFunction since in what way will a job ever take a variable amount of time?

koosemose commented 7 years ago

Ahh... I had assumed you'd chosen examples so that all (or most) variations would be present.

One possible way for a job to take variable time would be skill playing a part, or status of Crew (i.e. 1 armed Crew taking longer to build a thing). Though it could also be handled a different way as well (for example anything that could vary the time being built into the Order Action... which would make sense, since, as far as I can think of, if a build job, for example, can take a variable amount of time, all build jobs should have the same sort of variability, rather than having a per furniture way of handling it.

Perhaps having multiple options so instead of the nested version, you have options of using JobTime, or JobTimeFromFunction (or alternatively, it's smart about it, and if it can be converted to a number it uses that directly, and if it can't be converted it's treated as a function name).

It might be useful for discussion sake, rather than having 1 or 2 examples of each, having an "uberexample" have one object with every possible property (rather or not it would actually make sense in an actual object of that type). Minimize the conversational round trip time from a suggestion based on assuming something has fewer options than it actually does.

BraedonWooding commented 7 years ago

Note: I did choose examples that show most variations, just there were none there with jobs so I kinda forgot to makeup one, especially since you will have EITHER Time or FromFunction, not both at any one time (for jobs and the same goes with the other ones). So really it would be 2-3 uberexamples containing every possible variant, still can do it though.

koosemose commented 7 years ago

You could use some kind of marking to designate that it's one or the other... Perhaps an @ in front... since it looks sort of like a radio button, as in only one choice can be made..?

BraedonWooding commented 7 years ago

I still want to keep it as perfectly valid json, but I have an idea to make the document more clear and nice.