From 8ea6893fc3482e66b96bbbd197c20d000b50fdfd Mon Sep 17 00:00:00 2001 From: Ottermandias Date: Mon, 3 Jul 2023 16:39:34 +0200 Subject: [PATCH] Fix some ToDos, parallelization problems. --- OtterGui | 2 +- Penumbra.GameData/Actors/ActorIdentifier.cs | 4 +- Penumbra.GameData/Actors/ActorManager.Data.cs | 2 +- .../Actors/ActorManager.Identifiers.cs | 13 +++--- Penumbra.GameData/Data/ItemData.cs | 3 ++ .../Data/ObjectIdentification.cs | 2 +- Penumbra.GameData/Enums/FullEquipType.cs | 42 +++++++++---------- Penumbra.GameData/Structs/EquipItem.cs | 3 ++ .../PathResolving/CollectionResolver.cs | 4 +- .../Interop/PathResolving/PathResolver.cs | 6 ++- Penumbra/Interop/ResourceTree/ResourceTree.cs | 2 +- .../ResourceTree/ResourceTreeFactory.cs | 2 +- Penumbra/Interop/Services/RedrawService.cs | 2 +- Penumbra/Mods/Manager/ModManager.cs | 2 +- .../ResourceWatcher/ResourceWatcherTable.cs | 2 +- 15 files changed, 50 insertions(+), 41 deletions(-) diff --git a/OtterGui b/OtterGui index 39e11eaf..adce3030 160000 --- a/OtterGui +++ b/OtterGui @@ -1 +1 @@ -Subproject commit 39e11eafa4c019bdec6a937c1be80e3a53a5cb4a +Subproject commit adce3030c9dc125f2ebbaefbef6c756977c047c3 diff --git a/Penumbra.GameData/Actors/ActorIdentifier.cs b/Penumbra.GameData/Actors/ActorIdentifier.cs index e0a653d8..00f54ea6 100644 --- a/Penumbra.GameData/Actors/ActorIdentifier.cs +++ b/Penumbra.GameData/Actors/ActorIdentifier.cs @@ -171,7 +171,7 @@ public static class ActorManagerExtensions { ObjectKind.MountType => manager.Data.Mounts, ObjectKind.Companion => manager.Data.Companions, - (ObjectKind)15 => manager.Data.Ornaments, // TODO: CS Update + ObjectKind.Ornament => manager.Data.Ornaments, ObjectKind.BattleNpc => manager.Data.BNpcs, ObjectKind.EventNpc => manager.Data.ENpcs, _ => new Dictionary(), @@ -190,7 +190,7 @@ public static class ActorManagerExtensions ObjectKind.EventNpc => "Event NPC", ObjectKind.MountType => "Mount", ObjectKind.Companion => "Companion", - (ObjectKind)15 => "Accessory", // TODO: CS update + ObjectKind.Ornament => "Accessory", _ => kind.ToString(), }; diff --git a/Penumbra.GameData/Actors/ActorManager.Data.cs b/Penumbra.GameData/Actors/ActorManager.Data.cs index e4e5ae57..b23fabf9 100644 --- a/Penumbra.GameData/Actors/ActorManager.Data.cs +++ b/Penumbra.GameData/Actors/ActorManager.Data.cs @@ -98,7 +98,7 @@ public sealed partial class ActorManager : IDisposable { ObjectKind.MountType => Mounts.TryGetValue(dataId, out name), ObjectKind.Companion => Companions.TryGetValue(dataId, out name), - (ObjectKind)15 => Ornaments.TryGetValue(dataId, out name), // TODO: CS Update + ObjectKind.Ornament => Ornaments.TryGetValue(dataId, out name), ObjectKind.BattleNpc => BNpcs.TryGetValue(dataId, out name), ObjectKind.EventNpc => ENpcs.TryGetValue(dataId, out name), _ => false, diff --git a/Penumbra.GameData/Actors/ActorManager.Identifiers.cs b/Penumbra.GameData/Actors/ActorManager.Identifiers.cs index 9f5f246f..2a71081d 100644 --- a/Penumbra.GameData/Actors/ActorManager.Identifiers.cs +++ b/Penumbra.GameData/Actors/ActorManager.Identifiers.cs @@ -179,9 +179,8 @@ public partial class ActorManager case "o": case "accessory": case "ornament": - // TODO: Objectkind ornament. return FindDataId(split[1], Data.Ornaments, out id) - ? ((ObjectKind)15, id) + ? (ObjectKind.Ornament, id) : throw new IdentifierParseError($"Could not identify an Accessory named {split[1]}."); case "e": case "enpc": @@ -334,7 +333,7 @@ public partial class ActorManager } case ObjectKind.MountType: case ObjectKind.Companion: - case (ObjectKind)15: // TODO: CS Update + case ObjectKind.Ornament: { owner = HandleCutscene( (FFXIVClientStructs.FFXIV.Client.Game.Object.GameObject*)_objects.GetObjectAddress(actor->ObjectIndex - 1)); @@ -369,12 +368,12 @@ public partial class ActorManager /// Obtain the current companion ID for an object by its actor and owner. /// private unsafe uint GetCompanionId(FFXIVClientStructs.FFXIV.Client.Game.Object.GameObject* actor, - Character* owner) // TODO: CS Update + Character* owner) { return (ObjectKind)actor->ObjectKind switch { ObjectKind.MountType => owner->Mount.MountId, - (ObjectKind)15 => owner->Ornament.OrnamentId, + ObjectKind.Ornament => owner->Ornament.OrnamentId, ObjectKind.Companion => actor->DataID, _ => actor->DataID, }; @@ -571,7 +570,7 @@ public partial class ActorManager { ObjectKind.MountType => Data.Mounts.ContainsKey(dataId), ObjectKind.Companion => Data.Companions.ContainsKey(dataId), - (ObjectKind)15 => Data.Ornaments.ContainsKey(dataId), // TODO: CS Update + ObjectKind.Ornament => Data.Ornaments.ContainsKey(dataId), ObjectKind.BattleNpc => Data.BNpcs.ContainsKey(dataId), _ => false, }; @@ -582,7 +581,7 @@ public partial class ActorManager { ObjectKind.MountType => Data.Mounts.ContainsKey(dataId), ObjectKind.Companion => Data.Companions.ContainsKey(dataId), - (ObjectKind)15 => Data.Ornaments.ContainsKey(dataId), // TODO: CS Update + ObjectKind.Ornament => Data.Ornaments.ContainsKey(dataId), ObjectKind.BattleNpc => Data.BNpcs.ContainsKey(dataId), ObjectKind.EventNpc => Data.ENpcs.ContainsKey(dataId), _ => false, diff --git a/Penumbra.GameData/Data/ItemData.cs b/Penumbra.GameData/Data/ItemData.cs index cbde9ede..edd5e3ba 100644 --- a/Penumbra.GameData/Data/ItemData.cs +++ b/Penumbra.GameData/Data/ItemData.cs @@ -138,6 +138,9 @@ public sealed class ItemData : DataSharer, IReadOnlyDictionary AllItems(bool main) => (main ? _mainItems : _offItems).Select(i => (i.Key, (EquipItem)i.Value)); + public int TotalItemCount(bool main) + => main ? _mainItems.Count : _offItems.Count; + public bool TryGetValue(uint key, bool main, out EquipItem value) { var dict = main ? _mainItems : _offItems; diff --git a/Penumbra.GameData/Data/ObjectIdentification.cs b/Penumbra.GameData/Data/ObjectIdentification.cs index 8e789339..de71be3a 100644 --- a/Penumbra.GameData/Data/ObjectIdentification.cs +++ b/Penumbra.GameData/Data/ObjectIdentification.cs @@ -290,7 +290,7 @@ internal sealed class ObjectIdentification : DataSharer, IObjectIdentifier var options = new ParallelOptions() { - MaxDegreeOfParallelism = Environment.ProcessorCount / 2, + MaxDegreeOfParallelism = Math.Max(1, Environment.ProcessorCount / 2), }; Parallel.ForEach(gameData.GetExcelSheet(language)!.Where(b => b.RowId < BnpcNames.Count), options, bNpc => diff --git a/Penumbra.GameData/Enums/FullEquipType.cs b/Penumbra.GameData/Enums/FullEquipType.cs index 7db76496..6d5b015e 100644 --- a/Penumbra.GameData/Enums/FullEquipType.cs +++ b/Penumbra.GameData/Enums/FullEquipType.cs @@ -187,28 +187,28 @@ public static class FullEquipTypeExtensions FullEquipType.Scythe => "Scythe", FullEquipType.Nouliths => "Nouliths", FullEquipType.Shield => "Shield", - FullEquipType.Saw => "Saw (Carpenter)", - FullEquipType.CrossPeinHammer => "Hammer (Blacksmith)", - FullEquipType.RaisingHammer => "Hammer (Armorsmith)", - FullEquipType.LapidaryHammer => "Hammer (Goldsmith)", - FullEquipType.Knife => "Knife (Leatherworker)", - FullEquipType.Needle => "Needle (Weaver)", - FullEquipType.Alembic => "Alembic (Alchemist)", - FullEquipType.Frypan => "Frypan (Culinarian)", - FullEquipType.Pickaxe => "Pickaxe (Miner)", - FullEquipType.Hatchet => "Hatchet (Botanist)", + FullEquipType.Saw => "Saw", + FullEquipType.CrossPeinHammer => "Cross Pein Hammer", + FullEquipType.RaisingHammer => "Raising Hammer", + FullEquipType.LapidaryHammer => "Lapidary Hammer", + FullEquipType.Knife => "Round Knife", + FullEquipType.Needle => "Needle", + FullEquipType.Alembic => "Alembic", + FullEquipType.Frypan => "Frypan", + FullEquipType.Pickaxe => "Pickaxe", + FullEquipType.Hatchet => "Hatchet", FullEquipType.FishingRod => "Fishing Rod", - FullEquipType.ClawHammer => "Clawhammer (Carpenter)", - FullEquipType.File => "File (Blacksmith)", - FullEquipType.Pliers => "Pliers (Armorsmith)", - FullEquipType.GrindingWheel => "Grinding Wheel (Goldsmith)", - FullEquipType.Awl => "Awl (Leatherworker)", - FullEquipType.SpinningWheel => "Spinning Wheel (Weaver)", - FullEquipType.Mortar => "Mortar (Alchemist)", - FullEquipType.CulinaryKnife => "Knife (Culinarian)", - FullEquipType.Sledgehammer => "Sledgehammer (Miner)", - FullEquipType.GardenScythe => "Garden Scythe (Botanist)", - FullEquipType.Gig => "Gig (Fisher)", + FullEquipType.ClawHammer => "Clawhammer", + FullEquipType.File => "File", + FullEquipType.Pliers => "Pliers", + FullEquipType.GrindingWheel => "Grinding Wheel", + FullEquipType.Awl => "Awl", + FullEquipType.SpinningWheel => "Spinning Wheel", + FullEquipType.Mortar => "Mortar", + FullEquipType.CulinaryKnife => "Culinary Knife", + FullEquipType.Sledgehammer => "Sledgehammer", + FullEquipType.GardenScythe => "Garden Scythe", + FullEquipType.Gig => "Gig", _ => "Unknown", }; diff --git a/Penumbra.GameData/Structs/EquipItem.cs b/Penumbra.GameData/Structs/EquipItem.cs index 718ea2ad..ccd9b691 100644 --- a/Penumbra.GameData/Structs/EquipItem.cs +++ b/Penumbra.GameData/Structs/EquipItem.cs @@ -46,6 +46,9 @@ public readonly struct EquipItem Type = type; } + public string ModelString + => WeaponType == 0 ? $"{ModelId.Value}-{Variant}" : $"{ModelId.Value}-{WeaponType.Value}-{Variant}"; + public static implicit operator EquipItem(PseudoEquipItem it) => new(it.Item1, it.Item2, it.Item3, it.Item4, it.Item5, it.Item6, (FullEquipType)it.Item7); diff --git a/Penumbra/Interop/PathResolving/CollectionResolver.cs b/Penumbra/Interop/PathResolving/CollectionResolver.cs index 4e1f6963..c5b797fd 100644 --- a/Penumbra/Interop/PathResolving/CollectionResolver.cs +++ b/Penumbra/Interop/PathResolving/CollectionResolver.cs @@ -119,7 +119,7 @@ public unsafe class CollectionResolver /// Return whether the given character has a human model. public bool IsModelHuman(Character* character) - => character != null && IsModelHuman((uint)character->ModelCharaId); + => character != null && IsModelHuman((uint)character->CharacterData.ModelCharaId); /// /// Used if on the Login screen. Names are populated after actors are drawn, @@ -213,7 +213,7 @@ public unsafe class CollectionResolver // Only handle human models. var character = (Character*)actor; - if (!IsModelHuman((uint)character->ModelCharaId)) + if (!IsModelHuman((uint)character->CharacterData.ModelCharaId)) return null; if (character->DrawData.CustomizeData[0] == 0) diff --git a/Penumbra/Interop/PathResolving/PathResolver.cs b/Penumbra/Interop/PathResolving/PathResolver.cs index 6833e352..cc513a92 100644 --- a/Penumbra/Interop/PathResolving/PathResolver.cs +++ b/Penumbra/Interop/PathResolving/PathResolver.cs @@ -66,6 +66,11 @@ public class PathResolver : IDisposable ResourceCategory.Shader => Resolve(path, resourceType), ResourceCategory.Vfx => Resolve(path, resourceType), ResourceCategory.Sound => Resolve(path, resourceType), + // EXD Modding in general should probably be prohibited but is currently used for fan translations. + // We prevent WebURL specifically because it technically allows launching arbitrary programs / to execute arbitrary code. + ResourceCategory.Exd => path.Path.StartsWith("exd/weburl"u8) + ? (null, ResolveData.Invalid) + : DefaultResolver(path), // None of these files are ever associated with specific characters, // always use the default resolver for now, // except that common/font is conceptually more UI. @@ -75,7 +80,6 @@ public class PathResolver : IDisposable ResourceCategory.BgCommon => DefaultResolver(path), ResourceCategory.Bg => DefaultResolver(path), ResourceCategory.Cut => DefaultResolver(path), - ResourceCategory.Exd => DefaultResolver(path), ResourceCategory.Music => DefaultResolver(path), _ => DefaultResolver(path), }; diff --git a/Penumbra/Interop/ResourceTree/ResourceTree.cs b/Penumbra/Interop/ResourceTree/ResourceTree.cs index 57fdf20e..76d0c3f2 100644 --- a/Penumbra/Interop/ResourceTree/ResourceTree.cs +++ b/Penumbra/Interop/ResourceTree/ResourceTree.cs @@ -37,7 +37,7 @@ public class ResourceTree var model = (CharacterBase*)character->GameObject.GetDrawObject(); var equipment = new ReadOnlySpan(&character->DrawData.Head, 10); // var customize = new ReadOnlySpan( character->CustomizeData, 26 ); - ModelId = character->ModelCharaId; + ModelId = character->CharacterData.ModelCharaId; CustomizeData = character->DrawData.CustomizeData; RaceCode = model->GetModelType() == CharacterBase.ModelType.Human ? (GenderRace) ((Human*)model)->RaceSexId : GenderRace.Unknown; diff --git a/Penumbra/Interop/ResourceTree/ResourceTreeFactory.cs b/Penumbra/Interop/ResourceTree/ResourceTreeFactory.cs index 161f896f..2408bf67 100644 --- a/Penumbra/Interop/ResourceTree/ResourceTreeFactory.cs +++ b/Penumbra/Interop/ResourceTree/ResourceTreeFactory.cs @@ -74,7 +74,7 @@ public class ResourceTreeFactory var (name, related) = GetCharacterName(character, cache); var tree = new ResourceTree(name, (nint)gameObjStruct, related, collectionResolveData.ModCollection.Name); var globalContext = new GlobalResolveContext(_config, _identifier.AwaitedService, cache, collectionResolveData.ModCollection, - ((Character*)gameObjStruct)->ModelCharaId, withNames); + ((Character*)gameObjStruct)->CharacterData.ModelCharaId, withNames); tree.LoadResources(globalContext); return tree; } diff --git a/Penumbra/Interop/Services/RedrawService.cs b/Penumbra/Interop/Services/RedrawService.cs index f78d6dca..825eda5c 100644 --- a/Penumbra/Interop/Services/RedrawService.cs +++ b/Penumbra/Interop/Services/RedrawService.cs @@ -209,7 +209,7 @@ public sealed unsafe partial class RedrawService : IDisposable if (actor == null || _targets.Target != null) return; - _targets.SetTarget(actor); + _targets.Target = actor; _target = -1; } diff --git a/Penumbra/Mods/Manager/ModManager.cs b/Penumbra/Mods/Manager/ModManager.cs index 38eff57b..ac973be4 100644 --- a/Penumbra/Mods/Manager/ModManager.cs +++ b/Penumbra/Mods/Manager/ModManager.cs @@ -318,7 +318,7 @@ public sealed class ModManager : ModStorage, IDisposable { var options = new ParallelOptions() { - MaxDegreeOfParallelism = Environment.ProcessorCount / 2, + MaxDegreeOfParallelism = Math.Max(1, Environment.ProcessorCount / 2), }; var queue = new ConcurrentQueue(); Parallel.ForEach(BasePath.EnumerateDirectories(), options, dir => diff --git a/Penumbra/UI/ResourceWatcher/ResourceWatcherTable.cs b/Penumbra/UI/ResourceWatcher/ResourceWatcherTable.cs index f3d66725..0b2f2ae5 100644 --- a/Penumbra/UI/ResourceWatcher/ResourceWatcherTable.cs +++ b/Penumbra/UI/ResourceWatcher/ResourceWatcherTable.cs @@ -15,7 +15,7 @@ namespace Penumbra.UI; internal sealed class ResourceWatcherTable : Table { - public ResourceWatcherTable(Configuration config, ICollection records) + public ResourceWatcherTable(Configuration config, IReadOnlyCollection records) : base("##records", records, new PathColumn { Label = "Path" },