Skip to content

Commit

Permalink
Merge branch 'bleed' into rv-engine
Browse files Browse the repository at this point in the history
  • Loading branch information
MustaphaTR committed May 5, 2024
2 parents 4530f2d + 8c17455 commit dc38ce6
Show file tree
Hide file tree
Showing 215 changed files with 4,997 additions and 559 deletions.
10 changes: 10 additions & 0 deletions OpenRA.Game/Exts.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,16 @@ namespace OpenRA
{
public static class Exts
{
/// <summary>Returns <see cref="Color"/> of the <paramref name="actor"/>, taking <see cref="Actor.EffectiveOwner"/> into account.</summary>
public static Color OwnerColor(this Actor actor)
{
var effectiveOwner = actor.EffectiveOwner;
if (effectiveOwner != null && effectiveOwner.Disguised && actor.World.RenderPlayer != null)
return effectiveOwner.Owner.Color;

return actor.Owner.Color;
}

public static string FormatInvariant(this string format, params object[] args)
{
return string.Format(CultureInfo.InvariantCulture, format, args);
Expand Down
39 changes: 22 additions & 17 deletions OpenRA.Game/Game.cs
Original file line number Diff line number Diff line change
Expand Up @@ -368,22 +368,7 @@ static void Initialize(Arguments args)
Settings.Game.Platform = p;
try
{
var rendererPath = Path.Combine(Platform.BinDir, "OpenRA.Platforms." + p + ".dll");

#if NET5_0_OR_GREATER
var loader = new AssemblyLoader(rendererPath);
var platformType = loader.LoadDefaultAssembly().GetTypes().SingleOrDefault(t => typeof(IPlatform).IsAssignableFrom(t));

#else
// NOTE: This is currently the only use of System.Reflection in this file, so would give an unused using error if we import it above
var assembly = System.Reflection.Assembly.LoadFile(rendererPath);
var platformType = assembly.GetTypes().SingleOrDefault(t => typeof(IPlatform).IsAssignableFrom(t));
#endif

if (platformType == null)
throw new InvalidOperationException("Platform dll must include exactly one IPlatform implementation.");

var platform = (IPlatform)platformType.GetConstructor(Type.EmptyTypes).Invoke(null);
var platform = CreatePlatform(p);
Renderer = new Renderer(platform, Settings.Graphics);
Sound = new Sound(platform, Settings.Sound);

Expand Down Expand Up @@ -440,6 +425,26 @@ static void Initialize(Arguments args)
InitializeMod(modID, args);
}

public static IPlatform CreatePlatform(string platformName)
{
var rendererPath = Path.Combine(Platform.BinDir, "OpenRA.Platforms." + platformName + ".dll");

#if NET5_0_OR_GREATER
var loader = new AssemblyLoader(rendererPath);
var platformType = loader.LoadDefaultAssembly().GetTypes().SingleOrDefault(t => typeof(IPlatform).IsAssignableFrom(t));

#else
// NOTE: This is currently the only use of System.Reflection in this file, so would give an unused using error if we import it above
var assembly = System.Reflection.Assembly.LoadFile(rendererPath);
var platformType = assembly.GetTypes().SingleOrDefault(t => typeof(IPlatform).IsAssignableFrom(t));
#endif

if (platformType == null)
throw new InvalidOperationException("Platform dll must include exactly one IPlatform implementation.");

return (IPlatform)platformType.GetConstructor(Type.EmptyTypes).Invoke(null);
}

public static void InitializeMod(string mod, Arguments args)
{
// Clear static state if we have switched mods
Expand Down Expand Up @@ -980,7 +985,7 @@ public static void LoadMap(string launchMap)
Order.Command($"state {Session.ClientState.Ready}")
};

var map = ModData.MapCache.SingleOrDefault(m => m.Uid == launchMap || Path.GetFileName(m.Package.Name) == launchMap);
var map = ModData.MapCache.SingleOrDefault(m => m.Uid == launchMap || Path.GetFileName(m.PackageName) == launchMap);
if (map == null)
throw new ArgumentException($"Could not find map '{launchMap}'.");

Expand Down
2 changes: 1 addition & 1 deletion OpenRA.Game/GameInformation.cs
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ public void AddPlayer(OpenRA.Player runtimePlayer, Session lobbyInfo)
FactionId = runtimePlayer.Faction.InternalName,
DisplayFactionName = runtimePlayer.DisplayFaction.Name,
DisplayFactionId = runtimePlayer.DisplayFaction.InternalName,
Color = runtimePlayer.Color,
Color = OpenRA.Player.GetColor(runtimePlayer),
Team = client.Team,
Handicap = client.Handicap,
SpawnPoint = runtimePlayer.SpawnPoint,
Expand Down
3 changes: 3 additions & 0 deletions OpenRA.Game/Graphics/HardwarePalette.cs
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,10 @@ public void AddPalette(string name, ImmutablePalette p, bool allowModifiers)
public void ReplacePalette(string name, IPalette p)
{
if (mutablePalettes.ContainsKey(name))
{
palettes[name] = new ImmutablePalette(p);
CopyPaletteToBuffer(indices[name], mutablePalettes[name] = new MutablePalette(p));
}
else if (palettes.ContainsKey(name))
CopyPaletteToBuffer(indices[name], palettes[name] = new ImmutablePalette(p));
else
Expand Down
4 changes: 2 additions & 2 deletions OpenRA.Game/Graphics/SpriteFont.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ public sealed class SpriteFont : IDisposable

float deviceScale;

public SpriteFont(string name, byte[] data, int size, int ascender, float scale, SheetBuilder builder)
public SpriteFont(IPlatform platform, string name, byte[] data, int size, int ascender, float scale, SheetBuilder builder)
{
if (builder.Type != SheetType.BGRA)
throw new ArgumentException("The sheet builder must create BGRA sheets.", nameof(builder));
Expand All @@ -36,7 +36,7 @@ public SpriteFont(string name, byte[] data, int size, int ascender, float scale,
this.size = size;
this.builder = builder;

font = Game.Renderer.CreateFont(data);
font = platform.CreateFont(data);
glyphs = new Cache<char, GlyphInfo>(CreateGlyph);
contrastGlyphs = new Cache<(char, int), Sprite>(CreateContrastGlyph);
dilationElements = new Cache<int, float[]>(CreateCircularWeightMap);
Expand Down
3 changes: 1 addition & 2 deletions OpenRA.Game/Graphics/WorldRenderer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -62,8 +62,7 @@ internal WorldRenderer(ModData modData, World world)
foreach (var pal in world.TraitDict.ActorsWithTrait<ILoadsPalettes>())
pal.Trait.LoadPalettes(this);

foreach (var p in world.Players)
UpdatePalettesForPlayer(p.InternalName, p.Color, false);
Player.SetupRelationshipColors(world.Players, world.LocalPlayer, this, true);

palette.Initialize();

Expand Down
25 changes: 14 additions & 11 deletions OpenRA.Game/Map/Map.cs
Original file line number Diff line number Diff line change
Expand Up @@ -650,21 +650,24 @@ public void Save(IReadWritePackage toPackage)
foreach (var file in Package.Contents)
toPackage.Update(file, Package.GetStream(file).ReadAllBytes());

if (!LockPreview)
void UpdatePackage(string filename, byte[] data)
{
var previewData = SavePreview();
if (Package != toPackage || !Enumerable.SequenceEqual(previewData, Package.GetStream("map.png").ReadAllBytes()))
toPackage.Update("map.png", previewData);
if (Package != toPackage)
toPackage.Update(filename, data);
else
{
var stream = Package.GetStream(filename);
if (stream == null || !Enumerable.SequenceEqual(data, stream.ReadAllBytes()))
toPackage.Update(filename, data);
}
}

// Update the package with the new map data
var textData = Encoding.UTF8.GetBytes(root.WriteToString());
if (Package != toPackage || !Enumerable.SequenceEqual(textData, Package.GetStream("map.yaml").ReadAllBytes()))
toPackage.Update("map.yaml", textData);
if (!LockPreview)
UpdatePackage("map.png", SavePreview());

var binaryData = SaveBinaryData();
if (Package != toPackage || !Enumerable.SequenceEqual(binaryData, Package.GetStream("map.bin").ReadAllBytes()))
toPackage.Update("map.bin", binaryData);
// Update the package with the new map data
UpdatePackage("map.yaml", Encoding.UTF8.GetBytes(root.WriteToString()));
UpdatePackage("map.bin", SaveBinaryData());

Package = toPackage;

Expand Down
3 changes: 3 additions & 0 deletions OpenRA.Game/Map/MapCache.cs
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,9 @@ void LoadMapInternal(string map, IReadOnlyPackage package, MapClassification cla
var uid = Map.ComputeUID(mapPackage);
previews[uid].UpdateFromMap(mapPackage, package, classification, modData.Manifest.MapCompatibility, mapGrid.Type, modDataRules);

// Freeing the package to save memory if there is a lot of Maps
previews[uid].DisposePackage();

if (oldMap != uid)
{
LastModifiedMap = uid;
Expand Down
2 changes: 1 addition & 1 deletion OpenRA.Game/Map/MapDirectoryTracker.cs
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ public void UpdateMaps(MapCache mapcache)
dirty = false;
foreach (var mapAction in mapActionQueue)
{
var map = mapcache.FirstOrDefault(x => x.Package?.Name == mapAction.Key && x.Status == MapStatus.Available);
var map = mapcache.FirstOrDefault(x => x.PackageName == mapAction.Key && x.Status == MapStatus.Available);
if (map != null)
{
if (mapAction.Value == MapAction.Delete)
Expand Down
29 changes: 23 additions & 6 deletions OpenRA.Game/Map/MapPreview.cs
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,19 @@ public InnerData Clone()
readonly ModData modData;

public readonly string Uid;
public IReadOnlyPackage Package { get; private set; }
public string PackageName { get; private set; }
IReadOnlyPackage package;
public IReadOnlyPackage Package
{
get
{
package ??= parentPackage.OpenPackage(PackageName, modData.ModFiles);
return package;
}

private set => package = value;
}

IReadOnlyPackage parentPackage;

volatile InnerData innerData;
Expand Down Expand Up @@ -286,7 +298,7 @@ public MapPreview(Map map, ModData modData)
cache = modData.MapCache;

Uid = map.Uid;
Package = map.Package;
PackageName = map.Package.Name;

var mapPlayers = new MapPlayers(map.PlayerDefinitions);
var spawns = new List<CPos>();
Expand Down Expand Up @@ -338,7 +350,7 @@ public void UpdateFromMap(IReadOnlyPackage p, IReadOnlyPackage parent, MapClassi
yaml = new MiniYaml(null, MiniYaml.FromStream(yamlStream, $"{p.Name}:map.yaml", stringPool: cache.StringPool)).ToDictionary();
}

Package = p;
PackageName = p.Name;
parentPackage = parent;

var newData = innerData.Clone();
Expand Down Expand Up @@ -587,10 +599,15 @@ public void Invalidate()

public void Dispose()
{
if (Package != null)
DisposePackage();
}

public void DisposePackage()
{
if (package != null)
{
Package.Dispose();
Package = null;
package.Dispose();
package = null;
}
}

Expand Down
64 changes: 30 additions & 34 deletions OpenRA.Game/Player.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
using System.Linq;
using Eluant;
using Eluant.ObjectBinding;
using OpenRA.Graphics;
using OpenRA.Network;
using OpenRA.Primitives;
using OpenRA.Scripting;
Expand All @@ -37,17 +38,7 @@ public class PlayerBitMask { }

public class Player : IScriptBindable, IScriptNotifyBind, ILuaTableBinding, ILuaEqualityBinding, ILuaToStringBinding
{
struct StanceColors
{
public Color Self;
public Color Allies;
public Color Enemies;
public Color Neutrals;
}

public readonly Actor PlayerActor;
public readonly Color Color;

public readonly string PlayerName;
public readonly string InternalName;
public readonly FactionInfo Faction;
Expand All @@ -62,6 +53,11 @@ struct StanceColors
public readonly Shroud Shroud;
public readonly FrozenActorLayer FrozenActorLayer;

readonly Color color;

/// <summary>Returns player color with relationship colors applied.</summary>
public Color Color { get; private set; }

/// <summary>The faction (including Random, etc.) that was selected in the lobby.</summary>
public readonly FactionInfo DisplayFaction;

Expand Down Expand Up @@ -101,8 +97,6 @@ public bool UnlockedRenderPlayer
}
}

readonly StanceColors stanceColors;

public static FactionInfo ResolveFaction(string factionName, IEnumerable<FactionInfo> factionInfos, MersenneTwister playerRandom, bool requireSelectable = true)
{
var selectableFactions = factionInfos
Expand Down Expand Up @@ -162,7 +156,8 @@ public Player(World world, Session.Client client, PlayerReference pr, MersenneTw
if (client != null)
{
ClientIndex = client.Index;
Color = client.Color;
color = client.Color;
Color = color;
PlayerName = ResolvePlayerName(client, world.LobbyInfo.Clients, world.Map.Rules.Actors[SystemActors.Player].TraitInfos<IBotInfo>());

BotType = client.Bot;
Expand All @@ -180,6 +175,7 @@ public Player(World world, Session.Client client, PlayerReference pr, MersenneTw
{
// Map player
ClientIndex = world.LobbyInfo.Clients.FirstOrDefault(c => c.IsAdmin)?.Index ?? 0; // Owned by the host (TODO: fix this)
color = pr.Color;
Color = pr.Color;
PlayerName = pr.Name;
NonCombatant = pr.NonCombatant;
Expand Down Expand Up @@ -221,11 +217,6 @@ public Player(World world, Session.Client client, PlayerReference pr, MersenneTw
logic.Activate(this);
}

stanceColors.Self = ChromeMetrics.Get<Color>("PlayerStanceColorSelf");
stanceColors.Allies = ChromeMetrics.Get<Color>("PlayerStanceColorAllies");
stanceColors.Enemies = ChromeMetrics.Get<Color>("PlayerStanceColorEnemies");
stanceColors.Neutrals = ChromeMetrics.Get<Color>("PlayerStanceColorNeutrals");

unlockRenderPlayer = PlayerActor.TraitsImplementing<IUnlocksRenderPlayer>().ToArray();
notifyDisconnected = PlayerActor.TraitsImplementing<INotifyPlayerDisconnected>().ToArray();
}
Expand Down Expand Up @@ -259,28 +250,33 @@ public bool IsAlliedWith(Player p)
return RelationshipWith(p) == PlayerRelationship.Ally;
}

public Color PlayerRelationshipColor(Actor a)
/// <summary>Returns <see cref="color"/>, ignoring player relationship colors.</summary>
public static Color GetColor(Player p) => p.color;

public static void SetupRelationshipColors(Player[] players, Player viewer, WorldRenderer worldRenderer, bool firstRun)
{
var renderPlayer = a.World.RenderPlayer;
var player = renderPlayer ?? a.World.LocalPlayer;
if (player != null && !player.Spectating)
foreach (var p in players)
{
var effectiveOwner = a.EffectiveOwner;
var apparentOwner = a.Owner;
if (effectiveOwner != null && effectiveOwner.Disguised && !a.Owner.IsAlliedWith(renderPlayer))
apparentOwner = effectiveOwner.Owner;
p.Color = PlayerRelationshipColor(p, viewer);
worldRenderer.UpdatePalettesForPlayer(p.InternalName, p.Color, !firstRun);
}
}

if (apparentOwner == player)
return stanceColors.Self;
public static Color PlayerRelationshipColor(Player player, Player viewer)
{
if (!Game.Settings.Game.UsePlayerStanceColors || viewer == null || viewer.Spectating)
return player.color;

if (apparentOwner.IsAlliedWith(player))
return stanceColors.Allies;
if (viewer == player)
return ChromeMetrics.Get<Color>("PlayerStanceColorSelf");

if (!apparentOwner.NonCombatant)
return stanceColors.Enemies;
}
if (player.IsAlliedWith(viewer))
return ChromeMetrics.Get<Color>("PlayerStanceColorAllies");

if (player.NonCombatant)
return ChromeMetrics.Get<Color>("PlayerStanceColorNeutrals");

return stanceColors.Neutrals;
return ChromeMetrics.Get<Color>("PlayerStanceColorEnemies");
}

internal void PlayerDisconnected(Player p)
Expand Down
10 changes: 3 additions & 7 deletions OpenRA.Game/Renderer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -134,8 +134,9 @@ public void InitializeFonts(ModData modData)
fontSheetBuilder?.Dispose();
fontSheetBuilder = new SheetBuilder(SheetType.BGRA, 512);
Fonts = modData.Manifest.Get<Fonts>().FontList.ToDictionary(x => x.Key,
x => new SpriteFont(x.Value.Font, modData.DefaultFileSystem.Open(x.Value.Font).ReadAllBytes(),
x.Value.Size, x.Value.Ascender, Window.EffectiveWindowScale, fontSheetBuilder));
x => new SpriteFont(
platform, x.Value.Font, modData.DefaultFileSystem.Open(x.Value.Font).ReadAllBytes(),
x.Value.Size, x.Value.Ascender, Window.EffectiveWindowScale, fontSheetBuilder));
}

Window.OnWindowScaleChanged += (oldNative, oldEffective, newNative, newEffective) =>
Expand Down Expand Up @@ -563,11 +564,6 @@ public bool SetClipboardText(string text)

public string GLVersion => Context.GLVersion;

public IFont CreateFont(byte[] data)
{
return platform.CreateFont(data);
}

public int DisplayCount => Window.DisplayCount;

public int CurrentDisplay => Window.CurrentDisplay;
Expand Down
Loading

0 comments on commit dc38ce6

Please sign in to comment.