mirror of
https://github.com/OpenDiablo2/OpenDiablo2
synced 2024-07-22 13:04:18 -04:00
Added caching. Code cleanup.
This commit is contained in:
parent
98bb55a8ea
commit
2bf53e351c
@ -18,7 +18,7 @@ namespace OpenDiablo2.Common.Interfaces
|
|||||||
MPQFont GetMPQFont(string resourcePath);
|
MPQFont GetMPQFont(string resourcePath);
|
||||||
MPQDS1 GetMPQDS1(string resourcePath, LevelPreset level, LevelDetail levelDetail, LevelType levelType);
|
MPQDS1 GetMPQDS1(string resourcePath, LevelPreset level, LevelDetail levelDetail, LevelType levelType);
|
||||||
MPQDT1 GetMPQDT1(string resourcePath);
|
MPQDT1 GetMPQDT1(string resourcePath);
|
||||||
Palette GetPalette(string paletteName);
|
Palette GetPalette(string paletteFile);
|
||||||
MPQCOF GetPlayerAnimation(eHero hero, eWeaponClass weaponClass, eMobMode mobMode);
|
MPQCOF GetPlayerAnimation(eHero hero, eWeaponClass weaponClass, eMobMode mobMode);
|
||||||
MPQDCC GetPlayerDCC(MPQCOF.COFLayer cofLayer, eArmorType armorType, Palette palette);
|
MPQDCC GetPlayerDCC(MPQCOF.COFLayer cofLayer, eArmorType armorType, Palette palette);
|
||||||
|
|
||||||
|
39
OpenDiablo2.Common/Interfaces/ICache.cs
Normal file
39
OpenDiablo2.Common/Interfaces/ICache.cs
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
/* OpenDiablo 2 - An open source re-implementation of Diablo 2 in C#
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Runtime.Caching;
|
||||||
|
|
||||||
|
namespace OpenDiablo2.Common.Interfaces
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Provides access to the cache system.
|
||||||
|
/// </summary>
|
||||||
|
public interface ICache
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Gets an item from the cache. If the item does not exist, the value factory will be executed to
|
||||||
|
/// generate the value.
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="T">The return type of the value</typeparam>
|
||||||
|
/// <param name="key">The name of the cache key, in the form of Type::X::Y::Z where
|
||||||
|
/// Type is the base type, and x/y/z are unique identifiers for the item.</param>
|
||||||
|
/// <param name="valueFactory">A function that returns the correct value if it does not already exist.</param>
|
||||||
|
/// <param name="cacheItemPolicy">Pass in a new policy to control how this item is handled. Typically you can leave this null.</param>
|
||||||
|
/// <returns>The item requested</returns>
|
||||||
|
T AddOrGetExisting<T>(string key, Func<T> valueFactory, CacheItemPolicy cacheItemPolicy = null);
|
||||||
|
}
|
||||||
|
}
|
@ -1,17 +1,31 @@
|
|||||||
using System;
|
/* OpenDiablo 2 - An open source re-implementation of Diablo 2 in C#
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Drawing;
|
using System.Drawing;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace OpenDiablo2.Common.Models
|
namespace OpenDiablo2.Common.Models
|
||||||
{
|
{
|
||||||
public sealed class MPQFont
|
public sealed class MPQFont
|
||||||
{
|
{
|
||||||
public ImageSet FontImageSet;
|
public ImageSet FontImageSet { get; internal set; }
|
||||||
public Dictionary<byte, Size> CharacterMetric = new Dictionary<byte, Size>();
|
public Dictionary<char, Size> CharacterMetric { get; internal set; } = new Dictionary<char, Size>();
|
||||||
|
|
||||||
public static MPQFont LoadFromStream(Stream fontStream, Stream tableStream)
|
public static MPQFont LoadFromStream(Stream fontStream, Stream tableStream)
|
||||||
{
|
{
|
||||||
@ -31,7 +45,7 @@ namespace OpenDiablo2.Common.Models
|
|||||||
br.ReadBytes(3);
|
br.ReadBytes(3);
|
||||||
var size = new Size(br.ReadByte(), br.ReadByte());
|
var size = new Size(br.ReadByte(), br.ReadByte());
|
||||||
br.ReadBytes(3);
|
br.ReadBytes(3);
|
||||||
var charCode = br.ReadByte();
|
var charCode = (char)br.ReadByte();
|
||||||
result.CharacterMetric[charCode] = size;
|
result.CharacterMetric[charCode] = size;
|
||||||
br.ReadBytes(5);
|
br.ReadBytes(5);
|
||||||
|
|
||||||
|
@ -45,6 +45,7 @@
|
|||||||
<Reference Include="System" />
|
<Reference Include="System" />
|
||||||
<Reference Include="System.Core" />
|
<Reference Include="System.Core" />
|
||||||
<Reference Include="System.Drawing" />
|
<Reference Include="System.Drawing" />
|
||||||
|
<Reference Include="System.Runtime.Caching" />
|
||||||
<Reference Include="System.Xml.Linq" />
|
<Reference Include="System.Xml.Linq" />
|
||||||
<Reference Include="System.Data.DataSetExtensions" />
|
<Reference Include="System.Data.DataSetExtensions" />
|
||||||
<Reference Include="Microsoft.CSharp" />
|
<Reference Include="Microsoft.CSharp" />
|
||||||
@ -80,6 +81,7 @@
|
|||||||
<Compile Include="Enums\Mobs\eMobFlags.cs" />
|
<Compile Include="Enums\Mobs\eMobFlags.cs" />
|
||||||
<Compile Include="Enums\Mobs\eStatModifierType.cs" />
|
<Compile Include="Enums\Mobs\eStatModifierType.cs" />
|
||||||
<Compile Include="Interfaces\Drawing\ICharacterRenderer.cs" />
|
<Compile Include="Interfaces\Drawing\ICharacterRenderer.cs" />
|
||||||
|
<Compile Include="Interfaces\ICache.cs" />
|
||||||
<Compile Include="Interfaces\IItemManager.cs" />
|
<Compile Include="Interfaces\IItemManager.cs" />
|
||||||
<Compile Include="Extensions\MobManagerExtensions.cs" />
|
<Compile Include="Extensions\MobManagerExtensions.cs" />
|
||||||
<Compile Include="Interfaces\IGameServer.cs" />
|
<Compile Include="Interfaces\IGameServer.cs" />
|
||||||
|
@ -1,6 +1,21 @@
|
|||||||
using Autofac;
|
/* OpenDiablo 2 - An open source re-implementation of Diablo 2 in C#
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
using Autofac;
|
||||||
using OpenDiablo2.Common.Interfaces;
|
using OpenDiablo2.Common.Interfaces;
|
||||||
using OpenDiablo2.Common.Interfaces.Drawing;
|
|
||||||
using OpenDiablo2.Common.Interfaces.Mobs;
|
using OpenDiablo2.Common.Interfaces.Mobs;
|
||||||
using OpenDiablo2.Core.GameState_;
|
using OpenDiablo2.Core.GameState_;
|
||||||
using OpenDiablo2.Core.Map_Engine;
|
using OpenDiablo2.Core.Map_Engine;
|
||||||
@ -16,6 +31,7 @@ namespace OpenDiablo2.Core
|
|||||||
{
|
{
|
||||||
log.Info("Configuring OpenDiablo2.Core service implementations.");
|
log.Info("Configuring OpenDiablo2.Core service implementations.");
|
||||||
|
|
||||||
|
builder.RegisterType<Cache>().As<ICache>().SingleInstance();
|
||||||
builder.RegisterType<Button>().As<IButton>().InstancePerDependency();
|
builder.RegisterType<Button>().As<IButton>().InstancePerDependency();
|
||||||
builder.RegisterType<EngineDataManager>().As<IEngineDataManager>().SingleInstance();
|
builder.RegisterType<EngineDataManager>().As<IEngineDataManager>().SingleInstance();
|
||||||
builder.RegisterType<ItemManager>().As<IItemManager>().SingleInstance();
|
builder.RegisterType<ItemManager>().As<IItemManager>().SingleInstance();
|
||||||
|
44
OpenDiablo2.Core/Cache.cs
Normal file
44
OpenDiablo2.Core/Cache.cs
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
/* OpenDiablo 2 - An open source re-implementation of Diablo 2 in C#
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Runtime.Caching;
|
||||||
|
using OpenDiablo2.Common.Interfaces;
|
||||||
|
|
||||||
|
namespace OpenDiablo2.Core
|
||||||
|
{
|
||||||
|
public sealed class Cache : ICache
|
||||||
|
{
|
||||||
|
private readonly static MemoryCache _cache = new MemoryCache("OpenDiablo2.Cache");
|
||||||
|
|
||||||
|
public Cache() { }
|
||||||
|
|
||||||
|
public T AddOrGetExisting<T>(string key, Func<T> valueFactory, CacheItemPolicy cacheItemPolicy = null)
|
||||||
|
{
|
||||||
|
var newValue = new Lazy<T>(valueFactory);
|
||||||
|
var oldValue = _cache.AddOrGetExisting(key, newValue, cacheItemPolicy ?? new CacheItemPolicy()) as Lazy<T>;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return (oldValue ?? newValue).Value;
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
_cache.Remove(key);
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -44,6 +44,7 @@
|
|||||||
<Reference Include="System" />
|
<Reference Include="System" />
|
||||||
<Reference Include="System.Core" />
|
<Reference Include="System.Core" />
|
||||||
<Reference Include="System.Drawing" />
|
<Reference Include="System.Drawing" />
|
||||||
|
<Reference Include="System.Runtime.Caching" />
|
||||||
<Reference Include="System.Xml.Linq" />
|
<Reference Include="System.Xml.Linq" />
|
||||||
<Reference Include="System.Data.DataSetExtensions" />
|
<Reference Include="System.Data.DataSetExtensions" />
|
||||||
<Reference Include="Microsoft.CSharp" />
|
<Reference Include="Microsoft.CSharp" />
|
||||||
@ -56,6 +57,7 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Compile Include="AutofacModule.cs" />
|
<Compile Include="AutofacModule.cs" />
|
||||||
|
<Compile Include="Cache.cs" />
|
||||||
<Compile Include="ItemManager.cs" />
|
<Compile Include="ItemManager.cs" />
|
||||||
<Compile Include="EngineDataManager.cs" />
|
<Compile Include="EngineDataManager.cs" />
|
||||||
<Compile Include="GameEngine.cs" />
|
<Compile Include="GameEngine.cs" />
|
||||||
|
@ -1,8 +1,21 @@
|
|||||||
using System;
|
/* OpenDiablo 2 - An open source re-implementation of Diablo 2 in C#
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using OpenDiablo2.Common;
|
using OpenDiablo2.Common;
|
||||||
using OpenDiablo2.Common.Enums;
|
using OpenDiablo2.Common.Enums;
|
||||||
using OpenDiablo2.Common.Interfaces;
|
using OpenDiablo2.Common.Interfaces;
|
||||||
@ -12,19 +25,15 @@ namespace OpenDiablo2.Core
|
|||||||
{
|
{
|
||||||
public sealed class ResourceManager : IResourceManager
|
public sealed class ResourceManager : IResourceManager
|
||||||
{
|
{
|
||||||
|
private readonly ICache cache;
|
||||||
private readonly IMPQProvider mpqProvider;
|
private readonly IMPQProvider mpqProvider;
|
||||||
private readonly IEngineDataManager engineDataManager;
|
private readonly IEngineDataManager engineDataManager;
|
||||||
|
|
||||||
private readonly Dictionary<string, ImageSet> ImageSets = new Dictionary<string, ImageSet>();
|
public Dictionary<string, List<AnimationData>> Animations { get; private set; }
|
||||||
private readonly Dictionary<string, MPQFont> MPQFonts = new Dictionary<string, MPQFont>();
|
|
||||||
private readonly Dictionary<string, Palette> Palettes = new Dictionary<string, Palette>();
|
|
||||||
private readonly Dictionary<string, MPQDT1> DTs = new Dictionary<string, MPQDT1>();
|
|
||||||
private readonly Dictionary<string, MPQCOF> PlayerCOFs = new Dictionary<string, MPQCOF>();
|
|
||||||
|
|
||||||
public Dictionary<string, List<AnimationData>> Animations { get; private set; } = new Dictionary<string, List<AnimationData>>();
|
public ResourceManager(ICache cache, IMPQProvider mpqProvider, IEngineDataManager engineDataManager)
|
||||||
|
|
||||||
public ResourceManager(IMPQProvider mpqProvider, IEngineDataManager engineDataManager)
|
|
||||||
{
|
{
|
||||||
|
this.cache = cache;
|
||||||
this.mpqProvider = mpqProvider;
|
this.mpqProvider = mpqProvider;
|
||||||
this.engineDataManager = engineDataManager;
|
this.engineDataManager = engineDataManager;
|
||||||
|
|
||||||
@ -32,64 +41,32 @@ namespace OpenDiablo2.Core
|
|||||||
}
|
}
|
||||||
|
|
||||||
public ImageSet GetImageSet(string resourcePath)
|
public ImageSet GetImageSet(string resourcePath)
|
||||||
{
|
=> cache.AddOrGetExisting($"ImageSet::{resourcePath}", () => ImageSet.LoadFromStream(mpqProvider.GetStream(resourcePath)));
|
||||||
if (!ImageSets.ContainsKey(resourcePath))
|
|
||||||
ImageSets[resourcePath] = ImageSet.LoadFromStream(mpqProvider.GetStream(resourcePath));
|
|
||||||
|
|
||||||
return ImageSets[resourcePath];
|
|
||||||
}
|
|
||||||
|
|
||||||
public MPQFont GetMPQFont(string resourcePath)
|
public MPQFont GetMPQFont(string resourcePath)
|
||||||
{
|
=> cache.AddOrGetExisting($"Font::{resourcePath}", () => MPQFont.LoadFromStream(mpqProvider.GetStream($"{resourcePath}.DC6"), mpqProvider.GetStream($"{resourcePath}.tbl")));
|
||||||
if (!MPQFonts.ContainsKey(resourcePath))
|
|
||||||
MPQFonts[resourcePath] = MPQFont.LoadFromStream(mpqProvider.GetStream($"{resourcePath}.DC6"), mpqProvider.GetStream($"{resourcePath}.tbl"));
|
|
||||||
|
|
||||||
return MPQFonts[resourcePath];
|
|
||||||
}
|
|
||||||
|
|
||||||
public MPQDS1 GetMPQDS1(string resourcePath, LevelPreset level, LevelDetail levelDetail, LevelType levelType)
|
public MPQDS1 GetMPQDS1(string resourcePath, LevelPreset level, LevelDetail levelDetail, LevelType levelType)
|
||||||
{
|
=> cache.AddOrGetExisting($"DS1::{resourcePath}::{level}::{levelDetail}::{levelType}", ()
|
||||||
var mapName = resourcePath.Replace("data\\global\\tiles\\", "").Replace("\\", "/");
|
=> new MPQDS1(mpqProvider.GetStream(resourcePath), level, levelDetail, levelType, engineDataManager, this) { MapFile = resourcePath });
|
||||||
return new MPQDS1(mpqProvider.GetStream(resourcePath), level, levelDetail, levelType, engineDataManager, this)
|
|
||||||
{
|
|
||||||
MapFile = resourcePath
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
public Palette GetPalette(string paletteFile)
|
public Palette GetPalette(string paletteFile)
|
||||||
{
|
=> cache.AddOrGetExisting($"Palette::{paletteFile}", () =>
|
||||||
if (!Palettes.ContainsKey(paletteFile))
|
|
||||||
{
|
{
|
||||||
var paletteNameParts = paletteFile.Split('\\');
|
var paletteNameParts = paletteFile.Split('\\');
|
||||||
var paletteName = paletteNameParts[paletteNameParts.Count() - 2];
|
var paletteName = paletteNameParts[paletteNameParts.Count() - 2];
|
||||||
Palettes[paletteFile] = Palette.LoadFromStream(mpqProvider.GetStream(paletteFile), paletteName);
|
return Palette.LoadFromStream(mpqProvider.GetStream(paletteFile), paletteName);
|
||||||
}
|
});
|
||||||
|
|
||||||
return Palettes[paletteFile];
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public MPQDT1 GetMPQDT1(string resourcePath)
|
public MPQDT1 GetMPQDT1(string resourcePath)
|
||||||
{
|
=> cache.AddOrGetExisting($"DT1::{resourcePath}", () => new MPQDT1(mpqProvider.GetStream(resourcePath)));
|
||||||
if (!DTs.ContainsKey(resourcePath))
|
|
||||||
DTs[resourcePath] = new MPQDT1(mpqProvider.GetStream(resourcePath));
|
|
||||||
|
|
||||||
return DTs[resourcePath];
|
|
||||||
}
|
|
||||||
|
|
||||||
public MPQCOF GetPlayerAnimation(eHero hero, eWeaponClass weaponClass, eMobMode mobMode)
|
public MPQCOF GetPlayerAnimation(eHero hero, eWeaponClass weaponClass, eMobMode mobMode)
|
||||||
|
=> cache.AddOrGetExisting($"COF::{hero}::{weaponClass}::{mobMode}", () =>
|
||||||
{
|
{
|
||||||
var key = $"{hero.ToToken()}{mobMode.ToToken()}{weaponClass.ToToken()}";
|
|
||||||
if (PlayerCOFs.ContainsKey(key))
|
|
||||||
return PlayerCOFs[key];
|
|
||||||
|
|
||||||
var path = $"{ResourcePaths.PlayerAnimationBase}\\{hero.ToToken()}\\COF\\{hero.ToToken()}{mobMode.ToToken()}{weaponClass.ToToken()}.cof";
|
var path = $"{ResourcePaths.PlayerAnimationBase}\\{hero.ToToken()}\\COF\\{hero.ToToken()}{mobMode.ToToken()}{weaponClass.ToToken()}.cof";
|
||||||
var result = MPQCOF.Load(mpqProvider.GetStream(path), Animations, hero, weaponClass, mobMode);
|
return MPQCOF.Load(mpqProvider.GetStream(path), Animations, hero, weaponClass, mobMode);
|
||||||
PlayerCOFs[key] = result;
|
});
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
public MPQDCC GetPlayerDCC(MPQCOF.COFLayer cofLayer, eArmorType armorType, Palette palette)
|
public MPQDCC GetPlayerDCC(MPQCOF.COFLayer cofLayer, eArmorType armorType, Palette palette)
|
||||||
{
|
{
|
||||||
@ -107,5 +84,24 @@ namespace OpenDiablo2.Core
|
|||||||
var result = new MPQDCC(binaryData, palette);
|
var result = new MPQDCC(binaryData, palette);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
=> cache.AddOrGetExisting($"DCC::{cofLayer}::{armorType}::{palette.Name}", () =>
|
||||||
|
{
|
||||||
|
byte[] binaryData;
|
||||||
|
|
||||||
|
using (var stream = mpqProvider.GetStream(cofLayer.GetDCCPath(armorType)))
|
||||||
|
{
|
||||||
|
if (stream == null)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
binaryData = new byte[stream.Length];
|
||||||
|
stream.Read(binaryData, 0, (int)stream.Length);
|
||||||
|
}
|
||||||
|
var result = new MPQDCC(binaryData, palette);
|
||||||
|
return result;
|
||||||
|
});
|
||||||
|
/*
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -59,7 +59,6 @@ namespace OpenDiablo2.SDL2_
|
|||||||
private readonly IPaletteProvider paletteProvider;
|
private readonly IPaletteProvider paletteProvider;
|
||||||
|
|
||||||
private MPQCOF animationData;
|
private MPQCOF animationData;
|
||||||
private MPQDCC[] layerData;
|
|
||||||
|
|
||||||
static readonly byte[] directionConversion = new byte[] { 3, 15, 4, 8, 0, 9, 5, 10, 1, 11, 6, 12, 2, 13, 7, 14 };
|
static readonly byte[] directionConversion = new byte[] { 3, 15, 4, 8, 0, 9, 5, 10, 1, 11, 6, 12, 2, 13, 7, 14 };
|
||||||
|
|
||||||
@ -138,19 +137,10 @@ namespace OpenDiablo2.SDL2_
|
|||||||
throw new ApplicationException("Could not locate animation for the character!");
|
throw new ApplicationException("Could not locate animation for the character!");
|
||||||
|
|
||||||
var palette = paletteProvider.PaletteTable["Units"];
|
var palette = paletteProvider.PaletteTable["Units"];
|
||||||
var data = animationData.Layers
|
CacheFrames(animationData.Layers.Select(layer => resourceManager.GetPlayerDCC(layer, ArmorType, palette)));
|
||||||
.Select(layer => resourceManager.GetPlayerDCC(layer, ArmorType, palette))
|
|
||||||
.ToArray();
|
|
||||||
|
|
||||||
log.Warn($"{data.Where(x => x == null).Count()} animation layers were not found!");
|
|
||||||
|
|
||||||
layerData = data.Where(x => x != null)
|
|
||||||
.ToArray();
|
|
||||||
|
|
||||||
CacheFrames();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private unsafe void CacheFrames()
|
private unsafe void CacheFrames(IEnumerable<MPQDCC> layerData)
|
||||||
{
|
{
|
||||||
var cache = new DirectionCacheItem
|
var cache = new DirectionCacheItem
|
||||||
{
|
{
|
||||||
@ -170,14 +160,26 @@ namespace OpenDiablo2.SDL2_
|
|||||||
var maxX = Int32.MinValue;
|
var maxX = Int32.MinValue;
|
||||||
var maxY = Int32.MinValue;
|
var maxY = Int32.MinValue;
|
||||||
|
|
||||||
|
var layersIgnored = 0;
|
||||||
|
var layersToRender = new List<MPQDCC>();
|
||||||
foreach (var layer in layerData)
|
foreach (var layer in layerData)
|
||||||
{
|
{
|
||||||
|
if (layer == null)
|
||||||
|
{
|
||||||
|
layersIgnored++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
layersToRender.Add(layer);
|
||||||
minX = Math.Min(minX, layer.Directions[directionConversion[LocationDetails.MovementDirection]].Box.Left);
|
minX = Math.Min(minX, layer.Directions[directionConversion[LocationDetails.MovementDirection]].Box.Left);
|
||||||
minY = Math.Min(minY, layer.Directions[directionConversion[LocationDetails.MovementDirection]].Box.Top);
|
minY = Math.Min(minY, layer.Directions[directionConversion[LocationDetails.MovementDirection]].Box.Top);
|
||||||
maxX = Math.Max(maxX, layer.Directions[directionConversion[LocationDetails.MovementDirection]].Box.Right);
|
maxX = Math.Max(maxX, layer.Directions[directionConversion[LocationDetails.MovementDirection]].Box.Right);
|
||||||
maxY = Math.Max(maxY, layer.Directions[directionConversion[LocationDetails.MovementDirection]].Box.Bottom);
|
maxY = Math.Max(maxY, layer.Directions[directionConversion[LocationDetails.MovementDirection]].Box.Bottom);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (layersIgnored > 0)
|
||||||
|
log.Warn($"{layersIgnored} animation layer(s) were not found!");
|
||||||
|
|
||||||
var frameW = (maxX - minX) * 2; // Hack
|
var frameW = (maxX - minX) * 2; // Hack
|
||||||
var frameH = (maxY - minY) * 2;
|
var frameH = (maxY - minY) * 2;
|
||||||
|
|
||||||
@ -191,8 +193,11 @@ namespace OpenDiablo2.SDL2_
|
|||||||
SDL.SDL_LockTexture(texture, IntPtr.Zero, out IntPtr pixels, out int pitch);
|
SDL.SDL_LockTexture(texture, IntPtr.Zero, out IntPtr pixels, out int pitch);
|
||||||
UInt32* data = (UInt32*)pixels;
|
UInt32* data = (UInt32*)pixels;
|
||||||
|
|
||||||
foreach (var layer in layerData)
|
foreach (var layer in layersToRender)
|
||||||
{
|
{
|
||||||
|
if (layer == null)
|
||||||
|
continue;
|
||||||
|
|
||||||
var direction = layer.Directions[directionConversion[LocationDetails.MovementDirection]];
|
var direction = layer.Directions[directionConversion[LocationDetails.MovementDirection]];
|
||||||
var frame = direction.Frames[frameIndex];
|
var frame = direction.Frames[frameIndex];
|
||||||
|
|
||||||
@ -212,8 +217,6 @@ namespace OpenDiablo2.SDL2_
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
var color = palette.Colors[paletteIndex];
|
var color = palette.Colors[paletteIndex];
|
||||||
var relativeX = (frame.XOffset - minX);
|
|
||||||
var relativeY = (frame.YOffset - minY);
|
|
||||||
|
|
||||||
var offsetX = x + cell.XOffset + (frame.Box.X - minX);
|
var offsetX = x + cell.XOffset + (frame.Box.X - minX);
|
||||||
var offsetY = y + cell.YOffset + (frame.Box.Y - minY);
|
var offsetY = y + cell.YOffset + (frame.Box.Y - minY);
|
||||||
@ -228,6 +231,7 @@ namespace OpenDiablo2.SDL2_
|
|||||||
|
|
||||||
SDL.SDL_UnlockTexture(texture);
|
SDL.SDL_UnlockTexture(texture);
|
||||||
SDL.SDL_SetTextureBlendMode(texture, SDL.SDL_BlendMode.SDL_BLENDMODE_BLEND);
|
SDL.SDL_SetTextureBlendMode(texture, SDL.SDL_BlendMode.SDL_BLENDMODE_BLEND);
|
||||||
|
|
||||||
// TODO: Temporary code!
|
// TODO: Temporary code!
|
||||||
cache.SpriteTexture[frameIndex] = texture;
|
cache.SpriteTexture[frameIndex] = texture;
|
||||||
cache.SpriteRect[frameIndex] = new SDL.SDL_Rect { x = minX, y = minY, w = frameW, h = frameH };
|
cache.SpriteRect[frameIndex] = new SDL.SDL_Rect { x = minX, y = minY, w = frameW, h = frameH };
|
||||||
|
@ -48,7 +48,7 @@ namespace OpenDiablo2.SDL2_
|
|||||||
{
|
{
|
||||||
int w = 0;
|
int w = 0;
|
||||||
int h = 0;
|
int h = 0;
|
||||||
foreach(byte ch in text)
|
foreach(var ch in text)
|
||||||
{
|
{
|
||||||
w += font.CharacterMetric[ch].Width;
|
w += font.CharacterMetric[ch].Width;
|
||||||
h = Math.Max(h, font.CharacterMetric[ch].Height);
|
h = Math.Max(h, font.CharacterMetric[ch].Height);
|
||||||
|
@ -76,7 +76,7 @@ namespace OpenDiablo2.SDL2_
|
|||||||
int h = 0;
|
int h = 0;
|
||||||
foreach (var ch in text)
|
foreach (var ch in text)
|
||||||
{
|
{
|
||||||
var metric = font.font.CharacterMetric[(byte)ch];
|
var metric = font.font.CharacterMetric[ch];
|
||||||
w += metric.Width;
|
w += metric.Width;
|
||||||
h = Math.Max(Math.Max(h, metric.Height), font.sprite.FrameSize.Height);
|
h = Math.Max(Math.Max(h, metric.Height), font.sprite.FrameSize.Height);
|
||||||
}
|
}
|
||||||
@ -93,12 +93,12 @@ namespace OpenDiablo2.SDL2_
|
|||||||
var height = font.sprite.FrameSize.Height;
|
var height = font.sprite.FrameSize.Height;
|
||||||
for (int idx = 0; idx < text.Length; idx++)
|
for (int idx = 0; idx < text.Length; idx++)
|
||||||
{
|
{
|
||||||
width += font.font.CharacterMetric[(byte)text[idx]].Width;
|
width += font.font.CharacterMetric[text[idx]].Width;
|
||||||
|
|
||||||
if (width >= MaxWidth)
|
if (width >= MaxWidth)
|
||||||
{
|
{
|
||||||
idx = lastWordIndex;
|
idx = lastWordIndex;
|
||||||
height += font.font.CharacterMetric[(byte)'|'].Height + 6;
|
height += font.font.CharacterMetric['|'].Height + 6;
|
||||||
width = 0;
|
width = 0;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -146,7 +146,7 @@ namespace OpenDiablo2.SDL2_
|
|||||||
foreach (var ch in text)
|
foreach (var ch in text)
|
||||||
{
|
{
|
||||||
WriteCharacter(cx, cy, (byte)ch);
|
WriteCharacter(cx, cy, (byte)ch);
|
||||||
cx += font.font.CharacterMetric[(byte)ch].Width;
|
cx += font.font.CharacterMetric[ch].Width;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -158,7 +158,7 @@ namespace OpenDiablo2.SDL2_
|
|||||||
var lastStartX = 0;
|
var lastStartX = 0;
|
||||||
for (int idx = 0; idx < text.Length; idx++)
|
for (int idx = 0; idx < text.Length; idx++)
|
||||||
{
|
{
|
||||||
width += font.font.CharacterMetric[(byte)text[idx]].Width;
|
width += font.font.CharacterMetric[text[idx]].Width;
|
||||||
|
|
||||||
if (width >= MaxWidth)
|
if (width >= MaxWidth)
|
||||||
{
|
{
|
||||||
@ -180,7 +180,7 @@ namespace OpenDiablo2.SDL2_
|
|||||||
var y = 0;
|
var y = 0;
|
||||||
foreach(var line in linesToRender)
|
foreach(var line in linesToRender)
|
||||||
{
|
{
|
||||||
var lineWidth = (line.Sum(c => font.font.CharacterMetric[(byte)c].Width));
|
var lineWidth = (line.Sum(c => font.font.CharacterMetric[c].Width));
|
||||||
var x = 0;
|
var x = 0;
|
||||||
|
|
||||||
if (Alignment == eTextAlign.Centered)
|
if (Alignment == eTextAlign.Centered)
|
||||||
@ -191,10 +191,10 @@ namespace OpenDiablo2.SDL2_
|
|||||||
foreach (var ch in line)
|
foreach (var ch in line)
|
||||||
{
|
{
|
||||||
WriteCharacter(x, y, (byte)ch);
|
WriteCharacter(x, y, (byte)ch);
|
||||||
x += font.font.CharacterMetric[(byte)ch].Width;
|
x += font.font.CharacterMetric[ch].Width;
|
||||||
}
|
}
|
||||||
|
|
||||||
y += font.font.CharacterMetric[(byte)'|'].Height + 6;
|
y += font.font.CharacterMetric['|'].Height + 6;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
SDL.SDL_SetRenderTarget(renderer, IntPtr.Zero);
|
SDL.SDL_SetRenderTarget(renderer, IntPtr.Zero);
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||||
<ProjectGuid>{2B0CF1AC-06DD-4322-AE8B-FF8A8C70A3CD}</ProjectGuid>
|
<ProjectGuid>{2B0CF1AC-06DD-4322-AE8B-FF8A8C70A3CD}</ProjectGuid>
|
||||||
<OutputType>WinExe</OutputType>
|
<OutputType>Exe</OutputType>
|
||||||
<RootNamespace>OpenDiablo2</RootNamespace>
|
<RootNamespace>OpenDiablo2</RootNamespace>
|
||||||
<AssemblyName>OpenDiablo2</AssemblyName>
|
<AssemblyName>OpenDiablo2</AssemblyName>
|
||||||
<TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion>
|
<TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion>
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
</root>
|
</root>
|
||||||
<appender name="console" type="log4net.Appender.ConsoleAppender">
|
<appender name="console" type="log4net.Appender.ConsoleAppender">
|
||||||
<layout type="log4net.Layout.PatternLayout">
|
<layout type="log4net.Layout.PatternLayout">
|
||||||
<conversionPattern value="%date %level %logger - %message%newline" />
|
<conversionPattern value="%level %type{1}.%method - %message%newline" />
|
||||||
</layout>
|
</layout>
|
||||||
</appender>
|
</appender>
|
||||||
<appender name="file" type="log4net.Appender.RollingFileAppender">
|
<appender name="file" type="log4net.Appender.RollingFileAppender">
|
||||||
|
Loading…
Reference in New Issue
Block a user