Note that since nearly all of these are conditionally optional, I added two annotation kinds that I used in my workarounds:
- "rest_optional_if" to capture the pattern used by RotatedAnimation.layers and a few other places where if that property is set, it's a list of values to read and the other properties are ignored. "rest_optional_if" is set on the type and is the same of that property.
- "optional_if" to handle at least one alternative needing to be set. It's a list of property names and if any of those properties are true (i.e. not false or nil due to TileTransitionsVariants's handling of "empty_transitions") then it acts like "optional" was set to true.
- SpotNoiseArguments.comment is not marked optional; I assume it's supposed to be optional.
- "steam-all-the-way" has "excluded" but not "included" despite DontUseEntityInEnergyProductionAchievementPrototype listing both as required.
- "rest_optional_if" is used for FootstepTriggerEffectItem.actions, and RotatedAnimation/RotatedSprite.layers
- RecipeData.results is "optional_if" "result" is set, which is stated by the description, but not in a machine-readable way.
- data.raw.turret["small-worm-turret"].spawn_decoration[_] do not have a "type" property despite spawn_decoration saying the type is Array[CreateDecorativesTriggerEffectItem] where "type" is not marked optional. (I'm guessing "type" might always be optional if it's not needed to determine the type?)
- In data.raw["noise-expression"]["0_17-lakes-elevation"].expression.arguments[3].arguments[1].arguments[1].arguments[1].arguments[1].arguments[1].arguments.points, points is defined to be a NoiseArrayConstruction but it's actually a NoiseVariable.
- ItemProductPrototype/FluidProductPrototype both say in the description that the non-optional fields `amount_min` and `amount_max` are loaded only if `amount` is not defined, but don't say that in a machine-readable way. I added "optional_if" = { "amount" }.
- Similarly, TileTransitionsVariants has multiple fields with descriptions like "This or side_mask needs to be specified if empty_transitions is not true." which is not given in a machine-readable way. I added "optional_if" = { "empty_transitions", "side_mask" }.
- I'm not sure this one is actually a documentation bug or a bug in my understanding the semantics: BoundingBox is declared as a tuple but sometimes given as a struct with the keys "left_top" and "right_bottom". But I vaguely recall something about tuples and structs sometimes being interchangeable from Factorio's point of view.