mirror of
https://github.com/xivdev/Penumbra.git
synced 2025-12-13 12:14:17 +01:00
Fix some ToDos, parallelization problems.
This commit is contained in:
parent
0ed94676ed
commit
8ea6893fc3
15 changed files with 50 additions and 41 deletions
2
OtterGui
2
OtterGui
|
|
@ -1 +1 @@
|
||||||
Subproject commit 39e11eafa4c019bdec6a937c1be80e3a53a5cb4a
|
Subproject commit adce3030c9dc125f2ebbaefbef6c756977c047c3
|
||||||
|
|
@ -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(),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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,
|
||||||
|
|
|
||||||
|
|
@ -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,
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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 =>
|
||||||
|
|
|
||||||
|
|
@ -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",
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
|
||||||
|
|
@ -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),
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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 =>
|
||||||
|
|
|
||||||
|
|
@ -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" },
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue