diff --git a/OpenRA.Game/Map/Map.cs b/OpenRA.Game/Map/Map.cs index 67b610f6b7..05459f42a7 100644 --- a/OpenRA.Game/Map/Map.cs +++ b/OpenRA.Game/Map/Map.cs @@ -776,19 +776,10 @@ namespace OpenRA if (Grid.MaximumTerrainHeight > 0) { - // The minimap is drawn in cell space, so we need to - // unproject the PPos bounds to find the MPos boundaries. - // This matches the calculation in RadarWidget that is used ingame - for (var x = Bounds.Left; x < Bounds.Right; x++) - { - var allTop = Unproject(new PPos(x, Bounds.Top)); - var allBottom = Unproject(new PPos(x, Bounds.Bottom)); - if (allTop.Count > 0) - top = Math.Min(top, allTop.MinBy(uv => uv.V).V); + (top, bottom) = GetCellSpaceBounds(); - if (allBottom.Count > 0) - bottom = Math.Max(bottom, allBottom.MaxBy(uv => uv.V).V); - } + if (top == int.MaxValue || bottom == int.MinValue) + throw new InvalidDataException("The map has invalid boundaries"); } else { @@ -864,6 +855,28 @@ namespace OpenRA return png.Save(); } + public (int Top, int Bottom) GetCellSpaceBounds() + { + var top = int.MaxValue; + var bottom = int.MinValue; + + // The minimap is drawn in cell space, so we need to + // unproject the PPos bounds to find the MPos boundaries. + // This matches the calculation in RadarWidget that is used ingame + for (var x = Bounds.Left; x < Bounds.Right; x++) + { + var allTop = Unproject(new PPos(x, Bounds.Top)); + var allBottom = Unproject(new PPos(x, Bounds.Bottom)); + if (allTop.Count > 0) + top = Math.Min(top, allTop.MinBy(uv => uv.V).V); + + if (allBottom.Count > 0) + bottom = Math.Max(bottom, allBottom.MaxBy(uv => uv.V).V); + } + + return (top, bottom); + } + public bool Contains(CPos cell) { if (Grid.Type == MapGridType.RectangularIsometric) diff --git a/OpenRA.Mods.Cnc/UtilityCommands/ImportGen2MapCommand.cs b/OpenRA.Mods.Cnc/UtilityCommands/ImportGen2MapCommand.cs index 2d99002d61..4eb8fb0c41 100644 --- a/OpenRA.Mods.Cnc/UtilityCommands/ImportGen2MapCommand.cs +++ b/OpenRA.Mods.Cnc/UtilityCommands/ImportGen2MapCommand.cs @@ -421,9 +421,30 @@ namespace OpenRA.Mods.Cnc.UtilityCommands // Calculate Bounds edge tile coordinates. // Reduce bottom and right by 1 because map.SetBounds() increases them. var topLeft = new PPos(left, top); - var bottomRight = new PPos(playableAreaWidth + left - 1, playableAreaHeight + unknownHeightPadding + top - 1); - map.SetBounds(topLeft, bottomRight); + if (map.Height.Max() != 0) + { + // Workaround: Some custom TS maps have invalid boundaries, with no padding area at the bottom + // The boundary needs to be reduced until the projections are valid + bool hasValidBoundaries; + var paddingOffset = 1; + do + { + var bottomRight = new PPos(playableAreaWidth + left - 1, playableAreaHeight + unknownHeightPadding + top - paddingOffset); + map.SetBounds(topLeft, bottomRight); + + var (topBound, bottomBound) = map.GetCellSpaceBounds(); + + hasValidBoundaries = topBound != int.MaxValue && bottomBound != int.MinValue; + paddingOffset++; + } + while (!hasValidBoundaries); + } + else + { + var bottomRight = new PPos(playableAreaWidth + left - 1, playableAreaHeight + unknownHeightPadding + top - 1); + map.SetBounds(topLeft, bottomRight); + } } protected virtual bool TryHandleOverlayToActorInner(CPos cell, byte[] overlayPack, CellLayer overlayIndex, byte overlayType, out ActorReference actorReference) diff --git a/OpenRA.Mods.Common/FileFormats/IniFile.cs b/OpenRA.Mods.Common/FileFormats/IniFile.cs index 34393ee693..93eaaefaaa 100644 --- a/OpenRA.Mods.Common/FileFormats/IniFile.cs +++ b/OpenRA.Mods.Common/FileFormats/IniFile.cs @@ -44,7 +44,12 @@ namespace OpenRA.Mods.Common.FileFormats { case ';': break; case '[': currentSection = ProcessSection(line); break; - default: ProcessEntry(line, currentSection); break; + default: + // Skip everything before the first section + if (currentSection != null) + ProcessEntry(line, currentSection); + + break; } } }