Anaminus / rbxmk

A tool for processing Roblox files.
MIT License
109 stars 11 forks source link

Descriptor extensions #65

Open Anaminus opened 2 years ago

Anaminus commented 2 years ago

Example descriptor file:

{
    "Version": 0,
    "Classes": [],
    "Enums": [],
    "$rbxmkExtensions": {
        "Classes": {
            "Class": {
                "Fields": {
                    "ExtensionKey": "ExtensionValue"
                },
                "Members": {
                    "Member": {
                        "Fields": {
                            "ExtensionKey": "ExtensionValue"
                        }
                    }
                }
            }
        },
        "Enums": {
            "Enum": {
                "Fields": {
                    "ExtensionKey": "ExtensionValue"
                },
                "Items": {
                    "Item": {
                        "Fields": {
                            "ExtensionKey": "ExtensionValue"
                        }
                    }
                }
            }
        }
    },
    "$rbxmkConfig": {
        "Foo": {
            "Bar": [1, 2, 3]
        },
        "BrickColors": {
            "PaletteSize": 128,
            "IndexSize": 208,
            "Default": 194,
            "List": [
                {"Number":  1 , "Name": "White"         , "Color": [242, 243, 243] , "PaletteIndex":  87},
                {"Number": 21 , "Name": "Bright red"    , "Color": [196,  40,  28] , "PaletteIndex":  68},
                {"Number": 23 , "Name": "Bright blue"   , "Color": [ 13, 105, 172] , "PaletteIndex":  21},
                {"Number": 24 , "Name": "Bright yellow" , "Color": [245, 205,  48] , "PaletteIndex":  71},
                {"Number": 28 , "Name": "Dark green"    , "Color": [ 40, 127,  71] , "PaletteIndex":   8}
            ]
        }
    }
}

Example patch that enhances a property with a default value:

{
    "Extend": "Element",
    "Type": 1,
    "Element": "Class",
    "Primary": "BasePart",
    "Secondary": "BrickColor",
    "Fields": {
        "Default": {
            "BrickColor": 194
        }
    }
}

Example patch that modifies global BrickColor data:

{
    "Extend": "$rbxmkConfig",
    "Type": 0,
    "Primary": "BrickColors.List.0.Color",
    "Fields": {"Value": [242, 243, 243]}
}
Anaminus commented 2 years ago

Descriptor extensions can be used for configuration. e.g. AttrConfig. To support this well, inheritance should have a merging strategy that enables each component to be inherited individually.

For merging the descriptor portion, the set of descriptor fields is defined as all fields that aren't $rbxmkConfig. If none of these fields are present, then the descriptor portion is considered not present, and instead inherits from the upper descriptor as usual.

The $rbxmkConfig field is merged top to bottom. That is, if a queried value does not exist on the current RootDesc, then try again with the upper RootDesc, and so on.

To block inheritance, false can be passed as before, but this will block all fields. To block just descriptor fields, a RootDesc.new() can be used. To block just config fields, RootDesc.config() can be used.

RootDesc.config

RootDesc.config(config: table): RootDesc

The config constructor returns a RootDesc with only the config fields specified by config.

Anaminus commented 2 years ago

Handle desc extensions separately from desc format by implementing a generic json patching system.

Types:

Formats:

Libraries:

Desc gains several members:

Certain fields of Desc.Extensions are interpreted in certain ways:

rbxmk.globalDesc.Extensions = {
    Elements = ...,  -- Extends elements in Desc.
    Config = ...,    -- Additional non-element-specific config.
    Behaviors = ..., -- Instance behaviors.
}

Flags: