Anaminus/rbxmk

Better support for reading models and saving to .rbxmx files

Closed this issue · 7 comments

It seems like rbxmk doesn't currently do a great job at saving models to .rbxmx files. Attempting to import into Roblox Studio a .rbxmx generated by rbxmk will be unsuccessful.

I don't know if this is a known issue due to technical limitations, but here is how I am able to fix a corrupted .rbxmx file, even for somewhat complex models.

  1. For tags containing an asset URL, wrap the url inside a tag:
BEFORE:

<string name="PROPERTY">rbxassetid://ASSET_ID</string>

AFTER:

<string name="PROPERTY"><url>rbxassetid://ASSET_ID</url></string>
  1. Enter the appropriate value inside the ModelMeshData. Not sure how this is found programmatically, but I get it from a .rbxmx file that was directly exported from Roblox Studio.
BEFORE:

<SharedString name="ModelMeshData"></SharedString>

AFTER:

<SharedString name="ModelMeshData">**MODEL_MESH_DATA_STRING**</SharedString>
  1. PhysicalConfigData does not seem to contain a valid value. In the same manner as the previous fix for ModelMeshData, I get the tag value from a .rbxmx exported from Studio.
BEFORE:

<SharedString name="PhysicalConfigData"><![CDATA[**SOME_CDATA_STRING**]]></SharedString>

AFTER:

<SharedString name="PhysicalConfigData">**PHYSICAL_CONFIG_DATA_STRING**</SharedString>
  1. Finally, at the bottom of the .rbxmx file, add a new set of tags to reference to MODEL_MESH_DATA_STRING, PHYSICAL_CONFIG_DATA_STRING and SOME_CDATA_STRING.
<SharedStrings>	
	<SharedString md5="**MODEL_MESH_DATA_STRING**"></SharedString>	
	<SharedString md5="**PHYSICAL_CONFIG_DATA_STRING**">**SOME_CDATA_STRING**</SharedString>	
</SharedStrings>

For properties that should have the Content type, make sure you wrap the value in a Content exprim:

decal.Texture = types.Content("rbxassetid://ASSET_ID")

Alternatively, having a descriptor specified will do this conversion automatically. The easiest way is to include one of the descriptor flags when running a script:

# Download the latest API dump and use as rbxmk.globalDesc
rbxmk run --desc-latest script.lua

As for the SharedString type, this seems to be a problem with rbxfile, which I'll look into.

SharedStrings should be fixed, and will be available in the next release.

For properties that should have the Content type, make sure you wrap the value in a Content exprim:

decal.Texture = types.Content("rbxassetid://ASSET_ID")

Alternatively, having a descriptor specified will do this conversion automatically. The easiest way is to include one of the descriptor flags when running a script:

Looking back at this, I don't think this was fully relevant to my issue, which I failed to put into context.

The issue arises when reading models/instances from a .rbxl file and exporting each individual model/instance as a .rbxml file. Am I wrong to think that I should not have to do actions like wrapping values? Should I still use descriptors for this?

This is a known issue. rbxl stores all string-like values as strings, so a descriptor is required to convert these values back to their expected types.

However, even with a descriptor specified, it still wont work. The problem is that the rbx formats do not use descriptors when decoding or encoding types. My plan to fix this is to add a "Desc" option to each rbx format that allows a descriptor to be specified. Additionally, they will fall back to globalDesc if needed.

But yes, a descriptor will always be required to properly convert rbxl to rbxlx, because rbxl does not include information for certain types. I'll make a separate issue to track the progress of descriptors for the rbx formats.

Got it, I'll keep an eye out for an update. Thanks again.

So bb154a5 makes changes to do a lot more to handle value conversions. For example, if the descriptor says a property is of the Content type, then any string-like value will be converted to Content. I also added the DescMode format option to determine the strictness of these conversions.

There is still a caveat, which is that Roblox's API dumps do not include certain serialized properties. I've already anticipated this problem with a system that allows patching of descriptor files. This makes it easy to download the latest API dump and then apply a locally maintained patch.

For example, I have this patch file saved as dump.desc-patch.json:

[
	{
		"Type": 1,
		"Element": "Property",
		"Primary": "Instance",
		"Secondary": "AttributesSerialize",
		"Fields": {
			"CanLoad": true,
			"CanSave": true,
			"Category": "Data",
			"Name": "AttributesSerialize",
			"ReadSecurity": "None",
			"Tags": [
				"NotScriptable"
			],
			"ValueType": {
				"Category": "DataType",
				"Name": "BinaryString"
			},
			"WriteSecurity": "None"
		}
	},
	{
		"Type": 1,
		"Element": "Property",
		"Primary": "Instance",
		"Secondary": "Tags",
		"Fields": {
			"CanLoad": true,
			"CanSave": true,
			"Category": "Data",
			"Name": "Tags",
			"ReadSecurity": "None",
			"Tags": [
				"NotScriptable"
			],
			"ValueType": {
				"Category": "DataType",
				"Name": "BinaryString"
			},
			"WriteSecurity": "None"
		}
	}
]

The command to download the latest dump and apply this patch might look like this:

rbxmk --desc-latest --desc-patch dump.desc-patch.json script.lua

Or, patching it dynamically from within the script could be done like this:

rbxmk.patchDesc(rbxmk.globalDesc, fs.read("dump.desc-patch.json"))

I will mess around with this in the coming days and let you know how it goes.