From 760a97c7bd75a200ac3d77c1d37936257c68f50c Mon Sep 17 00:00:00 2001 From: Furkan SAMANLI Date: Wed, 3 Oct 2018 20:23:39 +0300 Subject: [PATCH 1/6] Zip support --- .gitignore | 4 - .../LeagueSandbox-Default/GameMode.json | 12 - Content/LeagueSandbox-Default | 2 +- GameServerCore/Content/HashFunctions.cs | 17 +- .../Domain/GameObjects/IChampion.cs | 2 +- GameServerCore/Domain/IInventoryManager.cs | 2 +- GameServerCore/Domain/IItem.cs | 2 +- .../Domain/{IItemType.cs => IItemData.cs} | 2 +- GameServerCore/Extensions.cs | 46 --- GameServerCore/GameServerCore.csproj | 2 +- .../Chatbox/Commands/ReloadScriptsCommand.cs | 2 +- GameServerLib/Config.cs | 14 +- GameServerLib/Content/CharData.cs | 17 +- GameServerLib/Content/ContentFile.cs | 32 +- GameServerLib/Content/ContentManager.cs | 305 ++++++++---------- GameServerLib/Content/ItemCollection.cs | 62 ---- GameServerLib/Content/SpellData.cs | 107 +++--- .../ContentNotFoundException.cs | 2 +- GameServerLib/Game.cs | 21 +- .../AttackableUnits/AI/ObjAIBase.cs | 2 +- GameServerLib/GameObjects/Missiles/Cone.cs | 25 +- GameServerLib/GameObjects/Missiles/Laser.cs | 22 +- .../GameObjects/Missiles/Projectile.cs | 20 +- GameServerLib/GameObjects/Spells/Spell.cs | 4 +- GameServerLib/GameServerLib.csproj | 9 +- GameServerLib/Items/Inventory.cs | 16 +- GameServerLib/Items/InventoryManager.cs | 12 +- GameServerLib/Items/Item.cs | 14 +- GameServerLib/Items/ItemData.cs | 129 ++++++++ GameServerLib/Items/ItemManager.cs | 51 +-- GameServerLib/Items/ItemRecipe.cs | 29 +- GameServerLib/Items/ItemType.cs | 138 -------- GameServerLib/Items/Shop.cs | 20 +- GameServerLib/Maps/Map.cs | 18 +- .../Scripting/CSharp/CSharpScriptEngine.cs | 25 +- GameServerLib/packages.config | 1 + .../Tests/Items/TestInventoryManager.cs | 30 +- .../PacketDefinitions/S2C/BuyItemResponse.cs | 2 +- PacketDefinitions420/PacketServer.cs | 4 +- 39 files changed, 541 insertions(+), 683 deletions(-) delete mode 100644 Content/GameMode/LeagueSandbox-Default/GameMode.json rename GameServerCore/Domain/{IItemType.cs => IItemData.cs} (92%) delete mode 100644 GameServerLib/Content/ItemCollection.cs rename GameServerLib/{Content => Exceptions}/ContentNotFoundException.cs (89%) create mode 100644 GameServerLib/Items/ItemData.cs delete mode 100644 GameServerLib/Items/ItemType.cs diff --git a/.gitignore b/.gitignore index 52eec13ba..6f51eb3a6 100644 --- a/.gitignore +++ b/.gitignore @@ -3,9 +3,6 @@ ## ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore -# Game settings files -GameServerApp/Settings/ - # User-specific files *.suo *.user @@ -308,7 +305,6 @@ __pycache__/ OpenCover/ # Custom stuff -GameServer/Settings/GameInfo.json GameServerConsole/Settings/GameInfo.json GameServerConsole/Settings/GameServerSettings.json MigrationBackup/ diff --git a/Content/GameMode/LeagueSandbox-Default/GameMode.json b/Content/GameMode/LeagueSandbox-Default/GameMode.json deleted file mode 100644 index 124448d31..000000000 --- a/Content/GameMode/LeagueSandbox-Default/GameMode.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "data": { - "LeagueSandbox-Default": { - "Champions": "*", - "Items": "*", - "Buffs": "*", - "Maps": "*", - "Stats": "*", - "Spells": "*" - } - } -} \ No newline at end of file diff --git a/Content/LeagueSandbox-Default b/Content/LeagueSandbox-Default index 132e90d05..f1dbca1e8 160000 --- a/Content/LeagueSandbox-Default +++ b/Content/LeagueSandbox-Default @@ -1 +1 @@ -Subproject commit 132e90d0578a0f80e29fc2752204ba70fd85ac03 +Subproject commit f1dbca1e827d5d940bbb170022650fa13ef9bd57 diff --git a/GameServerCore/Content/HashFunctions.cs b/GameServerCore/Content/HashFunctions.cs index 9f755a19e..ed35d5b89 100644 --- a/GameServerCore/Content/HashFunctions.cs +++ b/GameServerCore/Content/HashFunctions.cs @@ -5,7 +5,7 @@ public class HashFunctions public static uint HashString(string path) { uint hash = 0; - var mask = 0xF0000000; + const uint mask = 0xF0000000; for (var i = 0; i < path.Length; i++) { hash = char.ToLower(path[i]) + 0x10 * hash; @@ -18,22 +18,21 @@ public static uint HashString(string path) return hash; } - public static uint HashStringSdbm(string section, string name) + public static uint HashStringSdbm(string data) { uint hash = 0; - foreach (var c in section) - { - hash = char.ToLower(c) + 65599 * hash; - } - - hash = char.ToLower('*') + 65599 * hash; - foreach (var c in name) + foreach (var c in data) { hash = char.ToLower(c) + 65599 * hash; } return hash; } + + public static uint HashStringSdbm(string section, string name) + { + return HashStringSdbm($"{section}*{name}"); + } } diff --git a/GameServerCore/Domain/GameObjects/IChampion.cs b/GameServerCore/Domain/GameObjects/IChampion.cs index 7775ea2e9..7e3599ea0 100644 --- a/GameServerCore/Domain/GameObjects/IChampion.cs +++ b/GameServerCore/Domain/GameObjects/IChampion.cs @@ -29,6 +29,6 @@ public interface IChampion : IObjAiBase ISpell GetSpell(byte slot); ISpell LevelUpSpell(byte slot); - + } } diff --git a/GameServerCore/Domain/IInventoryManager.cs b/GameServerCore/Domain/IInventoryManager.cs index 2f16eeb5e..d022c369c 100644 --- a/GameServerCore/Domain/IInventoryManager.cs +++ b/GameServerCore/Domain/IInventoryManager.cs @@ -5,7 +5,7 @@ public interface IInventoryManager IItem GetItem(byte slot); void RemoveItem(byte slot); byte GetItemSlot(IItem item); - IItem SetExtraItem(byte slot, IItemType item); + IItem SetExtraItem(byte slot, IItemData item); void SwapItems(byte slot1, byte slot2); } } diff --git a/GameServerCore/Domain/IItem.cs b/GameServerCore/Domain/IItem.cs index 63d76311c..f84b13ad7 100644 --- a/GameServerCore/Domain/IItem.cs +++ b/GameServerCore/Domain/IItem.cs @@ -4,6 +4,6 @@ public interface IItem { byte StackSize { get; } int TotalPrice { get; } - IItemType ItemType { get; } + IItemData ItemData { get; } } } diff --git a/GameServerCore/Domain/IItemType.cs b/GameServerCore/Domain/IItemData.cs similarity index 92% rename from GameServerCore/Domain/IItemType.cs rename to GameServerCore/Domain/IItemData.cs index b76162681..d7d014494 100644 --- a/GameServerCore/Domain/IItemType.cs +++ b/GameServerCore/Domain/IItemData.cs @@ -1,6 +1,6 @@ namespace GameServerCore.Domain { - public interface IItemType + public interface IItemData { int ItemId { get; } string Name { get; } diff --git a/GameServerCore/Extensions.cs b/GameServerCore/Extensions.cs index 17e5450e8..db3f4142c 100644 --- a/GameServerCore/Extensions.cs +++ b/GameServerCore/Extensions.cs @@ -95,52 +95,6 @@ public static double RadianToDegree(double angle) } } - public class PairList : List> - { - public void Add(TKey key, TValue value) - { - Add(new Pair(key, value)); - } - public bool ContainsKey(TKey key) - { - foreach (var v in this) - { - if (v.Item1.Equals(key)) - { - return true; - } - } - - return false; - } - - public TValue this[TKey key] - { - get - { - foreach (var v in this) - { - if (v.Item1.Equals(key)) - { - return v.Item2; - } - } - - return default(TValue); - } - set - { - foreach (var v in this) - { - if (v.Item1.Equals(key)) - { - v.Item2 = value; - } - } - } - } - } - public static class CustomConvert { public static TeamId ToTeamId(this int i) diff --git a/GameServerCore/GameServerCore.csproj b/GameServerCore/GameServerCore.csproj index c78183e54..8e8faf01c 100644 --- a/GameServerCore/GameServerCore.csproj +++ b/GameServerCore/GameServerCore.csproj @@ -74,7 +74,7 @@ - + diff --git a/GameServerLib/Chatbox/Commands/ReloadScriptsCommand.cs b/GameServerLib/Chatbox/Commands/ReloadScriptsCommand.cs index a17858d28..c501fbad0 100644 --- a/GameServerLib/Chatbox/Commands/ReloadScriptsCommand.cs +++ b/GameServerLib/Chatbox/Commands/ReloadScriptsCommand.cs @@ -12,7 +12,7 @@ public ReloadScriptsCommand(ChatCommandManager chatCommandManager, Game game) public override void Execute(int userId, bool hasReceivedArguments, string arguments = "") { - if (Game.LoadScripts()) + if (Game.LoadScripts(true)) { ChatCommandManager.SendDebugMsgFormatted(DebugMsgType.INFO, "Scripts reloaded."); } diff --git a/GameServerLib/Config.cs b/GameServerLib/Config.cs index 5e429fd88..c41ec0c21 100644 --- a/GameServerLib/Config.cs +++ b/GameServerLib/Config.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.IO; using System.Numerics; +using System.Text; using LeagueSandbox.GameServer.Content; using Newtonsoft.Json.Linq; @@ -69,22 +70,19 @@ private void LoadConfig(Game game, string json) // Read where the content is ContentPath = (string)gameInfo.SelectToken("CONTENT_PATH"); - // Load items - game.ItemManager.AddItems(ItemContentCollection.LoadItemsFrom( - // todo: remove this hardcoded path with content pipeline refactor - $"{ContentPath}/LeagueSandbox-Default/Items" - )); - // Read the game configuration var gameToken = data.SelectToken("game"); GameConfig = new GameConfig(gameToken); // Read spawns info ContentManager = ContentManager.LoadGameMode(game, GameConfig.GameMode, ContentPath); - var mapPath = ContentManager.GetMapDataPath(GameConfig.Map); - var mapData = JObject.Parse(File.ReadAllText(mapPath)); + var mapPath = ContentManager.GetMapConfigPath(GameConfig.Map); + var mapData = JObject.Parse(Encoding.UTF8.GetString(ContentManager.Content[mapPath])); var spawns = mapData.SelectToken("spawns"); + // Load items + game.ItemManager.LoadItems(ContentManager); + MapSpawns = new MapSpawns(); foreach (JProperty teamSpawn in spawns) { diff --git a/GameServerLib/Content/CharData.cs b/GameServerLib/Content/CharData.cs index e2831ee35..9d64cf17b 100644 --- a/GameServerLib/Content/CharData.cs +++ b/GameServerLib/Content/CharData.cs @@ -1,8 +1,10 @@ using System; using System.IO; using GameServerCore.Enums; +using IniParser; using LeagueSandbox.GameServer.Logging; using log4net; +using LeagueSandbox.GameServer.Exceptions; using Newtonsoft.Json; namespace LeagueSandbox.GameServer.Content @@ -78,13 +80,17 @@ public void Load(string name) return; } - var file = new ContentFile(); + ContentFile file; try { var path = _game.Config.ContentManager.GetUnitStatPath(name); - _logger.Debug($"Loading {name}'s Stats from path: {Path.GetFullPath(path)}!"); - var text = File.ReadAllText(Path.GetFullPath(path)); - file = JsonConvert.DeserializeObject(text); + var iniParser = new FileIniDataParser(); + _logger.Debug($"Loading {name}'s Stats from path: {path}!"); + using (var stream = new StreamReader(new MemoryStream(_game.Config.ContentManager.Content[path]))) + { + var iniData = iniParser.ReadData(stream); + file = new ContentFile(ContentManager.ParseIniFile(iniData)); + } } catch (ContentNotFoundException notfound) { @@ -110,10 +116,11 @@ public void Load(string name) HpRegenPerLevel = file.GetFloat("Data", "HPRegenPerLevel", HpRegenPerLevel); MpRegenPerLevel = file.GetFloat("Data", "MPRegenPerLevel", MpRegenPerLevel); AttackSpeedPerLevel = file.GetFloat("Data", "AttackSpeedPerLevel", AttackSpeedPerLevel); - IsMelee = file.GetString("Data", "IsMelee", IsMelee ? "Yes" : "No").Equals("yes"); + IsMelee = file.GetString("Data", "IsMelee", IsMelee ? "Yes" : "No").ToLowerInvariant().Equals("yes"); PathfindingCollisionRadius = file.GetFloat("Data", "PathfindingCollisionRadius", PathfindingCollisionRadius); GameplayCollisionRadius = file.GetFloat("Data", "GameplayCollisionRadius", GameplayCollisionRadius); + Enum.TryParse(file.GetString("Data", "PARType", ParType.ToString()), out var tempPar); ParType = tempPar; diff --git a/GameServerLib/Content/ContentFile.cs b/GameServerLib/Content/ContentFile.cs index 91026c084..29cf34a70 100644 --- a/GameServerLib/Content/ContentFile.cs +++ b/GameServerLib/Content/ContentFile.cs @@ -1,31 +1,21 @@ using System.Collections.Generic; using System.Globalization; using GameServerCore.Content; +using LeagueSandbox.GameServer.Logging; namespace LeagueSandbox.GameServer.Content { public class ContentFile { public Dictionary> Values { get; set; } - = new Dictionary>(); - public Dictionary MetaData { get; set; } - = new Dictionary(); - - private uint Hash(string section, string name) + public ContentFile(Dictionary> data) { - uint hash = 0; - foreach (var c in section) - { - hash = char.ToLower(c) + 65599 * hash; - } - hash = char.ToLower('*') + 65599 * hash; - foreach (var c in name) - { - hash = char.ToLower(c) + 65599 * hash; - } + Values = data; + } - return hash; + public ContentFile() : this(new Dictionary>()) + { } public string GetObject(string section, string name) @@ -41,7 +31,8 @@ public string GetObject(string section, string name) var hash = HashFunctions.HashStringSdbm(section, name).ToString(); if (Values["UNKNOWN_HASHES"].ContainsKey(hash)) { - //TODO: Log that unkown hash was found! + LoggerProvider.GetLogger().Info($"UNKNOWN HASH {hash} WAS FOUND TO BE {section}*{name}!" + + "PLEASE SHOW THIS LOG TO A DEVELOPER."); return Values["UNKNOWN_HASHES"][hash]; } } @@ -84,7 +75,7 @@ public float[] GetFloatArray(string section, string name, float[] defaultValue ) var list = obj.Split(' '); if (defaultValue.Length == list.Length) { - for (var i = 0; i _spellData = new Dictionary(); private Dictionary _charData = new Dictionary(); + private Dictionary _navGrids = new Dictionary(); - private string _contentPath; - - private static readonly string[] ContentTypes = { - "Champions", - "Items", - "Buffs", - "Maps", - "Spells", - "Stats" - }; - - private Dictionary>> _content; + public Dictionary Content { get; set; } = new Dictionary(); public string GameModeName { get; } - private ContentManager(Game game, string gameModeName, string contentPath) + private ContentManager(Game game, string gameModeName) { - _contentPath = contentPath; _game = game; _logger = LoggerProvider.GetLogger(); GameModeName = gameModeName; - - _content = new Dictionary>>(); - foreach (var contentType in ContentTypes) - { - _content[contentType] = new Dictionary>(); - } } - private void AddContent(string packageName, string contentType, JToken contentSet) + public string GetMapConfigPath(int mapId) { - var contents = new string[0]; - if (contentSet is JArray) - { - contents = contentSet.ToObject(); - } - else if (contentSet.Value().Equals("*")) + var possibilities = new[] { - var contentPath = GetContentSetPath(packageName, contentType); - contents = GetFolderNamesFromPath(contentPath); - } - else - { - throw new Exception("Invalid content configuration"); - } - - foreach (var content in contents) - { - _logger.Debug($"Mapped Content [{packageName}][{contentType}][{content}]"); - if (!_content[contentType].ContainsKey(content)) - { - _content[contentType][content] = new List(); - } - - _content[contentType][content].Add(packageName); - } - } + $"LEVELS/Map{mapId}/Map{mapId}.json", + $"LEVELS/map{mapId}/Map{mapId}.json" + }; - private string[] GetFolderNamesFromPath(string folderPath) - { - var contents = new List(); - if (Directory.Exists(folderPath)) + foreach (var path in possibilities) { - var contentDirectories = Directory.GetDirectories(folderPath); - foreach (var directory in contentDirectories) + if (Content.ContainsKey(path)) { - contents.Add(directory.Replace('\\', '/').Split('/').Last()); + return path; } } - return contents.ToArray(); - } - - private string GetPackagePath(string packageName) - { - return $"{_contentPath}/{packageName}"; - } - - private string GetContentSetPath(string packageName, string contentType) - { - if (packageName.Equals("Self")) - { - return $"{_contentPath}/GameMode/{GameModeName}/Data/{contentType}"; - } - - return $"{GetPackagePath(packageName)}/{contentType}"; - } - - private string GetContentPath(string packageName, string contentType, string fileName) - { - return $"{GetContentSetPath(packageName, contentType)}/{fileName}"; - } - - private string GetContentPath(List contentPackages, string contentType, string fileName) - { - var path = ""; - var depth = contentPackages.Count; - while (!File.Exists(path) && depth > 0) - { - depth--; - path = GetContentPath(contentPackages[depth], contentType, fileName); - } - - if (!File.Exists(path)) - { - throw new ContentNotFoundException("Failed to load content [" + contentType + "][" + fileName + "]"); - } - - _logger.Debug($"Loaded content [{contentPackages[depth]}][{contentType}][{fileName}]"); - return path; - } - - public string GetMapDataPath(int mapId) - { - var mapName = $"Map{mapId}"; - var contentType = "Maps"; - - if (!_content.ContainsKey(contentType) || !_content[contentType].ContainsKey(mapName)) - { - throw new ContentNotFoundException($"Map{mapId} was not found in the files."); - } - - var contentPackages = _content[contentType][mapName]; - var fileName = $"{mapName}/{mapName}.json"; - return GetContentPath(contentPackages, contentType, fileName); - } - - public string GetSpellScriptPath(string championName, string spellSlot) - { - var contentType = "Champions"; - - if (!_content.ContainsKey(contentType) || !_content[contentType].ContainsKey(championName)) - { - throw new ContentNotFoundException($"{championName}/{spellSlot}.lua was not found."); - } - var contentPackages = _content[contentType][championName]; - var fileName = $"{championName}/{spellSlot}.lua"; - return GetContentPath(contentPackages, contentType, fileName); - } - - public string GetBuffScriptPath(string buffName) - { - var contentType = "Buffs"; - - if (!_content.ContainsKey(contentType) || !_content[contentType].ContainsKey(buffName)) - { - throw new ContentNotFoundException($"Buff {buffName} was not found."); - } - - var contentPackages = _content[contentType][buffName]; - var fileName = $"{buffName}/{buffName}.lua"; - return GetContentPath(contentPackages, contentType, fileName); + throw new ContentNotFoundException($"Map configuration for Map {mapId} was not found in the content."); } public string GetUnitStatPath(string model) { - var contentType = "Stats"; - - if (!_content.ContainsKey(contentType) || !_content[contentType].ContainsKey(model)) + var path = $"DATA/Characters/{model}/{model}.ini"; + if (!Content.ContainsKey(path)) { throw new ContentNotFoundException($"Stat file for {model} was not found."); } - var contentPackages = _content[contentType][model]; - var fileName = $"{model}/{model}.json"; - return GetContentPath(contentPackages, contentType, fileName); + return path; } - public string GetSpellDataPath(string spellName) + public string GetSpellDataPath(string model, string spellName) { - var contentType = "Spells"; + var possibilities = new[] + { + $"DATA/Characters/{model}/Spells/{spellName}.ini", + $"DATA/Shared/Spells/{spellName}.ini", + $"DATA/Spells/{spellName}.ini" + }; - if (!_content.ContainsKey(contentType) || !_content[contentType].ContainsKey(spellName)) + foreach (var path in possibilities) { - throw new ContentNotFoundException($"Spell data for {spellName} was not found."); + if (Content.ContainsKey(path)) + { + return path; + } } - var contentPackages = _content[contentType][spellName]; - var fileName = $"{spellName}/{spellName}.json"; - - return GetContentPath(contentPackages, contentType, fileName); + throw new ContentNotFoundException($"Spell data for {spellName} was not found."); } - public SpellData GetSpellData(string spellName) + public SpellData GetSpellData(string champ, string spellName) { if (_spellData.ContainsKey(spellName)) { @@ -207,7 +89,7 @@ public SpellData GetSpellData(string spellName) } _spellData[spellName] = new SpellData(_game); - _spellData[spellName].Load(spellName); + _spellData[spellName].Load(champ, spellName); return _spellData[spellName]; } @@ -217,39 +99,136 @@ public CharData GetCharData(string charName) { return _charData[charName]; } + _charData[charName] = new CharData(_game); _charData[charName].Load(charName); return _charData[charName]; } + public NavGrid GetNavGrid(int mapId) + { + var possibilities = new[] + { + $"LEVELS/Map{mapId}/AIPath.aimesh_ngrid", + $"LEVELS/map{mapId}/AIPath.aimesh_ngrid" + }; + foreach (var path in possibilities) + { + if (_navGrids.ContainsKey(path)) + { + return _navGrids[path]; + } + } + + throw new ContentNotFoundException($"NavGrid for map {mapId} was not loaded."); + } + public static ContentManager LoadGameMode(Game game, string gameModeName, string contentPath) { - var contentManager = new ContentManager(game, gameModeName, contentPath); + var contentManager = new ContentManager(game, gameModeName); - var gameModeConfigurationPath = $"{contentPath}/GameMode/{gameModeName}/GameMode.json"; - var gameModeConfiguration = JToken.Parse(File.ReadAllText(gameModeConfigurationPath)); - var dataConfiguration = gameModeConfiguration.SelectToken("data"); + var zipPath = Path.Combine(contentPath, gameModeName, gameModeName + ".zip"); - foreach (JProperty dataPackage in dataConfiguration) + // If zip exists + if (File.Exists(zipPath)) { - if (!ValidatePackageName(dataPackage.Name)) throw new Exception("Data packages must be namespaced!"); - - foreach (var contentType in ContentTypes) + // Read zip file data + using (var file = File.OpenRead(zipPath)) { - var contentSet = dataPackage.Value.SelectToken(contentType); + // Read archive data + using (var zip = new ZipArchive(file, ZipArchiveMode.Read)) + { + // For every entry in the zip + foreach (var entry in zip.Entries) + { + // Uncompress the entry and read it + using (var entryData = new BinaryReader(entry.Open())) + { + if (entry.FullName.EndsWith(".ini") || entry.FullName.EndsWith(".json")) + { + contentManager.Content[entry.FullName] = entryData.ReadBytes((int)entry.Length); + } + else if (entry.FullName.EndsWith(".aimesh_ngrid")) + { + contentManager._navGrids[entry.FullName] = + NavGridReader.ReadBinary(entryData.ReadBytes((int)entry.Length)); + + contentManager.Content[entry.FullName] = entryData.ReadBytes((int)entry.Length); + } + else if (entry.FullName.EndsWith(".cs")) + { + if (entry.FullName.StartsWith("bin") || entry.FullName.StartsWith("obj")) + { + continue; + } + + contentManager.Content[entry.FullName] = entryData.ReadBytes((int)entry.Length); + } + else + { + continue; + } + + contentManager._logger.Debug($"Mapped content from zip [{entry.FullName}]"); + } + } + } + } + } - if (contentSet == null) + // Read non-zipped data + foreach (var file in Directory.GetFiles(contentPath, "*.*", SearchOption.AllDirectories)) + { + var relativePath = file.Replace(contentPath, "").Replace(gameModeName, "").Substring(2) + .Replace('\\', '/'); + if (file.EndsWith(".ini") || file.EndsWith(".json")) + { + contentManager.Content[relativePath] = File.ReadAllBytes(file); + } + else if (file.EndsWith(".cs")) + { + if (relativePath.StartsWith("bin") || relativePath.StartsWith("obj")) { continue; } - contentManager.AddContent(dataPackage.Name, contentType, contentSet); + contentManager.Content[relativePath] = File.ReadAllBytes(file); + } + else if (file.EndsWith(".aimesh_ngrid")) + { + contentManager.Content[relativePath] = File.ReadAllBytes(file); + contentManager._navGrids[relativePath] = NavGridReader.ReadBinary(file); + } + else + { + continue; } + + contentManager._logger.Debug($"Mapped Content [{relativePath}]"); } return contentManager; } + public static Dictionary> ParseIniFile(IniData data) + { + var ret = new Dictionary>(); + foreach (var section in data.Sections) + { + if (!ret.ContainsKey(section.SectionName)) + { + ret[section.SectionName] = new Dictionary(); + } + + foreach (var field in section.Keys) + { + ret[section.SectionName][field.KeyName] = field.Value; + } + } + + return ret; + } + private static bool ValidatePackageName(string packageName) { if (packageName.Equals("Self")) @@ -257,7 +236,7 @@ private static bool ValidatePackageName(string packageName) return true; } - if (packageName.All(c => c != '-')) + if (!packageName.Contains('-')) { return false; } diff --git a/GameServerLib/Content/ItemCollection.cs b/GameServerLib/Content/ItemCollection.cs deleted file mode 100644 index 0a6a6bbc5..000000000 --- a/GameServerLib/Content/ItemCollection.cs +++ /dev/null @@ -1,62 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using Newtonsoft.Json; - -namespace LeagueSandbox.GameServer.Content -{ - public class ContentCollectionEntry : ContentFile - { - public int ContentFormatVersion => Convert.ToInt32(MetaData["ContentFormatVersion"]); - public string ResourcePath => Convert.ToString(MetaData["ResourcePath"]); - public string Name => Convert.ToString(MetaData["Name"]); - public object Id => MetaData["Id"]; - } - - public class ContentCollection - { - } - - public class ItemContentCollectionEntry : ContentCollectionEntry - { - public int ItemId => Convert.ToInt32(Id); - } - - public class ItemContentCollection : ContentCollection - { - private Dictionary _items; - - public Dictionary.Enumerator GetEnumerator() - { - return _items.GetEnumerator(); - } - - private ItemContentCollection() - { - _items = new Dictionary(); - } - - private void AddFromPath(string dataPath) - { - var data = File.ReadAllText(dataPath); - var collectionEntry = JsonConvert.DeserializeObject(data); - _items.Add(collectionEntry.ItemId, collectionEntry); - } - - public static ItemContentCollection LoadItemsFrom(string directoryPath) - { - var result = new ItemContentCollection(); - var itemDirectoryPaths = Directory.GetDirectories(directoryPath); - foreach (var location in itemDirectoryPaths) - { - var path = location.Replace('\\', '/'); - var itemName = path.Split('/').Last(); - var itemDataPath = $"{path}/{itemName}.json"; - result.AddFromPath(itemDataPath); - } - - return result; - } - } -} diff --git a/GameServerLib/Content/SpellData.cs b/GameServerLib/Content/SpellData.cs index 5f0b50c09..302079861 100644 --- a/GameServerLib/Content/SpellData.cs +++ b/GameServerLib/Content/SpellData.cs @@ -1,59 +1,61 @@ using System.IO; using System.Numerics; using GameServerCore.Domain; +using IniParser; using LeagueSandbox.GameServer.Logging; using log4net; +using LeagueSandbox.GameServer.Exceptions; using Newtonsoft.Json; namespace LeagueSandbox.GameServer.Content { public enum SpellFlag : uint { - SPELL_FLAG_AUTO_CAST = 0x00000002, - SPELL_FLAG_INSTANT_CAST = 0x00000004, - SPELL_FLAG_PERSIST_THROUGH_DEATH = 0x00000008, - SPELL_FLAG_NON_DISPELLABLE = 0x00000010, - SPELL_FLAG_NO_CLICK = 0x00000020, - SPELL_FLAG_AFFECT_IMPORTANT_BOT_TARGETS = 0x00000040, - SPELL_FLAG_ALLOW_WHILE_TAUNTED = 0x00000080, - SPELL_FLAG_NOT_AFFECT_ZOMBIE = 0x00000100, - SPELL_FLAG_AFFECT_UNTARGETABLE = 0x00000200, - SPELL_FLAG_AFFECT_ENEMIES = 0x00000400, - SPELL_FLAG_AFFECT_FRIENDS = 0x00000800, - SPELL_FLAG_AFFECT_BUILDINGS = 0x00001000, - SPELL_FLAG_NOT_AFFECT_SELF = 0x00002000, - SPELL_FLAG_AFFECT_NEUTRAL = 0x00004000, - SPELL_FLAG_AFFECT_ALL_SIDES = 0x00004C00, - SPELL_FLAG_AFFECT_MINIONS = 0x00008000, - SPELL_FLAG_AFFECT_HEROES = 0x00010000, - SPELL_FLAG_AFFECT_TURRETS = 0x00020000, - SPELL_FLAG_AFFECT_ALL_UNIT_TYPES = 0x00038000, - SPELL_FLAG_ALWAYS_SELF = 0x00040000, - SPELL_FLAG_AFFECT_DEAD = 0x00080000, - SPELL_FLAG_AFFECT_NOT_PET = 0x00100000, - SPELL_FLAG_AFFECT_BARRACKS_ONLY = 0x00200000, - SPELL_FLAG_IGNORE_VISIBILITY_CHECK = 0x00400000, - SPELL_FLAG_NON_TARGETABLE_ALLY = 0x00800000, - SPELL_FLAG_NON_TARGETABLE_ENEMY = 0x01000000, - SPELL_FLAG_NON_TARGETABLE_ALL = 0x01800000, - SPELL_FLAG_TARGETABLE_TO_ALL = 0x02000000, - SPELL_FLAG_AFFECT_WARDS = 0x04000000, - SPELL_FLAG_AFFECT_USEABLE = 0x08000000, - SPELL_FLAG_IGNORE_ALLY_MINION = 0x10000000, - SPELL_FLAG_IGNORE_ENEMY_MINION = 0x20000000, - SPELL_FLAG_IGNORE_LANE_MINION = 0x40000000, - SPELL_FLAG_IGNORE_CLONES = 0x80000000 + AUTO_CAST = 1u << 1, + INSTANT_CAST = 1u << 2, + PERSIST_THROUGH_DEATH = 1u << 3, + NON_DISPELLABLE = 1u << 4, + NO_CLICK = 1u << 5, + AFFECT_IMPORTANT_BOT_TARGETS = 1u << 6, + ALLOW_WHILE_TAUNTED = 1u << 7, + NOT_AFFECT_ZOMBIE = 1u << 8, + AFFECT_UNTARGETABLE = 1u << 9, + AFFECT_ENEMIES = 1u << 10, + AFFECT_FRIENDS = 1u << 11, + AFFECT_BUILDINGS = 1u << 12, + NOT_AFFECT_SELF = 1u << 13, + AFFECT_NEUTRAL = 1u << 14, + AFFECT_ALL_SIDES = AFFECT_ENEMIES | AFFECT_FRIENDS | AFFECT_NEUTRAL, + AFFECT_MINIONS = 1u << 15, + AFFECT_HEROES = 1u << 16, + AFFECT_TURRETS = 1u << 17, + AFFECT_ALL_UNIT_TYPES = AFFECT_MINIONS | AFFECT_HEROES | AFFECT_TURRETS, + ALWAYS_SELF = 1u << 18, + AFFECT_DEAD = 1u << 19, + AFFECT_NOT_PET = 1u << 20, + AFFECT_BARRACKS_ONLY = 1u << 21, + IGNORE_VISIBILITY_CHECK = 1u << 22, + NON_TARGETABLE_ALLY = 1u << 23, + NON_TARGETABLE_ENEMY = 1u << 24, + NON_TARGETABLE_ALL = NON_TARGETABLE_ALLY | NON_TARGETABLE_ENEMY, + TARGETABLE_TO_ALL = 1u << 25, + AFFECT_WARDS = 1u << 26, + AFFECT_USEABLE = 1u << 27, + IGNORE_ALLY_MINION = 1u << 28, + IGNORE_ENEMY_MINION = 1u << 29, + IGNORE_LANE_MINION = 1u << 30, + IGNORE_CLONES = 1u << 31 } public enum SpellTargetType { - TARGET_SELF = 0, // teemo W ; xin Q - TARGET_UNIT = 1, // Taric E ; Annie Q ; teemo Q ; xin E - TARGET_LOC_AOE = 2, // Lux E, Ziggs R - TARGET_CONE = 3, // Annie W, Kass E - TARGET_SELF_AOE = 4, // sivir R, Gangplanck E - TARGET_LOC = 6, // Ez Q, W, E, R ; Mundo Q - TARGET_LOC2 = 7 // Morg Q, Cait's Q -- These don't seem to have Missile inibins, and SpawnProjectile doesn't seem necessary to show the projectiles + SELF = 0, // teemo W ; xin Q + UNIT = 1, // Taric E ; Annie Q ; teemo Q ; xin E + LOC_AOE = 2, // Lux E, Ziggs R + CONE = 3, // Annie W, Kass E + SELF_AOE = 4, // sivir R, Gangplanck E + LOC = 6, // Ez Q, W, E, R ; Mundo Q + LOC2 = 7 // Morg Q, Cait's Q -- These don't seem to have Missile inibins, and SpawnProjectile doesn't seem necessary to show the projectiles } public class SpellData : ISpellData @@ -234,25 +236,28 @@ public float GetCastTime() return (1.0f + DelayCastOffsetPercent) / 2.0f; } - public void Load(string name) + public void Load(string champion, string spell) { - if (string.IsNullOrEmpty(name)) + if (string.IsNullOrEmpty(champion) || string.IsNullOrEmpty(spell)) { return; } - var file = new ContentFile(); + ContentFile file; try { - var path = _game.Config.ContentManager.GetSpellDataPath(name); - _logger.Debug($"Loading spell {name} data from path: {Path.GetFullPath(path)}!"); - var text = File.ReadAllText(Path.GetFullPath(path)); - file = JsonConvert.DeserializeObject(text); + var path = _game.Config.ContentManager.GetSpellDataPath(champion, spell); + _logger.Debug($"Loading spell {spell} data from path: {path}!"); + using (var stream = new StreamReader(new MemoryStream(_game.Config.ContentManager.Content[path]))) + { + var iniParser = new FileIniDataParser(); + var iniData = iniParser.ReadData(stream); + file = new ContentFile(ContentManager.ParseIniFile(iniData)); + } } - catch (ContentNotFoundException) { - _logger.Warn($"Spell data for {name} was not found."); + _logger.Warn($"Spell data for {spell} was not found."); return; } @@ -263,7 +268,7 @@ public void Load(string name) //AIRange //AISendEvent //AISpeed - AlternateName = file.GetString("SpellData", "AlternateName", name); + AlternateName = file.GetString("SpellData", "AlternateName", spell); AlwaysSnapFacing = file.GetBool("SpellData", "AlwaysSnapFacing", AlwaysSnapFacing); //AmmoCountHiddenInUI AmmoRechargeTime = file.GetMultiFloat("SpellData", "AmmoRechargeTime", 6, AmmoRechargeTime[0]); diff --git a/GameServerLib/Content/ContentNotFoundException.cs b/GameServerLib/Exceptions/ContentNotFoundException.cs similarity index 89% rename from GameServerLib/Content/ContentNotFoundException.cs rename to GameServerLib/Exceptions/ContentNotFoundException.cs index 357e4d4f1..3ff6a1f0c 100644 --- a/GameServerLib/Content/ContentNotFoundException.cs +++ b/GameServerLib/Exceptions/ContentNotFoundException.cs @@ -1,6 +1,6 @@ using System; -namespace LeagueSandbox.GameServer.Content +namespace LeagueSandbox.GameServer.Exceptions { internal class ContentNotFoundException : Exception { diff --git a/GameServerLib/Game.cs b/GameServerLib/Game.cs index 7bcaa2a01..3ccc59cfd 100644 --- a/GameServerLib/Game.cs +++ b/GameServerLib/Game.cs @@ -26,7 +26,6 @@ namespace LeagueSandbox.GameServer { public class Game : IGame { - private ILog _logger; public bool IsRunning { get; private set; } @@ -47,7 +46,7 @@ public class Game : IGame public IPacketNotifier PacketNotifier { get; private set; } public IObjectManager ObjectManager { get; private set; } public Map Map { get; private set; } - + public Config Config { get; protected set; } protected const double REFRESH_RATE = 1000.0 / 30.0; // 30 fps @@ -121,9 +120,23 @@ public void Initialize(ushort port, string blowfishKey, Config config) _logger.Info("Game is ready."); } - public bool LoadScripts() + public bool LoadScripts(bool doReloadContent = false) { - return ScriptEngine.LoadSubdirectoryScripts($"{Config.ContentPath}/{Config.GameConfig.GameMode}/"); + // todo: use the optional arg to *actually* reload the scripts + // current code only takes what was loaded in the startup and loads them back in, so it does nothing + + var scripts = new Dictionary(); + foreach (var contentData in Config.ContentManager.Content) + { + if (!contentData.Key.EndsWith(".cs")) + { + continue; + } + + scripts.Add(contentData.Key, contentData.Value); + } + + return ScriptEngine.LoadFromData(scripts); } public void GameLoop() diff --git a/GameServerLib/GameObjects/AttackableUnits/AI/ObjAIBase.cs b/GameServerLib/GameObjects/AttackableUnits/AI/ObjAIBase.cs index 07dc7a1fc..a6418a46a 100644 --- a/GameServerLib/GameObjects/AttackableUnits/AI/ObjAIBase.cs +++ b/GameServerLib/GameObjects/AttackableUnits/AI/ObjAIBase.cs @@ -81,7 +81,7 @@ public ObjAiBase(Game game, string model, Stats.Stats stats, int collisionRadius Stats.CurrentHealth = stats.HealthPoints.Total; if (!string.IsNullOrEmpty(model)) { - AaSpellData = _game.Config.ContentManager.GetSpellData(model + "BasicAttack"); + AaSpellData = _game.Config.ContentManager.GetSpellData(model, model + "BasicAttack"); AutoAttackDelay = AaSpellData.CastFrame / 30.0f; AutoAttackProjectileSpeed = AaSpellData.MissileSpeed; IsMelee = CharData.IsMelee; diff --git a/GameServerLib/GameObjects/Missiles/Cone.cs b/GameServerLib/GameObjects/Missiles/Cone.cs index 893d49de5..382180056 100644 --- a/GameServerLib/GameObjects/Missiles/Cone.cs +++ b/GameServerLib/GameObjects/Missiles/Cone.cs @@ -34,11 +34,10 @@ public Cone( float angleDeg ) : base(game, x, y, collisionRadius, owner, target, originSpell, 0, effectName, flags) { - SpellData = _game.Config.ContentManager.GetSpellData(effectName); + SpellData = _game.Config.ContentManager.GetSpellData(owner.Model, effectName); _affectAsCastIsOver = affectAsCastIsOver; _angleDeg = angleDeg; - CreateCone(new Target(x, y), target); - + CreateCone(new Target(x, y), target); } public override void Update(float diff) @@ -92,63 +91,63 @@ private bool CheckIfValidTarget(AttackableUnit unit) } if (unit.Team == Owner.Team - && !((SpellData.Flags & (int)SpellFlag.SPELL_FLAG_AFFECT_FRIENDS) > 0)) + && !((SpellData.Flags & (int)SpellFlag.AFFECT_FRIENDS) > 0)) { return false; } if (unit.Team == TeamId.TEAM_NEUTRAL - && !((SpellData.Flags & (int)SpellFlag.SPELL_FLAG_AFFECT_NEUTRAL) > 0)) + && !((SpellData.Flags & (int)SpellFlag.AFFECT_NEUTRAL) > 0)) { return false; } if (unit.Team != Owner.Team && unit.Team != TeamId.TEAM_NEUTRAL - && !((SpellData.Flags & (int)SpellFlag.SPELL_FLAG_AFFECT_ENEMIES) > 0)) + && !((SpellData.Flags & (int)SpellFlag.AFFECT_ENEMIES) > 0)) { return false; } - if (unit.IsDead && !((SpellData.Flags & (int)SpellFlag.SPELL_FLAG_AFFECT_DEAD) > 0)) + if (unit.IsDead && !((SpellData.Flags & (int)SpellFlag.AFFECT_DEAD) > 0)) { return false; } var m = unit as Minion; - if (m != null && !((SpellData.Flags & (int)SpellFlag.SPELL_FLAG_AFFECT_MINIONS) > 0)) + if (m != null && !((SpellData.Flags & (int)SpellFlag.AFFECT_MINIONS) > 0)) { return false; } var p = unit as Placeable; - if (p != null && !((SpellData.Flags & (int)SpellFlag.SPELL_FLAG_AFFECT_USEABLE) > 0)) + if (p != null && !((SpellData.Flags & (int)SpellFlag.AFFECT_USEABLE) > 0)) { return false; } var t = unit as BaseTurret; - if (t != null && !((SpellData.Flags & (int)SpellFlag.SPELL_FLAG_AFFECT_TURRETS) > 0)) + if (t != null && !((SpellData.Flags & (int)SpellFlag.AFFECT_TURRETS) > 0)) { return false; } var i = unit as Inhibitor; var n = unit as Nexus; - if ((i != null || n != null) && !((SpellData.Flags & (int)SpellFlag.SPELL_FLAG_AFFECT_BUILDINGS) > 0)) + if ((i != null || n != null) && !((SpellData.Flags & (int)SpellFlag.AFFECT_BUILDINGS) > 0)) { return false; } var c = unit as Champion; - if (c != null && !((SpellData.Flags & (int)SpellFlag.SPELL_FLAG_AFFECT_HEROES) > 0)) + if (c != null && !((SpellData.Flags & (int)SpellFlag.AFFECT_HEROES) > 0)) { return false; } return true; } - + private void ApplyEffects(AttackableUnit unit) { ObjectsHit.Add(unit); diff --git a/GameServerLib/GameObjects/Missiles/Laser.cs b/GameServerLib/GameObjects/Missiles/Laser.cs index f5672e87c..b37d413c0 100644 --- a/GameServerLib/GameObjects/Missiles/Laser.cs +++ b/GameServerLib/GameObjects/Missiles/Laser.cs @@ -31,9 +31,9 @@ public Laser( int flags, bool affectAsCastIsOver) : base(game, x, y, collisionRadius, owner, target, originSpell, 0, effectName, flags) { - SpellData = _game.Config.ContentManager.GetSpellData(effectName); + SpellData = _game.Config.ContentManager.GetSpellData(owner.Model, effectName); CreateRectangle(new Target(x, y), target); - _affectAsCastIsOver = affectAsCastIsOver; + _affectAsCastIsOver = affectAsCastIsOver; } public override void Update(float diff) @@ -87,56 +87,56 @@ private bool CheckIfValidTarget(AttackableUnit unit) } if (unit.Team == Owner.Team - && !((SpellData.Flags & (int)SpellFlag.SPELL_FLAG_AFFECT_FRIENDS) > 0)) + && !((SpellData.Flags & (int)SpellFlag.AFFECT_FRIENDS) > 0)) { return false; } if (unit.Team == TeamId.TEAM_NEUTRAL - && !((SpellData.Flags & (int)SpellFlag.SPELL_FLAG_AFFECT_NEUTRAL) > 0)) + && !((SpellData.Flags & (int)SpellFlag.AFFECT_NEUTRAL) > 0)) { return false; } if (unit.Team != Owner.Team && unit.Team != TeamId.TEAM_NEUTRAL - && !((SpellData.Flags & (int)SpellFlag.SPELL_FLAG_AFFECT_ENEMIES) > 0)) + && !((SpellData.Flags & (int)SpellFlag.AFFECT_ENEMIES) > 0)) { return false; } - if (unit.IsDead && !((SpellData.Flags & (int)SpellFlag.SPELL_FLAG_AFFECT_DEAD) > 0)) + if (unit.IsDead && !((SpellData.Flags & (int)SpellFlag.AFFECT_DEAD) > 0)) { return false; } var m = unit as Minion; - if (m != null && !((SpellData.Flags & (int)SpellFlag.SPELL_FLAG_AFFECT_MINIONS) > 0)) + if (m != null && !((SpellData.Flags & (int)SpellFlag.AFFECT_MINIONS) > 0)) { return false; } var p = unit as Placeable; - if (p != null && !((SpellData.Flags & (int)SpellFlag.SPELL_FLAG_AFFECT_USEABLE) > 0)) + if (p != null && !((SpellData.Flags & (int)SpellFlag.AFFECT_USEABLE) > 0)) { return false; } var t = unit as BaseTurret; - if (t != null && !((SpellData.Flags & (int)SpellFlag.SPELL_FLAG_AFFECT_TURRETS) > 0)) + if (t != null && !((SpellData.Flags & (int)SpellFlag.AFFECT_TURRETS) > 0)) { return false; } var i = unit as Inhibitor; var n = unit as Nexus; - if ((i != null || n != null) && !((SpellData.Flags & (int)SpellFlag.SPELL_FLAG_AFFECT_BUILDINGS) > 0)) + if ((i != null || n != null) && !((SpellData.Flags & (int)SpellFlag.AFFECT_BUILDINGS) > 0)) { return false; } var c = unit as Champion; - if (c != null && !((SpellData.Flags & (int)SpellFlag.SPELL_FLAG_AFFECT_HEROES) > 0)) + if (c != null && !((SpellData.Flags & (int)SpellFlag.AFFECT_HEROES) > 0)) { return false; } diff --git a/GameServerLib/GameObjects/Missiles/Projectile.cs b/GameServerLib/GameObjects/Missiles/Projectile.cs index d009cf9b1..67dbb26c8 100644 --- a/GameServerLib/GameObjects/Missiles/Projectile.cs +++ b/GameServerLib/GameObjects/Missiles/Projectile.cs @@ -39,7 +39,7 @@ public Projectile( uint netId = 0 ) : base(game, x, y, collisionRadius, 0, netId) { - SpellData = _game.Config.ContentManager.GetSpellData(projectileName); + SpellData = _game.Config.ContentManager.GetSpellData(owner.Model, projectileName); _originSpell = originSpell; _moveSpeed = moveSpeed; Owner = owner; @@ -108,51 +108,51 @@ protected virtual void CheckFlagsForUnit(AttackableUnit unit) } if (unit.Team == Owner.Team - && !((SpellData.Flags & (int)SpellFlag.SPELL_FLAG_AFFECT_FRIENDS) > 0)) + && !((SpellData.Flags & (int)SpellFlag.AFFECT_FRIENDS) > 0)) { return; } if (unit.Team == TeamId.TEAM_NEUTRAL - && !((SpellData.Flags & (int)SpellFlag.SPELL_FLAG_AFFECT_NEUTRAL) > 0)) + && !((SpellData.Flags & (int)SpellFlag.AFFECT_NEUTRAL) > 0)) { return; } if (unit.Team != Owner.Team && unit.Team != TeamId.TEAM_NEUTRAL - && !((SpellData.Flags & (int)SpellFlag.SPELL_FLAG_AFFECT_ENEMIES) > 0)) + && !((SpellData.Flags & (int)SpellFlag.AFFECT_ENEMIES) > 0)) { return; } - if (unit.IsDead && !((SpellData.Flags & (int)SpellFlag.SPELL_FLAG_AFFECT_DEAD) > 0)) + if (unit.IsDead && !((SpellData.Flags & (int)SpellFlag.AFFECT_DEAD) > 0)) { return; } - if (unit is Minion m && !((SpellData.Flags & (int)SpellFlag.SPELL_FLAG_AFFECT_MINIONS) > 0)) + if (unit is Minion m && !((SpellData.Flags & (int)SpellFlag.AFFECT_MINIONS) > 0)) { return; } - if (unit is Placeable p && !((SpellData.Flags & (int)SpellFlag.SPELL_FLAG_AFFECT_USEABLE) > 0)) + if (unit is Placeable p && !((SpellData.Flags & (int)SpellFlag.AFFECT_USEABLE) > 0)) { return; } - if (unit is BaseTurret t && !((SpellData.Flags & (int)SpellFlag.SPELL_FLAG_AFFECT_TURRETS) > 0)) + if (unit is BaseTurret t && !((SpellData.Flags & (int)SpellFlag.AFFECT_TURRETS) > 0)) { return; } - if ((unit is Inhibitor i || unit is Nexus n) && !((SpellData.Flags & (int)SpellFlag.SPELL_FLAG_AFFECT_BUILDINGS) > 0)) + if ((unit is Inhibitor i || unit is Nexus n) && !((SpellData.Flags & (int)SpellFlag.AFFECT_BUILDINGS) > 0)) { return; } - if (unit is Champion c && !((SpellData.Flags & (int)SpellFlag.SPELL_FLAG_AFFECT_HEROES) > 0)) + if (unit is Champion c && !((SpellData.Flags & (int)SpellFlag.AFFECT_HEROES) > 0)) { return; } diff --git a/GameServerLib/GameObjects/Spells/Spell.cs b/GameServerLib/GameObjects/Spells/Spell.cs index a889d4949..8314696dc 100644 --- a/GameServerLib/GameObjects/Spells/Spell.cs +++ b/GameServerLib/GameObjects/Spells/Spell.cs @@ -55,7 +55,7 @@ public Spell(Game game, Champion owner, string spellName, byte slot) SpellName = spellName; Slot = slot; _game = game; - SpellData = game.Config.ContentManager.GetSpellData(spellName); + SpellData = game.Config.ContentManager.GetSpellData(owner.Model, spellName); _scriptEngine = game.ScriptEngine; _networkIdManager = game.NetworkIdManager; @@ -107,7 +107,7 @@ public virtual bool Cast(float x, float y, float x2, float y2, AttackableUnit u _spellGameScript.OnStartCasting(Owner, this, Target); - if (SpellData.GetCastTime() > 0 && (SpellData.Flags & (int)SpellFlag.SPELL_FLAG_INSTANT_CAST) == 0) + if (SpellData.GetCastTime() > 0 && (SpellData.Flags & (int)SpellFlag.INSTANT_CAST) == 0) { Owner.SetPosition(Owner.X, Owner.Y); //stop moving serverside too. TODO: check for each spell if they stop movement or not State = SpellState.STATE_CASTING; diff --git a/GameServerLib/GameServerLib.csproj b/GameServerLib/GameServerLib.csproj index a0d902a2c..42e8089da 100644 --- a/GameServerLib/GameServerLib.csproj +++ b/GameServerLib/GameServerLib.csproj @@ -45,6 +45,10 @@ ..\packages\Crc32.NET.1.2.0\lib\net20\Crc32.NET.dll + + ..\packages\ini-parser.2.5.2\lib\net20\INIFileParser.dll + True + ..\packages\log4net.2.0.8\lib\net45-full\log4net.dll @@ -219,10 +223,9 @@ - - + @@ -266,7 +269,7 @@ - + diff --git a/GameServerLib/Items/Inventory.cs b/GameServerLib/Items/Inventory.cs index a677f7656..8447a1483 100644 --- a/GameServerLib/Items/Inventory.cs +++ b/GameServerLib/Items/Inventory.cs @@ -23,8 +23,8 @@ public Item[] GetBaseItems() { return _items.Take(BASE_INVENTORY_SIZE).ToArray(); } - - public Item AddItem(ItemType item) + + public Item AddItem(ItemData item) { if (item.IsTrinket()) { @@ -39,7 +39,7 @@ public Item AddItem(ItemType item) return AddNewItem(item); } - public Item SetExtraItem(byte slot, ItemType item) + public Item SetExtraItem(byte slot, ItemData item) { if (slot < BASE_INVENTORY_SIZE) { @@ -49,7 +49,7 @@ public Item SetExtraItem(byte slot, ItemType item) return SetItem(slot, item); } - private Item SetItem(byte slot, ItemType item) + private Item SetItem(byte slot, ItemData item) { _items[slot] = Item.CreateFromType(this, item); return _items[slot]; @@ -97,7 +97,7 @@ public void SwapItems(byte slot1, byte slot2) _items[slot2] = buffer; } - private Item AddTrinketItem(ItemType item) + private Item AddTrinketItem(ItemData item) { if (_items[TRINKET_SLOT] != null) { @@ -107,7 +107,7 @@ private Item AddTrinketItem(ItemType item) return SetItem(TRINKET_SLOT, item); } - private Item AddStackingItem(ItemType item) + private Item AddStackingItem(ItemData item) { for (var i = 0; i < BASE_INVENTORY_SIZE; i++) { @@ -116,7 +116,7 @@ private Item AddStackingItem(ItemType item) continue; } - if (item.ItemId != _items[i].ItemType.ItemId) + if (item.ItemId != _items[i].ItemData.ItemId) { continue; } @@ -131,7 +131,7 @@ private Item AddStackingItem(ItemType item) return AddNewItem(item); } - private Item AddNewItem(ItemType item) + private Item AddNewItem(ItemData item) { for (var i = 0; i < BASE_INVENTORY_SIZE; i++) { diff --git a/GameServerLib/Items/InventoryManager.cs b/GameServerLib/Items/InventoryManager.cs index 297b99fff..c8028e22f 100644 --- a/GameServerLib/Items/InventoryManager.cs +++ b/GameServerLib/Items/InventoryManager.cs @@ -14,12 +14,12 @@ private InventoryManager() _inventory = new Inventory(this); } - public Item AddItem(ItemType item) + public Item AddItem(ItemData item) { return _inventory.AddItem(item); } - public Item SetExtraItem(byte slot, ItemType item) + public Item SetExtraItem(byte slot, ItemData item) { return _inventory.SetExtraItem(slot, item); } @@ -54,7 +54,7 @@ public List GetAvailableItems(ItemRecipe recipe) var tempInv = new List(_inventory.GetBaseItems()); return GetAvailableItemsRecursive(ref tempInv, recipe); } - + private static List GetAvailableItemsRecursive(ref List inventoryState, ItemRecipe recipe) { var result = new List(); @@ -65,7 +65,7 @@ private static List GetAvailableItemsRecursive(ref List inventorySta { continue; } - var idx = inventoryState.FindIndex(i => i != null && i.ItemType == component); + var idx = inventoryState.FindIndex(i => i != null && i.ItemData == component); if (idx == -1) { result = result.Concat(GetAvailableItemsRecursive(ref inventoryState, component.Recipe)).ToList(); @@ -95,9 +95,9 @@ byte IInventoryManager.GetItemSlot(IItem item) return GetItemSlot((Item)item); } - IItem IInventoryManager.SetExtraItem(byte slot, IItemType item) + IItem IInventoryManager.SetExtraItem(byte slot, IItemData item) { - return SetExtraItem(slot, (ItemType)item); + return SetExtraItem(slot, (ItemData)item); } IItem IInventoryManager.GetItem(byte slot) diff --git a/GameServerLib/Items/Item.cs b/GameServerLib/Items/Item.cs index 200be6ab6..e7cd6cba6 100644 --- a/GameServerLib/Items/Item.cs +++ b/GameServerLib/Items/Item.cs @@ -5,23 +5,23 @@ namespace LeagueSandbox.GameServer.Items public class Item : IItem { public byte StackSize { get; private set; } - public int TotalPrice => ItemType.TotalPrice; - public ItemType ItemType { get; private set; } + public int TotalPrice { get; private set; } + public ItemData ItemData { get; private set; } - IItemType IItem.ItemType => ItemType; + IItemData IItem.ItemData => ItemData; private Inventory _owner; - private Item(Inventory owner, ItemType type) + private Item(Inventory owner, ItemData data) { _owner = owner; - ItemType = type; + ItemData = data; StackSize = 1; } public bool IncrementStackSize() { - if (StackSize >= ItemType.MaxStack) + if (StackSize >= ItemData.MaxStack) { return false; } @@ -41,7 +41,7 @@ public bool DecrementStackSize() return true; } - public static Item CreateFromType(Inventory inventory, ItemType item) + public static Item CreateFromType(Inventory inventory, ItemData item) { return new Item(inventory, item); } diff --git a/GameServerLib/Items/ItemData.cs b/GameServerLib/Items/ItemData.cs new file mode 100644 index 000000000..466376b29 --- /dev/null +++ b/GameServerLib/Items/ItemData.cs @@ -0,0 +1,129 @@ +using GameServerCore.Domain; +using LeagueSandbox.GameServer.Content; +using LeagueSandbox.GameServer.GameObjects.Stats; + +namespace LeagueSandbox.GameServer.Items +{ + public class ItemData : StatsModifier, IItemData + { + // Meta + public int ItemId { get; private set; } + public string Name { get; private set; } + + // General + public int MaxStack { get; private set; } + public int Price { get; private set; } + public string ItemGroup { get; private set; } + public string SpellName { get; private set; } + public float SellBackModifier { get; private set; } + + // Recipes + public int RecipeItem1 { get; private set; } + public int RecipeItem2 { get; private set; } + public int RecipeItem3 { get; private set; } + public int RecipeItem4 { get; private set; } + + // Not from data + public ItemRecipe Recipe { get; private set; } + public int TotalPrice => Recipe.TotalPrice; + + private void CreateRecipe(ItemManager manager) + { + Recipe = ItemRecipe.FromItemType(this, manager); + } + + public static ItemData Load(ItemManager owner, ContentFile content, int itemId) + { + // Because IntelliSense is nice to have + var result = new ItemData + { + ItemId = itemId, + Name = content.GetString("Data", "DisplayName"), + MaxStack = content.GetInt("Data", "MaxStack"), + Price = content.GetInt("Data", "Price"), + ItemGroup = content.GetString("Data", "ItemGroup"), + SpellName = content.GetString("Data", "SpellName"), + SellBackModifier = content.GetFloat("Data", "SellBackModifier", 0.7f), + + RecipeItem1 = content.GetInt("Data", "RecipeItem1", -1), + RecipeItem2 = content.GetInt("Data", "RecipeItem2", -1), + RecipeItem3 = content.GetInt("Data", "RecipeItem3", -1), + RecipeItem4 = content.GetInt("Data", "RecipeItem4", -1), + Armor = + { + FlatBonus = content.GetFloat("Data", "FlatArmorMod"), + PercentBonus = content.GetFloat("Data", "PercentArmorMod") + }, + CriticalChance = + { + FlatBonus = content.GetFloat("Data", "FlatCritChanceMod") + }, + HealthPoints = + { + FlatBonus = content.GetFloat("Data", "FlatHPPoolMod"), + PercentBonus = content.GetFloat("Data", "PercentHPPoolMod") + }, + ManaPoints = + { + FlatBonus = content.GetFloat("Data", "FlatMPPoolMod"), + PercentBonus = content.GetFloat("Data", "PercentMPPoolMod") + }, + AbilityPower = + { + FlatBonus = content.GetFloat("Data", "FlatMagicDamageMod"), + PercentBonus = content.GetFloat("Data", "PercentMagicDamageMod") + }, + MagicPenetration = + { + FlatBonus = content.GetFloat("Data", "FlatMagicPenetrationMod") + }, + MoveSpeed = + { + FlatBonus = content.GetFloat("Data", "FlatMovementSpeedMod"), + PercentBonus = content.GetFloat("Data", "PercentMovementSpeedMod") + }, + AttackDamage = + { + FlatBonus = content.GetFloat("Data", "FlatPhysicalDamageMod"), + PercentBonus = content.GetFloat("Data", "PercentPhysicalDamageMod") + }, + MagicResist = + { + FlatBonus = content.GetFloat("Data", "FlatSpellBlockMod"), + PercentBonus = content.GetFloat("Data", "PercentSpellBlockMod") + }, + AttackSpeed = + { + FlatBonus = content.GetFloat("Data", "PercentAttackSpeedMod") + }, + HealthRegeneration = + { + PercentBonus = content.GetFloat("Data", "PercentBaseHPRegenMod") + }, + ManaRegeneration = + { + PercentBonus = content.GetFloat("Data", "PercentBaseMPRegenMod") + }, + CriticalDamage = + { + FlatBonus = content.GetFloat("Data", "FlatCritDamageMod"), + PercentBonus = content.GetFloat("Data", "PercentCritDamageMod") + }, + LifeSteel = + { + FlatBonus = content.GetFloat("Data", "PercentLifeStealMod") + } + }; + + //itemInfo.SafeGetFloat("Data", "PercentEXPBonus"); // TODO + + result.CreateRecipe(owner); + return result; + } + + public bool IsTrinket() + { + return ItemGroup.ToLower().Equals("relicbase"); + } + } +} \ No newline at end of file diff --git a/GameServerLib/Items/ItemManager.cs b/GameServerLib/Items/ItemManager.cs index 7dfa8b273..a2906ad63 100644 --- a/GameServerLib/Items/ItemManager.cs +++ b/GameServerLib/Items/ItemManager.cs @@ -1,48 +1,57 @@ using System.Collections.Generic; +using System.IO; +using System.Linq; +using IniParser; using LeagueSandbox.GameServer.Content; namespace LeagueSandbox.GameServer.Items { public class ItemManager { - private Dictionary _itemTypes; + private Dictionary _itemData; public ItemManager() { - _itemTypes = new Dictionary(); + _itemData = new Dictionary(); } - public ItemType GetItemType(int itemId) + public ItemData GetItemType(int itemId) { - return _itemTypes[itemId]; + return _itemData[itemId]; } - public ItemType SafeGetItemType(int itemId, ItemType defaultValue) + public ItemData SafeGetItemType(int itemId, ItemData defaultValue = null) { - if (!_itemTypes.ContainsKey(itemId)) + if (!_itemData.ContainsKey(itemId)) { return defaultValue; } - return _itemTypes[itemId]; + return _itemData[itemId]; } - public ItemType SafeGetItemType(int itemId) + public void LoadItems(ContentManager contentManager) { - return SafeGetItemType(itemId, null); - } - - public void ResetItems() - { - _itemTypes.Clear(); - } - - public void AddItems(ItemContentCollection contentCollection) - { - foreach (var entry in contentCollection) + var iniParser = new FileIniDataParser(); + foreach (var content in contentManager.Content) { - var itemType = ItemType.Load(this, entry.Value); - _itemTypes.Add(entry.Key, itemType); + if (!content.Key.StartsWith("DATA/Items") || !content.Key.EndsWith(".ini")) + { + continue; + } + + var split = content.Key.Split('/'); + var itemIdStr = split.Last().Replace(".ini", ""); + + ContentFile contentFile; + using (var stream = new StreamReader(new MemoryStream(content.Value))) + { + var iniData = iniParser.ReadData(stream); + contentFile = new ContentFile(ContentManager.ParseIniFile(iniData)); + } + + var itemData = ItemData.Load(this, contentFile, int.Parse(itemIdStr)); + _itemData.Add(itemData.ItemId, itemData); } } } diff --git a/GameServerLib/Items/ItemRecipe.cs b/GameServerLib/Items/ItemRecipe.cs index 20e83ff28..79ebc330d 100644 --- a/GameServerLib/Items/ItemRecipe.cs +++ b/GameServerLib/Items/ItemRecipe.cs @@ -5,8 +5,8 @@ namespace LeagueSandbox.GameServer.Items { public class ItemRecipe { - private readonly ItemType _itemType; - private ItemType[] _items; + private ItemData _owner; + private ItemData[] _items; private int _totalPrice; private ItemManager _itemManager; @@ -23,14 +23,14 @@ public int TotalPrice } } - private ItemRecipe(ItemType itemType, ItemManager manager) + private ItemRecipe(ItemData owner, ItemManager manager) { - _itemType = itemType; + _owner = owner; _totalPrice = -1; _itemManager = manager; } - public List GetItems() + public List GetItems() { if (_items == null) { @@ -45,11 +45,11 @@ private void FindRecipeItems(ItemManager itemManager) // TODO: Figure out how to refactor this. _items = new[] { - itemManager.SafeGetItemType(_itemType.RecipeItem1), - itemManager.SafeGetItemType(_itemType.RecipeItem2), - itemManager.SafeGetItemType(_itemType.RecipeItem3), - itemManager.SafeGetItemType(_itemType.RecipeItem4) - }.Where(i => i != null).ToArray(); + itemManager.SafeGetItemType(_owner.RecipeItem1), + itemManager.SafeGetItemType(_owner.RecipeItem2), + itemManager.SafeGetItemType(_owner.RecipeItem3), + itemManager.SafeGetItemType(_owner.RecipeItem4) + }; } private void FindPrice() @@ -57,13 +57,16 @@ private void FindPrice() _totalPrice = 0; foreach (var item in GetItems()) { - _totalPrice += item.TotalPrice; + if (item != null) + { + _totalPrice += item.TotalPrice; + } } - _totalPrice += _itemType.Price; + _totalPrice += _owner.Price; } - public static ItemRecipe FromItemType(ItemType type, ItemManager manager) + public static ItemRecipe FromItemType(ItemData type, ItemManager manager) { return new ItemRecipe(type, manager); } diff --git a/GameServerLib/Items/ItemType.cs b/GameServerLib/Items/ItemType.cs deleted file mode 100644 index 1852b3f4f..000000000 --- a/GameServerLib/Items/ItemType.cs +++ /dev/null @@ -1,138 +0,0 @@ -using GameServerCore.Domain; -using LeagueSandbox.GameServer.Content; -using LeagueSandbox.GameServer.GameObjects.Stats; - -namespace LeagueSandbox.GameServer.Items -{ - public class ItemType : StatsModifier, IItemType - { - //private ItemManager _owner; - private ItemContentCollectionEntry _itemInfo; - - // Meta - public int ItemId { get; private set; } - public string Name { get; private set; } - - // General - public int MaxStack { get; private set; } - public int Price { get; private set; } - public string ItemGroup { get; private set; } - public string SpellName { get; private set; } - public float SellBackModifier { get; private set; } - - // Recipes - public int RecipeItem1 { get; private set; } - public int RecipeItem2 { get; private set; } - public int RecipeItem3 { get; private set; } - public int RecipeItem4 { get; private set; } - - // Not from data - public ItemRecipe Recipe { get; private set; } - public int TotalPrice => Recipe.TotalPrice; - - private ItemType(ItemContentCollectionEntry itemInfo) - { - _itemInfo = itemInfo; - } - - private void CreateRecipe(ItemManager manager) - { - Recipe = ItemRecipe.FromItemType(this, manager); - } - - public static ItemType Load(ItemManager owner, ItemContentCollectionEntry itemInfo) - { - // Because IntelliSense is nice to have - var result = new ItemType(itemInfo) - { - ItemId = itemInfo.ItemId, - Name = itemInfo.Name, - MaxStack = itemInfo.GetInt("Data", "MaxStack"), - Price = itemInfo.GetInt("Data", "Price"), - ItemGroup = itemInfo.GetString("Data", "ItemGroup"), - SpellName = itemInfo.GetString("Data", "SpellName"), - SellBackModifier = itemInfo.GetFloat("Data", "SellBackModifier", 0.7f), - - RecipeItem1 = itemInfo.GetInt("Data", "RecipeItem1", -1), - RecipeItem2 = itemInfo.GetInt("Data", "RecipeItem2", -1), - RecipeItem3 = itemInfo.GetInt("Data", "RecipeItem3", -1), - RecipeItem4 = itemInfo.GetInt("Data", "RecipeItem4", -1), - Armor = - { - FlatBonus = itemInfo.GetFloat("Data", "FlatArmorMod"), - PercentBonus = itemInfo.GetFloat("Data", "PercentArmorMod") - }, - CriticalChance = - { - FlatBonus = itemInfo.GetFloat("Data", "FlatCritChanceMod") - }, - HealthPoints = - { - FlatBonus = itemInfo.GetFloat("Data", "FlatHPPoolMod"), - PercentBonus = itemInfo.GetFloat("Data", "PercentHPPoolMod") - }, - ManaPoints = - { - FlatBonus = itemInfo.GetFloat("Data", "FlatMPPoolMod"), - PercentBonus = itemInfo.GetFloat("Data", "PercentMPPoolMod") - }, - AbilityPower = - { - FlatBonus = itemInfo.GetFloat("Data", "FlatMagicDamageMod"), - PercentBonus = itemInfo.GetFloat("Data", "PercentMagicDamageMod") - }, - MagicPenetration = - { - FlatBonus = itemInfo.GetFloat("Data", "FlatMagicPenetrationMod") - }, - MoveSpeed = - { - FlatBonus = itemInfo.GetFloat("Data", "FlatMovementSpeedMod"), - PercentBonus = itemInfo.GetFloat("Data", "PercentMovementSpeedMod") - }, - AttackDamage = - { - FlatBonus = itemInfo.GetFloat("Data", "FlatPhysicalDamageMod"), - PercentBonus = itemInfo.GetFloat("Data", "PercentPhysicalDamageMod") - }, - MagicResist = - { - FlatBonus = itemInfo.GetFloat("Data", "FlatSpellBlockMod"), - PercentBonus = itemInfo.GetFloat("Data", "PercentSpellBlockMod") - }, - AttackSpeed = - { - FlatBonus = itemInfo.GetFloat("Data", "PercentAttackSpeedMod") - }, - HealthRegeneration = - { - PercentBonus = itemInfo.GetFloat("Data", "PercentBaseHPRegenMod") - }, - ManaRegeneration = - { - PercentBonus = itemInfo.GetFloat("Data", "PercentBaseMPRegenMod") - }, - CriticalDamage = - { - FlatBonus = itemInfo.GetFloat("Data", "FlatCritDamageMod"), - PercentBonus = itemInfo.GetFloat("Data", "PercentCritDamageMod") - }, - LifeSteel = - { - FlatBonus = itemInfo.GetFloat("Data", "PercentLifeStealMod") - } - }; - - //itemInfo.SafeGetFloat("Data", "PercentEXPBonus"); // TODO - - result.CreateRecipe(owner); - return result; - } - - public bool IsTrinket() - { - return ItemGroup.ToLower().Equals("relicbase"); - } - } - -} \ No newline at end of file diff --git a/GameServerLib/Items/Shop.cs b/GameServerLib/Items/Shop.cs index 4c949eadc..8c1ad4b8d 100644 --- a/GameServerLib/Items/Shop.cs +++ b/GameServerLib/Items/Shop.cs @@ -9,7 +9,7 @@ public class Shop private readonly Game _game; public const byte ITEM_ACTIVE_OFFSET = 6; - + private Shop(Champion owner, Game game) { _owner = owner; @@ -25,10 +25,10 @@ public bool HandleItemSellRequest(byte slotId) return false; } - var sellPrice = i.TotalPrice * i.ItemType.SellBackModifier; + var sellPrice = i.TotalPrice * i.ItemData.SellBackModifier; _owner.Stats.Gold += sellPrice; - if (i.ItemType.MaxStack > 1) + if (i.ItemData.MaxStack > 1) { i.DecrementStackSize(); } @@ -51,7 +51,7 @@ public bool HandleItemBuyRequest(int itemId) if (ownedItems.Count != 0) { - price -= ownedItems.Sum(item => item.ItemType.TotalPrice); + price -= ownedItems.Sum(item => item.ItemData.TotalPrice); if (stats.Gold < price) { return false; @@ -76,24 +76,24 @@ public bool HandleItemBuyRequest(int itemId) private void RemoveItem(Item item, byte slotId, byte stackSize = 0) { var inventory = _owner.Inventory; - _owner.Stats.RemoveModifier(item.ItemType); + _owner.Stats.RemoveModifier(item.ItemData); _game.PacketNotifier.NotifyRemoveItem(_owner, slotId, stackSize); _owner.RemoveSpell((byte)(slotId + ITEM_ACTIVE_OFFSET)); inventory.RemoveItem(item); } - private bool AddItem(ItemType itemType) + private bool AddItem(ItemData ıtemData) { - var i = _owner.Inventory.AddItem(itemType); + var i = _owner.Inventory.AddItem(ıtemData); if (i == null) { return false; } - _owner.Stats.AddModifier(itemType); + _owner.Stats.AddModifier(ıtemData); _game.PacketNotifier.NotifyItemBought(_owner, i); - if (!string.IsNullOrEmpty(i.ItemType.SpellName)) + if (!string.IsNullOrEmpty(i.ItemData.SpellName)) { - _owner.SetSpell(i.ItemType.SpellName, (byte)(_owner.Inventory.GetItemSlot(i) + ITEM_ACTIVE_OFFSET), true); + _owner.SetSpell(i.ItemData.SpellName, (byte)(_owner.Inventory.GetItemSlot(i) + ITEM_ACTIVE_OFFSET), true); } return true; } diff --git a/GameServerLib/Maps/Map.cs b/GameServerLib/Maps/Map.cs index d7f55eafc..e62bd0fbe 100644 --- a/GameServerLib/Maps/Map.cs +++ b/GameServerLib/Maps/Map.cs @@ -29,23 +29,7 @@ public Map(Game game) _game = game; _logger = LoggerProvider.GetLogger(); Id = _game.Config.GameConfig.Map; - var path = Path.Combine( - game.Config.ContentPath, - _game.Config.ContentManager.GameModeName, - "AIMesh", - "Map" + Id, - "AIPath.aimesh_ngrid" - ); - - if (File.Exists(path)) - { - NavGrid = NavGridReader.ReadBinary(path); - } - else - { - _logger.Error("Failed to load navigation graph. Aborting map load."); - return; - } + NavGrid = _game.Config.ContentManager.GetNavGrid(Id); AnnouncerEvents = new List(); CollisionHandler = new CollisionHandler(_game, this); diff --git a/GameServerLib/Scripting/CSharp/CSharpScriptEngine.cs b/GameServerLib/Scripting/CSharp/CSharpScriptEngine.cs index 868a8ddc8..0111d5027 100644 --- a/GameServerLib/Scripting/CSharp/CSharpScriptEngine.cs +++ b/GameServerLib/Scripting/CSharp/CSharpScriptEngine.cs @@ -21,31 +21,15 @@ public CSharpScriptEngine() _logger = LoggerProvider.GetLogger(); } - public bool LoadSubdirectoryScripts(string folder) - { - var basePath = Path.GetFullPath(folder); - var allfiles = Directory.GetFiles(folder, "*.cs", SearchOption.AllDirectories).Where((string pathString) => { - var fileBasePath = Path.GetFullPath(pathString); - var trimmedPath = fileBasePath.Remove(0, basePath.Length); - string[] directories = trimmedPath.ToLower().Split(Path.DirectorySeparatorChar); - if (directories.Contains("bin") || directories.Contains("obj")) - { - return false; - } - return true; - }); - return Load(new List(allfiles)); - } - //Takes about 300 milliseconds for a single script - public bool Load(List scriptLocations) + public bool LoadFromData(Dictionary scriptFiles) { bool compiledSuccessfully; var treeList = new List(); - Parallel.For(0, scriptLocations.Count, i => + Parallel.ForEach(scriptFiles, keyValuePair => { - _logger.Debug($"Loading script: {scriptLocations[i]}"); - using (var sr = new StreamReader(scriptLocations[i])) + _logger.Debug($"Loading script: {keyValuePair.Key}"); + using (var sr = new StreamReader(new MemoryStream(keyValuePair.Value))) { // Read the stream to a string, and write the string to the console. var syntaxTree = CSharpSyntaxTree.ParseText(sr.ReadToEnd()); @@ -55,6 +39,7 @@ public bool Load(List scriptLocations) } } }); + var assemblyName = Path.GetRandomFileName(); var references = new List(); diff --git a/GameServerLib/packages.config b/GameServerLib/packages.config index abf362ee0..2495d25f2 100644 --- a/GameServerLib/packages.config +++ b/GameServerLib/packages.config @@ -2,6 +2,7 @@ + diff --git a/GameServerLibTests/Tests/Items/TestInventoryManager.cs b/GameServerLibTests/Tests/Items/TestInventoryManager.cs index 8b6172af5..9fb6b4c86 100644 --- a/GameServerLibTests/Tests/Items/TestInventoryManager.cs +++ b/GameServerLibTests/Tests/Items/TestInventoryManager.cs @@ -1,4 +1,5 @@ using System; +using LeagueSandbox.GameServer; using LeagueSandbox.GameServer.Content; using LeagueSandbox.GameServer.Items; using Microsoft.VisualStudio.TestTools.UnitTesting; @@ -12,7 +13,9 @@ public class InventoryManagerTests public void TestAddAndGetItem() { var itemManager = new ItemManager(); - itemManager.AddItems(ItemContentCollection.LoadItemsFrom("../../../Content")); + var contentMgr = + ContentManager.LoadGameMode(new Game(itemManager), "LeagueSandbox-Default", "../../../Content"); + itemManager.LoadItems(contentMgr); var inventoryManager = InventoryManager.CreateInventory(); @@ -50,7 +53,9 @@ public void TestAddAndGetItem() public void TestItemStacking() { var itemManager = new ItemManager(); - itemManager.AddItems(ItemContentCollection.LoadItemsFrom("../../../Content")); + var contentMgr = + ContentManager.LoadGameMode(new Game(itemManager), "LeagueSandbox-Default", "../../../Content"); + itemManager.LoadItems(contentMgr); var manager = InventoryManager.CreateInventory(); @@ -90,7 +95,9 @@ public void TestItemStacking() public void TestSetExtraItem() { var itemManager = new ItemManager(); - itemManager.AddItems(ItemContentCollection.LoadItemsFrom("../../../Content")); + var contentMgr = + ContentManager.LoadGameMode(new Game(itemManager), "LeagueSandbox-Default", "../../../Content"); + itemManager.LoadItems(contentMgr); var manager = InventoryManager.CreateInventory(); @@ -115,7 +122,9 @@ public void TestSetExtraItem() public void TestGetItemSlot() { var itemManager = new ItemManager(); - itemManager.AddItems(ItemContentCollection.LoadItemsFrom("../../../Content")); + var contentMgr = + ContentManager.LoadGameMode(new Game(itemManager), "LeagueSandbox-Default", "../../../Content"); + itemManager.LoadItems(contentMgr); var manager = InventoryManager.CreateInventory(); @@ -146,7 +155,9 @@ public void TestGetItemSlot() public void TestRemoveItem() { var itemManager = new ItemManager(); - itemManager.AddItems(ItemContentCollection.LoadItemsFrom("../../../Content")); + var contentMgr = + ContentManager.LoadGameMode(new Game(itemManager), "LeagueSandbox-Default", "../../../Content"); + itemManager.LoadItems(contentMgr); var manager = InventoryManager.CreateInventory(); @@ -171,7 +182,9 @@ public void TestRemoveItem() public void TestSwapItems() { var itemManager = new ItemManager(); - itemManager.AddItems(ItemContentCollection.LoadItemsFrom("../../../Content")); + var contentMgr = + ContentManager.LoadGameMode(new Game(itemManager), "LeagueSandbox-Default", "../../../Content"); + itemManager.LoadItems(contentMgr); var manager = InventoryManager.CreateInventory(); @@ -221,8 +234,9 @@ public void TestSwapItems() public void TestGetAvailableItems() { var itemManager = new ItemManager(); - itemManager.ResetItems(); - itemManager.AddItems(ItemContentCollection.LoadItemsFrom("../../../Content")); + var contentMgr = + ContentManager.LoadGameMode(new Game(itemManager), "LeagueSandbox-Default", "../../../Content"); + itemManager.LoadItems(contentMgr); var manager = InventoryManager.CreateInventory(); diff --git a/PacketDefinitions420/PacketDefinitions/S2C/BuyItemResponse.cs b/PacketDefinitions420/PacketDefinitions/S2C/BuyItemResponse.cs index 0eb41fefc..da3defd46 100644 --- a/PacketDefinitions420/PacketDefinitions/S2C/BuyItemResponse.cs +++ b/PacketDefinitions420/PacketDefinitions/S2C/BuyItemResponse.cs @@ -9,7 +9,7 @@ public class BuyItemResponse : BasePacket public BuyItemResponse(IAttackableUnit actor, IItem item, byte unk = 0x29) : base(PacketCmd.PKT_S2C_BUY_ITEM_ANS, actor.NetId) { - Write((int)item.ItemType.ItemId); + Write((int)item.ItemData.ItemId); Write((byte)actor.Inventory.GetItemSlot(item)); Write((byte)item.StackSize); Write((byte)0); //unk or stacks => short diff --git a/PacketDefinitions420/PacketServer.cs b/PacketDefinitions420/PacketServer.cs index ff99b373c..7783c0bed 100644 --- a/PacketDefinitions420/PacketServer.cs +++ b/PacketDefinitions420/PacketServer.cs @@ -14,7 +14,7 @@ public class PacketServer private uint _serverHost = Address.IPv4HostAny; public IPacketHandlerManager PacketHandlerManager { get; private set; } - + private IGame _game; @@ -35,7 +35,7 @@ public void InitServer(ushort port, string blowfishKey, IGame game) Blowfish = new BlowFish(key); PacketHandlerManager = new PacketHandlerManager(Blowfish, _server, game); - + } public void NetLoop() { From 322b5252c8a8a4b2efc39880e0b909e208cfe93c Mon Sep 17 00:00:00 2001 From: Furkan SAMANLI Date: Fri, 5 Oct 2018 21:54:15 +0300 Subject: [PATCH 2/6] Fixed requests --- GameServerCore/Domain/IItemData.cs | 6 +----- GameServerLib/Content/ContentManager.cs | 25 +++++++------------------ GameServerLib/Items/ItemData.cs | 19 ++++++++----------- GameServerLib/Items/ItemRecipe.cs | 11 +++++------ GameServerLib/Items/Shop.cs | 8 ++++---- 5 files changed, 25 insertions(+), 44 deletions(-) diff --git a/GameServerCore/Domain/IItemData.cs b/GameServerCore/Domain/IItemData.cs index d7d014494..889c0a223 100644 --- a/GameServerCore/Domain/IItemData.cs +++ b/GameServerCore/Domain/IItemData.cs @@ -8,11 +8,7 @@ public interface IItemData int Price { get; } string ItemGroup { get; } float SellBackModifier { get; } - int RecipeItem1 { get; } - int RecipeItem2 { get; } - int RecipeItem3 { get; } - int RecipeItem4 { get; } + int[] RecipeItems { get; } int TotalPrice { get; } - } } diff --git a/GameServerLib/Content/ContentManager.cs b/GameServerLib/Content/ContentManager.cs index ddd089942..155c5bb7f 100644 --- a/GameServerLib/Content/ContentManager.cs +++ b/GameServerLib/Content/ContentManager.cs @@ -39,15 +39,10 @@ public string GetMapConfigPath(int mapId) $"LEVELS/map{mapId}/Map{mapId}.json" }; - foreach (var path in possibilities) - { - if (Content.ContainsKey(path)) - { - return path; - } - } - - throw new ContentNotFoundException($"Map configuration for Map {mapId} was not found in the content."); + return possibilities.FirstOrDefault(path => Content.ContainsKey(path)) + ?? throw new ContentNotFoundException( + $"Map configuration for Map {mapId} was not found in the content." + ); } public string GetUnitStatPath(string model) @@ -70,15 +65,8 @@ public string GetSpellDataPath(string model, string spellName) $"DATA/Spells/{spellName}.ini" }; - foreach (var path in possibilities) - { - if (Content.ContainsKey(path)) - { - return path; - } - } - - throw new ContentNotFoundException($"Spell data for {spellName} was not found."); + return possibilities.FirstOrDefault(path => Content.ContainsKey(path)) + ?? throw new ContentNotFoundException($"Spell data for {spellName} was not found."); } public SpellData GetSpellData(string champ, string spellName) @@ -112,6 +100,7 @@ public NavGrid GetNavGrid(int mapId) $"LEVELS/Map{mapId}/AIPath.aimesh_ngrid", $"LEVELS/map{mapId}/AIPath.aimesh_ngrid" }; + foreach (var path in possibilities) { if (_navGrids.ContainsKey(path)) diff --git a/GameServerLib/Items/ItemData.cs b/GameServerLib/Items/ItemData.cs index 466376b29..a2b28d81f 100644 --- a/GameServerLib/Items/ItemData.cs +++ b/GameServerLib/Items/ItemData.cs @@ -17,11 +17,8 @@ public class ItemData : StatsModifier, IItemData public string SpellName { get; private set; } public float SellBackModifier { get; private set; } - // Recipes - public int RecipeItem1 { get; private set; } - public int RecipeItem2 { get; private set; } - public int RecipeItem3 { get; private set; } - public int RecipeItem4 { get; private set; } + // Recipe + public int[] RecipeItems { get; private set; } = new int[4]; // Not from data public ItemRecipe Recipe { get; private set; } @@ -44,11 +41,6 @@ public static ItemData Load(ItemManager owner, ContentFile content, int itemId) ItemGroup = content.GetString("Data", "ItemGroup"), SpellName = content.GetString("Data", "SpellName"), SellBackModifier = content.GetFloat("Data", "SellBackModifier", 0.7f), - - RecipeItem1 = content.GetInt("Data", "RecipeItem1", -1), - RecipeItem2 = content.GetInt("Data", "RecipeItem2", -1), - RecipeItem3 = content.GetInt("Data", "RecipeItem3", -1), - RecipeItem4 = content.GetInt("Data", "RecipeItem4", -1), Armor = { FlatBonus = content.GetFloat("Data", "FlatArmorMod"), @@ -115,6 +107,11 @@ public static ItemData Load(ItemManager owner, ContentFile content, int itemId) } }; + for (var i = 0; i < 4; i++) + { + result.RecipeItems[i] = content.GetInt("Data", $"RecipeItem{i + 1}", -1); + } + //itemInfo.SafeGetFloat("Data", "PercentEXPBonus"); // TODO result.CreateRecipe(owner); @@ -123,7 +120,7 @@ public static ItemData Load(ItemManager owner, ContentFile content, int itemId) public bool IsTrinket() { - return ItemGroup.ToLower().Equals("relicbase"); + return ItemGroup.ToLowerInvariant().Equals("relicbase"); } } } \ No newline at end of file diff --git a/GameServerLib/Items/ItemRecipe.cs b/GameServerLib/Items/ItemRecipe.cs index 79ebc330d..054290b5a 100644 --- a/GameServerLib/Items/ItemRecipe.cs +++ b/GameServerLib/Items/ItemRecipe.cs @@ -43,13 +43,12 @@ public List GetItems() private void FindRecipeItems(ItemManager itemManager) { // TODO: Figure out how to refactor this. - _items = new[] + _items = new ItemData[4]; + + for (var i = 0; i < 4; i++) { - itemManager.SafeGetItemType(_owner.RecipeItem1), - itemManager.SafeGetItemType(_owner.RecipeItem2), - itemManager.SafeGetItemType(_owner.RecipeItem3), - itemManager.SafeGetItemType(_owner.RecipeItem4) - }; + _items[i] = itemManager.SafeGetItemType(_owner.RecipeItems[i]); + } } private void FindPrice() diff --git a/GameServerLib/Items/Shop.cs b/GameServerLib/Items/Shop.cs index 8c1ad4b8d..996caede4 100644 --- a/GameServerLib/Items/Shop.cs +++ b/GameServerLib/Items/Shop.cs @@ -68,7 +68,7 @@ public bool HandleItemBuyRequest(int itemId) { return false; } - + stats.Gold -= price; return true; } @@ -82,14 +82,14 @@ private void RemoveItem(Item item, byte slotId, byte stackSize = 0) inventory.RemoveItem(item); } - private bool AddItem(ItemData ıtemData) + private bool AddItem(ItemData itemData) { - var i = _owner.Inventory.AddItem(ıtemData); + var i = _owner.Inventory.AddItem(itemData); if (i == null) { return false; } - _owner.Stats.AddModifier(ıtemData); + _owner.Stats.AddModifier(itemData); _game.PacketNotifier.NotifyItemBought(_owner, i); if (!string.IsNullOrEmpty(i.ItemData.SpellName)) { From c40c71bf435edb2c46dfde5bfa8b431db58bd42e Mon Sep 17 00:00:00 2001 From: Furkan SAMANLI Date: Fri, 5 Oct 2018 23:33:52 +0300 Subject: [PATCH 3/6] Even more changes --- Content/LeagueSandbox-Default | 2 +- GameServerCore/Content/HashFunctions.cs | 2 +- GameServerLib/Content/ContentManager.cs | 8 +++----- GameServerLib/Items/ItemData.cs | 4 ++-- GameServerLib/Items/ItemRecipe.cs | 4 ++-- GameServerLib/Program.cs | 1 + 6 files changed, 10 insertions(+), 11 deletions(-) diff --git a/Content/LeagueSandbox-Default b/Content/LeagueSandbox-Default index f1dbca1e8..d765f891f 160000 --- a/Content/LeagueSandbox-Default +++ b/Content/LeagueSandbox-Default @@ -1 +1 @@ -Subproject commit f1dbca1e827d5d940bbb170022650fa13ef9bd57 +Subproject commit d765f891ff3eabd9ce95a9ca054bf7e03ed8e279 diff --git a/GameServerCore/Content/HashFunctions.cs b/GameServerCore/Content/HashFunctions.cs index ed35d5b89..85b8b3494 100644 --- a/GameServerCore/Content/HashFunctions.cs +++ b/GameServerCore/Content/HashFunctions.cs @@ -23,7 +23,7 @@ public static uint HashStringSdbm(string data) uint hash = 0; foreach (var c in data) { - hash = char.ToLower(c) + 65599 * hash; + hash = char.ToLowerInvariant(c) + 65599 * hash; } return hash; diff --git a/GameServerLib/Content/ContentManager.cs b/GameServerLib/Content/ContentManager.cs index 155c5bb7f..a03b37e6c 100644 --- a/GameServerLib/Content/ContentManager.cs +++ b/GameServerLib/Content/ContentManager.cs @@ -1,5 +1,4 @@ -using System; -using System.Collections.Generic; +using System.Collections.Generic; using System.IO; using System.IO.Compression; using System.Linq; @@ -7,7 +6,6 @@ using LeagueSandbox.GameServer.Logging; using log4net; using LeagueSandbox.GameServer.Exceptions; -using Newtonsoft.Json.Linq; namespace LeagueSandbox.GameServer.Content { @@ -41,8 +39,8 @@ public string GetMapConfigPath(int mapId) return possibilities.FirstOrDefault(path => Content.ContainsKey(path)) ?? throw new ContentNotFoundException( - $"Map configuration for Map {mapId} was not found in the content." - ); + $"Map configuration for Map {mapId} was not found in the content." + ); } public string GetUnitStatPath(string model) diff --git a/GameServerLib/Items/ItemData.cs b/GameServerLib/Items/ItemData.cs index a2b28d81f..a399eea46 100644 --- a/GameServerLib/Items/ItemData.cs +++ b/GameServerLib/Items/ItemData.cs @@ -18,7 +18,7 @@ public class ItemData : StatsModifier, IItemData public float SellBackModifier { get; private set; } // Recipe - public int[] RecipeItems { get; private set; } = new int[4]; + public int[] RecipeItems { get; private set; } = new int[8]; // Not from data public ItemRecipe Recipe { get; private set; } @@ -107,7 +107,7 @@ public static ItemData Load(ItemManager owner, ContentFile content, int itemId) } }; - for (var i = 0; i < 4; i++) + for (var i = 0; i < 8; i++) { result.RecipeItems[i] = content.GetInt("Data", $"RecipeItem{i + 1}", -1); } diff --git a/GameServerLib/Items/ItemRecipe.cs b/GameServerLib/Items/ItemRecipe.cs index 054290b5a..44939e764 100644 --- a/GameServerLib/Items/ItemRecipe.cs +++ b/GameServerLib/Items/ItemRecipe.cs @@ -43,9 +43,9 @@ public List GetItems() private void FindRecipeItems(ItemManager itemManager) { // TODO: Figure out how to refactor this. - _items = new ItemData[4]; + _items = new ItemData[8]; - for (var i = 0; i < 4; i++) + for (var i = 0; i < 8; i++) { _items[i] = itemManager.SafeGetItemType(_owner.RecipeItems[i]); } diff --git a/GameServerLib/Program.cs b/GameServerLib/Program.cs index 072962175..acd858488 100644 --- a/GameServerLib/Program.cs +++ b/GameServerLib/Program.cs @@ -1,3 +1,4 @@ +using System; using LeagueSandbox.GameServer.Logging; using log4net; using LeagueSandbox.GameServer.Items; From a3b5ae70f6f1d9d5bc0f771bb01afc5ee626b576 Mon Sep 17 00:00:00 2001 From: Furkan SAMANLI Date: Sat, 6 Oct 2018 13:08:52 +0300 Subject: [PATCH 4/6] Idk what I changed either --- Content/LeagueSandbox-Default | 2 +- GameServerCore/GameServerCore.csproj | 3 --- GameServerCore/packages.config | 3 --- GameServerLib/Content/CharData.cs | 2 +- GameServerLib/GameServerLib.csproj | 7 ++----- 5 files changed, 4 insertions(+), 13 deletions(-) delete mode 100644 GameServerCore/packages.config diff --git a/Content/LeagueSandbox-Default b/Content/LeagueSandbox-Default index d765f891f..5068a5256 160000 --- a/Content/LeagueSandbox-Default +++ b/Content/LeagueSandbox-Default @@ -1 +1 @@ -Subproject commit d765f891ff3eabd9ce95a9ca054bf7e03ed8e279 +Subproject commit 5068a52561081386d5fee1496cd090d709e1386c diff --git a/GameServerCore/GameServerCore.csproj b/GameServerCore/GameServerCore.csproj index 8e8faf01c..a49341e46 100644 --- a/GameServerCore/GameServerCore.csproj +++ b/GameServerCore/GameServerCore.csproj @@ -144,8 +144,5 @@ - - - \ No newline at end of file diff --git a/GameServerCore/packages.config b/GameServerCore/packages.config deleted file mode 100644 index 6b8deb9c9..000000000 --- a/GameServerCore/packages.config +++ /dev/null @@ -1,3 +0,0 @@ - - - \ No newline at end of file diff --git a/GameServerLib/Content/CharData.cs b/GameServerLib/Content/CharData.cs index 9d64cf17b..a2971b22c 100644 --- a/GameServerLib/Content/CharData.cs +++ b/GameServerLib/Content/CharData.cs @@ -45,7 +45,7 @@ public CharData(Game game) public float HpRegenPerLevel { get; private set; } public float MpRegenPerLevel { get; private set; } public float AttackSpeedPerLevel { get; private set; } - public bool IsMelee { get; private set; } //Yes or no + public bool IsMelee { get; private set; } //Yes or No public float PathfindingCollisionRadius { get; private set; } = -1.0f; public float GameplayCollisionRadius { get; private set; } = 65.0f; public PrimaryAbilityResourceType ParType { get; private set; } = PrimaryAbilityResourceType.MANA; diff --git a/GameServerLib/GameServerLib.csproj b/GameServerLib/GameServerLib.csproj index 42e8089da..f5c775de1 100644 --- a/GameServerLib/GameServerLib.csproj +++ b/GameServerLib/GameServerLib.csproj @@ -45,9 +45,8 @@ ..\packages\Crc32.NET.1.2.0\lib\net20\Crc32.NET.dll - + ..\packages\ini-parser.2.5.2\lib\net20\INIFileParser.dll - True ..\packages\log4net.2.0.8\lib\net45-full\log4net.dll @@ -349,9 +348,7 @@ - - - + From 80b3f672472906bcefd835d02b5343240e7d67bc Mon Sep 17 00:00:00 2001 From: Furkan SAMANLI Date: Wed, 10 Oct 2018 22:44:59 +0300 Subject: [PATCH 5/6] Changed according to moon's requests --- GameServerLib/Config.cs | 7 +- GameServerLib/Content/CharData.cs | 2 +- GameServerLib/Content/ContentManager.cs | 93 +++++++++++-------------- GameServerLib/Content/FileEntry.cs | 38 ++++++++++ GameServerLib/Content/NavGrid.cs | 13 ++-- GameServerLib/Content/SpellData.cs | 2 +- GameServerLib/Game.cs | 9 ++- GameServerLib/GameServerLib.csproj | 1 + GameServerLib/Items/ItemManager.cs | 2 +- 9 files changed, 103 insertions(+), 64 deletions(-) create mode 100644 GameServerLib/Content/FileEntry.cs diff --git a/GameServerLib/Config.cs b/GameServerLib/Config.cs index c41ec0c21..066337494 100644 --- a/GameServerLib/Config.cs +++ b/GameServerLib/Config.cs @@ -77,7 +77,12 @@ private void LoadConfig(Game game, string json) // Read spawns info ContentManager = ContentManager.LoadGameMode(game, GameConfig.GameMode, ContentPath); var mapPath = ContentManager.GetMapConfigPath(GameConfig.Map); - var mapData = JObject.Parse(Encoding.UTF8.GetString(ContentManager.Content[mapPath])); + JObject mapData; + using (var stream = new BinaryReader(ContentManager.Content[mapPath].ReadFile())) + { + mapData = JObject.Parse(Encoding.UTF8.GetString(stream.ReadBytes((int)stream.BaseStream.Length))); + } + var spawns = mapData.SelectToken("spawns"); // Load items diff --git a/GameServerLib/Content/CharData.cs b/GameServerLib/Content/CharData.cs index a2971b22c..e38eb5dde 100644 --- a/GameServerLib/Content/CharData.cs +++ b/GameServerLib/Content/CharData.cs @@ -86,7 +86,7 @@ public void Load(string name) var path = _game.Config.ContentManager.GetUnitStatPath(name); var iniParser = new FileIniDataParser(); _logger.Debug($"Loading {name}'s Stats from path: {path}!"); - using (var stream = new StreamReader(new MemoryStream(_game.Config.ContentManager.Content[path]))) + using (var stream = new StreamReader(_game.Config.ContentManager.Content[path].ReadFile())) { var iniData = iniParser.ReadData(stream); file = new ContentFile(ContentManager.ParseIniFile(iniData)); diff --git a/GameServerLib/Content/ContentManager.cs b/GameServerLib/Content/ContentManager.cs index a03b37e6c..37d4e510e 100644 --- a/GameServerLib/Content/ContentManager.cs +++ b/GameServerLib/Content/ContentManager.cs @@ -1,4 +1,5 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; using System.IO; using System.IO.Compression; using System.Linq; @@ -18,7 +19,9 @@ public class ContentManager private Dictionary _charData = new Dictionary(); private Dictionary _navGrids = new Dictionary(); - public Dictionary Content { get; set; } = new Dictionary(); + public Dictionary Content { get; set; } + = new Dictionary(StringComparer.InvariantCultureIgnoreCase); + public string GameModeName { get; } private ContentManager(Game game, string gameModeName) @@ -31,16 +34,13 @@ private ContentManager(Game game, string gameModeName) public string GetMapConfigPath(int mapId) { - var possibilities = new[] + var path = $"LEVELS/Map{mapId}/Map{mapId}.json"; + if (!Content.ContainsKey(path)) { - $"LEVELS/Map{mapId}/Map{mapId}.json", - $"LEVELS/map{mapId}/Map{mapId}.json" - }; + throw new ContentNotFoundException($"Map configuration for Map {mapId} was not found in the content."); + } - return possibilities.FirstOrDefault(path => Content.ContainsKey(path)) - ?? throw new ContentNotFoundException( - $"Map configuration for Map {mapId} was not found in the content." - ); + return path; } public string GetUnitStatPath(string model) @@ -93,21 +93,14 @@ public CharData GetCharData(string charName) public NavGrid GetNavGrid(int mapId) { - var possibilities = new[] - { - $"LEVELS/Map{mapId}/AIPath.aimesh_ngrid", - $"LEVELS/map{mapId}/AIPath.aimesh_ngrid" - }; + var path = $"LEVELS/Map{mapId}/AIPath.aimesh_ngrid"; - foreach (var path in possibilities) + if (!_navGrids.ContainsKey(path)) { - if (_navGrids.ContainsKey(path)) - { - return _navGrids[path]; - } + throw new ContentNotFoundException($"NavGrid for map {mapId} was not loaded."); } - throw new ContentNotFoundException($"NavGrid for map {mapId} was not loaded."); + return _navGrids[path]; } public static ContentManager LoadGameMode(Game game, string gameModeName, string contentPath) @@ -128,36 +121,34 @@ public static ContentManager LoadGameMode(Game game, string gameModeName, string // For every entry in the zip foreach (var entry in zip.Entries) { - // Uncompress the entry and read it - using (var entryData = new BinaryReader(entry.Open())) + // If file is aimesh_ngrid, load it up + if (entry.FullName.EndsWith(".aimesh_ngrid")) { - if (entry.FullName.EndsWith(".ini") || entry.FullName.EndsWith(".json")) - { - contentManager.Content[entry.FullName] = entryData.ReadBytes((int)entry.Length); - } - else if (entry.FullName.EndsWith(".aimesh_ngrid")) + using (var reader = new BinaryReader(entry.Open())) { contentManager._navGrids[entry.FullName] = - NavGridReader.ReadBinary(entryData.ReadBytes((int)entry.Length)); - - contentManager.Content[entry.FullName] = entryData.ReadBytes((int)entry.Length); + NavGridReader.ReadBinary(reader.ReadBytes((int)entry.Length)); } - else if (entry.FullName.EndsWith(".cs")) - { - if (entry.FullName.StartsWith("bin") || entry.FullName.StartsWith("obj")) - { - continue; - } - - contentManager.Content[entry.FullName] = entryData.ReadBytes((int)entry.Length); - } - else + } + // if file is cs and is not in either "bin" or "obj" folder, load it + else if (entry.FullName.EndsWith(".cs")) + { + if (entry.FullName.StartsWith("bin") || entry.FullName.StartsWith("obj")) { continue; } - - contentManager._logger.Debug($"Mapped content from zip [{entry.FullName}]"); } + // if file is ini or json, load them too, otherwise skip it + else if (!entry.FullName.EndsWith(".ini") && !entry.FullName.EndsWith(".json")) + { + continue; + } + + // loading is put here to have less duplicate code + contentManager.Content[entry.FullName] = + new FileEntry(entry.Name, entry.FullName, entry.Open()); + + contentManager._logger.Debug($"Mapped content from zip [{entry.FullName}]"); } } } @@ -168,29 +159,27 @@ public static ContentManager LoadGameMode(Game game, string gameModeName, string { var relativePath = file.Replace(contentPath, "").Replace(gameModeName, "").Substring(2) .Replace('\\', '/'); - if (file.EndsWith(".ini") || file.EndsWith(".json")) - { - contentManager.Content[relativePath] = File.ReadAllBytes(file); - } - else if (file.EndsWith(".cs")) + + if (file.EndsWith(".cs")) { if (relativePath.StartsWith("bin") || relativePath.StartsWith("obj")) { continue; } - - contentManager.Content[relativePath] = File.ReadAllBytes(file); } else if (file.EndsWith(".aimesh_ngrid")) { - contentManager.Content[relativePath] = File.ReadAllBytes(file); contentManager._navGrids[relativePath] = NavGridReader.ReadBinary(file); } - else + else if (!file.EndsWith(".ini") && !file.EndsWith(".json")) { continue; } + var fileName = relativePath.Split('/').Last(); + contentManager.Content[relativePath] = + new FileEntry(fileName, file, File.Open(file, FileMode.Open)); + contentManager._logger.Debug($"Mapped Content [{relativePath}]"); } diff --git a/GameServerLib/Content/FileEntry.cs b/GameServerLib/Content/FileEntry.cs new file mode 100644 index 000000000..43a8e694d --- /dev/null +++ b/GameServerLib/Content/FileEntry.cs @@ -0,0 +1,38 @@ +using System.IO; + +namespace LeagueSandbox.GameServer.Content +{ + public class FileEntry + { + public string Name { get; } + public string FullPath { get; } + + private byte[] _data; + + public FileEntry(string name, string fullPath, Stream stream) + { + Name = name; + FullPath = fullPath; + using (stream) + { + _data = new byte[stream.Length]; + stream.Read(_data, 0, (int)stream.Length); + } + } + + public MemoryStream ReadFile() + { + return new MemoryStream(_data); + } + + public override string ToString() + { + return FullPath; + } + + public override int GetHashCode() + { + return FullPath.GetHashCode(); + } + } +} \ No newline at end of file diff --git a/GameServerLib/Content/NavGrid.cs b/GameServerLib/Content/NavGrid.cs index 9a0bd800b..a5ce2b07b 100644 --- a/GameServerLib/Content/NavGrid.cs +++ b/GameServerLib/Content/NavGrid.cs @@ -619,18 +619,17 @@ public class NavGridReader { public static NavGrid ReadBinary(string filePath) { - NavBinaryReader b = null; - + FileStream stream = null; try { - b = new NavBinaryReader(File.Open(filePath, FileMode.Open, FileAccess.Read)); + stream = File.Open(filePath, FileMode.Open, FileAccess.Read); + var b = new NavBinaryReader(stream); + return ReadData(b); } - catch + finally { - // Ignored + stream?.Dispose(); } - - return ReadData(b); } public static NavGrid ReadBinary(byte[] fileBytes) diff --git a/GameServerLib/Content/SpellData.cs b/GameServerLib/Content/SpellData.cs index 302079861..59b773682 100644 --- a/GameServerLib/Content/SpellData.cs +++ b/GameServerLib/Content/SpellData.cs @@ -248,7 +248,7 @@ public void Load(string champion, string spell) { var path = _game.Config.ContentManager.GetSpellDataPath(champion, spell); _logger.Debug($"Loading spell {spell} data from path: {path}!"); - using (var stream = new StreamReader(new MemoryStream(_game.Config.ContentManager.Content[path]))) + using (var stream = new StreamReader(_game.Config.ContentManager.Content[path].ReadFile())) { var iniParser = new FileIniDataParser(); var iniData = iniParser.ReadData(stream); diff --git a/GameServerLib/Game.cs b/GameServerLib/Game.cs index 3ccc59cfd..4d1cd7181 100644 --- a/GameServerLib/Game.cs +++ b/GameServerLib/Game.cs @@ -133,7 +133,14 @@ public bool LoadScripts(bool doReloadContent = false) continue; } - scripts.Add(contentData.Key, contentData.Value); + byte[] data; + using (var stream = contentData.Value.ReadFile()) + { + data = new byte[stream.Length]; + stream.Read(data, 0, (int)stream.Length); + } + + scripts.Add(contentData.Key, data); } return ScriptEngine.LoadFromData(scripts); diff --git a/GameServerLib/GameServerLib.csproj b/GameServerLib/GameServerLib.csproj index f5c775de1..5a7ae9929 100644 --- a/GameServerLib/GameServerLib.csproj +++ b/GameServerLib/GameServerLib.csproj @@ -185,6 +185,7 @@ + diff --git a/GameServerLib/Items/ItemManager.cs b/GameServerLib/Items/ItemManager.cs index a2906ad63..e5d7bc6d1 100644 --- a/GameServerLib/Items/ItemManager.cs +++ b/GameServerLib/Items/ItemManager.cs @@ -44,7 +44,7 @@ public void LoadItems(ContentManager contentManager) var itemIdStr = split.Last().Replace(".ini", ""); ContentFile contentFile; - using (var stream = new StreamReader(new MemoryStream(content.Value))) + using (var stream = new StreamReader(content.Value.ReadFile())) { var iniData = iniParser.ReadData(stream); contentFile = new ContentFile(ContentManager.ParseIniFile(iniData)); From 3678cdf63568b7161835939597ea9110ae6c4c36 Mon Sep 17 00:00:00 2001 From: Furkan SAMANLI Date: Wed, 10 Oct 2018 23:04:58 +0300 Subject: [PATCH 6/6] try/finally doesn't handle exceptions you dumbass --- GameServerLib/Content/NavGrid.cs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/GameServerLib/Content/NavGrid.cs b/GameServerLib/Content/NavGrid.cs index a5ce2b07b..c0a0b8cf3 100644 --- a/GameServerLib/Content/NavGrid.cs +++ b/GameServerLib/Content/NavGrid.cs @@ -619,16 +619,16 @@ public class NavGridReader { public static NavGrid ReadBinary(string filePath) { - FileStream stream = null; try { - stream = File.Open(filePath, FileMode.Open, FileAccess.Read); - var b = new NavBinaryReader(stream); - return ReadData(b); + using (var stream = File.Open(filePath, FileMode.Open, FileAccess.Read)) + { + return ReadData(new NavBinaryReader(stream)); + } } - finally + catch { - stream?.Dispose(); + return null; } }