Files
OpenRA/OpenRA.Game/PlayerDatabase.cs
2021-03-08 18:11:25 +01:00

119 lines
3.2 KiB
C#

#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.Linq;
using System.Threading.Tasks;
using OpenRA.FileFormats;
using OpenRA.Graphics;
using OpenRA.Primitives;
using OpenRA.Support;
namespace OpenRA
{
public class PlayerDatabase : IGlobalModData
{
public readonly string Profile = "https://forum.openra.net/openra/info/";
public readonly int IconSize = 24;
// 512x512 is large enough for 49 unique 72x72 badges
// or 100 unique 42x42 badges
// or 441 unique 24x24 badges
// or some combination of the above if the DPI changes ingame
[FieldLoader.Ignore]
SheetBuilder sheetBuilder;
[FieldLoader.Ignore]
Cache<(PlayerBadge, int), Sprite> iconCache;
Sprite LoadSprite(string url, int density)
{
var spriteSize = IconSize * density;
var sprite = sheetBuilder.Allocate(new Size(spriteSize, spriteSize), 1f / density);
Task.Run(async () =>
{
try
{
var client = HttpClientFactory.Create();
var httpResponseMessage = await client.GetAsync(url);
var result = await httpResponseMessage.Content.ReadAsStreamAsync();
var icon = new Png(result);
if (icon.Width == spriteSize && icon.Height == spriteSize)
{
Game.RunAfterTick(() =>
{
Util.FastCopyIntoSprite(sprite, icon);
sprite.Sheet.CommitBufferedData();
});
}
}
catch { }
});
return sprite;
}
Sheet CreateSheet()
{
var sheet = new Sheet(SheetType.BGRA, new Size(512, 512));
// We must manually force the buffer creation to avoid a crash
// that is indirectly triggered by rendering from a Sheet that
// has not yet been written to.
sheet.CreateBuffer();
sheet.GetTexture().ScaleFilter = TextureScaleFilter.Linear;
return sheet;
}
public PlayerBadge LoadBadge(MiniYaml yaml)
{
if (sheetBuilder == null)
{
sheetBuilder = new SheetBuilder(SheetType.BGRA, CreateSheet);
iconCache = new Cache<(PlayerBadge Badge, int Density), Sprite>(p =>
{
if (p.Density > 2 && !string.IsNullOrEmpty(p.Badge.Icon3x))
return LoadSprite(p.Badge.Icon3x, 3);
if (p.Density > 1 && !string.IsNullOrEmpty(p.Badge.Icon2x))
return LoadSprite(p.Badge.Icon2x, 2);
return LoadSprite(p.Badge.Icon, 1);
});
}
var labelNode = yaml.Nodes.FirstOrDefault(n => n.Key == "Label");
var icon24Node = yaml.Nodes.FirstOrDefault(n => n.Key == "Icon24");
var icon48Node = yaml.Nodes.FirstOrDefault(n => n.Key == "Icon48");
var icon72Node = yaml.Nodes.FirstOrDefault(n => n.Key == "Icon72");
if (labelNode == null)
return null;
return new PlayerBadge(
labelNode.Value.Value,
icon24Node?.Value.Value,
icon48Node?.Value.Value,
icon72Node?.Value.Value);
}
public Sprite GetIcon(PlayerBadge badge)
{
var ws = Game.Renderer.WindowScale;
var density = ws > 2 ? 3 : ws > 1 ? 2 : 1;
return iconCache[(badge, density)];
}
}
}