diff --git a/LiteEntitySystem/ClientEntityManager.cs b/LiteEntitySystem/ClientEntityManager.cs
index ef1fa8d..69ee918 100644
--- a/LiteEntitySystem/ClientEntityManager.cs
+++ b/LiteEntitySystem/ClientEntityManager.cs
@@ -611,7 +611,7 @@ protected override unsafe void OnLogicTick()
}
}
}
- else if(classData.UpdateOnClient)
+ else if(classData.Flags.HasFlagFast(EntityFlags.UpdateOnClient))
{
entity.Update();
}
@@ -755,13 +755,15 @@ public override unsafe void Update()
internal void AddOwned(EntityLogic entity)
{
- if (entity.GetClassData().IsUpdateable && !entity.GetClassData().UpdateOnClient)
+ var flags = entity.GetClassData().Flags;
+ if (flags.HasFlagFast(EntityFlags.Updateable) && !flags.HasFlagFast(EntityFlags.UpdateOnClient))
AliveEntities.Add(entity);
}
internal void RemoveOwned(EntityLogic entity)
{
- if (entity.GetClassData().IsUpdateable && !entity.GetClassData().UpdateOnClient)
+ var flags = entity.GetClassData().Flags;
+ if (flags.HasFlagFast(EntityFlags.Updateable) && !flags.HasFlagFast(EntityFlags.UpdateOnClient))
AliveEntities.Remove(entity);
}
diff --git a/LiteEntitySystem/ControllerLogic.cs b/LiteEntitySystem/ControllerLogic.cs
index d909783..a8425e7 100644
--- a/LiteEntitySystem/ControllerLogic.cs
+++ b/LiteEntitySystem/ControllerLogic.cs
@@ -5,6 +5,7 @@ namespace LiteEntitySystem
///
/// Base class for Controller entities
///
+ [SetEntityFlags(EntityFlags.OnlyForOwner)]
public abstract class ControllerLogic : InternalEntity
{
[SyncVarFlags(SyncFlags.NeverRollBack)]
@@ -58,7 +59,7 @@ protected ControllerLogic(EntityParams entityParams) : base(entityParams) { }
///
/// Base class for AI Controller entities
///
- [LocalOnly, UpdateableEntity]
+ [SetEntityFlags(EntityFlags.LocalOnly | EntityFlags.Updateable)]
public abstract class AiControllerLogic : ControllerLogic
{
public override bool IsBot => true;
@@ -69,7 +70,7 @@ protected AiControllerLogic(EntityParams entityParams) : base(entityParams) { }
///
/// Base class for AI Controller entities with typed ControlledEntity field
///
- [LocalOnly, UpdateableEntity]
+ [SetEntityFlags(EntityFlags.LocalOnly | EntityFlags.Updateable)]
public abstract class AiControllerLogic : AiControllerLogic where T : PawnLogic
{
public T ControlledEntity => GetControlledEntity();
diff --git a/LiteEntitySystem/EntityLogic.cs b/LiteEntitySystem/EntityLogic.cs
index 504614a..12209a0 100644
--- a/LiteEntitySystem/EntityLogic.cs
+++ b/LiteEntitySystem/EntityLogic.cs
@@ -4,28 +4,27 @@
namespace LiteEntitySystem
{
- ///
- /// Entity has update method
- ///
+ [Flags]
+ public enum EntityFlags
+ {
+ UpdateOnClient = Updateable | (1 << 0), //Update entity on client even when entity isn't owned
+ Updateable = 1 << 1, //Entity has update method
+ LocalOnly = 1 << 2, //Entity is local only (only on server or client no difference)
+ OnlyForOwner = 1 << 3, //Sync entity only for owner player
+ OnlyForOthers = 1 << 4 //Sync entity only for other players
+ }
+
[AttributeUsage(AttributeTargets.Class)]
- public class UpdateableEntity : Attribute
+ public class SetEntityFlags : Attribute
{
- public readonly bool UpdateOnClient;
-
- public UpdateableEntity() { }
+ public readonly EntityFlags Flags;
- public UpdateableEntity(bool updateOnClient)
+ public SetEntityFlags(EntityFlags flags)
{
- UpdateOnClient = updateOnClient;
+ Flags = flags;
}
}
- ///
- /// Entity is local only (only on server or client no difference)
- ///
- [AttributeUsage(AttributeTargets.Class)]
- public class LocalOnly : Attribute { }
-
///
/// Base class for simple (not controlled by controller) entity
///
diff --git a/LiteEntitySystem/EntityManager.cs b/LiteEntitySystem/EntityManager.cs
index 7c529d1..7a6bb16 100644
--- a/LiteEntitySystem/EntityManager.cs
+++ b/LiteEntitySystem/EntityManager.cs
@@ -499,7 +499,7 @@ private static bool IsEntityLagCompensated(InternalEntity e)
=> !e.IsLocal && e is EntityLogic { HasLagCompensation: true };
private bool IsEntityAlive(EntityClassData classData, InternalEntity entity)
- => classData.IsUpdateable && (IsServer || entity.IsLocal || (IsClient && classData.UpdateOnClient));
+ => classData.Flags.HasFlagFast(EntityFlags.Updateable) && (IsServer || entity.IsLocal || (IsClient && classData.Flags.HasFlagFast(EntityFlags.UpdateOnClient)));
internal virtual void RemoveEntity(InternalEntity e)
{
@@ -522,7 +522,7 @@ internal virtual void RemoveEntity(InternalEntity e)
AliveEntities.Remove(e);
if(IsEntityLagCompensated(e))
LagCompensatedEntities.Remove((EntityLogic)e);
- if (classData.IsLocalOnly)
+ if (classData.Flags.HasFlagFast(EntityFlags.LocalOnly))
_localIdQueue.ReuseId(e.Id);
EntitiesDict[e.Id] = null;
EntitiesCount--;
diff --git a/LiteEntitySystem/EntityTypesMap.cs b/LiteEntitySystem/EntityTypesMap.cs
index dd4ad92..a696163 100644
--- a/LiteEntitySystem/EntityTypesMap.cs
+++ b/LiteEntitySystem/EntityTypesMap.cs
@@ -37,7 +37,11 @@ public ulong EvaluateEntityClassDataHash()
//don't hash localonly types
foreach (var (entType, _) in RegisteredTypes
.OrderBy(kv => kv.Value.ClassId)
- .Where(kv => kv.Key.GetCustomAttribute(true) == null))
+ .Where(kv =>
+ {
+ var attr = kv.Key.GetCustomAttribute(true);
+ return attr == null || !attr.Flags.HasFlagFast(EntityFlags.LocalOnly);
+ }))
{
var allTypesStack = Utils.GetBaseTypes(entType, typeof(InternalEntity), true);
while(allTypesStack.Count > 0)
diff --git a/LiteEntitySystem/HumanControllerLogic.cs b/LiteEntitySystem/HumanControllerLogic.cs
index d72bd14..e3443bb 100644
--- a/LiteEntitySystem/HumanControllerLogic.cs
+++ b/LiteEntitySystem/HumanControllerLogic.cs
@@ -8,7 +8,7 @@ namespace LiteEntitySystem
///
/// Base class for human Controller entities
///
- [UpdateableEntity(true)]
+ [SetEntityFlags(EntityFlags.UpdateOnClient)]
public abstract class HumanControllerLogic : ControllerLogic where TInput : unmanaged
{
private struct ServerResponse
diff --git a/LiteEntitySystem/Internal/EntityClassData.cs b/LiteEntitySystem/Internal/EntityClassData.cs
index 860a9b1..da1cfa0 100644
--- a/LiteEntitySystem/Internal/EntityClassData.cs
+++ b/LiteEntitySystem/Internal/EntityClassData.cs
@@ -56,9 +56,7 @@ internal struct EntityClassData
public readonly EntityFieldInfo[] LagCompensatedFields;
public readonly int LagCompensatedSize;
public readonly int LagCompensatedCount;
- public readonly bool UpdateOnClient;
- public readonly bool IsUpdateable;
- public readonly bool IsLocalOnly;
+ public readonly EntityFlags Flags;
public readonly EntityConstructor EntityConstructor;
public RpcFieldInfo[] RemoteCallsClient;
@@ -81,20 +79,8 @@ public EntityClassData(ushort filterId, Type entType, RegisteredTypeInfo typeInf
RemoteCallsClient = null;
ClassId = typeInfo.ClassId;
-
- var updateAttribute = entType.GetCustomAttribute();
- if (updateAttribute != null)
- {
- IsUpdateable = true;
- UpdateOnClient = updateAttribute.UpdateOnClient;
- }
- else
- {
- IsUpdateable = false;
- UpdateOnClient = false;
- }
-
- IsLocalOnly = entType.GetCustomAttribute() != null;
+ Flags = 0;
+
EntityConstructor = typeInfo.Constructor;
IsSingleton = entType.IsSubclassOf(SingletonEntityType);
FilterId = filterId;
@@ -110,6 +96,10 @@ public EntityClassData(ushort filterId, Type entType, RegisteredTypeInfo typeInf
while(allTypesStack.Count > 0)
{
var baseType = allTypesStack.Pop();
+
+ var setFlagsAttribute = baseType.GetCustomAttribute();
+ Flags |= setFlagsAttribute != null ? setFlagsAttribute.Flags : 0;
+
//cache fields
foreach (var field in Utils.GetProcessedFields(baseType))
{
diff --git a/LiteEntitySystem/Internal/StateSerializer.cs b/LiteEntitySystem/Internal/StateSerializer.cs
index 807f8c9..383d696 100644
--- a/LiteEntitySystem/Internal/StateSerializer.cs
+++ b/LiteEntitySystem/Internal/StateSerializer.cs
@@ -34,6 +34,7 @@ private enum RPCMode
private EntityFieldInfo[] _fields;
private int _fieldsCount;
private int _fieldsFlagsSize;
+ private EntityFlags _flags;
private InternalEntity _entity;
private byte[] _latestEntityData;
@@ -44,7 +45,6 @@ private enum RPCMode
private RemoteCallPacket _rpcTail;
private RemoteCallPacket _syncRpcHead;
private RemoteCallPacket _syncRpcTail;
- private bool _isController;
private uint _fullDataSize;
private int _syncFrame;
private RPCMode _rpcMode;
@@ -104,6 +104,7 @@ public void AllocateMemory(ref EntityClassData classData)
_fieldsCount = classData.FieldsCount;
_fieldsFlagsSize = classData.FieldsFlagsSize;
_fullDataSize = (uint)(HeaderSize + classData.FixedFieldsSize);
+ _flags = classData.Flags;
//resize or clean prev data
if (_latestEntityData == null || _latestEntityData.Length < _fullDataSize)
@@ -121,7 +122,6 @@ public unsafe void Init(InternalEntity e, ushort tick)
_state = SerializerState.Active;
_syncFrame = -1;
_rpcMode = RPCMode.Normal;
- _isController = e is ControllerLogic;
_versionChangedTick = tick;
LastChangedTick = tick;
@@ -242,10 +242,13 @@ private unsafe void WriteInitialState(bool isOwned, ushort serverTick, byte* res
public unsafe void MakeBaseline(byte playerId, ushort serverTick, byte* resultData, ref int position)
{
//skip inactive and other controlled controllers
- if (_state != SerializerState.Active || (_isController && playerId != _entity.InternalOwnerId.Value))
+ bool isOwned = _entity.InternalOwnerId.Value == playerId;
+ if (_state != SerializerState.Active ||
+ (_flags.HasFlagFast(EntityFlags.OnlyForOwner) && !isOwned) ||
+ (_flags.HasFlagFast(EntityFlags.OnlyForOthers) && isOwned))
return;
//don't write total size in full sync and fields
- WriteInitialState(_entity.InternalOwnerId.Value == playerId, serverTick, resultData, ref position);
+ WriteInitialState(isOwned, serverTick, resultData, ref position);
//Logger.Log($"[SEM] SendBaseline for entity: {_entity.Id}, pos: {position}, posAfterData: {position + _fullDataSize}");
}
@@ -267,11 +270,14 @@ public unsafe DiffResult MakeDiff(byte playerId, ushort serverTick, ushort minim
}
//make diff
- int startPos = position;
bool isOwned = _entity.InternalOwnerId.Value == playerId;
- if (_isController && !isOwned)
+ if ((_flags.HasFlagFast(EntityFlags.OnlyForOwner) && !isOwned) ||
+ (_flags.HasFlagFast(EntityFlags.OnlyForOthers) && isOwned))
+ {
return DiffResult.Skip;
-
+ }
+
+ int startPos = position;
//at 0 ushort
ushort* fieldFlagAndSize = (ushort*)(resultData + startPos);
position += sizeof(ushort);
diff --git a/LiteEntitySystem/PawnLogic.cs b/LiteEntitySystem/PawnLogic.cs
index ed06f41..8d2c022 100644
--- a/LiteEntitySystem/PawnLogic.cs
+++ b/LiteEntitySystem/PawnLogic.cs
@@ -3,7 +3,7 @@
///
/// Base class for entites that can be controlled by Controller
///
- [UpdateableEntity]
+ [SetEntityFlags(EntityFlags.Updateable)]
public abstract class PawnLogic : EntityLogic
{
[SyncVarFlags(SyncFlags.OnlyForOwner)]
diff --git a/LiteEntitySystem/ServerEntityManager.cs b/LiteEntitySystem/ServerEntityManager.cs
index 3e4d76f..722d846 100644
--- a/LiteEntitySystem/ServerEntityManager.cs
+++ b/LiteEntitySystem/ServerEntityManager.cs
@@ -554,7 +554,7 @@ private T Add(Action initMethod) where T : InternalEntity
ref var classData = ref ClassDataDict[EntityClassInfo.ClassId];
T entity;
- if (classData.IsLocalOnly)
+ if (classData.Flags.HasFlagFast(EntityFlags.LocalOnly))
{
entity = AddLocalEntity(initMethod);
}