Use Tuple syntax

This commit is contained in:
teinarss
2020-08-02 13:41:03 +02:00
committed by Paul Chote
parent 8a74f6ea18
commit 19b02875c7
90 changed files with 738 additions and 826 deletions

View File

@@ -54,10 +54,10 @@ namespace OpenRA.Graphics
public static IReadOnlyDictionary<string, Collection> Collections { get; private set; } public static IReadOnlyDictionary<string, Collection> Collections { get; private set; }
static Dictionary<string, Collection> collections; static Dictionary<string, Collection> collections;
static Dictionary<string, Pair<Sheet, int>> cachedSheets; static Dictionary<string, (Sheet Sheet, int Density)> cachedSheets;
static Dictionary<string, Dictionary<string, Sprite>> cachedSprites; static Dictionary<string, Dictionary<string, Sprite>> cachedSprites;
static Dictionary<string, Sprite[]> cachedPanelSprites; static Dictionary<string, Sprite[]> cachedPanelSprites;
static Dictionary<Collection, Pair<Sheet, int>> cachedCollectionSheets; static Dictionary<Collection, (Sheet Sheet, int)> cachedCollectionSheets;
static IReadOnlyFileSystem fileSystem; static IReadOnlyFileSystem fileSystem;
static float dpiScale = 1; static float dpiScale = 1;
@@ -72,10 +72,10 @@ namespace OpenRA.Graphics
fileSystem = modData.DefaultFileSystem; fileSystem = modData.DefaultFileSystem;
collections = new Dictionary<string, Collection>(); collections = new Dictionary<string, Collection>();
cachedSheets = new Dictionary<string, Pair<Sheet, int>>(); cachedSheets = new Dictionary<string, (Sheet, int)>();
cachedSprites = new Dictionary<string, Dictionary<string, Sprite>>(); cachedSprites = new Dictionary<string, Dictionary<string, Sprite>>();
cachedPanelSprites = new Dictionary<string, Sprite[]>(); cachedPanelSprites = new Dictionary<string, Sprite[]>();
cachedCollectionSheets = new Dictionary<Collection, Pair<Sheet, int>>(); cachedCollectionSheets = new Dictionary<Collection, (Sheet, int)>();
Collections = new ReadOnlyDictionary<string, Collection>(collections); Collections = new ReadOnlyDictionary<string, Collection>(collections);
@@ -91,7 +91,7 @@ namespace OpenRA.Graphics
{ {
if (cachedSheets != null) if (cachedSheets != null)
foreach (var sheet in cachedSheets.Values) foreach (var sheet in cachedSheets.Values)
sheet.First.Dispose(); sheet.Sheet.Dispose();
collections = null; collections = null;
cachedSheets = null; cachedSheets = null;
@@ -108,12 +108,10 @@ namespace OpenRA.Graphics
collections.Add(name, FieldLoader.Load<Collection>(yaml)); collections.Add(name, FieldLoader.Load<Collection>(yaml));
} }
static Pair<Sheet, int> SheetForCollection(Collection c) static (Sheet Sheet, int Density) SheetForCollection(Collection c)
{ {
Pair<Sheet, int> sheetDensity;
// Outer cache avoids recalculating image names // Outer cache avoids recalculating image names
if (!cachedCollectionSheets.TryGetValue(c, out sheetDensity)) if (!cachedCollectionSheets.TryGetValue(c, out (Sheet, int) sheetDensity))
{ {
var image = c.Image; var image = c.Image;
var density = 1; var density = 1;
@@ -137,7 +135,7 @@ namespace OpenRA.Graphics
sheet.GetTexture().ScaleFilter = TextureScaleFilter.Linear; sheet.GetTexture().ScaleFilter = TextureScaleFilter.Linear;
sheetDensity = Pair.New(sheet, density); sheetDensity = (sheet, density);
cachedSheets.Add(image, sheetDensity); cachedSheets.Add(image, sheetDensity);
} }
@@ -153,13 +151,10 @@ namespace OpenRA.Graphics
return null; return null;
// Cached sprite // Cached sprite
Dictionary<string, Sprite> cachedCollection; if (cachedSprites.TryGetValue(collectionName, out var cachedCollection) && cachedCollection.TryGetValue(imageName, out var sprite))
Sprite sprite;
if (cachedSprites.TryGetValue(collectionName, out cachedCollection) && cachedCollection.TryGetValue(imageName, out sprite))
return sprite; return sprite;
Collection collection; if (!collections.TryGetValue(collectionName, out var collection))
if (!collections.TryGetValue(collectionName, out collection))
{ {
Log.Write("debug", "Could not find collection '{0}'", collectionName); Log.Write("debug", "Could not find collection '{0}'", collectionName);
return null; return null;
@@ -177,7 +172,7 @@ namespace OpenRA.Graphics
cachedSprites.Add(collectionName, cachedCollection); cachedSprites.Add(collectionName, cachedCollection);
} }
var image = new Sprite(sheetDensity.First, sheetDensity.Second * mi, TextureChannel.RGBA, 1f / sheetDensity.Second); var image = new Sprite(sheetDensity.Sheet, sheetDensity.Density * mi, TextureChannel.RGBA, 1f / sheetDensity.Density);
cachedCollection.Add(imageName, image); cachedCollection.Add(imageName, image);
return image; return image;
@@ -189,12 +184,10 @@ namespace OpenRA.Graphics
return null; return null;
// Cached sprite // Cached sprite
Sprite[] cachedSprites; if (cachedPanelSprites.TryGetValue(collectionName, out var cachedSprites))
if (cachedPanelSprites.TryGetValue(collectionName, out cachedSprites))
return cachedSprites; return cachedSprites;
Collection collection; if (!collections.TryGetValue(collectionName, out var collection))
if (!collections.TryGetValue(collectionName, out collection))
{ {
Log.Write("debug", "Could not find collection '{0}'", collectionName); Log.Write("debug", "Could not find collection '{0}'", collectionName);
return null; return null;
@@ -214,20 +207,20 @@ namespace OpenRA.Graphics
var pr = collection.PanelRegion; var pr = collection.PanelRegion;
var ps = collection.PanelSides; var ps = collection.PanelSides;
var sides = new[] var sides = new (PanelSides PanelSides, Rectangle Bounds)[]
{ {
Pair.New(PanelSides.Top | PanelSides.Left, new Rectangle(pr[0], pr[1], pr[2], pr[3])), (PanelSides.Top | PanelSides.Left, new Rectangle(pr[0], pr[1], pr[2], pr[3])),
Pair.New(PanelSides.Top, new Rectangle(pr[0] + pr[2], pr[1], pr[4], pr[3])), (PanelSides.Top, new Rectangle(pr[0] + pr[2], pr[1], pr[4], pr[3])),
Pair.New(PanelSides.Top | PanelSides.Right, new Rectangle(pr[0] + pr[2] + pr[4], pr[1], pr[6], pr[3])), (PanelSides.Top | PanelSides.Right, new Rectangle(pr[0] + pr[2] + pr[4], pr[1], pr[6], pr[3])),
Pair.New(PanelSides.Left, new Rectangle(pr[0], pr[1] + pr[3], pr[2], pr[5])), (PanelSides.Left, new Rectangle(pr[0], pr[1] + pr[3], pr[2], pr[5])),
Pair.New(PanelSides.Center, new Rectangle(pr[0] + pr[2], pr[1] + pr[3], pr[4], pr[5])), (PanelSides.Center, new Rectangle(pr[0] + pr[2], pr[1] + pr[3], pr[4], pr[5])),
Pair.New(PanelSides.Right, new Rectangle(pr[0] + pr[2] + pr[4], pr[1] + pr[3], pr[6], pr[5])), (PanelSides.Right, new Rectangle(pr[0] + pr[2] + pr[4], pr[1] + pr[3], pr[6], pr[5])),
Pair.New(PanelSides.Bottom | PanelSides.Left, new Rectangle(pr[0], pr[1] + pr[3] + pr[5], pr[2], pr[7])), (PanelSides.Bottom | PanelSides.Left, new Rectangle(pr[0], pr[1] + pr[3] + pr[5], pr[2], pr[7])),
Pair.New(PanelSides.Bottom, new Rectangle(pr[0] + pr[2], pr[1] + pr[3] + pr[5], pr[4], pr[7])), (PanelSides.Bottom, new Rectangle(pr[0] + pr[2], pr[1] + pr[3] + pr[5], pr[4], pr[7])),
Pair.New(PanelSides.Bottom | PanelSides.Right, new Rectangle(pr[0] + pr[2] + pr[4], pr[1] + pr[3] + pr[5], pr[6], pr[7])) (PanelSides.Bottom | PanelSides.Right, new Rectangle(pr[0] + pr[2] + pr[4], pr[1] + pr[3] + pr[5], pr[6], pr[7]))
}; };
sprites = sides.Select(x => ps.HasSide(x.First) ? new Sprite(sheetDensity.First, sheetDensity.Second * x.Second, TextureChannel.RGBA, 1f / sheetDensity.Second) : null) sprites = sides.Select(x => ps.HasSide(x.PanelSides) ? new Sprite(sheetDensity.Sheet, sheetDensity.Density * x.Bounds, TextureChannel.RGBA, 1f / sheetDensity.Density) : null)
.ToArray(); .ToArray();
} }
else else
@@ -256,8 +249,7 @@ namespace OpenRA.Graphics
if (string.IsNullOrEmpty(collectionName)) if (string.IsNullOrEmpty(collectionName))
return new Size(0, 0); return new Size(0, 0);
Collection collection; if (!collections.TryGetValue(collectionName, out var collection))
if (!collections.TryGetValue(collectionName, out collection))
{ {
Log.Write("debug", "Could not find collection '{0}'", collectionName); Log.Write("debug", "Could not find collection '{0}'", collectionName);
return new Size(0, 0); return new Size(0, 0);

View File

@@ -48,7 +48,7 @@ namespace OpenRA.Graphics
readonly Dictionary<Sheet, IFrameBuffer> mappedBuffers = new Dictionary<Sheet, IFrameBuffer>(); readonly Dictionary<Sheet, IFrameBuffer> mappedBuffers = new Dictionary<Sheet, IFrameBuffer>();
readonly Stack<KeyValuePair<Sheet, IFrameBuffer>> unmappedBuffers = new Stack<KeyValuePair<Sheet, IFrameBuffer>>(); readonly Stack<KeyValuePair<Sheet, IFrameBuffer>> unmappedBuffers = new Stack<KeyValuePair<Sheet, IFrameBuffer>>();
readonly List<Pair<Sheet, Action>> doRender = new List<Pair<Sheet, Action>>(); readonly List<(Sheet Sheet, Action Func)> doRender = new List<(Sheet, Action)>();
SheetBuilder sheetBuilderForFrame; SheetBuilder sheetBuilderForFrame;
bool isInFrame; bool isInFrame;
@@ -180,7 +180,7 @@ namespace OpenRA.Graphics
var correctionTransform = Util.MatrixMultiply(translateMtx, FlipMtx); var correctionTransform = Util.MatrixMultiply(translateMtx, FlipMtx);
var shadowCorrectionTransform = Util.MatrixMultiply(shadowTranslateMtx, ShadowScaleFlipMtx); var shadowCorrectionTransform = Util.MatrixMultiply(shadowTranslateMtx, ShadowScaleFlipMtx);
doRender.Add(Pair.New<Sheet, Action>(sprite.Sheet, () => doRender.Add((sprite.Sheet, () =>
{ {
foreach (var m in models) foreach (var m in models)
{ {
@@ -324,16 +324,16 @@ namespace OpenRA.Graphics
foreach (var v in doRender) foreach (var v in doRender)
{ {
// Change sheet // Change sheet
if (v.First != currentSheet) if (v.Sheet != currentSheet)
{ {
if (fbo != null) if (fbo != null)
DisableFrameBuffer(fbo); DisableFrameBuffer(fbo);
currentSheet = v.First; currentSheet = v.Sheet;
fbo = EnableFrameBuffer(currentSheet); fbo = EnableFrameBuffer(currentSheet);
} }
v.Second(); v.Func();
} }
if (fbo != null) if (fbo != null)

View File

@@ -47,8 +47,8 @@ namespace OpenRA.Graphics
remapRamp = ramp.Select(r => r - ramp[rampMaxIndex]); remapRamp = ramp.Select(r => r - ramp[rampMaxIndex]);
} }
remapColors = remapRamp.Select((x, i) => Pair.New(baseIndex + i, Exts.ColorLerp(x / (float)ramp.Length, c1, c2))) remapColors = remapRamp.Select((x, i) => (baseIndex + i, Exts.ColorLerp(x / (float)ramp.Length, c1, c2)))
.ToDictionary(u => u.First, u => u.Second); .ToDictionary(u => u.Item1, u => u.Item2);
} }
public Color GetRemappedColor(Color original, int index) public Color GetRemappedColor(Color original, int index)

View File

@@ -23,8 +23,8 @@ namespace OpenRA.Graphics
readonly SheetBuilder builder; readonly SheetBuilder builder;
readonly Func<string, float> lineWidth; readonly Func<string, float> lineWidth;
readonly IFont font; readonly IFont font;
readonly Cache<Pair<char, Color>, GlyphInfo> glyphs; readonly Cache<(char C, Color Color), GlyphInfo> glyphs;
readonly Cache<Tuple<char, Color, int>, Sprite> contrastGlyphs; readonly Cache<(char, Color, int), Sprite> contrastGlyphs;
readonly Cache<int, float[]> dilationElements; readonly Cache<int, float[]> dilationElements;
float deviceScale; float deviceScale;
@@ -40,12 +40,12 @@ namespace OpenRA.Graphics
font = Game.Renderer.CreateFont(data); font = Game.Renderer.CreateFont(data);
glyphs = new Cache<Pair<char, Color>, GlyphInfo>(CreateGlyph, Pair<char, Color>.EqualityComparer); glyphs = new Cache<(char, Color), GlyphInfo>(CreateGlyph);
contrastGlyphs = new Cache<Tuple<char, Color, int>, Sprite>(CreateContrastGlyph); contrastGlyphs = new Cache<(char, Color, int), Sprite>(CreateContrastGlyph);
dilationElements = new Cache<int, float[]>(CreateCircularWeightMap); dilationElements = new Cache<int, float[]>(CreateCircularWeightMap);
// PERF: Cache these delegates for Measure calls. // PERF: Cache these delegates for Measure calls.
Func<char, float> characterWidth = character => glyphs[Pair.New(character, Color.White)].Advance; Func<char, float> characterWidth = character => glyphs[(character, Color.White)].Advance;
lineWidth = line => line.Sum(characterWidth) / deviceScale; lineWidth = line => line.Sum(characterWidth) / deviceScale;
if (size <= 24) if (size <= 24)
@@ -65,7 +65,7 @@ namespace OpenRA.Graphics
{ {
using (new PerfTimer("PrecacheColor {0} {1}px {2}".F(name, size, c))) using (new PerfTimer("PrecacheColor {0} {1}px {2}".F(name, size, c)))
for (var n = (char)0x20; n < (char)0x7f; n++) for (var n = (char)0x20; n < (char)0x7f; n++)
if (glyphs[Pair.New(n, c)] == null) if (glyphs[(n, c)] == null)
throw new InvalidOperationException(); throw new InvalidOperationException();
} }
@@ -87,12 +87,12 @@ namespace OpenRA.Graphics
continue; continue;
} }
var g = glyphs[Pair.New(s, Color.Black)]; var g = glyphs[(s, Color.Black)];
// Convert screen coordinates back to UI coordinates for drawing // Convert screen coordinates back to UI coordinates for drawing
if (g.Sprite != null) if (g.Sprite != null)
{ {
var contrastSprite = contrastGlyphs[Tuple.Create(s, contrastColor, screenContrast)]; var contrastSprite = contrastGlyphs[(s, contrastColor, screenContrast)];
Game.Renderer.RgbaSpriteRenderer.DrawSprite(contrastSprite, Game.Renderer.RgbaSpriteRenderer.DrawSprite(contrastSprite,
(screen + g.Offset - contrastVector) / deviceScale, (screen + g.Offset - contrastVector) / deviceScale,
contrastSprite.Size / deviceScale); contrastSprite.Size / deviceScale);
@@ -118,7 +118,7 @@ namespace OpenRA.Graphics
continue; continue;
} }
var g = glyphs[Pair.New(s, c)]; var g = glyphs[(s, c)];
// Convert screen coordinates back to UI coordinates for drawing // Convert screen coordinates back to UI coordinates for drawing
if (g.Sprite != null) if (g.Sprite != null)
@@ -155,7 +155,7 @@ namespace OpenRA.Graphics
continue; continue;
} }
var g = glyphs[Pair.New(s, c)]; var g = glyphs[(s, c)];
if (g.Sprite != null) if (g.Sprite != null)
{ {
var tl = new float2( var tl = new float2(
@@ -241,9 +241,9 @@ namespace OpenRA.Graphics
return new int2((int)Math.Ceiling(lines.Max(lineWidth)), lines.Length * size); return new int2((int)Math.Ceiling(lines.Max(lineWidth)), lines.Length * size);
} }
GlyphInfo CreateGlyph(Pair<char, Color> c) GlyphInfo CreateGlyph((char C, Color Color) c)
{ {
var glyph = font.CreateGlyph(c.First, size, deviceScale); var glyph = font.CreateGlyph(c.C, size, deviceScale);
if (glyph.Data == null) if (glyph.Data == null)
{ {
@@ -274,7 +274,7 @@ namespace OpenRA.Graphics
if (p != 0) if (p != 0)
{ {
var q = destStride * (j + s.Bounds.Top) + 4 * (i + s.Bounds.Left); var q = destStride * (j + s.Bounds.Top) + 4 * (i + s.Bounds.Left);
var pmc = Util.PremultiplyAlpha(Color.FromArgb(p, c.Second)); var pmc = Util.PremultiplyAlpha(Color.FromArgb(p, c.Color));
dest[q] = pmc.B; dest[q] = pmc.B;
dest[q + 1] = pmc.G; dest[q + 1] = pmc.G;
@@ -347,10 +347,10 @@ namespace OpenRA.Graphics
return elem; return elem;
} }
Sprite CreateContrastGlyph(Tuple<char, Color, int> c) Sprite CreateContrastGlyph((char, Color, int) c)
{ {
// Source glyph color doesn't matter, so use black // Source glyph color doesn't matter, so use black
var glyph = glyphs[Pair.New(c.Item1, Color.Black)]; var glyph = glyphs[(c.Item1, Color.Black)];
var color = c.Item2; var color = c.Item2;
var r = c.Item3; var r = c.Item3;

View File

@@ -34,9 +34,9 @@ namespace OpenRA
mods = GetInstalledMods(searchPaths, explicitPaths); mods = GetInstalledMods(searchPaths, explicitPaths);
} }
static IEnumerable<Pair<string, string>> GetCandidateMods(IEnumerable<string> searchPaths) static IEnumerable<(string Id, string Path)> GetCandidateMods(IEnumerable<string> searchPaths)
{ {
var mods = new List<Pair<string, string>>(); var mods = new List<(string, string)>();
foreach (var path in searchPaths) foreach (var path in searchPaths)
{ {
try try
@@ -47,7 +47,7 @@ namespace OpenRA
var directory = new DirectoryInfo(resolved); var directory = new DirectoryInfo(resolved);
foreach (var subdir in directory.EnumerateDirectories()) foreach (var subdir in directory.EnumerateDirectories())
mods.Add(Pair.New(subdir.Name, subdir.FullName)); mods.Add((subdir.Name, subdir.FullName));
} }
catch (Exception e) catch (Exception e)
{ {
@@ -88,13 +88,13 @@ namespace OpenRA
{ {
var ret = new Dictionary<string, Manifest>(); var ret = new Dictionary<string, Manifest>();
var candidates = GetCandidateMods(searchPaths) var candidates = GetCandidateMods(searchPaths)
.Concat(explicitPaths.Select(p => Pair.New(Path.GetFileNameWithoutExtension(p), p))); .Concat(explicitPaths.Select(p => (Id: Path.GetFileNameWithoutExtension(p), Path: p)));
foreach (var pair in candidates) foreach (var pair in candidates)
{ {
var mod = LoadMod(pair.First, pair.Second); var mod = LoadMod(pair.Id, pair.Path);
if (mod != null) if (mod != null)
ret[pair.First] = mod; ret[pair.Id] = mod;
} }
return ret; return ret;

View File

@@ -662,7 +662,7 @@ namespace OpenRA
return dataStream.ToArray(); return dataStream.ToArray();
} }
public Pair<Color, Color> GetTerrainColorPair(MPos uv) public (Color Left, Color Right) GetTerrainColorPair(MPos uv)
{ {
Color left, right; Color left, right;
var tileset = Rules.TileSet; var tileset = Rules.TileSet;
@@ -687,7 +687,7 @@ namespace OpenRA
else else
left = right = Color.Black; left = right = Color.Black;
return Pair.New(left, right); return (left, right);
} }
public byte[] SavePreview() public byte[] SavePreview()
@@ -695,7 +695,7 @@ namespace OpenRA
var tileset = Rules.TileSet; var tileset = Rules.TileSet;
var actorTypes = Rules.Actors.Values.Where(a => a.HasTraitInfo<IMapPreviewSignatureInfo>()); var actorTypes = Rules.Actors.Values.Where(a => a.HasTraitInfo<IMapPreviewSignatureInfo>());
var actors = ActorDefinitions.Where(a => actorTypes.Where(ai => ai.Name == a.Value.Value).Any()); var actors = ActorDefinitions.Where(a => actorTypes.Where(ai => ai.Name == a.Value.Value).Any());
var positions = new List<Pair<MPos, Color>>(); var positions = new List<(MPos Position, Color Color)>();
foreach (var actor in actors) foreach (var actor in actors)
{ {
var s = new ActorReference(actor.Value.Value, actor.Value.ToDictionary()); var s = new ActorReference(actor.Value.Value, actor.Value.ToDictionary());
@@ -729,7 +729,7 @@ namespace OpenRA
var stride = bitmapWidth * 4; var stride = bitmapWidth * 4;
var pxStride = 4; var pxStride = 4;
var minimapData = new byte[stride * height]; var minimapData = new byte[stride * height];
Pair<Color, Color> terrainColor = default(Pair<Color, Color>); (Color Left, Color Right) terrainColor = default((Color, Color));
for (var y = 0; y < height; y++) for (var y = 0; y < height; y++)
{ {
@@ -737,8 +737,8 @@ namespace OpenRA
{ {
var uv = new MPos(x + Bounds.Left, y + Bounds.Top); var uv = new MPos(x + Bounds.Left, y + Bounds.Top);
// FirstOrDefault will return a Pair(MPos.Zero, Color.Transparent) if positions is empty // FirstOrDefault will return a (MPos.Zero, Color.Transparent) if positions is empty
var actorColor = positions.FirstOrDefault(ap => ap.First == uv).Second; var actorColor = positions.FirstOrDefault(ap => ap.Position == uv).Color;
if (actorColor.A == 0) if (actorColor.A == 0)
terrainColor = GetTerrainColorPair(uv); terrainColor = GetTerrainColorPair(uv);
@@ -750,7 +750,7 @@ namespace OpenRA
if (x + dx > 0) if (x + dx > 0)
{ {
var z = y * stride + xOffset - pxStride; var z = y * stride + xOffset - pxStride;
var c = actorColor.A == 0 ? terrainColor.First : actorColor; var c = actorColor.A == 0 ? terrainColor.Left : actorColor;
minimapData[z++] = c.R; minimapData[z++] = c.R;
minimapData[z++] = c.G; minimapData[z++] = c.G;
minimapData[z++] = c.B; minimapData[z++] = c.B;
@@ -760,7 +760,7 @@ namespace OpenRA
if (xOffset < stride) if (xOffset < stride)
{ {
var z = y * stride + xOffset; var z = y * stride + xOffset;
var c = actorColor.A == 0 ? terrainColor.Second : actorColor; var c = actorColor.A == 0 ? terrainColor.Right : actorColor;
minimapData[z++] = c.R; minimapData[z++] = c.R;
minimapData[z++] = c.G; minimapData[z++] = c.G;
minimapData[z++] = c.B; minimapData[z++] = c.B;
@@ -770,7 +770,7 @@ namespace OpenRA
else else
{ {
var z = y * stride + pxStride * x; var z = y * stride + pxStride * x;
var c = actorColor.A == 0 ? terrainColor.First : actorColor; var c = actorColor.A == 0 ? terrainColor.Left : actorColor;
minimapData[z++] = c.R; minimapData[z++] = c.R;
minimapData[z++] = c.G; minimapData[z++] = c.G;
minimapData[z++] = c.B; minimapData[z++] = c.B;

View File

@@ -89,7 +89,7 @@ namespace OpenRA
public bool DefinesUnsafeCustomRules { get; private set; } public bool DefinesUnsafeCustomRules { get; private set; }
public bool RulesLoaded { get; private set; } public bool RulesLoaded { get; private set; }
public void SetRulesetGenerator(ModData modData, Func<Pair<Ruleset, bool>> generator) public void SetRulesetGenerator(ModData modData, Func<(Ruleset Ruleset, bool DefinesUnsafeCustomRules)> generator)
{ {
InvalidCustomRules = false; InvalidCustomRules = false;
RulesLoaded = false; RulesLoaded = false;
@@ -106,8 +106,8 @@ namespace OpenRA
try try
{ {
var ret = generator(); var ret = generator();
DefinesUnsafeCustomRules = ret.Second; DefinesUnsafeCustomRules = ret.DefinesUnsafeCustomRules;
return ret.First; return ret.Ruleset;
} }
catch (Exception e) catch (Exception e)
{ {
@@ -318,7 +318,7 @@ namespace OpenRA
voiceDefinitions, notificationDefinitions, musicDefinitions, sequenceDefinitions, modelSequenceDefinitions); voiceDefinitions, notificationDefinitions, musicDefinitions, sequenceDefinitions, modelSequenceDefinitions);
var flagged = Ruleset.DefinesUnsafeCustomRules(modData, this, ruleDefinitions, var flagged = Ruleset.DefinesUnsafeCustomRules(modData, this, ruleDefinitions,
weaponDefinitions, voiceDefinitions, notificationDefinitions, sequenceDefinitions); weaponDefinitions, voiceDefinitions, notificationDefinitions, sequenceDefinitions);
return Pair.New(rules, flagged); return (rules, flagged);
}); });
if (p.Contains("map.png")) if (p.Contains("map.png"))
@@ -402,7 +402,7 @@ namespace OpenRA
voiceDefinitions, notificationDefinitions, musicDefinitions, sequenceDefinitions, modelSequenceDefinitions); voiceDefinitions, notificationDefinitions, musicDefinitions, sequenceDefinitions, modelSequenceDefinitions);
var flagged = Ruleset.DefinesUnsafeCustomRules(modData, this, ruleDefinitions, var flagged = Ruleset.DefinesUnsafeCustomRules(modData, this, ruleDefinitions,
weaponDefinitions, voiceDefinitions, notificationDefinitions, sequenceDefinitions); weaponDefinitions, voiceDefinitions, notificationDefinitions, sequenceDefinitions);
return Pair.New(rules, flagged); return (rules, flagged);
}); });
} }
catch (Exception e) catch (Exception e)

View File

@@ -115,7 +115,7 @@ namespace OpenRA.Network
Connection.SendImmediate(localImmediateOrders.Select(o => o.Serialize())); Connection.SendImmediate(localImmediateOrders.Select(o => o.Serialize()));
localImmediateOrders.Clear(); localImmediateOrders.Clear();
var immediatePackets = new List<Pair<int, byte[]>>(); var immediatePackets = new List<(int ClientId, byte[] Packet)>();
Connection.Receive( Connection.Receive(
(clientId, packet) => (clientId, packet) =>
@@ -126,16 +126,16 @@ namespace OpenRA.Network
else if (packet.Length >= 5 && packet[4] == (byte)OrderType.SyncHash) else if (packet.Length >= 5 && packet[4] == (byte)OrderType.SyncHash)
CheckSync(packet); CheckSync(packet);
else if (frame == 0) else if (frame == 0)
immediatePackets.Add(Pair.New(clientId, packet)); immediatePackets.Add((clientId, packet));
else else
frameData.AddFrameOrders(clientId, frame, packet); frameData.AddFrameOrders(clientId, frame, packet);
}); });
foreach (var p in immediatePackets) foreach (var p in immediatePackets)
{ {
foreach (var o in p.Second.ToOrderList(World)) foreach (var o in p.Packet.ToOrderList(World))
{ {
UnitOrders.ProcessOrder(this, World, p.First, o); UnitOrders.ProcessOrder(this, World, p.ClientId, o);
// A mod switch or other event has pulled the ground from beneath us // A mod switch or other event has pulled the ground from beneath us
if (disposed) if (disposed)

View File

@@ -14,7 +14,6 @@ using System.Collections.Generic;
using System.IO; using System.IO;
using System.Net; using System.Net;
using OpenRA.FileFormats; using OpenRA.FileFormats;
using OpenRA.Primitives;
namespace OpenRA.Network namespace OpenRA.Network
{ {
@@ -23,7 +22,7 @@ namespace OpenRA.Network
class Chunk class Chunk
{ {
public int Frame; public int Frame;
public Pair<int, byte[]>[] Packets; public (int ClientId, byte[] Packet)[] Packets;
} }
Queue<Chunk> chunks = new Queue<Chunk>(); Queue<Chunk> chunks = new Queue<Chunk>();
@@ -55,7 +54,7 @@ namespace OpenRA.Network
// to avoid issues with all immediate orders being resolved on the first tick. // to avoid issues with all immediate orders being resolved on the first tick.
using (var rs = File.OpenRead(replayFilename)) using (var rs = File.OpenRead(replayFilename))
{ {
var packets = new List<Pair<int, byte[]>>(); var packets = new List<(int ClientId, byte[] Packet)>();
var chunk = new Chunk(); var chunk = new Chunk();
@@ -67,7 +66,7 @@ namespace OpenRA.Network
var packetLen = rs.ReadInt32(); var packetLen = rs.ReadInt32();
var packet = rs.ReadBytes(packetLen); var packet = rs.ReadBytes(packetLen);
var frame = BitConverter.ToInt32(packet, 0); var frame = BitConverter.ToInt32(packet, 0);
packets.Add(Pair.New(client, packet)); packets.Add((client, packet));
if (frame != int.MaxValue && if (frame != int.MaxValue &&
(!lastClientsFrame.ContainsKey(client) || frame > lastClientsFrame[client])) (!lastClientsFrame.ContainsKey(client) || frame > lastClientsFrame[client]))
@@ -111,13 +110,13 @@ namespace OpenRA.Network
{ {
foreach (var tmpPacketPair in tmpChunk.Packets) foreach (var tmpPacketPair in tmpChunk.Packets)
{ {
var client = tmpPacketPair.First; var client = tmpPacketPair.ClientId;
// Don't replace the final disconnection packet - we still want this to end the replay. // Don't replace the final disconnection packet - we still want this to end the replay.
if (client == lastClientToDisconnect) if (client == lastClientToDisconnect)
continue; continue;
var packet = tmpPacketPair.Second; var packet = tmpPacketPair.Packet;
if (packet.Length == 5 && packet[4] == (byte)OrderType.Disconnect) if (packet.Length == 5 && packet[4] == (byte)OrderType.Disconnect)
{ {
var lastClientFrame = lastClientsFrame[client]; var lastClientFrame = lastClientsFrame[client];
@@ -156,7 +155,7 @@ namespace OpenRA.Network
while (chunks.Count != 0 && chunks.Peek().Frame <= ordersFrame) while (chunks.Count != 0 && chunks.Peek().Frame <= ordersFrame)
foreach (var o in chunks.Dequeue().Packets) foreach (var o in chunks.Dequeue().Packets)
packetFn(o.First, o.Second); packetFn(o.ClientId, o.Packet);
} }
public void Dispose() { } public void Dispose() { }

View File

@@ -29,7 +29,7 @@ namespace OpenRA.Network
readonly Report[] syncReports = new Report[NumSyncReports]; readonly Report[] syncReports = new Report[NumSyncReports];
int curIndex = 0; int curIndex = 0;
static Pair<string[], Values> DumpSyncTrait(ISync sync) static (string[] Names, Values Values) DumpSyncTrait(ISync sync)
{ {
var type = sync.GetType(); var type = sync.GetType();
TypeInfo typeInfo; TypeInfo typeInfo;
@@ -41,7 +41,7 @@ namespace OpenRA.Network
foreach (var func in typeInfo.SerializableCopyOfMemberFunctions) foreach (var func in typeInfo.SerializableCopyOfMemberFunctions)
values[index++] = func(sync); values[index++] = func(sync);
return Pair.New(typeInfo.Names, values); return (typeInfo.Names, values);
} }
public SyncReport(OrderManager orderManager) public SyncReport(OrderManager orderManager)
@@ -120,9 +120,9 @@ namespace OpenRA.Network
Log.Write("sync", "\t {0} {1} {2} {3} ({4})".F(a.ActorID, a.Type, a.Owner, a.Trait, a.Hash)); Log.Write("sync", "\t {0} {1} {2} {3} ({4})".F(a.ActorID, a.Type, a.Owner, a.Trait, a.Hash));
var nvp = a.NamesValues; var nvp = a.NamesValues;
for (int i = 0; i < nvp.First.Length; i++) for (int i = 0; i < nvp.Names.Length; i++)
if (nvp.Second[i] != null) if (nvp.Values[i] != null)
Log.Write("sync", "\t\t {0}: {1}".F(nvp.First[i], nvp.Second[i])); Log.Write("sync", "\t\t {0}: {1}".F(nvp.Names[i], nvp.Values[i]));
} }
Log.Write("sync", "Synced Effects:"); Log.Write("sync", "Synced Effects:");
@@ -131,9 +131,9 @@ namespace OpenRA.Network
Log.Write("sync", "\t {0} ({1})", e.Name, e.Hash); Log.Write("sync", "\t {0} ({1})", e.Name, e.Hash);
var nvp = e.NamesValues; var nvp = e.NamesValues;
for (int i = 0; i < nvp.First.Length; i++) for (int i = 0; i < nvp.Names.Length; i++)
if (nvp.Second[i] != null) if (nvp.Values[i] != null)
Log.Write("sync", "\t\t {0}: {1}".F(nvp.First[i], nvp.Second[i])); Log.Write("sync", "\t\t {0}: {1}".F(nvp.Names[i], nvp.Values[i]));
} }
Log.Write("sync", "Orders Issued:"); Log.Write("sync", "Orders Issued:");
@@ -163,14 +163,14 @@ namespace OpenRA.Network
public string Owner; public string Owner;
public string Trait; public string Trait;
public int Hash; public int Hash;
public Pair<string[], Values> NamesValues; public (string[] Names, Values Values) NamesValues;
} }
struct EffectReport struct EffectReport
{ {
public string Name; public string Name;
public int Hash; public int Hash;
public Pair<string[], Values> NamesValues; public (string[] Names, Values Values) NamesValues;
} }
struct TypeInfo struct TypeInfo

View File

@@ -26,7 +26,7 @@ namespace OpenRA
readonly Cache<string, Type> typeCache; readonly Cache<string, Type> typeCache;
readonly Cache<Type, ConstructorInfo> ctorCache; readonly Cache<Type, ConstructorInfo> ctorCache;
readonly Pair<Assembly, string>[] assemblies; readonly (Assembly Assembly, string Namespace)[] assemblies;
public ObjectCreator(Manifest manifest, InstalledMods mods) public ObjectCreator(Manifest manifest, InstalledMods mods)
{ {
@@ -59,7 +59,7 @@ namespace OpenRA
} }
AppDomain.CurrentDomain.AssemblyResolve += ResolveAssembly; AppDomain.CurrentDomain.AssemblyResolve += ResolveAssembly;
assemblies = assemblyList.SelectMany(asm => asm.GetNamespaces().Select(ns => Pair.New(asm, ns))).ToArray(); assemblies = assemblyList.SelectMany(asm => asm.GetNamespaces().Select(ns => (asm, ns))).ToArray();
} }
Assembly ResolveAssembly(object sender, ResolveEventArgs e) Assembly ResolveAssembly(object sender, ResolveEventArgs e)
@@ -71,7 +71,7 @@ namespace OpenRA
if (assemblies == null) if (assemblies == null)
return null; return null;
return assemblies.Select(a => a.First).FirstOrDefault(a => a.FullName == e.Name); return assemblies.Select(a => a.Assembly).FirstOrDefault(a => a.FullName == e.Name);
} }
// Only used by the linter to prevent exceptions from being thrown during a lint run // Only used by the linter to prevent exceptions from being thrown during a lint run
@@ -106,7 +106,7 @@ namespace OpenRA
public Type FindType(string className) public Type FindType(string className)
{ {
return assemblies return assemblies
.Select(pair => pair.First.GetType(pair.Second + "." + className, false)) .Select(pair => pair.Assembly.GetType(pair.Namespace + "." + className, false))
.FirstOrDefault(t => t != null); .FirstOrDefault(t => t != null);
} }
@@ -146,7 +146,7 @@ namespace OpenRA
public IEnumerable<Type> GetTypes() public IEnumerable<Type> GetTypes()
{ {
return assemblies.Select(ma => ma.First).Distinct() return assemblies.Select(ma => ma.Assembly).Distinct()
.SelectMany(ma => ma.GetTypes()); .SelectMany(ma => ma.GetTypes());
} }

View File

@@ -5,7 +5,7 @@
<AllowUnsafeBlocks>true</AllowUnsafeBlocks> <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<Optimize>true</Optimize> <Optimize>true</Optimize>
<UseVSHostingProcess>false</UseVSHostingProcess> <UseVSHostingProcess>false</UseVSHostingProcess>
<LangVersion>5</LangVersion> <LangVersion>7.3</LangVersion>
<DebugSymbols>true</DebugSymbols> <DebugSymbols>true</DebugSymbols>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors> <TreatWarningsAsErrors>true</TreatWarningsAsErrors>
<AutoGenerateBindingRedirects>false</AutoGenerateBindingRedirects> <AutoGenerateBindingRedirects>false</AutoGenerateBindingRedirects>

View File

@@ -32,7 +32,7 @@ namespace OpenRA
SheetBuilder sheetBuilder; SheetBuilder sheetBuilder;
[FieldLoader.Ignore] [FieldLoader.Ignore]
Cache<Pair<PlayerBadge, int>, Sprite> iconCache; Cache<(PlayerBadge, int), Sprite> iconCache;
Sprite LoadSprite(string url, int density) Sprite LoadSprite(string url, int density)
{ {
@@ -83,15 +83,15 @@ namespace OpenRA
{ {
sheetBuilder = new SheetBuilder(SheetType.BGRA, CreateSheet); sheetBuilder = new SheetBuilder(SheetType.BGRA, CreateSheet);
iconCache = new Cache<Pair<PlayerBadge, int>, Sprite>(p => iconCache = new Cache<(PlayerBadge Badge, int Density), Sprite>(p =>
{ {
if (p.Second > 2 && !string.IsNullOrEmpty(p.First.Icon3x)) if (p.Density > 2 && !string.IsNullOrEmpty(p.Badge.Icon3x))
return LoadSprite(p.First.Icon3x, 3); return LoadSprite(p.Badge.Icon3x, 3);
if (p.Second > 1 && !string.IsNullOrEmpty(p.First.Icon2x)) if (p.Density > 1 && !string.IsNullOrEmpty(p.Badge.Icon2x))
return LoadSprite(p.First.Icon2x, 2); return LoadSprite(p.Badge.Icon2x, 2);
return LoadSprite(p.First.Icon, 1); return LoadSprite(p.Badge.Icon, 1);
}); });
} }
@@ -113,7 +113,7 @@ namespace OpenRA
{ {
var ws = Game.Renderer.WindowScale; var ws = Game.Renderer.WindowScale;
var density = ws > 2 ? 3 : ws > 1 ? 2 : 1; var density = ws > 2 ? 3 : ws > 1 ? 2 : 1;
return iconCache[Pair.New(badge, density)]; return iconCache[(badge, density)];
} }
} }
} }

View File

@@ -1,70 +0,0 @@
#region Copyright & License Information
/*
* Copyright 2007-2020 The OpenRA Developers (see AUTHORS)
* This file is part of OpenRA, which is free software. It is made
* available to you under the terms of the GNU General Public License
* as published by the Free Software Foundation, either version 3 of
* the License, or (at your option) any later version. For more
* information, see COPYING.
*/
#endregion
using System;
using System.Collections.Generic;
namespace OpenRA.Primitives
{
public struct Pair<T, U> : IEquatable<Pair<T, U>>
{
public T First;
public U Second;
public Pair(T first, U second)
{
First = first;
Second = second;
}
internal static IEqualityComparer<T> Tcomparer = EqualityComparer<T>.Default;
internal static IEqualityComparer<U> Ucomparer = EqualityComparer<U>.Default;
public static bool operator ==(Pair<T, U> a, Pair<T, U> b)
{
return Tcomparer.Equals(a.First, b.First) && Ucomparer.Equals(a.Second, b.Second);
}
public static bool operator !=(Pair<T, U> a, Pair<T, U> b)
{
return !(a == b);
}
public override int GetHashCode() { return First.GetHashCode() ^ Second.GetHashCode(); }
public bool Equals(Pair<T, U> other) { return this == other; }
public override bool Equals(object obj) { return obj is Pair<T, U> && Equals((Pair<T, U>)obj); }
public Pair<T, U> WithFirst(T t) { return new Pair<T, U>(t, Second); }
public Pair<T, U> WithSecond(U u) { return new Pair<T, U>(First, u); }
public static T AsFirst(Pair<T, U> p) { return p.First; }
public static U AsSecond(Pair<T, U> p) { return p.Second; }
public override string ToString()
{
return "({0},{1})".F(First, Second);
}
class PairEqualityComparer : IEqualityComparer<Pair<T, U>>
{
public bool Equals(Pair<T, U> x, Pair<T, U> y) { return x == y; }
public int GetHashCode(Pair<T, U> obj) { return obj.GetHashCode(); }
}
public static IEqualityComparer<Pair<T, U>> EqualityComparer { get { return new PairEqualityComparer(); } }
}
public static class Pair
{
public static Pair<T, U> New<T, U>(T t, U u) { return new Pair<T, U>(t, u); }
}
}

View File

@@ -271,7 +271,7 @@ namespace OpenRA.Traits
public interface IMapPreviewSignatureInfo : ITraitInfoInterface public interface IMapPreviewSignatureInfo : ITraitInfoInterface
{ {
void PopulateMapPreviewSignatureCells(Map map, ActorInfo ai, ActorReference s, List<Pair<MPos, Color>> destinationBuffer); void PopulateMapPreviewSignatureCells(Map map, ActorInfo ai, ActorReference s, List<(MPos, Color)> destinationBuffer);
} }
public interface IOccupySpaceInfo : ITraitInfoInterface public interface IOccupySpaceInfo : ITraitInfoInterface
@@ -284,7 +284,7 @@ namespace OpenRA.Traits
{ {
WPos CenterPosition { get; } WPos CenterPosition { get; }
CPos TopLeft { get; } CPos TopLeft { get; }
Pair<CPos, SubCell>[] OccupiedCells(); (CPos Cell, SubCell SubCell)[] OccupiedCells();
} }
public enum SubCell : byte { Invalid = byte.MaxValue, Any = byte.MaxValue - 1, FullCell = 0, First = 1 } public enum SubCell : byte { Invalid = byte.MaxValue, Any = byte.MaxValue - 1, FullCell = 0, First = 1 }

View File

@@ -24,7 +24,7 @@ namespace OpenRA.Mods.Cnc.Graphics
static readonly float[] ChannelSelect = { 0.75f, 0.25f, -0.25f, -0.75f }; static readonly float[] ChannelSelect = { 0.75f, 0.25f, -0.25f, -0.75f };
readonly List<Vertex[]> vertices = new List<Vertex[]>(); readonly List<Vertex[]> vertices = new List<Vertex[]>();
readonly Cache<Pair<string, string>, Voxel> voxels; readonly Cache<(string, string), Voxel> voxels;
readonly IReadOnlyFileSystem fileSystem; readonly IReadOnlyFileSystem fileSystem;
IVertexBuffer<Vertex> vertexBuffer; IVertexBuffer<Vertex> vertexBuffer;
int totalVertexCount; int totalVertexCount;
@@ -49,7 +49,7 @@ namespace OpenRA.Mods.Cnc.Graphics
public VoxelLoader(IReadOnlyFileSystem fileSystem) public VoxelLoader(IReadOnlyFileSystem fileSystem)
{ {
this.fileSystem = fileSystem; this.fileSystem = fileSystem;
voxels = new Cache<Pair<string, string>, Voxel>(LoadFile); voxels = new Cache<(string, string), Voxel>(LoadFile);
vertices = new List<Vertex[]>(); vertices = new List<Vertex[]>();
totalVertexCount = 0; totalVertexCount = 0;
cachedVertexCount = 0; cachedVertexCount = 0;
@@ -211,20 +211,20 @@ namespace OpenRA.Mods.Cnc.Graphics
} }
} }
Voxel LoadFile(Pair<string, string> files) Voxel LoadFile((string Vxl, string Hva) files)
{ {
VxlReader vxl; VxlReader vxl;
HvaReader hva; HvaReader hva;
using (var s = fileSystem.Open(files.First + ".vxl")) using (var s = fileSystem.Open(files.Vxl + ".vxl"))
vxl = new VxlReader(s); vxl = new VxlReader(s);
using (var s = fileSystem.Open(files.Second + ".hva")) using (var s = fileSystem.Open(files.Hva + ".hva"))
hva = new HvaReader(s, files.Second + ".hva"); hva = new HvaReader(s, files.Hva + ".hva");
return new Voxel(this, vxl, hva); return new Voxel(this, vxl, hva);
} }
public Voxel Load(string vxl, string hva) public Voxel Load(string vxl, string hva)
{ {
return voxels[Pair.New(vxl, hva)]; return voxels[(vxl, hva)];
} }
public void Finish() public void Finish()

View File

@@ -3,7 +3,7 @@
<TargetFramework>net472</TargetFramework> <TargetFramework>net472</TargetFramework>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks> <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<Optimize>true</Optimize> <Optimize>true</Optimize>
<LangVersion>5</LangVersion> <LangVersion>7.3</LangVersion>
<DebugSymbols>true</DebugSymbols> <DebugSymbols>true</DebugSymbols>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors> <TreatWarningsAsErrors>true</TreatWarningsAsErrors>
<OutputPath>../mods/common</OutputPath> <OutputPath>../mods/common</OutputPath>

View File

@@ -146,7 +146,7 @@ namespace OpenRA.Mods.Cnc.Traits
get { return OpenRA.Mods.Common.Util.ApplyPercentageModifiers(Info.Speed, speedModifiers); } get { return OpenRA.Mods.Common.Util.ApplyPercentageModifiers(Info.Speed, speedModifiers); }
} }
public Pair<CPos, SubCell>[] OccupiedCells() { return new[] { Pair.New(TopLeft, SubCell.FullCell) }; } public (CPos, SubCell)[] OccupiedCells() { return new[] { (TopLeft, SubCell.FullCell) }; }
WVec MoveStep(WAngle facing) WVec MoveStep(WAngle facing)
{ {

View File

@@ -17,7 +17,6 @@ using System.Text;
using OpenRA.Mods.Cnc.FileFormats; using OpenRA.Mods.Cnc.FileFormats;
using OpenRA.Mods.Common.FileFormats; using OpenRA.Mods.Common.FileFormats;
using OpenRA.Mods.Common.UtilityCommands; using OpenRA.Mods.Common.UtilityCommands;
using OpenRA.Primitives;
namespace OpenRA.Mods.Cnc.UtilityCommands namespace OpenRA.Mods.Cnc.UtilityCommands
{ {
@@ -52,17 +51,17 @@ namespace OpenRA.Mods.Cnc.UtilityCommands
"fpls", "wcrate", "scrate", "barb", "sbag", "fpls", "wcrate", "scrate", "barb", "sbag",
}; };
static Dictionary<string, Pair<byte, byte>> overlayResourceMapping = new Dictionary<string, Pair<byte, byte>>() static Dictionary<string, (byte Type, byte Index)> overlayResourceMapping = new Dictionary<string, (byte, byte)>()
{ {
// RA ore & crystals // RA ore & crystals
{ "gold01", new Pair<byte, byte>(1, 0) }, { "gold01", (1, 0) },
{ "gold02", new Pair<byte, byte>(1, 1) }, { "gold02", (1, 1) },
{ "gold03", new Pair<byte, byte>(1, 2) }, { "gold03", (1, 2) },
{ "gold04", new Pair<byte, byte>(1, 3) }, { "gold04", (1, 3) },
{ "gem01", new Pair<byte, byte>(2, 0) }, { "gem01", (2, 0) },
{ "gem02", new Pair<byte, byte>(2, 1) }, { "gem02", (2, 1) },
{ "gem03", new Pair<byte, byte>(2, 2) }, { "gem03", (2, 2) },
{ "gem04", new Pair<byte, byte>(2, 3) }, { "gem04", (2, 3) },
}; };
void UnpackTileData(MemoryStream ms) void UnpackTileData(MemoryStream ms)
@@ -101,13 +100,13 @@ namespace OpenRA.Mods.Cnc.UtilityCommands
for (var i = 0; i < MapSize; i++) for (var i = 0; i < MapSize; i++)
{ {
var o = ms.ReadUInt8(); var o = ms.ReadUInt8();
var res = Pair.New((byte)0, (byte)0); var res = (Type: (byte)0, Index: (byte)0);
if (o != 255 && overlayResourceMapping.ContainsKey(redAlertOverlayNames[o])) if (o != 255 && overlayResourceMapping.ContainsKey(redAlertOverlayNames[o]))
res = overlayResourceMapping[redAlertOverlayNames[o]]; res = overlayResourceMapping[redAlertOverlayNames[o]];
var cell = new CPos(i, j); var cell = new CPos(i, j);
Map.Resources[cell] = new ResourceTile(res.First, res.Second); Map.Resources[cell] = new ResourceTile(res.Type, res.Index);
if (o != 255 && overlayActors.Contains(redAlertOverlayNames[o])) if (o != 255 && overlayActors.Contains(redAlertOverlayNames[o]))
{ {

View File

@@ -15,7 +15,6 @@ using System.IO;
using System.Linq; using System.Linq;
using OpenRA.Mods.Common.FileFormats; using OpenRA.Mods.Common.FileFormats;
using OpenRA.Mods.Common.UtilityCommands; using OpenRA.Mods.Common.UtilityCommands;
using OpenRA.Primitives;
namespace OpenRA.Mods.Cnc.UtilityCommands namespace OpenRA.Mods.Cnc.UtilityCommands
{ {
@@ -40,21 +39,21 @@ namespace OpenRA.Mods.Cnc.UtilityCommands
} }
} }
static Dictionary<string, Pair<byte, byte>> overlayResourceMapping = new Dictionary<string, Pair<byte, byte>>() static Dictionary<string, (byte Type, byte Index)> overlayResourceMapping = new Dictionary<string, (byte, byte)>()
{ {
// Tiberium // Tiberium
{ "ti1", new Pair<byte, byte>(1, 0) }, { "ti1", (1, 0) },
{ "ti2", new Pair<byte, byte>(1, 1) }, { "ti2", (1, 1) },
{ "ti3", new Pair<byte, byte>(1, 2) }, { "ti3", (1, 2) },
{ "ti4", new Pair<byte, byte>(1, 3) }, { "ti4", (1, 3) },
{ "ti5", new Pair<byte, byte>(1, 4) }, { "ti5", (1, 4) },
{ "ti6", new Pair<byte, byte>(1, 5) }, { "ti6", (1, 5) },
{ "ti7", new Pair<byte, byte>(1, 6) }, { "ti7", (1, 6) },
{ "ti8", new Pair<byte, byte>(1, 7) }, { "ti8", (1, 7) },
{ "ti9", new Pair<byte, byte>(1, 8) }, { "ti9", (1, 8) },
{ "ti10", new Pair<byte, byte>(1, 9) }, { "ti10", (1, 9) },
{ "ti11", new Pair<byte, byte>(1, 10) }, { "ti11", (1, 10) },
{ "ti12", new Pair<byte, byte>(1, 11) }, { "ti12", (1, 11) },
}; };
void UnpackTileData(Stream ms) void UnpackTileData(Stream ms)
@@ -93,12 +92,12 @@ namespace OpenRA.Mods.Cnc.UtilityCommands
var loc = Exts.ParseIntegerInvariant(kv.Key); var loc = Exts.ParseIntegerInvariant(kv.Key);
var cell = new CPos(loc % MapSize, loc / MapSize); var cell = new CPos(loc % MapSize, loc / MapSize);
var res = Pair.New((byte)0, (byte)0); var res = (Type: (byte)0, Index: (byte)0);
var type = kv.Value.ToLowerInvariant(); var type = kv.Value.ToLowerInvariant();
if (overlayResourceMapping.ContainsKey(type)) if (overlayResourceMapping.ContainsKey(type))
res = overlayResourceMapping[type]; res = overlayResourceMapping[type];
Map.Resources[cell] = new ResourceTile(res.First, res.Second); Map.Resources[cell] = new ResourceTile(res.Type, res.Index);
if (overlayActors.Contains(type)) if (overlayActors.Contains(type))
{ {
var ar = new ActorReference(type) var ar = new ActorReference(type)

View File

@@ -201,16 +201,16 @@ namespace OpenRA.Mods.Common.Activities
if (nextCell == null) if (nextCell == null)
return false; return false;
var firstFacing = self.World.Map.FacingBetween(mobile.FromCell, nextCell.Value.First, mobile.Facing); var firstFacing = self.World.Map.FacingBetween(mobile.FromCell, nextCell.Value.Cell, mobile.Facing);
if (firstFacing != mobile.Facing) if (firstFacing != mobile.Facing)
{ {
path.Add(nextCell.Value.First); path.Add(nextCell.Value.Cell);
QueueChild(new Turn(self, firstFacing)); QueueChild(new Turn(self, firstFacing));
mobile.TurnToMove = true; mobile.TurnToMove = true;
return false; return false;
} }
mobile.SetLocation(mobile.FromCell, mobile.FromSubCell, nextCell.Value.First, nextCell.Value.Second); mobile.SetLocation(mobile.FromCell, mobile.FromSubCell, nextCell.Value.Cell, nextCell.Value.SubCell);
var map = self.World.Map; var map = self.World.Map;
var from = (mobile.FromCell.Layer == 0 ? map.CenterOfCell(mobile.FromCell) : var from = (mobile.FromCell.Layer == 0 ? map.CenterOfCell(mobile.FromCell) :
@@ -224,7 +224,7 @@ namespace OpenRA.Mods.Common.Activities
return false; return false;
} }
Pair<CPos, SubCell>? PopPath(Actor self) (CPos Cell, SubCell SubCell)? PopPath(Actor self)
{ {
if (path.Count == 0) if (path.Count == 0)
return null; return null;
@@ -310,7 +310,7 @@ namespace OpenRA.Mods.Common.Activities
var newCell = path[path.Count - 1]; var newCell = path[path.Count - 1];
path.RemoveAt(path.Count - 1); path.RemoveAt(path.Count - 1);
return Pair.New(newCell, mobile.GetAvailableSubCell(nextCell, mobile.FromSubCell, ignoreActor)); return (newCell, mobile.GetAvailableSubCell(nextCell, mobile.FromSubCell, ignoreActor));
} }
else if (mobile.IsBlocking) else if (mobile.IsBlocking)
{ {
@@ -321,7 +321,7 @@ namespace OpenRA.Mods.Common.Activities
if ((nextCell - newCell).Value.LengthSquared > 2) if ((nextCell - newCell).Value.LengthSquared > 2)
path.Add(mobile.ToCell); path.Add(mobile.ToCell);
return Pair.New(newCell.Value, mobile.GetAvailableSubCell(newCell.Value, mobile.FromSubCell, ignoreActor)); return (newCell.Value, mobile.GetAvailableSubCell(newCell.Value, mobile.FromSubCell, ignoreActor));
} }
} }
@@ -331,7 +331,7 @@ namespace OpenRA.Mods.Common.Activities
hasWaited = false; hasWaited = false;
path.RemoveAt(path.Count - 1); path.RemoveAt(path.Count - 1);
return Pair.New(nextCell, mobile.GetAvailableSubCell(nextCell, mobile.FromSubCell, ignoreActor)); return (nextCell, mobile.GetAvailableSubCell(nextCell, mobile.FromSubCell, ignoreActor));
} }
protected override void OnLastRun(Actor self) protected override void OnLastRun(Actor self)
@@ -518,23 +518,23 @@ namespace OpenRA.Mods.Common.Activities
var nextCell = parent.PopPath(self); var nextCell = parent.PopPath(self);
if (nextCell != null) if (nextCell != null)
{ {
if (!mobile.IsTraitPaused && !mobile.IsTraitDisabled && IsTurn(mobile, nextCell.Value.First, map)) if (!mobile.IsTraitPaused && !mobile.IsTraitDisabled && IsTurn(mobile, nextCell.Value.Cell, map))
{ {
var nextSubcellOffset = map.Grid.OffsetOfSubCell(nextCell.Value.Second); var nextSubcellOffset = map.Grid.OffsetOfSubCell(nextCell.Value.SubCell);
var ret = new MoveFirstHalf( var ret = new MoveFirstHalf(
Move, Move,
Util.BetweenCells(self.World, mobile.FromCell, mobile.ToCell) + (fromSubcellOffset + toSubcellOffset) / 2, Util.BetweenCells(self.World, mobile.FromCell, mobile.ToCell) + (fromSubcellOffset + toSubcellOffset) / 2,
Util.BetweenCells(self.World, mobile.ToCell, nextCell.Value.First) + (toSubcellOffset + nextSubcellOffset) / 2, Util.BetweenCells(self.World, mobile.ToCell, nextCell.Value.Cell) + (toSubcellOffset + nextSubcellOffset) / 2,
mobile.Facing, mobile.Facing,
map.FacingBetween(mobile.ToCell, nextCell.Value.First, mobile.Facing), map.FacingBetween(mobile.ToCell, nextCell.Value.Cell, mobile.Facing),
moveFraction - MoveFractionTotal); moveFraction - MoveFractionTotal);
mobile.FinishedMoving(self); mobile.FinishedMoving(self);
mobile.SetLocation(mobile.ToCell, mobile.ToSubCell, nextCell.Value.First, nextCell.Value.Second); mobile.SetLocation(mobile.ToCell, mobile.ToSubCell, nextCell.Value.Cell, nextCell.Value.SubCell);
return ret; return ret;
} }
parent.path.Add(nextCell.Value.First); parent.path.Add(nextCell.Value.Cell);
} }
var toPos = mobile.ToCell.Layer == 0 ? map.CenterOfCell(mobile.ToCell) : var toPos = mobile.ToCell.Layer == 0 ? map.CenterOfCell(mobile.ToCell) :

View File

@@ -50,15 +50,15 @@ namespace OpenRA.Mods.Common.Activities
this.unloadRange = unloadRange; this.unloadRange = unloadRange;
} }
public Pair<CPos, SubCell>? ChooseExitSubCell(Actor passenger) public (CPos Cell, SubCell SubCell)? ChooseExitSubCell(Actor passenger)
{ {
var pos = passenger.Trait<IPositionable>(); var pos = passenger.Trait<IPositionable>();
return cargo.CurrentAdjacentCells return cargo.CurrentAdjacentCells
.Shuffle(self.World.SharedRandom) .Shuffle(self.World.SharedRandom)
.Select(c => Pair.New(c, pos.GetAvailableSubCell(c))) .Select(c => (c, pos.GetAvailableSubCell(c)))
.Cast<Pair<CPos, SubCell>?>() .Cast<(CPos, SubCell SubCell)?>()
.FirstOrDefault(s => s.Value.Second != SubCell.Invalid); .FirstOrDefault(s => s.Value.SubCell != SubCell.Invalid);
} }
IEnumerable<CPos> BlockedExitCells(Actor passenger) IEnumerable<CPos> BlockedExitCells(Actor passenger)
@@ -121,7 +121,7 @@ namespace OpenRA.Mods.Common.Activities
var move = actor.Trait<IMove>(); var move = actor.Trait<IMove>();
var pos = actor.Trait<IPositionable>(); var pos = actor.Trait<IPositionable>();
pos.SetPosition(actor, exitSubCell.Value.First, exitSubCell.Value.Second); pos.SetPosition(actor, exitSubCell.Value.Cell, exitSubCell.Value.SubCell);
pos.SetVisualPosition(actor, spawn); pos.SetVisualPosition(actor, spawn);
actor.CancelActivity(); actor.CancelActivity();

View File

@@ -116,7 +116,7 @@ namespace OpenRA.Mods.Common.Widgets
var dest = new CellRegion(gridType, source.TopLeft + offset, source.BottomRight + offset); var dest = new CellRegion(gridType, source.TopLeft + offset, source.BottomRight + offset);
var previews = new Dictionary<string, ActorReference>(); var previews = new Dictionary<string, ActorReference>();
var tiles = new Dictionary<CPos, Tuple<TerrainTile, ResourceTile, byte>>(); var tiles = new Dictionary<CPos, (TerrainTile, ResourceTile, byte)>();
var copyFilters = getCopyFilters(); var copyFilters = getCopyFilters();
foreach (var cell in source) foreach (var cell in source)
@@ -124,7 +124,7 @@ namespace OpenRA.Mods.Common.Widgets
if (!mapTiles.Contains(cell) || !mapTiles.Contains(cell + offset)) if (!mapTiles.Contains(cell) || !mapTiles.Contains(cell + offset))
continue; continue;
tiles.Add(cell + offset, Tuple.Create(mapTiles[cell], mapResources[cell], mapHeight[cell])); tiles.Add(cell + offset, (mapTiles[cell], mapResources[cell], mapHeight[cell]));
if (copyFilters.HasFlag(MapCopyFilters.Actors)) if (copyFilters.HasFlag(MapCopyFilters.Actors))
{ {
@@ -178,7 +178,7 @@ namespace OpenRA.Mods.Common.Widgets
public string Text { get; private set; } public string Text { get; private set; }
readonly MapCopyFilters copyFilters; readonly MapCopyFilters copyFilters;
readonly Dictionary<CPos, Tuple<TerrainTile, ResourceTile, byte>> tiles; readonly Dictionary<CPos, (TerrainTile Tile, ResourceTile Resource, byte Height)> tiles;
readonly Dictionary<string, ActorReference> previews; readonly Dictionary<string, ActorReference> previews;
readonly EditorActorLayer editorLayer; readonly EditorActorLayer editorLayer;
readonly CellRegion dest; readonly CellRegion dest;
@@ -191,7 +191,7 @@ namespace OpenRA.Mods.Common.Widgets
readonly Queue<EditorActorPreview> addedActorPreviews = new Queue<EditorActorPreview>(); readonly Queue<EditorActorPreview> addedActorPreviews = new Queue<EditorActorPreview>();
public CopyPasteEditorAction(MapCopyFilters copyFilters, Map map, public CopyPasteEditorAction(MapCopyFilters copyFilters, Map map,
Dictionary<CPos, Tuple<TerrainTile, ResourceTile, byte>> tiles, Dictionary<string, ActorReference> previews, Dictionary<CPos, (TerrainTile, ResourceTile, byte)> tiles, Dictionary<string, ActorReference> previews,
EditorActorLayer editorLayer, CellRegion dest) EditorActorLayer editorLayer, CellRegion dest)
{ {
this.copyFilters = copyFilters; this.copyFilters = copyFilters;
@@ -219,12 +219,12 @@ namespace OpenRA.Mods.Common.Widgets
undoCopyPastes.Enqueue(new UndoCopyPaste(kv.Key, mapTiles[kv.Key], mapResources[kv.Key], mapHeight[kv.Key])); undoCopyPastes.Enqueue(new UndoCopyPaste(kv.Key, mapTiles[kv.Key], mapResources[kv.Key], mapHeight[kv.Key]));
if (copyFilters.HasFlag(MapCopyFilters.Terrain)) if (copyFilters.HasFlag(MapCopyFilters.Terrain))
mapTiles[kv.Key] = kv.Value.Item1; mapTiles[kv.Key] = kv.Value.Tile;
if (copyFilters.HasFlag(MapCopyFilters.Resources)) if (copyFilters.HasFlag(MapCopyFilters.Resources))
mapResources[kv.Key] = kv.Value.Item2; mapResources[kv.Key] = kv.Value.Resource;
mapHeight[kv.Key] = kv.Value.Item3; mapHeight[kv.Key] = kv.Value.Height;
} }
if (copyFilters.HasFlag(MapCopyFilters.Actors)) if (copyFilters.HasFlag(MapCopyFilters.Actors))

View File

@@ -133,7 +133,7 @@ namespace OpenRA.Mods.Common.Graphics
// HACK: We don't have enough texture channels to pass the depth data to the shader // HACK: We don't have enough texture channels to pass the depth data to the shader
// so for now just offset everything forward so that the back corner is rendered at pos. // so for now just offset everything forward so that the back corner is rendered at pos.
pxOrigin -= new float3(0, 0, Screen3DBounds(wr).Second.X); pxOrigin -= new float3(0, 0, Screen3DBounds(wr).Z.X);
var shadowOrigin = pxOrigin - groundZ * (new float2(renderProxy.ShadowDirection, 1)); var shadowOrigin = pxOrigin - groundZ * (new float2(renderProxy.ShadowDirection, 1));
@@ -221,10 +221,10 @@ namespace OpenRA.Mods.Common.Graphics
public Rectangle ScreenBounds(WorldRenderer wr) public Rectangle ScreenBounds(WorldRenderer wr)
{ {
return Screen3DBounds(wr).First; return Screen3DBounds(wr).Bounds;
} }
Pair<Rectangle, float2> Screen3DBounds(WorldRenderer wr) (Rectangle Bounds, float2 Z) Screen3DBounds(WorldRenderer wr)
{ {
var pxOrigin = wr.ScreenPosition(model.pos); var pxOrigin = wr.ScreenPosition(model.pos);
var draw = model.models.Where(v => v.IsVisible); var draw = model.models.Where(v => v.IsVisible);
@@ -260,7 +260,7 @@ namespace OpenRA.Mods.Common.Graphics
} }
} }
return Pair.New(Rectangle.FromLTRB((int)minX, (int)minY, (int)maxX, (int)maxY), new float2(minZ, maxZ)); return (Rectangle.FromLTRB((int)minX, (int)minY, (int)maxX, (int)maxY), new float2(minZ, maxZ));
} }
} }
} }

View File

@@ -106,13 +106,13 @@ namespace OpenRA.Mods.Common.Graphics
public Rectangle ScreenBounds(WorldRenderer wr) public Rectangle ScreenBounds(WorldRenderer wr)
{ {
return Screen3DBounds(wr).First; return Screen3DBounds(wr).Bounds;
} }
static readonly uint[] CornerXIndex = { 0, 0, 0, 0, 3, 3, 3, 3 }; static readonly uint[] CornerXIndex = { 0, 0, 0, 0, 3, 3, 3, 3 };
static readonly uint[] CornerYIndex = { 1, 1, 4, 4, 1, 1, 4, 4 }; static readonly uint[] CornerYIndex = { 1, 1, 4, 4, 1, 1, 4, 4 };
static readonly uint[] CornerZIndex = { 2, 5, 2, 5, 2, 5, 2, 5 }; static readonly uint[] CornerZIndex = { 2, 5, 2, 5, 2, 5, 2, 5 };
Pair<Rectangle, float2> Screen3DBounds(WorldRenderer wr) (Rectangle Bounds, float2 Z) Screen3DBounds(WorldRenderer wr)
{ {
var pxOrigin = model.screenPos; var pxOrigin = model.screenPos;
var draw = model.models.Where(v => v.IsVisible); var draw = model.models.Where(v => v.IsVisible);
@@ -148,7 +148,7 @@ namespace OpenRA.Mods.Common.Graphics
} }
} }
return Pair.New(Rectangle.FromLTRB((int)minX, (int)minY, (int)maxX, (int)maxY), new float2(minZ, maxZ)); return (Rectangle.FromLTRB((int)minX, (int)minY, (int)maxX, (int)maxY), new float2(minZ, maxZ));
} }
} }
} }

View File

@@ -41,7 +41,7 @@ namespace OpenRA.Mods.Common.Lint
var checkWidgetFields = modData.ObjectCreator.GetTypesImplementing<Widget>() var checkWidgetFields = modData.ObjectCreator.GetTypesImplementing<Widget>()
.SelectMany(w => w.GetFields() .SelectMany(w => w.GetFields()
.Where(f => f.FieldType == typeof(HotkeyReference)) .Where(f => f.FieldType == typeof(HotkeyReference))
.Select(f => Pair.New(w.Name.Substring(0, w.Name.Length - 6), f.Name))) .Select(f => (w.Name.Substring(0, w.Name.Length - 6), f.Name)))
.ToArray(); .ToArray();
var customLintMethods = new Dictionary<string, List<string>>(); var customLintMethods = new Dictionary<string, List<string>>();
@@ -64,7 +64,7 @@ namespace OpenRA.Mods.Common.Lint
} }
} }
void CheckInner(ModData modData, string[] namedKeys, Pair<string, string>[] checkWidgetFields, Dictionary<string, List<string>> customLintMethods, void CheckInner(ModData modData, string[] namedKeys, (string Widget, string Field)[] checkWidgetFields, Dictionary<string, List<string>> customLintMethods,
List<MiniYamlNode> nodes, string filename, MiniYamlNode parent, Action<string> emitError, Action<string> emitWarning) List<MiniYamlNode> nodes, string filename, MiniYamlNode parent, Action<string> emitError, Action<string> emitWarning)
{ {
foreach (var node in nodes) foreach (var node in nodes)
@@ -74,19 +74,17 @@ namespace OpenRA.Mods.Common.Lint
foreach (var x in checkWidgetFields) foreach (var x in checkWidgetFields)
{ {
if (node.Key == x.Second && parent != null && parent.Key.StartsWith(x.First, StringComparison.Ordinal)) if (node.Key == x.Field && parent != null && parent.Key.StartsWith(x.Widget, StringComparison.Ordinal))
{ {
// Keys are valid if they refer to a named key or can be parsed as a regular Hotkey. // Keys are valid if they refer to a named key or can be parsed as a regular Hotkey.
Hotkey unused; if (!namedKeys.Contains(node.Value.Value) && !Hotkey.TryParse(node.Value.Value, out var unused))
if (!namedKeys.Contains(node.Value.Value) && !Hotkey.TryParse(node.Value.Value, out unused))
emitError("{0} refers to a Key named `{1}` that does not exist".F(node.Location, node.Value.Value)); emitError("{0} refers to a Key named `{1}` that does not exist".F(node.Location, node.Value.Value));
} }
} }
// Check runtime-defined hotkey names // Check runtime-defined hotkey names
List<string> checkMethods;
var widgetType = node.Key.Split('@')[0]; var widgetType = node.Key.Split('@')[0];
if (customLintMethods.TryGetValue(widgetType, out checkMethods)) if (customLintMethods.TryGetValue(widgetType, out var checkMethods))
{ {
var type = modData.ObjectCreator.FindType(widgetType + "Widget"); var type = modData.ObjectCreator.FindType(widgetType + "Widget");
var keyNames = checkMethods.SelectMany(m => (IEnumerable<string>)type.GetMethod(m).Invoke(null, new object[] { node, emitError, emitWarning })); var keyNames = checkMethods.SelectMany(m => (IEnumerable<string>)type.GetMethod(m).Invoke(null, new object[] { node, emitError, emitWarning }));
@@ -111,10 +109,9 @@ namespace OpenRA.Mods.Common.Lint
checkArgKeys.AddRange(type.GetCustomAttributes<ChromeLogicArgsHotkeys>(true).SelectMany(x => x.LogicArgKeys)); checkArgKeys.AddRange(type.GetCustomAttributes<ChromeLogicArgsHotkeys>(true).SelectMany(x => x.LogicArgKeys));
} }
Hotkey unused;
foreach (var n in node.Value.Nodes) foreach (var n in node.Value.Nodes)
if (checkArgKeys.Contains(n.Key)) if (checkArgKeys.Contains(n.Key))
if (!namedKeys.Contains(n.Value.Value) && !Hotkey.TryParse(n.Value.Value, out unused)) if (!namedKeys.Contains(n.Value.Value) && !Hotkey.TryParse(n.Value.Value, out var unused))
emitError("{0} {1}:{2} refers to a Key named `{3}` that does not exist".F(filename, node.Value.Value, n.Key, n.Value.Value)); emitError("{0} {1}:{2} refers to a Key named `{3}` that does not exist".F(filename, node.Value.Value, n.Key, n.Value.Value));
} }

View File

@@ -3,7 +3,7 @@
<TargetFramework>net472</TargetFramework> <TargetFramework>net472</TargetFramework>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks> <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<Optimize>true</Optimize> <Optimize>true</Optimize>
<LangVersion>5</LangVersion> <LangVersion>7.3</LangVersion>
<DebugSymbols>true</DebugSymbols> <DebugSymbols>true</DebugSymbols>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors> <TreatWarningsAsErrors>true</TreatWarningsAsErrors>
<OutputPath>../mods/common</OutputPath> <OutputPath>../mods/common</OutputPath>

View File

@@ -262,9 +262,9 @@ namespace OpenRA.Mods.Common.Orders
{ {
foreach (var t in BuildingUtils.GetLineBuildCells(world, topLeft, actorInfo, buildingInfo, owner)) foreach (var t in BuildingUtils.GetLineBuildCells(world, topLeft, actorInfo, buildingInfo, owner))
{ {
var lineBuildable = world.IsCellBuildable(t.First, actorInfo, buildingInfo); var lineBuildable = world.IsCellBuildable(t.Cell, actorInfo, buildingInfo);
var lineCloseEnough = buildingInfo.IsCloseEnoughToBase(world, world.LocalPlayer, actorInfo, t.First); var lineCloseEnough = buildingInfo.IsCloseEnoughToBase(world, world.LocalPlayer, actorInfo, t.Cell);
footprint.Add(t.First, MakeCellType(lineBuildable && lineCloseEnough, true)); footprint.Add(t.Cell, MakeCellType(lineBuildable && lineCloseEnough, true));
} }
} }

View File

@@ -27,7 +27,7 @@ namespace OpenRA.Mods.Common.Pathfinder
/// <summary> /// <summary>
/// Stores the analyzed nodes by the expand function /// Stores the analyzed nodes by the expand function
/// </summary> /// </summary>
IEnumerable<Pair<CPos, int>> Considered { get; } IEnumerable<(CPos Cell, int Cost)> Considered { get; }
Player Owner { get; } Player Owner { get; }
@@ -68,7 +68,7 @@ namespace OpenRA.Mods.Common.Pathfinder
protected IPriorityQueue<GraphConnection> OpenQueue { get; private set; } protected IPriorityQueue<GraphConnection> OpenQueue { get; private set; }
public abstract IEnumerable<Pair<CPos, int>> Considered { get; } public abstract IEnumerable<(CPos Cell, int Cost)> Considered { get; }
public Player Owner { get { return Graph.Actor.Owner; } } public Player Owner { get { return Graph.Actor.Owner; } }
public int MaxCost { get; protected set; } public int MaxCost { get; protected set; }

View File

@@ -92,8 +92,8 @@ namespace OpenRA.Mods.Common.Pathfinder
readonly bool checkTerrainHeight; readonly bool checkTerrainHeight;
CellLayer<CellInfo> groundInfo; CellLayer<CellInfo> groundInfo;
readonly Dictionary<byte, Pair<ICustomMovementLayer, CellLayer<CellInfo>>> customLayerInfo = readonly Dictionary<byte, (ICustomMovementLayer Layer, CellLayer<CellInfo> Info)> customLayerInfo =
new Dictionary<byte, Pair<ICustomMovementLayer, CellLayer<CellInfo>>>(); new Dictionary<byte, (ICustomMovementLayer, CellLayer<CellInfo>)>();
public PathGraph(CellInfoLayerPool layerPool, Locomotor locomotor, Actor actor, World world, BlockedByActor check) public PathGraph(CellInfoLayerPool layerPool, Locomotor locomotor, Actor actor, World world, BlockedByActor check)
{ {
@@ -105,7 +105,7 @@ namespace OpenRA.Mods.Common.Pathfinder
.Where(cml => cml.EnabledForActor(actor.Info, locomotorInfo)); .Where(cml => cml.EnabledForActor(actor.Info, locomotorInfo));
foreach (var cml in layers) foreach (var cml in layers)
customLayerInfo[cml.Index] = Pair.New(cml, pooledLayer.GetLayer()); customLayerInfo[cml.Index] = (cml, pooledLayer.GetLayer());
World = world; World = world;
worldMovementInfo = locomotorInfo.GetWorldMovementInfo(world); worldMovementInfo = locomotorInfo.GetWorldMovementInfo(world);
@@ -135,7 +135,7 @@ namespace OpenRA.Mods.Common.Pathfinder
public List<GraphConnection> GetConnections(CPos position) public List<GraphConnection> GetConnections(CPos position)
{ {
var info = position.Layer == 0 ? groundInfo : customLayerInfo[position.Layer].Second; var info = position.Layer == 0 ? groundInfo : customLayerInfo[position.Layer].Info;
var previousPos = info[position].PreviousPos; var previousPos = info[position].PreviousPos;
var dx = position.X - previousPos.X; var dx = position.X - previousPos.X;
@@ -156,8 +156,8 @@ namespace OpenRA.Mods.Common.Pathfinder
{ {
foreach (var cli in customLayerInfo.Values) foreach (var cli in customLayerInfo.Values)
{ {
var layerPosition = new CPos(position.X, position.Y, cli.First.Index); var layerPosition = new CPos(position.X, position.Y, cli.Layer.Index);
var entryCost = cli.First.EntryMovementCost(Actor.Info, locomotor.Info, layerPosition); var entryCost = cli.Layer.EntryMovementCost(Actor.Info, locomotor.Info, layerPosition);
if (entryCost != CostForInvalidCell) if (entryCost != CostForInvalidCell)
validNeighbors.Add(new GraphConnection(layerPosition, entryCost)); validNeighbors.Add(new GraphConnection(layerPosition, entryCost));
} }
@@ -165,7 +165,7 @@ namespace OpenRA.Mods.Common.Pathfinder
else else
{ {
var layerPosition = new CPos(position.X, position.Y, 0); var layerPosition = new CPos(position.X, position.Y, 0);
var exitCost = customLayerInfo[position.Layer].First.ExitMovementCost(Actor.Info, locomotor.Info, layerPosition); var exitCost = customLayerInfo[position.Layer].Layer.ExitMovementCost(Actor.Info, locomotor.Info, layerPosition);
if (exitCost != CostForInvalidCell) if (exitCost != CostForInvalidCell)
validNeighbors.Add(new GraphConnection(layerPosition, exitCost)); validNeighbors.Add(new GraphConnection(layerPosition, exitCost));
} }
@@ -224,8 +224,8 @@ namespace OpenRA.Mods.Common.Pathfinder
public CellInfo this[CPos pos] public CellInfo this[CPos pos]
{ {
get { return (pos.Layer == 0 ? groundInfo : customLayerInfo[pos.Layer].Second)[pos]; } get { return (pos.Layer == 0 ? groundInfo : customLayerInfo[pos.Layer].Info)[pos]; }
set { (pos.Layer == 0 ? groundInfo : customLayerInfo[pos.Layer].Second)[pos] = value; } set { (pos.Layer == 0 ? groundInfo : customLayerInfo[pos.Layer].Info)[pos] = value; }
} }
public void Dispose() public void Dispose()

View File

@@ -30,19 +30,19 @@ namespace OpenRA.Mods.Common.Pathfinder
return LayerPoolTable.GetValue(world, CreateLayerPool); return LayerPoolTable.GetValue(world, CreateLayerPool);
} }
public override IEnumerable<Pair<CPos, int>> Considered public override IEnumerable<(CPos, int)> Considered
{ {
get { return considered; } get { return considered; }
} }
LinkedList<Pair<CPos, int>> considered; LinkedList<(CPos, int)> considered;
#region Constructors #region Constructors
private PathSearch(IGraph<CellInfo> graph) private PathSearch(IGraph<CellInfo> graph)
: base(graph) : base(graph)
{ {
considered = new LinkedList<Pair<CPos, int>>(); considered = new LinkedList<(CPos, int)>();
} }
public static IPathSearch Search(World world, Locomotor locomotor, Actor self, BlockedByActor check, Func<CPos, bool> goalCondition) public static IPathSearch Search(World world, Locomotor locomotor, Actor self, BlockedByActor check, Func<CPos, bool> goalCondition)
@@ -94,7 +94,7 @@ namespace OpenRA.Mods.Common.Pathfinder
var connection = new GraphConnection(location, cost); var connection = new GraphConnection(location, cost);
OpenQueue.Add(connection); OpenQueue.Add(connection);
StartPoints.Add(connection); StartPoints.Add(connection);
considered.AddLast(new Pair<CPos, int>(location, 0)); considered.AddLast((location, 0));
} }
#endregion #endregion
@@ -146,7 +146,7 @@ namespace OpenRA.Mods.Common.Pathfinder
if (gCost > MaxCost) if (gCost > MaxCost)
MaxCost = gCost; MaxCost = gCost;
considered.AddLast(new Pair<CPos, int>(neighborCPos, gCost)); considered.AddLast((neighborCPos, gCost));
} }
} }

View File

@@ -31,7 +31,7 @@ namespace OpenRA.Mods.Common.Scripting
public Actor[] TargetParatroopers(WPos target, WAngle? facing = null) public Actor[] TargetParatroopers(WPos target, WAngle? facing = null)
{ {
var actors = pp.SendParatroopers(Self, target, facing); var actors = pp.SendParatroopers(Self, target, facing);
return actors.First; return actors.Aircraft;
} }
[Desc("Activate the actor's Paratroopers Power. Returns the aircraft that will drop the reinforcements. DEPRECATED! Will be removed.")] [Desc("Activate the actor's Paratroopers Power. Returns the aircraft that will drop the reinforcements. DEPRECATED! Will be removed.")]
@@ -39,7 +39,7 @@ namespace OpenRA.Mods.Common.Scripting
{ {
Game.Debug("SendParatroopersFrom is deprecated. Use TargetParatroopers instead."); Game.Debug("SendParatroopersFrom is deprecated. Use TargetParatroopers instead.");
var actors = pp.SendParatroopers(Self, target, facing == -1 ? (WAngle?)null : WAngle.FromFacing(facing)); var actors = pp.SendParatroopers(Self, target, facing == -1 ? (WAngle?)null : WAngle.FromFacing(facing));
return actors.First; return actors.Aircraft;
} }
} }
} }

View File

@@ -9,18 +9,17 @@
*/ */
#endregion #endregion
using OpenRA.Primitives;
using OpenRA.Traits; using OpenRA.Traits;
namespace OpenRA.Mods.Common namespace OpenRA.Mods.Common
{ {
public static class ShroudExts public static class ShroudExts
{ {
public static bool AnyExplored(this Shroud shroud, Pair<CPos, SubCell>[] cells) public static bool AnyExplored(this Shroud shroud, (CPos Cell, SubCell SubCell)[] cells)
{ {
// PERF: Avoid LINQ. // PERF: Avoid LINQ.
foreach (var cell in cells) foreach (var cell in cells)
if (shroud.IsExplored(cell.First)) if (shroud.IsExplored(cell.Cell))
return true; return true;
return false; return false;
@@ -36,11 +35,11 @@ namespace OpenRA.Mods.Common
return false; return false;
} }
public static bool AnyVisible(this Shroud shroud, Pair<CPos, SubCell>[] cells) public static bool AnyVisible(this Shroud shroud, (CPos Cell, SubCell SubCell)[] cells)
{ {
// PERF: Avoid LINQ. // PERF: Avoid LINQ.
foreach (var cell in cells) foreach (var cell in cells)
if (shroud.IsVisible(cell.First)) if (shroud.IsVisible(cell.Cell))
return true; return true;
return false; return false;

View File

@@ -72,7 +72,7 @@ namespace OpenRA.Mods.Common.Traits
{ {
// PERF: Reuse collection to avoid allocations. // PERF: Reuse collection to avoid allocations.
footprint.UnionWith(self.OccupiesSpace.OccupiedCells() footprint.UnionWith(self.OccupiesSpace.OccupiedCells()
.SelectMany(kv => Shroud.ProjectedCellsInRange(map, map.CenterOfCell(kv.First), minRange, maxRange, Info.MaxHeightDelta))); .SelectMany(kv => Shroud.ProjectedCellsInRange(map, map.CenterOfCell(kv.Cell), minRange, maxRange, Info.MaxHeightDelta)));
var cells = footprint.ToArray(); var cells = footprint.ToArray();
footprint.Clear(); footprint.Clear();
return cells; return cells;

View File

@@ -211,7 +211,7 @@ namespace OpenRA.Mods.Common.Traits
INotifyAddedToWorld, INotifyRemovedFromWorld, INotifyActorDisposing, INotifyBecomingIdle, ICreationActivity, INotifyAddedToWorld, INotifyRemovedFromWorld, INotifyActorDisposing, INotifyBecomingIdle, ICreationActivity,
IActorPreviewInitModifier, IDeathActorInitModifier, IIssueDeployOrder, IIssueOrder, IResolveOrder, IOrderVoice IActorPreviewInitModifier, IDeathActorInitModifier, IIssueDeployOrder, IIssueOrder, IResolveOrder, IOrderVoice
{ {
static readonly Pair<CPos, SubCell>[] NoCells = { }; static readonly (CPos, SubCell)[] NoCells = { };
readonly Actor self; readonly Actor self;
@@ -597,12 +597,12 @@ namespace OpenRA.Mods.Common.Traits
get { return !IsTraitDisabled && !IsTraitPaused ? Util.ApplyPercentageModifiers(Info.Speed, speedModifiers) : 0; } get { return !IsTraitDisabled && !IsTraitPaused ? Util.ApplyPercentageModifiers(Info.Speed, speedModifiers) : 0; }
} }
public Pair<CPos, SubCell>[] OccupiedCells() public (CPos Cell, SubCell SubCell)[] OccupiedCells()
{ {
if (!self.IsAtGroundLevel()) if (!self.IsAtGroundLevel())
return landingCells.Select(c => Pair.New(c, SubCell.FullCell)).ToArray(); return landingCells.Select(c => (c, SubCell.FullCell)).ToArray();
return new[] { Pair.New(TopLeft, SubCell.FullCell) }; return new[] { (TopLeft, SubCell.FullCell) };
} }
public WVec FlyStep(WAngle facing) public WVec FlyStep(WAngle facing)

View File

@@ -26,7 +26,7 @@ namespace OpenRA.Mods.Common.Traits
"Overrides `Color` if both set.")] "Overrides `Color` if both set.")]
public readonly string Terrain = null; public readonly string Terrain = null;
void IMapPreviewSignatureInfo.PopulateMapPreviewSignatureCells(Map map, ActorInfo ai, ActorReference s, List<Pair<MPos, Color>> destinationBuffer) void IMapPreviewSignatureInfo.PopulateMapPreviewSignatureCells(Map map, ActorInfo ai, ActorReference s, List<(MPos, Color)> destinationBuffer)
{ {
var tileSet = map.Rules.TileSet; var tileSet = map.Rules.TileSet;
@@ -50,7 +50,7 @@ namespace OpenRA.Mods.Common.Traits
var ios = ai.TraitInfo<IOccupySpaceInfo>(); var ios = ai.TraitInfo<IOccupySpaceInfo>();
var cells = ios.OccupiedCells(ai, s.Get<LocationInit>().Value); var cells = ios.OccupiedCells(ai, s.Get<LocationInit>().Value);
foreach (var cell in cells) foreach (var cell in cells)
destinationBuffer.Add(new Pair<MPos, Color>(cell.Key.ToMPos(map), color)); destinationBuffer.Add((cell.Key.ToMPos(map), color));
} }
} }

View File

@@ -127,7 +127,7 @@ namespace OpenRA.Mods.Common.Traits
int currentBarrel; int currentBarrel;
int barrelCount; int barrelCount;
List<Pair<int, Action>> delayedActions = new List<Pair<int, Action>>(); List<(int Ticks, Action Func)> delayedActions = new List<(int, Action)>();
public WDist Recoil; public WDist Recoil;
public int FireDelay { get; protected set; } public int FireDelay { get; protected set; }
@@ -211,12 +211,12 @@ namespace OpenRA.Mods.Common.Traits
for (var i = 0; i < delayedActions.Count; i++) for (var i = 0; i < delayedActions.Count; i++)
{ {
var x = delayedActions[i]; var x = delayedActions[i];
if (--x.First <= 0) if (--x.Ticks <= 0)
x.Second(); x.Func();
delayedActions[i] = x; delayedActions[i] = x;
} }
delayedActions.RemoveAll(a => a.First <= 0); delayedActions.RemoveAll(a => a.Ticks <= 0);
} }
void ITick.Tick(Actor self) void ITick.Tick(Actor self)
@@ -228,7 +228,7 @@ namespace OpenRA.Mods.Common.Traits
protected void ScheduleDelayedAction(int t, Action a) protected void ScheduleDelayedAction(int t, Action a)
{ {
if (t > 0) if (t > 0)
delayedActions.Add(Pair.New(t, a)); delayedActions.Add((t, a));
else else
a(); a();
} }

View File

@@ -64,27 +64,27 @@ namespace OpenRA.Mods.Common.Traits
DemolishWeaponInfo = weapon; DemolishWeaponInfo = weapon;
} }
public IEnumerable<Pair<ushort, int>> Templates public IEnumerable<(ushort Template, int Health)> Templates
{ {
get get
{ {
if (Template != 0) if (Template != 0)
yield return Pair.New(Template, 100); yield return (Template, 100);
if (DamagedTemplate != 0) if (DamagedTemplate != 0)
yield return Pair.New(DamagedTemplate, 49); yield return (DamagedTemplate, 49);
if (DestroyedTemplate != 0) if (DestroyedTemplate != 0)
yield return Pair.New(DestroyedTemplate, 0); yield return (DestroyedTemplate, 0);
if (DestroyedPlusNorthTemplate != 0) if (DestroyedPlusNorthTemplate != 0)
yield return Pair.New(DestroyedPlusNorthTemplate, 0); yield return (DestroyedPlusNorthTemplate, 0);
if (DestroyedPlusSouthTemplate != 0) if (DestroyedPlusSouthTemplate != 0)
yield return Pair.New(DestroyedPlusSouthTemplate, 0); yield return (DestroyedPlusSouthTemplate, 0);
if (DestroyedPlusBothTemplate != 0) if (DestroyedPlusBothTemplate != 0)
yield return Pair.New(DestroyedPlusBothTemplate, 0); yield return (DestroyedPlusBothTemplate, 0);
} }
} }
} }
@@ -212,7 +212,7 @@ namespace OpenRA.Mods.Common.Traits
var palette = wr.Palette(TileSet.TerrainPaletteInternalName); var palette = wr.Palette(TileSet.TerrainPaletteInternalName);
renderables = new Dictionary<ushort, IRenderable[]>(); renderables = new Dictionary<ushort, IRenderable[]>();
foreach (var t in info.Templates) foreach (var t in info.Templates)
renderables.Add(t.First, TemplateRenderables(wr, palette, t.First)); renderables.Add(t.Template, TemplateRenderables(wr, palette, t.Template));
initialized = true; initialized = true;
} }

View File

@@ -13,7 +13,6 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using OpenRA.Graphics; using OpenRA.Graphics;
using OpenRA.Primitives;
using OpenRA.Traits; using OpenRA.Traits;
namespace OpenRA.Mods.Common.Traits namespace OpenRA.Mods.Common.Traits
@@ -268,8 +267,8 @@ namespace OpenRA.Mods.Common.Traits
readonly Actor self; readonly Actor self;
readonly BuildingInfluence influence; readonly BuildingInfluence influence;
Pair<CPos, SubCell>[] occupiedCells; (CPos, SubCell)[] occupiedCells;
Pair<CPos, SubCell>[] targetableCells; (CPos, SubCell)[] targetableCells;
CPos[] transitOnlyCells; CPos[] transitOnlyCells;
public CPos TopLeft { get { return topLeft; } } public CPos TopLeft { get { return topLeft; } }
@@ -283,21 +282,21 @@ namespace OpenRA.Mods.Common.Traits
influence = self.World.WorldActor.Trait<BuildingInfluence>(); influence = self.World.WorldActor.Trait<BuildingInfluence>();
occupiedCells = Info.OccupiedTiles(TopLeft) occupiedCells = Info.OccupiedTiles(TopLeft)
.Select(c => Pair.New(c, SubCell.FullCell)).ToArray(); .Select(c => (c, SubCell.FullCell)).ToArray();
targetableCells = Info.FootprintTiles(TopLeft, FootprintCellType.Occupied) targetableCells = Info.FootprintTiles(TopLeft, FootprintCellType.Occupied)
.Select(c => Pair.New(c, SubCell.FullCell)).ToArray(); .Select(c => (c, SubCell.FullCell)).ToArray();
transitOnlyCells = Info.TransitOnlyTiles(TopLeft).ToArray(); transitOnlyCells = Info.TransitOnlyTiles(TopLeft).ToArray();
CenterPosition = init.World.Map.CenterOfCell(topLeft) + Info.CenterOffset(init.World); CenterPosition = init.World.Map.CenterOfCell(topLeft) + Info.CenterOffset(init.World);
} }
public Pair<CPos, SubCell>[] OccupiedCells() { return occupiedCells; } public (CPos, SubCell)[] OccupiedCells() { return occupiedCells; }
public CPos[] TransitOnlyCells() { return transitOnlyCells; } public CPos[] TransitOnlyCells() { return transitOnlyCells; }
Pair<CPos, SubCell>[] ITargetableCells.TargetableCells() { return targetableCells; } (CPos, SubCell)[] ITargetableCells.TargetableCells() { return targetableCells; }
void INotifyAddedToWorld.AddedToWorld(Actor self) void INotifyAddedToWorld.AddedToWorld(Actor self)
{ {

View File

@@ -54,13 +54,13 @@ namespace OpenRA.Mods.Common.Traits
world.IsCellBuildable(t, ai, bi, toIgnore)); world.IsCellBuildable(t, ai, bi, toIgnore));
} }
public static IEnumerable<Pair<CPos, Actor>> GetLineBuildCells(World world, CPos cell, ActorInfo ai, BuildingInfo bi, Player owner) public static IEnumerable<(CPos Cell, Actor Actor)> GetLineBuildCells(World world, CPos cell, ActorInfo ai, BuildingInfo bi, Player owner)
{ {
var lbi = ai.TraitInfo<LineBuildInfo>(); var lbi = ai.TraitInfo<LineBuildInfo>();
var topLeft = cell; // 1x1 assumption! var topLeft = cell; // 1x1 assumption!
if (world.IsCellBuildable(topLeft, ai, bi)) if (world.IsCellBuildable(topLeft, ai, bi))
yield return Pair.New<CPos, Actor>(topLeft, null); yield return (topLeft, null);
// Start at place location, search outwards // Start at place location, search outwards
// TODO: First make it work, then make it nice // TODO: First make it work, then make it nice
@@ -91,7 +91,7 @@ namespace OpenRA.Mods.Common.Traits
// Place intermediate-line sections // Place intermediate-line sections
if (dirs[d] > 0) if (dirs[d] > 0)
for (var i = 1; i < dirs[d]; i++) for (var i = 1; i < dirs[d]; i++)
yield return Pair.New(topLeft + i * vecs[d], connectors[d]); yield return (topLeft + i * vecs[d], connectors[d]);
} }
} }
} }

View File

@@ -26,7 +26,7 @@ namespace OpenRA.Mods.Common.Traits
class CapturableProgressBar : ConditionalTrait<CapturableProgressBarInfo>, ISelectionBar, ICaptureProgressWatcher class CapturableProgressBar : ConditionalTrait<CapturableProgressBarInfo>, ISelectionBar, ICaptureProgressWatcher
{ {
Dictionary<Actor, Pair<int, int>> progress = new Dictionary<Actor, Pair<int, int>>(); Dictionary<Actor, (int Current, int Total)> progress = new Dictionary<Actor, (int, int)>();
public CapturableProgressBar(Actor self, CapturableProgressBarInfo info) public CapturableProgressBar(Actor self, CapturableProgressBarInfo info)
: base(info) { } : base(info) { }
@@ -39,7 +39,7 @@ namespace OpenRA.Mods.Common.Traits
if (total == 0) if (total == 0)
progress.Remove(captor); progress.Remove(captor);
else else
progress[captor] = Pair.New(current, total); progress[captor] = (current, total);
} }
float ISelectionBar.GetValue() float ISelectionBar.GetValue()
@@ -47,7 +47,7 @@ namespace OpenRA.Mods.Common.Traits
if (IsTraitDisabled || !progress.Any()) if (IsTraitDisabled || !progress.Any())
return 0f; return 0f;
return progress.Values.Max(p => (float)p.First / p.Second); return progress.Values.Max(p => (float)p.Current / p.Total);
} }
Color ISelectionBar.GetColor() { return Info.Color; } Color ISelectionBar.GetColor() { return Info.Color; }

View File

@@ -155,20 +155,20 @@ namespace OpenRA.Mods.Common.Traits
if (crateActions.Any()) if (crateActions.Any())
{ {
var shares = crateActions.Select(a => Pair.New(a, a.GetSelectionSharesOuter(crusher))); var shares = crateActions.Select(a => (Action: a, Shares: a.GetSelectionSharesOuter(crusher)));
var totalShares = shares.Sum(a => a.Second); var totalShares = shares.Sum(a => a.Shares);
var n = self.World.SharedRandom.Next(totalShares); var n = self.World.SharedRandom.Next(totalShares);
foreach (var s in shares) foreach (var s in shares)
{ {
if (n < s.Second) if (n < s.Shares)
{ {
s.First.Activate(crusher); s.Action.Activate(crusher);
return; return;
} }
n -= s.Second; n -= s.Shares;
} }
} }
} }
@@ -180,7 +180,7 @@ namespace OpenRA.Mods.Common.Traits
} }
public CPos TopLeft { get { return Location; } } public CPos TopLeft { get { return Location; } }
public Pair<CPos, SubCell>[] OccupiedCells() { return new[] { Pair.New(Location, SubCell.FullCell) }; } public (CPos, SubCell)[] OccupiedCells() { return new[] { (Location, SubCell.FullCell) }; }
public WPos CenterPosition { get; private set; } public WPos CenterPosition { get; private set; }

View File

@@ -67,7 +67,7 @@ namespace OpenRA.Mods.Common.Traits
foreach (var kv in self.OccupiesSpace.OccupiedCells()) foreach (var kv in self.OccupiesSpace.OccupiedCells())
{ {
totalTiles++; totalTiles++;
if (!Info.Terrain.Contains(self.World.Map.GetTerrainInfo(kv.First).Type)) if (!Info.Terrain.Contains(self.World.Map.GetTerrainInfo(kv.Cell).Type))
safeTiles++; safeTiles++;
} }

View File

@@ -70,7 +70,7 @@ namespace OpenRA.Mods.Common.Traits
if (info.DrawPerimiterCellVectors) if (info.DrawPerimiterCellVectors)
{ {
var occupiedCells = self.OccupiesSpace.OccupiedCells().Select(p => p.First).ToArray(); var occupiedCells = self.OccupiesSpace.OccupiedCells().Select(p => p.Cell).ToArray();
perimeterCells = Util.ExpandFootprint(occupiedCells, true).Except(occupiedCells).ToArray(); perimeterCells = Util.ExpandFootprint(occupiedCells, true).Except(occupiedCells).ToArray();
foreach (var perimCell in perimeterCells) foreach (var perimCell in perimeterCells)

View File

@@ -58,7 +58,7 @@ namespace OpenRA.Mods.Common.Traits
readonly GainsExperienceInfo info; readonly GainsExperienceInfo info;
readonly int initialExperience; readonly int initialExperience;
readonly List<Pair<int, string>> nextLevel = new List<Pair<int, string>>(); readonly List<(int RequiredExperience, string Condition)> nextLevel = new List<(int, string)>();
// Stored as a percentage of our value // Stored as a percentage of our value
[Sync] [Sync]
@@ -83,7 +83,7 @@ namespace OpenRA.Mods.Common.Traits
var valued = self.Info.TraitInfoOrDefault<ValuedInfo>(); var valued = self.Info.TraitInfoOrDefault<ValuedInfo>();
var requiredExperience = info.ExperienceModifier < 0 ? (valued != null ? valued.Cost : 1) : info.ExperienceModifier; var requiredExperience = info.ExperienceModifier < 0 ? (valued != null ? valued.Cost : 1) : info.ExperienceModifier;
foreach (var kv in info.Conditions) foreach (var kv in info.Conditions)
nextLevel.Add(Pair.New(kv.Key * requiredExperience, kv.Value)); nextLevel.Add((kv.Key * requiredExperience, kv.Value));
if (initialExperience > 0) if (initialExperience > 0)
GiveExperience(initialExperience, info.SuppressLevelupAnimation); GiveExperience(initialExperience, info.SuppressLevelupAnimation);
@@ -97,7 +97,7 @@ namespace OpenRA.Mods.Common.Traits
return; return;
var newLevel = Math.Min(Level + numLevels, MaxLevel); var newLevel = Math.Min(Level + numLevels, MaxLevel);
GiveExperience(nextLevel[newLevel - 1].First - Experience, silent); GiveExperience(nextLevel[newLevel - 1].RequiredExperience - Experience, silent);
} }
public void GiveExperience(int amount, bool silent = false) public void GiveExperience(int amount, bool silent = false)
@@ -108,11 +108,11 @@ namespace OpenRA.Mods.Common.Traits
if (MaxLevel == 0) if (MaxLevel == 0)
return; return;
Experience = (Experience + amount).Clamp(0, nextLevel[MaxLevel - 1].First); Experience = (Experience + amount).Clamp(0, nextLevel[MaxLevel - 1].RequiredExperience);
while (Level < MaxLevel && Experience >= nextLevel[Level].First) while (Level < MaxLevel && Experience >= nextLevel[Level].RequiredExperience)
{ {
self.GrantCondition(nextLevel[Level].Second); self.GrantCondition(nextLevel[Level].Condition);
Level++; Level++;

View File

@@ -94,7 +94,7 @@ namespace OpenRA.Mods.Common.Traits
if (Info.UseTargetableCellsOffsets && targetableCells != null) if (Info.UseTargetableCellsOffsets && targetableCells != null)
foreach (var c in targetableCells.TargetableCells()) foreach (var c in targetableCells.TargetableCells())
yield return self.World.Map.CenterOfCell(c.First); yield return self.World.Map.CenterOfCell(c.Cell);
foreach (var o in Info.TargetableOffsets) foreach (var o in Info.TargetableOffsets)
{ {

View File

@@ -116,7 +116,7 @@ namespace OpenRA.Mods.Common.Traits
return true; return true;
} }
public Pair<CPos, SubCell>[] OccupiedCells() { return new[] { Pair.New(TopLeft, SubCell.FullCell) }; } public (CPos, SubCell)[] OccupiedCells() { return new[] { (TopLeft, SubCell.FullCell) }; }
public bool IsLeavingCell(CPos location, SubCell subCell = SubCell.Any) { return false; } public bool IsLeavingCell(CPos location, SubCell subCell = SubCell.Any) { return false; }
public SubCell GetValidSubCell(SubCell preferred = SubCell.Any) { return SubCell.FullCell; } public SubCell GetValidSubCell(SubCell preferred = SubCell.Any) { return SubCell.FullCell; }
public SubCell GetAvailableSubCell(CPos cell, SubCell preferredSubCell = SubCell.Any, Actor ignoreActor = null, BlockedByActor check = BlockedByActor.All) public SubCell GetAvailableSubCell(CPos cell, SubCell preferredSubCell = SubCell.Any, Actor ignoreActor = null, BlockedByActor check = BlockedByActor.All)

View File

@@ -39,7 +39,7 @@ namespace OpenRA.Mods.Common.Traits
[Sync] [Sync]
readonly WPos position; readonly WPos position;
readonly Pair<CPos, SubCell>[] occupied; readonly (CPos, SubCell)[] occupied;
public Immobile(ActorInitializer init, ImmobileInfo info) public Immobile(ActorInitializer init, ImmobileInfo info)
{ {
@@ -47,14 +47,14 @@ namespace OpenRA.Mods.Common.Traits
position = init.World.Map.CenterOfCell(location); position = init.World.Map.CenterOfCell(location);
if (info.OccupiesSpace) if (info.OccupiesSpace)
occupied = new[] { Pair.New(TopLeft, SubCell.FullCell) }; occupied = new[] { (TopLeft, SubCell.FullCell) };
else else
occupied = new Pair<CPos, SubCell>[0]; occupied = new (CPos, SubCell)[0];
} }
public CPos TopLeft { get { return location; } } public CPos TopLeft { get { return location; } }
public WPos CenterPosition { get { return position; } } public WPos CenterPosition { get { return position; } }
public Pair<CPos, SubCell>[] OccupiedCells() { return occupied; } public (CPos, SubCell)[] OccupiedCells() { return occupied; }
void INotifyAddedToWorld.AddedToWorld(Actor self) void INotifyAddedToWorld.AddedToWorld(Actor self)
{ {

View File

@@ -229,16 +229,16 @@ namespace OpenRA.Mods.Common.Traits
public CPos TopLeft { get { return ToCell; } } public CPos TopLeft { get { return ToCell; } }
public Pair<CPos, SubCell>[] OccupiedCells() public (CPos, SubCell)[] OccupiedCells()
{ {
if (FromCell == ToCell) if (FromCell == ToCell)
return new[] { Pair.New(FromCell, FromSubCell) }; return new[] { (FromCell, FromSubCell) };
// HACK: Should be fixed properly, see https://github.com/OpenRA/OpenRA/pull/17292 for an explanation // HACK: Should be fixed properly, see https://github.com/OpenRA/OpenRA/pull/17292 for an explanation
if (Info.LocomotorInfo.SharesCell) if (Info.LocomotorInfo.SharesCell)
return new[] { Pair.New(ToCell, ToSubCell) }; return new[] { (ToCell, ToSubCell) };
return new[] { Pair.New(FromCell, FromSubCell), Pair.New(ToCell, ToSubCell) }; return new[] { (FromCell, FromSubCell), (ToCell, ToSubCell) };
} }
#endregion #endregion

View File

@@ -78,12 +78,12 @@ namespace OpenRA.Mods.Common.Traits
var myTeam = self.World.LobbyInfo.ClientWithIndex(self.Owner.ClientIndex).Team; var myTeam = self.World.LobbyInfo.ClientWithIndex(self.Owner.ClientIndex).Team;
var teams = self.World.Players.Where(p => !p.NonCombatant && p.Playable) var teams = self.World.Players.Where(p => !p.NonCombatant && p.Playable)
.Select(p => new Pair<Player, PlayerStatistics>(p, p.PlayerActor.TraitOrDefault<PlayerStatistics>())) .Select(p => (Player: p, PlayerStatistics: p.PlayerActor.TraitOrDefault<PlayerStatistics>()))
.OrderByDescending(p => p.Second != null ? p.Second.Experience : 0) .OrderByDescending(p => p.PlayerStatistics != null ? p.PlayerStatistics.Experience : 0)
.GroupBy(p => (self.World.LobbyInfo.ClientWithIndex(p.First.ClientIndex) ?? new Session.Client()).Team) .GroupBy(p => (self.World.LobbyInfo.ClientWithIndex(p.Player.ClientIndex) ?? new Session.Client()).Team)
.OrderByDescending(g => g.Sum(gg => gg.Second != null ? gg.Second.Experience : 0)); .OrderByDescending(g => g.Sum(gg => gg.PlayerStatistics != null ? gg.PlayerStatistics.Experience : 0));
if (teams.First().Key == myTeam && (myTeam != 0 || teams.First().First().First == self.Owner)) if (teams.First().Key == myTeam && (myTeam != 0 || teams.First().First().Player == self.Owner))
{ {
mo.MarkCompleted(self.Owner, objectiveID); mo.MarkCompleted(self.Owner, objectiveID);
return; return;

View File

@@ -25,7 +25,7 @@ namespace OpenRA.Mods.Common.Traits
public class GrantConditionOnPrerequisiteManager : ITechTreeElement public class GrantConditionOnPrerequisiteManager : ITechTreeElement
{ {
readonly Actor self; readonly Actor self;
readonly Dictionary<string, List<Pair<Actor, GrantConditionOnPrerequisite>>> upgradables = new Dictionary<string, List<Pair<Actor, GrantConditionOnPrerequisite>>>(); readonly Dictionary<string, List<(Actor Actor, GrantConditionOnPrerequisite GrantConditionOnPrerequisite)>> upgradables = new Dictionary<string, List<(Actor, GrantConditionOnPrerequisite)>>();
readonly TechTree techTree; readonly TechTree techTree;
public GrantConditionOnPrerequisiteManager(ActorInitializer init) public GrantConditionOnPrerequisiteManager(ActorInitializer init)
@@ -44,11 +44,11 @@ namespace OpenRA.Mods.Common.Traits
var key = MakeKey(prerequisites); var key = MakeKey(prerequisites);
if (!upgradables.ContainsKey(key)) if (!upgradables.ContainsKey(key))
{ {
upgradables.Add(key, new List<Pair<Actor, GrantConditionOnPrerequisite>>()); upgradables.Add(key, new List<(Actor, GrantConditionOnPrerequisite)>());
techTree.Add(key, prerequisites, 0, this); techTree.Add(key, prerequisites, 0, this);
} }
upgradables[key].Add(Pair.New(actor, u)); upgradables[key].Add((actor, u));
// Notify the current state // Notify the current state
u.PrerequisitesUpdated(actor, techTree.HasPrerequisites(prerequisites)); u.PrerequisitesUpdated(actor, techTree.HasPrerequisites(prerequisites));
@@ -59,7 +59,7 @@ namespace OpenRA.Mods.Common.Traits
var key = MakeKey(prerequisites); var key = MakeKey(prerequisites);
var list = upgradables[key]; var list = upgradables[key];
list.RemoveAll(x => x.First == actor && x.Second == u); list.RemoveAll(x => x.Actor == actor && x.GrantConditionOnPrerequisite == u);
if (!list.Any()) if (!list.Any())
{ {
upgradables.Remove(key); upgradables.Remove(key);
@@ -69,22 +69,22 @@ namespace OpenRA.Mods.Common.Traits
public void PrerequisitesAvailable(string key) public void PrerequisitesAvailable(string key)
{ {
List<Pair<Actor, GrantConditionOnPrerequisite>> list; List<(Actor Actor, GrantConditionOnPrerequisite GrantConditionOnPrerequisite)> list;
if (!upgradables.TryGetValue(key, out list)) if (!upgradables.TryGetValue(key, out list))
return; return;
foreach (var u in list) foreach (var u in list)
u.Second.PrerequisitesUpdated(u.First, true); u.GrantConditionOnPrerequisite.PrerequisitesUpdated(u.Actor, true);
} }
public void PrerequisitesUnavailable(string key) public void PrerequisitesUnavailable(string key)
{ {
List<Pair<Actor, GrantConditionOnPrerequisite>> list; List<(Actor Actor, GrantConditionOnPrerequisite GrantConditionOnPrerequisite)> list;
if (!upgradables.TryGetValue(key, out list)) if (!upgradables.TryGetValue(key, out list))
return; return;
foreach (var u in list) foreach (var u in list)
u.Second.PrerequisitesUpdated(u.First, false); u.GrantConditionOnPrerequisite.PrerequisitesUpdated(u.Actor, false);
} }
public void PrerequisitesItemHidden(string key) { } public void PrerequisitesItemHidden(string key) { }

View File

@@ -119,16 +119,16 @@ namespace OpenRA.Mods.Common.Traits
foreach (var t in BuildingUtils.GetLineBuildCells(w, targetLocation, actorInfo, buildingInfo, order.Player)) foreach (var t in BuildingUtils.GetLineBuildCells(w, targetLocation, actorInfo, buildingInfo, order.Player))
{ {
if (t.First == targetLocation) if (t.Cell == targetLocation)
continue; continue;
w.CreateActor(t.First == targetLocation ? actorInfo.Name : segmentType, new TypeDictionary w.CreateActor(t.Cell == targetLocation ? actorInfo.Name : segmentType, new TypeDictionary
{ {
new LocationInit(t.First), new LocationInit(t.Cell),
new OwnerInit(order.Player), new OwnerInit(order.Player),
new FactionInit(faction), new FactionInit(faction),
new LineBuildDirectionInit(t.First.X == targetLocation.X ? LineBuildDirection.Y : LineBuildDirection.X), new LineBuildDirectionInit(t.Cell.X == targetLocation.X ? LineBuildDirection.Y : LineBuildDirection.X),
new LineBuildParentInit(new[] { t.Second, placed }), new LineBuildParentInit(new[] { t.Actor, placed }),
new PlaceBuildingInit() new PlaceBuildingInit()
}); });
} }

View File

@@ -29,7 +29,7 @@ namespace OpenRA.Mods.Common.Traits
public bool IsInitialized { get; private set; } public bool IsInitialized { get; private set; }
readonly World world; readonly World world;
CellLayer<Pair<int, int>> terrainColor; CellLayer<(int, int)> terrainColor;
readonly Shroud shroud; readonly Shroud shroud;
public event Action<MPos> CellTerrainColorChanged = null; public event Action<MPos> CellTerrainColorChanged = null;
@@ -67,7 +67,7 @@ namespace OpenRA.Mods.Common.Traits
public void WorldLoaded(World w, WorldRenderer wr) public void WorldLoaded(World w, WorldRenderer wr)
{ {
terrainColor = new CellLayer<Pair<int, int>>(w.Map); terrainColor = new CellLayer<(int, int)>(w.Map);
w.AddFrameEndTask(_ => w.AddFrameEndTask(_ =>
{ {
@@ -82,22 +82,22 @@ namespace OpenRA.Mods.Common.Traits
}); });
} }
public Pair<int, int> this[MPos uv] public (int Left, int Right) this[MPos uv]
{ {
get { return terrainColor[uv]; } get { return terrainColor[uv]; }
} }
public static Pair<int, int> GetColor(Map map, MPos uv) public static (int Left, int Right) GetColor(Map map, MPos uv)
{ {
var custom = map.CustomTerrain[uv]; var custom = map.CustomTerrain[uv];
if (custom != byte.MaxValue) if (custom != byte.MaxValue)
{ {
var c = map.Rules.TileSet[custom].Color.ToArgb(); var c = map.Rules.TileSet[custom].Color.ToArgb();
return Pair.New(c, c); return (c, c);
} }
var tc = map.GetTerrainColorPair(uv); var tc = map.GetTerrainColorPair(uv);
return Pair.New(tc.First.ToArgb(), tc.Second.ToArgb()); return (tc.Left.ToArgb(), tc.Right.ToArgb());
} }
} }
} }

View File

@@ -119,12 +119,12 @@ namespace OpenRA.Mods.Common.Traits
var myTeam = self.World.LobbyInfo.ClientWithIndex(self.Owner.ClientIndex).Team; var myTeam = self.World.LobbyInfo.ClientWithIndex(self.Owner.ClientIndex).Team;
var teams = self.World.Players.Where(p => !p.NonCombatant && p.Playable) var teams = self.World.Players.Where(p => !p.NonCombatant && p.Playable)
.Select(p => new Pair<Player, PlayerStatistics>(p, p.PlayerActor.TraitOrDefault<PlayerStatistics>())) .Select(p => (Player: p, PlayerStatistics: p.PlayerActor.TraitOrDefault<PlayerStatistics>()))
.OrderByDescending(p => p.Second != null ? p.Second.Experience : 0) .OrderByDescending(p => p.PlayerStatistics != null ? p.PlayerStatistics.Experience : 0)
.GroupBy(p => (self.World.LobbyInfo.ClientWithIndex(p.First.ClientIndex) ?? new Session.Client()).Team) .GroupBy(p => (self.World.LobbyInfo.ClientWithIndex(p.Player.ClientIndex) ?? new Session.Client()).Team)
.OrderByDescending(g => g.Sum(gg => gg.Second != null ? gg.Second.Experience : 0)); .OrderByDescending(g => g.Sum(gg => gg.PlayerStatistics != null ? gg.PlayerStatistics.Experience : 0));
if (teams.First().Key == myTeam && (myTeam != 0 || teams.First().First().First == self.Owner)) if (teams.First().Key == myTeam && (myTeam != 0 || teams.First().First().Player == self.Owner))
{ {
mo.MarkCompleted(self.Owner, objectiveID); mo.MarkCompleted(self.Owner, objectiveID);
return; return;

View File

@@ -39,7 +39,7 @@ namespace OpenRA.Mods.Common.Traits.Radar
modifier = self.TraitsImplementing<IRadarColorModifier>().FirstOrDefault(); modifier = self.TraitsImplementing<IRadarColorModifier>().FirstOrDefault();
} }
public void PopulateRadarSignatureCells(Actor self, List<Pair<CPos, Color>> destinationBuffer) public void PopulateRadarSignatureCells(Actor self, List<(CPos Cell, Color Color)> destinationBuffer)
{ {
var viewer = self.World.RenderPlayer ?? self.World.LocalPlayer; var viewer = self.World.RenderPlayer ?? self.World.LocalPlayer;
if (IsTraitDisabled || (viewer != null && !Info.ValidStances.HasStance(self.Owner.Stances[viewer]))) if (IsTraitDisabled || (viewer != null && !Info.ValidStances.HasStance(self.Owner.Stances[viewer])))
@@ -51,12 +51,12 @@ namespace OpenRA.Mods.Common.Traits.Radar
if (Info.UseLocation) if (Info.UseLocation)
{ {
destinationBuffer.Add(Pair.New(self.Location, color)); destinationBuffer.Add((self.Location, color));
return; return;
} }
foreach (var cell in self.OccupiesSpace.OccupiedCells()) foreach (var cell in self.OccupiesSpace.OccupiedCells())
destinationBuffer.Add(Pair.New(cell.First, color)); destinationBuffer.Add((cell.Cell, color));
} }
} }
} }

View File

@@ -87,12 +87,12 @@ namespace OpenRA.Mods.Common.Traits.Render
public class RenderSprites : IRender, ITick, INotifyOwnerChanged, INotifyEffectiveOwnerChanged, IActorPreviewInitModifier public class RenderSprites : IRender, ITick, INotifyOwnerChanged, INotifyEffectiveOwnerChanged, IActorPreviewInitModifier
{ {
static readonly Pair<DamageState, string>[] DamagePrefixes = static readonly (DamageState DamageState, string Prefix)[] DamagePrefixes =
{ {
Pair.New(DamageState.Critical, "critical-"), (DamageState.Critical, "critical-"),
Pair.New(DamageState.Heavy, "damaged-"), (DamageState.Heavy, "damaged-"),
Pair.New(DamageState.Medium, "scratched-"), (DamageState.Medium, "scratched-"),
Pair.New(DamageState.Light, "scuffed-") (DamageState.Light, "scuffed-")
}; };
class AnimationWrapper class AnimationWrapper
@@ -251,9 +251,9 @@ namespace OpenRA.Mods.Common.Traits.Render
// Remove existing damage prefix // Remove existing damage prefix
foreach (var s in DamagePrefixes) foreach (var s in DamagePrefixes)
{ {
if (sequence.StartsWith(s.Second, StringComparison.Ordinal)) if (sequence.StartsWith(s.Prefix, StringComparison.Ordinal))
{ {
sequence = sequence.Substring(s.Second.Length); sequence = sequence.Substring(s.Prefix.Length);
break; break;
} }
} }
@@ -267,8 +267,8 @@ namespace OpenRA.Mods.Common.Traits.Render
sequence = UnnormalizeSequence(sequence); sequence = UnnormalizeSequence(sequence);
foreach (var s in DamagePrefixes) foreach (var s in DamagePrefixes)
if (state >= s.First && anim.HasSequence(s.Second + sequence)) if (state >= s.DamageState && anim.HasSequence(s.Prefix + sequence))
return s.Second + sequence; return s.Prefix + sequence;
return sequence; return sequence;
} }

View File

@@ -97,7 +97,7 @@ namespace OpenRA.Mods.Common.Traits
SendParatroopers(self, order.Target.CenterPosition, facing); SendParatroopers(self, order.Target.CenterPosition, facing);
} }
public Pair<Actor[], Actor[]> SendParatroopers(Actor self, WPos target, WAngle? facing = null) public (Actor[] Aircraft, Actor[] Units) SendParatroopers(Actor self, WPos target, WAngle? facing = null)
{ {
var aircraft = new List<Actor>(); var aircraft = new List<Actor>();
var units = new List<Actor>(); var units = new List<Actor>();
@@ -266,7 +266,7 @@ namespace OpenRA.Mods.Common.Traits
} }
}); });
return Pair.New(aircraft.ToArray(), units.ToArray()); return (aircraft.ToArray(), units.ToArray());
} }
void RemoveCamera(Actor camera) void RemoveCamera(Actor camera)

View File

@@ -359,20 +359,20 @@ namespace OpenRA.Mods.Common.Traits
{ {
foreach (var c in ios.OccupiedCells()) foreach (var c in ios.OccupiedCells())
{ {
var uv = c.First.ToMPos(map); var uv = c.Cell.ToMPos(map);
if (!influence.Contains(uv)) if (!influence.Contains(uv))
continue; continue;
var layer = c.First.Layer == 0 ? influence : customInfluence[c.First.Layer]; var layer = c.Cell.Layer == 0 ? influence : customInfluence[c.Cell.Layer];
layer[uv] = new InfluenceNode { Next = layer[uv], SubCell = c.Second, Actor = self }; layer[uv] = new InfluenceNode { Next = layer[uv], SubCell = c.SubCell, Actor = self };
List<CellTrigger> triggers; List<CellTrigger> triggers;
if (cellTriggerInfluence.TryGetValue(c.First, out triggers)) if (cellTriggerInfluence.TryGetValue(c.Cell, out triggers))
foreach (var t in triggers) foreach (var t in triggers)
t.Dirty = true; t.Dirty = true;
if (CellUpdated != null) if (CellUpdated != null)
CellUpdated(c.First); CellUpdated(c.Cell);
} }
} }
@@ -380,22 +380,22 @@ namespace OpenRA.Mods.Common.Traits
{ {
foreach (var c in ios.OccupiedCells()) foreach (var c in ios.OccupiedCells())
{ {
var uv = c.First.ToMPos(map); var uv = c.Cell.ToMPos(map);
if (!influence.Contains(uv)) if (!influence.Contains(uv))
continue; continue;
var layer = c.First.Layer == 0 ? influence : customInfluence[c.First.Layer]; var layer = c.Cell.Layer == 0 ? influence : customInfluence[c.Cell.Layer];
var temp = layer[uv]; var temp = layer[uv];
RemoveInfluenceInner(ref temp, self); RemoveInfluenceInner(ref temp, self);
layer[uv] = temp; layer[uv] = temp;
List<CellTrigger> triggers; List<CellTrigger> triggers;
if (cellTriggerInfluence.TryGetValue(c.First, out triggers)) if (cellTriggerInfluence.TryGetValue(c.Cell, out triggers))
foreach (var t in triggers) foreach (var t in triggers)
t.Dirty = true; t.Dirty = true;
if (CellUpdated != null) if (CellUpdated != null)
CellUpdated(c.First); CellUpdated(c.Cell);
} }
} }
@@ -416,7 +416,7 @@ namespace OpenRA.Mods.Common.Traits
return; return;
foreach (var c in ios.OccupiedCells()) foreach (var c in ios.OccupiedCells())
CellUpdated(c.First); CellUpdated(c.Cell);
} }
void ITick.Tick(Actor self) void ITick.Tick(Actor self)

View File

@@ -315,11 +315,11 @@ namespace OpenRA.Mods.Common.Traits
return nodes; return nodes;
} }
public void PopulateRadarSignatureCells(Actor self, List<Pair<CPos, Color>> destinationBuffer) public void PopulateRadarSignatureCells(Actor self, List<(CPos Cell, Color Color)> destinationBuffer)
{ {
foreach (var previewsForCell in cellMap) foreach (var previewsForCell in cellMap)
foreach (var preview in previewsForCell.Value) foreach (var preview in previewsForCell.Value)
destinationBuffer.Add(Pair.New(previewsForCell.Key, preview.RadarColor)); destinationBuffer.Add((previewsForCell.Key, preview.RadarColor));
} }
public EditorActorPreview this[string id] public EditorActorPreview this[string id]

View File

@@ -28,7 +28,7 @@ namespace OpenRA.Mods.Common.Traits
class LegacyBridgeLayer : IWorldLoaded class LegacyBridgeLayer : IWorldLoaded
{ {
readonly LegacyBridgeLayerInfo info; readonly LegacyBridgeLayerInfo info;
readonly Dictionary<ushort, Pair<string, int>> bridgeTypes = new Dictionary<ushort, Pair<string, int>>(); readonly Dictionary<ushort, (string Template, int Health)> bridgeTypes = new Dictionary<ushort, (string, int)>();
CellLayer<Bridge> bridges; CellLayer<Bridge> bridges;
@@ -46,7 +46,7 @@ namespace OpenRA.Mods.Common.Traits
{ {
var bi = w.Map.Rules.Actors[bridge].TraitInfo<BridgeInfo>(); var bi = w.Map.Rules.Actors[bridge].TraitInfo<BridgeInfo>();
foreach (var template in bi.Templates) foreach (var template in bi.Templates)
bridgeTypes.Add(template.First, Pair.New(bridge, template.Second)); bridgeTypes.Add(template.Template, (bridge, template.Health));
} }
// Take all templates to overlay from the map // Take all templates to overlay from the map
@@ -73,11 +73,11 @@ namespace OpenRA.Mods.Common.Traits
var nj = cell.Y - index / template.Size.X; var nj = cell.Y - index / template.Size.X;
// Create a new actor for this bridge and keep track of which subtiles this bridge includes // Create a new actor for this bridge and keep track of which subtiles this bridge includes
var bridge = w.CreateActor(bridgeTypes[tile].First, new TypeDictionary var bridge = w.CreateActor(bridgeTypes[tile].Template, new TypeDictionary
{ {
new LocationInit(new CPos(ni, nj)), new LocationInit(new CPos(ni, nj)),
new OwnerInit(w.WorldActor.Owner), new OwnerInit(w.WorldActor.Owner),
new HealthInit(bridgeTypes[tile].Second, true), new HealthInit(bridgeTypes[tile].Health, true),
}).Trait<Bridge>(); }).Trait<Bridge>();
var subTiles = new Dictionary<CPos, byte>(); var subTiles = new Dictionary<CPos, byte>();

View File

@@ -133,8 +133,8 @@ namespace OpenRA.Mods.Common.Traits
var n = taken.Count == 0 || !separateTeamSpawns var n = taken.Count == 0 || !separateTeamSpawns
? world.SharedRandom.Next(available.Count) ? world.SharedRandom.Next(available.Count)
: available // pick the most distant spawnpoint from everyone else : available // pick the most distant spawnpoint from everyone else
.Select((k, i) => Pair.New(k, i)) .Select((k, i) => (Cell: k, Index: i))
.MaxBy(a => taken.Sum(t => (t - a.First).LengthSquared)).Second; .MaxBy(a => taken.Sum(t => (t - a.Cell).LengthSquared)).Index;
var sp = available[n]; var sp = available[n];
available.RemoveAt(n); available.RemoveAt(n);

View File

@@ -63,7 +63,7 @@ namespace OpenRA.Mods.Common.Traits
[Desc("Allow resource to spawn on ramp tiles.")] [Desc("Allow resource to spawn on ramp tiles.")]
public readonly bool AllowOnRamps = false; public readonly bool AllowOnRamps = false;
void IMapPreviewSignatureInfo.PopulateMapPreviewSignatureCells(Map map, ActorInfo ai, ActorReference s, List<Pair<MPos, Color>> destinationBuffer) void IMapPreviewSignatureInfo.PopulateMapPreviewSignatureCells(Map map, ActorInfo ai, ActorReference s, List<(MPos, Color)> destinationBuffer)
{ {
var tileSet = map.Rules.TileSet; var tileSet = map.Rules.TileSet;
var color = tileSet[tileSet.GetTerrainIndex(TerrainType)].Color; var color = tileSet[tileSet.GetTerrainIndex(TerrainType)].Color;
@@ -74,7 +74,7 @@ namespace OpenRA.Mods.Common.Traits
{ {
var cell = new MPos(i, j); var cell = new MPos(i, j);
if (map.Resources[cell].Type == ResourceType) if (map.Resources[cell].Type == ResourceType)
destinationBuffer.Add(new Pair<MPos, Color>(cell, color)); destinationBuffer.Add((cell, color));
} }
} }
} }

View File

@@ -441,7 +441,7 @@ namespace OpenRA.Mods.Common.Traits
public interface IRadarSignature public interface IRadarSignature
{ {
void PopulateRadarSignatureCells(Actor self, List<Pair<CPos, Color>> destinationBuffer); void PopulateRadarSignatureCells(Actor self, List<(CPos Cell, Color Color)> destinationBuffer);
} }
public interface IRadarColorModifier { Color RadarColorOverride(Actor self, Color color); } public interface IRadarColorModifier { Color RadarColorOverride(Actor self, Color color); }
@@ -476,7 +476,7 @@ namespace OpenRA.Mods.Common.Traits
[RequireExplicitImplementation] [RequireExplicitImplementation]
public interface ITargetableCells public interface ITargetableCells
{ {
Pair<CPos, SubCell>[] TargetableCells(); (CPos Cell, SubCell SubCell)[] TargetableCells();
} }
[RequireExplicitImplementation] [RequireExplicitImplementation]

View File

@@ -17,7 +17,7 @@ using OpenRA.FileSystem;
namespace OpenRA.Mods.Common.UpdateRules namespace OpenRA.Mods.Common.UpdateRules
{ {
using YamlFileSet = List<Tuple<IReadWritePackage, string, List<MiniYamlNode>>>; using YamlFileSet = List<(IReadWritePackage, string, List<MiniYamlNode>)>;
public static class UpdateUtils public static class UpdateUtils
{ {
@@ -37,7 +37,7 @@ namespace OpenRA.Mods.Common.UpdateRules
continue; continue;
} }
yaml.Add(Tuple.Create((IReadWritePackage)package, name, MiniYaml.FromStream(package.GetStream(name), name, false))); yaml.Add(((IReadWritePackage)package, name, MiniYaml.FromStream(package.GetStream(name), name, false)));
} }
return yaml; return yaml;
@@ -62,7 +62,7 @@ namespace OpenRA.Mods.Common.UpdateRules
{ {
var fileSet = new YamlFileSet() var fileSet = new YamlFileSet()
{ {
Tuple.Create<IReadWritePackage, string, List<MiniYamlNode>>(null, "map.yaml", yaml.Nodes) (null, "map.yaml", yaml.Nodes)
}; };
var files = FieldLoader.GetValue<string[]>("value", yaml.Value); var files = FieldLoader.GetValue<string[]>("value", yaml.Value);
@@ -70,7 +70,7 @@ namespace OpenRA.Mods.Common.UpdateRules
{ {
// Ignore any files that aren't in the map bundle // Ignore any files that aren't in the map bundle
if (!filename.Contains("|") && mapPackage.Contains(filename)) if (!filename.Contains("|") && mapPackage.Contains(filename))
fileSet.Add(Tuple.Create(mapPackage, filename, MiniYaml.FromStream(mapPackage.GetStream(filename), filename, false))); fileSet.Add((mapPackage, filename, MiniYaml.FromStream(mapPackage.GetStream(filename), filename, false)));
else if (modData.ModFiles.Exists(filename)) else if (modData.ModFiles.Exists(filename))
externalFilenames.Add(filename); externalFilenames.Add(filename);
} }
@@ -97,7 +97,7 @@ namespace OpenRA.Mods.Common.UpdateRules
} }
var yaml = new MiniYaml(null, MiniYaml.FromStream(mapStream, mapPackage.Name, false)); var yaml = new MiniYaml(null, MiniYaml.FromStream(mapStream, mapPackage.Name, false));
files = new YamlFileSet() { Tuple.Create(mapPackage, "map.yaml", yaml.Nodes) }; files = new YamlFileSet() { (mapPackage, "map.yaml", yaml.Nodes) };
manualSteps.AddRange(rule.BeforeUpdate(modData)); manualSteps.AddRange(rule.BeforeUpdate(modData));
@@ -106,7 +106,7 @@ namespace OpenRA.Mods.Common.UpdateRules
{ {
var mapActors = new YamlFileSet() var mapActors = new YamlFileSet()
{ {
Tuple.Create<IReadWritePackage, string, List<MiniYamlNode>>(null, "map.yaml", mapActorsNode.Value.Nodes) (null, "map.yaml", mapActorsNode.Value.Nodes)
}; };
manualSteps.AddRange(ApplyTopLevelTransform(modData, mapActors, rule.UpdateMapActorNode)); manualSteps.AddRange(ApplyTopLevelTransform(modData, mapActors, rule.UpdateMapActorNode));

View File

@@ -46,24 +46,24 @@ namespace OpenRA.Mods.Common.UtilityCommands
var pr = c.Value.PanelRegion; var pr = c.Value.PanelRegion;
if (pr != null && pr.Length == 8) if (pr != null && pr.Length == 8)
{ {
var sides = new[] var sides = new (PanelSides PanelSides, Rectangle Bounds)[]
{ {
Pair.New(PanelSides.Top | PanelSides.Left, new Rectangle(pr[0], pr[1], pr[2], pr[3])), (PanelSides.Top | PanelSides.Left, new Rectangle(pr[0], pr[1], pr[2], pr[3])),
Pair.New(PanelSides.Top, new Rectangle(pr[0] + pr[2], pr[1], pr[4], pr[3])), (PanelSides.Top, new Rectangle(pr[0] + pr[2], pr[1], pr[4], pr[3])),
Pair.New(PanelSides.Top | PanelSides.Right, new Rectangle(pr[0] + pr[2] + pr[4], pr[1], pr[6], pr[3])), (PanelSides.Top | PanelSides.Right, new Rectangle(pr[0] + pr[2] + pr[4], pr[1], pr[6], pr[3])),
Pair.New(PanelSides.Left, new Rectangle(pr[0], pr[1] + pr[3], pr[2], pr[5])), (PanelSides.Left, new Rectangle(pr[0], pr[1] + pr[3], pr[2], pr[5])),
Pair.New(PanelSides.Center, new Rectangle(pr[0] + pr[2], pr[1] + pr[3], pr[4], pr[5])), (PanelSides.Center, new Rectangle(pr[0] + pr[2], pr[1] + pr[3], pr[4], pr[5])),
Pair.New(PanelSides.Right, new Rectangle(pr[0] + pr[2] + pr[4], pr[1] + pr[3], pr[6], pr[5])), (PanelSides.Right, new Rectangle(pr[0] + pr[2] + pr[4], pr[1] + pr[3], pr[6], pr[5])),
Pair.New(PanelSides.Bottom | PanelSides.Left, new Rectangle(pr[0], pr[1] + pr[3] + pr[5], pr[2], pr[7])), (PanelSides.Bottom | PanelSides.Left, new Rectangle(pr[0], pr[1] + pr[3] + pr[5], pr[2], pr[7])),
Pair.New(PanelSides.Bottom, new Rectangle(pr[0] + pr[2], pr[1] + pr[3] + pr[5], pr[4], pr[7])), (PanelSides.Bottom, new Rectangle(pr[0] + pr[2], pr[1] + pr[3] + pr[5], pr[4], pr[7])),
Pair.New(PanelSides.Bottom | PanelSides.Right, new Rectangle(pr[0] + pr[2] + pr[4], pr[1] + pr[3] + pr[5], pr[6], pr[7])) (PanelSides.Bottom | PanelSides.Right, new Rectangle(pr[0] + pr[2] + pr[4], pr[1] + pr[3] + pr[5], pr[6], pr[7]))
}; };
foreach (var s in sides) foreach (var s in sides)
{ {
var r = s.Second; var r = s.Bounds;
if (c.Value.PanelSides.HasSide(s.First)) if (c.Value.PanelSides.HasSide(s.PanelSides))
regions.Add("[\"{0}.<{1}>\",{2},{3},{4},{5}]".F(c.Key, s.First, r.X, r.Y, r.Width, r.Height)); regions.Add("[\"{0}.<{1}>\",{2},{3},{4},{5}]".F(c.Key, s.PanelSides, r.X, r.Y, r.Width, r.Height));
} }
} }

View File

@@ -87,7 +87,7 @@ namespace OpenRA.Mods.Common.UtilityCommands
var category = catAttr != null ? catAttr.Category : "Unsorted"; var category = catAttr != null ? catAttr.Category : "Unsorted";
var required = RequiredTraitNames(cg); var required = RequiredTraitNames(cg);
return ScriptMemberWrapper.WrappableMembers(cg).Select(mi => Tuple.Create(category, mi, required)); return ScriptMemberWrapper.WrappableMembers(cg).Select(mi => (category, mi, required));
}).GroupBy(g => g.Item1).OrderBy(g => g.Key); }).GroupBy(g => g.Item1).OrderBy(g => g.Key);
foreach (var kv in actorCategories) foreach (var kv in actorCategories)
@@ -132,7 +132,7 @@ namespace OpenRA.Mods.Common.UtilityCommands
var category = catAttr != null ? catAttr.Category : "Unsorted"; var category = catAttr != null ? catAttr.Category : "Unsorted";
var required = RequiredTraitNames(cg); var required = RequiredTraitNames(cg);
return ScriptMemberWrapper.WrappableMembers(cg).Select(mi => Tuple.Create(category, mi, required)); return ScriptMemberWrapper.WrappableMembers(cg).Select(mi => (category, mi, required));
}).GroupBy(g => g.Item1).OrderBy(g => g.Key); }).GroupBy(g => g.Item1).OrderBy(g => g.Key);
foreach (var kv in playerCategories) foreach (var kv in playerCategories)

View File

@@ -251,17 +251,17 @@ namespace OpenRA.Mods.Common.UtilityCommands
var actorCount = Map.ActorDefinitions.Count; var actorCount = Map.ActorDefinitions.Count;
var wps = waypointSection var wps = waypointSection
.Where(kv => Exts.ParseIntegerInvariant(kv.Value) > 0) .Where(kv => Exts.ParseIntegerInvariant(kv.Value) > 0)
.Select(kv => Pair.New(Exts.ParseIntegerInvariant(kv.Key), .Select(kv => (WaypointNumber: Exts.ParseIntegerInvariant(kv.Key),
LocationFromMapOffset(Exts.ParseIntegerInvariant(kv.Value), MapSize))); Location: LocationFromMapOffset(Exts.ParseIntegerInvariant(kv.Value), MapSize)));
// Add waypoint actors skipping duplicate entries // Add waypoint actors skipping duplicate entries
foreach (var kv in wps.DistinctBy(location => location.Second)) foreach (var kv in wps.DistinctBy(location => location.Location))
{ {
if (!singlePlayer && kv.First <= 7) if (!singlePlayer && kv.WaypointNumber <= 7)
{ {
var ar = new ActorReference("mpspawn") var ar = new ActorReference("mpspawn")
{ {
new LocationInit((CPos)kv.Second), new LocationInit((CPos)kv.Location),
new OwnerInit("Neutral") new OwnerInit("Neutral")
}; };
@@ -272,11 +272,11 @@ namespace OpenRA.Mods.Common.UtilityCommands
{ {
var ar = new ActorReference("waypoint") var ar = new ActorReference("waypoint")
{ {
new LocationInit((CPos)kv.Second), new LocationInit((CPos)kv.Location),
new OwnerInit("Neutral") new OwnerInit("Neutral")
}; };
SaveWaypoint(kv.First, ar); SaveWaypoint(kv.WaypointNumber, ar);
} }
} }
} }

View File

@@ -18,7 +18,7 @@ using OpenRA.Mods.Common.UpdateRules;
namespace OpenRA.Mods.Common.UtilityCommands namespace OpenRA.Mods.Common.UtilityCommands
{ {
using YamlFileSet = List<Tuple<IReadWritePackage, string, List<MiniYamlNode>>>; using YamlFileSet = List<(IReadWritePackage, string, List<MiniYamlNode>)>;
class UpdateMapCommand : IUtilityCommand class UpdateMapCommand : IUtilityCommand
{ {

View File

@@ -18,7 +18,7 @@ using OpenRA.Mods.Common.UpdateRules;
namespace OpenRA.Mods.Common.UtilityCommands namespace OpenRA.Mods.Common.UtilityCommands
{ {
using YamlFileSet = List<Tuple<IReadWritePackage, string, List<MiniYamlNode>>>; using YamlFileSet = List<(IReadWritePackage, string, List<MiniYamlNode>)>;
class UpdateModCommand : IUtilityCommand class UpdateModCommand : IUtilityCommand
{ {

View File

@@ -61,18 +61,18 @@ namespace OpenRA.Mods.Common.Warheads
var closestActiveShape = victim.TraitsImplementing<HitShape>() var closestActiveShape = victim.TraitsImplementing<HitShape>()
.Where(Exts.IsTraitEnabled) .Where(Exts.IsTraitEnabled)
.Select(s => Pair.New(s, s.DistanceFromEdge(victim, pos))) .Select(s => (HitShape: s, Distance: s.DistanceFromEdge(victim, pos)))
.MinByOrDefault(s => s.Second); .MinByOrDefault(s => s.Distance);
// Cannot be damaged without an active HitShape. // Cannot be damaged without an active HitShape.
if (closestActiveShape.First == null) if (closestActiveShape.HitShape == null)
continue; continue;
var falloffDistance = 0; var falloffDistance = 0;
switch (DamageCalculationType) switch (DamageCalculationType)
{ {
case DamageCalculationType.HitShape: case DamageCalculationType.HitShape:
falloffDistance = closestActiveShape.Second.Length; falloffDistance = closestActiveShape.Distance.Length;
break; break;
case DamageCalculationType.ClosestTargetablePosition: case DamageCalculationType.ClosestTargetablePosition:
falloffDistance = victim.GetTargetablePositions().Select(x => (x - pos).Length).Min(); falloffDistance = victim.GetTargetablePositions().Select(x => (x - pos).Length).Min();
@@ -104,7 +104,7 @@ namespace OpenRA.Mods.Common.Warheads
ImpactOrientation = impactOrientation, ImpactOrientation = impactOrientation,
}; };
InflictDamage(victim, firedBy, closestActiveShape.First, updatedWarheadArgs); InflictDamage(victim, firedBy, closestActiveShape.HitShape, updatedWarheadArgs);
} }
} }

View File

@@ -38,18 +38,18 @@ namespace OpenRA.Mods.Common.Warheads
var closestActiveShape = victim.TraitsImplementing<HitShape>() var closestActiveShape = victim.TraitsImplementing<HitShape>()
.Where(Exts.IsTraitEnabled) .Where(Exts.IsTraitEnabled)
.Select(s => Pair.New(s, s.DistanceFromEdge(victim, pos))) .Select(s => (HitShape: s, Distance: s.DistanceFromEdge(victim, pos)))
.MinByOrDefault(s => s.Second); .MinByOrDefault(s => s.Distance);
// Cannot be damaged without an active HitShape. // Cannot be damaged without an active HitShape.
if (closestActiveShape.First == null) if (closestActiveShape.HitShape == null)
continue; continue;
// Cannot be damaged if HitShape is outside Spread. // Cannot be damaged if HitShape is outside Spread.
if (closestActiveShape.Second > Spread) if (closestActiveShape.Distance > Spread)
continue; continue;
InflictDamage(victim, firedBy, closestActiveShape.First, args); InflictDamage(victim, firedBy, closestActiveShape.HitShape, args);
} }
} }
} }

View File

@@ -20,25 +20,25 @@ namespace OpenRA.Mods.Common.Widgets
public class LabelWithHighlightWidget : LabelWidget public class LabelWithHighlightWidget : LabelWidget
{ {
public Color HighlightColor = ChromeMetrics.Get<Color>("TextHighlightColor"); public Color HighlightColor = ChromeMetrics.Get<Color>("TextHighlightColor");
readonly CachedTransform<string, Pair<string, bool>[]> textComponents; readonly CachedTransform<string, (string Text, bool Highlighted)[]> textComponents;
[ObjectCreator.UseCtor] [ObjectCreator.UseCtor]
public LabelWithHighlightWidget() public LabelWithHighlightWidget()
: base() : base()
{ {
textComponents = new CachedTransform<string, Pair<string, bool>[]>(MakeComponents); textComponents = new CachedTransform<string, (string, bool)[]>(MakeComponents);
} }
protected LabelWithHighlightWidget(LabelWithHighlightWidget other) protected LabelWithHighlightWidget(LabelWithHighlightWidget other)
: base(other) : base(other)
{ {
HighlightColor = other.HighlightColor; HighlightColor = other.HighlightColor;
textComponents = new CachedTransform<string, Pair<string, bool>[]>(MakeComponents); textComponents = new CachedTransform<string, (string, bool)[]>(MakeComponents);
} }
Pair<string, bool>[] MakeComponents(string text) (string, bool)[] MakeComponents(string text)
{ {
List<Pair<string, bool>> components = new List<Pair<string, bool>>(); var components = new List<(string, bool)>();
foreach (var l in text.Split(new[] { "\\n" }, StringSplitOptions.None)) foreach (var l in text.Split(new[] { "\\n" }, StringSplitOptions.None))
{ {
var line = l; var line = l;
@@ -54,18 +54,18 @@ namespace OpenRA.Mods.Common.Widgets
{ {
// Normal line segment before highlight // Normal line segment before highlight
var lineNormal = line.Substring(0, highlightStart); var lineNormal = line.Substring(0, highlightStart);
components.Add(Pair.New(lineNormal, false)); components.Add((lineNormal, false));
} }
// Highlight line segment // Highlight line segment
var lineHighlight = line.Substring(highlightStart + 1, highlightEnd - highlightStart - 1); var lineHighlight = line.Substring(highlightStart + 1, highlightEnd - highlightStart - 1);
components.Add(Pair.New(lineHighlight, true)); components.Add((lineHighlight, true));
line = line.Substring(highlightEnd + 1); line = line.Substring(highlightEnd + 1);
} }
else else
{ {
// Final normal line segment // Final normal line segment
components.Add(Pair.New(line, false)); components.Add((line, false));
break; break;
} }
} }
@@ -79,8 +79,8 @@ namespace OpenRA.Mods.Common.Widgets
var advance = 0; var advance = 0;
foreach (var c in textComponents.Update(text)) foreach (var c in textComponents.Update(text))
{ {
base.DrawInner(c.First, font, c.Second ? HighlightColor : color, position + new int2(advance, 0)); base.DrawInner(c.Text, font, c.Highlighted ? HighlightColor : color, position + new int2(advance, 0));
advance += font.Measure(c.First).X; advance += font.Measure(c.Text).X;
} }
} }

View File

@@ -66,10 +66,10 @@ namespace OpenRA.Mods.Common.Widgets.Logic
playerPanel.RemoveChildren(); playerPanel.RemoveChildren();
var teams = world.Players.Where(p => !p.NonCombatant && p.Playable) var teams = world.Players.Where(p => !p.NonCombatant && p.Playable)
.Select(p => new Pair<Player, PlayerStatistics>(p, p.PlayerActor.TraitOrDefault<PlayerStatistics>())) .Select(p => (Player: p, PlayerStatistics: p.PlayerActor.TraitOrDefault<PlayerStatistics>()))
.OrderByDescending(p => p.Second != null ? p.Second.Experience : 0) .OrderByDescending(p => p.PlayerStatistics != null ? p.PlayerStatistics.Experience : 0)
.GroupBy(p => (world.LobbyInfo.ClientWithIndex(p.First.ClientIndex) ?? new Session.Client()).Team) .GroupBy(p => (world.LobbyInfo.ClientWithIndex(p.Player.ClientIndex) ?? new Session.Client()).Team)
.OrderByDescending(g => g.Sum(gg => gg.Second != null ? gg.Second.Experience : 0)); .OrderByDescending(g => g.Sum(gg => gg.PlayerStatistics != null ? gg.PlayerStatistics.Experience : 0));
foreach (var t in teams) foreach (var t in teams)
{ {
@@ -79,7 +79,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic
teamHeader.Get<LabelWidget>("TEAM").GetText = () => t.Key == 0 ? "No Team" : "Team {0}".F(t.Key); teamHeader.Get<LabelWidget>("TEAM").GetText = () => t.Key == 0 ? "No Team" : "Team {0}".F(t.Key);
var teamRating = teamHeader.Get<LabelWidget>("TEAM_SCORE"); var teamRating = teamHeader.Get<LabelWidget>("TEAM_SCORE");
var scoreCache = new CachedTransform<int, string>(s => s.ToString()); var scoreCache = new CachedTransform<int, string>(s => s.ToString());
var teamMemberScores = t.Select(tt => tt.Second).Where(s => s != null).ToArray().Select(s => s.Experience); var teamMemberScores = t.Select(tt => tt.PlayerStatistics).Where(s => s != null).ToArray().Select(s => s.Experience);
teamRating.GetText = () => scoreCache.Update(teamMemberScores.Sum()); teamRating.GetText = () => scoreCache.Update(teamMemberScores.Sum());
playerPanel.AddChild(teamHeader); playerPanel.AddChild(teamHeader);
@@ -87,7 +87,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic
foreach (var p in t.ToList()) foreach (var p in t.ToList())
{ {
var pp = p.First; var pp = p.Player;
var client = world.LobbyInfo.ClientWithIndex(pp.ClientIndex); var client = world.LobbyInfo.ClientWithIndex(pp.ClientIndex);
var item = playerTemplate.Clone(); var item = playerTemplate.Clone();
LobbyUtils.SetupProfileWidget(item, client, orderManager, worldRenderer); LobbyUtils.SetupProfileWidget(item, client, orderManager, worldRenderer);
@@ -110,7 +110,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic
} }
var scoreCache = new CachedTransform<int, string>(s => s.ToString()); var scoreCache = new CachedTransform<int, string>(s => s.ToString());
item.Get<LabelWidget>("SCORE").GetText = () => scoreCache.Update(p.Second != null ? p.Second.Experience : 0); item.Get<LabelWidget>("SCORE").GetText = () => scoreCache.Update(p.PlayerStatistics != null ? p.PlayerStatistics.Experience : 0);
playerPanel.AddChild(item); playerPanel.AddChild(item);
} }
@@ -133,13 +133,13 @@ namespace OpenRA.Mods.Common.Widgets.Logic
var nameFont = Game.Renderer.Fonts[nameLabel.Font]; var nameFont = Game.Renderer.Fonts[nameLabel.Font];
var suffixLength = new CachedTransform<string, int>(s => nameFont.Measure(s).X); var suffixLength = new CachedTransform<string, int>(s => nameFont.Measure(s).X);
var name = new CachedTransform<Pair<string, string>, string>(c => var name = new CachedTransform<(string Name, string Suffix), string>(c =>
WidgetUtils.TruncateText(c.First, nameLabel.Bounds.Width - suffixLength.Update(c.Second), nameFont) + c.Second); WidgetUtils.TruncateText(c.Name, nameLabel.Bounds.Width - suffixLength.Update(c.Suffix), nameFont) + c.Suffix);
nameLabel.GetText = () => nameLabel.GetText = () =>
{ {
var suffix = client.State == Session.ClientState.Disconnected ? " (Gone)" : ""; var suffix = client.State == Session.ClientState.Disconnected ? " (Gone)" : "";
return name.Update(Pair.New(client.Name, suffix)); return name.Update((client.Name, suffix));
}; };
var kickButton = item.Get<ButtonWidget>("KICK"); var kickButton = item.Get<ButtonWidget>("KICK");

View File

@@ -442,8 +442,8 @@ namespace OpenRA.Mods.Common.Widgets.Logic
if (powerRes != null) if (powerRes != null)
{ {
var power = template.Get<LabelWidget>("POWER"); var power = template.Get<LabelWidget>("POWER");
var powerText = new CachedTransform<Pair<int, int>, string>(p => p.First + "/" + p.Second); var powerText = new CachedTransform<(int PowerDrained, int PowerProvided), string>(p => p.PowerDrained + "/" + p.PowerProvided);
power.GetText = () => powerText.Update(new Pair<int, int>(powerRes.PowerDrained, powerRes.PowerProvided)); power.GetText = () => powerText.Update((powerRes.PowerDrained, powerRes.PowerProvided));
power.GetColor = () => GetPowerColor(powerRes.PowerState); power.GetColor = () => GetPowerColor(powerRes.PowerState);
} }

View File

@@ -162,15 +162,15 @@ namespace OpenRA.Mods.Common.Widgets.Logic
} }
/// <summary>Splits a string into two parts on the first instance of a given token.</summary> /// <summary>Splits a string into two parts on the first instance of a given token.</summary>
static Pair<string, string> SplitOnFirstToken(string input, string token = "\\n") static (string First, string Second) SplitOnFirstToken(string input, string token = "\\n")
{ {
if (string.IsNullOrEmpty(input)) if (string.IsNullOrEmpty(input))
return Pair.New<string, string>(null, null); return (null, null);
var split = input.IndexOf(token, StringComparison.Ordinal); var split = input.IndexOf(token, StringComparison.Ordinal);
var first = split > 0 ? input.Substring(0, split) : input; var first = split > 0 ? input.Substring(0, split) : input;
var second = split > 0 ? input.Substring(split + token.Length) : null; var second = split > 0 ? input.Substring(split + token.Length) : null;
return Pair.New(first, second); return (first, second);
} }
public static void ShowFactionDropDown(DropDownButtonWidget dropdown, Session.Client client, public static void ShowFactionDropDown(DropDownButtonWidget dropdown, Session.Client client,
@@ -253,9 +253,9 @@ namespace OpenRA.Mods.Common.Widgets.Logic
var spawnSize = ChromeProvider.GetImage("lobby-bits", "spawn-unclaimed").Size.XY; var spawnSize = ChromeProvider.GetImage("lobby-bits", "spawn-unclaimed").Size.XY;
var selectedSpawn = preview.SpawnPoints var selectedSpawn = preview.SpawnPoints
.Select((sp, i) => Pair.New(mapPreview.ConvertToPreview(sp, preview.GridType), i)) .Select((sp, i) => (SpawnLocation: mapPreview.ConvertToPreview(sp, preview.GridType), Index: i))
.Where(a => ((a.First - mi.Location).ToFloat2() / spawnSize * 2).LengthSquared <= 1) .Where(a => ((a.SpawnLocation - mi.Location).ToFloat2() / spawnSize * 2).LengthSquared <= 1)
.Select(a => a.Second + 1) .Select(a => a.Index + 1)
.FirstOrDefault(); .FirstOrDefault();
var locals = orderManager.LobbyInfo.Clients.Where(c => c.Index == orderManager.LocalClient.Index || (Game.IsHost && c.Bot != null)); var locals = orderManager.LobbyInfo.Clients.Where(c => c.Index == orderManager.LocalClient.Index || (Game.IsHost && c.Bot != null));

View File

@@ -12,7 +12,6 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using OpenRA.Primitives;
using OpenRA.Widgets; using OpenRA.Widgets;
namespace OpenRA.Mods.Common.Widgets.Logic namespace OpenRA.Mods.Common.Widgets.Logic
@@ -182,20 +181,20 @@ namespace OpenRA.Mods.Common.Widgets.Logic
// Order categories alphabetically // Order categories alphabetically
var categories = categoryDict var categories = categoryDict
.Select(kv => Pair.New(kv.Key, kv.Value)) .Select(kv => (Category: kv.Key, Count: kv.Value))
.OrderBy(p => p.First) .OrderBy(p => p.Category)
.ToList(); .ToList();
// 'all game types' extra item // 'all game types' extra item
categories.Insert(0, Pair.New(null as string, tabMaps[tab].Count())); categories.Insert(0, (null as string, tabMaps[tab].Count()));
Func<Pair<string, int>, string> showItem = x => "{0} ({1})".F(x.First ?? "All Maps", x.Second); Func<(string Category, int Count), string> showItem = x => "{0} ({1})".F(x.Category ?? "All Maps", x.Count);
Func<Pair<string, int>, ScrollItemWidget, ScrollItemWidget> setupItem = (ii, template) => Func<(string Category, int Count), ScrollItemWidget, ScrollItemWidget> setupItem = (ii, template) =>
{ {
var item = ScrollItemWidget.Setup(template, var item = ScrollItemWidget.Setup(template,
() => category == ii.First, () => category == ii.Category,
() => { category = ii.First; EnumerateMaps(tab, itemTemplate); }); () => { category = ii.Category; EnumerateMaps(tab, itemTemplate); });
item.Get<LabelWidget>("LABEL").GetText = () => showItem(ii); item.Get<LabelWidget>("LABEL").GetText = () => showItem(ii);
return item; return item;
}; };
@@ -205,9 +204,9 @@ namespace OpenRA.Mods.Common.Widgets.Logic
gameModeDropdown.GetText = () => gameModeDropdown.GetText = () =>
{ {
var item = categories.FirstOrDefault(m => m.First == category); var item = categories.FirstOrDefault(m => m.Category == category);
if (item == default(Pair<string, int>)) if (item == default((string, int)))
item.First = "No matches"; item.Category = "No matches";
return showItem(item); return showItem(item);
}; };

View File

@@ -138,25 +138,25 @@ namespace OpenRA.Mods.Common.Widgets.Logic
if (ddb != null) if (ddb != null)
{ {
// Using list to maintain the order // Using list to maintain the order
var options = new List<Pair<GameType, string>> var options = new List<(GameType GameType, string Text)>
{ {
Pair.New(GameType.Any, ddb.GetText()), (GameType.Any, ddb.GetText()),
Pair.New(GameType.Singleplayer, "Singleplayer"), (GameType.Singleplayer, "Singleplayer"),
Pair.New(GameType.Multiplayer, "Multiplayer") (GameType.Multiplayer, "Multiplayer")
}; };
var lookup = options.ToDictionary(kvp => kvp.First, kvp => kvp.Second); var lookup = options.ToDictionary(kvp => kvp.GameType, kvp => kvp.Text);
ddb.GetText = () => lookup[filter.Type]; ddb.GetText = () => lookup[filter.Type];
ddb.OnMouseDown = _ => ddb.OnMouseDown = _ =>
{ {
Func<Pair<GameType, string>, ScrollItemWidget, ScrollItemWidget> setupItem = (option, tpl) => Func<(GameType GameType, string Text), ScrollItemWidget, ScrollItemWidget> setupItem = (option, tpl) =>
{ {
var item = ScrollItemWidget.Setup( var item = ScrollItemWidget.Setup(
tpl, tpl,
() => filter.Type == option.First, () => filter.Type == option.GameType,
() => { filter.Type = option.First; ApplyFilter(); }); () => { filter.Type = option.GameType; ApplyFilter(); });
item.Get<LabelWidget>("LABEL").GetText = () => option.Second; item.Get<LabelWidget>("LABEL").GetText = () => option.Text;
return item; return item;
}; };
@@ -171,28 +171,28 @@ namespace OpenRA.Mods.Common.Widgets.Logic
if (ddb != null) if (ddb != null)
{ {
// Using list to maintain the order // Using list to maintain the order
var options = new List<Pair<DateType, string>> var options = new List<(DateType DateType, string Text)>
{ {
Pair.New(DateType.Any, ddb.GetText()), (DateType.Any, ddb.GetText()),
Pair.New(DateType.Today, "Today"), (DateType.Today, "Today"),
Pair.New(DateType.LastWeek, "Last 7 days"), (DateType.LastWeek, "Last 7 days"),
Pair.New(DateType.LastFortnight, "Last 14 days"), (DateType.LastFortnight, "Last 14 days"),
Pair.New(DateType.LastMonth, "Last 30 days") (DateType.LastMonth, "Last 30 days")
}; };
var lookup = options.ToDictionary(kvp => kvp.First, kvp => kvp.Second); var lookup = options.ToDictionary(kvp => kvp.DateType, kvp => kvp.Text);
ddb.GetText = () => lookup[filter.Date]; ddb.GetText = () => lookup[filter.Date];
ddb.OnMouseDown = _ => ddb.OnMouseDown = _ =>
{ {
Func<Pair<DateType, string>, ScrollItemWidget, ScrollItemWidget> setupItem = (option, tpl) => Func<(DateType DateType, string Text), ScrollItemWidget, ScrollItemWidget> setupItem = (option, tpl) =>
{ {
var item = ScrollItemWidget.Setup( var item = ScrollItemWidget.Setup(
tpl, tpl,
() => filter.Date == option.First, () => filter.Date == option.DateType,
() => { filter.Date = option.First; ApplyFilter(); }); () => { filter.Date = option.DateType; ApplyFilter(); });
item.Get<LabelWidget>("LABEL").GetText = () => option.Second; item.Get<LabelWidget>("LABEL").GetText = () => option.Text;
return item; return item;
}; };
@@ -207,27 +207,27 @@ namespace OpenRA.Mods.Common.Widgets.Logic
if (ddb != null) if (ddb != null)
{ {
// Using list to maintain the order // Using list to maintain the order
var options = new List<Pair<DurationType, string>> var options = new List<(DurationType DurationType, string Text)>
{ {
Pair.New(DurationType.Any, ddb.GetText()), (DurationType.Any, ddb.GetText()),
Pair.New(DurationType.VeryShort, "Under 5 min"), (DurationType.VeryShort, "Under 5 min"),
Pair.New(DurationType.Short, "Short (10 min)"), (DurationType.Short, "Short (10 min)"),
Pair.New(DurationType.Medium, "Medium (30 min)"), (DurationType.Medium, "Medium (30 min)"),
Pair.New(DurationType.Long, "Long (60+ min)") (DurationType.Long, "Long (60+ min)")
}; };
var lookup = options.ToDictionary(kvp => kvp.First, kvp => kvp.Second); var lookup = options.ToDictionary(kvp => kvp.DurationType, kvp => kvp.Text);
ddb.GetText = () => lookup[filter.Duration]; ddb.GetText = () => lookup[filter.Duration];
ddb.OnMouseDown = _ => ddb.OnMouseDown = _ =>
{ {
Func<Pair<DurationType, string>, ScrollItemWidget, ScrollItemWidget> setupItem = (option, tpl) => Func<(DurationType DurationType, string Text), ScrollItemWidget, ScrollItemWidget> setupItem = (option, tpl) =>
{ {
var item = ScrollItemWidget.Setup( var item = ScrollItemWidget.Setup(
tpl, tpl,
() => filter.Duration == option.First, () => filter.Duration == option.DurationType,
() => { filter.Duration = option.First; ApplyFilter(); }); () => { filter.Duration = option.DurationType; ApplyFilter(); });
item.Get<LabelWidget>("LABEL").GetText = () => option.Second; item.Get<LabelWidget>("LABEL").GetText = () => option.Text;
return item; return item;
}; };
@@ -244,25 +244,25 @@ namespace OpenRA.Mods.Common.Widgets.Logic
ddb.IsDisabled = () => string.IsNullOrEmpty(filter.PlayerName); ddb.IsDisabled = () => string.IsNullOrEmpty(filter.PlayerName);
// Using list to maintain the order // Using list to maintain the order
var options = new List<Pair<WinState, string>> var options = new List<(WinState WinState, string Text)>
{ {
Pair.New(WinState.Undefined, ddb.GetText()), (WinState.Undefined, ddb.GetText()),
Pair.New(WinState.Lost, "Defeat"), (WinState.Lost, "Defeat"),
Pair.New(WinState.Won, "Victory") (WinState.Won, "Victory")
}; };
var lookup = options.ToDictionary(kvp => kvp.First, kvp => kvp.Second); var lookup = options.ToDictionary(kvp => kvp.WinState, kvp => kvp.Text);
ddb.GetText = () => lookup[filter.Outcome]; ddb.GetText = () => lookup[filter.Outcome];
ddb.OnMouseDown = _ => ddb.OnMouseDown = _ =>
{ {
Func<Pair<WinState, string>, ScrollItemWidget, ScrollItemWidget> setupItem = (option, tpl) => Func<(WinState WinState, string Text), ScrollItemWidget, ScrollItemWidget> setupItem = (option, tpl) =>
{ {
var item = ScrollItemWidget.Setup( var item = ScrollItemWidget.Setup(
tpl, tpl,
() => filter.Outcome == option.First, () => filter.Outcome == option.WinState,
() => { filter.Outcome = option.First; ApplyFilter(); }); () => { filter.Outcome = option.WinState; ApplyFilter(); });
item.Get<LabelWidget>("LABEL").GetText = () => option.Second; item.Get<LabelWidget>("LABEL").GetText = () => option.Text;
return item; return item;
}; };

View File

@@ -14,7 +14,6 @@ using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis; using System.Diagnostics.CodeAnalysis;
using System.Globalization; using System.Globalization;
using System.Linq; using System.Linq;
using OpenRA.Primitives;
using OpenRA.Widgets; using OpenRA.Widgets;
namespace OpenRA.Mods.Common.Widgets.Logic namespace OpenRA.Mods.Common.Widgets.Logic
@@ -26,22 +25,22 @@ namespace OpenRA.Mods.Common.Widgets.Logic
// Increment the version number when adding new stats // Increment the version number when adding new stats
const int SystemInformationVersion = 4; const int SystemInformationVersion = 4;
static Dictionary<string, Pair<string, string>> GetSystemInformation() static Dictionary<string, (string Label, string Value)> GetSystemInformation()
{ {
var lang = CultureInfo.InstalledUICulture.TwoLetterISOLanguageName; var lang = CultureInfo.InstalledUICulture.TwoLetterISOLanguageName;
return new Dictionary<string, Pair<string, string>>() return new Dictionary<string, (string, string)>()
{ {
{ "id", Pair.New("Anonymous ID", Game.Settings.Debug.UUID) }, { "id", ("Anonymous ID", Game.Settings.Debug.UUID) },
{ "platform", Pair.New("OS Type", Platform.CurrentPlatform.ToString()) }, { "platform", ("OS Type", Platform.CurrentPlatform.ToString()) },
{ "os", Pair.New("OS Version", Environment.OSVersion.ToString()) }, { "os", ("OS Version", Environment.OSVersion.ToString()) },
{ "x64", Pair.New("OS is 64 bit", Environment.Is64BitOperatingSystem.ToString()) }, { "x64", ("OS is 64 bit", Environment.Is64BitOperatingSystem.ToString()) },
{ "x64process", Pair.New("Process is 64 bit", Environment.Is64BitProcess.ToString()) }, { "x64process", ("Process is 64 bit", Environment.Is64BitProcess.ToString()) },
{ "runtime", Pair.New(".NET Runtime", Platform.RuntimeVersion) }, { "runtime", (".NET Runtime", Platform.RuntimeVersion) },
{ "gl", Pair.New("OpenGL Version", Game.Renderer.GLVersion) }, { "gl", ("OpenGL Version", Game.Renderer.GLVersion) },
{ "windowsize", Pair.New("Window Size", "{0}x{1}".F(Game.Renderer.NativeResolution.Width, Game.Renderer.NativeResolution.Height)) }, { "windowsize", ("Window Size", "{0}x{1}".F(Game.Renderer.NativeResolution.Width, Game.Renderer.NativeResolution.Height)) },
{ "windowscale", Pair.New("Window Scale", Game.Renderer.NativeWindowScale.ToString("F2", CultureInfo.InvariantCulture)) }, { "windowscale", ("Window Scale", Game.Renderer.NativeWindowScale.ToString("F2", CultureInfo.InvariantCulture)) },
{ "uiscale", Pair.New("UI Scale", Game.Settings.Graphics.UIScale.ToString("F2", CultureInfo.InvariantCulture)) }, { "uiscale", ("UI Scale", Game.Settings.Graphics.UIScale.ToString("F2", CultureInfo.InvariantCulture)) },
{ "lang", Pair.New("System Language", lang) } { "lang", ("System Language", lang) }
}; };
} }
@@ -57,7 +56,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic
return "&sysinfoversion={0}&".F(SystemInformationVersion) return "&sysinfoversion={0}&".F(SystemInformationVersion)
+ GetSystemInformation() + GetSystemInformation()
.Select(kv => kv.Key + "=" + Uri.EscapeUriString(kv.Value.Second)) .Select(kv => kv.Key + "=" + Uri.EscapeUriString(kv.Value.Value))
.JoinWith("&"); .JoinWith("&");
} }
@@ -75,7 +74,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic
foreach (var info in GetSystemInformation().Values) foreach (var info in GetSystemInformation().Values)
{ {
var label = template.Clone() as LabelWidget; var label = template.Clone() as LabelWidget;
var text = info.First + ": " + info.Second; var text = info.Label + ": " + info.Value;
label.GetText = () => text; label.GetText = () => text;
sysInfoData.AddChild(label); sysInfoData.AddChild(label);
} }

View File

@@ -206,8 +206,8 @@ namespace OpenRA.Mods.Common.Widgets
void UpdateTerrainColor(MPos uv) void UpdateTerrainColor(MPos uv)
{ {
var colorPair = playerRadarTerrain != null && playerRadarTerrain.IsInitialized ? playerRadarTerrain[uv] : PlayerRadarTerrain.GetColor(world.Map, uv); var colorPair = playerRadarTerrain != null && playerRadarTerrain.IsInitialized ? playerRadarTerrain[uv] : PlayerRadarTerrain.GetColor(world.Map, uv);
var leftColor = colorPair.First; var leftColor = colorPair.Left;
var rightColor = colorPair.Second; var rightColor = colorPair.Right;
var stride = radarSheet.Size.Width; var stride = radarSheet.Size.Width;
@@ -386,7 +386,7 @@ namespace OpenRA.Mods.Common.Widgets
var stride = radarSheet.Size.Width; var stride = radarSheet.Size.Width;
Array.Clear(radarData, 4 * actorSprite.Bounds.Top * stride, 4 * actorSprite.Bounds.Height * stride); Array.Clear(radarData, 4 * actorSprite.Bounds.Top * stride, 4 * actorSprite.Bounds.Height * stride);
var cells = new List<Pair<CPos, Color>>(); var cells = new List<(CPos Cell, Color Color)>();
unsafe unsafe
{ {
@@ -403,11 +403,11 @@ namespace OpenRA.Mods.Common.Widgets
t.Trait.PopulateRadarSignatureCells(t.Actor, cells); t.Trait.PopulateRadarSignatureCells(t.Actor, cells);
foreach (var cell in cells) foreach (var cell in cells)
{ {
if (!world.Map.Contains(cell.First)) if (!world.Map.Contains(cell.Cell))
continue; continue;
var uv = cell.First.ToMPos(world.Map.Grid.Type); var uv = cell.Cell.ToMPos(world.Map.Grid.Type);
var color = cell.Second.ToArgb(); var color = cell.Color.ToArgb();
if (isRectangularIsometric) if (isRectangularIsometric)
{ {
// Odd rows are shifted right by 1px // Odd rows are shifted right by 1px

View File

@@ -27,7 +27,7 @@ namespace OpenRA.Mods.Common.Widgets
readonly int timestep; readonly int timestep;
readonly IEnumerable<SupportPowerInstance> powers; readonly IEnumerable<SupportPowerInstance> powers;
readonly Color bgDark, bgLight; readonly Color bgDark, bgLight;
Pair<string, Color>[] texts; (string Text, Color Color)[] texts;
[ObjectCreator.UseCtor] [ObjectCreator.UseCtor]
public SupportPowerTimerWidget(World world) public SupportPowerTimerWidget(World world)
@@ -67,7 +67,7 @@ namespace OpenRA.Mods.Common.Widgets
var color = !p.Ready || Game.LocalTick % 50 < 25 ? playerColor : Color.White; var color = !p.Ready || Game.LocalTick % 50 < 25 ? playerColor : Color.White;
return Pair.New(text, color); return (text, color);
}).ToArray(); }).ToArray();
} }
@@ -80,8 +80,8 @@ namespace OpenRA.Mods.Common.Widgets
foreach (var t in texts) foreach (var t in texts)
{ {
var font = Game.Renderer.Fonts[Font]; var font = Game.Renderer.Fonts[Font];
font.DrawTextWithShadow(t.First, new float2(Bounds.Location) + new float2(0, y), t.Second, bgDark, bgLight, 1); font.DrawTextWithShadow(t.Text, new float2(Bounds.Location) + new float2(0, y), t.Color, bgDark, bgLight, 1);
y += (font.Measure(t.First).Y + 5) * (int)Order; y += (font.Measure(t.Text).Y + 5) * (int)Order;
} }
} }

View File

@@ -337,19 +337,19 @@ namespace OpenRA.Mods.Common.Widgets
{ {
var client = p.World.LobbyInfo.ClientWithIndex(p.ClientIndex); var client = p.World.LobbyInfo.ClientWithIndex(p.ClientIndex);
var nameFont = Game.Renderer.Fonts[label.Font]; var nameFont = Game.Renderer.Fonts[label.Font];
var name = new CachedTransform<Tuple<string, WinState, Session.ClientState>, string>(c => var name = new CachedTransform<(string Name, WinState WinState, Session.ClientState ClientState), string>(c =>
{ {
var suffix = c.Item2 == WinState.Undefined ? "" : " (" + c.Item2 + ")"; var suffix = c.WinState == WinState.Undefined ? "" : " (" + c.Item2 + ")";
if (c.Item3 == Session.ClientState.Disconnected) if (c.ClientState == Session.ClientState.Disconnected)
suffix = " (Gone)"; suffix = " (Gone)";
return TruncateText(c.Item1, label.Bounds.Width - nameFont.Measure(suffix).X, nameFont) + suffix; return TruncateText(c.Name, label.Bounds.Width - nameFont.Measure(suffix).X, nameFont) + suffix;
}); });
label.GetText = () => label.GetText = () =>
{ {
var clientState = client != null ? client.State : Session.ClientState.Ready; var clientState = client != null ? client.State : Session.ClientState.Ready;
return name.Update(Tuple.Create(p.PlayerName, p.WinState, clientState)); return name.Update((p.PlayerName, p.WinState, clientState));
}; };
} }
} }

View File

@@ -21,8 +21,8 @@ namespace OpenRA.Mods.D2k.Lint
{ {
foreach (var actorData in D2kMapImporter.ActorDataByActorCode.Values) foreach (var actorData in D2kMapImporter.ActorDataByActorCode.Values)
{ {
if (!rules.Actors.ContainsKey(actorData.First)) if (!rules.Actors.ContainsKey(actorData.Actor))
emitError("Undefined actor {0} in map import code.".F(actorData.First)); emitError("Undefined actor {0} in map import code.".F(actorData.Actor));
} }
} }
} }

View File

@@ -3,7 +3,7 @@
<TargetFramework>net472</TargetFramework> <TargetFramework>net472</TargetFramework>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks> <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<Optimize>true</Optimize> <Optimize>true</Optimize>
<LangVersion>5</LangVersion> <LangVersion>7.3</LangVersion>
<DebugSymbols>true</DebugSymbols> <DebugSymbols>true</DebugSymbols>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors> <TreatWarningsAsErrors>true</TreatWarningsAsErrors>
<OutputPath>../mods/d2k</OutputPath> <OutputPath>../mods/d2k</OutputPath>

View File

@@ -21,236 +21,236 @@ namespace OpenRA.Mods.D2k.UtilityCommands
{ {
const int MapCordonWidth = 2; const int MapCordonWidth = 2;
public static Dictionary<int, Pair<string, string>> ActorDataByActorCode = new Dictionary<int, Pair<string, string>> public static Dictionary<int, (string Actor, string Owner)> ActorDataByActorCode = new Dictionary<int, (string, string)>
{ {
{ 20, Pair.New("wormspawner", "Creeps") }, { 20, ("wormspawner", "Creeps") },
{ 23, Pair.New("mpspawn", "Neutral") }, { 23, ("mpspawn", "Neutral") },
{ 41, Pair.New("spicebloom.spawnpoint", "Neutral") }, { 41, ("spicebloom.spawnpoint", "Neutral") },
{ 42, Pair.New("spicebloom.spawnpoint", "Neutral") }, { 42, ("spicebloom.spawnpoint", "Neutral") },
{ 43, Pair.New("spicebloom.spawnpoint", "Neutral") }, { 43, ("spicebloom.spawnpoint", "Neutral") },
{ 44, Pair.New("spicebloom.spawnpoint", "Neutral") }, { 44, ("spicebloom.spawnpoint", "Neutral") },
{ 45, Pair.New("spicebloom.spawnpoint", "Neutral") }, { 45, ("spicebloom.spawnpoint", "Neutral") },
// Atreides: // Atreides:
{ 4, Pair.New("wall", "Atreides") }, { 4, ("wall", "Atreides") },
{ 5, Pair.New("wind_trap", "Atreides") }, { 5, ("wind_trap", "Atreides") },
{ 8, Pair.New("construction_yard", "Atreides") }, { 8, ("construction_yard", "Atreides") },
{ 11, Pair.New("barracks", "Atreides") }, { 11, ("barracks", "Atreides") },
{ 14, Pair.New("refinery", "Atreides") }, { 14, ("refinery", "Atreides") },
{ 17, Pair.New("outpost", "Atreides") }, { 17, ("outpost", "Atreides") },
{ 63, Pair.New("light_factory", "Atreides") }, { 63, ("light_factory", "Atreides") },
{ 69, Pair.New("silo", "Atreides") }, { 69, ("silo", "Atreides") },
{ 72, Pair.New("heavy_factory", "Atreides") }, { 72, ("heavy_factory", "Atreides") },
{ 75, Pair.New("repair_pad", "Atreides") }, { 75, ("repair_pad", "Atreides") },
{ 78, Pair.New("medium_gun_turret", "Atreides") }, { 78, ("medium_gun_turret", "Atreides") },
{ 120, Pair.New("high_tech_factory", "Atreides") }, { 120, ("high_tech_factory", "Atreides") },
{ 123, Pair.New("large_gun_turret", "Atreides") }, { 123, ("large_gun_turret", "Atreides") },
{ 126, Pair.New("research_centre", "Atreides") }, { 126, ("research_centre", "Atreides") },
{ 129, Pair.New("starport", "Atreides") }, { 129, ("starport", "Atreides") },
{ 132, Pair.New("palace", "Atreides") }, { 132, ("palace", "Atreides") },
{ 180, Pair.New("light_inf", "Atreides") }, { 180, ("light_inf", "Atreides") },
{ 181, Pair.New("trooper", "Atreides") }, { 181, ("trooper", "Atreides") },
{ 182, Pair.New("fremen", "Atreides") }, { 182, ("fremen", "Atreides") },
{ 183, Pair.New("sardaukar", "Atreides") }, { 183, ("sardaukar", "Atreides") },
{ 184, Pair.New("engineer", "Atreides") }, { 184, ("engineer", "Atreides") },
{ 185, Pair.New("harvester", "Atreides") }, { 185, ("harvester", "Atreides") },
{ 186, Pair.New("mcv", "Atreides") }, { 186, ("mcv", "Atreides") },
{ 187, Pair.New("trike", "Atreides") }, { 187, ("trike", "Atreides") },
{ 188, Pair.New("quad", "Atreides") }, { 188, ("quad", "Atreides") },
{ 189, Pair.New("combat_tank_a", "Atreides") }, { 189, ("combat_tank_a", "Atreides") },
{ 190, Pair.New("missile_tank", "Atreides") }, { 190, ("missile_tank", "Atreides") },
{ 191, Pair.New("siege_tank", "Atreides") }, { 191, ("siege_tank", "Atreides") },
{ 192, Pair.New("carryall", "Atreides") }, { 192, ("carryall", "Atreides") },
{ 194, Pair.New("sonic_tank", "Atreides") }, { 194, ("sonic_tank", "Atreides") },
// Harkonnen: // Harkonnen:
{ 204, Pair.New("wall", "Harkonnen") }, { 204, ("wall", "Harkonnen") },
{ 205, Pair.New("wind_trap", "Harkonnen") }, { 205, ("wind_trap", "Harkonnen") },
{ 208, Pair.New("construction_yard", "Harkonnen") }, { 208, ("construction_yard", "Harkonnen") },
{ 211, Pair.New("barracks", "Harkonnen") }, { 211, ("barracks", "Harkonnen") },
{ 214, Pair.New("refinery", "Harkonnen") }, { 214, ("refinery", "Harkonnen") },
{ 217, Pair.New("outpost", "Harkonnen") }, { 217, ("outpost", "Harkonnen") },
{ 263, Pair.New("light_factory", "Harkonnen") }, { 263, ("light_factory", "Harkonnen") },
{ 269, Pair.New("silo", "Harkonnen") }, { 269, ("silo", "Harkonnen") },
{ 272, Pair.New("heavy_factory", "Harkonnen") }, { 272, ("heavy_factory", "Harkonnen") },
{ 275, Pair.New("repair_pad", "Harkonnen") }, { 275, ("repair_pad", "Harkonnen") },
{ 278, Pair.New("medium_gun_turret", "Harkonnen") }, { 278, ("medium_gun_turret", "Harkonnen") },
{ 320, Pair.New("high_tech_factory", "Harkonnen") }, { 320, ("high_tech_factory", "Harkonnen") },
{ 323, Pair.New("large_gun_turret", "Harkonnen") }, { 323, ("large_gun_turret", "Harkonnen") },
{ 326, Pair.New("research_centre", "Harkonnen") }, { 326, ("research_centre", "Harkonnen") },
{ 329, Pair.New("starport", "Harkonnen") }, { 329, ("starport", "Harkonnen") },
{ 332, Pair.New("palace", "Harkonnen") }, { 332, ("palace", "Harkonnen") },
{ 360, Pair.New("light_inf", "Harkonnen") }, { 360, ("light_inf", "Harkonnen") },
{ 361, Pair.New("trooper", "Harkonnen") }, { 361, ("trooper", "Harkonnen") },
{ 362, Pair.New("fremen", "Harkonnen") }, { 362, ("fremen", "Harkonnen") },
{ 363, Pair.New("mpsardaukar", "Harkonnen") }, { 363, ("mpsardaukar", "Harkonnen") },
{ 364, Pair.New("engineer", "Harkonnen") }, { 364, ("engineer", "Harkonnen") },
{ 365, Pair.New("harvester", "Harkonnen") }, { 365, ("harvester", "Harkonnen") },
{ 366, Pair.New("mcv", "Harkonnen") }, { 366, ("mcv", "Harkonnen") },
{ 367, Pair.New("trike", "Harkonnen") }, { 367, ("trike", "Harkonnen") },
{ 368, Pair.New("quad", "Harkonnen") }, { 368, ("quad", "Harkonnen") },
{ 369, Pair.New("combat_tank_h", "Harkonnen") }, { 369, ("combat_tank_h", "Harkonnen") },
{ 370, Pair.New("missile_tank", "Harkonnen") }, { 370, ("missile_tank", "Harkonnen") },
{ 371, Pair.New("siege_tank", "Harkonnen") }, { 371, ("siege_tank", "Harkonnen") },
{ 372, Pair.New("carryall", "Harkonnen") }, { 372, ("carryall", "Harkonnen") },
{ 374, Pair.New("devastator", "Harkonnen") }, { 374, ("devastator", "Harkonnen") },
// Ordos: // Ordos:
{ 404, Pair.New("wall", "Ordos") }, { 404, ("wall", "Ordos") },
{ 405, Pair.New("wind_trap", "Ordos") }, { 405, ("wind_trap", "Ordos") },
{ 408, Pair.New("construction_yard", "Ordos") }, { 408, ("construction_yard", "Ordos") },
{ 411, Pair.New("barracks", "Ordos") }, { 411, ("barracks", "Ordos") },
{ 414, Pair.New("refinery", "Ordos") }, { 414, ("refinery", "Ordos") },
{ 417, Pair.New("outpost", "Ordos") }, { 417, ("outpost", "Ordos") },
{ 463, Pair.New("light_factory", "Ordos") }, { 463, ("light_factory", "Ordos") },
{ 469, Pair.New("silo", "Ordos") }, { 469, ("silo", "Ordos") },
{ 472, Pair.New("heavy_factory", "Ordos") }, { 472, ("heavy_factory", "Ordos") },
{ 475, Pair.New("repair_pad", "Ordos") }, { 475, ("repair_pad", "Ordos") },
{ 478, Pair.New("medium_gun_turret", "Ordos") }, { 478, ("medium_gun_turret", "Ordos") },
{ 520, Pair.New("high_tech_factory", "Ordos") }, { 520, ("high_tech_factory", "Ordos") },
{ 523, Pair.New("large_gun_turret", "Ordos") }, { 523, ("large_gun_turret", "Ordos") },
{ 526, Pair.New("research_centre", "Ordos") }, { 526, ("research_centre", "Ordos") },
{ 529, Pair.New("starport", "Ordos") }, { 529, ("starport", "Ordos") },
{ 532, Pair.New("palace", "Ordos") }, { 532, ("palace", "Ordos") },
{ 560, Pair.New("light_inf", "Ordos") }, { 560, ("light_inf", "Ordos") },
{ 561, Pair.New("trooper", "Ordos") }, { 561, ("trooper", "Ordos") },
{ 562, Pair.New("saboteur", "Ordos") }, { 562, ("saboteur", "Ordos") },
{ 563, Pair.New("sardaukar", "Ordos") }, { 563, ("sardaukar", "Ordos") },
{ 564, Pair.New("engineer", "Ordos") }, { 564, ("engineer", "Ordos") },
{ 565, Pair.New("harvester", "Ordos") }, { 565, ("harvester", "Ordos") },
{ 566, Pair.New("mcv", "Ordos") }, { 566, ("mcv", "Ordos") },
{ 567, Pair.New("raider", "Ordos") }, { 567, ("raider", "Ordos") },
{ 568, Pair.New("quad", "Ordos") }, { 568, ("quad", "Ordos") },
{ 569, Pair.New("combat_tank_o", "Ordos") }, { 569, ("combat_tank_o", "Ordos") },
{ 570, Pair.New("missile_tank", "Ordos") }, { 570, ("missile_tank", "Ordos") },
{ 571, Pair.New("siege_tank", "Ordos") }, { 571, ("siege_tank", "Ordos") },
{ 572, Pair.New("carryall", "Ordos") }, { 572, ("carryall", "Ordos") },
{ 574, Pair.New("deviator", "Ordos") }, { 574, ("deviator", "Ordos") },
// Corrino: // Corrino:
{ 580, Pair.New("wall", "Corrino") }, { 580, ("wall", "Corrino") },
{ 581, Pair.New("wind_trap", "Corrino") }, { 581, ("wind_trap", "Corrino") },
{ 582, Pair.New("construction_yard", "Corrino") }, { 582, ("construction_yard", "Corrino") },
{ 583, Pair.New("barracks", "Corrino") }, { 583, ("barracks", "Corrino") },
{ 584, Pair.New("refinery", "Corrino") }, { 584, ("refinery", "Corrino") },
{ 585, Pair.New("outpost", "Corrino") }, { 585, ("outpost", "Corrino") },
{ 587, Pair.New("light_factory", "Corrino") }, { 587, ("light_factory", "Corrino") },
{ 588, Pair.New("palace", "Corrino") }, { 588, ("palace", "Corrino") },
{ 589, Pair.New("silo", "Corrino") }, { 589, ("silo", "Corrino") },
{ 590, Pair.New("heavy_factory", "Corrino") }, { 590, ("heavy_factory", "Corrino") },
{ 591, Pair.New("repair_pad", "Corrino") }, { 591, ("repair_pad", "Corrino") },
{ 592, Pair.New("medium_gun_turret", "Corrino") }, { 592, ("medium_gun_turret", "Corrino") },
{ 593, Pair.New("high_tech_factory", "Corrino") }, { 593, ("high_tech_factory", "Corrino") },
{ 594, Pair.New("large_gun_turret", "Corrino") }, { 594, ("large_gun_turret", "Corrino") },
{ 595, Pair.New("research_centre", "Corrino") }, { 595, ("research_centre", "Corrino") },
{ 596, Pair.New("starport", "Corrino") }, { 596, ("starport", "Corrino") },
{ 597, Pair.New("sietch", "Corrino") }, { 597, ("sietch", "Corrino") },
{ 598, Pair.New("light_inf", "Corrino") }, { 598, ("light_inf", "Corrino") },
{ 599, Pair.New("trooper", "Corrino") }, { 599, ("trooper", "Corrino") },
{ 600, Pair.New("sardaukar", "Corrino") }, { 600, ("sardaukar", "Corrino") },
{ 601, Pair.New("fremen", "Corrino") }, { 601, ("fremen", "Corrino") },
{ 602, Pair.New("engineer", "Corrino") }, { 602, ("engineer", "Corrino") },
{ 603, Pair.New("harvester", "Corrino") }, { 603, ("harvester", "Corrino") },
{ 604, Pair.New("mcv", "Corrino") }, { 604, ("mcv", "Corrino") },
{ 605, Pair.New("trike", "Corrino") }, { 605, ("trike", "Corrino") },
{ 606, Pair.New("quad", "Corrino") }, { 606, ("quad", "Corrino") },
{ 607, Pair.New("combat_tank_h", "Corrino") }, { 607, ("combat_tank_h", "Corrino") },
{ 608, Pair.New("missile_tank", "Corrino") }, { 608, ("missile_tank", "Corrino") },
{ 609, Pair.New("siege_tank", "Corrino") }, { 609, ("siege_tank", "Corrino") },
{ 610, Pair.New("carryall", "Corrino") }, { 610, ("carryall", "Corrino") },
// Fremen: // Fremen:
{ 620, Pair.New("wall", "Fremen") }, { 620, ("wall", "Fremen") },
{ 621, Pair.New("wind_trap", "Fremen") }, { 621, ("wind_trap", "Fremen") },
{ 622, Pair.New("construction_yard", "Fremen") }, { 622, ("construction_yard", "Fremen") },
{ 623, Pair.New("barracks", "Fremen") }, { 623, ("barracks", "Fremen") },
{ 624, Pair.New("refinery", "Fremen") }, { 624, ("refinery", "Fremen") },
{ 625, Pair.New("outpost", "Fremen") }, { 625, ("outpost", "Fremen") },
{ 627, Pair.New("light_factory", "Fremen") }, { 627, ("light_factory", "Fremen") },
{ 628, Pair.New("palace", "Fremen") }, { 628, ("palace", "Fremen") },
{ 629, Pair.New("silo", "Fremen") }, { 629, ("silo", "Fremen") },
{ 630, Pair.New("heavy_factory", "Fremen") }, { 630, ("heavy_factory", "Fremen") },
{ 631, Pair.New("repair_pad", "Fremen") }, { 631, ("repair_pad", "Fremen") },
{ 632, Pair.New("medium_gun_turret", "Fremen") }, { 632, ("medium_gun_turret", "Fremen") },
{ 633, Pair.New("high_tech_factory", "Fremen") }, { 633, ("high_tech_factory", "Fremen") },
{ 634, Pair.New("large_gun_turret", "Fremen") }, { 634, ("large_gun_turret", "Fremen") },
{ 635, Pair.New("research_centre", "Fremen") }, { 635, ("research_centre", "Fremen") },
{ 636, Pair.New("starport", "Fremen") }, { 636, ("starport", "Fremen") },
{ 637, Pair.New("sietch", "Fremen") }, { 637, ("sietch", "Fremen") },
{ 638, Pair.New("light_inf", "Fremen") }, { 638, ("light_inf", "Fremen") },
{ 639, Pair.New("trooper", "Fremen") }, { 639, ("trooper", "Fremen") },
{ 640, Pair.New("fremen", "Fremen") }, { 640, ("fremen", "Fremen") },
{ 641, Pair.New("nsfremen", "Fremen") }, { 641, ("nsfremen", "Fremen") },
{ 642, Pair.New("engineer", "Fremen") }, { 642, ("engineer", "Fremen") },
{ 643, Pair.New("harvester", "Fremen") }, { 643, ("harvester", "Fremen") },
{ 644, Pair.New("mcv", "Fremen") }, { 644, ("mcv", "Fremen") },
{ 645, Pair.New("trike", "Fremen") }, { 645, ("trike", "Fremen") },
{ 646, Pair.New("quad", "Fremen") }, { 646, ("quad", "Fremen") },
{ 647, Pair.New("combat_tank_a", "Fremen") }, { 647, ("combat_tank_a", "Fremen") },
{ 648, Pair.New("missile_tank", "Fremen") }, { 648, ("missile_tank", "Fremen") },
{ 649, Pair.New("siege_tank", "Fremen") }, { 649, ("siege_tank", "Fremen") },
{ 650, Pair.New("carryall", "Fremen") }, { 650, ("carryall", "Fremen") },
{ 652, Pair.New("sonic_tank", "Fremen") }, { 652, ("sonic_tank", "Fremen") },
// Smugglers: // Smugglers:
{ 660, Pair.New("wall", "Smugglers") }, { 660, ("wall", "Smugglers") },
{ 661, Pair.New("wind_trap", "Smugglers") }, { 661, ("wind_trap", "Smugglers") },
{ 662, Pair.New("construction_yard", "Smugglers") }, { 662, ("construction_yard", "Smugglers") },
{ 663, Pair.New("barracks", "Smugglers") }, { 663, ("barracks", "Smugglers") },
{ 664, Pair.New("refinery", "Smugglers") }, { 664, ("refinery", "Smugglers") },
{ 666, Pair.New("outpost", "Smugglers") }, { 666, ("outpost", "Smugglers") },
{ 667, Pair.New("light_factory", "Smugglers") }, { 667, ("light_factory", "Smugglers") },
{ 668, Pair.New("silo", "Smugglers") }, { 668, ("silo", "Smugglers") },
{ 669, Pair.New("heavy_factory", "Smugglers") }, { 669, ("heavy_factory", "Smugglers") },
{ 670, Pair.New("repair_pad", "Smugglers") }, { 670, ("repair_pad", "Smugglers") },
{ 671, Pair.New("medium_gun_turret", "Smugglers") }, { 671, ("medium_gun_turret", "Smugglers") },
{ 672, Pair.New("high_tech_factory", "Smugglers") }, { 672, ("high_tech_factory", "Smugglers") },
{ 673, Pair.New("large_gun_turret", "Smugglers") }, { 673, ("large_gun_turret", "Smugglers") },
{ 674, Pair.New("research_centre", "Smugglers") }, { 674, ("research_centre", "Smugglers") },
{ 675, Pair.New("starport", "Smugglers") }, { 675, ("starport", "Smugglers") },
{ 676, Pair.New("palace", "Smugglers") }, { 676, ("palace", "Smugglers") },
{ 677, Pair.New("light_inf", "Smugglers") }, { 677, ("light_inf", "Smugglers") },
{ 678, Pair.New("trooper", "Smugglers") }, { 678, ("trooper", "Smugglers") },
{ 679, Pair.New("saboteur", "Smugglers") }, { 679, ("saboteur", "Smugglers") },
{ 680, Pair.New("engineer", "Smugglers") }, { 680, ("engineer", "Smugglers") },
{ 681, Pair.New("harvester", "Smugglers") }, { 681, ("harvester", "Smugglers") },
{ 682, Pair.New("mcv", "Smugglers") }, { 682, ("mcv", "Smugglers") },
{ 683, Pair.New("trike", "Smugglers") }, { 683, ("trike", "Smugglers") },
{ 684, Pair.New("quad", "Smugglers") }, { 684, ("quad", "Smugglers") },
{ 685, Pair.New("combat_tank_o", "Smugglers") }, { 685, ("combat_tank_o", "Smugglers") },
{ 686, Pair.New("missile_tank", "Smugglers") }, { 686, ("missile_tank", "Smugglers") },
{ 687, Pair.New("siege_tank", "Smugglers") }, { 687, ("siege_tank", "Smugglers") },
{ 688, Pair.New("carryall", "Smugglers") }, { 688, ("carryall", "Smugglers") },
// Mercenaries: // Mercenaries:
{ 700, Pair.New("wall", "Mercenaries") }, { 700, ("wall", "Mercenaries") },
{ 701, Pair.New("wind_trap", "Mercenaries") }, { 701, ("wind_trap", "Mercenaries") },
{ 702, Pair.New("construction_yard", "Mercenaries") }, { 702, ("construction_yard", "Mercenaries") },
{ 703, Pair.New("barracks", "Mercenaries") }, { 703, ("barracks", "Mercenaries") },
{ 704, Pair.New("refinery", "Mercenaries") }, { 704, ("refinery", "Mercenaries") },
{ 705, Pair.New("outpost", "Mercenaries") }, { 705, ("outpost", "Mercenaries") },
{ 707, Pair.New("light_factory", "Mercenaries") }, { 707, ("light_factory", "Mercenaries") },
{ 708, Pair.New("silo", "Mercenaries") }, { 708, ("silo", "Mercenaries") },
{ 709, Pair.New("heavy_factory", "Mercenaries") }, { 709, ("heavy_factory", "Mercenaries") },
{ 710, Pair.New("repair_pad", "Mercenaries") }, { 710, ("repair_pad", "Mercenaries") },
{ 711, Pair.New("medium_gun_turret", "Mercenaries") }, { 711, ("medium_gun_turret", "Mercenaries") },
{ 712, Pair.New("high_tech_factory", "Mercenaries") }, { 712, ("high_tech_factory", "Mercenaries") },
{ 713, Pair.New("large_gun_turret", "Mercenaries") }, { 713, ("large_gun_turret", "Mercenaries") },
{ 714, Pair.New("research_centre", "Mercenaries") }, { 714, ("research_centre", "Mercenaries") },
{ 715, Pair.New("starport", "Mercenaries") }, { 715, ("starport", "Mercenaries") },
{ 716, Pair.New("palace", "Mercenaries") }, { 716, ("palace", "Mercenaries") },
{ 717, Pair.New("light_inf", "Mercenaries") }, { 717, ("light_inf", "Mercenaries") },
{ 718, Pair.New("trooper", "Mercenaries") }, { 718, ("trooper", "Mercenaries") },
{ 719, Pair.New("saboteur", "Mercenaries") }, { 719, ("saboteur", "Mercenaries") },
{ 720, Pair.New("harvester", "Mercenaries") }, { 720, ("harvester", "Mercenaries") },
{ 721, Pair.New("harvester", "Mercenaries") }, { 721, ("harvester", "Mercenaries") },
{ 722, Pair.New("mcv", "Mercenaries") }, { 722, ("mcv", "Mercenaries") },
{ 723, Pair.New("trike", "Mercenaries") }, { 723, ("trike", "Mercenaries") },
{ 724, Pair.New("quad", "Mercenaries") }, { 724, ("quad", "Mercenaries") },
{ 725, Pair.New("combat_tank_o", "Mercenaries") }, { 725, ("combat_tank_o", "Mercenaries") },
{ 726, Pair.New("missile_tank", "Mercenaries") }, { 726, ("missile_tank", "Mercenaries") },
{ 727, Pair.New("siege_tank", "Mercenaries") }, { 727, ("siege_tank", "Mercenaries") },
{ 728, Pair.New("carryall", "Mercenaries") }, { 728, ("carryall", "Mercenaries") },
}; };
readonly Ruleset rules; readonly Ruleset rules;
@@ -350,18 +350,18 @@ namespace OpenRA.Mods.D2k.UtilityCommands
if (ActorDataByActorCode.ContainsKey(tileSpecialInfo)) if (ActorDataByActorCode.ContainsKey(tileSpecialInfo))
{ {
var kvp = ActorDataByActorCode[tileSpecialInfo]; var kvp = ActorDataByActorCode[tileSpecialInfo];
if (!rules.Actors.ContainsKey(kvp.First.ToLowerInvariant())) if (!rules.Actors.ContainsKey(kvp.Actor.ToLowerInvariant()))
throw new InvalidOperationException("Actor with name {0} could not be found in the rules YAML file!".F(kvp.First)); throw new InvalidOperationException("Actor with name {0} could not be found in the rules YAML file!".F(kvp.Actor));
var a = new ActorReference(kvp.First) var a = new ActorReference(kvp.Actor)
{ {
new LocationInit(locationOnMap), new LocationInit(locationOnMap),
new OwnerInit(kvp.Second) new OwnerInit(kvp.Owner)
}; };
map.ActorDefinitions.Add(new MiniYamlNode("Actor" + map.ActorDefinitions.Count, a.Save())); map.ActorDefinitions.Add(new MiniYamlNode("Actor" + map.ActorDefinitions.Count, a.Save()));
if (kvp.First == "mpspawn") if (kvp.Actor == "mpspawn")
playerCount++; playerCount++;
} }
} }

View File

@@ -16,8 +16,8 @@ namespace OpenRA.Platforms.Default
{ {
static class MultiTapDetection static class MultiTapDetection
{ {
static Cache<Pair<Keycode, Modifiers>, TapHistory> keyHistoryCache = static Cache<(Keycode Key, Modifiers Mods), TapHistory> keyHistoryCache =
new Cache<Pair<Keycode, Modifiers>, TapHistory>(_ => new TapHistory(DateTime.Now - TimeSpan.FromSeconds(1))); new Cache<(Keycode, Modifiers), TapHistory>(_ => new TapHistory(DateTime.Now - TimeSpan.FromSeconds(1)));
static Cache<byte, TapHistory> clickHistoryCache = static Cache<byte, TapHistory> clickHistoryCache =
new Cache<byte, TapHistory>(_ => new TapHistory(DateTime.Now - TimeSpan.FromSeconds(1))); new Cache<byte, TapHistory>(_ => new TapHistory(DateTime.Now - TimeSpan.FromSeconds(1)));
@@ -33,35 +33,35 @@ namespace OpenRA.Platforms.Default
public static int DetectFromKeyboard(Keycode key, Modifiers mods) public static int DetectFromKeyboard(Keycode key, Modifiers mods)
{ {
return keyHistoryCache[Pair.New(key, mods)].GetTapCount(int2.Zero); return keyHistoryCache[(key, mods)].GetTapCount(int2.Zero);
} }
public static int InfoFromKeyboard(Keycode key, Modifiers mods) public static int InfoFromKeyboard(Keycode key, Modifiers mods)
{ {
return keyHistoryCache[Pair.New(key, mods)].LastTapCount(); return keyHistoryCache[(key, mods)].LastTapCount();
} }
} }
class TapHistory class TapHistory
{ {
public Pair<DateTime, int2> FirstRelease, SecondRelease, ThirdRelease; public (DateTime Time, int2 Location) FirstRelease, SecondRelease, ThirdRelease;
public TapHistory(DateTime now) public TapHistory(DateTime now)
{ {
FirstRelease = SecondRelease = ThirdRelease = Pair.New(now, int2.Zero); FirstRelease = SecondRelease = ThirdRelease = (now, int2.Zero);
} }
static bool CloseEnough(Pair<DateTime, int2> a, Pair<DateTime, int2> b) static bool CloseEnough((DateTime Time, int2 Location) a, (DateTime Time, int2 Location) b)
{ {
return a.First - b.First < TimeSpan.FromMilliseconds(250) return a.Time - b.Time < TimeSpan.FromMilliseconds(250)
&& (a.Second - b.Second).Length < 4; && (a.Location - b.Location).Length < 4;
} }
public int GetTapCount(int2 xy) public int GetTapCount(int2 xy)
{ {
FirstRelease = SecondRelease; FirstRelease = SecondRelease;
SecondRelease = ThirdRelease; SecondRelease = ThirdRelease;
ThirdRelease = Pair.New(DateTime.Now, xy); ThirdRelease = (DateTime.Now, xy);
if (!CloseEnough(ThirdRelease, SecondRelease)) if (!CloseEnough(ThirdRelease, SecondRelease))
return 1; return 1;

View File

@@ -3,7 +3,7 @@
<TargetFramework>net472</TargetFramework> <TargetFramework>net472</TargetFramework>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks> <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<Optimize>true</Optimize> <Optimize>true</Optimize>
<LangVersion>5</LangVersion> <LangVersion>7.3</LangVersion>
<DebugSymbols>true</DebugSymbols> <DebugSymbols>true</DebugSymbols>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors> <TreatWarningsAsErrors>true</TreatWarningsAsErrors>
<OutputPath>..</OutputPath> <OutputPath>..</OutputPath>

View File

@@ -89,7 +89,7 @@ namespace OpenRA.Platforms.Default
getCreateFrameBuffer = getCreateFrameBuffer =
tuple => tuple =>
{ {
var t = (Tuple<Size, Color>)tuple; var t = (ValueTuple<Size, Color>)tuple;
return new ThreadedFrameBuffer(this, return new ThreadedFrameBuffer(this,
context.CreateFrameBuffer(t.Item1, (ITextureInternal)CreateTexture(), t.Item2)); context.CreateFrameBuffer(t.Item1, (ITextureInternal)CreateTexture(), t.Item2));
}; };
@@ -98,13 +98,13 @@ namespace OpenRA.Platforms.Default
doDrawPrimitives = doDrawPrimitives =
tuple => tuple =>
{ {
var t = (Tuple<PrimitiveType, int, int>)tuple; var t = (ValueTuple<PrimitiveType, int, int>)tuple;
context.DrawPrimitives(t.Item1, t.Item2, t.Item3); context.DrawPrimitives(t.Item1, t.Item2, t.Item3);
}; };
doEnableScissor = doEnableScissor =
tuple => tuple =>
{ {
var t = (Tuple<int, int, int, int>)tuple; var t = (ValueTuple<int, int, int, int>)tuple;
context.EnableScissor(t.Item1, t.Item2, t.Item3, t.Item4); context.EnableScissor(t.Item1, t.Item2, t.Item3, t.Item4);
}; };
doSetBlendMode = mode => { context.SetBlendMode((BlendMode)mode); }; doSetBlendMode = mode => { context.SetBlendMode((BlendMode)mode); };
@@ -390,12 +390,12 @@ namespace OpenRA.Platforms.Default
public IFrameBuffer CreateFrameBuffer(Size s) public IFrameBuffer CreateFrameBuffer(Size s)
{ {
return Send(getCreateFrameBuffer, Tuple.Create(s, Color.FromArgb(0))); return Send(getCreateFrameBuffer, (s, Color.FromArgb(0)));
} }
public IFrameBuffer CreateFrameBuffer(Size s, Color clearColor) public IFrameBuffer CreateFrameBuffer(Size s, Color clearColor)
{ {
return Send(getCreateFrameBuffer, Tuple.Create(s, clearColor)); return Send(getCreateFrameBuffer, (s, clearColor));
} }
public IShader CreateShader(string name) public IShader CreateShader(string name)
@@ -425,7 +425,7 @@ namespace OpenRA.Platforms.Default
public void DrawPrimitives(PrimitiveType type, int firstVertex, int numVertices) public void DrawPrimitives(PrimitiveType type, int firstVertex, int numVertices)
{ {
Post(doDrawPrimitives, Tuple.Create(type, firstVertex, numVertices)); Post(doDrawPrimitives, (type, firstVertex, numVertices));
} }
public void EnableDepthBuffer() public void EnableDepthBuffer()
@@ -435,7 +435,7 @@ namespace OpenRA.Platforms.Default
public void EnableScissor(int left, int top, int width, int height) public void EnableScissor(int left, int top, int width, int height)
{ {
Post(doEnableScissor, Tuple.Create(left, top, width, height)); Post(doEnableScissor, (left, top, width, height));
} }
public void Present() public void Present()
@@ -522,8 +522,8 @@ namespace OpenRA.Platforms.Default
{ {
this.device = device; this.device = device;
bind = vertexBuffer.Bind; bind = vertexBuffer.Bind;
setData1 = tuple => { var t = (Tuple<Vertex[], int>)tuple; vertexBuffer.SetData(t.Item1, t.Item2); device.ReturnVertices(t.Item1); }; setData1 = tuple => { var t = (ValueTuple<Vertex[], int>)tuple; vertexBuffer.SetData(t.Item1, t.Item2); device.ReturnVertices(t.Item1); };
setData2 = tuple => { var t = (Tuple<IntPtr, int, int>)tuple; vertexBuffer.SetData(t.Item1, t.Item2, t.Item3); return null; }; setData2 = tuple => { var t = (ValueTuple<IntPtr, int, int>)tuple; vertexBuffer.SetData(t.Item1, t.Item2, t.Item3); return null; };
dispose = vertexBuffer.Dispose; dispose = vertexBuffer.Dispose;
} }
@@ -536,20 +536,20 @@ namespace OpenRA.Platforms.Default
{ {
var buffer = device.GetVertices(length); var buffer = device.GetVertices(length);
Array.Copy(vertices, buffer, length); Array.Copy(vertices, buffer, length);
device.Post(setData1, Tuple.Create(buffer, length)); device.Post(setData1, (buffer, length));
} }
public void SetData(IntPtr data, int start, int length) public void SetData(IntPtr data, int start, int length)
{ {
// We can't return until we are finished with the data, so we must Send here. // We can't return until we are finished with the data, so we must Send here.
device.Send(setData2, Tuple.Create(data, start, length)); device.Send(setData2, (data, start, length));
} }
public void SetData(Vertex[] vertices, int start, int length) public void SetData(Vertex[] vertices, int start, int length)
{ {
var buffer = device.GetVertices(length); var buffer = device.GetVertices(length);
Array.Copy(vertices, start, buffer, 0, length); Array.Copy(vertices, start, buffer, 0, length);
device.Post(setData1, Tuple.Create(buffer, length)); device.Post(setData1, (buffer, length));
} }
public void Dispose() public void Dispose()
@@ -578,10 +578,10 @@ namespace OpenRA.Platforms.Default
getScaleFilter = () => texture.ScaleFilter; getScaleFilter = () => texture.ScaleFilter;
setScaleFilter = value => texture.ScaleFilter = (TextureScaleFilter)value; setScaleFilter = value => texture.ScaleFilter = (TextureScaleFilter)value;
getSize = () => texture.Size; getSize = () => texture.Size;
setEmpty = tuple => { var t = (Tuple<int, int>)tuple; texture.SetEmpty(t.Item1, t.Item2); }; setEmpty = tuple => { var t = (ValueTuple<int, int>)tuple; texture.SetEmpty(t.Item1, t.Item2); };
getData = () => texture.GetData(); getData = () => texture.GetData();
setData1 = colors => { texture.SetData((uint[,])colors); return null; }; setData1 = colors => { texture.SetData((uint[,])colors); return null; };
setData2 = tuple => { var t = (Tuple<byte[], int, int>)tuple; texture.SetData(t.Item1, t.Item2, t.Item3); }; setData2 = tuple => { var t = (ValueTuple<byte[], int, int>)tuple; texture.SetData(t.Item1, t.Item2, t.Item3); };
dispose = texture.Dispose; dispose = texture.Dispose;
} }
@@ -616,7 +616,7 @@ namespace OpenRA.Platforms.Default
public void SetEmpty(int width, int height) public void SetEmpty(int width, int height)
{ {
device.Post(setEmpty, Tuple.Create(width, height)); device.Post(setEmpty, (width, height));
} }
public byte[] GetData() public byte[] GetData()
@@ -636,7 +636,7 @@ namespace OpenRA.Platforms.Default
// but allows us post a message instead of blocking the message queue by sending it. // but allows us post a message instead of blocking the message queue by sending it.
var temp = new byte[colors.Length]; var temp = new byte[colors.Length];
Array.Copy(colors, temp, temp.Length); Array.Copy(colors, temp, temp.Length);
device.Post(setData2, Tuple.Create(temp, width, height)); device.Post(setData2, (temp, width, height));
} }
public void Dispose() public void Dispose()
@@ -661,13 +661,13 @@ namespace OpenRA.Platforms.Default
{ {
this.device = device; this.device = device;
prepareRender = shader.PrepareRender; prepareRender = shader.PrepareRender;
setBool = tuple => { var t = (Tuple<string, bool>)tuple; shader.SetBool(t.Item1, t.Item2); }; setBool = tuple => { var t = (ValueTuple<string, bool>)tuple; shader.SetBool(t.Item1, t.Item2); };
setMatrix = tuple => { var t = (Tuple<string, float[]>)tuple; shader.SetMatrix(t.Item1, t.Item2); }; setMatrix = tuple => { var t = (ValueTuple<string, float[]>)tuple; shader.SetMatrix(t.Item1, t.Item2); };
setTexture = tuple => { var t = (Tuple<string, ITexture>)tuple; shader.SetTexture(t.Item1, t.Item2); }; setTexture = tuple => { var t = (ValueTuple<string, ITexture>)tuple; shader.SetTexture(t.Item1, t.Item2); };
setVec1 = tuple => { var t = (Tuple<string, float>)tuple; shader.SetVec(t.Item1, t.Item2); }; setVec1 = tuple => { var t = (ValueTuple<string, float>)tuple; shader.SetVec(t.Item1, t.Item2); };
setVec2 = tuple => { var t = (Tuple<string, float[], int>)tuple; shader.SetVec(t.Item1, t.Item2, t.Item3); }; setVec2 = tuple => { var t = (ValueTuple<string, float[], int>)tuple; shader.SetVec(t.Item1, t.Item2, t.Item3); };
setVec3 = tuple => { var t = (Tuple<string, float, float>)tuple; shader.SetVec(t.Item1, t.Item2, t.Item3); }; setVec3 = tuple => { var t = (ValueTuple<string, float, float>)tuple; shader.SetVec(t.Item1, t.Item2, t.Item3); };
setVec4 = tuple => { var t = (Tuple<string, float, float, float>)tuple; shader.SetVec(t.Item1, t.Item2, t.Item3, t.Item4); }; setVec4 = tuple => { var t = (ValueTuple<string, float, float, float>)tuple; shader.SetVec(t.Item1, t.Item2, t.Item3, t.Item4); };
} }
public void PrepareRender() public void PrepareRender()
@@ -677,37 +677,37 @@ namespace OpenRA.Platforms.Default
public void SetBool(string name, bool value) public void SetBool(string name, bool value)
{ {
device.Post(setBool, Tuple.Create(name, value)); device.Post(setBool, (name, value));
} }
public void SetMatrix(string param, float[] mtx) public void SetMatrix(string param, float[] mtx)
{ {
device.Post(setMatrix, Tuple.Create(param, mtx)); device.Post(setMatrix, (param, mtx));
} }
public void SetTexture(string param, ITexture texture) public void SetTexture(string param, ITexture texture)
{ {
device.Post(setTexture, Tuple.Create(param, texture)); device.Post(setTexture, (param, texture));
} }
public void SetVec(string name, float x) public void SetVec(string name, float x)
{ {
device.Post(setVec1, Tuple.Create(name, x)); device.Post(setVec1, (name, x));
} }
public void SetVec(string name, float[] vec, int length) public void SetVec(string name, float[] vec, int length)
{ {
device.Post(setVec2, Tuple.Create(name, vec, length)); device.Post(setVec2, (name, vec, length));
} }
public void SetVec(string name, float x, float y) public void SetVec(string name, float x, float y)
{ {
device.Post(setVec3, Tuple.Create(name, x, y)); device.Post(setVec3, (name, x, y));
} }
public void SetVec(string name, float x, float y, float z) public void SetVec(string name, float x, float y, float z)
{ {
device.Post(setVec4, Tuple.Create(name, x, y, z)); device.Post(setVec4, (name, x, y, z));
} }
} }
} }

View File

@@ -7,7 +7,7 @@
<UseVSHostingProcess>false</UseVSHostingProcess> <UseVSHostingProcess>false</UseVSHostingProcess>
<OutputPath>..</OutputPath> <OutputPath>..</OutputPath>
<AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath> <AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
<LangVersion>5</LangVersion> <LangVersion>7.3</LangVersion>
<DebugSymbols>true</DebugSymbols> <DebugSymbols>true</DebugSymbols>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors> <TreatWarningsAsErrors>true</TreatWarningsAsErrors>
<PlatformTarget>AnyCPU</PlatformTarget> <PlatformTarget>AnyCPU</PlatformTarget>

View File

@@ -2,7 +2,7 @@
<PropertyGroup> <PropertyGroup>
<TargetFramework>net472</TargetFramework> <TargetFramework>net472</TargetFramework>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks> <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<LangVersion>5</LangVersion> <LangVersion>7.3</LangVersion>
<DebugSymbols>true</DebugSymbols> <DebugSymbols>true</DebugSymbols>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors> <TreatWarningsAsErrors>true</TreatWarningsAsErrors>
<OutputPath>..</OutputPath> <OutputPath>..</OutputPath>

View File

@@ -7,7 +7,7 @@
<UseVSHostingProcess>false</UseVSHostingProcess> <UseVSHostingProcess>false</UseVSHostingProcess>
<OutputPath>..</OutputPath> <OutputPath>..</OutputPath>
<AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath> <AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
<LangVersion>5</LangVersion> <LangVersion>7.3</LangVersion>
<DebugSymbols>true</DebugSymbols> <DebugSymbols>true</DebugSymbols>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors> <TreatWarningsAsErrors>true</TreatWarningsAsErrors>
<PlatformTarget>AnyCPU</PlatformTarget> <PlatformTarget>AnyCPU</PlatformTarget>