Merge branch 'master' into Textures

# Conflicts:
#	Penumbra/Import/TexToolsImporter.Archives.cs
#	Penumbra/UI/Classes/ModEditWindow.Textures.cs
This commit is contained in:
Ottermandias 2022-09-16 21:55:24 +02:00
commit 19e5e94c64
97 changed files with 861 additions and 651 deletions

@ -1 +1 @@
Subproject commit 9ec5e2ad2f2d35d62c2ac7c300b914fffbda2191
Subproject commit b92dbe60887503a77a89aeae80729236fb2bfa10

View file

@ -1,5 +1,4 @@
using System.Linq;
using System.Runtime.InteropServices;
using Penumbra.GameData.Util;
namespace Penumbra.GameData.ByteString;

View file

@ -1,5 +1,3 @@
using System;
namespace Penumbra.GameData.Enums;
public enum ObjectType : byte

View file

@ -1,6 +1,5 @@
using System;
using System.Collections.Generic;
using Dalamud;
using Dalamud.Data;
using Lumina.Excel.GeneratedSheets;
using Penumbra.GameData.Enums;

View file

@ -1,10 +1,10 @@
using System;
using System.Collections.Generic;
using Dalamud.Game.ClientState.Objects.Types;
using Lumina.Data;
using Penumbra.Collections;
using Penumbra.GameData.Enums;
using Penumbra.Mods;
using System;
using System.Collections.Generic;
namespace Penumbra.Api;

View file

@ -1,12 +1,5 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Numerics;
using System.Reflection;
using Dalamud.Game.ClientState.Objects.Types;
using Dalamud.Interface;
using Dalamud.Logging;
using Dalamud.Plugin;
using Dalamud.Plugin.Ipc;
using ImGuiNET;
@ -16,6 +9,12 @@ using Penumbra.Collections;
using Penumbra.GameData.ByteString;
using Penumbra.GameData.Enums;
using Penumbra.Mods;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Numerics;
using System.Reflection;
namespace Penumbra.Api;
@ -62,7 +61,6 @@ public class IpcTester : IDisposable
{
if( !_subscribed )
{
_initialized.Subscribe( AddInitialized );
_disposed.Subscribe( AddDisposed );
_redrawn.Subscribe( SetLastRedrawn );
@ -124,7 +122,7 @@ public class IpcTester : IDisposable
}
catch( Exception e )
{
PluginLog.Error( $"Error during IPC Tests:\n{e}" );
Penumbra.Log.Error( $"Error during IPC Tests:\n{e}" );
}
}
@ -911,7 +909,7 @@ public class IpcTester : IDisposable
return;
}
using var table = ImRaii.Table( "##collTree", 4 );
using var table = ImRaii.Table( "##collTree", 5 );
if( !table )
{
return;
@ -927,6 +925,11 @@ public class IpcTester : IDisposable
ImGui.TextUnformatted( collection.ResolvedFiles.Count.ToString() );
ImGui.TableNextColumn();
ImGui.TextUnformatted( collection.MetaCache?.Count.ToString() ?? "0" );
ImGui.TableNextColumn();
if( ImGui.Button( $"Save##{character}" ) )
{
Mod.TemporaryMod.SaveTempCollection( collection, character );
}
}
}

View file

@ -1,8 +1,7 @@
using System.Collections.Generic;
using System.Linq;
using EmbedIO;
using EmbedIO.Routing;
using EmbedIO.WebApi;
using System.Linq;
namespace Penumbra.Api;

View file

@ -1,11 +1,4 @@
using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.IO;
using System.Linq;
using System.Reflection;
using Dalamud.Game.ClientState.Objects.Types;
using Dalamud.Logging;
using Lumina.Data;
using Newtonsoft.Json;
using OtterGui;
@ -16,6 +9,12 @@ using Penumbra.Interop.Resolver;
using Penumbra.Interop.Structs;
using Penumbra.Meta.Manipulations;
using Penumbra.Mods;
using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.IO;
using System.Linq;
using System.Reflection;
namespace Penumbra.Api;
@ -206,12 +205,12 @@ public class PenumbraApi : IDisposable, IPenumbraApi
return collection.ChangedItems.ToDictionary( kvp => kvp.Key, kvp => kvp.Value.Item2 );
}
PluginLog.Warning( $"Collection {collectionName} does not exist or is not loaded." );
Penumbra.Log.Warning( $"Collection {collectionName} does not exist or is not loaded." );
return new Dictionary< string, object? >();
}
catch( Exception e )
{
PluginLog.Error( $"Could not obtain Changed Items for {collectionName}:\n{e}" );
Penumbra.Log.Error( $"Could not obtain Changed Items for {collectionName}:\n{e}" );
throw;
}
}
@ -619,7 +618,7 @@ public class PenumbraApi : IDisposable, IPenumbraApi
}
catch( Exception e )
{
PluginLog.Warning( $"Could not load file {resolvedPath}:\n{e}" );
Penumbra.Log.Warning( $"Could not load file {resolvedPath}:\n{e}" );
return null;
}
}

View file

@ -1,11 +1,10 @@
using System;
using System.Collections.Generic;
using Dalamud.Game.ClientState.Objects.Types;
using Dalamud.Logging;
using Dalamud.Plugin;
using Dalamud.Plugin.Ipc;
using Penumbra.Collections;
using Penumbra.GameData.Enums;
using System;
using System.Collections.Generic;
namespace Penumbra.Api;
@ -73,7 +72,7 @@ public partial class PenumbraIpc
}
catch( Exception e )
{
PluginLog.Error( $"Error registering IPC provider for {LabelProviderInitialized}:\n{e}" );
Penumbra.Log.Error( $"Error registering IPC provider for {LabelProviderInitialized}:\n{e}" );
}
try
@ -82,7 +81,7 @@ public partial class PenumbraIpc
}
catch( Exception e )
{
PluginLog.Error( $"Error registering IPC provider for {LabelProviderDisposed}:\n{e}" );
Penumbra.Log.Error( $"Error registering IPC provider for {LabelProviderDisposed}:\n{e}" );
}
try
@ -90,13 +89,13 @@ public partial class PenumbraIpc
ProviderApiVersion = pi.GetIpcProvider< int >( LabelProviderApiVersion );
ProviderApiVersion.RegisterFunc( () =>
{
PluginLog.Warning( $"{LabelProviderApiVersion} is outdated. Please use {LabelProviderApiVersions} instead." );
Penumbra.Log.Warning( $"{LabelProviderApiVersion} is outdated. Please use {LabelProviderApiVersions} instead." );
return Api.ApiVersion.Breaking;
} );
}
catch( Exception e )
{
PluginLog.Error( $"Error registering IPC provider for {LabelProviderApiVersion}:\n{e}" );
Penumbra.Log.Error( $"Error registering IPC provider for {LabelProviderApiVersion}:\n{e}" );
}
try
@ -106,7 +105,7 @@ public partial class PenumbraIpc
}
catch( Exception e )
{
PluginLog.Error( $"Error registering IPC provider for {LabelProviderApiVersions}:\n{e}" );
Penumbra.Log.Error( $"Error registering IPC provider for {LabelProviderApiVersions}:\n{e}" );
}
try
@ -116,7 +115,7 @@ public partial class PenumbraIpc
}
catch( Exception e )
{
PluginLog.Error( $"Error registering IPC provider for {LabelProviderGetModDirectory}:\n{e}" );
Penumbra.Log.Error( $"Error registering IPC provider for {LabelProviderGetModDirectory}:\n{e}" );
}
try
@ -126,7 +125,7 @@ public partial class PenumbraIpc
}
catch( Exception e )
{
PluginLog.Error( $"Error registering IPC provider for {LabelProviderModDirectoryChanged}:\n{e}" );
Penumbra.Log.Error( $"Error registering IPC provider for {LabelProviderModDirectoryChanged}:\n{e}" );
}
try
@ -136,7 +135,7 @@ public partial class PenumbraIpc
}
catch( Exception e )
{
PluginLog.Error( $"Error registering IPC provider for {LabelProviderGetConfiguration}:\n{e}" );
Penumbra.Log.Error( $"Error registering IPC provider for {LabelProviderGetConfiguration}:\n{e}" );
}
try
@ -146,7 +145,7 @@ public partial class PenumbraIpc
}
catch( Exception e )
{
PluginLog.Error( $"Error registering IPC provider for {LabelProviderPreSettingsDraw}:\n{e}" );
Penumbra.Log.Error( $"Error registering IPC provider for {LabelProviderPreSettingsDraw}:\n{e}" );
}
try
@ -156,7 +155,7 @@ public partial class PenumbraIpc
}
catch( Exception e )
{
PluginLog.Error( $"Error registering IPC provider for {LabelProviderPostSettingsDraw}:\n{e}" );
Penumbra.Log.Error( $"Error registering IPC provider for {LabelProviderPostSettingsDraw}:\n{e}" );
}
}
@ -215,7 +214,7 @@ public partial class PenumbraIpc
}
catch( Exception e )
{
PluginLog.Error( $"Error registering IPC provider for {LabelProviderRedrawName}:\n{e}" );
Penumbra.Log.Error( $"Error registering IPC provider for {LabelProviderRedrawName}:\n{e}" );
}
try
@ -225,7 +224,7 @@ public partial class PenumbraIpc
}
catch( Exception e )
{
PluginLog.Error( $"Error registering IPC provider for {LabelProviderRedrawObject}:\n{e}" );
Penumbra.Log.Error( $"Error registering IPC provider for {LabelProviderRedrawObject}:\n{e}" );
}
try
@ -235,7 +234,7 @@ public partial class PenumbraIpc
}
catch( Exception e )
{
PluginLog.Error( $"Error registering IPC provider for {LabelProviderRedrawName}:\n{e}" );
Penumbra.Log.Error( $"Error registering IPC provider for {LabelProviderRedrawName}:\n{e}" );
}
try
@ -245,7 +244,7 @@ public partial class PenumbraIpc
}
catch( Exception e )
{
PluginLog.Error( $"Error registering IPC provider for {LabelProviderRedrawAll}:\n{e}" );
Penumbra.Log.Error( $"Error registering IPC provider for {LabelProviderRedrawAll}:\n{e}" );
}
try
@ -255,7 +254,7 @@ public partial class PenumbraIpc
}
catch( Exception e )
{
PluginLog.Error( $"Error registering IPC provider for {LabelProviderGameObjectRedrawn}:\n{e}" );
Penumbra.Log.Error( $"Error registering IPC provider for {LabelProviderGameObjectRedrawn}:\n{e}" );
}
}
@ -305,7 +304,7 @@ public partial class PenumbraIpc
}
catch( Exception e )
{
PluginLog.Error( $"Error registering IPC provider for {LabelProviderResolveDefault}:\n{e}" );
Penumbra.Log.Error( $"Error registering IPC provider for {LabelProviderResolveDefault}:\n{e}" );
}
try
@ -315,7 +314,7 @@ public partial class PenumbraIpc
}
catch( Exception e )
{
PluginLog.Error( $"Error registering IPC provider for {LabelProviderResolveCharacter}:\n{e}" );
Penumbra.Log.Error( $"Error registering IPC provider for {LabelProviderResolveCharacter}:\n{e}" );
}
try
@ -325,7 +324,7 @@ public partial class PenumbraIpc
}
catch( Exception e )
{
PluginLog.Error( $"Error registering IPC provider for {LabelProviderResolveCharacter}:\n{e}" );
Penumbra.Log.Error( $"Error registering IPC provider for {LabelProviderResolveCharacter}:\n{e}" );
}
try
@ -335,7 +334,7 @@ public partial class PenumbraIpc
}
catch( Exception e )
{
PluginLog.Error( $"Error registering IPC provider for {LabelProviderGetDrawObjectInfo}:\n{e}" );
Penumbra.Log.Error( $"Error registering IPC provider for {LabelProviderGetDrawObjectInfo}:\n{e}" );
}
try
@ -345,7 +344,7 @@ public partial class PenumbraIpc
}
catch( Exception e )
{
PluginLog.Error( $"Error registering IPC provider for {LabelProviderGetCutsceneParentIndex}:\n{e}" );
Penumbra.Log.Error( $"Error registering IPC provider for {LabelProviderGetCutsceneParentIndex}:\n{e}" );
}
try
@ -355,7 +354,7 @@ public partial class PenumbraIpc
}
catch( Exception e )
{
PluginLog.Error( $"Error registering IPC provider for {LabelProviderReverseResolvePath}:\n{e}" );
Penumbra.Log.Error( $"Error registering IPC provider for {LabelProviderReverseResolvePath}:\n{e}" );
}
try
@ -365,7 +364,7 @@ public partial class PenumbraIpc
}
catch( Exception e )
{
PluginLog.Error( $"Error registering IPC provider for {LabelProviderReverseResolvePlayerPath}:\n{e}" );
Penumbra.Log.Error( $"Error registering IPC provider for {LabelProviderReverseResolvePlayerPath}:\n{e}" );
}
try
@ -376,7 +375,7 @@ public partial class PenumbraIpc
}
catch( Exception e )
{
PluginLog.Error( $"Error registering IPC provider for {LabelProviderCreatingCharacterBase}:\n{e}" );
Penumbra.Log.Error( $"Error registering IPC provider for {LabelProviderCreatingCharacterBase}:\n{e}" );
}
try
@ -387,7 +386,7 @@ public partial class PenumbraIpc
}
catch( Exception e )
{
PluginLog.Error( $"Error registering IPC provider for {LabelProviderCreatedCharacterBase}:\n{e}" );
Penumbra.Log.Error( $"Error registering IPC provider for {LabelProviderCreatedCharacterBase}:\n{e}" );
}
try
@ -398,7 +397,7 @@ public partial class PenumbraIpc
}
catch( Exception e )
{
PluginLog.Error( $"Error registering IPC provider for {LabelProviderGameObjectResourcePathResolved}:\n{e}" );
Penumbra.Log.Error( $"Error registering IPC provider for {LabelProviderGameObjectResourcePathResolved}:\n{e}" );
}
}
@ -462,7 +461,7 @@ public partial class PenumbraIpc
}
catch( Exception e )
{
PluginLog.Error( $"Error registering IPC provider for {LabelProviderChangedItemTooltip}:\n{e}" );
Penumbra.Log.Error( $"Error registering IPC provider for {LabelProviderChangedItemTooltip}:\n{e}" );
}
try
@ -472,7 +471,7 @@ public partial class PenumbraIpc
}
catch( Exception e )
{
PluginLog.Error( $"Error registering IPC provider for {LabelProviderChangedItemClick}:\n{e}" );
Penumbra.Log.Error( $"Error registering IPC provider for {LabelProviderChangedItemClick}:\n{e}" );
}
try
@ -482,7 +481,7 @@ public partial class PenumbraIpc
}
catch( Exception e )
{
PluginLog.Error( $"Error registering IPC provider for {LabelProviderChangedItemClick}:\n{e}" );
Penumbra.Log.Error( $"Error registering IPC provider for {LabelProviderChangedItemClick}:\n{e}" );
}
}
@ -521,7 +520,7 @@ public partial class PenumbraIpc
}
catch( Exception e )
{
PluginLog.Error( $"Error registering IPC provider for {LabelProviderGetMods}:\n{e}" );
Penumbra.Log.Error( $"Error registering IPC provider for {LabelProviderGetMods}:\n{e}" );
}
try
@ -531,7 +530,7 @@ public partial class PenumbraIpc
}
catch( Exception e )
{
PluginLog.Error( $"Error registering IPC provider for {LabelProviderGetCollections}:\n{e}" );
Penumbra.Log.Error( $"Error registering IPC provider for {LabelProviderGetCollections}:\n{e}" );
}
try
@ -541,7 +540,7 @@ public partial class PenumbraIpc
}
catch( Exception e )
{
PluginLog.Error( $"Error registering IPC provider for {LabelProviderCurrentCollectionName}:\n{e}" );
Penumbra.Log.Error( $"Error registering IPC provider for {LabelProviderCurrentCollectionName}:\n{e}" );
}
try
@ -551,7 +550,7 @@ public partial class PenumbraIpc
}
catch( Exception e )
{
PluginLog.Error( $"Error registering IPC provider for {LabelProviderDefaultCollectionName}:\n{e}" );
Penumbra.Log.Error( $"Error registering IPC provider for {LabelProviderDefaultCollectionName}:\n{e}" );
}
try
@ -561,7 +560,7 @@ public partial class PenumbraIpc
}
catch( Exception e )
{
PluginLog.Error( $"Error registering IPC provider for {LabelProviderCharacterCollectionName}:\n{e}" );
Penumbra.Log.Error( $"Error registering IPC provider for {LabelProviderCharacterCollectionName}:\n{e}" );
}
try
@ -571,7 +570,7 @@ public partial class PenumbraIpc
}
catch( Exception e )
{
PluginLog.Error( $"Error registering IPC provider for {LabelProviderGetPlayerMetaManipulations}:\n{e}" );
Penumbra.Log.Error( $"Error registering IPC provider for {LabelProviderGetPlayerMetaManipulations}:\n{e}" );
}
try
@ -581,7 +580,7 @@ public partial class PenumbraIpc
}
catch( Exception e )
{
PluginLog.Error( $"Error registering IPC provider for {LabelProviderGetMetaManipulations}:\n{e}" );
Penumbra.Log.Error( $"Error registering IPC provider for {LabelProviderGetMetaManipulations}:\n{e}" );
}
}
@ -633,7 +632,7 @@ public partial class PenumbraIpc
}
catch( Exception e )
{
PluginLog.Error( $"Error registering IPC provider for {LabelProviderModSettingChanged}:\n{e}" );
Penumbra.Log.Error( $"Error registering IPC provider for {LabelProviderModSettingChanged}:\n{e}" );
}
try
@ -645,7 +644,7 @@ public partial class PenumbraIpc
}
catch( Exception e )
{
PluginLog.Error( $"Error registering IPC provider for {LabelProviderGetAvailableModSettings}:\n{e}" );
Penumbra.Log.Error( $"Error registering IPC provider for {LabelProviderGetAvailableModSettings}:\n{e}" );
}
try
@ -655,7 +654,7 @@ public partial class PenumbraIpc
}
catch( Exception e )
{
PluginLog.Error( $"Error registering IPC provider for {LabelProviderReloadMod}:\n{e}" );
Penumbra.Log.Error( $"Error registering IPC provider for {LabelProviderReloadMod}:\n{e}" );
}
try
@ -665,7 +664,7 @@ public partial class PenumbraIpc
}
catch( Exception e )
{
PluginLog.Error( $"Error registering IPC provider for {LabelProviderChangedItemClick}:\n{e}" );
Penumbra.Log.Error( $"Error registering IPC provider for {LabelProviderChangedItemClick}:\n{e}" );
}
try
@ -677,7 +676,7 @@ public partial class PenumbraIpc
}
catch( Exception e )
{
PluginLog.Error( $"Error registering IPC provider for {LabelProviderGetCurrentModSettings}:\n{e}" );
Penumbra.Log.Error( $"Error registering IPC provider for {LabelProviderGetCurrentModSettings}:\n{e}" );
}
try
@ -687,7 +686,7 @@ public partial class PenumbraIpc
}
catch( Exception e )
{
PluginLog.Error( $"Error registering IPC provider for {LabelProviderTryInheritMod}:\n{e}" );
Penumbra.Log.Error( $"Error registering IPC provider for {LabelProviderTryInheritMod}:\n{e}" );
}
try
@ -697,7 +696,7 @@ public partial class PenumbraIpc
}
catch( Exception e )
{
PluginLog.Error( $"Error registering IPC provider for {LabelProviderTrySetMod}:\n{e}" );
Penumbra.Log.Error( $"Error registering IPC provider for {LabelProviderTrySetMod}:\n{e}" );
}
try
@ -707,7 +706,7 @@ public partial class PenumbraIpc
}
catch( Exception e )
{
PluginLog.Error( $"Error registering IPC provider for {LabelProviderTrySetModPriority}:\n{e}" );
Penumbra.Log.Error( $"Error registering IPC provider for {LabelProviderTrySetModPriority}:\n{e}" );
}
try
@ -718,7 +717,7 @@ public partial class PenumbraIpc
}
catch( Exception e )
{
PluginLog.Error( $"Error registering IPC provider for {LabelProviderTrySetModSetting}:\n{e}" );
Penumbra.Log.Error( $"Error registering IPC provider for {LabelProviderTrySetModSetting}:\n{e}" );
}
try
@ -729,7 +728,7 @@ public partial class PenumbraIpc
}
catch( Exception e )
{
PluginLog.Error( $"Error registering IPC provider for {LabelProviderTrySetModSettings}:\n{e}" );
Penumbra.Log.Error( $"Error registering IPC provider for {LabelProviderTrySetModSettings}:\n{e}" );
}
}
@ -782,7 +781,7 @@ public partial class PenumbraIpc
}
catch( Exception e )
{
PluginLog.Error( $"Error registering IPC provider for {LabelProviderCreateTemporaryCollection}:\n{e}" );
Penumbra.Log.Error( $"Error registering IPC provider for {LabelProviderCreateTemporaryCollection}:\n{e}" );
}
try
@ -793,7 +792,7 @@ public partial class PenumbraIpc
}
catch( Exception e )
{
PluginLog.Error( $"Error registering IPC provider for {LabelProviderRemoveTemporaryCollection}:\n{e}" );
Penumbra.Log.Error( $"Error registering IPC provider for {LabelProviderRemoveTemporaryCollection}:\n{e}" );
}
try
@ -805,7 +804,7 @@ public partial class PenumbraIpc
}
catch( Exception e )
{
PluginLog.Error( $"Error registering IPC provider for {LabelProviderAddTemporaryModAll}:\n{e}" );
Penumbra.Log.Error( $"Error registering IPC provider for {LabelProviderAddTemporaryModAll}:\n{e}" );
}
try
@ -817,7 +816,7 @@ public partial class PenumbraIpc
}
catch( Exception e )
{
PluginLog.Error( $"Error registering IPC provider for {LabelProviderAddTemporaryMod}:\n{e}" );
Penumbra.Log.Error( $"Error registering IPC provider for {LabelProviderAddTemporaryMod}:\n{e}" );
}
try
@ -827,7 +826,7 @@ public partial class PenumbraIpc
}
catch( Exception e )
{
PluginLog.Error( $"Error registering IPC provider for {LabelProviderRemoveTemporaryModAll}:\n{e}" );
Penumbra.Log.Error( $"Error registering IPC provider for {LabelProviderRemoveTemporaryModAll}:\n{e}" );
}
try
@ -837,7 +836,7 @@ public partial class PenumbraIpc
}
catch( Exception e )
{
PluginLog.Error( $"Error registering IPC provider for {LabelProviderRemoveTemporaryMod}:\n{e}" );
Penumbra.Log.Error( $"Error registering IPC provider for {LabelProviderRemoveTemporaryMod}:\n{e}" );
}
}

View file

@ -1,8 +1,8 @@
using System.Threading.Tasks;
using EmbedIO;
using EmbedIO.Routing;
using EmbedIO.WebApi;
using Penumbra.GameData.Enums;
using System.Threading.Tasks;
namespace Penumbra.Api;

View file

@ -1,11 +1,11 @@
using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using OtterGui;
using Penumbra.Collections;
using Penumbra.GameData.ByteString;
using Penumbra.Meta.Manipulations;
using Penumbra.Mods;
using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
namespace Penumbra.Api;

View file

@ -1,13 +1,12 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Dalamud.Logging;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using OtterGui;
using Penumbra.Mods;
using Penumbra.UI;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
namespace Penumbra.Collections;
@ -197,7 +196,7 @@ public partial class ModCollection
var defaultIdx = GetIndexForCollectionName( defaultName );
if( defaultIdx < 0 )
{
PluginLog.Error( $"Last choice of {ConfigWindow.DefaultCollection} {defaultName} is not available, reset to {Empty.Name}." );
Penumbra.Log.Error( $"Last choice of {ConfigWindow.DefaultCollection} {defaultName} is not available, reset to {Empty.Name}." );
Default = Empty;
configChanged = true;
}
@ -211,7 +210,7 @@ public partial class ModCollection
var currentIdx = GetIndexForCollectionName( currentName );
if( currentIdx < 0 )
{
PluginLog.Error( $"Last choice of {ConfigWindow.SelectedCollection} {currentName} is not available, reset to {DefaultCollection}." );
Penumbra.Log.Error( $"Last choice of {ConfigWindow.SelectedCollection} {currentName} is not available, reset to {DefaultCollection}." );
Current = DefaultName;
configChanged = true;
}
@ -229,7 +228,7 @@ public partial class ModCollection
var idx = GetIndexForCollectionName( typeName );
if( idx < 0 )
{
PluginLog.Error( $"Last choice of {type.ToName()} Collection {typeName} is not available, removed." );
Penumbra.Log.Error( $"Last choice of {type.ToName()} Collection {typeName} is not available, removed." );
configChanged = true;
}
else
@ -246,7 +245,7 @@ public partial class ModCollection
var idx = GetIndexForCollectionName( collectionName );
if( idx < 0 )
{
PluginLog.Error( $"Last choice of <{player}>'s Collection {collectionName} is not available, reset to {Empty.Name}." );
Penumbra.Log.Error( $"Last choice of <{player}>'s Collection {collectionName} is not available, reset to {Empty.Name}." );
_characters.Add( player, Empty );
configChanged = true;
}
@ -306,11 +305,11 @@ public partial class ModCollection
j.WriteEndObject();
j.WriteEndObject();
PluginLog.Verbose( "Active Collections saved." );
Penumbra.Log.Verbose( "Active Collections saved." );
}
catch( Exception e )
{
PluginLog.Error( $"Could not save active collections to file {file}:\n{e}" );
Penumbra.Log.Error( $"Could not save active collections to file {file}:\n{e}" );
}
}
@ -328,7 +327,7 @@ public partial class ModCollection
}
catch( Exception e )
{
PluginLog.Error( $"Could not read active collections from file {file}:\n{e}" );
Penumbra.Log.Error( $"Could not read active collections from file {file}:\n{e}" );
}
}

View file

@ -1,13 +1,12 @@
using OtterGui;
using OtterGui.Filesystem;
using Penumbra.Mods;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.IO;
using System.Linq;
using Dalamud.Logging;
using OtterGui;
using OtterGui.Filesystem;
using Penumbra.Mods;
namespace Penumbra.Collections;
@ -107,7 +106,7 @@ public partial class ModCollection
{
if( !CanAddCollection( name, out var fixedName ) )
{
PluginLog.Warning( $"The new collection {name} would lead to the same path {fixedName} as one that already exists." );
Penumbra.Log.Warning( $"The new collection {name} would lead to the same path {fixedName} as one that already exists." );
return false;
}
@ -115,7 +114,7 @@ public partial class ModCollection
newCollection.Index = _collections.Count;
_collections.Add( newCollection );
newCollection.Save();
PluginLog.Debug( "Added collection {Name:l}.", newCollection.AnonymizedName );
Penumbra.Log.Debug( $"Added collection {newCollection.AnonymizedName}." );
CollectionChanged.Invoke( CollectionType.Inactive, null, newCollection );
SetCollection( newCollection.Index, CollectionType.Current );
return true;
@ -128,13 +127,13 @@ public partial class ModCollection
{
if( idx <= Empty.Index || idx >= _collections.Count )
{
PluginLog.Error( "Can not remove the empty collection." );
Penumbra.Log.Error( "Can not remove the empty collection." );
return false;
}
if( idx == DefaultName.Index )
{
PluginLog.Error( "Can not remove the default collection." );
Penumbra.Log.Error( "Can not remove the default collection." );
return false;
}
@ -179,7 +178,7 @@ public partial class ModCollection
}
}
PluginLog.Debug( "Removed collection {Name:l}.", collection.AnonymizedName );
Penumbra.Log.Debug( $"Removed collection {collection.AnonymizedName}." );
CollectionChanged.Invoke( CollectionType.Inactive, collection, null );
return true;
}
@ -335,12 +334,12 @@ public partial class ModCollection
if( !ByName( subCollectionName, out var subCollection ) )
{
changes = true;
PluginLog.Warning( $"Inherited collection {subCollectionName} for {collection.Name} does not exist, removed." );
Penumbra.Log.Warning( $"Inherited collection {subCollectionName} for {collection.Name} does not exist, removed." );
}
else if( !collection.AddInheritance( subCollection ) )
{
changes = true;
PluginLog.Warning( $"{collection.Name} can not inherit from {subCollectionName}, removed." );
Penumbra.Log.Warning( $"{collection.Name} can not inherit from {subCollectionName}, removed." );
}
}
@ -370,12 +369,12 @@ public partial class ModCollection
if( file.Name != $"{collection.Name.RemoveInvalidPathSymbols()}.json" )
{
PluginLog.Warning( $"Collection {file.Name} does not correspond to {collection.Name}." );
Penumbra.Log.Warning( $"Collection {file.Name} does not correspond to {collection.Name}." );
}
if( this[ collection.Name ] != null )
{
PluginLog.Warning( $"Duplicate collection found: {collection.Name} already exists." );
Penumbra.Log.Warning( $"Duplicate collection found: {collection.Name} already exists." );
}
else
{

View file

@ -1,6 +1,6 @@
using Penumbra.GameData.Enums;
using System;
using System.Linq;
using Penumbra.GameData.Enums;
namespace Penumbra.Collections;

View file

@ -1,13 +1,14 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Runtime.CompilerServices;
using System.Threading;
using Dalamud.Logging;
using OtterGui.Classes;
using Penumbra.GameData.ByteString;
using Penumbra.GameData.Enums;
using Penumbra.Meta.Manager;
using Penumbra.Mods;
using System;
using System.Collections.Generic;
using System.Runtime.CompilerServices;
using System.Threading;
using Penumbra.Interop;
using Penumbra.Meta.Manipulations;
namespace Penumbra.Collections;
@ -29,7 +30,7 @@ public partial class ModCollection
if( _cache == null )
{
CalculateEffectiveFileList();
PluginLog.Verbose( "Created new cache for collection {Name:l}.", Name );
Penumbra.Log.Verbose( $"Created new cache for collection {Name}." );
}
}
@ -61,7 +62,7 @@ public partial class ModCollection
{
_cache?.Dispose();
_cache = null;
PluginLog.Verbose( "Cleared cache of collection {Name:l}.", Name );
Penumbra.Log.Verbose( $"Cleared cache of collection {Name}." );
}
public IEnumerable< Utf8GamePath > ReverseResolvePath( FullPath path )
@ -87,7 +88,7 @@ public partial class ModCollection
return true;
}
PluginLog.Error( $"The redirected path is too long to add the redirection\n\t{path}\n\t--> {fullPath}" );
Penumbra.Log.Error( $"The redirected path is too long to add the redirection\n\t{path}\n\t--> {fullPath}" );
return false;
}
@ -125,13 +126,11 @@ public partial class ModCollection
return;
}
PluginLog.Debug( "[{Thread}] Recalculating effective file list for {CollectionName:l}",
Thread.CurrentThread.ManagedThreadId, AnonymizedName );
Penumbra.Log.Debug( $"[{Thread.CurrentThread.ManagedThreadId}] Recalculating effective file list for {AnonymizedName}" );
_cache ??= new Cache( this );
_cache.FullRecalculation();
PluginLog.Debug( "[{Thread}] Recalculation of effective file list for {CollectionName:l} finished.",
Thread.CurrentThread.ManagedThreadId, AnonymizedName );
Penumbra.Log.Debug( $"[{Thread.CurrentThread.ManagedThreadId}] Recalculation of effective file list for {AnonymizedName} finished." );
}
// Set Metadata files.
@ -204,7 +203,24 @@ public partial class ModCollection
else
{
_cache.MetaManipulations.SetFiles();
PluginLog.Debug( "Set CharacterUtility resources for collection {Name:l}.", Name );
Penumbra.Log.Debug( $"Set CharacterUtility resources for collection {Name}." );
}
}
}
// Used for short periods of changed files.
public CharacterUtility.List.MetaReverter? TemporarilySetEqdpFile( GenderRace genderRace, bool accessory )
=> _cache?.MetaManipulations.TemporarilySetEqdpFile( genderRace, accessory );
public CharacterUtility.List.MetaReverter? TemporarilySetEqpFile()
=> _cache?.MetaManipulations.TemporarilySetEqpFile();
public CharacterUtility.List.MetaReverter? TemporarilySetGmpFile()
=> _cache?.MetaManipulations.TemporarilySetGmpFile();
public CharacterUtility.List.MetaReverter? TemporarilySetCmpFile()
=> _cache?.MetaManipulations.TemporarilySetCmpFile();
public CharacterUtility.List.MetaReverter? TemporarilySetEstFile( EstManipulation.EstType type )
=> _cache?.MetaManipulations.TemporarilySetEstFile( type );
}

View file

@ -1,13 +1,12 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Dalamud.Logging;
using OtterGui;
using OtterGui.Classes;
using Penumbra.GameData.ByteString;
using Penumbra.Meta.Manager;
using Penumbra.Meta.Manipulations;
using Penumbra.Mods;
using System;
using System.Collections.Generic;
using System.Linq;
namespace Penumbra.Collections;
@ -496,7 +495,7 @@ public partial class ModCollection
}
catch( Exception e )
{
PluginLog.Error( $"Unknown Error:\n{e}" );
Penumbra.Log.Error( $"Unknown Error:\n{e}" );
}
}
}

View file

@ -1,7 +1,7 @@
using Penumbra.Mods;
using System;
using System.Collections.Generic;
using System.Linq;
using Penumbra.Mods;
namespace Penumbra.Collections;

View file

@ -1,13 +1,12 @@
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using OtterGui.Filesystem;
using Penumbra.Mods;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using Dalamud.Logging;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using OtterGui.Filesystem;
using Penumbra.Mods;
namespace Penumbra.Collections;
@ -67,7 +66,7 @@ public partial class ModCollection
}
catch( Exception e )
{
PluginLog.Error( $"Could not save collection {AnonymizedName}:\n{e}" );
Penumbra.Log.Error( $"Could not save collection {AnonymizedName}:\n{e}" );
}
}
@ -90,11 +89,11 @@ public partial class ModCollection
try
{
file.Delete();
PluginLog.Information( "Deleted collection file for {Name:l}.", AnonymizedName );
Penumbra.Log.Information( $"Deleted collection file for {AnonymizedName}." );
}
catch( Exception e )
{
PluginLog.Error( $"Could not delete collection file for {AnonymizedName}:\n{e}" );
Penumbra.Log.Error( $"Could not delete collection file for {AnonymizedName}:\n{e}" );
}
}
@ -105,7 +104,7 @@ public partial class ModCollection
inheritance = Array.Empty< string >();
if( !file.Exists )
{
PluginLog.Error( $"Could not read collection because file does not exist." );
Penumbra.Log.Error( "Could not read collection because file does not exist." );
return null;
}
@ -123,7 +122,7 @@ public partial class ModCollection
}
catch( Exception e )
{
PluginLog.Error( $"Could not read collection information from file:\n{e}" );
Penumbra.Log.Error( $"Could not read collection information from file:\n{e}" );
}
return null;

View file

@ -1,9 +1,8 @@
using OtterGui.Filesystem;
using Penumbra.Mods;
using System;
using System.Collections.Generic;
using System.Linq;
using Dalamud.Logging;
using OtterGui.Filesystem;
using Penumbra.Mods;
namespace Penumbra.Collections;
@ -81,7 +80,7 @@ public partial class ModCollection
collection.ModSettingChanged += OnInheritedModSettingChange;
collection.InheritanceChanged += OnInheritedInheritanceChange;
InheritanceChanged.Invoke( false );
PluginLog.Debug( "Added {InheritedName:l} to {Name:l} inheritances.", collection.AnonymizedName, AnonymizedName );
Penumbra.Log.Debug( $"Added {collection.AnonymizedName} to {AnonymizedName} inheritances." );
return true;
}
@ -91,7 +90,7 @@ public partial class ModCollection
ClearSubscriptions( inheritance );
_inheritance.RemoveAt( idx );
InheritanceChanged.Invoke( false );
PluginLog.Debug( "Removed {InheritedName:l} from {Name:l} inheritances.", inheritance.AnonymizedName, AnonymizedName );
Penumbra.Log.Debug( $"Removed {inheritance.AnonymizedName} from {AnonymizedName} inheritances." );
}
private void ClearSubscriptions( ModCollection other )
@ -106,7 +105,7 @@ public partial class ModCollection
if( _inheritance.Move( from, to ) )
{
InheritanceChanged.Invoke( false );
PluginLog.Debug( "Moved {Name:l}s inheritance {From} to {To}.", AnonymizedName, from, to );
Penumbra.Log.Debug( $"Moved {AnonymizedName}s inheritance {from} to {to}." );
}
}
@ -122,7 +121,7 @@ public partial class ModCollection
default:
if( modIdx < 0 || modIdx >= _settings.Count )
{
PluginLog.Warning(
Penumbra.Log.Warning(
$"Collection state broken, Mod {modIdx} in inheritance does not exist. ({_settings.Count} mods exist)." );
return;
}

View file

@ -1,6 +1,6 @@
using Penumbra.Mods;
using System.Collections.Generic;
using System.Linq;
using Penumbra.Mods;
namespace Penumbra.Collections;

View file

@ -1,8 +1,8 @@
using OtterGui.Filesystem;
using Penumbra.Mods;
using System;
using System.Collections.Generic;
using System.Linq;
using OtterGui.Filesystem;
using Penumbra.Mods;
namespace Penumbra.Collections;

View file

@ -2,7 +2,6 @@ using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Dalamud.Logging;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using OtterGui.Filesystem;
@ -47,6 +46,15 @@ public partial class Configuration
m.Version1To2();
m.Version2To3();
m.Version3To4();
m.Version4To5();
}
// Mod backup extension was changed from .zip to .pmp.
// Actual migration takes place in ModManager.
private void Version4To5()
{
Mod.Manager.MigrateModBackups = true;
_config.Version = 5;
}
// SortMode was changed from an enum to a type.
@ -117,7 +125,7 @@ public partial class Configuration
}
catch( Exception e )
{
PluginLog.Error( $"Could not delete the outdated penumbrametatmp folder:\n{e}" );
Penumbra.Log.Error( $"Could not delete the outdated penumbrametatmp folder:\n{e}" );
}
}
}
@ -144,7 +152,7 @@ public partial class Configuration
}
catch( Exception e )
{
PluginLog.Error(
Penumbra.Log.Error(
$"Could not transfer forced collection {ForcedCollection} to inheritance of collection {collection}:\n{e}" );
}
}
@ -249,7 +257,7 @@ public partial class Configuration
}
catch( Exception e )
{
PluginLog.Error( $"Could not migrate the old collection file to new collection files:\n{e}" );
Penumbra.Log.Error( $"Could not migrate the old collection file to new collection files:\n{e}" );
throw;
}
}
@ -265,7 +273,7 @@ public partial class Configuration
}
catch( Exception e )
{
PluginLog.Error( $"Could not create backup copy of config at {bakName}:\n{e}" );
Penumbra.Log.Error( $"Could not create backup copy of config at {bakName}:\n{e}" );
}
}

View file

@ -3,7 +3,6 @@ using System.Collections.Generic;
using System.IO;
using System.Linq;
using Dalamud.Configuration;
using Dalamud.Logging;
using Newtonsoft.Json;
using OtterGui;
using OtterGui.Classes;
@ -23,6 +22,7 @@ public partial class Configuration : IPluginConfiguration
public int Version { get; set; } = Constants.CurrentVersion;
public int LastSeenVersion { get; set; } = ConfigWindow.LastChangelogVersion;
public ChangeLogDisplayType ChangeLogDisplayType { get; set; } = ChangeLogDisplayType.New;
public bool EnableMods { get; set; } = true;
public string ModDirectory { get; set; } = string.Empty;
@ -79,7 +79,7 @@ public partial class Configuration : IPluginConfiguration
{
void HandleDeserializationError( object? sender, ErrorEventArgs errorArgs )
{
PluginLog.Error(
Penumbra.Log.Error(
$"Error parsing Configuration at {errorArgs.ErrorContext.Path}, using default or migrating:\n{errorArgs.ErrorContext.Error}" );
errorArgs.ErrorContext.Handled = true;
}
@ -117,7 +117,7 @@ public partial class Configuration : IPluginConfiguration
}
catch( Exception e )
{
PluginLog.Error( $"Could not save plugin configuration:\n{e}" );
Penumbra.Log.Error( $"Could not save plugin configuration:\n{e}" );
}
}
@ -142,7 +142,7 @@ public partial class Configuration : IPluginConfiguration
// Contains some default values or boundaries for config values.
public static class Constants
{
public const int CurrentVersion = 4;
public const int CurrentVersion = 5;
public const float MaxAbsoluteSize = 600;
public const int DefaultAbsoluteSize = 250;
public const float MinAbsoluteSize = 50;

View file

@ -1,6 +1,6 @@
using System.Text.RegularExpressions;
using Penumbra.GameData.Enums;
using Penumbra.GameData.Util;
using System.Text.RegularExpressions;
namespace Penumbra.Import;

View file

@ -1,6 +1,6 @@
using Penumbra.Util;
using System;
using System.IO;
using Penumbra.Util;
namespace Penumbra.Import;

View file

@ -5,7 +5,6 @@ using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Dalamud.Logging;
using Newtonsoft.Json;
using Penumbra.Mods;
using FileMode = System.IO.FileMode;
@ -121,7 +120,7 @@ public partial class TexToolsImporter : IDisposable
// Puts out warnings if extension does not correspond to data.
private DirectoryInfo VerifyVersionAndImport( FileInfo modPackFile )
{
if( modPackFile.Extension is ".zip" or ".7z" or ".rar" )
if( modPackFile.Extension.ToLowerInvariant() is ".pmp" or ".zip" or ".7z" or ".rar" )
{
return HandleRegularArchive( modPackFile );
}
@ -142,7 +141,7 @@ public partial class TexToolsImporter : IDisposable
{
if( modPackFile.Extension != ".ttmp2" )
{
PluginLog.Warning( $"File {modPackFile.FullName} seems to be a V2 TTMP, but has the wrong extension." );
Penumbra.Log.Warning( $"File {modPackFile.FullName} seems to be a V2 TTMP, but has the wrong extension." );
}
return ImportV2ModPack( modPackFile, extractedModPack, modRaw );
@ -150,7 +149,7 @@ public partial class TexToolsImporter : IDisposable
if( modPackFile.Extension != ".ttmp" )
{
PluginLog.Warning( $"File {modPackFile.FullName} seems to be a V1 TTMP, but has the wrong extension." );
Penumbra.Log.Warning( $"File {modPackFile.FullName} seems to be a V1 TTMP, but has the wrong extension." );
}
return ImportV1ModPack( modPackFile, extractedModPack, modRaw );

View file

@ -1,7 +1,3 @@
using System;
using System.IO;
using System.Linq;
using Dalamud.Logging;
using Dalamud.Utility;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
@ -13,6 +9,9 @@ using SharpCompress.Archives.SevenZip;
using SharpCompress.Archives.Zip;
using SharpCompress.Common;
using SharpCompress.Readers;
using System;
using System.IO;
using System.Linq;
namespace Penumbra.Import;
@ -43,7 +42,7 @@ public partial class TexToolsImporter
SevenZipArchive s => s.Entries.Count,
_ => archive.Entries.Count(),
};
PluginLog.Log( $" -> Importing {archive.Type} Archive." );
Penumbra.Log.Information( $" -> Importing {archive.Type} Archive." );
_currentModDirectory = Mod.CreateModFolder( _baseDirectory, Path.GetRandomFileName() );
var options = new ExtractionOptions()
@ -66,7 +65,7 @@ public partial class TexToolsImporter
continue;
}
PluginLog.Log( " -> Extracting {0}", reader.Entry.Key );
Penumbra.Log.Information( $" -> Extracting {reader.Entry.Key}" );
// Check that the mod has a valid name in the meta.json file.
if( Path.GetFileName( reader.Entry.Key ) == "meta.json" )
{

View file

@ -3,7 +3,6 @@ using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using Dalamud.Logging;
using Newtonsoft.Json;
using Penumbra.Mods;
using Penumbra.Util;
@ -24,7 +23,7 @@ public partial class TexToolsImporter
_currentGroupName = string.Empty;
_currentOptionName = DefaultTexToolsData.DefaultOption;
PluginLog.Log( " -> Importing V1 ModPack" );
Penumbra.Log.Information( " -> Importing V1 ModPack" );
var modListRaw = modRaw.Split(
new[] { "\r\n", "\r", "\n" },
@ -62,12 +61,12 @@ public partial class TexToolsImporter
try
{
PluginLog.Warning( $"Unknown TTMPVersion <{modList.TtmpVersion}> given, trying to export as simple mod pack." );
Penumbra.Log.Warning( $"Unknown TTMPVersion <{modList.TtmpVersion}> given, trying to export as simple mod pack." );
return ImportSimpleV2ModPack( extractedModPack, modList );
}
catch( Exception e1 )
{
PluginLog.Warning( $"Exporting as simple mod pack failed with following error, retrying as extended mod pack:\n{e1}" );
Penumbra.Log.Warning( $"Exporting as simple mod pack failed with following error, retrying as extended mod pack:\n{e1}" );
try
{
return ImportExtendedV2ModPack( extractedModPack, modRaw );
@ -87,7 +86,7 @@ public partial class TexToolsImporter
_currentModName = modList.Name;
_currentGroupName = string.Empty;
_currentOptionName = DefaultTexToolsData.DefaultOption;
PluginLog.Log( " -> Importing Simple V2 ModPack" );
Penumbra.Log.Information( " -> Importing Simple V2 ModPack" );
_currentModDirectory = Mod.CreateModFolder( _baseDirectory, _currentModName );
Mod.CreateMeta( _currentModDirectory, _currentModName, modList.Author, string.IsNullOrEmpty( modList.Description )
@ -128,7 +127,7 @@ public partial class TexToolsImporter
private DirectoryInfo ImportExtendedV2ModPack( ZipArchive extractedModPack, string modRaw )
{
_currentOptionIdx = 0;
PluginLog.Log( " -> Importing Extended V2 ModPack" );
Penumbra.Log.Information( " -> Importing Extended V2 ModPack" );
var modList = JsonConvert.DeserializeObject< ExtendedModPack >( modRaw, JsonSettings )!;
_currentNumOptions = GetOptionCount( modList );
@ -243,7 +242,7 @@ public partial class TexToolsImporter
return;
}
PluginLog.Log( " -> Extracting {0} at {1}", mod.FullPath, mod.ModOffset.ToString( "X" ) );
Penumbra.Log.Information( $" -> Extracting {mod.FullPath} at {mod.ModOffset:X}" );
_token.ThrowIfCancellationRequested();
var data = stream.ReadFile< PenumbraSqPackStream.PenumbraFileResource >( mod.ModOffset );

View file

@ -1,6 +1,5 @@
using System;
using System.IO;
using Dalamud.Logging;
using Lumina.Extensions;
using Penumbra.GameData.Enums;
using Penumbra.GameData.Structs;
@ -166,7 +165,7 @@ public partial class TexToolsMeta
}
catch( Exception e )
{
PluginLog.Warning(
Penumbra.Log.Warning(
$"Could not compute IMC manipulation for {metaFileInfo.PrimaryType} {metaFileInfo.PrimaryId}. This is in all likelihood due to TexTools corrupting your index files.\n"
+ $"If the following error looks like Lumina is having trouble to read an IMC file, please do a do-over in TexTools:\n{e}" );
}

View file

@ -1,6 +1,5 @@
using System;
using System.IO;
using Dalamud.Logging;
using Penumbra.GameData.Enums;
using Penumbra.Meta.Files;
using Penumbra.Meta.Manipulations;
@ -14,7 +13,7 @@ public partial class TexToolsMeta
{
if( data.Length != 45 && data.Length != 42 )
{
PluginLog.Error( "Error while parsing .rgsp file:\n\tInvalid number of bytes." );
Penumbra.Log.Error( "Error while parsing .rgsp file:\n\tInvalid number of bytes." );
return Invalid;
}
@ -32,7 +31,7 @@ public partial class TexToolsMeta
var subRace = ( SubRace )( version == 1 ? flag + 1 : br.ReadByte() + 1 );
if( !Enum.IsDefined( typeof( SubRace ), subRace ) || subRace == SubRace.Unknown )
{
PluginLog.Error( $"Error while parsing .rgsp file:\n\t{subRace} is not a valid SubRace." );
Penumbra.Log.Error( $"Error while parsing .rgsp file:\n\t{subRace} is not a valid SubRace." );
return Invalid;
}
@ -40,7 +39,7 @@ public partial class TexToolsMeta
var gender = br.ReadByte();
if( gender != 1 && gender != 0 )
{
PluginLog.Error( $"Error while parsing .rgsp file:\n\t{gender} is neither Male nor Female." );
Penumbra.Log.Error( $"Error while parsing .rgsp file:\n\t{gender} is neither Male nor Female." );
return Invalid;
}

View file

@ -1,7 +1,6 @@
using System;
using System.Collections.Generic;
using System.IO;
using Dalamud.Logging;
using Penumbra.Meta.Manipulations;
namespace Penumbra.Import;
@ -72,7 +71,7 @@ public partial class TexToolsMeta
catch( Exception e )
{
FilePath = "";
PluginLog.Error( $"Error while parsing .meta file:\n{e}" );
Penumbra.Log.Error( $"Error while parsing .meta file:\n{e}" );
}
}

View file

@ -1,8 +1,8 @@
using System;
using System.IO;
using Lumina.Data.Files;
using SixLabors.ImageSharp;
using SixLabors.ImageSharp.PixelFormats;
using System;
using System.IO;
namespace Penumbra.Import.Dds;

View file

@ -0,0 +1,147 @@
using System;
using System.Collections.Generic;
namespace Penumbra.Interop;
public unsafe partial class CharacterUtility
{
public class List : IDisposable
{
private readonly LinkedList< MetaReverter > _entries = new();
public readonly InternalIndex Index;
public readonly Structs.CharacterUtility.Index GlobalIndex;
private IntPtr _defaultResourceData = IntPtr.Zero;
private int _defaultResourceSize = 0;
public bool Ready { get; private set; } = false;
public List( InternalIndex index )
{
Index = index;
GlobalIndex = RelevantIndices[ index.Value ];
}
public void SetDefaultResource( IntPtr data, int size )
{
if( !Ready )
{
_defaultResourceData = data;
_defaultResourceSize = size;
Ready = _defaultResourceData != IntPtr.Zero && size != 0;
if( _entries.Count > 0 )
{
var first = _entries.First!.Value;
SetResource( first.Data, first.Length );
}
}
}
public (IntPtr Address, int Size) DefaultResource
=> ( _defaultResourceData, _defaultResourceSize );
public MetaReverter TemporarilySetResource( IntPtr data, int length )
{
Penumbra.Log.Verbose( $"Temporarily set resource {GlobalIndex} to 0x{( ulong )data:X} ({length} bytes)." );
var reverter = new MetaReverter( this, data, length );
_entries.AddFirst( reverter );
SetResourceInternal( data, length );
return reverter;
}
public MetaReverter TemporarilyResetResource()
{
Penumbra.Log.Verbose( $"Temporarily reset resource {GlobalIndex} to default at 0x{_defaultResourceData:X} ({_defaultResourceSize} bytes)." );
var reverter = new MetaReverter( this );
_entries.AddFirst( reverter );
ResetResourceInternal();
return reverter;
}
public void SetResource( IntPtr data, int length )
{
Penumbra.Log.Verbose( $"Set resource {GlobalIndex} to 0x{( ulong )data:X} ({length} bytes)." );
SetResourceInternal( data, length );
}
public void ResetResource()
{
Penumbra.Log.Verbose( $"Reset resource {GlobalIndex} to default at 0x{_defaultResourceData:X} ({_defaultResourceSize} bytes)." );
ResetResourceInternal();
}
// Set the currently stored data of this resource to new values.
private void SetResourceInternal( IntPtr data, int length )
{
if( Ready )
{
var resource = Penumbra.CharacterUtility.Address->Resource( GlobalIndex );
resource->SetData( data, length );
}
}
// Reset the currently stored data of this resource to its default values.
private void ResetResourceInternal()
=> SetResourceInternal( _defaultResourceData, _defaultResourceSize );
public void Dispose()
{
if( _entries.Count > 0 )
{
_entries.Clear();
ResetResourceInternal();
}
}
public sealed class MetaReverter : IDisposable
{
public readonly List List;
public readonly IntPtr Data;
public readonly int Length;
public readonly bool Resetter;
public MetaReverter( List list, IntPtr data, int length )
{
List = list;
Data = data;
Length = length;
}
public MetaReverter( List list )
{
List = list;
Data = IntPtr.Zero;
Length = 0;
Resetter = true;
}
public void Dispose()
{
var list = List._entries;
var wasCurrent = ReferenceEquals( this, list.First?.Value );
list.Remove( this );
if( !wasCurrent )
{
return;
}
if( list.Count == 0 )
{
List.ResetResourceInternal();
}
else
{
var next = list.First!.Value;
if( next.Resetter )
{
List.ResetResourceInternal();
}
else
{
List.SetResourceInternal( next.Data, next.Length );
}
}
}
}
}
}

View file

@ -1,11 +1,10 @@
using System;
using System.Linq;
using Dalamud.Logging;
using Dalamud.Utility.Signatures;
namespace Penumbra.Interop;
public unsafe class CharacterUtility : IDisposable
public unsafe partial class CharacterUtility : IDisposable
{
public record struct InternalIndex( int Value );
@ -35,22 +34,20 @@ public unsafe class CharacterUtility : IDisposable
public static readonly InternalIndex[] ReverseIndices
= Enumerable.Range( 0, Structs.CharacterUtility.TotalNumResources )
.Select( i => new InternalIndex( Array.IndexOf( RelevantIndices, (Structs.CharacterUtility.Index) i ) ) )
.Select( i => new InternalIndex( Array.IndexOf( RelevantIndices, ( Structs.CharacterUtility.Index )i ) ) )
.ToArray();
private readonly (IntPtr Address, int Size)[] _defaultResources = new (IntPtr, int)[RelevantIndices.Length];
public (IntPtr Address, int Size) DefaultResource( Structs.CharacterUtility.Index idx )
=> _defaultResources[ ReverseIndices[ ( int )idx ].Value ];
private readonly List[] _lists = Enumerable.Range( 0, RelevantIndices.Length )
.Select( idx => new List( new InternalIndex( idx ) ) )
.ToArray();
public (IntPtr Address, int Size) DefaultResource( InternalIndex idx )
=> _defaultResources[ idx.Value ];
=> _lists[ idx.Value ].DefaultResource;
public CharacterUtility()
{
SignatureHelper.Initialise( this );
LoadingFinished += () => PluginLog.Debug( "Loading of CharacterUtility finished." );
LoadingFinished += () => Penumbra.Log.Debug( "Loading of CharacterUtility finished." );
LoadDefaultResources( null! );
if( !Ready )
{
@ -61,30 +58,25 @@ public unsafe class CharacterUtility : IDisposable
// We store the default data of the resources so we can always restore them.
private void LoadDefaultResources( object _ )
{
var missingCount = 0;
if( Address == null )
{
return;
}
var anyMissing = false;
for( var i = 0; i < RelevantIndices.Length; ++i )
{
if( _defaultResources[ i ].Size == 0 )
var list = _lists[ i ];
if( !list.Ready )
{
var resource = Address->Resource( RelevantIndices[i] );
var data = resource->GetData();
if( data.Data != IntPtr.Zero && data.Length != 0 )
{
_defaultResources[ i ] = data;
}
else
{
++missingCount;
}
var resource = Address->Resource( RelevantIndices[ i ] );
var (data, length) = resource->GetData();
list.SetDefaultResource( data, length );
anyMissing |= !_lists[ i ].Ready;
}
}
if( missingCount == 0 )
if( !anyMissing )
{
Ready = true;
LoadingFinished.Invoke();
@ -92,51 +84,41 @@ public unsafe class CharacterUtility : IDisposable
}
}
// Set the data of one of the stored resources to a given pointer and length.
public bool SetResource( Structs.CharacterUtility.Index resourceIdx, IntPtr data, int length )
public void SetResource( Structs.CharacterUtility.Index resourceIdx, IntPtr data, int length )
{
if( !Ready )
{
PluginLog.Error( $"Can not set resource {resourceIdx}: CharacterUtility not ready yet." );
return false;
}
var resource = Address->Resource( resourceIdx );
var ret = resource->SetData( data, length );
PluginLog.Verbose( "Set resource {Idx} to 0x{NewData:X} ({NewLength} bytes).", resourceIdx, ( ulong )data, length );
return ret;
var idx = ReverseIndices[( int )resourceIdx];
var list = _lists[idx.Value];
list.SetResource( data, length );
}
// Reset the data of one of the stored resources to its default values.
public void ResetResource( Structs.CharacterUtility.Index resourceIdx )
{
if( !Ready )
{
PluginLog.Error( $"Can not reset {resourceIdx}: CharacterUtility not ready yet." );
return;
}
var idx = ReverseIndices[( int )resourceIdx];
var list = _lists[idx.Value];
list.ResetResource();
}
var (data, length) = DefaultResource( resourceIdx);
var resource = Address->Resource( resourceIdx );
PluginLog.Verbose( "Reset resource {Idx} to default at 0x{DefaultData:X} ({NewLength} bytes).", resourceIdx, ( ulong )data, length );
resource->SetData( data, length );
public List.MetaReverter TemporarilySetResource( Structs.CharacterUtility.Index resourceIdx, IntPtr data, int length )
{
var idx = ReverseIndices[ ( int )resourceIdx ];
var list = _lists[ idx.Value ];
return list.TemporarilySetResource( data, length );
}
public List.MetaReverter TemporarilyResetResource( Structs.CharacterUtility.Index resourceIdx )
{
var idx = ReverseIndices[ ( int )resourceIdx ];
var list = _lists[ idx.Value ];
return list.TemporarilyResetResource();
}
// Return all relevant resources to the default resource.
public void ResetAll()
{
if( !Ready )
foreach( var list in _lists )
{
PluginLog.Error( "Can not reset all resources: CharacterUtility not ready yet." );
return;
list.Dispose();
}
foreach( var idx in RelevantIndices )
{
ResetResource( idx );
}
PluginLog.Debug( "Reset all CharacterUtility resources to default." );
}
public void Dispose()

View file

@ -1,4 +1,3 @@
using Dalamud.Logging;
using FFXIVClientStructs.FFXIV.Client.System.Framework;
using FFXIVClientStructs.FFXIV.Component.GUI;
@ -22,7 +21,7 @@ public static unsafe class FontReloader
}
else
{
PluginLog.Error( "Could not reload fonts, function could not be found." );
Penumbra.Log.Error( "Could not reload fonts, function could not be found." );
}
}

View file

@ -2,7 +2,6 @@ using System;
using System.Collections.Generic;
using System.Linq;
using Dalamud.Hooking;
using Dalamud.Logging;
using Dalamud.Utility.Signatures;
using FFXIVClientStructs.FFXIV.Client.System.Resource;
using FFXIVClientStructs.FFXIV.Client.System.Resource.Handle;
@ -20,7 +19,7 @@ public unsafe partial class ResourceLoader
private readonly Hook< ResourceHandleDecRef > _decRefHook;
public delegate IntPtr ResourceHandleDestructor( ResourceHandle* handle );
[Signature( "48 89 5C 24 ?? 57 48 83 EC ?? 48 8D 05 ?? ?? ?? ?? 48 8B D9 48 89 01 B8",
DetourName = nameof( ResourceHandleDestructorDetour ) )]
public static Hook< ResourceHandleDestructor >? ResourceHandleDestructorHook;
@ -29,8 +28,7 @@ public unsafe partial class ResourceLoader
{
if( handle != null )
{
PluginLog.Information( "[ResourceLoader] Destructing Resource Handle {Path:l} at 0x{Address:X} (Refcount {Refcount}).",
handle->FileName, ( ulong )handle, handle->RefCount );
Penumbra.Log.Information( $"[ResourceLoader] Destructing Resource Handle {handle->FileName} at 0x{( ulong )handle:X} (Refcount {handle->RefCount}).");
}
return ResourceHandleDestructorHook!.Original( handle );
@ -95,7 +93,7 @@ public unsafe partial class ResourceLoader
}
catch( Exception e )
{
PluginLog.Error( e.ToString() );
Penumbra.Log.Error( e.ToString() );
}
}
@ -236,22 +234,22 @@ public unsafe partial class ResourceLoader
return _decRefHook.Original( handle );
}
PluginLog.Error( $"Caught decrease of Reference Counter for {handle->FileName} at 0x{( ulong )handle:X} below 0." );
Penumbra.Log.Error( $"Caught decrease of Reference Counter for {handle->FileName} at 0x{( ulong )handle:X} below 0." );
return 1;
}
// Logging functions for EnableFullLogging.
private static void LogPath( Utf8GamePath path, bool synchronous )
=> PluginLog.Information( $"[ResourceLoader] Requested {path} {( synchronous ? "synchronously." : "asynchronously." )}" );
=> Penumbra.Log.Information( $"[ResourceLoader] Requested {path} {( synchronous ? "synchronously." : "asynchronously." )}" );
private static void LogResource( Structs.ResourceHandle* handle, Utf8GamePath path, FullPath? manipulatedPath, ResolveData _ )
{
var pathString = manipulatedPath != null ? $"custom file {manipulatedPath} instead of {path}" : path.ToString();
PluginLog.Information( $"[ResourceLoader] Loaded {pathString} to 0x{( ulong )handle:X}. (Refcount {handle->RefCount})" );
Penumbra.Log.Information( $"[ResourceLoader] Loaded {pathString} to 0x{( ulong )handle:X}. (Refcount {handle->RefCount})" );
}
private static void LogLoadedFile( Utf8String path, bool success, bool custom )
=> PluginLog.Information( success
=> Penumbra.Log.Information( success
? $"[ResourceLoader] Loaded {path} from {( custom ? "local files" : "SqPack" )}"
: $"[ResourceLoader] Failed to load {path} from {( custom ? "local files" : "SqPack" )}." );
}

View file

@ -1,12 +1,9 @@
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Runtime.InteropServices;
using System.Threading;
using Dalamud.Hooking;
using Dalamud.Logging;
using Dalamud.Utility.Signatures;
using FFXIVClientStructs.FFXIV.Client.System.Resource;
using Penumbra.Collections;
@ -68,7 +65,7 @@ public unsafe partial class ResourceLoader
{
if( local != game )
{
PluginLog.Warning( "Hash function appears to have changed. Computed {Hash1:X8} vs Game {Hash2:X8} for {Path}.", local, game, path );
Penumbra.Log.Warning( $"Hash function appears to have changed. Computed {local:X8} vs Game {game:X8} for {path}." );
}
}
@ -79,7 +76,7 @@ public unsafe partial class ResourceLoader
{
if( !Utf8GamePath.FromPointer( path, out var gamePath ) )
{
PluginLog.Error( "Could not create GamePath from resource path." );
Penumbra.Log.Error( "Could not create GamePath from resource path." );
return CallOriginalHandler( isSync, resourceManager, categoryId, resourceType, resourceHash, path, pGetResParams, isUnk );
}
@ -161,7 +158,7 @@ public unsafe partial class ResourceLoader
if( fileDescriptor == null || fileDescriptor->ResourceHandle == null )
{
PluginLog.Error( "Failure to load file from SqPack: invalid File Descriptor." );
Penumbra.Log.Error( "Failure to load file from SqPack: invalid File Descriptor." );
return ReadSqPackHook.Original( resourceManager, fileDescriptor, priority, isSync );
}

View file

@ -1,6 +1,5 @@
using System;
using System.Text.RegularExpressions;
using Dalamud.Logging;
using Penumbra.GameData.ByteString;
namespace Penumbra.Interop.Loader;
@ -79,7 +78,7 @@ public class ResourceLogger : IDisposable
var path = Match( data.Path );
if( path != null )
{
PluginLog.Information( $"{path} was requested {( synchronous ? "synchronously." : "asynchronously." )}" );
Penumbra.Log.Information( $"{path} was requested {( synchronous ? "synchronously." : "asynchronously." )}" );
}
}

View file

@ -1,4 +1,3 @@
using Dalamud.Logging;
using Dalamud.Utility.Signatures;
namespace Penumbra.Interop;
@ -31,7 +30,7 @@ public unsafe class ResidentResourceManager
{
if( Address != null && Address->NumResources > 0 )
{
PluginLog.Debug( "Reload of resident resources triggered." );
Penumbra.Log.Debug( "Reload of resident resources triggered." );
UnloadPlayerResources.Invoke( Address );
LoadPlayerResources.Invoke( Address );
}

View file

@ -1,5 +1,4 @@
using System;
using System.Diagnostics.CodeAnalysis;
using Dalamud.Hooking;
using Dalamud.Utility.Signatures;
using Penumbra.Collections;

View file

@ -3,7 +3,6 @@ using Dalamud.Utility.Signatures;
using Penumbra.Collections;
using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using FFXIVClientStructs.FFXIV.Client.Game.Object;
using Penumbra.Api;
@ -55,7 +54,7 @@ public unsafe partial class PathResolver
public bool HandleDecalFile( ResourceType type, Utf8GamePath gamePath, out ResolveData resolveData )
{
if( type == ResourceType.Tex
if( type == ResourceType.Tex
&& LastCreatedCollection.Valid
&& gamePath.Path.Substring( "chara/common/texture/".Length ).StartsWith( 'd', 'e', 'c', 'a', 'l', '_', 'f', 'a', 'c', 'e' ) )
{
@ -124,7 +123,7 @@ public unsafe partial class PathResolver
// This map links DrawObjects directly to Actors (by ObjectTable index) and their collections.
// It contains any DrawObjects that correspond to a human actor, even those without specific collections.
private readonly Dictionary< IntPtr, (ResolveData, int) > _drawObjectToObject = new();
private readonly Dictionary< IntPtr, (ResolveData, int) > _drawObjectToObject = new();
private ResolveData _lastCreatedCollection = ResolveData.Invalid;
// Keep track of created DrawObjects that are CharacterBase,
@ -136,22 +135,37 @@ public unsafe partial class PathResolver
private IntPtr CharacterBaseCreateDetour( uint a, IntPtr b, IntPtr c, byte d )
{
using var cmp = MetaChanger.ChangeCmp( LastGameObject, out _lastCreatedCollection );
CharacterUtility.List.MetaReverter? cmp = null;
if( LastGameObject != null )
{
_lastCreatedCollection = IdentifyCollection( LastGameObject );
var modelPtr = &a;
CreatingCharacterBase?.Invoke( ( IntPtr )LastGameObject, _lastCreatedCollection!.ModCollection, ( IntPtr )modelPtr, b, c );
if( _lastCreatedCollection.ModCollection != Penumbra.CollectionManager.Default )
{
cmp = _lastCreatedCollection.ModCollection.TemporarilySetCmpFile();
}
try
{
CreatingCharacterBase?.Invoke( ( IntPtr )LastGameObject, _lastCreatedCollection!.ModCollection, ( IntPtr )modelPtr, b, c );
}
catch( Exception e )
{
Penumbra.Log.Error( $"Unknown Error during CreatingCharacterBase:\n{e}" );
}
}
var ret = _characterBaseCreateHook.Original( a, b, c, d );
if( LastGameObject != null )
using( cmp )
{
_drawObjectToObject[ ret ] = ( _lastCreatedCollection!, LastGameObject->ObjectIndex );
CreatedCharacterBase?.Invoke( ( IntPtr )LastGameObject, _lastCreatedCollection!.ModCollection, ret );
}
if( LastGameObject != null )
{
_drawObjectToObject[ ret ] = ( _lastCreatedCollection!, LastGameObject->ObjectIndex );
CreatedCharacterBase?.Invoke( ( IntPtr )LastGameObject, _lastCreatedCollection!.ModCollection, ret );
}
return ret;
return ret;
}
}

View file

@ -1,17 +1,14 @@
using System;
using System.Diagnostics.CodeAnalysis;
using Dalamud.Logging;
using Dalamud.Utility.Signatures;
using FFXIVClientStructs.FFXIV.Client.Game.Character;
using FFXIVClientStructs.FFXIV.Client.Game.Object;
using FFXIVClientStructs.FFXIV.Client.UI;
using FFXIVClientStructs.FFXIV.Client.UI.Agent;
using FFXIVClientStructs.FFXIV.Component.GUI;
using Lumina.Excel.GeneratedSheets;
using Penumbra.Collections;
using Penumbra.GameData.ByteString;
using Penumbra.GameData.Enums;
using Penumbra.GameData.Structs;
using CustomizeData = Penumbra.GameData.Structs.CustomizeData;
using ObjectKind = Dalamud.Game.ClientState.Objects.Enums.ObjectKind;
@ -41,10 +38,10 @@ public unsafe partial class PathResolver
}
var ui = ( AtkUnitBase* )addon;
var nodeId = Dalamud.GameData.GetExcelSheet< Title >()?.GetRow( *_inspectTitleId )?.IsPrefix == true ? 2u : 6u;
var nodeId = Dalamud.GameData.GetExcelSheet< Title >()?.GetRow( *_inspectTitleId )?.IsPrefix == true ? 7u : 6u;
var text = ( AtkTextNode* )ui->UldManager.SearchNodeById( nodeId );
return text != null ? text->NodeText.ToString() : null;
return text != null && text->AtkResNode.Type == NodeType.Text ? text->NodeText.ToString() : null;
}
// Obtain the name displayed in the Character Card from the agent.
@ -205,7 +202,7 @@ public unsafe partial class PathResolver
}
catch( Exception e )
{
PluginLog.Error( $"Error identifying collection:\n{e}" );
Penumbra.Log.Error( $"Error identifying collection:\n{e}" );
return Penumbra.CollectionManager.Default.ToResolveData( gameObject );
}
}
@ -245,7 +242,7 @@ public unsafe partial class PathResolver
collection = null;
// Check for the Yourself collection.
if( actor->ObjectIndex == 0
|| actor->ObjectIndex == ObjectReloader.GPosePlayerIdx && name.Length > 0
|| Cutscenes.GetParentIndex(actor->ObjectIndex) == 0
|| name == Dalamud.ClientState.LocalPlayer?.Name.ToString() )
{
collection = Penumbra.CollectionManager.ByType( CollectionType.Yourself );

View file

@ -1,8 +1,6 @@
using System;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using Dalamud.Hooking;
using Dalamud.Logging;
using Dalamud.Utility.Signatures;
using FFXIVClientStructs.FFXIV.Client.System.Resource;
using Penumbra.Collections;
@ -95,7 +93,7 @@ public unsafe partial class PathResolver
|| Penumbra.CollectionManager.ByName( name, out collection ) )
{
#if DEBUG
PluginLog.Verbose( "Using MtrlLoadHandler with collection {$Split:l} for path {$Path:l}.", name, path );
Penumbra.Log.Verbose( $"Using MtrlLoadHandler with collection {name} for path {path}." );
#endif
var objFromObjTable = Dalamud.Objects.FirstOrDefault( f => f.Name.TextValue == name );
@ -105,7 +103,7 @@ public unsafe partial class PathResolver
else
{
#if DEBUG
PluginLog.Verbose( "Using MtrlLoadHandler with no collection for path {$Path:l}.", path );
Penumbra.Log.Verbose( $"Using MtrlLoadHandler with no collection for path {path}." );
#endif
}

View file

@ -1,10 +1,9 @@
using System;
using Dalamud.Hooking;
using Dalamud.Utility.Signatures;
using FFXIVClientStructs.FFXIV.Client.Game.Object;
using FFXIVClientStructs.FFXIV.Client.Graphics.Scene;
using Penumbra.Collections;
using Penumbra.Meta.Manipulations;
using Penumbra.GameData.Enums;
using ObjectType = FFXIVClientStructs.FFXIV.Client.Graphics.Scene.ObjectType;
namespace Penumbra.Interop.Resolver;
@ -30,17 +29,13 @@ namespace Penumbra.Interop.Resolver;
// ChangeCustomize and RspSetupCharacter, which is hooked here.
// GMP Entries seem to be only used by "48 8B ?? 53 55 57 48 83 ?? ?? 48 8B", which has a DrawObject as its first parameter.
public unsafe partial class PathResolver
{
public unsafe class MetaState : IDisposable
public class MetaState : IDisposable
{
private readonly PathResolver _parent;
public MetaState( PathResolver parent, IntPtr* humanVTable )
public MetaState( IntPtr* humanVTable )
{
SignatureHelper.Initialise( this );
_parent = parent;
_onModelLoadCompleteHook = Hook< OnModelLoadCompleteDelegate >.FromAddress( humanVTable[ 58 ], OnModelLoadCompleteDetour );
}
@ -82,8 +77,10 @@ public unsafe partial class PathResolver
var collection = GetResolveData( drawObject );
if( collection.Valid )
{
using var eqp = MetaChanger.ChangeEqp( collection.ModCollection );
using var eqdp = MetaChanger.ChangeEqdp( collection.ModCollection );
var race = GetDrawObjectGenderRace( drawObject );
using var eqp = collection.ModCollection.TemporarilySetEqpFile();
using var eqdp1 = collection.ModCollection.TemporarilySetEqdpFile( race, false );
using var eqdp2 = collection.ModCollection.TemporarilySetEqdpFile( race, true );
_onModelLoadCompleteHook.Original.Invoke( drawObject );
}
else
@ -109,8 +106,10 @@ public unsafe partial class PathResolver
var collection = GetResolveData( drawObject );
if( collection.Valid )
{
using var eqp = MetaChanger.ChangeEqp( collection.ModCollection );
using var eqdp = MetaChanger.ChangeEqdp( collection.ModCollection );
var race = GetDrawObjectGenderRace( drawObject );
using var eqp = collection.ModCollection.TemporarilySetEqpFile();
using var eqdp1 = collection.ModCollection.TemporarilySetEqdpFile( race, false );
using var eqdp2 = collection.ModCollection.TemporarilySetEqdpFile( race, true );
_updateModelsHook.Original.Invoke( drawObject );
}
else
@ -119,6 +118,24 @@ public unsafe partial class PathResolver
}
}
private static GenderRace GetDrawObjectGenderRace( IntPtr drawObject )
{
var draw = ( DrawObject* )drawObject;
if( draw->Object.GetObjectType() == ObjectType.CharacterBase )
{
var c = ( CharacterBase* )drawObject;
if( c->GetModelType() == CharacterBase.ModelType.Human )
{
return GetHumanGenderRace( drawObject );
}
}
return GenderRace.Unknown;
}
public static GenderRace GetHumanGenderRace( IntPtr human )
=> ( GenderRace )( ( Human* )human )->RaceSexId;
[Signature( "40 ?? 48 83 ?? ?? ?? 81 ?? ?? ?? ?? ?? 48 8B ?? 74 ?? ?? 83 ?? ?? ?? ?? ?? ?? 74 ?? 4C",
DetourName = nameof( GetEqpIndirectDetour ) )]
private readonly Hook< OnModelLoadCompleteDelegate > _getEqpIndirectHook = null!;
@ -132,7 +149,8 @@ public unsafe partial class PathResolver
return;
}
using var eqp = MetaChanger.ChangeEqp( _parent, drawObject );
var resolveData = GetResolveData( drawObject );
using var eqp = resolveData.Valid ? resolveData.ModCollection.TemporarilySetEqpFile() : null;
_getEqpIndirectHook.Original( drawObject );
}
@ -146,7 +164,8 @@ public unsafe partial class PathResolver
private byte SetupVisorDetour( IntPtr drawObject, ushort modelId, byte visorState )
{
using var gmp = MetaChanger.ChangeGmp( _parent, drawObject );
var resolveData = GetResolveData( drawObject );
using var eqp = resolveData.Valid ? resolveData.ModCollection.TemporarilySetGmpFile() : null;
return _setupVisorHook.Original( drawObject, modelId, visorState );
}
@ -164,13 +183,14 @@ public unsafe partial class PathResolver
}
else
{
using var rsp = MetaChanger.ChangeCmp( _parent, drawObject );
var resolveData = GetResolveData( drawObject );
using var eqp = resolveData.Valid ? resolveData.ModCollection.TemporarilySetCmpFile() : null;
_rspSetupCharacterHook.Original( drawObject, unk2, unk3, unk4, unk5 );
}
}
// ChangeCustomize calls RspSetupCharacter, so skip the additional cmp change.
private bool _inChangeCustomize = false;
private bool _inChangeCustomize;
private delegate bool ChangeCustomizeDelegate( IntPtr human, IntPtr data, byte skipEquipment );
[Signature( "E8 ?? ?? ?? ?? 41 0F B6 C5 66 41 89 86", DetourName = nameof( ChangeCustomizeDetour ) )]
@ -179,154 +199,9 @@ public unsafe partial class PathResolver
private bool ChangeCustomizeDetour( IntPtr human, IntPtr data, byte skipEquipment )
{
_inChangeCustomize = true;
using var rsp = MetaChanger.ChangeCmp( _parent, human );
var resolveData = GetResolveData( human );
using var eqp = resolveData.Valid ? resolveData.ModCollection.TemporarilySetEqpFile() : null;
return _changeCustomize.Original( human, data, skipEquipment );
}
}
// Small helper to handle setting metadata and reverting it at the end of the function.
// Since eqp and eqdp may be called multiple times in a row, we need to count them,
// so that we do not reset the files too early.
private readonly struct MetaChanger : IDisposable
{
private static int _eqpCounter;
private static int _eqdpCounter;
private readonly MetaManipulation.Type _type;
private MetaChanger( MetaManipulation.Type type )
{
_type = type;
if( type == MetaManipulation.Type.Eqp )
{
++_eqpCounter;
}
else if( type == MetaManipulation.Type.Eqdp )
{
++_eqdpCounter;
}
}
public static MetaChanger ChangeEqp( ModCollection collection )
{
collection.SetEqpFiles();
return new MetaChanger( MetaManipulation.Type.Eqp );
}
public static MetaChanger ChangeEqp( PathResolver _, IntPtr drawObject )
{
var resolveData = GetResolveData( drawObject );
if( resolveData.Valid )
{
return ChangeEqp( resolveData.ModCollection );
}
return new MetaChanger( MetaManipulation.Type.Unknown );
}
// We only need to change anything if it is actually equipment here.
public static MetaChanger ChangeEqdp( PathResolver _, IntPtr drawObject, uint modelType )
{
if( modelType < 10 )
{
var collection = GetResolveData( drawObject );
if( collection.Valid )
{
return ChangeEqdp( collection.ModCollection );
}
}
return new MetaChanger( MetaManipulation.Type.Unknown );
}
public static MetaChanger ChangeEqdp( ModCollection collection )
{
collection.SetEqdpFiles();
return new MetaChanger( MetaManipulation.Type.Eqdp );
}
public static MetaChanger ChangeGmp( PathResolver resolver, IntPtr drawObject )
{
var resolveData = GetResolveData( drawObject );
if( resolveData.Valid )
{
resolveData.ModCollection.SetGmpFiles();
return new MetaChanger( MetaManipulation.Type.Gmp );
}
return new MetaChanger( MetaManipulation.Type.Unknown );
}
public static MetaChanger ChangeEst( PathResolver resolver, IntPtr drawObject )
{
var resolveData = GetResolveData( drawObject );
if( resolveData.Valid )
{
resolveData.ModCollection.SetEstFiles();
return new MetaChanger( MetaManipulation.Type.Est );
}
return new MetaChanger( MetaManipulation.Type.Unknown );
}
public static MetaChanger ChangeCmp( GameObject* gameObject, out ResolveData resolveData )
{
if( gameObject != null )
{
resolveData = IdentifyCollection( gameObject );
if( resolveData.ModCollection != Penumbra.CollectionManager.Default && resolveData.ModCollection.HasCache )
{
resolveData.ModCollection.SetCmpFiles();
return new MetaChanger( MetaManipulation.Type.Rsp );
}
}
else
{
resolveData = ResolveData.Invalid;
}
return new MetaChanger( MetaManipulation.Type.Unknown );
}
public static MetaChanger ChangeCmp( PathResolver resolver, IntPtr drawObject )
{
var resolveData = GetResolveData( drawObject );
if( resolveData.Valid )
{
resolveData.ModCollection.SetCmpFiles();
return new MetaChanger( MetaManipulation.Type.Rsp );
}
return new MetaChanger( MetaManipulation.Type.Unknown );
}
public void Dispose()
{
switch( _type )
{
case MetaManipulation.Type.Eqdp:
if( --_eqdpCounter == 0 )
{
Penumbra.CollectionManager.Default.SetEqdpFiles();
}
break;
case MetaManipulation.Type.Eqp:
if( --_eqpCounter == 0 )
{
Penumbra.CollectionManager.Default.SetEqpFiles();
}
break;
case MetaManipulation.Type.Est:
Penumbra.CollectionManager.Default.SetEstFiles();
break;
case MetaManipulation.Type.Gmp:
Penumbra.CollectionManager.Default.SetGmpFiles();
break;
case MetaManipulation.Type.Rsp:
Penumbra.CollectionManager.Default.SetCmpFiles();
break;
}
}
}
}

View file

@ -1,7 +1,6 @@
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Runtime.CompilerServices;
using Dalamud.Utility.Signatures;
using Penumbra.Collections;

View file

@ -2,7 +2,9 @@ using System;
using System.Runtime.CompilerServices;
using Dalamud.Hooking;
using FFXIVClientStructs.FFXIV.Client.Graphics.Scene;
using Penumbra.Collections;
using OtterGui.Classes;
using Penumbra.GameData.Enums;
using Penumbra.Meta.Manipulations;
namespace Penumbra.Interop.Resolver;
@ -141,34 +143,64 @@ public partial class PathResolver
private IntPtr ResolveMdlHuman( IntPtr drawObject, IntPtr path, IntPtr unk3, uint modelType )
{
using var eqdp = MetaChanger.ChangeEqdp( _parent, drawObject, modelType );
CharacterUtility.List.MetaReverter? Get()
{
if( modelType > 9 )
{
return null;
}
var race = MetaState.GetHumanGenderRace( drawObject );
if( race == GenderRace.Unknown )
{
return null;
}
var data = GetResolveData( drawObject );
return !data.Valid ? null : data.ModCollection.TemporarilySetEqdpFile( race, modelType > 4 );
}
using var eqdp = Get();
return ResolvePath( drawObject, _resolveMdlPathHook.Original( drawObject, path, unk3, modelType ) );
}
private IntPtr ResolvePapHuman( IntPtr drawObject, IntPtr path, IntPtr unk3, uint unk4, ulong unk5 )
{
using var est = MetaChanger.ChangeEst( _parent, drawObject );
using var est = GetEstChanges( drawObject );
return ResolvePath( drawObject, _resolvePapPathHook.Original( drawObject, path, unk3, unk4, unk5 ) );
}
private IntPtr ResolvePhybHuman( IntPtr drawObject, IntPtr path, IntPtr unk3, uint unk4 )
{
using var est = MetaChanger.ChangeEst( _parent, drawObject );
using var est = GetEstChanges( drawObject );
return ResolvePath( drawObject, _resolvePhybPathHook.Original( drawObject, path, unk3, unk4 ) );
}
private IntPtr ResolveSklbHuman( IntPtr drawObject, IntPtr path, IntPtr unk3, uint unk4 )
{
using var est = MetaChanger.ChangeEst( _parent, drawObject );
using var est = GetEstChanges( drawObject );
return ResolvePath( drawObject, _resolveSklbPathHook.Original( drawObject, path, unk3, unk4 ) );
}
private IntPtr ResolveSkpHuman( IntPtr drawObject, IntPtr path, IntPtr unk3, uint unk4 )
{
using var est = MetaChanger.ChangeEst( _parent, drawObject );
using var est = GetEstChanges( drawObject );
return ResolvePath( drawObject, _resolveSkpPathHook.Original( drawObject, path, unk3, unk4 ) );
}
private DisposableContainer GetEstChanges( IntPtr drawObject )
{
var data = GetResolveData( drawObject );
if( !data.Valid )
{
return DisposableContainer.Empty;
}
return new DisposableContainer( data.ModCollection.TemporarilySetEstFile( EstManipulation.EstType.Face ),
data.ModCollection.TemporarilySetEstFile( EstManipulation.EstType.Body ),
data.ModCollection.TemporarilySetEstFile( EstManipulation.EstType.Hair ),
data.ModCollection.TemporarilySetEstFile( EstManipulation.EstType.Head ) );
}
private IntPtr ResolveDecalWeapon( IntPtr drawObject, IntPtr path, IntPtr unk3, uint unk4 )
=> ResolveWeaponPath( drawObject, _resolveDecalPathHook.Original( drawObject, path, unk3, unk4 ) );
@ -227,9 +259,10 @@ public partial class PathResolver
// Implementation
[MethodImpl( MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization )]
private IntPtr ResolvePath( IntPtr drawObject, IntPtr path )
=> _parent._paths.ResolvePath( (IntPtr?)FindParent( drawObject, out _) ?? IntPtr.Zero, FindParent( drawObject, out var collection ) == null
? Penumbra.CollectionManager.Default
: collection.ModCollection, path );
=> _parent._paths.ResolvePath( ( IntPtr? )FindParent( drawObject, out _ ) ?? IntPtr.Zero,
FindParent( drawObject, out var collection ) == null
? Penumbra.CollectionManager.Default
: collection.ModCollection, path );
// Weapons have the characters DrawObject as a parent,
// but that may not be set yet when creating a new object, so we have to do the same detour
@ -240,18 +273,18 @@ public partial class PathResolver
var parent = FindParent( drawObject, out var collection );
if( parent != null )
{
return _parent._paths.ResolvePath( (IntPtr)parent, collection.ModCollection, path );
return _parent._paths.ResolvePath( ( IntPtr )parent, collection.ModCollection, path );
}
var parentObject = ( IntPtr )( ( DrawObject* )drawObject )->Object.ParentObject;
var parentCollection = DrawObjects.CheckParentDrawObject( drawObject, parentObject );
if( parentCollection.Valid )
{
return _parent._paths.ResolvePath( (IntPtr)FindParent(parentObject, out _), parentCollection.ModCollection, path );
return _parent._paths.ResolvePath( ( IntPtr )FindParent( parentObject, out _ ), parentCollection.ModCollection, path );
}
parent = FindParent( parentObject, out collection );
return _parent._paths.ResolvePath( (IntPtr?)parent ?? IntPtr.Zero, parent == null
return _parent._paths.ResolvePath( ( IntPtr? )parent ?? IntPtr.Zero, parent == null
? Penumbra.CollectionManager.Default
: collection.ModCollection, path );
}

View file

@ -1,6 +1,5 @@
using System;
using System.Collections.Generic;
using Dalamud.Logging;
using Dalamud.Utility.Signatures;
using FFXIVClientStructs.FFXIV.Client.Game.Object;
using FFXIVClientStructs.FFXIV.Client.Graphics.Scene;
@ -35,7 +34,7 @@ public partial class PathResolver : IDisposable
_loader = loader;
_animations = new AnimationState( DrawObjects );
_paths = new PathState( this );
_meta = new MetaState( this, _paths.HumanVTable );
_meta = new MetaState( _paths.HumanVTable );
_materials = new MaterialState( _paths );
}
@ -84,7 +83,7 @@ public partial class PathResolver : IDisposable
_materials.Enable();
_loader.ResolvePathCustomization += CharacterResolver;
PluginLog.Debug( "Character Path Resolver enabled." );
Penumbra.Log.Debug( "Character Path Resolver enabled." );
}
public void Disable()
@ -103,7 +102,7 @@ public partial class PathResolver : IDisposable
_materials.Disable();
_loader.ResolvePathCustomization -= CharacterResolver;
PluginLog.Debug( "Character Path Resolver disabled." );
Penumbra.Log.Debug( "Character Path Resolver disabled." );
}
public void Dispose()

View file

@ -2,7 +2,6 @@ using System;
using System.Runtime.InteropServices;
using FFXIVClientStructs.FFXIV.Client.System.Resource;
using Penumbra.GameData.Enums;
using Penumbra.Interop.Resolver;
namespace Penumbra.Interop.Structs;

View file

@ -2,7 +2,6 @@ using System;
using System.Collections;
using System.Collections.Generic;
using System.Numerics;
using System.Runtime.CompilerServices;
using Penumbra.GameData.Structs;
using Penumbra.GameData.Util;
using Penumbra.Interop.Structs;

View file

@ -1,6 +1,5 @@
using System;
using System.Numerics;
using Dalamud.Logging;
using Newtonsoft.Json;
using Penumbra.GameData.ByteString;
using Penumbra.GameData.Enums;
@ -125,7 +124,7 @@ public unsafe class ImcFile : MetaBaseFile
if( ActualLength > Length )
{
var newLength = ( ( ( ActualLength - 1 ) >> 7 ) + 1 ) << 7;
PluginLog.Verbose( "Resized IMC {Path} from {Length} to {NewLength}.", Path, Length, newLength );
Penumbra.Log.Verbose( $"Resized IMC {Path} from {Length} to {newLength}." );
ResizeResources( newLength );
}
@ -135,7 +134,7 @@ public unsafe class ImcFile : MetaBaseFile
Functions.MemCpyUnchecked( defaultPtr + i * NumParts, defaultPtr, NumParts * sizeof( ImcEntry ) );
}
PluginLog.Verbose( "Expanded IMC {Path} from {Count} to {NewCount} variants.", Path, oldCount, numVariants );
Penumbra.Log.Verbose( $"Expanded IMC {Path} from {oldCount} to {numVariants} variants." );
return true;
}
@ -151,7 +150,7 @@ public unsafe class ImcFile : MetaBaseFile
var variantPtr = VariantPtr( Data, partIdx, variantIdx );
if( variantPtr == null )
{
PluginLog.Error( "Error during expansion of imc file." );
Penumbra.Log.Error( "Error during expansion of imc file." );
return false;
}
@ -222,7 +221,7 @@ public unsafe class ImcFile : MetaBaseFile
var newData = Penumbra.MetaFileManager.AllocateDefaultMemory( ActualLength, 8 );
if( newData == null )
{
PluginLog.Error("Could not replace loaded IMC data at 0x{Data:X}, allocation failed." );
Penumbra.Log.Error($"Could not replace loaded IMC data at 0x{(ulong) resource:X}, allocation failed." );
return;
}
Functions.MemCpyUnchecked( newData, Data, ActualLength );

View file

@ -18,6 +18,9 @@ public partial class MetaManager
public static void ResetCmpFiles()
=> SetFile( null, CharacterUtility.Index.HumanCmp );
public Interop.CharacterUtility.List.MetaReverter TemporarilySetCmpFile()
=> TemporarilySetFile( _cmpFile, CharacterUtility.Index.HumanCmp );
public void ResetCmp()
{
if( _cmpFile == null )

View file

@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
using OtterGui;
using OtterGui.Filesystem;
using Penumbra.GameData.Enums;
using Penumbra.Interop.Structs;
@ -23,6 +24,21 @@ public partial class MetaManager
}
}
public Interop.CharacterUtility.List.MetaReverter? TemporarilySetEqdpFile( GenderRace genderRace, bool accessory )
{
var idx = CharacterUtility.EqdpIdx( genderRace, accessory );
if( ( int )idx != -1 )
{
var i = CharacterUtility.EqdpIndices.IndexOf( idx );
if( i != -1 )
{
return TemporarilySetFile( _eqdpFiles[ i ], idx );
}
}
return null;
}
public static void ResetEqdpFiles()
{
foreach( var idx in CharacterUtility.EqdpIndices )
@ -33,7 +49,7 @@ public partial class MetaManager
public void ResetEqdp()
{
foreach( var file in _eqdpFiles.OfType<ExpandedEqdpFile>() )
foreach( var file in _eqdpFiles.OfType< ExpandedEqdpFile >() )
{
var relevant = Interop.CharacterUtility.RelevantIndices[ file.Index.Value ];
file.Reset( _eqdpManipulations.Where( m => m.FileIndex() == relevant ).Select( m => ( int )m.SetId ) );

View file

@ -18,6 +18,9 @@ public partial class MetaManager
public static void ResetEqpFiles()
=> SetFile( null, CharacterUtility.Index.Eqp );
public Interop.CharacterUtility.List.MetaReverter TemporarilySetEqpFile()
=> TemporarilySetFile( _eqpFile, CharacterUtility.Index.Eqp );
public void ResetEqp()
{
if( _eqpFile == null )

View file

@ -33,6 +33,20 @@ public partial class MetaManager
SetFile( null, CharacterUtility.Index.HeadEst );
}
public Interop.CharacterUtility.List.MetaReverter? TemporarilySetEstFile(EstManipulation.EstType type)
{
var (file, idx) = type switch
{
EstManipulation.EstType.Face => ( _estFaceFile, CharacterUtility.Index.FaceEst ),
EstManipulation.EstType.Hair => ( _estHairFile, CharacterUtility.Index.HairEst ),
EstManipulation.EstType.Body => ( _estBodyFile, CharacterUtility.Index.BodyEst ),
EstManipulation.EstType.Head => ( _estHeadFile, CharacterUtility.Index.HeadEst ),
_ => ( null, 0 ),
};
return idx != 0 ? TemporarilySetFile( file, idx ) : null;
}
public void ResetEst()
{
_estFaceFile?.Reset();

View file

@ -1,12 +1,9 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using OtterGui.Filesystem;
using Penumbra.Interop.Structs;
using Penumbra.Meta.Files;
using Penumbra.Meta.Manipulations;
using Penumbra.Mods;
namespace Penumbra.Meta.Manager;
@ -21,6 +18,9 @@ public partial class MetaManager
public static void ResetGmpFiles()
=> SetFile( null, CharacterUtility.Index.Gmp );
public Interop.CharacterUtility.List.MetaReverter TemporarilySetGmpFile()
=> TemporarilySetFile( _gmpFile, CharacterUtility.Index.Gmp );
public void ResetGmp()
{
if( _gmpFile == null )

View file

@ -1,10 +1,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Dalamud.Logging;
using FFXIVClientStructs.FFXIV.Client.System.Resource;
using OtterGui.Filesystem;
using Penumbra.Collections;
using Penumbra.GameData.ByteString;
using Penumbra.GameData.Enums;
using Penumbra.Interop.Structs;
@ -81,7 +78,7 @@ public partial class MetaManager
catch( Exception e )
{
++Penumbra.ImcExceptions;
PluginLog.Error( $"Could not apply IMC Manipulation:\n{e}" );
Penumbra.Log.Error( $"Could not apply IMC Manipulation:\n{e}" );
return false;
}
}
@ -156,7 +153,7 @@ public partial class MetaManager
return false;
}
PluginLog.Verbose( "Using ImcLoadHandler for path {$Path:l}.", path );
Penumbra.Log.Verbose( $"Using ImcLoadHandler for path {path}." );
ret = Penumbra.ResourceLoader.ReadSqPackHook.Original( resourceManager, fileDescriptor, priority, isSync );
var lastUnderscore = split.LastIndexOf( ( byte )'_' );
@ -166,8 +163,7 @@ public partial class MetaManager
&& collection.HasCache
&& collection.MetaCache!._imcFiles.TryGetValue( Utf8GamePath.FromSpan( path.Span, out var p ) ? p : Utf8GamePath.Empty, out var file ) )
{
PluginLog.Debug( "Loaded {GamePath:l} from file and replaced with IMC from collection {Collection:l}.", path,
collection.AnonymizedName );
Penumbra.Log.Debug( $"Loaded {path} from file and replaced with IMC from collection {collection.AnonymizedName}." );
file.Replace( fileDescriptor->ResourceHandle );
}

View file

@ -4,7 +4,6 @@ using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Runtime.CompilerServices;
using Dalamud.Logging;
using Penumbra.Collections;
using Penumbra.Interop.Structs;
using Penumbra.Meta.Files;
@ -165,7 +164,7 @@ public partial class MetaManager : IDisposable, IEnumerable< KeyValuePair< MetaM
}
Penumbra.CharacterUtility.LoadingFinished -= ApplyStoredManipulations;
PluginLog.Debug( "{Collection}: Loaded {Num} delayed meta manipulations.", _collection.Name, loaded );
Penumbra.Log.Debug( $"{_collection.AnonymizedName}: Loaded {loaded} delayed meta manipulations." );
}
[MethodImpl( MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization )]
@ -180,4 +179,10 @@ public partial class MetaManager : IDisposable, IEnumerable< KeyValuePair< MetaM
Penumbra.CharacterUtility.SetResource( index, ( IntPtr )file.Data, file.Length );
}
}
[MethodImpl( MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization )]
private static unsafe Interop.CharacterUtility.List.MetaReverter TemporarilySetFile( MetaBaseFile? file, CharacterUtility.Index index )
=> file == null
? Penumbra.CharacterUtility.TemporarilyResetResource( index )
: Penumbra.CharacterUtility.TemporarilySetResource( index, ( IntPtr )file.Data, file.Length );
}

View file

@ -1,4 +1,3 @@
using System;
using System.Runtime.InteropServices;
using Penumbra.GameData.Structs;
using Penumbra.Interop.Structs;

View file

@ -5,7 +5,6 @@ using System.IO;
using System.Linq;
using System.Security.Cryptography;
using System.Threading.Tasks;
using Dalamud.Logging;
using Penumbra.GameData.ByteString;
namespace Penumbra.Mods;
@ -87,7 +86,7 @@ public partial class Mod
}
catch( Exception e )
{
PluginLog.Error( $"[DeleteDuplicates] Could not delete duplicate {duplicate.FullName} of {remaining.FullName}:\n{e}" );
Penumbra.Log.Error( $"[DeleteDuplicates] Could not delete duplicate {duplicate.FullName} of {remaining.FullName}:\n{e}" );
}
}
@ -100,7 +99,7 @@ public partial class Mod
}
changes = true;
PluginLog.Debug( "[DeleteDuplicates] Changing {GamePath:l} for {Mod:d}\n : {Old:l}\n -> {New:l}", key, _mod.Name, from, to );
Penumbra.Log.Debug( $"[DeleteDuplicates] Changing {key} for {_mod.Name}\n : {from}\n -> {to}" );
return to;
}
@ -263,7 +262,7 @@ public partial class Mod
}
catch( Exception e )
{
PluginLog.Error( $"Could not delete empty directories in {baseDir.FullName}:\n{e}" );
Penumbra.Log.Error( $"Could not delete empty directories in {baseDir.FullName}:\n{e}" );
}
}
@ -282,7 +281,7 @@ public partial class Mod
}
catch( Exception e )
{
PluginLog.Warning( $"Could not deduplicate mod {modDirectory.Name}:\n{e}" );
Penumbra.Log.Warning( $"Could not deduplicate mod {modDirectory.Name}:\n{e}" );
}
}
}

View file

@ -3,7 +3,6 @@ using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.IO;
using System.Linq;
using Dalamud.Logging;
using Penumbra.GameData.ByteString;
namespace Penumbra.Mods;
@ -114,7 +113,7 @@ public partial class Mod
return true;
}
PluginLog.Debug( "[RemoveMissingPaths] Removing {GamePath} -> {File} from {Mod}.", key, file, _mod.Name );
Penumbra.Log.Debug( $"[RemoveMissingPaths] Removing {key} -> {file} from {_mod.Name}." );
return false;
}
@ -257,12 +256,12 @@ public partial class Mod
try
{
File.Delete( file.File.FullName );
PluginLog.Debug( "[DeleteFiles] Deleted {File} from {Mod}.", file.File.FullName, _mod.Name );
Penumbra.Log.Debug( $"[DeleteFiles] Deleted {file.File.FullName} from {_mod.Name}." );
++deletions;
}
catch( Exception e )
{
PluginLog.Error( $"[DeleteFiles] Could not delete {file.File.FullName} from {_mod.Name}:\n{e}" );
Penumbra.Log.Error( $"[DeleteFiles] Could not delete {file.File.FullName} from {_mod.Name}:\n{e}" );
}
}

View file

@ -1,6 +1,3 @@
using System.Collections.Generic;
using Penumbra.GameData.ByteString;
namespace Penumbra.Mods;
public partial class Mod

View file

@ -4,7 +4,6 @@ using System.IO;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using Dalamud.Logging;
using OtterGui;
using Penumbra.GameData.ByteString;
using Penumbra.GameData.Enums;
@ -90,7 +89,7 @@ public partial class Mod
}
catch( Exception e )
{
PluginLog.Error( $"Unexpected error scanning {_mod.Name}'s {file.File.FullName} for materials:\n{e}" );
Penumbra.Log.Error( $"Unexpected error scanning {_mod.Name}'s {file.File.FullName} for materials:\n{e}" );
}
}
}
@ -152,7 +151,7 @@ public partial class Mod
catch( Exception e )
{
Restore();
PluginLog.Error( $"Could not write manipulated .mdl file {Path.FullName}:\n{e}" );
Penumbra.Log.Error( $"Could not write manipulated .mdl file {Path.FullName}:\n{e}" );
}
}

View file

@ -2,7 +2,6 @@ using System;
using System.IO;
using System.IO.Compression;
using System.Threading.Tasks;
using Dalamud.Logging;
namespace Penumbra.Mods;
@ -18,10 +17,39 @@ public class ModBackup
public ModBackup( Mod mod )
{
_mod = mod;
Name = mod.ModPath + ".zip";
Name = _mod.ModPath + ".pmp";
Exists = File.Exists( Name );
}
// Migrate file extensions.
public static void MigrateZipToPmp(Mod.Manager manager)
{
foreach( var mod in manager )
{
var pmpName = mod.ModPath + ".pmp";
var zipName = mod.ModPath + ".zip";
if( File.Exists( zipName ) )
{
try
{
if( !File.Exists( pmpName ) )
{
File.Move( zipName, pmpName );
}
else
{
File.Delete( zipName );
}
Penumbra.Log.Information( $"Migrated mod backup from {zipName} to {pmpName}." );
}
catch( Exception e )
{
Penumbra.Log.Warning( $"Could not migrate mod backup of {mod.ModPath} from .pmp to .zip:\n{e}" );
}
}
}
}
// Create a backup zip without blocking the main thread.
public async void CreateAsync()
{
@ -43,11 +71,11 @@ public class ModBackup
{
Delete();
ZipFile.CreateFromDirectory( _mod.ModPath.FullName, Name, CompressionLevel.Optimal, false );
PluginLog.Debug( "Created backup file {backupName} from {modDirectory}.", Name, _mod.ModPath.FullName );
Penumbra.Log.Debug( $"Created backup file {Name} from {_mod.ModPath.FullName}.");
}
catch( Exception e )
{
PluginLog.Error( $"Could not backup mod {_mod.Name} to \"{Name}\":\n{e}" );
Penumbra.Log.Error( $"Could not backup mod {_mod.Name} to \"{Name}\":\n{e}" );
}
}
@ -62,11 +90,11 @@ public class ModBackup
try
{
File.Delete( Name );
PluginLog.Debug( "Deleted backup file {backupName}.", Name );
Penumbra.Log.Debug( $"Deleted backup file {Name}." );
}
catch( Exception e )
{
PluginLog.Error( $"Could not delete file \"{Name}\":\n{e}" );
Penumbra.Log.Error( $"Could not delete file \"{Name}\":\n{e}" );
}
}
@ -79,16 +107,16 @@ public class ModBackup
if( Directory.Exists( _mod.ModPath.FullName ) )
{
Directory.Delete( _mod.ModPath.FullName, true );
PluginLog.Debug( "Deleted mod folder {modFolder}.", _mod.ModPath.FullName );
Penumbra.Log.Debug( $"Deleted mod folder {_mod.ModPath.FullName}." );
}
ZipFile.ExtractToDirectory( Name, _mod.ModPath.FullName );
PluginLog.Debug( "Extracted backup file {backupName} to {modName}.", Name, _mod.ModPath.FullName );
Penumbra.Log.Debug( $"Extracted backup file {Name} to {_mod.ModPath.FullName}.");
Penumbra.ModManager.ReloadMod( _mod.Index );
}
catch( Exception e )
{
PluginLog.Error( $"Could not restore {_mod.Name} from backup \"{Name}\":\n{e}" );
Penumbra.Log.Error( $"Could not restore {_mod.Name} from backup \"{Name}\":\n{e}" );
}
}
}

View file

@ -274,7 +274,7 @@ public partial class Mod
// }
// catch( Exception e )
// {
// PluginLog.Error( $"Could not split Mod:\n{e}" );
// Penumbra.Log.Error( $"Could not split Mod:\n{e}" );
// }
// }
//
@ -394,7 +394,7 @@ public partial class Mod
// }
// }
//
// PluginLog.Information( $"File {relName1} and {relName2} are identical. Deleting the second." );
// Penumbra.Log.Information( $"File {relName1} and {relName2} are identical. Deleting the second." );
// f2.Delete();
// }
//
@ -498,7 +498,7 @@ public partial class Mod
// }
// catch( Exception e )
// {
// PluginLog.Error( $"Could not move file from {oldRelPath} to {newRelPath}:\n{e}" );
// Penumbra.Log.Error( $"Could not move file from {oldRelPath} to {newRelPath}:\n{e}" );
// return false;
// }
//

View file

@ -1,7 +1,6 @@
using System;
using System.IO;
using System.Linq;
using Dalamud.Logging;
namespace Penumbra.Mods;
@ -34,7 +33,7 @@ public partial class Mod
}
catch( Exception e )
{
PluginLog.Error( $"Could not delete empty directory {dir!.FullName} to move {mod.Name} to it:\n{e}" );
Penumbra.Log.Error( $"Could not delete empty directory {dir!.FullName} to move {mod.Name} to it:\n{e}" );
return;
}
@ -55,7 +54,7 @@ public partial class Mod
}
catch( Exception e )
{
PluginLog.Error( $"Could not move {mod.Name} from {oldDirectory.Name} to {dir!.Name}:\n{e}" );
Penumbra.Log.Error( $"Could not move {mod.Name} from {oldDirectory.Name} to {dir!.Name}:\n{e}" );
return;
}
@ -63,7 +62,7 @@ public partial class Mod
mod.ModPath = dir;
if( !mod.Reload( out var metaChange ) )
{
PluginLog.Error( $"Error reloading moved mod {mod.Name}." );
Penumbra.Log.Error( $"Error reloading moved mod {mod.Name}." );
return;
}
@ -81,10 +80,10 @@ public partial class Mod
var mod = this[ idx ];
var oldName = mod.Name;
ModPathChanged.Invoke(ModPathChangeType.StartingReload, mod, mod.ModPath, mod.ModPath );
ModPathChanged.Invoke( ModPathChangeType.StartingReload, mod, mod.ModPath, mod.ModPath );
if( !mod.Reload( out var metaChange ) )
{
PluginLog.Warning( mod.Name.Length == 0
Penumbra.Log.Warning( mod.Name.Length == 0
? $"Reloading mod {oldName} has failed, new name is empty. Deleting instead."
: $"Reloading mod {oldName} failed, {mod.ModPath.FullName} does not exist anymore or it ha. Deleting instead." );
@ -110,11 +109,11 @@ public partial class Mod
try
{
Directory.Delete( mod.ModPath.FullName, true );
PluginLog.Debug( "Deleted directory {Directory:l} for {Name:l}.", mod.ModPath.FullName, mod.Name );
Penumbra.Log.Debug( $"Deleted directory {mod.ModPath.FullName} for {mod.Name}.");
}
catch( Exception e )
{
PluginLog.Error( $"Could not delete the mod {mod.ModPath.Name}:\n{e}" );
Penumbra.Log.Error( $"Could not delete the mod {mod.ModPath.Name}:\n{e}" );
}
}
@ -125,7 +124,7 @@ public partial class Mod
--remainingMod.Index;
}
PluginLog.Debug( "Deleted mod {Name:l}.", mod.Name );
Penumbra.Log.Debug( $"Deleted mod {mod.Name}." );
}
// Load a new mod and add it to the manager if successful.
@ -145,7 +144,7 @@ public partial class Mod
mod.Index = _mods.Count;
_mods.Add( mod );
ModPathChanged.Invoke( ModPathChangeType.Added, mod, null, mod.ModPath );
PluginLog.Debug( "Added new mod {Name:l} from {Directory:l}.", mod.Name, modFolder.FullName );
Penumbra.Log.Debug( $"Added new mod {mod.Name} from {modFolder.FullName}." );
}
public enum NewDirectoryState

View file

@ -1,7 +1,6 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Dalamud.Logging;
using OtterGui;
using OtterGui.Filesystem;
using Penumbra.GameData.ByteString;
@ -88,7 +87,7 @@ public sealed partial class Mod
{
foreach( var (group, groupIdx) in mod._groups.WithIndex().Skip( fromGroup ) )
{
foreach( var (o, optionIdx) in group.OfType<SubMod>().WithIndex() )
foreach( var (o, optionIdx) in group.OfType< SubMod >().WithIndex() )
{
o.SetPosition( groupIdx, optionIdx );
}
@ -176,18 +175,19 @@ public sealed partial class Mod
public void AddOption( Mod mod, int groupIdx, string newName )
{
var group = mod._groups[groupIdx];
var group = mod._groups[ groupIdx ];
var subMod = new SubMod( mod ) { Name = newName };
subMod.SetPosition( groupIdx, group.Count );
switch( group )
{
case SingleModGroup s:
s.OptionData.Add( new SubMod(mod) { Name = newName } );
s.OptionData.Add( subMod );
break;
case MultiModGroup m:
m.PrioritizedOptions.Add( ( new SubMod(mod) { Name = newName }, 0 ) );
m.PrioritizedOptions.Add( ( subMod, 0 ) );
break;
}
group.UpdatePositions( group.Count - 1 );
ModOptionChanged.Invoke( ModOptionChangeType.OptionAdded, mod, groupIdx, group.Count - 1, -1 );
}
@ -201,12 +201,14 @@ public sealed partial class Mod
var group = mod._groups[ groupIdx ];
if( group.Count > 63 )
{
PluginLog.Error(
Penumbra.Log.Error(
$"Could not add option {option.Name} to {group.Name} for mod {mod.Name}, "
+ "since only up to 64 options are supported in one group." );
return;
}
o.SetPosition( groupIdx, group.Count );
switch( group )
{
case SingleModGroup s:
@ -216,13 +218,13 @@ public sealed partial class Mod
m.PrioritizedOptions.Add( ( o, priority ) );
break;
}
group.UpdatePositions( group.Count - 1 );
ModOptionChanged.Invoke( ModOptionChangeType.OptionAdded, mod, groupIdx, group.Count - 1, -1 );
}
public void DeleteOption( Mod mod, int groupIdx, int optionIdx )
{
var group = mod._groups[groupIdx];
var group = mod._groups[ groupIdx ];
ModOptionChanged.Invoke( ModOptionChangeType.PrepareChange, mod, groupIdx, optionIdx, -1 );
switch( group )
{
@ -234,6 +236,7 @@ public sealed partial class Mod
m.PrioritizedOptions.RemoveAt( optionIdx );
break;
}
group.UpdatePositions( optionIdx );
ModOptionChanged.Invoke( ModOptionChangeType.OptionDeleted, mod, groupIdx, optionIdx, -1 );
}
@ -307,7 +310,7 @@ public sealed partial class Mod
{
if( message )
{
PluginLog.Warning( $"Could not name option {newName} because option with same filename {path} already exists." );
Penumbra.Log.Warning( $"Could not name option {newName} because option with same filename {path} already exists." );
}
return false;
@ -333,6 +336,11 @@ public sealed partial class Mod
private static void OnModOptionChange( ModOptionChangeType type, Mod mod, int groupIdx, int _, int _2 )
{
if( type == ModOptionChangeType.PrepareChange )
{
return;
}
// File deletion is handled in the actual function.
if( type is ModOptionChangeType.GroupDeleted or ModOptionChangeType.GroupMoved )
{

View file

@ -1,6 +1,5 @@
using System;
using System.IO;
using Dalamud.Logging;
namespace Penumbra.Mods;
@ -53,7 +52,7 @@ public sealed partial class Mod
}
catch( Exception e )
{
PluginLog.Error( $"Could not create specified mod directory {newDir.FullName}:\n{e}" );
Penumbra.Log.Error( $"Could not create specified mod directory {newDir.FullName}:\n{e}" );
}
}
@ -68,8 +67,7 @@ public sealed partial class Mod
private static void OnModDirectoryChange( string newPath, bool _ )
{
PluginLog.Information( "Set new mod base directory from {OldDirectory:l} to {NewDirectory:l}.",
Penumbra.Config.ModDirectory, newPath );
Penumbra.Log.Information( $"Set new mod base directory from {Penumbra.Config.ModDirectory} to {newPath}." );
Penumbra.Config.ModDirectory = newPath;
Penumbra.Config.Save();
}
@ -98,7 +96,12 @@ public sealed partial class Mod
}
ModDiscoveryFinished?.Invoke();
PluginLog.Information( "Rediscovered mods." );
Penumbra.Log.Information( "Rediscovered mods." );
if( MigrateModBackups )
{
ModBackup.MigrateZipToPmp( this );
}
}
}
}

View file

@ -9,6 +9,9 @@ public sealed partial class Mod
{
public sealed partial class Manager : IReadOnlyList< Mod >
{
// Set when reading Config and migrating from v4 to v5.
public static bool MigrateModBackups = false;
// An easily accessible set of new mods.
// Mods are added when they are created or imported.
// Mods are removed when they are deleted or when they are toggled in any collection.

View file

@ -1,5 +1,4 @@
using System.IO;
using Dalamud.Logging;
namespace Penumbra.Mods;
@ -32,7 +31,7 @@ public partial class Mod
modPath.Refresh();
if( !modPath.Exists )
{
PluginLog.Error( $"Supplied mod directory {modPath} does not exist." );
Penumbra.Log.Error( $"Supplied mod directory {modPath} does not exist." );
return null;
}
@ -40,7 +39,7 @@ public partial class Mod
if( !mod.Reload( out _ ) )
{
// Can not be base path not existing because that is checked before.
PluginLog.Error( $"Mod at {modPath} without name is not supported." );
Penumbra.Log.Error( $"Mod at {modPath} without name is not supported." );
return null;
}

View file

@ -2,7 +2,6 @@ using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Dalamud.Logging;
using Newtonsoft.Json.Linq;
using OtterGui;
using Penumbra.GameData.ByteString;
@ -88,7 +87,7 @@ public partial class Mod
}
catch( Exception e )
{
PluginLog.Error( $"Could not read mod group from {file.FullName}:\n{e}" );
Penumbra.Log.Error( $"Could not read mod group from {file.FullName}:\n{e}" );
}
return null;
@ -133,7 +132,7 @@ public partial class Mod
}
catch( Exception e )
{
PluginLog.Error( $"Could not delete outdated group file {file}:\n{e}" );
Penumbra.Log.Error( $"Could not delete outdated group file {file}:\n{e}" );
}
}

View file

@ -3,7 +3,6 @@ using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text.RegularExpressions;
using Dalamud.Logging;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using OtterGui;
@ -37,7 +36,7 @@ public sealed partial class Mod
}
catch( Exception e )
{
PluginLog.Error( $"Could not rename group file {group.Name} to {newName} during migration:\n{e}" );
Penumbra.Log.Error( $"Could not rename group file {group.Name} to {newName} during migration:\n{e}" );
}
}
@ -69,7 +68,7 @@ public sealed partial class Mod
if( unusedFile.ToGamePath( mod.ModPath, out var gamePath )
&& !mod._default.FileData.TryAdd( gamePath, unusedFile ) )
{
PluginLog.Error( $"Could not add {gamePath} because it already points to {mod._default.FileData[ gamePath ]}." );
Penumbra.Log.Error( $"Could not add {gamePath} because it already points to {mod._default.FileData[ gamePath ]}." );
}
}
@ -95,7 +94,7 @@ public sealed partial class Mod
}
catch( Exception e )
{
PluginLog.Warning( $"Could not delete meta file {file.FullName} during migration:\n{e}" );
Penumbra.Log.Warning( $"Could not delete meta file {file.FullName} during migration:\n{e}" );
}
}
@ -109,7 +108,7 @@ public sealed partial class Mod
}
catch( Exception e )
{
PluginLog.Warning( $"Could not delete old meta file {oldMetaFile} during migration:\n{e}" );
Penumbra.Log.Warning( $"Could not delete old meta file {oldMetaFile} during migration:\n{e}" );
}
}

View file

@ -1,9 +1,7 @@
using System;
using System.IO;
using Dalamud.Logging;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using OtterGui;
using OtterGui.Classes;
namespace Penumbra.Mods;
@ -48,7 +46,7 @@ public sealed partial class Mod
var metaFile = MetaFile;
if( !File.Exists( metaFile.FullName ) )
{
PluginLog.Debug( "No mod meta found for {ModLocation}.", ModPath.Name );
Penumbra.Log.Debug( $"No mod meta found for {ModPath.Name}." );
return MetaChangeType.Deletion;
}
@ -115,7 +113,7 @@ public sealed partial class Mod
}
catch( Exception e )
{
PluginLog.Error( $"Could not load mod meta:\n{e}" );
Penumbra.Log.Error( $"Could not load mod meta:\n{e}" );
return MetaChangeType.Deletion;
}
}
@ -142,7 +140,7 @@ public sealed partial class Mod
}
catch( Exception e )
{
PluginLog.Error( $"Could not write meta file for mod {Name} to {metaFile.FullName}:\n{e}" );
Penumbra.Log.Error( $"Could not write meta file for mod {Name} to {metaFile.FullName}:\n{e}" );
}
}

View file

@ -1,6 +1,9 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using OtterGui.Classes;
using Penumbra.Collections;
using Penumbra.GameData.ByteString;
using Penumbra.Meta.Manipulations;
@ -42,5 +45,67 @@ public sealed partial class Mod
_default.FileData = dict;
_default.ManipulationData = manips;
}
public static void SaveTempCollection( ModCollection collection, string? character = null )
{
DirectoryInfo? dir = null;
try
{
dir = CreateModFolder( Penumbra.ModManager.BasePath, collection.Name );
var fileDir = Directory.CreateDirectory( Path.Combine( dir.FullName, "files" ) );
CreateMeta( dir, collection.Name, character ?? Penumbra.Config.DefaultModAuthor,
$"Mod generated from temporary collection {collection.Name} for {character ?? "Unknown Character"}.", null, null );
var mod = new Mod( dir );
var defaultMod = mod._default;
foreach( var (gamePath, fullPath) in collection.ResolvedFiles )
{
if( gamePath.Path.EndsWith( '.', 'i', 'm', 'c' ) )
{
continue;
}
var targetPath = fullPath.Path.FullName;
if( fullPath.Path.Name.StartsWith( '|' ) )
{
targetPath = targetPath.Split( '|', 3, StringSplitOptions.RemoveEmptyEntries ).Last();
}
if( Path.IsPathRooted(targetPath) )
{
var target = Path.Combine( fileDir.FullName, Path.GetFileName(targetPath) );
File.Copy( targetPath, target, true );
defaultMod.FileData[ gamePath ] = new FullPath( target );
}
else
{
defaultMod.FileSwapData[ gamePath ] = new FullPath(targetPath);
}
}
foreach( var manip in collection.MetaCache?.Manipulations ?? Array.Empty< MetaManipulation >() )
{
defaultMod.ManipulationData.Add( manip );
}
mod.SaveDefaultMod();
Penumbra.ModManager.AddMod( dir );
Penumbra.Log.Information( $"Successfully generated mod {mod.Name} at {mod.ModPath.FullName} for collection {collection.Name}." );
}
catch( Exception e )
{
Penumbra.Log.Error( $"Could not save temporary collection {collection.Name} to permanent Mod:\n{e}" );
if( dir != null && Directory.Exists( dir.FullName ) )
{
try
{
Directory.Delete( dir.FullName, true );
}
catch
{
// ignored
}
}
}
}
}
}

View file

@ -3,7 +3,6 @@ using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text.RegularExpressions;
using Dalamud.Logging;
using OtterGui.Filesystem;
namespace Penumbra.Mods;
@ -19,7 +18,7 @@ public sealed class ModFileSystem : FileSystem< Mod >, IDisposable
private void SaveFilesystem()
{
SaveToFile( new FileInfo( ModFileSystemFile ), SaveMod, true );
PluginLog.Verbose( "Saved mod filesystem." );
Penumbra.Log.Verbose( "Saved mod filesystem." );
}
private void Save()
@ -79,7 +78,7 @@ public sealed class ModFileSystem : FileSystem< Mod >, IDisposable
Save();
}
PluginLog.Debug( "Reloaded mod filesystem." );
Penumbra.Log.Debug( "Reloaded mod filesystem." );
}
// Save the filesystem on every filesystem change except full reloading.

View file

@ -1,7 +1,6 @@
using System;
using System.Collections.Generic;
using System.IO;
using Dalamud.Logging;
using Newtonsoft.Json;
using OtterGui.Filesystem;
@ -50,11 +49,11 @@ public interface IModGroup : IEnumerable< ISubMod >
try
{
File.Delete( file );
PluginLog.Debug( "Deleted group file {File:l} for group {GroupIdx}: {GroupName:l}.", file, groupIdx + 1, Name );
Penumbra.Log.Debug( $"Deleted group file {file} for group {groupIdx + 1}: {Name}." );
}
catch( Exception e )
{
PluginLog.Error( $"Could not delete file {file}:\n{e}" );
Penumbra.Log.Error( $"Could not delete file {file}:\n{e}" );
throw;
}
}
@ -92,7 +91,7 @@ public interface IModGroup : IEnumerable< ISubMod >
j.WriteEndArray();
j.WriteEndObject();
PluginLog.Debug( "Saved group file {File:l} for group {GroupIdx}: {GroupName:l}.", file, groupIdx + 1, group.Name );
Penumbra.Log.Debug( $"Saved group file {file} for group {groupIdx + 1}: {group.Name}." );
}
public IModGroup Convert( SelectType type );

View file

@ -1,9 +1,7 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Dalamud.Logging;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using OtterGui;
@ -61,7 +59,7 @@ public partial class Mod
{
if( ret.PrioritizedOptions.Count == IModGroup.MaxMultiOptions )
{
PluginLog.Warning(
Penumbra.Log.Warning(
$"Multi Group {ret.Name} has more than {IModGroup.MaxMultiOptions} options, ignoring excessive options." );
break;
}

View file

@ -1,7 +1,6 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;

View file

@ -2,7 +2,6 @@ using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Dalamud.Logging;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Penumbra.GameData.ByteString;
@ -56,7 +55,7 @@ public partial class Mod
}
catch( Exception e )
{
PluginLog.Error( $"Could not parse default file for {Name}:\n{e}" );
Penumbra.Log.Error( $"Could not parse default file for {Name}:\n{e}" );
}
}
@ -196,8 +195,7 @@ public partial class Mod
}
catch( Exception e )
{
PluginLog.Error( $"Could not incorporate meta changes in mod {basePath} from file {file.FullName}:\n{e}" );
continue;
Penumbra.Log.Error( $"Could not incorporate meta changes in mod {basePath} from file {file.FullName}:\n{e}" );
}
}
}

View file

@ -70,7 +70,7 @@ public class ModSettings
var config = Settings[ groupIdx ];
Settings[ groupIdx ] = group.Type switch
{
SelectType.Single => config >= optionIdx ? Math.Max( 0, config - 1 ) : config,
SelectType.Single => config >= optionIdx ? (config > 1 ? config - 1 : 0) : config,
SelectType.Multi => RemoveBit( config, optionIdx ),
_ => config,
};

View file

@ -6,7 +6,6 @@ using System.Reflection;
using System.Text;
using Dalamud.Game.Command;
using Dalamud.Interface.Windowing;
using Dalamud.Logging;
using Dalamud.Plugin;
using EmbedIO;
using EmbedIO.WebApi;
@ -14,6 +13,8 @@ using ImGuiNET;
using Lumina.Excel.GeneratedSheets;
using OtterGui;
using OtterGui.Classes;
using OtterGui.Log;
using OtterGui.Widgets;
using Penumbra.Api;
using Penumbra.GameData.Enums;
using Penumbra.Interop;
@ -43,6 +44,7 @@ public class Penumbra : IDalamudPlugin
public static bool DevPenumbraExists;
public static bool IsNotInstalledPenumbra;
public static Logger Log { get; private set; } = null!;
public static Configuration Config { get; private set; } = null!;
public static ResidentResourceManager ResidentResources { get; private set; } = null!;
@ -64,6 +66,7 @@ public class Penumbra : IDalamudPlugin
private readonly ConfigWindow _configWindow;
private readonly LaunchButton _launchButton;
private readonly WindowSystem _windowSystem;
private readonly Changelog _changelog;
internal WebServer? WebServer;
@ -72,6 +75,7 @@ public class Penumbra : IDalamudPlugin
try
{
Dalamud.Initialize( pluginInterface );
Log = new Logger();
GameData.GameData.GetIdentifier( Dalamud.GameData );
DevPenumbraExists = CheckDevPluginPenumbra();
IsNotInstalledPenumbra = CheckIsNotInstalled();
@ -99,7 +103,7 @@ public class Penumbra : IDalamudPlugin
HelpMessage = "/penumbra - toggle ui\n/penumbra reload - reload mod file lists & discover any new mods",
} );
SetupInterface( out _configWindow, out _launchButton, out _windowSystem );
SetupInterface( out _configWindow, out _launchButton, out _windowSystem, out _changelog );
if( Config.EnableMods )
{
@ -133,17 +137,17 @@ public class Penumbra : IDalamudPlugin
SubscribeItemLinks();
if( ImcExceptions > 0 )
{
PluginLog.Error( $"{ImcExceptions} IMC Exceptions thrown. Please repair your game files." );
Log.Error( $"{ImcExceptions} IMC Exceptions thrown. Please repair your game files." );
}
else
{
PluginLog.Information( $"Penumbra Version {Version}, Commit #{CommitHash} successfully Loaded." );
Log.Information( $"Penumbra Version {Version}, Commit #{CommitHash} successfully Loaded." );
}
Dalamud.PluginInterface.UiBuilder.Draw += _windowSystem.Draw;
OtterTex.NativeDll.Initialize( Dalamud.PluginInterface.AssemblyLocation.DirectoryName );
PluginLog.Information( $"Loading native assembly from {OtterTex.NativeDll.Directory}." );
Log.Information( $"Loading native OtterTex assembly from {OtterTex.NativeDll.Directory}." );
}
catch
{
@ -152,23 +156,31 @@ public class Penumbra : IDalamudPlugin
}
}
private void SetupInterface( out ConfigWindow cfg, out LaunchButton btn, out WindowSystem system )
private void SetupInterface( out ConfigWindow cfg, out LaunchButton btn, out WindowSystem system, out Changelog changelog )
{
cfg = new ConfigWindow( this );
btn = new LaunchButton( _configWindow );
system = new WindowSystem( Name );
cfg = new ConfigWindow( this );
btn = new LaunchButton( _configWindow );
system = new WindowSystem( Name );
changelog = ConfigWindow.CreateChangelog();
system.AddWindow( _configWindow );
system.AddWindow( cfg.ModEditPopup );
system.AddWindow( ConfigWindow.CreateChangelog() );
system.AddWindow( changelog );
Dalamud.PluginInterface.UiBuilder.OpenConfigUi += cfg.Toggle;
}
private void DisposeInterface()
{
Dalamud.PluginInterface.UiBuilder.Draw -= _windowSystem.Draw;
Dalamud.PluginInterface.UiBuilder.OpenConfigUi -= _configWindow.Toggle;
if( _windowSystem != null )
{
Dalamud.PluginInterface.UiBuilder.Draw -= _windowSystem.Draw;
}
_launchButton?.Dispose();
_configWindow?.Dispose();
if( _configWindow != null )
{
Dalamud.PluginInterface.UiBuilder.OpenConfigUi -= _configWindow.Toggle;
_configWindow.Dispose();
}
}
public bool Enable()
@ -216,6 +228,9 @@ public class Penumbra : IDalamudPlugin
public bool SetEnabled( bool enabled )
=> enabled ? Enable() : Disable();
public void ForceChangelogOpen()
=> _changelog.ForceOpen = true;
private void SubscribeItemLinks()
{
Api.ChangedItemTooltip += it =>
@ -248,7 +263,7 @@ public class Penumbra : IDalamudPlugin
.WithController( () => new ModsController( this ) )
.WithController( () => new RedrawController( this ) ) );
WebServer.StateChanged += ( _, e ) => PluginLog.Information( $"WebServer New State - {e.NewState}" );
WebServer.StateChanged += ( _, e ) => Log.Information( $"WebServer New State - {e.NewState}" );
WebServer.RunAsync();
}
@ -502,7 +517,7 @@ public class Penumbra : IDalamudPlugin
}
catch( Exception e )
{
PluginLog.Error( $"Could not check for dev plugin Penumbra:\n{e}" );
Log.Error( $"Could not check for dev plugin Penumbra:\n{e}" );
return true;
}
#else
@ -517,7 +532,7 @@ public class Penumbra : IDalamudPlugin
var checkedDirectory = Dalamud.PluginInterface.AssemblyLocation.Directory?.Parent?.Parent?.Name;
var ret = checkedDirectory?.Equals( "installedPlugins", StringComparison.OrdinalIgnoreCase ) ?? false;
if (!ret)
PluginLog.Error($"Penumbra is not correctly installed. Application loaded from \"{Dalamud.PluginInterface.AssemblyLocation.Directory!.FullName}\"." );
Log.Error($"Penumbra is not correctly installed. Application loaded from \"{Dalamud.PluginInterface.AssemblyLocation.Directory!.FullName}\"." );
return !ret;
#else
return false;

View file

@ -3,7 +3,6 @@ using System.Collections.Generic;
using System.IO;
using System.Numerics;
using Dalamud.Interface;
using Dalamud.Logging;
using ImGuiNET;
using OtterGui;
using OtterGui.Raii;
@ -134,7 +133,7 @@ public partial class ModEditWindow
}
catch( Exception e )
{
PluginLog.Error( $"Could not parse {_fileType} file {_currentPath.File.FullName}:\n{e}" );
Penumbra.Log.Error( $"Could not parse {_fileType} file {_currentPath.File.FullName}:\n{e}" );
_currentFile = null;
}
}

View file

@ -3,7 +3,6 @@ using System.Collections.Generic;
using System.Linq;
using System.Numerics;
using Dalamud.Interface;
using Dalamud.Logging;
using ImGuiNET;
using OtterGui;
using OtterGui.Classes;
@ -321,7 +320,7 @@ public partial class ModEditWindow
var failedFiles = _editor!.ApplyFiles();
if( failedFiles > 0 )
{
PluginLog.Information( $"Failed to apply {failedFiles} file redirections to {_editor.CurrentOption.FullName}." );
Penumbra.Log.Information( $"Failed to apply {failedFiles} file redirections to {_editor.CurrentOption.FullName}." );
}
}

View file

@ -2,7 +2,6 @@ using System;
using System.IO;
using System.Numerics;
using Dalamud.Interface.ImGuiFileDialog;
using Dalamud.Logging;
using ImGuiNET;
using OtterGui;
using OtterGui.Raii;
@ -123,7 +122,7 @@ public partial class ModEditWindow
}
catch( Exception e )
{
PluginLog.Error( $"Unknown Error while drawing textures:\n{e}" );
Penumbra.Log.Error( $"Unknown Error while drawing textures:\n{e}" );
}
}

View file

@ -1,6 +1,5 @@
using Dalamud.Interface;
using Dalamud.Interface.ImGuiFileDialog;
using Dalamud.Logging;
using ImGuiNET;
using OtterGui;
using OtterGui.Filesystem;
@ -14,7 +13,6 @@ using System.Collections.Concurrent;
using System.IO;
using System.Linq;
using System.Numerics;
using Penumbra.Util;
namespace Penumbra.UI.Classes;
@ -100,7 +98,7 @@ public sealed partial class ModFileSystemSelector : FileSystemSelector< Mod, Mod
}
catch( Exception e )
{
PluginLog.Error( $"Could not create directory for new Mod {_newModName}:\n{e}" );
Penumbra.Log.Error( $"Could not create directory for new Mod {_newModName}:\n{e}" );
}
}
@ -200,7 +198,7 @@ public sealed partial class ModFileSystemSelector : FileSystemSelector< Mod, Mod
private void AddImportModButton( Vector2 size )
{
var button = ImGuiUtil.DrawDisabledButton( FontAwesomeIcon.FileImport.ToIconString(), size,
"Import one or multiple mods from Tex Tools Mod Pack Files.", !Penumbra.ModManager.Valid, true );
"Import one or multiple mods from Tex Tools Mod Pack Files or Penumbra Mod Pack Files.", !Penumbra.ModManager.Valid, true );
ConfigWindow.OpenTutorial( ConfigWindow.BasicTutorialSteps.ModImport );
if( !button )
{
@ -213,7 +211,7 @@ public sealed partial class ModFileSystemSelector : FileSystemSelector< Mod, Mod
_hasSetFolder = true;
_fileManager.OpenFileDialog( "Import Mod Pack",
"Mod Packs{.ttmp,.ttmp2,.zip,.7z,.rar},TexTools Mod Packs{.ttmp,.ttmp2},Archives{.zip,.7z,.rar}", ( s, f ) =>
"Mod Packs{.ttmp,.ttmp2,.pmp},TexTools Mod Packs{.ttmp,.ttmp2},Penumbra Mod Packs{.pmp},Archives{.zip,.7z,.rar}", ( s, f ) =>
{
if( s )
{
@ -273,13 +271,13 @@ public sealed partial class ModFileSystemSelector : FileSystemSelector< Mod, Mod
}
catch( Exception e )
{
PluginLog.Error( $"Error cleaning up failed mod extraction of {file.FullName} to {dir.FullName}:\n{e}" );
Penumbra.Log.Error( $"Error cleaning up failed mod extraction of {file.FullName} to {dir.FullName}:\n{e}" );
}
}
if( error is not OperationCanceledException )
{
PluginLog.Error( $"Error extracting {file.FullName}, mod skipped:\n{error}" );
Penumbra.Log.Error( $"Error extracting {file.FullName}, mod skipped:\n{error}" );
}
}
else if( dir != null )
@ -445,7 +443,7 @@ public sealed partial class ModFileSystemSelector : FileSystemSelector< Mod, Mod
}
catch( Exception e )
{
PluginLog.Warning(
Penumbra.Log.Warning(
$"Could not move newly imported mod {mod.Name} to default import folder {Penumbra.Config.DefaultImportFolder}:\n{e}" );
}
}

View file

@ -1,4 +1,3 @@
using Lumina.Excel.GeneratedSheets;
using OtterGui.Widgets;
namespace Penumbra.UI;
@ -9,23 +8,57 @@ public partial class ConfigWindow
public static Changelog CreateChangelog()
{
var ret = new Changelog( "Penumbra Changelog", () => Penumbra.Config.LastSeenVersion, version =>
{
Penumbra.Config.LastSeenVersion = version;
Penumbra.Config.Save();
} );
var ret = new Changelog( "Penumbra Changelog", () => ( Penumbra.Config.LastSeenVersion, Penumbra.Config.ChangeLogDisplayType ),
( version, type ) =>
{
Penumbra.Config.LastSeenVersion = version;
Penumbra.Config.ChangeLogDisplayType = type;
Penumbra.Config.Save();
} );
Add5_7_0( ret );
Add5_7_1( ret );
return ret;
}
private static void Add5_8_0( Changelog log )
=> log.NextVersion( "Version 0.5.8.0" )
.RegisterEntry( "Added choices what Change Logs are to be displayed. It is recommended to just keep showing all." )
.RegisterEntry( "Fixed an issue with Actor 201 using Your Character collections in cutscenes." )
.RegisterEntry( "Fixed issues with and improved mod option editing." )
.RegisterEntry( "Backend optimizations." );
private static void Add5_7_1( Changelog log )
=> log.NextVersion( "Version 0.5.7.1" )
.RegisterEntry( "Fixed the Changelog window not considering UI Scale correctly." )
.RegisterEntry( "Reworked Changelog display slightly." );
private static void Add5_7_0( Changelog log )
=> log.NextVersion( "Version 0.5.7.0" )
.RegisterEntry( "Added a Changelog!" )
.RegisterEntry( "Files in the UI category will no longer be deduplicated for the moment." )
.RegisterHighlight( "If you experience UI-related crashes, please re-import your UI mods.", 1 )
.RegisterEntry( "This is a temporary fix against those not-yet fully understood crashes and may be reworked later.", 1 )
.RegisterHighlight(
"There is still a possibility of UI related mods crashing the game, we are still investigating - they behave very weirdly. If you continue to experience crashing, try disabling your UI mods.",
1 )
.RegisterEntry(
"On import, Penumbra will now show files with extensions '.ttmp', '.ttmp2' and '.pmp'. You can still select showing generic archive files." )
.RegisterEntry(
"Penumbra Mod Pack ('.pmp') files are meant to be renames of any of the archive types that could already be imported that contain the necessary Penumbra meta files.",
1 )
.RegisterHighlight(
"If you distribute any mod as an archive specifically for Penumbra, you should change its extension to '.pmp'. Supported base archive types are ZIP, 7-Zip and RAR.",
1 )
.RegisterEntry( "Penumbra will now save mod backups with the file extension '.pmp'. They still are regular ZIP files.", 1 )
.RegisterEntry(
"Existing backups in your current mod directory should be automatically renamed. If you manage multiple mod directories, you may need to migrate the other ones manually.",
1 )
.RegisterEntry( "Fixed assigned collections not working correctly on adventurer plates." )
.RegisterEntry( "Fixed a wrongly displayed folder line in some circumstances." )
.RegisterEntry( "Fixed crash after deleting mod options." )
.RegisterEntry( "Fixed Inspect Window collections not working correctly." )
.RegisterEntry( "Made identically named options selectable in mod configuration. Do not name your options identically." )
.RegisterEntry( "Added some additional functionality for Mare Synchronos." );
}

View file

@ -8,7 +8,6 @@ using OtterGui;
using OtterGui.Raii;
using Penumbra.Collections;
using Penumbra.UI.Classes;
using Penumbra.Util;
namespace Penumbra.UI;

View file

@ -6,7 +6,6 @@ using ImGuiNET;
using OtterGui;
using OtterGui.Raii;
using Penumbra.Collections;
using Penumbra.Util;
namespace Penumbra.UI;

View file

@ -11,7 +11,6 @@ using OtterGui;
using OtterGui.Raii;
using Penumbra.GameData.ByteString;
using Penumbra.Interop.Loader;
using Penumbra.Interop.Resolver;
using Penumbra.Interop.Structs;
using CharacterUtility = Penumbra.Interop.CharacterUtility;

View file

@ -1,4 +1,3 @@
using System;
using System.Linq;
using System.Numerics;
using Dalamud.Interface;
@ -13,7 +12,6 @@ using Penumbra.GameData.ByteString;
using Penumbra.GameData.Enums;
using Penumbra.Interop.Structs;
using Penumbra.UI.Classes;
using Penumbra.Util;
namespace Penumbra.UI;

View file

@ -5,7 +5,6 @@ using System.IO;
using System.Numerics;
using Dalamud.Interface;
using Dalamud.Interface.Components;
using Dalamud.Logging;
using ImGuiNET;
using OtterGui;
using OtterGui.Raii;
@ -51,7 +50,7 @@ public partial class ConfigWindow
}
catch( Exception e )
{
PluginLog.Warning( e.Message );
Penumbra.Log.Warning( e.Message );
}
}
@ -478,7 +477,7 @@ public partial class ConfigWindow
EditOption( panel, group, groupIdx, optionIdx );
}
DrawNewOption( panel._mod, groupIdx, panel._window._iconButtonSize );
DrawNewOption( panel, groupIdx, panel._window._iconButtonSize );
}
// Draw a line for a single option.
@ -519,9 +518,14 @@ public partial class ConfigWindow
}
// Draw the line to add a new option.
private static void DrawNewOption( Mod mod, int groupIdx, Vector2 iconButtonSize )
private static void DrawNewOption( ModPanel panel, int groupIdx, Vector2 iconButtonSize )
{
var mod = panel._mod;
var group = mod.Groups[ groupIdx ];
ImGui.TableNextColumn();
ImGui.AlignTextToFramePadding();
ImGui.Selectable( $"Option #{group.Count + 1}" );
Target( panel, group, groupIdx, group.Count );
ImGui.TableNextColumn();
ImGui.SetNextItemWidth( -1 );
var tmp = _newOptionNameIdx == groupIdx ? _newOptionName : string.Empty;
@ -565,14 +569,13 @@ public partial class ConfigWindow
private static void Target( ModPanel panel, IModGroup group, int groupIdx, int optionIdx )
{
// TODO drag options to other groups without options.
using var target = ImRaii.DragDropTarget();
if( !target.Success || !ImGuiUtil.IsDropping( DragDropLabel ) )
{
return;
}
if( _dragDropGroupIdx >= 0 && _dragDropOptionIdx >= 0 )
if( _dragDropGroupIdx >= 0 && _dragDropOptionIdx >= 0 )
{
if( _dragDropGroupIdx == groupIdx )
{
@ -581,15 +584,18 @@ public partial class ConfigWindow
}
else
{
// Move from one group to another by deleting, then adding the option.
var sourceGroup = _dragDropGroupIdx;
var sourceOption = _dragDropOptionIdx;
var option = group[ _dragDropOptionIdx ];
var priority = group.OptionPriority( _dragDropGroupIdx );
// Move from one group to another by deleting, then adding, then moving the option.
var sourceGroupIdx = _dragDropGroupIdx;
var sourceOption = _dragDropOptionIdx;
var sourceGroup = panel._mod.Groups[ sourceGroupIdx ];
var currentCount = group.Count;
var option = sourceGroup[sourceOption];
var priority = sourceGroup.OptionPriority( _dragDropGroupIdx );
panel._delayedActions.Enqueue( () =>
{
Penumbra.ModManager.DeleteOption( panel._mod, sourceGroup, sourceOption );
Penumbra.ModManager.DeleteOption( panel._mod, sourceGroupIdx, sourceOption );
Penumbra.ModManager.AddOption( panel._mod, groupIdx, option, priority );
Penumbra.ModManager.MoveOption( panel._mod, groupIdx, currentCount, optionIdx );
} );
}
}

View file

@ -1,4 +1,3 @@
using System;
using System.Numerics;
using Dalamud.Interface;
using ImGuiNET;
@ -168,10 +167,13 @@ public partial class ConfigWindow
{
for( var idx2 = 0; idx2 < group.Count; ++idx2 )
{
id.Push( idx2 );
if( ImGui.Selectable( group[ idx2 ].Name, idx2 == selectedOption ) )
{
Penumbra.CollectionManager.Current.SetModSetting( _mod.Index, groupIdx, ( uint )idx2 );
}
id.Pop();
}
}
@ -201,6 +203,7 @@ public partial class ConfigWindow
Widget.BeginFramedGroup( group.Name, group.Description );
for( var idx2 = 0; idx2 < group.Count; ++idx2 )
{
id.Push( idx2 );
var flag = 1u << idx2;
var setting = ( flags & flag ) != 0;
if( ImGui.Checkbox( group[ idx2 ].Name, ref setting ) )
@ -208,6 +211,8 @@ public partial class ConfigWindow
flags = setting ? flags | flag : flags & ~flag;
Penumbra.CollectionManager.Current.SetModSetting( _mod.Index, groupIdx, flags );
}
id.Pop();
}
Widget.EndFramedGroup();

View file

@ -7,7 +7,6 @@ using Penumbra.UI.Classes;
using System;
using System.Linq;
using System.Numerics;
using Dalamud.Logging;
namespace Penumbra.UI;
@ -42,8 +41,8 @@ public partial class ConfigWindow
}
catch( Exception e )
{
PluginLog.Error( $"Exception thrown during ModPanel Render:\n{e}" );
PluginLog.Error( $"{Penumbra.ModManager.Count} Mods\n"
Penumbra.Log.Error( $"Exception thrown during ModPanel Render:\n{e}" );
Penumbra.Log.Error( $"{Penumbra.ModManager.Count} Mods\n"
+ $"{Penumbra.CollectionManager.Current.AnonymizedName} Current Collection\n"
+ $"{Penumbra.CollectionManager.Current.Settings.Count} Settings\n"
+ $"{_selector.SortMode.Name} Sort Mode\n"

View file

@ -335,7 +335,7 @@ public partial class ConfigWindow
+ "Not directly affiliated and potentially, but not usually out of date." );
}
private static void DrawSupportButtons()
private void DrawSupportButtons()
{
var width = ImGui.CalcTextSize( SupportInfoButtonText ).X + ImGui.GetStyle().FramePadding.X * 2;
var xPos = ImGui.GetWindowWidth() - width;
@ -363,7 +363,7 @@ public partial class ConfigWindow
ImGui.SetCursorPos( new Vector2( xPos, 4 * ImGui.GetFrameHeightWithSpacing() ) );
if( ImGui.Button( "Show Changelogs", new Vector2( width, 0 ) ) )
{
Penumbra.Config.LastSeenVersion = 0;
_window._penumbra.ForceChangelogOpen();
}
}
}

View file

@ -2,7 +2,6 @@ using System;
using System.Numerics;
using Dalamud.Interface;
using Dalamud.Interface.Windowing;
using Dalamud.Logging;
using ImGuiNET;
using OtterGui.Raii;
using Penumbra.UI.Classes;
@ -92,7 +91,7 @@ public sealed partial class ConfigWindow : Window, IDisposable
}
catch( Exception e )
{
PluginLog.Error( $"Exception thrown during UI Render:\n{e}" );
Penumbra.Log.Error( $"Exception thrown during UI Render:\n{e}" );
}
}

View file

@ -3,7 +3,6 @@ using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Dalamud.Game;
using Dalamud.Logging;
namespace Penumbra.Util;
@ -58,7 +57,7 @@ public class FrameworkManager : IDisposable
}
catch( Exception e )
{
PluginLog.Error( $"Problem saving data:\n{e}" );
Penumbra.Log.Error( $"Problem saving data:\n{e}" );
}
}

View file

@ -334,14 +334,13 @@ public class PenumbraSqPackStream : IDisposable
if( blockHeader.CompressedSize == 32000 )
{
dest.Write( Reader.ReadBytes( ( int )blockHeader.UncompressedSize ) );
return blockHeader.UncompressedSize;
}
var data = Reader.ReadBytes( ( int )blockHeader.CompressedSize );
using( var compressedStream = new MemoryStream( data ) )
else
{
using var zlibStream = new DeflateStream( compressedStream, CompressionMode.Decompress );
var data = Reader.ReadBytes( ( int )blockHeader.CompressedSize );
using var compressedStream = new MemoryStream( data );
using var zlibStream = new DeflateStream( compressedStream, CompressionMode.Decompress );
zlibStream.CopyTo( dest );
}

View file

@ -4,8 +4,8 @@
"Name": "Penumbra",
"Description": "Runtime mod loader and manager.",
"InternalName": "Penumbra",
"AssemblyVersion": "0.5.6.3",
"TestingAssemblyVersion": "0.5.6.3",
"AssemblyVersion": "0.5.7.1",
"TestingAssemblyVersion": "0.5.7.1",
"RepoUrl": "https://github.com/xivdev/Penumbra",
"ApplicableVersion": "any",
"DalamudApiLevel": 7,
@ -16,9 +16,9 @@
"LoadPriority": 69420,
"LoadRequiredState": 2,
"LoadSync": true,
"DownloadLinkInstall": "https://github.com/xivdev/Penumbra/releases/download/0.5.6.3/Penumbra.zip",
"DownloadLinkTesting": "https://github.com/xivdev/Penumbra/releases/download/0.5.6.3/Penumbra.zip",
"DownloadLinkUpdate": "https://github.com/xivdev/Penumbra/releases/download/0.5.6.3/Penumbra.zip",
"DownloadLinkInstall": "https://github.com/xivdev/Penumbra/releases/download/0.5.7.1/Penumbra.zip",
"DownloadLinkTesting": "https://github.com/xivdev/Penumbra/releases/download/0.5.7.1/Penumbra.zip",
"DownloadLinkUpdate": "https://github.com/xivdev/Penumbra/releases/download/0.5.7.1/Penumbra.zip",
"IconUrl": "https://raw.githubusercontent.com/xivdev/Penumbra/master/images/icon.png"
}
]