blizzless-diiis/src/DiIiS-NA/BGS-Server/Objects/RPCObject.cs
Lucca Faria Ferri 2ebdff6c61 MonsterBrain.cs cleanup.
Removed Blizzless using comments as it clutters the dependency view.
2023-01-27 12:02:19 -08:00

147 lines
5.1 KiB
C#

//Blizzless Project 2022
using DiIiS_NA.Core.Logging;
using DiIiS_NA.LoginServer.Base;
using DiIiS_NA.LoginServer.Battle;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace DiIiS_NA.LoginServer.Objects
{
public class RPCObject
{
protected static readonly Logger Logger = LogManager.CreateLogger("RPCTransfer");
public ulong DynamicId { get; set; }
public bgs.protocol.EntityId BnetEntityId;
public ConcurrentDictionary<BattleClient, byte> Subscribers { get; private set; }
protected RPCObject()
{
RPCObjectManager.Init(this);
this.Subscribers = new ConcurrentDictionary<BattleClient, byte>();
}
/// <summary>
/// Adds a client subscriber to object, which will eventually be notified whenever the object changes state.
/// </summary>
/// <param name="client">The client to add as a subscriber.</param>
/// <param name="remoteObjectId">The client's dynamic ID.</param>
public void AddSubscriber(BattleClient client, ulong remoteObjectId)
{
if (this.Subscribers.ContainsKey(client)) return;
this.Subscribers.TryAdd(client, 0);
client.MapLocalObjectID(this.DynamicId, remoteObjectId);
if (client.SocketConnection.Active)
{
var operations = GetSubscriptionNotifications();
if (operations.Count > 0)
MakeRPC(client, operations);
}
}
public void RemoveSubscriber(BattleClient client)
{
if (!this.Subscribers.ContainsKey(client)) return;
client.UnmapLocalObjectId(this.DynamicId);
this.Subscribers.TryRemove(client, out _);
}
public virtual List<bgs.protocol.presence.v1.FieldOperation> GetSubscriptionNotifications()
{
return new List<bgs.protocol.presence.v1.FieldOperation>();
}
public Helpers.FieldKeyHelper ChangedFields = new Helpers.FieldKeyHelper();
protected void NotifySubscriptionAdded(BattleClient client)
{
var operations = GetSubscriptionNotifications();
if (operations.Count > 0)
MakeRPC(client, operations);
}
public virtual void NotifyUpdate() { }
public void CheckSubscribers()
{
foreach (var subscriber in this.Subscribers)
{
if (!subscriber.Key.SocketConnection.Active)
{
Logger.Trace("Removing disconnected subscriber {0}", subscriber.Key);
this.Subscribers.TryRemove(subscriber.Key, out _);
}
}
}
public void UpdateSubscribers(ConcurrentDictionary<BattleClient, byte> subscribers, List<bgs.protocol.presence.v1.FieldOperation> operations)
{
this.CheckSubscribers();
foreach (var subscriber in subscribers.Where(c => c.Key.Account.GameAccount != null))
{
var gameAccount = subscriber.Key.Account.GameAccount;
var state = bgs.protocol.presence.v1.ChannelState.CreateBuilder().SetEntityId(this.BnetEntityId);
state = state.AddRangeFieldOperation(operations);
var channelState = bgs.protocol.channel.v1.ChannelState.CreateBuilder().SetExtension(bgs.protocol.presence.v1.ChannelState.Presence, state.Build());
var notification = bgs.protocol.channel.v1.UpdateChannelStateNotification.CreateBuilder().SetStateChange(channelState);
var altnotification = bgs.protocol.channel.v1.JoinNotification.CreateBuilder().SetChannelState(channelState);
if (gameAccount.LoggedInClient != null)
{
gameAccount.LoggedInClient.MakeTargetedRPC(this, (lid) => bgs.protocol.channel.v1.ChannelListener.CreateStub(gameAccount.LoggedInClient).OnUpdateChannelState(new HandlerController() { ListenerId = lid }, notification.Build(), callback => { }));
gameAccount.LoggedInClient.MakeTargetedRPC(this, (lid) =>
bgs.protocol.channel.v1.ChannelListener.CreateStub(gameAccount.LoggedInClient).OnJoin(new HandlerController() { ListenerId = lid }, altnotification.Build(), callback => { }));
}
}
}
protected void MakeRPC(BattleClient client, List<bgs.protocol.presence.v1.FieldOperation> operations)
{
if (!client.SocketConnection.Active) return;
var state = bgs.protocol.presence.v1.ChannelState.CreateBuilder().SetEntityId(this.BnetEntityId).AddRangeFieldOperation(operations).Build();
var channelState = bgs.protocol.channel.v1.ChannelState.CreateBuilder().SetExtension(bgs.protocol.presence.v1.ChannelState.Presence, state);
var builder = bgs.protocol.channel.v1.JoinNotification.CreateBuilder().SetChannelState(channelState);
var notification = bgs.protocol.channel.v1.UpdateChannelStateNotification.CreateBuilder().SetStateChange(channelState);
client.MakeTargetedRPC(this, (lid) =>
bgs.protocol.channel.v1.ChannelListener.CreateStub(client).OnJoin(new HandlerController() { ListenerId = lid }, builder.Build(), callback => { }));
client.MakeTargetedRPC(this, (lid) =>
bgs.protocol.channel.v1.ChannelListener.CreateStub(client).OnUpdateChannelState(new HandlerController() { ListenerId = lid }, notification.Build(), callback => { }));
}
#region de-ctor
private bool _disposed = false;
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
private void Dispose(bool disposing)
{
if (this._disposed) return;
if (disposing) { }
RPCObjectManager.Release(this);
_disposed = true;
}
~RPCObject()
{
Dispose(false);
}
#endregion
}
}