just misc

This commit is contained in:
2026-01-05 07:48:14 +09:00
parent b6b9c81a57
commit 4da2548e03
7 changed files with 107 additions and 22 deletions

View File

@@ -1,4 +1,5 @@
using Dalamud.Plugin.Services;
using Dalamud.Game.ClientState.Objects.SubKinds;
using FFXIVClientStructs.FFXIV.Client.Game.Character;
using FFXIVClientStructs.FFXIV.Client.UI.Info;
using Microsoft.Extensions.Logging;
@@ -11,24 +12,35 @@ public unsafe class BlockedCharacterHandler
private readonly Dictionary<CharaData, bool> _blockedCharacterCache = new();
private readonly ILogger<BlockedCharacterHandler> _logger;
private readonly IObjectTable _objectTable;
public BlockedCharacterHandler(ILogger<BlockedCharacterHandler> logger, IGameInteropProvider gameInteropProvider)
public BlockedCharacterHandler(ILogger<BlockedCharacterHandler> logger, IGameInteropProvider gameInteropProvider, IObjectTable objectTable)
{
gameInteropProvider.InitializeFromAttributes(this);
_logger = logger;
_objectTable = objectTable;
}
private static CharaData GetIdsFromPlayerPointer(nint ptr)
private CharaData? TryGetIdsFromPlayerPointer(nint ptr, ushort objectIndex)
{
if (ptr == nint.Zero) return new(0, 0);
var castChar = ((BattleChara*)ptr);
if (ptr == nint.Zero || objectIndex >= 200)
return null;
var obj = _objectTable[objectIndex];
if (obj is not IPlayerCharacter player || player.Address != ptr)
return null;
var castChar = (BattleChara*)player.Address;
return new(castChar->Character.AccountId, castChar->Character.ContentId);
}
public bool IsCharacterBlocked(nint ptr, out bool firstTime)
public bool IsCharacterBlocked(nint ptr, ushort objectIndex, out bool firstTime)
{
firstTime = false;
var combined = GetIdsFromPlayerPointer(ptr);
var combined = TryGetIdsFromPlayerPointer(ptr, objectIndex);
if (combined == null)
return false;
if (_blockedCharacterCache.TryGetValue(combined, out var isBlocked))
return isBlocked;

View File

@@ -24,7 +24,7 @@ public class PlayerPerformanceConfig : ILightlessConfiguration
public bool KeepOriginalTextureFiles { get; set; } = false;
public bool SkipTextureDownscaleForPreferredPairs { get; set; } = true;
public bool EnableModelDecimation { get; set; } = false;
public int ModelDecimationTriangleThreshold { get; set; } = 50_000;
public int ModelDecimationTriangleThreshold { get; set; } = 20_000;
public double ModelDecimationTargetRatio { get; set; } = 0.8;
public bool KeepOriginalModelFiles { get; set; } = true;
public bool SkipModelDecimationForPreferredPairs { get; set; } = true;

View File

@@ -123,6 +123,7 @@ public sealed class Plugin : IDalamudPlugin
services.AddSingleton<HubFactory>();
services.AddSingleton<FileUploadManager>();
services.AddSingleton<FileTransferOrchestrator>();
services.AddSingleton<FileDownloadDeduplicator>();
services.AddSingleton<LightlessPlugin>();
services.AddSingleton<LightlessProfileManager>();
services.AddSingleton<TextureCompressionService>();
@@ -180,7 +181,8 @@ public sealed class Plugin : IDalamudPlugin
services.AddSingleton(sp => new BlockedCharacterHandler(
sp.GetRequiredService<ILogger<BlockedCharacterHandler>>(),
gameInteropProvider));
gameInteropProvider,
objectTable));
services.AddSingleton(sp => new IpcProvider(
sp.GetRequiredService<ILogger<IpcProvider>>(),

View File

@@ -1010,7 +1010,7 @@ public class DalamudUtilService : IHostedService, IMediatorSubscriber
if (actor.ObjectIndex >= 200)
continue;
if (_blockedCharacterHandler.IsCharacterBlocked(playerAddress, out bool firstTime) && firstTime)
if (_blockedCharacterHandler.IsCharacterBlocked(playerAddress, actor.ObjectIndex, out bool firstTime) && firstTime)
{
_logger.LogTrace("Skipping character {addr}, blocked/muted", playerAddress.ToString("X"));
continue;

View File

@@ -1,6 +1,7 @@
using Lumina.Data.Parsing;
using Lumina.Extensions;
using MeshDecimator;
using MeshDecimator.Algorithms;
using MeshDecimator.Math;
using Microsoft.Extensions.Logging;
using Penumbra.GameData.Files.ModelStructs;
@@ -94,6 +95,8 @@ internal static class MdlDecimator
var newVertexBuffer = new List<byte>(mdl.VertexBufferSize[lodIndex] > 0 ? (int)mdl.VertexBufferSize[lodIndex] : 0);
var newIndexBuffer = new List<ushort>(mdl.IndexBufferSize[lodIndex] > 0 ? (int)(mdl.IndexBufferSize[lodIndex] / sizeof(ushort)) : 0);
var subMeshCursor = 0;
DecimationAlgorithm? decimationAlgorithm = null;
int? decimationUvChannelCount = null;
for (var meshIndex = 0; meshIndex < meshes.Length; meshIndex++)
{
@@ -119,6 +122,8 @@ internal static class MdlDecimator
out vertexStreams,
out indices,
out decimated,
ref decimationAlgorithm,
ref decimationUvChannelCount,
logger))
{
updatedSubMeshes = OffsetSubMeshes(updatedSubMeshes, meshIndexBase);
@@ -309,6 +314,8 @@ internal static class MdlDecimator
out byte[][] vertexStreams,
out int[] indices,
out bool decimated,
ref DecimationAlgorithm? decimationAlgorithm,
ref int? decimationUvChannelCount,
MsLogger logger)
{
updatedMesh = mesh;
@@ -352,8 +359,7 @@ internal static class MdlDecimator
}
var meshDecimatorMesh = BuildMesh(decoded, subMeshIndices);
var algorithm = MeshDecimation.CreateAlgorithm(Algorithm.Default);
algorithm.Logger = logger;
var algorithm = GetOrCreateAlgorithm(format, ref decimationAlgorithm, ref decimationUvChannelCount, logger);
algorithm.Initialize(meshDecimatorMesh);
algorithm.DecimateMesh(targetTriangles);
var decimatedMesh = algorithm.ToMesh();
@@ -374,6 +380,23 @@ internal static class MdlDecimator
return true;
}
private static DecimationAlgorithm GetOrCreateAlgorithm(
VertexFormat format,
ref DecimationAlgorithm? decimationAlgorithm,
ref int? decimationUvChannelCount,
MsLogger logger)
{
var uvChannelCount = format.UvChannelCount;
if (decimationAlgorithm == null || decimationUvChannelCount != uvChannelCount)
{
decimationAlgorithm = MeshDecimation.CreateAlgorithm(Algorithm.Default);
decimationAlgorithm.Logger = logger;
decimationUvChannelCount = uvChannelCount;
}
return decimationAlgorithm;
}
private static Mesh BuildMesh(DecodedMeshData decoded, int[][] subMeshIndices)
{
var mesh = new Mesh(decoded.Positions, subMeshIndices);

View File

@@ -3635,8 +3635,31 @@ public class SettingsUi : WindowMediatorSubscriberBase
new SeStringUtils.RichTextEntry("destructive", UIColors.Get("DimRed"), true),
new SeStringUtils.RichTextEntry(" process and may cause broken or incorrect character appearances."));
_uiShared.DrawNoteLine("! ", UIColors.Get("DimRed"),
new SeStringUtils.RichTextEntry("this shit is placeholder still owo"));
new SeStringUtils.RichTextEntry("This feature is encouraged to help "),
new SeStringUtils.RichTextEntry("lower-end systems with limited VRAM", UIColors.Get("LightlessYellow"), true),
new SeStringUtils.RichTextEntry(" and for use in "),
new SeStringUtils.RichTextEntry("performance-critical scenarios", UIColors.Get("LightlessYellow"), true),
new SeStringUtils.RichTextEntry("."));
_uiShared.DrawNoteLine("! ", UIColors.Get("DimRed"),
new SeStringUtils.RichTextEntry("Runtime decimation "),
new SeStringUtils.RichTextEntry("MAY", UIColors.Get("DimRed"), true),
new SeStringUtils.RichTextEntry(" cause higher load on the system when processing downloads."));
_uiShared.DrawNoteLine("!!! ", UIColors.Get("DimRed"),
new SeStringUtils.RichTextEntry("When enabled, we cannot provide support for appearance issues caused by this setting!", UIColors.Get("DimRed"), true));
ImGui.Dummy(new Vector2(15));
_uiShared.DrawNoteLine("! ", UIColors.Get("LightlessGreen"),
new SeStringUtils.RichTextEntry("If a mesh exceeds the "),
new SeStringUtils.RichTextEntry("triangle threshold", UIColors.Get("LightlessGreen"), true),
new SeStringUtils.RichTextEntry(", it will be decimated automatically to the set "),
new SeStringUtils.RichTextEntry("target triangle ratio", UIColors.Get("LightlessGreen"), true),
new SeStringUtils.RichTextEntry(". This will reduce quality of the mesh or may break it's intended structure."));
var performanceConfig = _playerPerformanceConfigService.Current;
var enableDecimation = performanceConfig.EnableModelDecimation;
@@ -3667,9 +3690,9 @@ public class SettingsUi : WindowMediatorSubscriberBase
var triangleThreshold = performanceConfig.ModelDecimationTriangleThreshold;
ImGui.SetNextItemWidth(300 * ImGuiHelpers.GlobalScale);
if (ImGui.SliderInt("Decimate models above", ref triangleThreshold, 10_000, 100_000))
if (ImGui.SliderInt("Decimate models above", ref triangleThreshold, 8_000, 100_000))
{
performanceConfig.ModelDecimationTriangleThreshold = Math.Clamp(triangleThreshold, 10_000, 100_000);
performanceConfig.ModelDecimationTriangleThreshold = Math.Clamp(triangleThreshold, 8_000, 100_000);
_playerPerformanceConfigService.Save();
}
ImGui.SameLine();
@@ -3677,7 +3700,7 @@ public class SettingsUi : WindowMediatorSubscriberBase
_uiShared.DrawHelpText($"Models below this triangle count are left untouched.{UiSharedService.TooltipSeparator}Default: 50,000");
var targetPercent = (float)(performanceConfig.ModelDecimationTargetRatio * 100.0);
var clampedPercent = Math.Clamp(targetPercent, 70f, 99f);
var clampedPercent = Math.Clamp(targetPercent, 60f, 99f);
if (Math.Abs(clampedPercent - targetPercent) > float.Epsilon)
{
performanceConfig.ModelDecimationTargetRatio = clampedPercent / 100.0;
@@ -3685,17 +3708,30 @@ public class SettingsUi : WindowMediatorSubscriberBase
targetPercent = clampedPercent;
}
ImGui.SetNextItemWidth(300 * ImGuiHelpers.GlobalScale);
if (ImGui.SliderFloat("Target triangle ratio", ref targetPercent, 70f, 99f, "%.0f%%"))
if (ImGui.SliderFloat("Target triangle ratio", ref targetPercent, 60f, 99f, "%.0f%%"))
{
performanceConfig.ModelDecimationTargetRatio = Math.Clamp(targetPercent / 100f, 0.7f, 0.99f);
performanceConfig.ModelDecimationTargetRatio = Math.Clamp(targetPercent / 100f, 0.6f, 0.99f);
_playerPerformanceConfigService.Save();
}
_uiShared.DrawHelpText($"Target ratio relative to original triangle count (70% keeps 70% of triangles).{UiSharedService.TooltipSeparator}Default: 70%");
_uiShared.DrawHelpText($"Target ratio relative to original triangle count (80% keeps 80% of triangles).{UiSharedService.TooltipSeparator}Default: 80%");
ImGui.Dummy(new Vector2(5));
ImGui.Dummy(new Vector2(15));
ImGui.TextUnformatted("Decimation targets");
_uiShared.DrawHelpText("Hair mods are always excluded from decimation.");
_uiShared.DrawNoteLine("! ", UIColors.Get("LightlessGreen"),
new SeStringUtils.RichTextEntry("Automatic decimation will only target the selected "),
new SeStringUtils.RichTextEntry("decimation targets", UIColors.Get("LightlessGreen"), true),
new SeStringUtils.RichTextEntry("."));
_uiShared.DrawNoteLine("! ", UIColors.Get("LightlessYellow"),
new SeStringUtils.RichTextEntry("It is advised to not decimate any body related meshes which includes: "),
new SeStringUtils.RichTextEntry("facial mods + sculpts, chest, legs, hands and feet", UIColors.Get("LightlessYellow"), true),
new SeStringUtils.RichTextEntry("."));
_uiShared.DrawNoteLine("!!! ", UIColors.Get("DimRed"),
new SeStringUtils.RichTextEntry("Remember, automatic decimation is not perfect and can cause meshes to be ruined, especially hair mods.", UIColors.Get("DimRed"), true));
var allowBody = performanceConfig.ModelDecimationAllowBody;
if (ImGui.Checkbox("Body", ref allowBody))
{
@@ -3731,6 +3767,10 @@ public class SettingsUi : WindowMediatorSubscriberBase
_playerPerformanceConfigService.Save();
}
ImGui.Dummy(new Vector2(5));
UiSharedService.ColoredSeparator(UIColors.Get("LightlessGrey"), 3f);
ImGui.Dummy(new Vector2(5));
DrawTriangleDecimationCounters();
ImGui.Dummy(new Vector2(5));

View File

@@ -205,10 +205,8 @@ public sealed class ZoneChatUi : WindowMediatorSubscriberBase
private void ApplyUiVisibilitySettings()
{
var config = _chatConfigService.Current;
_uiBuilder.DisableUserUiHide = true;
_uiBuilder.DisableCutsceneUiHide = config.ShowInCutscenes;
_uiBuilder.DisableGposeUiHide = config.ShowInGpose;
_uiBuilder.DisableCutsceneUiHide = true;
}
private bool ShouldHide()
@@ -220,6 +218,16 @@ public sealed class ZoneChatUi : WindowMediatorSubscriberBase
return true;
}
if (!config.ShowInGpose && _dalamudUtilService.IsInGpose)
{
return true;
}
if (!config.ShowInCutscenes && _dalamudUtilService.IsInCutscene)
{
return true;
}
if (config.HideInCombat && _dalamudUtilService.IsInCombat)
{
return true;