Dynamic character rendering based on server provided information (#56)

* Update

* Partial work

* More stuff

* Shield rendering

* tmp

* Update

* WeaponCode

* Cleanup

* Fix build

* Initial inventory cleanup and sync

* Update

* Render body parts based on equipped torso

* Initial dynamic equipment work

* Update thingies
This commit is contained in:
Diego M 2018-12-19 20:44:22 -03:00 committed by Tim Sarbin
parent 5904658dad
commit ae10a9fa3b
18 changed files with 238 additions and 44 deletions

View File

@ -11,6 +11,8 @@
FocusOnPlayer = 0x05,
MoveRequest = 0x06,
PlayerMove = 0x07,
UpdateEquipment = 0x08,
ChangeEquipment = 0x09,
MAX = 0xFF, // NOTE:
// You absolutely cannot have a higher ID than this without

View File

@ -12,5 +12,6 @@ namespace OpenDiablo2.Common.Interfaces.Drawing
void Update(long ms);
void Render(int pixelOffsetX, int pixelOffsetY);
void ResetAnimationData();
void ResetCache();
}
}

View File

@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using OpenDiablo2.Common.Enums;
using OpenDiablo2.Common.Models;
using OpenDiablo2.Common.Models.Mobs;
namespace OpenDiablo2.Common.Interfaces
@ -13,5 +14,6 @@ namespace OpenDiablo2.Common.Interfaces
void Update(int ms);
void InitializeNewGame();
int SpawnNewPlayer(int clientHash, string playerName, eHero heroType);
PlayerEquipment UpdateEquipment(int clientHash, string slot, ItemInstance itemInstance);
}
}

View File

@ -3,21 +3,29 @@ using System.Collections.Generic;
using System.Drawing;
using OpenDiablo2.Common.Enums;
using OpenDiablo2.Common.Models;
using OpenDiablo2.Common.Models.Mobs;
namespace OpenDiablo2.Common.Interfaces
{
public delegate void OnSetSeedEvent(int clientHash, int seed);
public delegate void OnJoinGameEvent(int clientHash, eHero heroType, string playerName);
public delegate void OnUpdateEquipmentEvent(int clientHash, string slot, ItemInstance itemInstance);
public delegate void OnChangeEquipment(int clientHash, Guid PlayerUID, PlayerEquipment playerEquipment);
public delegate void OnLocatePlayersEvent(int clientHash, IEnumerable<LocationDetails> playerLocationDetails);
public delegate void OnPlayerInfoEvent(int clientHash, IEnumerable<PlayerInfo> playerInfo);
public delegate void OnFocusOnPlayer(int clientHash, Guid playerId);
public delegate void OnMoveRequest(int clientHash, PointF targetCell, eMovementType movementType);
public interface ISessionEventProvider
{
OnSetSeedEvent OnSetSeed { get; set; }
OnJoinGameEvent OnJoinGame { get; set; }
OnLocatePlayersEvent OnLocatePlayers { get; set; }
OnUpdateEquipmentEvent OnUpdateEquipment { get; set; }
OnChangeEquipment OnChangeEquipment { get; set; }
OnPlayerInfoEvent OnPlayerInfo { get; set; }
OnFocusOnPlayer OnFocusOnPlayer { get; set; }
OnMoveRequest OnMoveRequest { get; set; }

View File

@ -1,10 +1,8 @@
using System;
using System.Collections.Generic;
using OpenDiablo2.Common.Enums;
using OpenDiablo2.Common.Models;
using OpenDiablo2.Common.Models.Mobs;
using System;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using OpenDiablo2.Common.Enums;
namespace OpenDiablo2.Common.Interfaces
{
@ -16,5 +14,6 @@ namespace OpenDiablo2.Common.Interfaces
void JoinGame(string playerName, eHero heroType);
void MoveRequest(PointF targetCell, eMovementType movementType);
void UpdateEquipment(string slot, ItemInstance itemInstance);
}
}

View File

@ -8,6 +8,7 @@ namespace OpenDiablo2.Common.Interfaces
{
ItemInstance ContainedItem { get; }
Point Location { get; set; }
string Slot { get; set; }
void SetContainedItem(ItemInstance containedItem);
void Render();

View File

@ -31,7 +31,7 @@ namespace OpenDiablo2.Common.Models.Mobs
else if (RightArm?.Item is Weapon)
return ((Weapon)RightArm.Item).WeaponClass.ToWeaponClass();
else
return eWeaponClass.None;
return eWeaponClass.HandToHand;
}
}

View File

@ -6,6 +6,7 @@ using OpenDiablo2.Common.Enums;
using OpenDiablo2.Common.Interfaces;
using OpenDiablo2.Common.Interfaces.Drawing;
using OpenDiablo2.Common.Models;
using OpenDiablo2.Common.Models.Mobs;
namespace OpenDiablo2.Core.Map_Engine
{
@ -91,7 +92,6 @@ namespace OpenDiablo2.Core.Map_Engine
}
}
private const int SkewX = 400;
private const int SkewY = 300;
@ -175,8 +175,8 @@ namespace OpenDiablo2.Core.Map_Engine
var my = y - 300;
return new PointF
{
X = (float) Math.Round((mx / (float) CellSizeXHalf) + (my / (float) CellSizeYHalf) / 2f, 1) + _cameraLocation.X,
Y = (float) Math.Round((my / (float) CellSizeYHalf) - (mx / (float) CellSizeXHalf) / 2f, 1) + _cameraLocation.Y
X = (float)Math.Round((mx / (float)CellSizeXHalf) + (my / (float)CellSizeYHalf) / 2f, 1) + _cameraLocation.X,
Y = (float)Math.Round((my / (float)CellSizeYHalf) - (mx / (float)CellSizeXHalf) / 2f, 1) + _cameraLocation.Y
};
}
/*

View File

@ -68,7 +68,6 @@ namespace OpenDiablo2.Core
public MPQCOF GetPlayerAnimation(eHero hero, eMobMode mobMode, PlayerEquipment equipment)
=> cache.AddOrGetExisting($"COF::{hero}{mobMode.ToToken()}{equipment.HashKey}", () =>
{
var path = $"{ResourcePaths.PlayerAnimationBase}\\{hero.ToToken()}\\COF\\{hero.ToToken()}{mobMode.ToToken()}{equipment.WeaponClass.ToToken()}.cof";
return MPQCOF.Load(mpqProvider.GetStream(path), Animations, hero, mobMode, equipment);
}, new System.Runtime.Caching.CacheItemPolicy { Priority = System.Runtime.Caching.CacheItemPriority.NotRemovable });

View File

@ -1,9 +1,9 @@
using System.Collections.Generic;
using System.Drawing;
using OpenDiablo2.Common;
using OpenDiablo2.Common;
using OpenDiablo2.Common.Enums;
using OpenDiablo2.Common.Interfaces;
using OpenDiablo2.Common.Models;
using System.Collections.Generic;
using System.Drawing;
namespace OpenDiablo2.Core.UI
{
@ -16,12 +16,14 @@ namespace OpenDiablo2.Core.UI
private readonly ItemContainerLayout itemContainerLayout;
private readonly IMouseInfoProvider mouseInfoProvider;
private readonly ISessionManager sessionManager;
public ItemInstance ContainedItem { get; internal set; }
private readonly Dictionary<eItemContainerType, ISprite> sprites = new Dictionary<eItemContainerType, ISprite>();
private Point location = new Point();
private IMapRenderer mapRenderer;
public Point Location
{
@ -39,13 +41,16 @@ namespace OpenDiablo2.Core.UI
private readonly ISprite placeholderSprite;
public Size Size { get; internal set; }
public string Slot { get; set; }
public ItemContainer(IRenderWindow renderWindow, IGameState gameState, ItemContainerLayout itemContainerLayout, IMouseInfoProvider mouseInfoProvider)
public ItemContainer(IRenderWindow renderWindow, IGameState gameState, ItemContainerLayout itemContainerLayout, IMouseInfoProvider mouseInfoProvider, ISessionManager sessionManager, IMapRenderer mapRenderer)
{
this.renderWindow = renderWindow;
this.gameState = gameState;
this.itemContainerLayout = itemContainerLayout;
this.mouseInfoProvider = mouseInfoProvider;
this.sessionManager = sessionManager;
this.mapRenderer = mapRenderer;
placeholderSprite = renderWindow.LoadSprite(itemContainerLayout.ResourceName, itemContainerLayout.PaletteName, true);
placeholderSprite.Location = new Point(location.X, location.Y + placeholderSprite.LocalFrameSize.Height);
@ -63,6 +68,21 @@ namespace OpenDiablo2.Core.UI
}
}
// TODO: Add all restrictions.
public bool CanEquip(ItemInstance itemInstance)
{
if (Slot == "rarm" || Slot == "larm")
return (itemInstance.Item is Weapon || (itemInstance.Item is Armor && (itemInstance.Item as Armor).Type == "shie"));
if (Slot == "tors")
return (itemInstance.Item is Armor && (itemInstance.Item as Armor).Type == "tors");
if (Slot == "head")
return (itemInstance.Item is Armor && (itemInstance.Item as Armor).Type == "helm");
return true;
}
public void Update()
{
var hovered = mouseInfoProvider.MouseX >= location.X && mouseInfoProvider.MouseX < (location.X + this.Size.Width)
@ -75,21 +95,30 @@ namespace OpenDiablo2.Core.UI
{
if (this.gameState.SelectedItem != null)
{
var switchItem = this.gameState.SelectedItem;
if(CanEquip(this.gameState.SelectedItem))
{
var switchItem = this.gameState.SelectedItem;
this.gameState.SelectItem(this.ContainedItem);
this.SetContainedItem(switchItem);
this.gameState.SelectItem(this.ContainedItem);
this.SetContainedItem(switchItem);
}
} else
{
this.gameState.SelectItem(this.ContainedItem);
this.SetContainedItem(null);
}
sessionManager.UpdateEquipment(Slot, ContainedItem);
}
else if (this.gameState.SelectedItem != null)
{
this.SetContainedItem(this.gameState.SelectedItem);
this.gameState.SelectItem(null);
if (CanEquip(this.gameState.SelectedItem))
{
this.SetContainedItem(this.gameState.SelectedItem);
this.gameState.SelectItem(null);
sessionManager.UpdateEquipment(Slot, ContainedItem);
}
}
}
}

View File

@ -23,6 +23,7 @@ using OpenDiablo2.Common.Enums;
using OpenDiablo2.Common.Extensions;
using OpenDiablo2.Common.Interfaces;
using OpenDiablo2.Common.Models;
using OpenDiablo2.Common.Models.Mobs;
namespace OpenDiablo2.Core.UI
{
@ -35,7 +36,7 @@ namespace OpenDiablo2.Core.UI
private readonly IMapRenderer mapRenderer;
private readonly ISprite panelSprite;
private readonly IGameState gameState;
public IItemContainer headContainer, torsoContainer, beltContainer, gloveContainer, bootsContainer,
leftHandContainer, rightHandContainer, secondaryLeftHandContainer, secondaryRightHandContainer,
ringLeftContainer, ringRightContainer, neckContainer;
@ -58,6 +59,7 @@ namespace OpenDiablo2.Core.UI
sessionManager.OnFocusOnPlayer += OnFocusOnPlayer;
sessionManager.OnPlayerInfo += OnPlayerInfo;
sessionManager.OnChangeEquipment += OnChangeEquipment;
panelSprite = renderWindow.LoadSprite(ResourcePaths.InventoryCharacterPanel, Palettes.Units, FrameType.GetOffset(), true);
@ -79,18 +81,23 @@ namespace OpenDiablo2.Core.UI
headContainer = createItemContainer(eItemContainerType.Helm);
headContainer.Location = panelSprite.Location + new Size(135, 5);
headContainer.Slot = "head";
neckContainer = createItemContainer(eItemContainerType.Amulet);
neckContainer.Location = panelSprite.Location + new Size(209, 34);
neckContainer.Slot = "neck";
torsoContainer = createItemContainer(eItemContainerType.Armor);
torsoContainer.Location = panelSprite.Location + new Size(135, 75);
torsoContainer.Slot = "tors";
rightHandContainer = createItemContainer(eItemContainerType.Weapon);
rightHandContainer.Location = panelSprite.Location + new Size(20, 47);
rightHandContainer.Slot = "rarm";
leftHandContainer = createItemContainer(eItemContainerType.Weapon);
leftHandContainer.Location = panelSprite.Location + new Size(253, 47);
leftHandContainer.Slot = "larm";
secondaryLeftHandContainer = createItemContainer(eItemContainerType.Weapon);
secondaryLeftHandContainer.Location = panelSprite.Location + new Size(24, 45);
@ -100,45 +107,63 @@ namespace OpenDiablo2.Core.UI
beltContainer = createItemContainer(eItemContainerType.Belt);
beltContainer.Location = panelSprite.Location + new Size(136, 178);
beltContainer.Slot = "belt";
ringLeftContainer = createItemContainer(eItemContainerType.Ring);
ringLeftContainer.Location = panelSprite.Location + new Size(95, 179);
ringLeftContainer.Slot = "rrin";
ringRightContainer = createItemContainer(eItemContainerType.Ring);
ringRightContainer.Location = panelSprite.Location + new Size(209, 179);
ringRightContainer.Slot = "lrin";
gloveContainer = createItemContainer(eItemContainerType.Glove);
gloveContainer.Location = panelSprite.Location + new Size(20, 179);
gloveContainer.Slot = "glov";
bootsContainer = createItemContainer(eItemContainerType.Boots);
bootsContainer.Location = panelSprite.Location + new Size(251, 178);
bootsContainer.Slot = "feet";
}
private void OnPlayerInfo(int clientHash, IEnumerable<PlayerInfo> playerInfo)
{
var currentPlayer = gameState.PlayerInfos.FirstOrDefault(x => x.UID == mapRenderer.FocusedPlayerId);
if (currentPlayer != null)
UpdateInventoryPanel(currentPlayer);
UpdateInventoryPanel(currentPlayer.Equipment);
}
private void OnFocusOnPlayer(int clientHash, Guid playerId)
{
var currentPlayer = gameState.PlayerInfos.FirstOrDefault(x => x.UID == playerId);
if (currentPlayer != null)
UpdateInventoryPanel(currentPlayer);
if (currentPlayer != null) { }
UpdateInventoryPanel(currentPlayer.Equipment);
}
private void UpdateInventoryPanel(PlayerInfo currentPlayer)
private void OnChangeEquipment(int clientHash, Guid playerUID, PlayerEquipment playerEquipment)
{
leftHandContainer.SetContainedItem(currentPlayer.Equipment.LeftArm);
rightHandContainer.SetContainedItem(currentPlayer.Equipment.RightArm);
torsoContainer.SetContainedItem(currentPlayer.Equipment.Torso);
headContainer.SetContainedItem(currentPlayer.Equipment.Head);
ringLeftContainer.SetContainedItem(currentPlayer.Equipment.LeftRing);
ringRightContainer.SetContainedItem(currentPlayer.Equipment.RightRing);
beltContainer.SetContainedItem(currentPlayer.Equipment.Belt);
neckContainer.SetContainedItem(currentPlayer.Equipment.Neck);
gloveContainer.SetContainedItem(currentPlayer.Equipment.Gloves);
var player = gameState.PlayerInfos.FirstOrDefault(x => x.UID == playerUID);
if (player != null)
{
player.Equipment = playerEquipment;
UpdateInventoryPanel(playerEquipment);
}
}
private void UpdateInventoryPanel(PlayerEquipment playerEquipment)
{
leftHandContainer.SetContainedItem(playerEquipment.LeftArm);
rightHandContainer.SetContainedItem(playerEquipment.RightArm);
torsoContainer.SetContainedItem(playerEquipment.Torso);
headContainer.SetContainedItem(playerEquipment.Head);
ringLeftContainer.SetContainedItem(playerEquipment.LeftRing);
ringRightContainer.SetContainedItem(playerEquipment.RightRing);
beltContainer.SetContainedItem(playerEquipment.Belt);
neckContainer.SetContainedItem(playerEquipment.Neck);
gloveContainer.SetContainedItem(playerEquipment.Gloves);
}
public ePanelType PanelType => ePanelType.Inventory;

View File

@ -16,9 +16,11 @@
using System;
using System.Collections.Generic;
using System.Linq;
using OpenDiablo2.Common.Enums;
using OpenDiablo2.Common.Interfaces;
using OpenDiablo2.Common.Interfaces.Mobs;
using OpenDiablo2.Common.Models;
using OpenDiablo2.Common.Models.Mobs;
using OpenDiablo2.Common.Services;
@ -100,6 +102,15 @@ namespace OpenDiablo2.GameServer_
return newPlayer.Id;
}
public PlayerEquipment UpdateEquipment(int clienthash, string slot, ItemInstance itemInstance)
{
var player = mobManager.Players.FirstOrDefault(x => x.ClientHash == clienthash);
player.Equipment.EquipItem(slot, itemInstance);
return player.Equipment;
}
public void Update(int ms)
{
var seconds = ms / 1000f;

View File

@ -35,6 +35,7 @@ namespace OpenDiablo2.SDL2_
{
public int Direction { get; set; }
public eMobMode MobMode { get; set; }
public string EquipmentHash { get; set; }
public SDL.SDL_Rect[] SpriteRect { get; set; }
public IntPtr[] SpriteTexture { get; set; }
@ -80,6 +81,7 @@ namespace OpenDiablo2.SDL2_
private readonly IGameState gameState;
private int lastDirection = -1;
private eMovementType lastMovementType = eMovementType.Stopped;
private string lastEquipmentHash = string.Empty;
private MPQCOF animationData;
@ -115,10 +117,11 @@ namespace OpenDiablo2.SDL2_
return;
if ((lastDirection != MobLocation.MovementDirection) || (lastMovementType != MobLocation.MovementType))
if ((lastDirection != MobLocation.MovementDirection) || (lastMovementType != MobLocation.MovementType) || (lastEquipmentHash != Equipment.HashKey))
{
lastMovementType = MobLocation.MovementType;
lastDirection = MobLocation.MovementDirection;
lastEquipmentHash = Equipment.HashKey;
ResetAnimationData();
}
@ -138,6 +141,11 @@ namespace OpenDiablo2.SDL2_
}
public void ResetCache()
{
directionCache.Clear();
}
public void ResetAnimationData()
{
@ -160,7 +168,8 @@ namespace OpenDiablo2.SDL2_
if (lastMobMode != MobMode)
renderFrameIndex = 0;
currentDirectionCache = directionCache.FirstOrDefault(x => x.MobMode == MobMode && x.Direction == directionConversion[MobLocation.MovementDirection]);
currentDirectionCache = directionCache.FirstOrDefault(x => x.MobMode == MobMode && x.Direction == directionConversion[MobLocation.MovementDirection] && x.EquipmentHash == Equipment.HashKey);
if (currentDirectionCache != null)
return;
@ -179,7 +188,7 @@ namespace OpenDiablo2.SDL2_
MobMode = MobMode,
Direction = directionConversion[MobLocation.MovementDirection]
};
var palette = paletteProvider.PaletteTable[Palettes.Units];
var dirAnimation = animationData.Animations[0];
@ -264,7 +273,7 @@ namespace OpenDiablo2.SDL2_
directionCache.SpriteTexture[frameIndex] = texture;
directionCache.SpriteRect[frameIndex] = new SDL.SDL_Rect { x = minX, y = minY, w = frameW, h = frameH };
directionCache.EquipmentHash = Equipment.HashKey;
this.directionCache.Add(directionCache);
}

View File

@ -0,0 +1,40 @@
using OpenDiablo2.Common.Attributes;
using OpenDiablo2.Common.Enums;
using OpenDiablo2.Common.Interfaces;
using OpenDiablo2.Common.Models;
using OpenDiablo2.Common.Models.Mobs;
using System.IO;
namespace OpenDiablo2.ServiceBus.Message_Frames.Client
{
[MessageFrame(eMessageFrameType.UpdateEquipment)]
public sealed class MFUpdateEquipment : IMessageFrame
{
public ItemInstance ItemInstance { get; internal set; }
public string Slot { get; private set; }
public void WriteTo(BinaryWriter bw)
{
bw.Write(Slot);
bw.Write(ItemInstance);
}
public void LoadFrom(BinaryReader br)
{
Slot = br.ReadString();
ItemInstance = br.ReadItemInstance();
}
public MFUpdateEquipment() { }
public MFUpdateEquipment(string slot, ItemInstance itemInstance)
{
Slot = slot;
ItemInstance = itemInstance;
}
public void Process(int clientHash, ISessionEventProvider sessionEventProvider)
{
sessionEventProvider.OnUpdateEquipment(clientHash, Slot, ItemInstance);
}
}
}

View File

@ -0,0 +1,40 @@
using OpenDiablo2.Common.Attributes;
using OpenDiablo2.Common.Enums;
using OpenDiablo2.Common.Interfaces;
using OpenDiablo2.Common.Models.Mobs;
using System;
using System.IO;
namespace OpenDiablo2.ServiceBus.Message_Frames.Server
{
[MessageFrame(eMessageFrameType.ChangeEquipment)]
public sealed class MFChangeEquipment : IMessageFrame
{
public PlayerEquipment PlayerEquipment { get; internal set; }
public Guid PlayerId { get; internal set; }
public void WriteTo(BinaryWriter bw)
{
bw.Write(PlayerId.ToByteArray());
bw.Write(PlayerEquipment);
}
public void LoadFrom(BinaryReader br)
{
PlayerId = new Guid(br.ReadBytes(16));
PlayerEquipment = br.ReadPlayerEquipment();
}
public MFChangeEquipment() { }
public MFChangeEquipment(Guid playerId, PlayerEquipment playerEquipment)
{
PlayerEquipment = playerEquipment;
PlayerId = playerId;
}
public void Process(int clientHash, ISessionEventProvider sessionEventProvider)
{
sessionEventProvider.OnChangeEquipment(clientHash, PlayerId, PlayerEquipment);
}
}
}

View File

@ -59,12 +59,14 @@
</ItemGroup>
<ItemGroup>
<Compile Include="AutofacModule.cs" />
<Compile Include="Message Frames\Client\MFUpdateEquipment.cs" />
<Compile Include="Message Frames\Client\MFJoinGame.cs" />
<Compile Include="Message Frames\Client\MFMoveRequest.cs" />
<Compile Include="Message Frames\Server\MFFocusOnPlayer.cs" />
<Compile Include="Message Frames\Server\MFPlayerInfo.cs" />
<Compile Include="Message Frames\Server\MFLocatePlayers.cs" />
<Compile Include="Message Frames\Server\MFSetSeed.cs" />
<Compile Include="Message Frames\Server\MFChangeEquipment.cs" />
<Compile Include="SessionManager.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="SessionServer.cs" />

View File

@ -26,6 +26,8 @@ using OpenDiablo2.Common.Attributes;
using OpenDiablo2.Common.Enums;
using OpenDiablo2.Common.Exceptions;
using OpenDiablo2.Common.Interfaces;
using OpenDiablo2.Common.Models;
using OpenDiablo2.Common.Models.Mobs;
using OpenDiablo2.ServiceBus.Message_Frames.Client;
using OpenDiablo2.ServiceBus.Message_Frames.Server;
@ -51,6 +53,8 @@ namespace OpenDiablo2.ServiceBus
public OnPlayerInfoEvent OnPlayerInfo { get; set; }
public OnFocusOnPlayer OnFocusOnPlayer { get; set; }
public OnMoveRequest OnMoveRequest { get; set; }
public OnUpdateEquipmentEvent OnUpdateEquipment { get; set; }
public OnChangeEquipment OnChangeEquipment { get; set; }
public SessionManager(
eSessionType sessionType,
@ -176,5 +180,14 @@ namespace OpenDiablo2.ServiceBus
Send(new MFMoveRequest(targetCell, movementType));
ProcessMessageFrame<MFLocatePlayers>();
});
public void UpdateEquipment(string slot, ItemInstance itemInstance)
{
Task.Run(() =>
{
Send(new MFUpdateEquipment(slot, itemInstance));
ProcessMessageFrame<MFChangeEquipment>();
});
}
}
}

View File

@ -48,12 +48,14 @@ namespace OpenDiablo2.ServiceBus
public OnJoinGameEvent OnJoinGame { get; set; }
public OnMoveRequest OnMoveRequest { get; set; }
public OnUpdateEquipmentEvent OnUpdateEquipment { get; set; }
// TODO: Fix interface so we don't need this in the session server
public OnSetSeedEvent OnSetSeed { get; set; }
public OnLocatePlayersEvent OnLocatePlayers { get; set; }
public OnPlayerInfoEvent OnPlayerInfo { get; set; }
public OnFocusOnPlayer OnFocusOnPlayer { get; set; }
public OnChangeEquipment OnChangeEquipment { get; set; }
const int serverUpdateRate = 30;
@ -94,6 +96,7 @@ namespace OpenDiablo2.ServiceBus
OnJoinGame += OnJoinGameHandler;
OnMoveRequest += OnMovementRequestHandler;
OnUpdateEquipment += OnUpdateEquipmentHandler;
var proactor = new NetMQProactor(responseSocket, (socket, message) =>
{
@ -226,5 +229,15 @@ namespace OpenDiablo2.ServiceBus
Send(new MFLocatePlayers(gameServer.Players.Select(x => x.ToPlayerLocationDetails())), true);
Send(new MFFocusOnPlayer(gameServer.Players.First(x => x.ClientHash == clientHash).UID));
}
private void OnUpdateEquipmentHandler(int clientHash, string Slot, ItemInstance itemInstance)
{
var player = gameServer.Players.FirstOrDefault(x => x.ClientHash == clientHash);
if (player == null)
return;
var equipment = gameServer.UpdateEquipment(clientHash, Slot, itemInstance);
Send(new MFChangeEquipment(player.UID, equipment));
}
}
}