Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 7 additions & 2 deletions GameServer/ECS-Components/EffectListComponent.cs
Original file line number Diff line number Diff line change
Expand Up @@ -479,7 +479,9 @@ static void OnEffectAddedOrEnabled(EffectListComponent component, AddEffectResul
if (start)
effect.OnStartEffect();

ServiceObjectStore.Add(effect);
if (effect.Duration > 0)
ServiceObjectStore.Schedule(effect, effect.GetNextTick());

effect.Owner.effectListComponent.RequestPlayerUpdate(EffectHelper.GetPlayerUpdateFromEffect(effect.EffectType));

// Animations must be sent after calling `OnStartEffect` to prevent interrupts from interfering with them.
Expand Down Expand Up @@ -670,7 +672,10 @@ private AddEffectResult AddOrEnableEffectInternal(ECSGameEffect effect)
{
ServiceObjectStore.Remove(existingEffect);
existingEffect.IsBeingReplaced = true; // Will be checked by the parent pulse effect so that it doesn't call `Stop` on it.
ServiceObjectStore.Add(effect);

if (effect.Duration > 0)
ServiceObjectStore.Schedule(effect, effect.GetNextTick());

existingEffects[i] = effect;
result = existingEffect.IsActive ? AddEffectResult.RenewedActive : AddEffectResult.RenewedDisabled;
}
Expand Down
2 changes: 1 addition & 1 deletion GameServer/ECS-Effects/CrowdControlECSEffect.cs
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ protected void OnHardCCStop()

// Re-schedule the next think so that the NPC can resume its attack immediately for example.
if (Owner is GameNPC npc && npc.Brain is ABrain brain)
brain.NextThinkTick = GameLoop.GameLoopTime;
brain.Schedule(GameLoop.GameLoopTime);

if (SpellHandler.Caster.Realm == 0 || Owner.Realm == 0)
Owner.LastAttackedByEnemyTickPvE = GameLoop.GameLoopTime;
Expand Down
7 changes: 6 additions & 1 deletion GameServer/ECS-Effects/ECSGameAbilityEffect.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,10 @@ public class ECSGameAbilityEffect : ECSGameEffect, IPooledList<ECSGameAbilityEff
public override string Name { get { return "Default Ability Name"; } }

public ECSGameAbilityEffect(in ECSGameEffectInitParams initParams) : base(initParams) { }

public override long GetNextTick()
{
return NextTick > 0 ? NextTick : base.GetNextTick();
}
}
}
}
14 changes: 12 additions & 2 deletions GameServer/ECS-Effects/ECSGameEffect.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

namespace DOL.GS
{
public abstract class ECSGameEffect : IServiceObject, IPooledList<ECSGameEffect>
public abstract class ECSGameEffect : IShardedServiceObject, IPooledList<ECSGameEffect>
{
private State _state;
private TransitionalState _transitionalState;
Expand All @@ -34,7 +34,6 @@ public abstract class ECSGameEffect : IServiceObject, IPooledList<ECSGameEffect>
public bool TriggersImmunity { get; set; }
public int ImmunityDuration { get; protected set; } = 60000;
public bool IsBeingReplaced { get; set; } // Used externally to force an effect to be silent (no message, no immunity) when being refreshed.
public ServiceObjectId ServiceObjectId { get; } = new(ServiceObjectType.Effect);

// State properties.
public bool IsActive => _state is State.Active;
Expand All @@ -54,6 +53,12 @@ public abstract class ECSGameEffect : IServiceObject, IPooledList<ECSGameEffect>
public bool CanBeEnabled => IsDisabled && CanChangeState;
public bool CanBeEnded => (IsActive || IsDisabled) && CanChangeState;

// IServiceObject implementation.
private readonly ShardedServiceObjectId _serviceObjectId = new(ServiceObjectType.Effect);
public ServiceObjectId ServiceObjectId => _serviceObjectId;
SchedulableServiceObjectId ISchedulableServiceObject.ServiceObjectId => _serviceObjectId;
ShardedServiceObjectId IShardedServiceObject.ServiceObjectId => _serviceObjectId;

public ECSGameEffect(in ECSGameEffectInitParams initParams)
{
Owner = initParams.Target;
Expand All @@ -66,6 +71,11 @@ public ECSGameEffect(in ECSGameEffectInitParams initParams)
SpellHandler = initParams.SpellHandler;
}

public virtual long GetNextTick()
{
return ExpireTick;
}

public bool Start()
{
if (!CanStart || !Owner.IsAlive)
Expand Down
5 changes: 5 additions & 0 deletions GameServer/ECS-Effects/ECSGameSpellEffect.cs
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,11 @@ public ECSGameSpellEffect(in ECSGameEffectInitParams initParams) : base(initPara
NextTick = StartTick;
}

public override long GetNextTick()
{
return NextTick > 0 && (IsAllowedToPulse || IsConcentrationEffect()) ? NextTick : base.GetNextTick();
}

public override bool IsConcentrationEffect()
{
return SpellHandler.Spell.IsConcentration;
Expand Down
12 changes: 5 additions & 7 deletions GameServer/ECS-Services/AttackService.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
using System;
using System.Collections.Generic;
using System.Reflection;
using System.Threading;
using DOL.Logging;
Expand All @@ -12,7 +11,7 @@ public class AttackService : GameServiceBase
{
private static readonly Logger log = LoggerManager.Create(MethodBase.GetCurrentMethod().DeclaringType);

private List<AttackComponent> _list;
private ServiceObjectView<AttackComponent> _view;

public static AttackService Instance { get; }

Expand All @@ -24,24 +23,23 @@ static AttackService()
public override void Tick()
{
ProcessPostedActionsParallel();
int lastValidIndex;

try
{
_list = ServiceObjectStore.UpdateAndGetAll<AttackComponent>(ServiceObjectType.AttackComponent, out lastValidIndex);
_view = ServiceObjectStore.UpdateAndGetView<AttackComponent>(ServiceObjectType.AttackComponent);
}
catch (Exception e)
{
if (log.IsErrorEnabled)
log.Error($"{nameof(ServiceObjectStore.UpdateAndGetAll)} failed. Skipping this tick.", e);
log.Error($"{nameof(ServiceObjectStore.UpdateAndGetView)} failed. Skipping this tick.", e);

return;
}

GameLoop.ExecuteForEach(_list, lastValidIndex + 1, TickInternal);
_view.ExecuteForEach(TickInternal);

if (Diagnostics.CheckServiceObjectCount)
Diagnostics.PrintServiceObjectCount(ServiceName, ref EntityCount, _list.Count);
Diagnostics.PrintServiceObjectCount(ServiceName, ref EntityCount, _view.TotalValidCount);
}

private static void TickInternal(AttackComponent attackComponent)
Expand Down
12 changes: 5 additions & 7 deletions GameServer/ECS-Services/CastingService.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
using System;
using System.Collections.Generic;
using System.Reflection;
using System.Threading;
using DOL.Logging;
Expand All @@ -12,7 +11,7 @@ public sealed class CastingService : GameServiceBase
{
private static readonly Logger log = LoggerManager.Create(MethodBase.GetCurrentMethod().DeclaringType);

private List<CastingComponent> _list;
private ServiceObjectView<CastingComponent> _view;

public static CastingService Instance { get; }

Expand All @@ -24,24 +23,23 @@ static CastingService()
public override void Tick()
{
ProcessPostedActionsParallel();
int lastValidIndex;

try
{
_list = ServiceObjectStore.UpdateAndGetAll<CastingComponent>(ServiceObjectType.CastingComponent, out lastValidIndex);
_view = ServiceObjectStore.UpdateAndGetView<CastingComponent>(ServiceObjectType.CastingComponent);
}
catch (Exception e)
{
if (log.IsErrorEnabled)
log.Error($"{nameof(ServiceObjectStore.UpdateAndGetAll)} failed. Skipping this tick.", e);
log.Error($"{nameof(ServiceObjectStore.UpdateAndGetView)} failed. Skipping this tick.", e);

return;
}

GameLoop.ExecuteForEach(_list, lastValidIndex + 1, TickInternal);
_view.ExecuteForEach(TickInternal);

if (Diagnostics.CheckServiceObjectCount)
Diagnostics.PrintServiceObjectCount(ServiceName, ref EntityCount, _list.Count);
Diagnostics.PrintServiceObjectCount(ServiceName, ref EntityCount, _view.TotalValidCount);
}

private static void TickInternal(CastingComponent castingComponent)
Expand Down
36 changes: 14 additions & 22 deletions GameServer/ECS-Services/ClientService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,8 @@ public sealed class ClientService : GameServiceBase
private const int HARD_TIMEOUT = 150000;
private const int STATIC_OBJECT_UPDATE_MIN_DISTANCE = 4000;

private List<GameClient> _clients = new();
private ServiceObjectView<GameClient> _view;
private SimpleDisposableLock _lock = new(LockRecursionPolicy.SupportsRecursion);
private int _lastValidIndex = -1;
private int _clientCount;
private GameClient[] _clientsBySessionId = new GameClient[ushort.MaxValue];
private Trie<GamePlayer> _playerNameTrie = new();
Expand All @@ -44,27 +43,26 @@ public override void BeginTick()

try
{
_clients = ServiceObjectStore.UpdateAndGetAll<GameClient>(ServiceObjectType.Client, out _lastValidIndex);
_view = ServiceObjectStore.UpdateAndGetView<GameClient>(ServiceObjectType.Client);
}
catch (Exception e)
{
if (log.IsErrorEnabled)
log.Error($"{nameof(ServiceObjectStore.UpdateAndGetAll)} failed. Skipping this tick.", e);
log.Error($"{nameof(ServiceObjectStore.UpdateAndGetView)} failed. Skipping this tick.", e);

_lastValidIndex = -1;
return;
}
}

GameLoop.ExecuteForEach(_clients, _lastValidIndex + 1, BeginTickInternal);
_view.ExecuteForEach(BeginTickInternal);
}

public override void EndTick()
{
GameLoop.ExecuteForEach(_clients, _lastValidIndex + 1, EndTickInternal);
_view.ExecuteForEach(EndTickInternal);

if (Diagnostics.CheckServiceObjectCount)
Diagnostics.PrintServiceObjectCount(ServiceName, ref EntityCount, _clients.Count);
Diagnostics.PrintServiceObjectCount(ServiceName, ref EntityCount, _view.TotalValidCount);
}

private static void BeginTickInternal(GameClient client)
Expand Down Expand Up @@ -193,9 +191,6 @@ public void OnClientConnect(GameClient client)
ServiceObjectId serviceObjectId = client.ServiceObjectId;
log.Warn($"{nameof(OnClientConnect)} was called but the client couldn't be added to the entity manager." +
$"(Client: {client})" +
$"(IsIdSet: {serviceObjectId.IsSet})" +
$"(IsPendingAddition: {serviceObjectId.IsPendingAddition})" +
$"(IsPendingRemoval: {serviceObjectId.IsPendingAddition})" +
$"\n{Environment.StackTrace}");
}
}
Expand All @@ -216,9 +211,6 @@ public void OnClientDisconnect(GameClient client)
ServiceObjectId serviceObjectId = client.ServiceObjectId;
log.Warn($"{nameof(OnClientDisconnect)} was called but the client couldn't be removed from the entity manager." +
$"(Client: {client})" +
$"(IsIdSet: {serviceObjectId.IsSet})" +
$"(IsPendingAddition: {serviceObjectId.IsPendingAddition})" +
$"(IsPendingRemoval: {serviceObjectId.IsPendingAddition})" +
$"\n{Environment.StackTrace}");
}
}
Expand All @@ -244,9 +236,9 @@ public GamePlayer GetPlayer<T>(CheckPlayerAction<T> action, T actionArgument)
{
_lock.EnterReadLock();

for (int i = 0; i <= _lastValidIndex; i++)
for (int i = 0; i < _view.TotalValidCount; i++)
{
GameClient client = _clients[i];
GameClient client = _view.Items[i];

if (client == null || !client.IsPlaying)
continue;
Expand Down Expand Up @@ -287,9 +279,9 @@ public List<GamePlayer> GetPlayers<T>(CheckPlayerAction<T> action, T actionArgum
{
_lock.EnterReadLock();

for (int i = 0; i <= _lastValidIndex; i++)
for (int i = 0; i < _view.TotalValidCount; i++)
{
GameClient client = _clients[i];
GameClient client = _view.Items[i];

if (!client.IsPlaying)
continue;
Expand Down Expand Up @@ -323,9 +315,9 @@ public GameClient GetClient<T>(CheckClientAction<T> action, T actionArgument)
{
_lock.EnterReadLock();

for (int i = 0; i <= _lastValidIndex; i++)
for (int i = 0; i < _view.TotalValidCount; i++)
{
GameClient client = _clients[i];
GameClient client = _view.Items[i];

// Most code assumes clients have an account for privilege checks.
if (client.Account == null)
Expand Down Expand Up @@ -357,9 +349,9 @@ public List<GameClient> GetClients<T>(CheckClientAction<T> action, T actionArgum
{
_lock.EnterReadLock();

for (int i = 0; i <= _lastValidIndex; i++)
for (int i = 0; i < _view.TotalValidCount; i++)
{
GameClient client = _clients[i];
GameClient client = _view.Items[i];

// Most code assumes clients have an account for privilege checks.
if (client.Account == null)
Expand Down
12 changes: 5 additions & 7 deletions GameServer/ECS-Services/CraftingService.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
using System;
using System.Collections.Generic;
using System.Reflection;
using System.Threading;
using DOL.Logging;
Expand All @@ -11,7 +10,7 @@ public sealed class CraftingService : GameServiceBase
{
private static readonly Logger log = LoggerManager.Create(MethodBase.GetCurrentMethod().DeclaringType);

private List<CraftComponent> _list;
private ServiceObjectView<CraftComponent> _view;

public static CraftingService Instance { get; }

Expand All @@ -23,24 +22,23 @@ static CraftingService()
public override void Tick()
{
ProcessPostedActionsParallel();
int lastValidIndex;

try
{
_list = ServiceObjectStore.UpdateAndGetAll<CraftComponent>(ServiceObjectType.CraftComponent, out lastValidIndex);
_view = ServiceObjectStore.UpdateAndGetView<CraftComponent>(ServiceObjectType.CraftComponent);
}
catch (Exception e)
{
if (log.IsErrorEnabled)
log.Error($"{nameof(ServiceObjectStore.UpdateAndGetAll)} failed. Skipping this tick.", e);
log.Error($"{nameof(ServiceObjectStore.UpdateAndGetView)} failed. Skipping this tick.", e);

return;
}

GameLoop.ExecuteForEach(_list, lastValidIndex + 1, TickInternal);
_view.ExecuteForEach(TickInternal);

if (Diagnostics.CheckServiceObjectCount)
Diagnostics.PrintServiceObjectCount(ServiceName, ref EntityCount, _list.Count);
Diagnostics.PrintServiceObjectCount(ServiceName, ref EntityCount, _view.TotalValidCount);
}

private static void TickInternal(CraftComponent craftComponent)
Expand Down
11 changes: 5 additions & 6 deletions GameServer/ECS-Services/DailyQuestService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -53,26 +53,25 @@ public override void Tick()
GameServer.Database.AddObject(newTime);
}

List<GameClient> clients;
int lastValidIndex;
ServiceObjectView<GameClient> view;

try
{
clients = ServiceObjectStore.UpdateAndGetAll<GameClient>(ServiceObjectType.Client, out lastValidIndex);
view = ServiceObjectStore.UpdateAndGetView<GameClient>(ServiceObjectType.Client);
}
catch (Exception e)
{
if (log.IsErrorEnabled)
log.Error($"{nameof(ServiceObjectStore.UpdateAndGetAll)} failed. Skipping this tick.", e);
log.Error($"{nameof(ServiceObjectStore.UpdateAndGetView)} failed. Skipping this tick.", e);

return;
}

_lastDailyRollover = DateTime.Now;

for (int i = 0; i < lastValidIndex + 1; i++)
for (int i = 0; i < view.TotalValidCount; i++)
{
GameClient client = clients[i];
GameClient client = view.Items[i];
client.Player?.RemoveFinishedQuests(x => x is Quests.DailyQuest);
}

Expand Down
Loading
Loading