Fix some ToDos, parallelization problems.

This commit is contained in:
Ottermandias 2023-07-03 16:39:34 +02:00
parent 0ed94676ed
commit 8ea6893fc3
15 changed files with 50 additions and 41 deletions

@ -1 +1 @@
Subproject commit 39e11eafa4c019bdec6a937c1be80e3a53a5cb4a Subproject commit adce3030c9dc125f2ebbaefbef6c756977c047c3

View file

@ -171,7 +171,7 @@ public static class ActorManagerExtensions
{ {
ObjectKind.MountType => manager.Data.Mounts, ObjectKind.MountType => manager.Data.Mounts,
ObjectKind.Companion => manager.Data.Companions, ObjectKind.Companion => manager.Data.Companions,
(ObjectKind)15 => manager.Data.Ornaments, // TODO: CS Update ObjectKind.Ornament => manager.Data.Ornaments,
ObjectKind.BattleNpc => manager.Data.BNpcs, ObjectKind.BattleNpc => manager.Data.BNpcs,
ObjectKind.EventNpc => manager.Data.ENpcs, ObjectKind.EventNpc => manager.Data.ENpcs,
_ => new Dictionary<uint, string>(), _ => new Dictionary<uint, string>(),
@ -190,7 +190,7 @@ public static class ActorManagerExtensions
ObjectKind.EventNpc => "Event NPC", ObjectKind.EventNpc => "Event NPC",
ObjectKind.MountType => "Mount", ObjectKind.MountType => "Mount",
ObjectKind.Companion => "Companion", ObjectKind.Companion => "Companion",
(ObjectKind)15 => "Accessory", // TODO: CS update ObjectKind.Ornament => "Accessory",
_ => kind.ToString(), _ => kind.ToString(),
}; };

View file

@ -98,7 +98,7 @@ public sealed partial class ActorManager : IDisposable
{ {
ObjectKind.MountType => Mounts.TryGetValue(dataId, out name), ObjectKind.MountType => Mounts.TryGetValue(dataId, out name),
ObjectKind.Companion => Companions.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.BattleNpc => BNpcs.TryGetValue(dataId, out name),
ObjectKind.EventNpc => ENpcs.TryGetValue(dataId, out name), ObjectKind.EventNpc => ENpcs.TryGetValue(dataId, out name),
_ => false, _ => false,

View file

@ -179,9 +179,8 @@ public partial class ActorManager
case "o": case "o":
case "accessory": case "accessory":
case "ornament": case "ornament":
// TODO: Objectkind ornament.
return FindDataId(split[1], Data.Ornaments, out id) 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]}."); : throw new IdentifierParseError($"Could not identify an Accessory named {split[1]}.");
case "e": case "e":
case "enpc": case "enpc":
@ -334,7 +333,7 @@ public partial class ActorManager
} }
case ObjectKind.MountType: case ObjectKind.MountType:
case ObjectKind.Companion: case ObjectKind.Companion:
case (ObjectKind)15: // TODO: CS Update case ObjectKind.Ornament:
{ {
owner = HandleCutscene( owner = HandleCutscene(
(FFXIVClientStructs.FFXIV.Client.Game.Object.GameObject*)_objects.GetObjectAddress(actor->ObjectIndex - 1)); (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. /// Obtain the current companion ID for an object by its actor and owner.
/// </summary> /// </summary>
private unsafe uint GetCompanionId(FFXIVClientStructs.FFXIV.Client.Game.Object.GameObject* actor, private unsafe uint GetCompanionId(FFXIVClientStructs.FFXIV.Client.Game.Object.GameObject* actor,
Character* owner) // TODO: CS Update Character* owner)
{ {
return (ObjectKind)actor->ObjectKind switch return (ObjectKind)actor->ObjectKind switch
{ {
ObjectKind.MountType => owner->Mount.MountId, ObjectKind.MountType => owner->Mount.MountId,
(ObjectKind)15 => owner->Ornament.OrnamentId, ObjectKind.Ornament => owner->Ornament.OrnamentId,
ObjectKind.Companion => actor->DataID, ObjectKind.Companion => actor->DataID,
_ => actor->DataID, _ => actor->DataID,
}; };
@ -571,7 +570,7 @@ public partial class ActorManager
{ {
ObjectKind.MountType => Data.Mounts.ContainsKey(dataId), ObjectKind.MountType => Data.Mounts.ContainsKey(dataId),
ObjectKind.Companion => Data.Companions.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.BattleNpc => Data.BNpcs.ContainsKey(dataId),
_ => false, _ => false,
}; };
@ -582,7 +581,7 @@ public partial class ActorManager
{ {
ObjectKind.MountType => Data.Mounts.ContainsKey(dataId), ObjectKind.MountType => Data.Mounts.ContainsKey(dataId),
ObjectKind.Companion => Data.Companions.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.BattleNpc => Data.BNpcs.ContainsKey(dataId),
ObjectKind.EventNpc => Data.ENpcs.ContainsKey(dataId), ObjectKind.EventNpc => Data.ENpcs.ContainsKey(dataId),
_ => false, _ => false,

View file

@ -138,6 +138,9 @@ public sealed class ItemData : DataSharer, IReadOnlyDictionary<FullEquipType, IR
public IEnumerable<(uint, EquipItem)> AllItems(bool main) public IEnumerable<(uint, EquipItem)> AllItems(bool main)
=> (main ? _mainItems : _offItems).Select(i => (i.Key, (EquipItem)i.Value)); => (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) public bool TryGetValue(uint key, bool main, out EquipItem value)
{ {
var dict = main ? _mainItems : _offItems; var dict = main ? _mainItems : _offItems;

View file

@ -290,7 +290,7 @@ internal sealed class ObjectIdentification : DataSharer, IObjectIdentifier
var options = new ParallelOptions() var options = new ParallelOptions()
{ {
MaxDegreeOfParallelism = Environment.ProcessorCount / 2, MaxDegreeOfParallelism = Math.Max(1, Environment.ProcessorCount / 2),
}; };
Parallel.ForEach(gameData.GetExcelSheet<BNpcBase>(language)!.Where(b => b.RowId < BnpcNames.Count), options, bNpc => Parallel.ForEach(gameData.GetExcelSheet<BNpcBase>(language)!.Where(b => b.RowId < BnpcNames.Count), options, bNpc =>

View file

@ -187,28 +187,28 @@ public static class FullEquipTypeExtensions
FullEquipType.Scythe => "Scythe", FullEquipType.Scythe => "Scythe",
FullEquipType.Nouliths => "Nouliths", FullEquipType.Nouliths => "Nouliths",
FullEquipType.Shield => "Shield", FullEquipType.Shield => "Shield",
FullEquipType.Saw => "Saw (Carpenter)", FullEquipType.Saw => "Saw",
FullEquipType.CrossPeinHammer => "Hammer (Blacksmith)", FullEquipType.CrossPeinHammer => "Cross Pein Hammer",
FullEquipType.RaisingHammer => "Hammer (Armorsmith)", FullEquipType.RaisingHammer => "Raising Hammer",
FullEquipType.LapidaryHammer => "Hammer (Goldsmith)", FullEquipType.LapidaryHammer => "Lapidary Hammer",
FullEquipType.Knife => "Knife (Leatherworker)", FullEquipType.Knife => "Round Knife",
FullEquipType.Needle => "Needle (Weaver)", FullEquipType.Needle => "Needle",
FullEquipType.Alembic => "Alembic (Alchemist)", FullEquipType.Alembic => "Alembic",
FullEquipType.Frypan => "Frypan (Culinarian)", FullEquipType.Frypan => "Frypan",
FullEquipType.Pickaxe => "Pickaxe (Miner)", FullEquipType.Pickaxe => "Pickaxe",
FullEquipType.Hatchet => "Hatchet (Botanist)", FullEquipType.Hatchet => "Hatchet",
FullEquipType.FishingRod => "Fishing Rod", FullEquipType.FishingRod => "Fishing Rod",
FullEquipType.ClawHammer => "Clawhammer (Carpenter)", FullEquipType.ClawHammer => "Clawhammer",
FullEquipType.File => "File (Blacksmith)", FullEquipType.File => "File",
FullEquipType.Pliers => "Pliers (Armorsmith)", FullEquipType.Pliers => "Pliers",
FullEquipType.GrindingWheel => "Grinding Wheel (Goldsmith)", FullEquipType.GrindingWheel => "Grinding Wheel",
FullEquipType.Awl => "Awl (Leatherworker)", FullEquipType.Awl => "Awl",
FullEquipType.SpinningWheel => "Spinning Wheel (Weaver)", FullEquipType.SpinningWheel => "Spinning Wheel",
FullEquipType.Mortar => "Mortar (Alchemist)", FullEquipType.Mortar => "Mortar",
FullEquipType.CulinaryKnife => "Knife (Culinarian)", FullEquipType.CulinaryKnife => "Culinary Knife",
FullEquipType.Sledgehammer => "Sledgehammer (Miner)", FullEquipType.Sledgehammer => "Sledgehammer",
FullEquipType.GardenScythe => "Garden Scythe (Botanist)", FullEquipType.GardenScythe => "Garden Scythe",
FullEquipType.Gig => "Gig (Fisher)", FullEquipType.Gig => "Gig",
_ => "Unknown", _ => "Unknown",
}; };

View file

@ -46,6 +46,9 @@ public readonly struct EquipItem
Type = type; Type = type;
} }
public string ModelString
=> WeaponType == 0 ? $"{ModelId.Value}-{Variant}" : $"{ModelId.Value}-{WeaponType.Value}-{Variant}";
public static implicit operator EquipItem(PseudoEquipItem it) public static implicit operator EquipItem(PseudoEquipItem it)
=> new(it.Item1, it.Item2, it.Item3, it.Item4, it.Item5, it.Item6, (FullEquipType)it.Item7); => new(it.Item1, it.Item2, it.Item3, it.Item4, it.Item5, it.Item6, (FullEquipType)it.Item7);

View file

@ -119,7 +119,7 @@ public unsafe class CollectionResolver
/// <summary> Return whether the given character has a human model. </summary> /// <summary> Return whether the given character has a human model. </summary>
public bool IsModelHuman(Character* character) public bool IsModelHuman(Character* character)
=> character != null && IsModelHuman((uint)character->ModelCharaId); => character != null && IsModelHuman((uint)character->CharacterData.ModelCharaId);
/// <summary> /// <summary>
/// Used if on the Login screen. Names are populated after actors are drawn, /// 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. // Only handle human models.
var character = (Character*)actor; var character = (Character*)actor;
if (!IsModelHuman((uint)character->ModelCharaId)) if (!IsModelHuman((uint)character->CharacterData.ModelCharaId))
return null; return null;
if (character->DrawData.CustomizeData[0] == 0) if (character->DrawData.CustomizeData[0] == 0)

View file

@ -66,6 +66,11 @@ public class PathResolver : IDisposable
ResourceCategory.Shader => Resolve(path, resourceType), ResourceCategory.Shader => Resolve(path, resourceType),
ResourceCategory.Vfx => Resolve(path, resourceType), ResourceCategory.Vfx => Resolve(path, resourceType),
ResourceCategory.Sound => 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, // None of these files are ever associated with specific characters,
// always use the default resolver for now, // always use the default resolver for now,
// except that common/font is conceptually more UI. // except that common/font is conceptually more UI.
@ -75,7 +80,6 @@ public class PathResolver : IDisposable
ResourceCategory.BgCommon => DefaultResolver(path), ResourceCategory.BgCommon => DefaultResolver(path),
ResourceCategory.Bg => DefaultResolver(path), ResourceCategory.Bg => DefaultResolver(path),
ResourceCategory.Cut => DefaultResolver(path), ResourceCategory.Cut => DefaultResolver(path),
ResourceCategory.Exd => DefaultResolver(path),
ResourceCategory.Music => DefaultResolver(path), ResourceCategory.Music => DefaultResolver(path),
_ => DefaultResolver(path), _ => DefaultResolver(path),
}; };

View file

@ -37,7 +37,7 @@ public class ResourceTree
var model = (CharacterBase*)character->GameObject.GetDrawObject(); var model = (CharacterBase*)character->GameObject.GetDrawObject();
var equipment = new ReadOnlySpan<CharacterArmor>(&character->DrawData.Head, 10); var equipment = new ReadOnlySpan<CharacterArmor>(&character->DrawData.Head, 10);
// var customize = new ReadOnlySpan<byte>( character->CustomizeData, 26 ); // var customize = new ReadOnlySpan<byte>( character->CustomizeData, 26 );
ModelId = character->ModelCharaId; ModelId = character->CharacterData.ModelCharaId;
CustomizeData = character->DrawData.CustomizeData; CustomizeData = character->DrawData.CustomizeData;
RaceCode = model->GetModelType() == CharacterBase.ModelType.Human ? (GenderRace) ((Human*)model)->RaceSexId : GenderRace.Unknown; RaceCode = model->GetModelType() == CharacterBase.ModelType.Human ? (GenderRace) ((Human*)model)->RaceSexId : GenderRace.Unknown;

View file

@ -74,7 +74,7 @@ public class ResourceTreeFactory
var (name, related) = GetCharacterName(character, cache); var (name, related) = GetCharacterName(character, cache);
var tree = new ResourceTree(name, (nint)gameObjStruct, related, collectionResolveData.ModCollection.Name); var tree = new ResourceTree(name, (nint)gameObjStruct, related, collectionResolveData.ModCollection.Name);
var globalContext = new GlobalResolveContext(_config, _identifier.AwaitedService, cache, collectionResolveData.ModCollection, var globalContext = new GlobalResolveContext(_config, _identifier.AwaitedService, cache, collectionResolveData.ModCollection,
((Character*)gameObjStruct)->ModelCharaId, withNames); ((Character*)gameObjStruct)->CharacterData.ModelCharaId, withNames);
tree.LoadResources(globalContext); tree.LoadResources(globalContext);
return tree; return tree;
} }

View file

@ -209,7 +209,7 @@ public sealed unsafe partial class RedrawService : IDisposable
if (actor == null || _targets.Target != null) if (actor == null || _targets.Target != null)
return; return;
_targets.SetTarget(actor); _targets.Target = actor;
_target = -1; _target = -1;
} }

View file

@ -318,7 +318,7 @@ public sealed class ModManager : ModStorage, IDisposable
{ {
var options = new ParallelOptions() var options = new ParallelOptions()
{ {
MaxDegreeOfParallelism = Environment.ProcessorCount / 2, MaxDegreeOfParallelism = Math.Max(1, Environment.ProcessorCount / 2),
}; };
var queue = new ConcurrentQueue<Mod>(); var queue = new ConcurrentQueue<Mod>();
Parallel.ForEach(BasePath.EnumerateDirectories(), options, dir => Parallel.ForEach(BasePath.EnumerateDirectories(), options, dir =>

View file

@ -15,7 +15,7 @@ namespace Penumbra.UI;
internal sealed class ResourceWatcherTable : Table<Record> internal sealed class ResourceWatcherTable : Table<Record>
{ {
public ResourceWatcherTable(Configuration config, ICollection<Record> records) public ResourceWatcherTable(Configuration config, IReadOnlyCollection<Record> records)
: base("##records", : base("##records",
records, records,
new PathColumn { Label = "Path" }, new PathColumn { Label = "Path" },