mirror of
https://github.com/OpenDiablo2/OpenDiablo2
synced 2025-02-20 07:27:19 -05:00
Fleshed out mob management on server. Added player location message frame.
This commit is contained in:
parent
1fc0eec1be
commit
1c5a0d3361
@ -27,7 +27,7 @@ namespace OpenDiablo2.Common.UT
|
||||
2250,
|
||||
4125,
|
||||
});
|
||||
PlayerState ps = new PlayerState("player1", id: 1, level: 1, x: 0, y: 0,
|
||||
PlayerState ps = new PlayerState(0, "player1", id: 1, level: 1, x: 0, y: 0,
|
||||
vitality: herotypeconfig.StartingVitality,
|
||||
strength: herotypeconfig.StartingStrength,
|
||||
energy: herotypeconfig.StartingEnergy,
|
||||
|
@ -6,11 +6,13 @@ using System.Threading.Tasks;
|
||||
|
||||
namespace OpenDiablo2.Common.Enums
|
||||
{
|
||||
// TODO: I don't think this needs to live in core...
|
||||
public enum eMessageFrameType
|
||||
{
|
||||
None = 0x00,
|
||||
SetSeed = 0x01,
|
||||
JoinGame = 0x02,
|
||||
LocatePlayers = 0x03,
|
||||
|
||||
MAX = 0xFF, // NOTE:
|
||||
// You absolutely cannot have a higher ID than this without
|
||||
|
12
OpenDiablo2.Common/Extensions/MobManagerExtensions.cs
Normal file
12
OpenDiablo2.Common/Extensions/MobManagerExtensions.cs
Normal file
@ -0,0 +1,12 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using OpenDiablo2.Common.Models.Mobs;
|
||||
|
||||
namespace OpenDiablo2.Common.Extensions
|
||||
{
|
||||
public static class MobManagerExtensions
|
||||
{
|
||||
public static IEnumerable<MobState> FindInRadius(this IEnumerable<MobState> mobs, float centerx, float centery, float radius)
|
||||
=> mobs.Where(x => x.GetDistance(centerx, centery) <= radius);
|
||||
}
|
||||
}
|
16
OpenDiablo2.Common/Interfaces/IGameServer.cs
Normal file
16
OpenDiablo2.Common/Interfaces/IGameServer.cs
Normal file
@ -0,0 +1,16 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using OpenDiablo2.Common.Enums;
|
||||
using OpenDiablo2.Common.Models.Mobs;
|
||||
|
||||
namespace OpenDiablo2.Common.Interfaces
|
||||
{
|
||||
public interface IGameServer : IDisposable
|
||||
{
|
||||
IEnumerable<PlayerState> Players { get; }
|
||||
int Seed { get; }
|
||||
|
||||
void InitializeNewGame();
|
||||
int SpawnNewPlayer(int clientHash, string playerName, eHero heroType);
|
||||
}
|
||||
}
|
@ -1,11 +1,10 @@
|
||||
using System;
|
||||
using System.Drawing;
|
||||
using OpenDiablo2.Common.Models;
|
||||
using System.Drawing;
|
||||
|
||||
namespace OpenDiablo2.Common.Interfaces
|
||||
{
|
||||
public interface IMapEngine
|
||||
{
|
||||
int FocusedMobId { get; set; }
|
||||
PointF CameraLocation { get; set; }
|
||||
void Update(long ms);
|
||||
void Render();
|
||||
|
@ -9,6 +9,6 @@ namespace OpenDiablo2.Common.Interfaces
|
||||
public interface IMessageFrame
|
||||
{
|
||||
byte[] Data { get; set; }
|
||||
void Process(object sender, ISessionEventProvider sessionEventProvider);
|
||||
void Process(int clientHash, ISessionEventProvider sessionEventProvider);
|
||||
}
|
||||
}
|
||||
|
@ -1,18 +1,18 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using OpenDiablo2.Common.Enums;
|
||||
using OpenDiablo2.Common.Interfaces.MessageBus;
|
||||
|
||||
namespace OpenDiablo2.Common.Interfaces
|
||||
{
|
||||
public delegate void OnSetSeedEvent(object sender, int seed);
|
||||
public delegate void OnJoinGameEvent(object sender, Guid playerId, string playerName); // TODO: Not the final version..
|
||||
public delegate void OnSetSeedEvent(int clientHash, int seed);
|
||||
public delegate void OnJoinGameEvent(int clientHash, eHero heroType, string playerName);
|
||||
public delegate void OnLocatePlayersEvent(int clientHash, IEnumerable<PlayerLocationDetails> playerLocationDetails);
|
||||
|
||||
public interface ISessionEventProvider
|
||||
{
|
||||
|
||||
OnSetSeedEvent OnSetSeed { get; set; }
|
||||
OnJoinGameEvent OnJoinGame { get; set; }
|
||||
OnLocatePlayersEvent OnLocatePlayers { get; set; }
|
||||
}
|
||||
}
|
||||
|
@ -3,15 +3,18 @@ using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using OpenDiablo2.Common.Enums;
|
||||
|
||||
namespace OpenDiablo2.Common.Interfaces
|
||||
{
|
||||
|
||||
public interface ISessionManager : ISessionEventProvider, IDisposable
|
||||
{
|
||||
Guid PlayerId { get; }
|
||||
|
||||
void Initialize();
|
||||
void Stop();
|
||||
|
||||
void JoinGame(string playerName, Action<Guid> callback);
|
||||
void JoinGame(string playerName, eHero heroType);
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,44 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using OpenDiablo2.Common.Models.Mobs;
|
||||
|
||||
namespace OpenDiablo2.Common.Interfaces.MessageBus
|
||||
{
|
||||
public sealed class PlayerLocationDetails
|
||||
{
|
||||
public int PlayerId { get; set; }
|
||||
public float PlayerX { get; set; }
|
||||
public float PlayerY { get; set; }
|
||||
// TODO: They may not be on the same 'anchor map'...
|
||||
|
||||
public byte[] GetBytes()
|
||||
{
|
||||
var result = new List<byte>();
|
||||
result.AddRange(BitConverter.GetBytes(PlayerId));
|
||||
result.AddRange(BitConverter.GetBytes(PlayerX));
|
||||
result.AddRange(BitConverter.GetBytes(PlayerY));
|
||||
return result.ToArray();
|
||||
}
|
||||
|
||||
public static PlayerLocationDetails FromBytes(byte[] data, int offset = 0)
|
||||
=> new PlayerLocationDetails
|
||||
{
|
||||
PlayerId = BitConverter.ToInt32(data, offset + 0),
|
||||
PlayerX = BitConverter.ToSingle(data, offset + 4),
|
||||
PlayerY = BitConverter.ToSingle(data, offset + 8)
|
||||
};
|
||||
|
||||
public static int SizeInBytes => 12;
|
||||
}
|
||||
|
||||
public static class PlayerLocationDetailsExtensions
|
||||
{
|
||||
public static PlayerLocationDetails ToPlayerLocationDetails(this PlayerState source)
|
||||
=> new PlayerLocationDetails
|
||||
{
|
||||
PlayerId = source.Id,
|
||||
PlayerX = source.GetPosition().X,
|
||||
PlayerY = source.GetPosition().Y
|
||||
};
|
||||
}
|
||||
}
|
@ -1,14 +0,0 @@
|
||||
using OpenDiablo2.Common.Models.Mobs;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace OpenDiablo2.Common.Interfaces.Mobs
|
||||
{
|
||||
public interface IMobCondition
|
||||
{
|
||||
bool Evaluate(MobState mob);
|
||||
}
|
||||
}
|
@ -1,13 +1,22 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Collections.Generic;
|
||||
using OpenDiablo2.Common.Models.Mobs;
|
||||
|
||||
namespace OpenDiablo2.Common.Interfaces.Mobs
|
||||
{
|
||||
public interface IMobManager
|
||||
{
|
||||
// TODO:
|
||||
IEnumerable<MobState> Mobs { get; }
|
||||
IEnumerable<PlayerState> Players { get; }
|
||||
IEnumerable<EnemyState> Enemies { get; }
|
||||
|
||||
void AddPlayer(PlayerState player);
|
||||
void RemovePlayer(PlayerState player);
|
||||
|
||||
void AddMob(MobState mob);
|
||||
void RemoveMob(MobState mob);
|
||||
int GetNextAvailableMobId();
|
||||
|
||||
void AddEnemy(EnemyState enemy);
|
||||
void RemoveEnemy(EnemyState enemy);
|
||||
}
|
||||
}
|
||||
|
@ -1,9 +1,4 @@
|
||||
using OpenDiablo2.Common.Enums.Mobs;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace OpenDiablo2.Common.Models.Mobs
|
||||
{
|
||||
@ -11,6 +6,8 @@ namespace OpenDiablo2.Common.Models.Mobs
|
||||
{
|
||||
public int ExperienceGiven { get; protected set; }
|
||||
|
||||
public EnemyState() : base() { }
|
||||
|
||||
public EnemyState(string name, int id, int level, int maxhealth, float x, float y, int experiencegiven)
|
||||
: base(name, id, level, maxhealth, x, y)
|
||||
{
|
||||
|
@ -1,97 +0,0 @@
|
||||
using OpenDiablo2.Common.Enums.Mobs;
|
||||
using OpenDiablo2.Common.Interfaces.Mobs;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace OpenDiablo2.Common.Models.Mobs
|
||||
{
|
||||
public class MobConditionAnd : IMobCondition
|
||||
{
|
||||
public List<IMobCondition> Conditions = new List<IMobCondition>();
|
||||
|
||||
public MobConditionAnd(List<IMobCondition> conditions)
|
||||
{
|
||||
Conditions = conditions;
|
||||
}
|
||||
|
||||
public bool Evaluate(MobState mob)
|
||||
{
|
||||
foreach(IMobCondition condition in Conditions)
|
||||
{
|
||||
if (!condition.Evaluate(mob))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
public class MobConditionOr : IMobCondition
|
||||
{
|
||||
public List<IMobCondition> Conditions = new List<IMobCondition>();
|
||||
|
||||
public MobConditionOr(List<IMobCondition> conditions)
|
||||
{
|
||||
Conditions = conditions;
|
||||
}
|
||||
|
||||
public bool Evaluate(MobState mob)
|
||||
{
|
||||
foreach (IMobCondition condition in Conditions)
|
||||
{
|
||||
if (condition.Evaluate(mob))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public class MobConditionNot : IMobCondition
|
||||
{
|
||||
public IMobCondition Condition = null;
|
||||
|
||||
public MobConditionNot(IMobCondition condition)
|
||||
{
|
||||
Condition = condition;
|
||||
}
|
||||
|
||||
public bool Evaluate(MobState mob)
|
||||
{
|
||||
if(Condition == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return !Condition.Evaluate(mob);
|
||||
}
|
||||
}
|
||||
|
||||
public class MobConditionFlags : IMobCondition
|
||||
{
|
||||
public Dictionary<eMobFlags, bool> Flags = new Dictionary<eMobFlags, bool>();
|
||||
|
||||
public MobConditionFlags(Dictionary<eMobFlags, bool> flags)
|
||||
{
|
||||
Flags = flags;
|
||||
}
|
||||
|
||||
public bool Evaluate(MobState mob)
|
||||
{
|
||||
foreach(eMobFlags flag in Flags.Keys)
|
||||
{
|
||||
if(Flags[flag] != mob.HasFlag(flag))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: implement more of these
|
||||
}
|
@ -1,14 +1,11 @@
|
||||
using OpenDiablo2.Common.Enums.Mobs;
|
||||
using System;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using OpenDiablo2.Common.Enums.Mobs;
|
||||
|
||||
namespace OpenDiablo2.Common.Models.Mobs
|
||||
{
|
||||
public class MobState
|
||||
public class MobState : IComparable
|
||||
{
|
||||
public readonly string Name;
|
||||
public readonly int Id;
|
||||
@ -26,6 +23,8 @@ namespace OpenDiablo2.Common.Models.Mobs
|
||||
|
||||
protected Dictionary<eMobFlags, bool> Flags = new Dictionary<eMobFlags, bool>();
|
||||
|
||||
public MobState() { }
|
||||
|
||||
public MobState(string name, int id, int level, int maxhealth, float x, float y)
|
||||
{
|
||||
Name = name;
|
||||
@ -163,6 +162,10 @@ namespace OpenDiablo2.Common.Models.Mobs
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
#endregion Flags
|
||||
|
||||
|
||||
public int CompareTo(object obj) => Id - ((MobState)obj).Id;
|
||||
}
|
||||
}
|
||||
|
@ -1,27 +1,23 @@
|
||||
using OpenDiablo2.Common.Enums;
|
||||
using System;
|
||||
using OpenDiablo2.Common.Enums;
|
||||
using OpenDiablo2.Common.Enums.Mobs;
|
||||
using OpenDiablo2.Common.Interfaces.Mobs;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace OpenDiablo2.Common.Models.Mobs
|
||||
{
|
||||
public class PlayerState : MobState
|
||||
{
|
||||
public Guid Id { get; protected set; }
|
||||
public eHero HeroType { get; protected set; }
|
||||
private IHeroTypeConfig HeroTypeConfig;
|
||||
private ILevelExperienceConfig ExperienceConfig;
|
||||
public int ClientHash { get; protected set; }
|
||||
|
||||
// Player character stats
|
||||
protected Stat Vitality;
|
||||
protected Stat Strength;
|
||||
protected Stat Energy;
|
||||
protected Stat Dexterity;
|
||||
|
||||
|
||||
protected Stat DefenseRating;
|
||||
protected Stat AttackRating;
|
||||
|
||||
@ -30,11 +26,14 @@ namespace OpenDiablo2.Common.Models.Mobs
|
||||
|
||||
public int Experience { get; protected set; }
|
||||
|
||||
public PlayerState(string name, int id, int level, float x, float y,
|
||||
int vitality, int strength, int energy, int dexterity, int experience, eHero herotype,
|
||||
public PlayerState() : base() { }
|
||||
|
||||
public PlayerState(int clientHash, string name, int id, int level, float x, float y,
|
||||
int vitality, int strength, int energy, int dexterity, int experience, eHero herotype,
|
||||
IHeroTypeConfig heroconfig, ILevelExperienceConfig expconfig)
|
||||
: base(name, id, level, 0, x, y)
|
||||
{
|
||||
this.ClientHash = clientHash;
|
||||
Stamina = new Stat(0, 0, 0, true);
|
||||
Mana = new Stat(0, 0, 0, true);
|
||||
|
||||
@ -43,7 +42,7 @@ namespace OpenDiablo2.Common.Models.Mobs
|
||||
Energy = new Stat(0, energy, energy, true);
|
||||
Dexterity = new Stat(0, dexterity, dexterity, true);
|
||||
|
||||
AttackRating = new Stat(0, 0, 0, false);
|
||||
AttackRating = new Stat(0, 0, 0, false);
|
||||
DefenseRating = new Stat(0, 0, 0, false);
|
||||
|
||||
Experience = experience; // how much total exp do they have
|
||||
@ -82,11 +81,11 @@ namespace OpenDiablo2.Common.Models.Mobs
|
||||
}
|
||||
public bool TryLevelUp()
|
||||
{
|
||||
if(Level >= GetMaxLevel())
|
||||
if (Level >= GetMaxLevel())
|
||||
{
|
||||
return false; // can't level up anymore
|
||||
}
|
||||
if(GetExperienceToLevel() > 0)
|
||||
if (GetExperienceToLevel() > 0)
|
||||
{
|
||||
return false; // not enough exp
|
||||
}
|
||||
|
@ -69,10 +69,13 @@
|
||||
<Compile Include="Enums\Mobs\eDamageTypes.cs" />
|
||||
<Compile Include="Enums\Mobs\eMobFlags.cs" />
|
||||
<Compile Include="Enums\Mobs\eStatModifierType.cs" />
|
||||
<Compile Include="Extensions\MobManagerExtensions.cs" />
|
||||
<Compile Include="Interfaces\IGameServer.cs" />
|
||||
<Compile Include="Interfaces\MessageBus\ISessionEventProvider.cs" />
|
||||
<Compile Include="Interfaces\MessageBus\IMessageFrame.cs" />
|
||||
<Compile Include="Interfaces\MessageBus\ISessionManager.cs" />
|
||||
<Compile Include="Interfaces\MessageBus\ISessionServer.cs" />
|
||||
<Compile Include="Interfaces\MessageBus\PlayerLocationDetails.cs" />
|
||||
<Compile Include="Interfaces\UI\IButton.cs" />
|
||||
<Compile Include="Interfaces\UI\IPanelFrame.cs" />
|
||||
<Compile Include="Interfaces\UI\IInventoryPanel.cs" />
|
||||
@ -101,7 +104,6 @@
|
||||
<Compile Include="Interfaces\Drawing\ITexture.cs" />
|
||||
<Compile Include="Interfaces\Mobs\IHeroTypeConfig.cs" />
|
||||
<Compile Include="Interfaces\Mobs\ILevelExperienceConfig.cs" />
|
||||
<Compile Include="Interfaces\Mobs\IMobCondition.cs" />
|
||||
<Compile Include="Interfaces\Mobs\IMobManager.cs" />
|
||||
<Compile Include="Interfaces\Mobs\IStatModifier.cs" />
|
||||
<Compile Include="Models\BitStream.cs" />
|
||||
@ -114,7 +116,6 @@
|
||||
<Compile Include="Models\Mobs\EnemyState.cs" />
|
||||
<Compile Include="Models\Mobs\HeroTypeConfig.cs" />
|
||||
<Compile Include="Models\Mobs\LevelExperienceConfig.cs" />
|
||||
<Compile Include="Models\Mobs\MobCondition.cs" />
|
||||
<Compile Include="Models\Mobs\MobState.cs" />
|
||||
<Compile Include="Models\Mobs\PlayerState.cs" />
|
||||
<Compile Include="Models\Mobs\Stat.cs" />
|
||||
|
@ -1,13 +1,9 @@
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using System.Linq;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using OpenDiablo2.Common.Enums.Mobs;
|
||||
using OpenDiablo2.Common.Extensions;
|
||||
using OpenDiablo2.Common.Models.Mobs;
|
||||
using OpenDiablo2.Core.GameState_;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace OpenDiablo2.Core.UT
|
||||
{
|
||||
@ -19,34 +15,21 @@ namespace OpenDiablo2.Core.UT
|
||||
{
|
||||
MobManager mobman = new MobManager();
|
||||
MobState mob1 = new MobState("test1", mobman.GetNextAvailableMobId(), 1, 100, 0, 0);
|
||||
MobState mob2 = new MobState("test2", mobman.GetNextAvailableMobId(), 1, 100, 0, 0);
|
||||
MobState mob3 = new MobState("test3", mobman.GetNextAvailableMobId(), 1, 100, 0, 0);
|
||||
mob1.AddFlag(eMobFlags.ENEMY);
|
||||
mobman.AddMob(mob1);
|
||||
|
||||
MobState mob2 = new MobState("test2", mobman.GetNextAvailableMobId(), 1, 100, 0, 0);
|
||||
mob2.AddFlag(eMobFlags.ENEMY);
|
||||
mob2.AddFlag(eMobFlags.INVULNERABLE);
|
||||
mobman.AddMob(mob1);
|
||||
mobman.AddMob(mob2);
|
||||
|
||||
MobState mob3 = new MobState("test3", mobman.GetNextAvailableMobId(), 1, 100, 0, 0);
|
||||
mobman.AddMob(mob3);
|
||||
|
||||
Assert.IsTrue(mobman.FindMobs(new MobConditionFlags(
|
||||
new Dictionary<eMobFlags, bool> {
|
||||
{ eMobFlags.ENEMY, true }
|
||||
})).Count == 2);
|
||||
|
||||
Assert.IsTrue(mobman.FindMobs(new MobConditionFlags(
|
||||
new Dictionary<eMobFlags, bool> {
|
||||
{ eMobFlags.INVULNERABLE, true }
|
||||
})).Count == 1);
|
||||
|
||||
Assert.IsTrue(mobman.FindMobs(new MobConditionFlags(
|
||||
new Dictionary<eMobFlags, bool> {
|
||||
{ eMobFlags.PLAYER, true }
|
||||
})).Count == 0);
|
||||
|
||||
Assert.IsTrue(mobman.FindMobs(new MobConditionFlags(
|
||||
new Dictionary<eMobFlags, bool> {
|
||||
{ eMobFlags.PLAYER, false }
|
||||
})).Count == 3);
|
||||
Assert.IsTrue(mobman.Mobs.Count(x => x.HasFlag(eMobFlags.ENEMY)) == 2);
|
||||
Assert.IsTrue(mobman.Mobs.Count(x => x.HasFlag(eMobFlags.INVULNERABLE)) == 1);
|
||||
Assert.IsTrue(mobman.Mobs.Count(x => x.HasFlag(eMobFlags.PLAYER)) == 0);
|
||||
Assert.IsTrue(mobman.Mobs.Count(x => !x.HasFlag(eMobFlags.PLAYER)) == 3);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
@ -54,19 +37,21 @@ namespace OpenDiablo2.Core.UT
|
||||
{
|
||||
MobManager mobman = new MobManager();
|
||||
MobState mob1 = new MobState("test1", mobman.GetNextAvailableMobId(), 1, 100, 0, 0);
|
||||
MobState mob2 = new MobState("test2", mobman.GetNextAvailableMobId(), 1, 100, 10, 10);
|
||||
MobState mob3 = new MobState("test3", mobman.GetNextAvailableMobId(), 1, 100, 3, 1);
|
||||
mob1.AddFlag(eMobFlags.ENEMY);
|
||||
mobman.AddMob(mob1);
|
||||
|
||||
MobState mob2 = new MobState("test2", mobman.GetNextAvailableMobId(), 1, 100, 10, 10);
|
||||
mob2.AddFlag(eMobFlags.ENEMY);
|
||||
mob2.AddFlag(eMobFlags.INVULNERABLE);
|
||||
mobman.AddMob(mob1);
|
||||
mobman.AddMob(mob2);
|
||||
|
||||
MobState mob3 = new MobState("test3", mobman.GetNextAvailableMobId(), 1, 100, 3, 1);
|
||||
mobman.AddMob(mob3);
|
||||
|
||||
Assert.IsTrue(mobman.FindMobsInRadius(0, 0, 1, null).Count == 1);
|
||||
Assert.IsTrue(mobman.FindMobsInRadius(0, 0, 7, null).Count == 2);
|
||||
Assert.IsTrue(mobman.FindMobsInRadius(0, 0, 20, null).Count == 3);
|
||||
Assert.IsTrue(mobman.FindMobsInRadius(10, 10, 1, null).Count == 1);
|
||||
Assert.IsTrue(mobman.Mobs.FindInRadius(0, 0, 1).Count() == 1);
|
||||
Assert.IsTrue(mobman.Mobs.FindInRadius(0, 0, 7).Count() == 2);
|
||||
Assert.IsTrue(mobman.Mobs.FindInRadius(0, 0, 20).Count() == 3);
|
||||
Assert.IsTrue(mobman.Mobs.FindInRadius(10, 10, 1).Count() == 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
using Autofac;
|
||||
using OpenDiablo2.Common.Interfaces;
|
||||
using OpenDiablo2.Common.Interfaces.Mobs;
|
||||
using OpenDiablo2.Core.GameState_;
|
||||
using OpenDiablo2.Core.Map_Engine;
|
||||
using OpenDiablo2.Core.UI;
|
||||
@ -27,6 +28,8 @@ namespace OpenDiablo2.Core
|
||||
builder.RegisterType<ResourceManager>().As<IResourceManager>().SingleInstance();
|
||||
builder.RegisterType<TextDictionary>().As<ITextDictionary>().SingleInstance();
|
||||
builder.RegisterType<TextBox>().As<ITextBox>().InstancePerDependency();
|
||||
|
||||
builder.RegisterType<MobManager>().As<IMobManager>().SingleInstance(); // TODO: This needs to have client and server versions...
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,5 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Drawing;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
|
@ -4,6 +4,7 @@ using System.Drawing;
|
||||
using System.Linq;
|
||||
using OpenDiablo2.Common.Enums;
|
||||
using OpenDiablo2.Common.Interfaces;
|
||||
using OpenDiablo2.Common.Interfaces.MessageBus;
|
||||
using OpenDiablo2.Common.Models;
|
||||
using OpenDiablo2.Core.Map_Engine;
|
||||
|
||||
@ -21,7 +22,6 @@ namespace OpenDiablo2.Core.GameState_
|
||||
private readonly Func<IMapEngine> getMapEngine;
|
||||
private readonly Func<eSessionType, ISessionManager> getSessionManager;
|
||||
|
||||
private Guid playerId;
|
||||
private float animationTime = 0f;
|
||||
private List<MapInfo> mapInfo;
|
||||
private List<MapCellInfo> mapDataLookup = new List<MapCellInfo>();
|
||||
@ -30,6 +30,7 @@ namespace OpenDiablo2.Core.GameState_
|
||||
public int Act { get; private set; }
|
||||
public string MapName { get; private set; }
|
||||
public Palette CurrentPalette => paletteProvider.PaletteTable[$"ACT{Act}"];
|
||||
public IEnumerable<PlayerLocationDetails> PlayerLocationDetails { get; private set; } = new List<PlayerLocationDetails>();
|
||||
|
||||
public bool ShowInventoryPanel { get; set; } = false;
|
||||
public bool ShowCharacterPanel { get; set; } = false;
|
||||
@ -64,19 +65,20 @@ namespace OpenDiablo2.Core.GameState_
|
||||
sessionManager.Initialize();
|
||||
|
||||
sessionManager.OnSetSeed += OnSetSeedEvent;
|
||||
sessionManager.OnLocatePlayers += OnLocatePlayers;
|
||||
|
||||
mapInfo = new List<MapInfo>();
|
||||
sceneManager.ChangeScene("Game");
|
||||
|
||||
sessionManager.JoinGame(characterName, (id) =>
|
||||
{
|
||||
log.Info("hoo");
|
||||
playerId = id;
|
||||
}); // TODO: we need more attributes...
|
||||
log.Info("woo");
|
||||
sessionManager.JoinGame(characterName, hero);
|
||||
}
|
||||
|
||||
private void OnSetSeedEvent(object sender, int seed)
|
||||
private void OnLocatePlayers(int clientHash, IEnumerable<PlayerLocationDetails> playerLocationDetails)
|
||||
{
|
||||
PlayerLocationDetails = playerLocationDetails;
|
||||
}
|
||||
|
||||
private void OnSetSeedEvent(int clientHash, int seed)
|
||||
{
|
||||
log.Info($"Setting seed to {seed}");
|
||||
this.Seed = seed;
|
||||
@ -224,15 +226,7 @@ namespace OpenDiablo2.Core.GameState_
|
||||
return ShowCharacterPanel;
|
||||
}
|
||||
|
||||
|
||||
private MapCellInfo GetMapCellInfo(
|
||||
MapInfo map,
|
||||
int cellX,
|
||||
int cellY,
|
||||
MPQDS1TileProps props,
|
||||
eRenderCellType cellType,
|
||||
MPQDS1WallOrientationTileProps wallOrientations = null
|
||||
)
|
||||
private MapCellInfo GetMapCellInfo(MapInfo map, int cellX, int cellY, MPQDS1TileProps props, eRenderCellType cellType, MPQDS1WallOrientationTileProps wallOrientations = null)
|
||||
{
|
||||
if (!map.CellInfo.ContainsKey(cellType))
|
||||
{
|
||||
|
@ -1,20 +1,21 @@
|
||||
using OpenDiablo2.Common.Enums;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using OpenDiablo2.Common.Interfaces.Mobs;
|
||||
using OpenDiablo2.Common.Models.Mobs;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace OpenDiablo2.Core.GameState_
|
||||
{
|
||||
public class MobManager : IMobManager
|
||||
{
|
||||
private List<MobState> Mobs = new List<MobState>(); // all mobs (including players!)
|
||||
private List<PlayerState> Players = new List<PlayerState>();
|
||||
private List<EnemyState> Enemies = new List<EnemyState>();
|
||||
private List<int> IdsUsed = new List<int>();
|
||||
public HashSet<MobState> Mobs { get; private set; } = new HashSet<MobState>(); // all mobs (including players!)
|
||||
public HashSet<PlayerState> Players { get; private set; } = new HashSet<PlayerState>();
|
||||
public HashSet<EnemyState> Enemies { get; private set;} = new HashSet<EnemyState>();
|
||||
|
||||
IEnumerable<MobState> IMobManager.Mobs => Mobs;
|
||||
IEnumerable<PlayerState> IMobManager.Players => Players;
|
||||
IEnumerable<EnemyState> IMobManager.Enemies => Enemies;
|
||||
|
||||
private HashSet<int> IdsUsed = new HashSet<int>();
|
||||
|
||||
#region Player Controls
|
||||
public void AddPlayer(PlayerState player)
|
||||
@ -33,22 +34,9 @@ namespace OpenDiablo2.Core.GameState_
|
||||
public void AddMob(MobState mob)
|
||||
{
|
||||
Mobs.Add(mob);
|
||||
// add id to idsused in order
|
||||
int i = 0;
|
||||
while(i < IdsUsed.Count)
|
||||
{
|
||||
if(IdsUsed[i] > mob.Id)
|
||||
{
|
||||
IdsUsed.Insert(i, mob.Id);
|
||||
break;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
if(i == IdsUsed.Count)
|
||||
{
|
||||
// didn't get added
|
||||
IdsUsed.Add(mob.Id);
|
||||
}
|
||||
if (IdsUsed.Contains(mob.Id))
|
||||
throw new ApplicationException("Tried to insert an existing mob id!");
|
||||
IdsUsed.Add(mob.Id);
|
||||
}
|
||||
public void RemoveMob(MobState mob)
|
||||
{
|
||||
@ -57,16 +45,11 @@ namespace OpenDiablo2.Core.GameState_
|
||||
}
|
||||
public int GetNextAvailableMobId()
|
||||
{
|
||||
int i = 0;
|
||||
while(i < IdsUsed.Count)
|
||||
{
|
||||
if(IdsUsed[i] != i)
|
||||
{
|
||||
for (var i = 1; i < int.MaxValue; i++)
|
||||
if (!IdsUsed.Contains(i))
|
||||
return i;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
return IdsUsed.Count;
|
||||
|
||||
throw new ApplicationException("Ran out of IDs. How did this even happen?!");
|
||||
}
|
||||
#endregion Mob Controls
|
||||
|
||||
@ -83,59 +66,5 @@ namespace OpenDiablo2.Core.GameState_
|
||||
}
|
||||
#endregion Enemy Controls
|
||||
|
||||
#region Searching and Filtering
|
||||
public List<MobState> FilterMobs(IEnumerable<MobState> mobs, IMobCondition condition)
|
||||
{
|
||||
// note: if condition is null, returns full list
|
||||
List<MobState> filtered = new List<MobState>();
|
||||
foreach(MobState mob in mobs)
|
||||
{
|
||||
if (condition == null || condition.Evaluate(mob))
|
||||
{
|
||||
filtered.Add(mob);
|
||||
}
|
||||
}
|
||||
return filtered;
|
||||
}
|
||||
|
||||
public List<MobState> FindMobs(IMobCondition condition)
|
||||
{
|
||||
return FilterMobs(Mobs, condition);
|
||||
}
|
||||
public List<MobState> FindEnemies(IMobCondition condition)
|
||||
{
|
||||
return FilterMobs(Enemies, condition);
|
||||
}
|
||||
public List<MobState> FindPlayers(IMobCondition condition)
|
||||
{
|
||||
return FilterMobs(Players, condition);
|
||||
}
|
||||
|
||||
public List<MobState> FindInRadius(IEnumerable<MobState> mobs, float centerx, float centery, float radius)
|
||||
{
|
||||
List<MobState> filtered = new List<MobState>();
|
||||
foreach(MobState mob in mobs)
|
||||
{
|
||||
if(mob.GetDistance(centerx, centery) <= radius)
|
||||
{
|
||||
filtered.Add(mob);
|
||||
}
|
||||
}
|
||||
return filtered;
|
||||
}
|
||||
|
||||
public List<MobState> FindMobsInRadius(float centerx, float centery, float radius, IMobCondition condition)
|
||||
{
|
||||
return FilterMobs(FindInRadius(Mobs, centerx, centery, radius), condition);
|
||||
}
|
||||
public List<MobState> FindEnemiesInRadius(float centerx, float centery, float radius, IMobCondition condition)
|
||||
{
|
||||
return FilterMobs(FindInRadius(Enemies, centerx, centery, radius), condition);
|
||||
}
|
||||
public List<MobState> FindPlayersInRadius(float centerx, float centery, float radius, IMobCondition condition)
|
||||
{
|
||||
return FilterMobs(FindInRadius(Players, centerx, centery, radius), condition);
|
||||
}
|
||||
#endregion Searching and Filtering
|
||||
}
|
||||
}
|
||||
|
@ -12,6 +12,8 @@ namespace OpenDiablo2.Core.Map_Engine
|
||||
private readonly IRenderWindow renderWindow;
|
||||
private readonly IResourceManager resourceManager;
|
||||
|
||||
public int FocusedMobId { get; set; } = -1;
|
||||
|
||||
private PointF cameraLocation = new PointF();
|
||||
public PointF CameraLocation
|
||||
{
|
||||
|
18
OpenDiablo2.GameServer/AutofacModule.cs
Normal file
18
OpenDiablo2.GameServer/AutofacModule.cs
Normal file
@ -0,0 +1,18 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Autofac;
|
||||
using OpenDiablo2.Common.Interfaces;
|
||||
|
||||
namespace OpenDiablo2.GameServer_
|
||||
{
|
||||
public sealed class AutofacModule : Module
|
||||
{
|
||||
protected override void Load(ContainerBuilder builder)
|
||||
{
|
||||
builder.RegisterType<GameServer>().As<IGameServer>().SingleInstance();
|
||||
}
|
||||
}
|
||||
}
|
43
OpenDiablo2.GameServer/GameServer.cs
Normal file
43
OpenDiablo2.GameServer/GameServer.cs
Normal file
@ -0,0 +1,43 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using OpenDiablo2.Common.Enums;
|
||||
using OpenDiablo2.Common.Interfaces;
|
||||
using OpenDiablo2.Common.Interfaces.Mobs;
|
||||
using OpenDiablo2.Common.Models.Mobs;
|
||||
|
||||
namespace OpenDiablo2.GameServer_
|
||||
{
|
||||
public sealed class GameServer : IGameServer
|
||||
{
|
||||
private static readonly log4net.ILog log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
|
||||
|
||||
private readonly IMobManager mobManager;
|
||||
|
||||
public int Seed { get; private set; }
|
||||
public IEnumerable<PlayerState> Players => mobManager.Players;
|
||||
|
||||
public GameServer(IMobManager mobManager)
|
||||
{
|
||||
this.mobManager = mobManager;
|
||||
}
|
||||
|
||||
public void InitializeNewGame()
|
||||
{
|
||||
log.Info("Initializing a new game");
|
||||
Seed = (new Random()).Next();
|
||||
}
|
||||
|
||||
public int SpawnNewPlayer(int clientHash, string playerName, eHero heroType)
|
||||
{
|
||||
var newPlayer = new PlayerState(clientHash, playerName, mobManager.GetNextAvailableMobId(), 1, 20.0f, 20.0f, 10, 10, 10, 10, 0, heroType,
|
||||
new HeroTypeConfig(10, 10, 10, 50, 50, 50, 10, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1), new LevelExperienceConfig(new List<int>() { 100 }));
|
||||
|
||||
mobManager.AddPlayer(newPlayer);
|
||||
return newPlayer.Id;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
65
OpenDiablo2.GameServer/OpenDiablo2.GameServer.csproj
Normal file
65
OpenDiablo2.GameServer/OpenDiablo2.GameServer.csproj
Normal file
@ -0,0 +1,65 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProjectGuid>{C29A84E8-E708-4BE2-9946-202899B68E19}</ProjectGuid>
|
||||
<OutputType>Library</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>OpenDiablo2.GameServer</RootNamespace>
|
||||
<AssemblyName>OpenDiablo2.GameServer</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<Deterministic>true</Deterministic>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<OutputPath>bin\x64\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<DebugType>full</DebugType>
|
||||
<PlatformTarget>x64</PlatformTarget>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
|
||||
<OutputPath>bin\x64\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<Optimize>true</Optimize>
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<PlatformTarget>x64</PlatformTarget>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="Autofac, Version=4.8.1.0, Culture=neutral, PublicKeyToken=17863af14b0044da, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Autofac.4.8.1\lib\net45\Autofac.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="log4net, Version=2.0.8.0, Culture=neutral, PublicKeyToken=669e0ddf0bb1aa2a, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\log4net.2.0.8\lib\net45-full\log4net.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.Xml.Linq" />
|
||||
<Reference Include="System.Data.DataSetExtensions" />
|
||||
<Reference Include="Microsoft.CSharp" />
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.Net.Http" />
|
||||
<Reference Include="System.Xml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="AutofacModule.cs" />
|
||||
<Compile Include="GameServer.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="packages.config" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\OpenDiablo2.Common\OpenDiablo2.Common.csproj">
|
||||
<Project>{b743160e-a0bb-45dc-9998-967a85e50562}</Project>
|
||||
<Name>OpenDiablo2.Common</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
</Project>
|
36
OpenDiablo2.GameServer/Properties/AssemblyInfo.cs
Normal file
36
OpenDiablo2.GameServer/Properties/AssemblyInfo.cs
Normal file
@ -0,0 +1,36 @@
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
// General Information about an assembly is controlled through the following
|
||||
// set of attributes. Change these attribute values to modify the information
|
||||
// associated with an assembly.
|
||||
[assembly: AssemblyTitle("OpenDiablo2.GameServer")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("OpenDiablo2.GameServer")]
|
||||
[assembly: AssemblyCopyright("Copyright © 2018")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
// Setting ComVisible to false makes the types in this assembly not visible
|
||||
// to COM components. If you need to access a type in this assembly from
|
||||
// COM, set the ComVisible attribute to true on that type.
|
||||
[assembly: ComVisible(false)]
|
||||
|
||||
// The following GUID is for the ID of the typelib if this project is exposed to COM
|
||||
[assembly: Guid("c29a84e8-e708-4be2-9946-202899b68e19")]
|
||||
|
||||
// Version information for an assembly consists of the following four values:
|
||||
//
|
||||
// Major Version
|
||||
// Minor Version
|
||||
// Build Number
|
||||
// Revision
|
||||
//
|
||||
// You can specify all the values or you can default the Build and Revision Numbers
|
||||
// by using the '*' as shown below:
|
||||
// [assembly: AssemblyVersion("1.0.*")]
|
||||
[assembly: AssemblyVersion("1.0.0.0")]
|
||||
[assembly: AssemblyFileVersion("1.0.0.0")]
|
5
OpenDiablo2.GameServer/packages.config
Normal file
5
OpenDiablo2.GameServer/packages.config
Normal file
@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="Autofac" version="4.8.1" targetFramework="net461" />
|
||||
<package id="log4net" version="2.0.8" targetFramework="net461" />
|
||||
</packages>
|
@ -5,18 +5,19 @@ using OpenDiablo2.Common.Attributes;
|
||||
using OpenDiablo2.Common.Enums;
|
||||
using OpenDiablo2.Common.Interfaces;
|
||||
|
||||
namespace OpenDiablo2.ServiceBus.Message_Frames
|
||||
namespace OpenDiablo2.ServiceBus.Message_Frames.Client
|
||||
{
|
||||
[MessageFrame(eMessageFrameType.JoinGame)]
|
||||
public sealed class MFJoinGame : IMessageFrame
|
||||
{
|
||||
public Guid PlayerId { get; set; }
|
||||
public string PlayerName { get; set; }
|
||||
public eHero HeroType { get; set; }
|
||||
|
||||
public byte[] Data
|
||||
{
|
||||
get
|
||||
{
|
||||
return PlayerId.ToByteArray()
|
||||
return new byte[] { (byte)HeroType }
|
||||
.Concat(BitConverter.GetBytes((UInt16)PlayerName.Length))
|
||||
.Concat(Encoding.UTF8.GetBytes(PlayerName))
|
||||
.ToArray();
|
||||
@ -24,10 +25,9 @@ namespace OpenDiablo2.ServiceBus.Message_Frames
|
||||
|
||||
set
|
||||
{
|
||||
|
||||
PlayerId = new Guid(value.Take(16).ToArray());
|
||||
var playerNameLen = BitConverter.ToUInt16(value, 16);
|
||||
PlayerName = Encoding.UTF8.GetString(value, 18, value.Length - 18);
|
||||
HeroType = (eHero)value[0];
|
||||
var playerNameLen = BitConverter.ToUInt16(value, 1);
|
||||
PlayerName = Encoding.UTF8.GetString(value, 3, value.Length - 3);
|
||||
|
||||
if (PlayerName.Length != playerNameLen)
|
||||
throw new ApplicationException("Invalid player length!");
|
||||
@ -35,15 +35,15 @@ namespace OpenDiablo2.ServiceBus.Message_Frames
|
||||
}
|
||||
|
||||
public MFJoinGame() { }
|
||||
public MFJoinGame(string playerName)
|
||||
public MFJoinGame(string playerName, eHero heroType)
|
||||
{
|
||||
PlayerId = Guid.NewGuid();
|
||||
PlayerName = playerName;
|
||||
HeroType = heroType;
|
||||
}
|
||||
|
||||
public void Process(object sender, ISessionEventProvider sessionEventProvider)
|
||||
public void Process(int clientHash, ISessionEventProvider sessionEventProvider)
|
||||
{
|
||||
sessionEventProvider.OnJoinGame(sender, PlayerId, PlayerName);
|
||||
sessionEventProvider.OnJoinGame(clientHash, HeroType, PlayerName);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,49 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using OpenDiablo2.Common.Attributes;
|
||||
using OpenDiablo2.Common.Enums;
|
||||
using OpenDiablo2.Common.Interfaces;
|
||||
using OpenDiablo2.Common.Interfaces.MessageBus;
|
||||
|
||||
namespace OpenDiablo2.ServiceBus.Message_Frames.Server
|
||||
{
|
||||
[MessageFrame(eMessageFrameType.LocatePlayers)]
|
||||
public sealed class MFLocatePlayers : IMessageFrame
|
||||
{
|
||||
public IEnumerable<PlayerLocationDetails> LocationDetails { get; set; }
|
||||
|
||||
public byte[] Data
|
||||
{
|
||||
get
|
||||
{
|
||||
var result = new List<byte>();
|
||||
result.AddRange(BitConverter.GetBytes((UInt16)LocationDetails.Count()));
|
||||
result.AddRange(LocationDetails.SelectMany(x => x.GetBytes()));
|
||||
return result.ToArray();
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
var count = BitConverter.ToUInt16(value, 0);
|
||||
var result = new List<PlayerLocationDetails>();
|
||||
|
||||
for(var i = 0; i < count; i++)
|
||||
{
|
||||
result.Add(PlayerLocationDetails.FromBytes(value, 2 + (i * PlayerLocationDetails.SizeInBytes)));
|
||||
}
|
||||
|
||||
LocationDetails = result;
|
||||
}
|
||||
}
|
||||
|
||||
public MFLocatePlayers() { }
|
||||
public MFLocatePlayers(IEnumerable<PlayerLocationDetails> locationDetails)
|
||||
{
|
||||
this.LocationDetails = locationDetails;
|
||||
}
|
||||
|
||||
public void Process(int clientHash, ISessionEventProvider sessionEventProvider)
|
||||
=> sessionEventProvider.OnLocatePlayers(clientHash, LocationDetails);
|
||||
}
|
||||
}
|
@ -3,7 +3,7 @@ using OpenDiablo2.Common.Attributes;
|
||||
using OpenDiablo2.Common.Enums;
|
||||
using OpenDiablo2.Common.Interfaces;
|
||||
|
||||
namespace OpenDiablo2.ServiceBus.Message_Frames
|
||||
namespace OpenDiablo2.ServiceBus.Message_Frames.Server
|
||||
{
|
||||
[MessageFrame(eMessageFrameType.SetSeed)]
|
||||
public sealed class MFSetSeed : IMessageFrame
|
||||
@ -19,7 +19,6 @@ namespace OpenDiablo2.ServiceBus.Message_Frames
|
||||
|
||||
public MFSetSeed()
|
||||
{
|
||||
Seed = (new Random()).Next();
|
||||
}
|
||||
|
||||
public MFSetSeed(int seed)
|
||||
@ -27,9 +26,8 @@ namespace OpenDiablo2.ServiceBus.Message_Frames
|
||||
Seed = seed;
|
||||
}
|
||||
|
||||
public void Process(object sender, ISessionEventProvider sessionEventProvider)
|
||||
{
|
||||
sessionEventProvider.OnSetSeed?.Invoke(sender, Seed);
|
||||
}
|
||||
public void Process(int clientHash, ISessionEventProvider sessionEventProvider)
|
||||
=> sessionEventProvider.OnSetSeed?.Invoke(clientHash, Seed);
|
||||
|
||||
}
|
||||
}
|
@ -21,6 +21,7 @@
|
||||
<PlatformTarget>x64</PlatformTarget>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
|
||||
<AllowUnsafeBlocks>false</AllowUnsafeBlocks>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
|
||||
<OutputPath>bin\x64\Release\</OutputPath>
|
||||
@ -30,6 +31,7 @@
|
||||
<PlatformTarget>x64</PlatformTarget>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
|
||||
<AllowUnsafeBlocks>false</AllowUnsafeBlocks>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="AsyncIO, Version=0.1.61.0, Culture=neutral, PublicKeyToken=44a94435bd6f33f8, processorArchitecture=MSIL">
|
||||
@ -56,8 +58,9 @@
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="AutofacModule.cs" />
|
||||
<Compile Include="Message Frames\MFJoinGame.cs" />
|
||||
<Compile Include="Message Frames\MFSetSeed.cs" />
|
||||
<Compile Include="Message Frames\Client\MFJoinGame.cs" />
|
||||
<Compile Include="Message Frames\Server\MFLocatePlayers.cs" />
|
||||
<Compile Include="Message Frames\Server\MFSetSeed.cs" />
|
||||
<Compile Include="SessionManager.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="SessionServer.cs" />
|
||||
|
@ -7,7 +7,8 @@ using NetMQ.Sockets;
|
||||
using OpenDiablo2.Common.Attributes;
|
||||
using OpenDiablo2.Common.Enums;
|
||||
using OpenDiablo2.Common.Interfaces;
|
||||
using OpenDiablo2.ServiceBus.Message_Frames;
|
||||
using OpenDiablo2.ServiceBus.Message_Frames.Client;
|
||||
using OpenDiablo2.ServiceBus.Message_Frames.Server;
|
||||
|
||||
namespace OpenDiablo2.ServiceBus
|
||||
{
|
||||
@ -23,11 +24,12 @@ namespace OpenDiablo2.ServiceBus
|
||||
private RequestSocket requestSocket;
|
||||
private AutoResetEvent resetEvent = new AutoResetEvent(false);
|
||||
private ISessionServer sessionServer;
|
||||
private Guid playerId;
|
||||
public Guid PlayerId { get; private set; }
|
||||
private bool running = false;
|
||||
|
||||
public OnSetSeedEvent OnSetSeed { get; set; }
|
||||
public OnJoinGameEvent OnJoinGame { get; set; }
|
||||
public OnLocatePlayersEvent OnLocatePlayers { get; set; }
|
||||
|
||||
public SessionManager(
|
||||
eSessionType sessionType,
|
||||
@ -71,15 +73,7 @@ namespace OpenDiablo2.ServiceBus
|
||||
default:
|
||||
throw new ApplicationException("This session type is currently unsupported.");
|
||||
}
|
||||
|
||||
|
||||
//var bytes = message.First().ToByteArray();
|
||||
//var frameType = (eMessageFrameType)bytes[0];
|
||||
//var frameData = bytes.Skip(1).ToArray(); // TODO: Can we maybe use pointers? This seems wasteful
|
||||
//var messageFrame = getMessageFrame(frameType);
|
||||
//messageFrame.Data = frameData;
|
||||
//messageFrame.Process(socket, this);
|
||||
|
||||
|
||||
running = true;
|
||||
resetEvent.WaitOne();
|
||||
running = false;
|
||||
@ -124,22 +118,17 @@ namespace OpenDiablo2.ServiceBus
|
||||
messageFrame.Data = frameData;
|
||||
lock (getGameState().ThreadLocker)
|
||||
{
|
||||
messageFrame.Process(requestSocket, this);
|
||||
messageFrame.Process(requestSocket.GetHashCode(), this);
|
||||
}
|
||||
}
|
||||
|
||||
public void JoinGame(string playerName, Action<Guid> callback)
|
||||
public void JoinGame(string playerName, eHero heroType)
|
||||
{
|
||||
Task.Run(() =>
|
||||
{
|
||||
var mf = new MFJoinGame(playerName);
|
||||
playerId = mf.PlayerId;
|
||||
Send(mf);
|
||||
Send(new MFJoinGame(playerName, heroType));
|
||||
ProcessMessageFrame<MFSetSeed>();
|
||||
lock (getGameState().ThreadLocker)
|
||||
{
|
||||
callback(playerId);
|
||||
}
|
||||
ProcessMessageFrame<MFLocatePlayers>();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -7,7 +7,8 @@ using NetMQ.Sockets;
|
||||
using OpenDiablo2.Common.Attributes;
|
||||
using OpenDiablo2.Common.Enums;
|
||||
using OpenDiablo2.Common.Interfaces;
|
||||
using OpenDiablo2.ServiceBus.Message_Frames;
|
||||
using OpenDiablo2.Common.Interfaces.MessageBus;
|
||||
using OpenDiablo2.ServiceBus.Message_Frames.Server;
|
||||
|
||||
namespace OpenDiablo2.ServiceBus
|
||||
{
|
||||
@ -16,26 +17,34 @@ namespace OpenDiablo2.ServiceBus
|
||||
private static readonly log4net.ILog log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
|
||||
|
||||
private readonly eSessionType sessionType;
|
||||
private readonly IGameServer gameServer;
|
||||
private readonly Func<eMessageFrameType, IMessageFrame> getMessageFrame;
|
||||
|
||||
private AutoResetEvent resetEvent = new AutoResetEvent(false);
|
||||
public AutoResetEvent WaitServerStartEvent { get; set; } = new AutoResetEvent(false);
|
||||
|
||||
private int gameSeed;
|
||||
private bool running = false;
|
||||
private ResponseSocket responseSocket;
|
||||
|
||||
public OnSetSeedEvent OnSetSeed { get; set; }
|
||||
public OnJoinGameEvent OnJoinGame { get; set; }
|
||||
public OnLocatePlayersEvent OnLocatePlayers { get; set; }
|
||||
|
||||
public SessionServer(eSessionType sessionType, Func<eMessageFrameType, IMessageFrame> getMessageFrame)
|
||||
public SessionServer(
|
||||
eSessionType sessionType,
|
||||
IGameServer gameServer,
|
||||
Func<eMessageFrameType, IMessageFrame> getMessageFrame
|
||||
)
|
||||
{
|
||||
this.sessionType = sessionType;
|
||||
this.getMessageFrame = getMessageFrame;
|
||||
this.gameServer = gameServer;
|
||||
}
|
||||
|
||||
public void Start()
|
||||
{
|
||||
gameSeed = (new Random()).Next();
|
||||
// TODO: Loading existing games...
|
||||
gameServer.InitializeNewGame();
|
||||
|
||||
Task.Run(() => Serve());
|
||||
}
|
||||
|
||||
@ -64,7 +73,7 @@ namespace OpenDiablo2.ServiceBus
|
||||
var frameData = bytes.Skip(1).ToArray(); // TODO: Can we maybe use pointers? This seems wasteful
|
||||
var messageFrame = getMessageFrame(frameType);
|
||||
messageFrame.Data = frameData;
|
||||
messageFrame.Process(socket, this);
|
||||
messageFrame.Process(socket.GetHashCode(), this);
|
||||
});
|
||||
running = true;
|
||||
WaitServerStartEvent.Set();
|
||||
@ -89,16 +98,17 @@ namespace OpenDiablo2.ServiceBus
|
||||
Stop();
|
||||
}
|
||||
|
||||
private void Send(NetMQSocket target, IMessageFrame messageFrame)
|
||||
private void Send(IMessageFrame messageFrame, bool more = false)
|
||||
{
|
||||
var attr = messageFrame.GetType().GetCustomAttributes(true).First(x => typeof(MessageFrameAttribute).IsAssignableFrom(x.GetType())) as MessageFrameAttribute;
|
||||
responseSocket.SendFrame(new byte[] { (byte)attr.FrameType }.Concat(messageFrame.Data).ToArray());
|
||||
responseSocket.SendFrame(new byte[] { (byte)attr.FrameType }.Concat(messageFrame.Data).ToArray(), more);
|
||||
}
|
||||
|
||||
private void OnJoinGameHandler(object sender, Guid playerId, string playerName)
|
||||
private void OnJoinGameHandler(int clientHash, eHero heroType, string playerName)
|
||||
{
|
||||
// TODO: Try to make this less stupid
|
||||
Send(sender as NetMQSocket, new MFSetSeed(gameSeed));
|
||||
gameServer.SpawnNewPlayer(clientHash, playerName, heroType);
|
||||
Send(new MFSetSeed(gameServer.Seed), true);
|
||||
Send(new MFLocatePlayers(gameServer.Players.Select(x => x.ToPlayerLocationDetails())));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -25,6 +25,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{1FAD6E2F
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OpenDiablo2.ServiceBus", "OpenDiablo2.ServiceBus\OpenDiablo2.ServiceBus.csproj", "{D3F0F44F-2AB4-4342-A684-53193032A621}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OpenDiablo2.GameServer", "OpenDiablo2.GameServer\OpenDiablo2.GameServer.csproj", "{C29A84E8-E708-4BE2-9946-202899B68E19}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|x64 = Debug|x64
|
||||
@ -67,6 +69,10 @@ Global
|
||||
{D3F0F44F-2AB4-4342-A684-53193032A621}.Debug|x64.Build.0 = Debug|x64
|
||||
{D3F0F44F-2AB4-4342-A684-53193032A621}.Release|x64.ActiveCfg = Release|x64
|
||||
{D3F0F44F-2AB4-4342-A684-53193032A621}.Release|x64.Build.0 = Release|x64
|
||||
{C29A84E8-E708-4BE2-9946-202899B68E19}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{C29A84E8-E708-4BE2-9946-202899B68E19}.Debug|x64.Build.0 = Debug|x64
|
||||
{C29A84E8-E708-4BE2-9946-202899B68E19}.Release|x64.ActiveCfg = Release|x64
|
||||
{C29A84E8-E708-4BE2-9946-202899B68E19}.Release|x64.Build.0 = Release|x64
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
|
@ -5,7 +5,7 @@
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProjectGuid>{2B0CF1AC-06DD-4322-AE8B-FF8A8C70A3CD}</ProjectGuid>
|
||||
<OutputType>Exe</OutputType>
|
||||
<OutputType>WinExe</OutputType>
|
||||
<RootNamespace>OpenDiablo2</RootNamespace>
|
||||
<AssemblyName>OpenDiablo2</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion>
|
||||
@ -99,6 +99,10 @@
|
||||
<Project>{8fc6bf7d-835a-47c1-a6b2-125495fa0900}</Project>
|
||||
<Name>OpenDiablo2.Core</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\OpenDiablo2.GameServer\OpenDiablo2.GameServer.csproj">
|
||||
<Project>{c29a84e8-e708-4be2-9946-202899b68e19}</Project>
|
||||
<Name>OpenDiablo2.GameServer</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\OpenDiablo2.Scenes\OpenDiablo2.Scenes.csproj">
|
||||
<Project>{05224fe7-293f-4184-b1d6-89f5171b60e0}</Project>
|
||||
<Name>OpenDiablo2.Scenes</Name>
|
||||
|
Loading…
x
Reference in New Issue
Block a user