mirror of
https://github.com/xivdev/Penumbra.git
synced 2025-12-12 18:27:24 +01:00
Give messages for unsupported file redirection types.
This commit is contained in:
parent
9b18ffce66
commit
50c4207844
3 changed files with 59 additions and 40 deletions
|
|
@ -1,3 +1,4 @@
|
||||||
|
using Dalamud.Interface.ImGuiNotification;
|
||||||
using OtterGui;
|
using OtterGui;
|
||||||
using OtterGui.Classes;
|
using OtterGui.Classes;
|
||||||
using Penumbra.Meta.Manipulations;
|
using Penumbra.Meta.Manipulations;
|
||||||
|
|
@ -274,6 +275,24 @@ public sealed class CollectionCache : IDisposable
|
||||||
_manager.ResolvedFileChanged.Invoke(collection, type, key, value, old, mod);
|
_manager.ResolvedFileChanged.Invoke(collection, type, key, value, old, mod);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static bool IsRedirectionSupported(Utf8GamePath path, IMod mod)
|
||||||
|
{
|
||||||
|
var ext = path.Extension().AsciiToLower().ToString();
|
||||||
|
switch (ext)
|
||||||
|
{
|
||||||
|
case ".atch" or ".eqp" or ".eqdp" or ".est" or ".gmp" or ".cmp" or ".imc":
|
||||||
|
Penumbra.Messager.NotificationMessage(
|
||||||
|
$"Redirection of {ext} files for {mod.Name} is unsupported. Please use the corresponding meta manipulations instead.",
|
||||||
|
NotificationType.Warning);
|
||||||
|
return false;
|
||||||
|
case ".lvb" or ".lgb" or ".sgb":
|
||||||
|
Penumbra.Messager.NotificationMessage($"Redirection of {ext} files for {mod.Name} is unsupported as this breaks the game.",
|
||||||
|
NotificationType.Warning);
|
||||||
|
return false;
|
||||||
|
default: return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Add a specific file redirection, handling potential conflicts.
|
// Add a specific file redirection, handling potential conflicts.
|
||||||
// For different mods, higher mod priority takes precedence before option group priority,
|
// For different mods, higher mod priority takes precedence before option group priority,
|
||||||
// which takes precedence before option priority, which takes precedence before ordering.
|
// which takes precedence before option priority, which takes precedence before ordering.
|
||||||
|
|
@ -283,6 +302,9 @@ public sealed class CollectionCache : IDisposable
|
||||||
if (!CheckFullPath(path, file))
|
if (!CheckFullPath(path, file))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
if (!IsRedirectionSupported(path, mod))
|
||||||
|
return;
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (ResolvedFiles.TryAdd(path, new ModPath(mod, file)))
|
if (ResolvedFiles.TryAdd(path, new ModPath(mod, file)))
|
||||||
|
|
@ -342,8 +364,9 @@ public sealed class CollectionCache : IDisposable
|
||||||
// Returns if the added mod takes priority before the existing mod.
|
// Returns if the added mod takes priority before the existing mod.
|
||||||
private bool AddConflict(object data, IMod addedMod, IMod existingMod)
|
private bool AddConflict(object data, IMod addedMod, IMod existingMod)
|
||||||
{
|
{
|
||||||
var addedPriority = addedMod.Index >= 0 ? _collection.GetActualSettings(addedMod.Index).Settings!.Priority : addedMod.Priority;
|
var addedPriority = addedMod.Index >= 0 ? _collection.GetActualSettings(addedMod.Index).Settings!.Priority : addedMod.Priority;
|
||||||
var existingPriority = existingMod.Index >= 0 ? _collection.GetActualSettings(existingMod.Index).Settings!.Priority : existingMod.Priority;
|
var existingPriority =
|
||||||
|
existingMod.Index >= 0 ? _collection.GetActualSettings(existingMod.Index).Settings!.Priority : existingMod.Priority;
|
||||||
|
|
||||||
if (existingPriority < addedPriority)
|
if (existingPriority < addedPriority)
|
||||||
{
|
{
|
||||||
|
|
@ -427,7 +450,8 @@ public sealed class CollectionCache : IDisposable
|
||||||
if (!_changedItems.TryGetValue(name, out var data))
|
if (!_changedItems.TryGetValue(name, out var data))
|
||||||
_changedItems.Add(name, (new SingleArray<IMod>(mod), obj));
|
_changedItems.Add(name, (new SingleArray<IMod>(mod), obj));
|
||||||
else if (!data.Item1.Contains(mod))
|
else if (!data.Item1.Contains(mod))
|
||||||
_changedItems[name] = (data.Item1.Append(mod), obj is IdentifiedCounter x && data.Item2 is IdentifiedCounter y ? x + y : obj);
|
_changedItems[name] = (data.Item1.Append(mod),
|
||||||
|
obj is IdentifiedCounter x && data.Item2 is IdentifiedCounter y ? x + y : obj);
|
||||||
else if (obj is IdentifiedCounter x && data.Item2 is IdentifiedCounter y)
|
else if (obj is IdentifiedCounter x && data.Item2 is IdentifiedCounter y)
|
||||||
_changedItems[name] = (data.Item1, x + y);
|
_changedItems[name] = (data.Item1, x + y);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -171,8 +171,7 @@ public class CollectionCacheManager : IDisposable, IService
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
ResolvedFileChanged.Invoke(collection, ResolvedFileChanged.Type.FullRecomputeStart, Utf8GamePath.Empty, FullPath.Empty,
|
ResolvedFileChanged.Invoke(collection, ResolvedFileChanged.Type.FullRecomputeStart, Utf8GamePath.Empty, FullPath.Empty,
|
||||||
FullPath.Empty,
|
FullPath.Empty, null);
|
||||||
null);
|
|
||||||
cache.ResolvedFiles.Clear();
|
cache.ResolvedFiles.Clear();
|
||||||
cache.Meta.Reset();
|
cache.Meta.Reset();
|
||||||
cache.ConflictDict.Clear();
|
cache.ConflictDict.Clear();
|
||||||
|
|
|
||||||
|
|
@ -49,42 +49,38 @@ public class PathResolver : IDisposable, IService
|
||||||
if (!_config.EnableMods)
|
if (!_config.EnableMods)
|
||||||
return (null, ResolveData.Invalid);
|
return (null, ResolveData.Invalid);
|
||||||
|
|
||||||
// Do not allow manipulating layers to prevent very obvious cheating and softlocks.
|
return resourceType switch
|
||||||
if (resourceType is ResourceType.Lvb or ResourceType.Lgb or ResourceType.Sgb)
|
|
||||||
return (null, ResolveData.Invalid);
|
|
||||||
|
|
||||||
// Prevent .atch loading to prevent crashes on outdated .atch files. TODO: handle atch modding differently.
|
|
||||||
if (resourceType is ResourceType.Atch)
|
|
||||||
return ResolveAtch(path);
|
|
||||||
|
|
||||||
return category switch
|
|
||||||
{
|
{
|
||||||
// Only Interface collection.
|
// Do not allow manipulating layers to prevent very obvious cheating and softlocks.
|
||||||
ResourceCategory.Ui => ResolveUi(path),
|
ResourceType.Lvb or ResourceType.Lgb or ResourceType.Sgb => (null, ResolveData.Invalid),
|
||||||
// Never allow changing scripts.
|
// Prevent .atch loading to prevent crashes on outdated .atch files.
|
||||||
ResourceCategory.UiScript => (null, ResolveData.Invalid),
|
ResourceType.Atch => ResolveAtch(path),
|
||||||
ResourceCategory.GameScript => (null, ResolveData.Invalid),
|
|
||||||
// Use actual resolving.
|
_ => category switch
|
||||||
ResourceCategory.Chara => Resolve(path, resourceType),
|
{
|
||||||
ResourceCategory.Shader => ResolveShader(path, resourceType),
|
// Only Interface collection.
|
||||||
ResourceCategory.Vfx => Resolve(path, resourceType),
|
ResourceCategory.Ui => ResolveUi(path),
|
||||||
ResourceCategory.Sound => Resolve(path, resourceType),
|
// Never allow changing scripts.
|
||||||
// EXD Modding in general should probably be prohibited but is currently used for fan translations.
|
ResourceCategory.UiScript => (null, ResolveData.Invalid),
|
||||||
// We prevent WebURL specifically because it technically allows launching arbitrary programs / to execute arbitrary code.
|
ResourceCategory.GameScript => (null, ResolveData.Invalid),
|
||||||
ResourceCategory.Exd => path.Path.StartsWith("exd/weburl"u8)
|
// Use actual resolving.
|
||||||
? (null, ResolveData.Invalid)
|
ResourceCategory.Chara => Resolve(path, resourceType),
|
||||||
: DefaultResolver(path),
|
ResourceCategory.Shader => ResolveShader(path, resourceType),
|
||||||
// None of these files are ever associated with specific characters,
|
ResourceCategory.Vfx => Resolve(path, resourceType),
|
||||||
// always use the default resolver for now,
|
ResourceCategory.Sound => Resolve(path, resourceType),
|
||||||
// except that common/font is conceptually more UI.
|
// EXD Modding in general should probably be prohibited but is currently used for fan translations.
|
||||||
ResourceCategory.Common => path.Path.StartsWith("common/font"u8)
|
// We prevent WebURL specifically because it technically allows launching arbitrary programs / to execute arbitrary code.
|
||||||
? ResolveUi(path)
|
ResourceCategory.Exd => path.Path.StartsWith("exd/weburl"u8) ? (null, ResolveData.Invalid) : DefaultResolver(path),
|
||||||
: DefaultResolver(path),
|
// None of these files are ever associated with specific characters,
|
||||||
ResourceCategory.BgCommon => DefaultResolver(path),
|
// always use the default resolver for now,
|
||||||
ResourceCategory.Bg => DefaultResolver(path),
|
// except that common/font is conceptually more UI.
|
||||||
ResourceCategory.Cut => DefaultResolver(path),
|
ResourceCategory.Common => path.Path.StartsWith("common/font"u8) ? ResolveUi(path) : DefaultResolver(path),
|
||||||
ResourceCategory.Music => DefaultResolver(path),
|
ResourceCategory.BgCommon => DefaultResolver(path),
|
||||||
_ => DefaultResolver(path),
|
ResourceCategory.Bg => DefaultResolver(path),
|
||||||
|
ResourceCategory.Cut => DefaultResolver(path),
|
||||||
|
ResourceCategory.Music => DefaultResolver(path),
|
||||||
|
_ => DefaultResolver(path),
|
||||||
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue