Creating PlayerMask
This commit is contained in:
@@ -33,6 +33,8 @@ namespace OpenRA
|
|||||||
|
|
||||||
public enum WinState { Undefined, Won, Lost }
|
public enum WinState { Undefined, Won, Lost }
|
||||||
|
|
||||||
|
public class PlayerBitMask { }
|
||||||
|
|
||||||
public class Player : IScriptBindable, IScriptNotifyBind, ILuaTableBinding, ILuaEqualityBinding, ILuaToStringBinding
|
public class Player : IScriptBindable, IScriptNotifyBind, ILuaTableBinding, ILuaEqualityBinding, ILuaToStringBinding
|
||||||
{
|
{
|
||||||
struct StanceColors
|
struct StanceColors
|
||||||
@@ -71,6 +73,12 @@ namespace OpenRA
|
|||||||
readonly bool inMissionMap;
|
readonly bool inMissionMap;
|
||||||
readonly IUnlocksRenderPlayer[] unlockRenderPlayer;
|
readonly IUnlocksRenderPlayer[] unlockRenderPlayer;
|
||||||
|
|
||||||
|
// Each player is identified with a unique bit in the set
|
||||||
|
// Cache masks for the player's index and ally/enemy player indices for performance.
|
||||||
|
public LongBitSet<PlayerBitMask> PlayerMask;
|
||||||
|
public LongBitSet<PlayerBitMask> AllyMask = default(LongBitSet<PlayerBitMask>);
|
||||||
|
public LongBitSet<PlayerBitMask> EnemyMask = default(LongBitSet<PlayerBitMask>);
|
||||||
|
|
||||||
public bool UnlockedRenderPlayer
|
public bool UnlockedRenderPlayer
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
@@ -153,6 +161,9 @@ namespace OpenRA
|
|||||||
DisplayFaction = ChooseDisplayFaction(world, pr.Faction);
|
DisplayFaction = ChooseDisplayFaction(world, pr.Faction);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!Spectating)
|
||||||
|
PlayerMask = new LongBitSet<PlayerBitMask>(InternalName);
|
||||||
|
|
||||||
var playerActorType = world.Type == WorldType.Editor ? "EditorPlayer" : "Player";
|
var playerActorType = world.Type == WorldType.Editor ? "EditorPlayer" : "Player";
|
||||||
PlayerActor = world.CreateActor(playerActorType, new TypeDictionary { new OwnerInit(this) });
|
PlayerActor = world.CreateActor(playerActorType, new TypeDictionary { new OwnerInit(this) });
|
||||||
Shroud = PlayerActor.Trait<Shroud>();
|
Shroud = PlayerActor.Trait<Shroud>();
|
||||||
|
|||||||
194
OpenRA.Game/Primitives/LongBitSet.cs
Normal file
194
OpenRA.Game/Primitives/LongBitSet.cs
Normal file
@@ -0,0 +1,194 @@
|
|||||||
|
#region Copyright & License Information
|
||||||
|
/*
|
||||||
|
* Copyright 2007-2019 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;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace OpenRA.Primitives
|
||||||
|
{
|
||||||
|
static class LongBitSetAllocator<T> where T : class
|
||||||
|
{
|
||||||
|
static readonly Cache<string, long> Bits = new Cache<string, long>(Allocate);
|
||||||
|
static long nextBits = 1;
|
||||||
|
|
||||||
|
static long Allocate(string value)
|
||||||
|
{
|
||||||
|
lock (Bits)
|
||||||
|
{
|
||||||
|
var bits = nextBits;
|
||||||
|
nextBits <<= 1;
|
||||||
|
|
||||||
|
if (nextBits == 0)
|
||||||
|
throw new OverflowException("Trying to allocate bit index outside of index 64.");
|
||||||
|
|
||||||
|
return bits;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static long GetBits(string[] values)
|
||||||
|
{
|
||||||
|
long bits = 0;
|
||||||
|
lock (Bits)
|
||||||
|
foreach (var value in values)
|
||||||
|
bits |= Bits[value];
|
||||||
|
|
||||||
|
return bits;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static long GetBitsNoAlloc(string[] values)
|
||||||
|
{
|
||||||
|
// Map strings to existing bits; do not allocate missing values new bits
|
||||||
|
long bits = 0;
|
||||||
|
|
||||||
|
lock (Bits)
|
||||||
|
{
|
||||||
|
foreach (var value in values)
|
||||||
|
{
|
||||||
|
long valueBit;
|
||||||
|
if (Bits.TryGetValue(value, out valueBit))
|
||||||
|
bits |= valueBit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return bits;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static IEnumerable<string> GetStrings(long bits)
|
||||||
|
{
|
||||||
|
var values = new List<string>();
|
||||||
|
lock (Bits)
|
||||||
|
foreach (var kvp in Bits)
|
||||||
|
if ((kvp.Value & bits) != 0)
|
||||||
|
values.Add(kvp.Key);
|
||||||
|
|
||||||
|
return values;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool BitsContainString(long bits, string value)
|
||||||
|
{
|
||||||
|
long valueBit;
|
||||||
|
lock (Bits)
|
||||||
|
if (!Bits.TryGetValue(value, out valueBit))
|
||||||
|
return false;
|
||||||
|
return (bits & valueBit) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void Reset()
|
||||||
|
{
|
||||||
|
lock (Bits)
|
||||||
|
{
|
||||||
|
Bits.Clear();
|
||||||
|
nextBits = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Opitmized BitSet to be used only when guaranteed to be no more than 64 values.
|
||||||
|
public struct LongBitSet<T> : IEnumerable<string>, IEquatable<LongBitSet<T>> where T : class
|
||||||
|
{
|
||||||
|
readonly long bits;
|
||||||
|
|
||||||
|
public LongBitSet(params string[] values)
|
||||||
|
: this(LongBitSetAllocator<T>.GetBits(values)) { }
|
||||||
|
|
||||||
|
LongBitSet(long bits) { this.bits = bits; }
|
||||||
|
|
||||||
|
public static LongBitSet<T> FromStringsNoAlloc(string[] values)
|
||||||
|
{
|
||||||
|
return new LongBitSet<T>(LongBitSetAllocator<T>.GetBitsNoAlloc(values)) { };
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void Reset()
|
||||||
|
{
|
||||||
|
LongBitSetAllocator<T>.Reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string ToString()
|
||||||
|
{
|
||||||
|
return BitSetAllocator<T>.GetStrings(bits).JoinWith(",");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool operator ==(LongBitSet<T> me, LongBitSet<T> other) { return me.bits == other.bits; }
|
||||||
|
public static bool operator !=(LongBitSet<T> me, LongBitSet<T> other) { return !(me == other); }
|
||||||
|
|
||||||
|
public bool Equals(LongBitSet<T> other) { return other == this; }
|
||||||
|
public override bool Equals(object obj) { return obj is LongBitSet<T> && Equals((LongBitSet<T>)obj); }
|
||||||
|
public override int GetHashCode() { return bits.GetHashCode(); }
|
||||||
|
|
||||||
|
public bool IsEmpty { get { return bits == 0; } }
|
||||||
|
|
||||||
|
public bool IsProperSubsetOf(LongBitSet<T> other)
|
||||||
|
{
|
||||||
|
return IsSubsetOf(other) && !SetEquals(other);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool IsProperSupersetOf(LongBitSet<T> other)
|
||||||
|
{
|
||||||
|
return IsSupersetOf(other) && !SetEquals(other);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool IsSubsetOf(LongBitSet<T> other)
|
||||||
|
{
|
||||||
|
return (bits | other.bits) == other.bits;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool IsSupersetOf(LongBitSet<T> other)
|
||||||
|
{
|
||||||
|
return (bits | other.bits) == bits;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Overlaps(LongBitSet<T> other)
|
||||||
|
{
|
||||||
|
return (bits & other.bits) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool SetEquals(LongBitSet<T> other)
|
||||||
|
{
|
||||||
|
return bits == other.bits;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Contains(string value)
|
||||||
|
{
|
||||||
|
return BitSetAllocator<T>.BitsContainString(bits, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public IEnumerator<string> GetEnumerator()
|
||||||
|
{
|
||||||
|
return BitSetAllocator<T>.GetStrings(bits).GetEnumerator();
|
||||||
|
}
|
||||||
|
|
||||||
|
IEnumerator IEnumerable.GetEnumerator()
|
||||||
|
{
|
||||||
|
return GetEnumerator();
|
||||||
|
}
|
||||||
|
|
||||||
|
public LongBitSet<T> Except(LongBitSet<T> other)
|
||||||
|
{
|
||||||
|
return new LongBitSet<T>(bits & ~other.bits);
|
||||||
|
}
|
||||||
|
|
||||||
|
public LongBitSet<T> Intersect(LongBitSet<T> other)
|
||||||
|
{
|
||||||
|
return new LongBitSet<T>(bits & other.bits);
|
||||||
|
}
|
||||||
|
|
||||||
|
public LongBitSet<T> SymmetricExcept(LongBitSet<T> other)
|
||||||
|
{
|
||||||
|
return new LongBitSet<T>(bits ^ other.bits);
|
||||||
|
}
|
||||||
|
|
||||||
|
public LongBitSet<T> Union(LongBitSet<T> other)
|
||||||
|
{
|
||||||
|
return new LongBitSet<T>(bits | other.bits);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -43,6 +43,7 @@ namespace OpenRA
|
|||||||
public readonly MersenneTwister SharedRandom;
|
public readonly MersenneTwister SharedRandom;
|
||||||
public readonly MersenneTwister LocalRandom;
|
public readonly MersenneTwister LocalRandom;
|
||||||
public readonly IModelCache ModelCache;
|
public readonly IModelCache ModelCache;
|
||||||
|
public LongBitSet<PlayerBitMask> AllPlayerMask = default(LongBitSet<PlayerBitMask>);
|
||||||
|
|
||||||
public Player[] Players = new Player[0];
|
public Player[] Players = new Player[0];
|
||||||
|
|
||||||
@@ -196,15 +197,27 @@ namespace OpenRA
|
|||||||
ScreenMap = WorldActor.Trait<ScreenMap>();
|
ScreenMap = WorldActor.Trait<ScreenMap>();
|
||||||
Selection = WorldActor.Trait<ISelection>();
|
Selection = WorldActor.Trait<ISelection>();
|
||||||
|
|
||||||
|
// Reset mask
|
||||||
|
LongBitSet<PlayerBitMask>.Reset();
|
||||||
|
|
||||||
// Add players
|
// Add players
|
||||||
foreach (var cmp in WorldActor.TraitsImplementing<ICreatePlayers>())
|
foreach (var cmp in WorldActor.TraitsImplementing<ICreatePlayers>())
|
||||||
cmp.CreatePlayers(this);
|
cmp.CreatePlayers(this);
|
||||||
|
|
||||||
// Set defaults for any unset stances
|
// Set defaults for any unset stances
|
||||||
foreach (var p in Players)
|
foreach (var p in Players)
|
||||||
|
{
|
||||||
|
if (!p.Spectating)
|
||||||
|
AllPlayerMask = AllPlayerMask.Union(p.PlayerMask);
|
||||||
|
|
||||||
foreach (var q in Players)
|
foreach (var q in Players)
|
||||||
|
{
|
||||||
|
SetUpPlayerMask(p, q);
|
||||||
|
|
||||||
if (!p.Stances.ContainsKey(q))
|
if (!p.Stances.ContainsKey(q))
|
||||||
p.Stances[q] = Stance.Neutral;
|
p.Stances[q] = Stance.Neutral;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Game.Sound.SoundVolumeModifier = 1.0f;
|
Game.Sound.SoundVolumeModifier = 1.0f;
|
||||||
|
|
||||||
@@ -220,6 +233,25 @@ namespace OpenRA
|
|||||||
RulesContainTemporaryBlocker = map.Rules.Actors.Any(a => a.Value.HasTraitInfo<ITemporaryBlockerInfo>());
|
RulesContainTemporaryBlocker = map.Rules.Actors.Any(a => a.Value.HasTraitInfo<ITemporaryBlockerInfo>());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SetUpPlayerMask(Player p, Player q)
|
||||||
|
{
|
||||||
|
if (q.Spectating)
|
||||||
|
return;
|
||||||
|
|
||||||
|
var bitSet = q.PlayerMask;
|
||||||
|
|
||||||
|
switch (p.Stances[q])
|
||||||
|
{
|
||||||
|
case Stance.Enemy:
|
||||||
|
case Stance.Neutral:
|
||||||
|
p.EnemyMask = p.EnemyMask.Union(bitSet);
|
||||||
|
break;
|
||||||
|
case Stance.Ally:
|
||||||
|
p.AllyMask = p.AllyMask.Union(bitSet);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void AddToMaps(Actor self, IOccupySpace ios)
|
public void AddToMaps(Actor self, IOccupySpace ios)
|
||||||
{
|
{
|
||||||
ActorMap.AddInfluence(self, ios);
|
ActorMap.AddInfluence(self, ios);
|
||||||
|
|||||||
Reference in New Issue
Block a user