Compare commits
No commits in common. "97ace3375a25fadec093d5ab765d1e93a9cf2820" and "725bbf473fc9cb6a2c6c638cc0ea645986cad076" have entirely different histories.
97ace3375a
...
725bbf473f
7 changed files with 0 additions and 205 deletions
|
|
@ -1,145 +0,0 @@
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using Decal.Adapter;
|
|
||||||
using Decal.Adapter.Wrappers;
|
|
||||||
using Mag.Shared;
|
|
||||||
|
|
||||||
namespace MosswartMassacre
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Sends inventory delta events (add/remove/update) via WebSocket
|
|
||||||
/// whenever items change in the player's inventory.
|
|
||||||
/// </summary>
|
|
||||||
internal class LiveInventoryTracker
|
|
||||||
{
|
|
||||||
private readonly IPluginLogger _logger;
|
|
||||||
private readonly HashSet<int> _trackedItemIds = new HashSet<int>();
|
|
||||||
|
|
||||||
internal LiveInventoryTracker(IPluginLogger logger)
|
|
||||||
{
|
|
||||||
_logger = logger;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Initialize tracking for all current inventory items.
|
|
||||||
/// Called after login or hot reload, after the full inventory dump.
|
|
||||||
/// </summary>
|
|
||||||
internal void Initialize()
|
|
||||||
{
|
|
||||||
_trackedItemIds.Clear();
|
|
||||||
try
|
|
||||||
{
|
|
||||||
foreach (WorldObject wo in CoreManager.Current.WorldFilter.GetInventory())
|
|
||||||
{
|
|
||||||
_trackedItemIds.Add(wo.Id);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
_logger?.Log($"[LiveInv] Error initializing: {ex.Message}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
internal void OnCreateObject(object sender, CreateObjectEventArgs e)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
var item = e.New;
|
|
||||||
if (!IsPlayerInventory(item)) return;
|
|
||||||
if (_trackedItemIds.Contains(item.Id)) return;
|
|
||||||
|
|
||||||
_trackedItemIds.Add(item.Id);
|
|
||||||
var mwo = MyWorldObjectCreator.Create(item);
|
|
||||||
_ = WebSocket.SendInventoryDeltaAsync("add", mwo);
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
_logger?.Log($"[LiveInv] Error in OnCreate: {ex.Message}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
internal void OnReleaseObject(object sender, ReleaseObjectEventArgs e)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
var item = e.Released;
|
|
||||||
if (!_trackedItemIds.Contains(item.Id)) return;
|
|
||||||
|
|
||||||
_trackedItemIds.Remove(item.Id);
|
|
||||||
_ = WebSocket.SendInventoryRemoveAsync(item.Id);
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
_logger?.Log($"[LiveInv] Error in OnRelease: {ex.Message}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
internal void OnChangeObject(object sender, ChangeObjectEventArgs e)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
var item = e.Changed;
|
|
||||||
if (!IsPlayerInventory(item))
|
|
||||||
{
|
|
||||||
// Item left our inventory
|
|
||||||
if (_trackedItemIds.Contains(item.Id))
|
|
||||||
{
|
|
||||||
_trackedItemIds.Remove(item.Id);
|
|
||||||
_ = WebSocket.SendInventoryRemoveAsync(item.Id);
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!_trackedItemIds.Contains(item.Id))
|
|
||||||
{
|
|
||||||
// New item appeared via ChangeObject
|
|
||||||
_trackedItemIds.Add(item.Id);
|
|
||||||
var mwo = MyWorldObjectCreator.Create(item);
|
|
||||||
_ = WebSocket.SendInventoryDeltaAsync("add", mwo);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Existing item changed (equip/unequip, stack change, container move)
|
|
||||||
var mwo = MyWorldObjectCreator.Create(item);
|
|
||||||
_ = WebSocket.SendInventoryDeltaAsync("update", mwo);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
_logger?.Log($"[LiveInv] Error in OnChange: {ex.Message}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
internal void Cleanup()
|
|
||||||
{
|
|
||||||
_trackedItemIds.Clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
private static bool IsPlayerInventory(WorldObject item)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
int containerId = item.Container;
|
|
||||||
int charId = CoreManager.Current.CharacterFilter.Id;
|
|
||||||
|
|
||||||
// Directly in character's inventory
|
|
||||||
if (containerId == charId) return true;
|
|
||||||
|
|
||||||
// In a side pack owned by the character
|
|
||||||
WorldObject container = CoreManager.Current.WorldFilter[containerId];
|
|
||||||
if (container != null &&
|
|
||||||
container.ObjectClass == ObjectClass.Container &&
|
|
||||||
container.Container == charId)
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
catch
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -312,7 +312,6 @@
|
||||||
<Compile Include="IPluginLogger.cs" />
|
<Compile Include="IPluginLogger.cs" />
|
||||||
<Compile Include="QuestStreamingService.cs" />
|
<Compile Include="QuestStreamingService.cs" />
|
||||||
<Compile Include="InventoryMonitor.cs" />
|
<Compile Include="InventoryMonitor.cs" />
|
||||||
<Compile Include="LiveInventoryTracker.cs" />
|
|
||||||
<Compile Include="KillTracker.cs" />
|
<Compile Include="KillTracker.cs" />
|
||||||
<Compile Include="RareTracker.cs" />
|
<Compile Include="RareTracker.cs" />
|
||||||
<Compile Include="ClientTelemetry.cs" />
|
<Compile Include="ClientTelemetry.cs" />
|
||||||
|
|
|
||||||
|
|
@ -144,7 +144,6 @@ namespace MosswartMassacre
|
||||||
private GameEventRouter _gameEventRouter;
|
private GameEventRouter _gameEventRouter;
|
||||||
private QuestStreamingService _questStreamingService;
|
private QuestStreamingService _questStreamingService;
|
||||||
private CommandRouter _commandRouter;
|
private CommandRouter _commandRouter;
|
||||||
private LiveInventoryTracker _liveInventoryTracker;
|
|
||||||
|
|
||||||
protected override void Startup()
|
protected override void Startup()
|
||||||
{
|
{
|
||||||
|
|
@ -182,12 +181,6 @@ namespace MosswartMassacre
|
||||||
CoreManager.Current.WorldFilter.ReleaseObject -= _inventoryMonitor.OnInventoryRelease;
|
CoreManager.Current.WorldFilter.ReleaseObject -= _inventoryMonitor.OnInventoryRelease;
|
||||||
CoreManager.Current.WorldFilter.ChangeObject -= _inventoryMonitor.OnInventoryChange;
|
CoreManager.Current.WorldFilter.ChangeObject -= _inventoryMonitor.OnInventoryChange;
|
||||||
}
|
}
|
||||||
if (_liveInventoryTracker != null)
|
|
||||||
{
|
|
||||||
CoreManager.Current.WorldFilter.CreateObject -= _liveInventoryTracker.OnCreateObject;
|
|
||||||
CoreManager.Current.WorldFilter.ReleaseObject -= _liveInventoryTracker.OnReleaseObject;
|
|
||||||
CoreManager.Current.WorldFilter.ChangeObject -= _liveInventoryTracker.OnChangeObject;
|
|
||||||
}
|
|
||||||
if (_gameEventRouter != null)
|
if (_gameEventRouter != null)
|
||||||
CoreManager.Current.EchoFilter.ServerDispatch -= _gameEventRouter.OnServerDispatch;
|
CoreManager.Current.EchoFilter.ServerDispatch -= _gameEventRouter.OnServerDispatch;
|
||||||
WebSocket.OnServerCommand -= HandleServerCommand;
|
WebSocket.OnServerCommand -= HandleServerCommand;
|
||||||
|
|
@ -225,9 +218,6 @@ namespace MosswartMassacre
|
||||||
_inventoryMonitor = new InventoryMonitor(this);
|
_inventoryMonitor = new InventoryMonitor(this);
|
||||||
_staticInventoryMonitor = _inventoryMonitor;
|
_staticInventoryMonitor = _inventoryMonitor;
|
||||||
|
|
||||||
// Initialize live inventory tracker (delta WebSocket messages)
|
|
||||||
_liveInventoryTracker = new LiveInventoryTracker(this);
|
|
||||||
|
|
||||||
// Initialize chat event router (rareTracker set later in LoginComplete)
|
// Initialize chat event router (rareTracker set later in LoginComplete)
|
||||||
_chatEventRouter = new ChatEventRouter(
|
_chatEventRouter = new ChatEventRouter(
|
||||||
this, _killTracker, null,
|
this, _killTracker, null,
|
||||||
|
|
@ -250,9 +240,6 @@ namespace MosswartMassacre
|
||||||
CoreManager.Current.WorldFilter.CreateObject += _inventoryMonitor.OnInventoryCreate;
|
CoreManager.Current.WorldFilter.CreateObject += _inventoryMonitor.OnInventoryCreate;
|
||||||
CoreManager.Current.WorldFilter.ReleaseObject += _inventoryMonitor.OnInventoryRelease;
|
CoreManager.Current.WorldFilter.ReleaseObject += _inventoryMonitor.OnInventoryRelease;
|
||||||
CoreManager.Current.WorldFilter.ChangeObject += _inventoryMonitor.OnInventoryChange;
|
CoreManager.Current.WorldFilter.ChangeObject += _inventoryMonitor.OnInventoryChange;
|
||||||
CoreManager.Current.WorldFilter.CreateObject += _liveInventoryTracker.OnCreateObject;
|
|
||||||
CoreManager.Current.WorldFilter.ReleaseObject += _liveInventoryTracker.OnReleaseObject;
|
|
||||||
CoreManager.Current.WorldFilter.ChangeObject += _liveInventoryTracker.OnChangeObject;
|
|
||||||
|
|
||||||
// Initialize VVS view after character login
|
// Initialize VVS view after character login
|
||||||
ViewManager.ViewInit();
|
ViewManager.ViewInit();
|
||||||
|
|
@ -426,15 +413,6 @@ namespace MosswartMassacre
|
||||||
// Clean up taper tracking
|
// Clean up taper tracking
|
||||||
_inventoryMonitor?.Cleanup();
|
_inventoryMonitor?.Cleanup();
|
||||||
|
|
||||||
// Clean up live inventory tracker
|
|
||||||
if (_liveInventoryTracker != null)
|
|
||||||
{
|
|
||||||
CoreManager.Current.WorldFilter.CreateObject -= _liveInventoryTracker.OnCreateObject;
|
|
||||||
CoreManager.Current.WorldFilter.ReleaseObject -= _liveInventoryTracker.OnReleaseObject;
|
|
||||||
CoreManager.Current.WorldFilter.ChangeObject -= _liveInventoryTracker.OnChangeObject;
|
|
||||||
_liveInventoryTracker.Cleanup();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Clean up Harmony patches
|
// Clean up Harmony patches
|
||||||
DecalHarmonyClean.Cleanup();
|
DecalHarmonyClean.Cleanup();
|
||||||
|
|
||||||
|
|
@ -504,9 +482,6 @@ namespace MosswartMassacre
|
||||||
// Initialize cached Prismatic Taper count
|
// Initialize cached Prismatic Taper count
|
||||||
_inventoryMonitor.Initialize();
|
_inventoryMonitor.Initialize();
|
||||||
|
|
||||||
// Initialize live inventory tracking (after full inventory dump)
|
|
||||||
_liveInventoryTracker?.Initialize();
|
|
||||||
|
|
||||||
// Initialize quest manager for always-on quest streaming
|
// Initialize quest manager for always-on quest streaming
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
|
@ -631,9 +606,6 @@ namespace MosswartMassacre
|
||||||
// 7. Reinitialize cached Prismatic Taper count
|
// 7. Reinitialize cached Prismatic Taper count
|
||||||
_inventoryMonitor?.Initialize();
|
_inventoryMonitor?.Initialize();
|
||||||
|
|
||||||
// 7b. Reinitialize live inventory tracking
|
|
||||||
_liveInventoryTracker?.Initialize();
|
|
||||||
|
|
||||||
// 8. Reinitialize quest manager for hot reload
|
// 8. Reinitialize quest manager for hot reload
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -295,34 +295,6 @@ namespace MosswartMassacre
|
||||||
await SendEncodedAsync(json, CancellationToken.None);
|
await SendEncodedAsync(json, CancellationToken.None);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static async Task SendInventoryDeltaAsync(string action, Mag.Shared.MyWorldObject item)
|
|
||||||
{
|
|
||||||
var envelope = new
|
|
||||||
{
|
|
||||||
type = "inventory_delta",
|
|
||||||
timestamp = DateTime.UtcNow.ToString("o"),
|
|
||||||
character_name = CoreManager.Current.CharacterFilter.Name,
|
|
||||||
action = action,
|
|
||||||
item = item
|
|
||||||
};
|
|
||||||
var json = JsonConvert.SerializeObject(envelope);
|
|
||||||
await SendEncodedAsync(json, CancellationToken.None);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static async Task SendInventoryRemoveAsync(int itemId)
|
|
||||||
{
|
|
||||||
var envelope = new
|
|
||||||
{
|
|
||||||
type = "inventory_delta",
|
|
||||||
timestamp = DateTime.UtcNow.ToString("o"),
|
|
||||||
character_name = CoreManager.Current.CharacterFilter.Name,
|
|
||||||
action = "remove",
|
|
||||||
item_id = itemId
|
|
||||||
};
|
|
||||||
var json = JsonConvert.SerializeObject(envelope);
|
|
||||||
await SendEncodedAsync(json, CancellationToken.None);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static async Task SendVitalsAsync(object vitalsData)
|
public static async Task SendVitalsAsync(object vitalsData)
|
||||||
{
|
{
|
||||||
var json = JsonConvert.SerializeObject(vitalsData);
|
var json = JsonConvert.SerializeObject(vitalsData);
|
||||||
|
|
|
||||||
Binary file not shown.
|
|
@ -18,7 +18,6 @@ namespace Mag.Shared
|
||||||
public int LastIdTime;
|
public int LastIdTime;
|
||||||
public int ObjectClass;
|
public int ObjectClass;
|
||||||
public int Icon;
|
public int Icon;
|
||||||
public int ContainerId;
|
|
||||||
|
|
||||||
public SerializableDictionary<int, bool> BoolValues = new SerializableDictionary<int, bool>();
|
public SerializableDictionary<int, bool> BoolValues = new SerializableDictionary<int, bool>();
|
||||||
public SerializableDictionary<int, double> DoubleValues = new SerializableDictionary<int, double>();
|
public SerializableDictionary<int, double> DoubleValues = new SerializableDictionary<int, double>();
|
||||||
|
|
|
||||||
|
|
@ -36,7 +36,6 @@ namespace Mag.Shared
|
||||||
spells.Add(wo.Spell(i));
|
spells.Add(wo.Spell(i));
|
||||||
|
|
||||||
mwo.Init(wo.HasIdData, wo.Id, wo.LastIdTime, (int)wo.ObjectClass, wo.Icon, boolValues, doubleValues, intValues, stringValues, activeSpells, spells);
|
mwo.Init(wo.HasIdData, wo.Id, wo.LastIdTime, (int)wo.ObjectClass, wo.Icon, boolValues, doubleValues, intValues, stringValues, activeSpells, spells);
|
||||||
mwo.ContainerId = wo.Container;
|
|
||||||
|
|
||||||
return mwo;
|
return mwo;
|
||||||
}
|
}
|
||||||
|
|
@ -55,7 +54,6 @@ namespace Mag.Shared
|
||||||
MyWorldObject mwo = Create(newer);
|
MyWorldObject mwo = Create(newer);
|
||||||
|
|
||||||
older.AddTo(mwo.BoolValues, mwo.DoubleValues, mwo.IntValues, mwo.StringValues);
|
older.AddTo(mwo.BoolValues, mwo.DoubleValues, mwo.IntValues, mwo.StringValues);
|
||||||
older.ContainerId = newer.Container;
|
|
||||||
|
|
||||||
return older;
|
return older;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue