Compare commits

..

113 Commits

Author SHA1 Message Date
cake
995e11371a updated ptrguard to use system_info for minimum calculations 2026-01-20 16:42:31 +01:00
cake
22fe9901a4 Fixed some issues. 2026-01-20 00:25:26 +01:00
cake
cff866dcc2 Added ptrguard to be used whenever ptrs are being used. 2026-01-20 00:24:42 +01:00
cake
367af2c3d0 Remove blankspace 2026-01-19 19:26:00 +01:00
cake
19a238c808 Removal of unsafe and check if PTR is correctly aligning, checking in virtual query instead of memory 2026-01-19 19:24:44 +01:00
7d86b41cee Merge pull request 'update-decimation-filters' (#140) from update-decimation-filters into 2.0.3
Reviewed-on: #140
2026-01-19 17:22:27 +00:00
0185e6b534 Merge pull request 'Implement Lifestream With Location Sharing.' (#139) from lifestream-location-share into 2.0.3
Reviewed-on: #139
Reviewed-by: cake <cake@noreply.git.lightless-sync.org>
2026-01-19 17:02:13 +00:00
defnotken
90bf84f8eb Implement Lifestream With Location Sharing. 2026-01-19 10:58:37 -06:00
f27db300ec fix temp collection config and migrate it 2026-01-19 23:04:54 +09:00
828be6eb5b fix body materials 2026-01-19 21:20:54 +09:00
d039d2fd90 add emperors oops 2026-01-19 14:19:08 +09:00
e75a371475 improve filtering 2026-01-19 14:14:14 +09:00
cake
d6437998ac Added imgui flag for notifcation 2026-01-19 03:51:08 +01:00
cake
4fa9876c1c Fix build 2026-01-19 03:35:36 +01:00
9dd8e19fb7 Merge pull request 'meow decimation' (#138) from meow into 2.0.3
Reviewed-on: #138
2026-01-19 02:29:02 +00:00
5167465d28 up to date with 2.0.3 2026-01-19 10:06:21 +09:00
e8c7539770 fix log level 2026-01-19 09:57:50 +09:00
54d6a0a1a4 reworked mesh decimation yes 2026-01-19 09:50:54 +09:00
b57d54d69c fix some existing issues 2026-01-17 08:00:58 +09:00
8be0811b4a fix pair offline state 2026-01-17 03:06:46 +09:00
7c281926a5 :sludge: 2026-01-16 19:29:24 +09:00
6c7e4e6303 fix task register 2026-01-16 19:18:11 +09:00
e2d663cae9 removal of *temporary* collections 2026-01-16 18:19:12 +09:00
96123d00a2 sigma update 2026-01-16 11:00:58 +09:00
Tsubasahane
4502cadaeb Fix lumina offset for WorldSheet 2026-01-12 13:58:23 +08:00
7f33b6a4ce Fixed missing symbol
"@" was missing for the LightlessClient.zip
2026-01-09 06:11:08 +00:00
61f584f059 Merge pull request 'ci-cd-rework' (#137) from ci-cd-rework into 2.0.3
Reviewed-on: #137
Reviewed-by: defnotken <defnotken@noreply.git.lightless-sync.org>
2026-01-09 05:58:21 +00:00
95d286f990 Yeet 2026-01-08 20:35:15 +00:00
choco
42d6a19db1 syncshell list cleanup 2026-01-07 01:08:28 +01:00
choco
05f7d256d7 syncshell join modal to overlay, which doesnt prevent game interaction 2026-01-07 00:54:50 +01:00
cake
058ba504cb Updated text of options 2026-01-06 15:10:15 +01:00
cake
19966f3828 Default to unsafe 2026-01-06 15:06:21 +01:00
cake
d8b9e9cf19 Splitting havok tasks. 2026-01-06 14:27:01 +01:00
cake
ad34d88336 Merged I18N and latest 2.0.3 changes 2026-01-06 13:54:04 +01:00
9167bb1afd i18n init (#135)
shouldnt break anything?

Co-authored-by: Tsubasahane <wozaiha@gmail.com>
Reviewed-on: #135
Co-authored-by: Tsubasa <tsubasa@noreply.git.lightless-sync.org>
Co-committed-by: Tsubasa <tsubasa@noreply.git.lightless-sync.org>
2026-01-06 12:51:29 +00:00
cake
5161c6bad3 Attempt fix on crash. 2026-01-06 13:50:58 +01:00
59ed03a825 replace with log in/out flags 2026-01-06 13:27:24 +09:00
ae76efedf8 Merge remote-tracking branch 'origin/2.0.3' into meow 2026-01-06 11:57:37 +09:00
0e24da75d5 MEOW MEOW MEOW 2026-01-06 11:57:01 +09:00
defnotken
ce28799db3 More checks for animations and bones. 2026-01-05 20:46:14 -06:00
defnotken
9b9010ab8e Defenses? 2026-01-05 18:57:18 -06:00
cake
032201ed9e Changed logging, last change of gameobject 2026-01-06 00:31:08 +01:00
cake
775b128cf3 Removal of parameter 2026-01-06 00:23:24 +01:00
cake
4bb8db8c03 Game object handler changes. 2026-01-06 00:22:22 +01:00
defnotken
f307c65c66 check nulls remove redundant catches. 2026-01-05 17:19:31 -06:00
defnotken
4eec363cd2 yeet some comments 2026-01-05 15:40:32 -06:00
defnotken
d00df84ed6 even more violation checks.... 2026-01-05 15:39:18 -06:00
defnotken
9048b3bd87 more checks on drawing 2026-01-05 15:07:48 -06:00
defnotken
a2ed9f8d2b Adding memory violations catches and null checks to NameString and GameObj 2026-01-05 14:48:14 -06:00
8e08da7471 Chat changes for 2.0.3 (#134)
Co-authored-by: azyges <aaaaaa@aaa.aaa>
Co-authored-by: cake <admin@cakeandbanana.nl>
Reviewed-on: #134
Reviewed-by: defnotken <defnotken@noreply.git.lightless-sync.org>
2026-01-05 19:58:10 +00:00
defnotken
3205e6e0c3 Adding AccessViolationException catch to return true for NullDrawObject 2026-01-05 10:40:31 -06:00
cake
d16e46200d Added clear of block of pap files. 2026-01-05 16:41:30 +01:00
cake
5fc13647ae Fixed name getting, cast fix on compact ui 2026-01-05 14:24:07 +01:00
cake
39d5d9d7c1 Another few fixes. 2026-01-05 01:54:19 +01:00
cake
c19db58ead Fix build error from conflict 2026-01-05 01:49:00 +01:00
30717ba200 Merged Cake and Abel branched into 2.0.3 (#131)
Co-authored-by: azyges <aaaaaa@aaa.aaa>
Co-authored-by: cake <admin@cakeandbanana.nl>
Co-authored-by: defnotken <itsdefnotken@gmail.com>
Reviewed-on: #131
2026-01-05 00:45:14 +00:00
e0b8070aa8 Merge pull request 'Lifestream IPC witrh Debug Example' (#124) from lifestream-ipc into 2.0.3
Reviewed-on: #124
2026-01-04 14:50:00 +00:00
3241b9222b Merge pull request 'Changes of admin ui for banning users.' (#128) from ban-admin-changes into 2.0.3
Reviewed-on: #128
2026-01-04 14:49:47 +00:00
80b082240f Merge branch '2.0.3' into ban-admin-changes 2026-01-04 14:49:38 +00:00
b8c8f3dffd Merge pull request 'Lightless Lightfinder redesign + stuff' (#127) from 2.0.0-crashing-bugfixes into 2.0.3
Reviewed-on: #127
2026-01-04 14:21:27 +00:00
543ea6c865 Merge branch '2.0.3' into 2.0.0-crashing-bugfixes 2026-01-04 14:19:23 +00:00
defnotken
de9c9955ef add more functionality for future features. 2026-01-04 00:54:40 -06:00
cake
2eb0c463e3 Fixed refreshing of ban list 2026-01-04 05:40:34 +01:00
cake
cd510f93af Changed banning into syncshell 2026-01-04 05:08:08 +01:00
cake
3bbda69699 Revert "Added another try on fetching download status"
This reverts commit deb7f67e59.
2026-01-03 23:22:18 +01:00
cake
deb7f67e59 Added another try on fetching download status 2026-01-03 23:12:18 +01:00
choco
9ba45670c5 top menu cleanup, removed duplicate old code 2026-01-03 02:08:28 +01:00
cake
f7bb73bcd1 Updated api 2026-01-02 18:34:07 +01:00
choco
4c07162ee3 Merge remote-tracking branch 'origin/2.0.3' into 2.0.0-crashing-bugfixes
# Conflicts:
#	LightlessAPI
2026-01-02 09:26:21 +01:00
choco
a4d62af73d lightfinder user text 2026-01-02 09:23:23 +01:00
choco
5fba3c01e7 lightfinder nearby badge alignment 2026-01-02 09:19:39 +01:00
defnotken
df33a0f0a2 Move buttons to debug 2026-01-01 17:27:12 -06:00
c439d1c822 Merge branch '2.0.3' into lifestream-ipc 2026-01-01 23:21:46 +00:00
choco
906dda3885 lightfinder nearby badge icon 2026-01-01 22:32:45 +01:00
choco
f812b6d09e own syncshell sometimes not showing in list bug 2026-01-01 22:32:34 +01:00
7e61954541 Location Sharing 2.0 (#125)
Need: Lightless-Sync/LightlessServer#49
Authored-by: Tsubasahane <wozaiha@gmail.com>
Reviewed-on: #125
Reviewed-by: cake <cake@noreply.git.lightless-sync.org>
Co-authored-by: Tsubasa <tsubasa@noreply.git.lightless-sync.org>
Co-committed-by: Tsubasa <tsubasa@noreply.git.lightless-sync.org>
2025-12-31 17:31:31 +00:00
choco
89f59a98f5 Merge remote-tracking branch 'origin/2.0.3' into 2.0.0-crashing-bugfixes 2025-12-31 09:02:55 +01:00
defnotken
fb58d8657d Lifestream IPC witrh Debug Example 2025-12-30 23:43:22 -06:00
bbb3375661 2.0.3 staaato 2025-12-31 02:44:31 +00:00
choco
e95a2c3352 Merge remote-tracking branch 'refs/remotes/origin/2.0.2' into 2.0.0-crashing-bugfixes 2025-12-30 19:32:42 +01:00
choco
a8340c3279 Merge remote-tracking branch 'origin/2.0.2-Location' into 2.0.0-crashing-bugfixes
# Conflicts:
#	LightlessSync/Services/DalamudUtilService.cs
2025-12-30 14:55:42 +01:00
Tsubasahane
e25979e089 fix Icon direction 2025-12-30 18:04:54 +08:00
Tsubasahane
ca7375b9c3 dont check location when target is offline 2025-12-30 14:42:02 +08:00
Tsubasahane
f8752fcb4d changed kanmoji to show correctly 2025-12-30 14:37:13 +08:00
Tsubasahane
d1c955c74f Reuse WorldData and make context menu work for non-Global uses 2025-12-30 14:23:37 +08:00
Tsubasahane
91e60694ad triggers update when map changes 2025-12-30 11:20:12 +08:00
Tsubasahane
f37fdefddd show icon correctly 2025-12-29 16:43:12 +08:00
Tsubasahane
18fa0a47b1 Locationshare fix 2025-12-29 15:42:55 +08:00
Tsubasahane
9f5cc9e0d1 Merge branch '2.0.2' into 2.0.2-Location 2025-12-29 14:48:07 +08:00
choco
b02db4c1e1 Merge remote-tracking branch 'origin/2.0.0-crashing-bugfixes' into 2.0.0-crashing-bugfixes
# Conflicts:
#	LightlessSync/Services/DalamudUtilService.cs
#	LightlessSync/UI/DtrEntry.cs
2025-12-28 16:56:06 +01:00
cake
d6b31ed5b9 Fixed finder again. 2025-12-28 16:55:01 +01:00
cake
9e600bfae0 Fixed merge conflicts. 2025-12-28 16:48:51 +01:00
cake
1a73d5a4d9 2.0.2 merged again 2025-12-28 16:40:47 +01:00
Tsubasahane
a933330418 Share location 2025-12-28 23:07:45 +08:00
Tsubasahane
ea34b18f40 Merge branch '2.0.2' into 2.0.2-Location 2025-12-28 13:10:17 +08:00
defnotken
67dc215e83 Merge branch '2.0.2-Location' of https://git.lightless-sync.org/Lightless-Sync/LightlessClient into 2.0.2-Location 2025-12-27 21:17:32 -06:00
defnotken
baf3869cec Merge conf 2025-12-27 21:17:26 -06:00
Tsubasahane
eeda5aeb66 Revert "Location Sharing"
This reverts commit 70745613e1.
2025-12-28 10:54:01 +08:00
choco
754df95071 Merge remote-tracking branch 'origin/2.0.2-Location' into 2.0.0-crashing-bugfixes
# Conflicts:
#	LightlessSync/UI/DtrEntry.cs
2025-12-27 23:13:20 +01:00
choco
24fca31606 join syncshell draw modal 2025-12-27 23:09:29 +01:00
choco
a99c1c01b0 Merge remote-tracking branch 'origin/2.0.2' into 2.0.0-crashing-bugfixes 2025-12-27 23:08:03 +01:00
choco
85999fab8f Merge remote-tracking branch 'origin/2.0.2' into 2.0.0-crashing-bugfixes
# Conflicts:
#	LightlessSync/LightlessConfiguration/Configurations/LightlessConfig.cs
#	LightlessSync/UI/SyncshellFinderUI.cs
#	LightlessSync/UI/TopTabMenu.cs
#	LightlessSync/WebAPI/Files/FileDownloadManager.cs
2025-12-27 20:49:20 +01:00
Tsubasahane
70745613e1 Location Sharing 2025-12-27 19:57:21 +08:00
Tsubasahane
5c8e239a7b implement playerState
- use IPlayerState for DalamudUtilService and make things less asynced
- make LocationInfo work with ContentFinderData
2025-12-27 17:04:39 +08:00
choco
5eed65149a nearby lightfinder users window, wiht pair func 2025-12-27 02:38:56 +01:00
cake
1ab4e2f94b Added color options for header 2025-12-26 22:26:29 +01:00
choco
f792bc1954 compact ui design refactor with lightfinder redesign 2025-12-26 00:00:13 +01:00
choco
ced72ab9eb icon centering changes 2025-12-24 16:59:46 +01:00
choco
6c1cc77aaa settings animated header 2025-12-23 17:36:36 +01:00
choco
5b81caf5a8 compact menu redesign with new animated particle header, enable particles toggle added in UI settings 2025-12-23 17:16:51 +01:00
choco
4e03b381dc animated header main menu redesign test 2025-12-23 00:48:47 +01:00
choco
3222133aa0 Merge branch '2.0.1' into 2.0.0-crashing-bugfixes 2025-12-23 00:36:56 +01:00
choco
0ec423e65c potential resolve disposal crashes and race conditions 2025-12-21 22:34:39 +01:00
13 changed files with 20 additions and 297 deletions

View File

@@ -1,86 +1,11 @@
tagline: "Lightless Sync v2.1.0"
subline: "Location Sharing, Animation Scanning, Sync Improvements, Lifestream IPC, and More!"
tagline: "Lightless Sync v2.0.1"
subline: "LIGHTLESS IS EVOLVING!!"
changelog:
- name: "v2.1.0"
tagline: "Happy New Year!"
date: "January 20 2026"
# be sure to set this every new version
isCurrent: true
versions:
- number: "Location Sharing (S/O to Tsubasa from the MareCN team for this feature!)"
icon: ""
items:
- "Are you TIRED of scrambling to find the address of the venue you're in to share with your friends? We are introducing Location Sharing! An optional feature where you can share your location with direct pairs temporarily [30 minutes, 1 hour, 3 hours] or until you turn it off for them. That's up to you!"
- "To share your location with a pair, click the three dots beside the pair and choose a duration to share with them."
- "To view the location of someone who's shared with you, simply hover over the globe icon!"
- number: "Model Optimization (Mesh Decimating)"
icon: ""
items:
- "This new option can automatically “simplify” incoming character meshes to help performance by reducing triangle counts. You choose how strong the reduction is (default/recommended is 80%). "
- "Decimation only kicks in when a mesh is above a certain triangle threshold, and only for the items that qualify for it and you selected for."
- "Hair meshes is always excluded, since simplifying hair meshes is very prone to breaking."
- "You can find everything under Settings → Performance → Model Optimization."
- "IF YOU HAVE USED DECIMATION IN TESTING, PLEASE CLEAR YOUR CACHE!"
- number: "Animation (PAP) Validation (Safer animations)"
icon: ""
items:
- "Lightless now checks your currently animations to see if they work with your local skeleton/bone mod. If an animation matches, its included in what gets sent to other players. If it doesnt, Lightless will skip it and write a warning to your log showing how many were skipped due to skeleton changes. Its defaulted to Unsafe (off). turn it on if you experience crashes from others users."
- "Lightless also does the same kind of check for incoming animation files, to make sure they match the body/skeleton they were sent with."
- "Because these checks can sometimes be a little picky, you can adjust how strict they are in Settings -> General -> Animation & Bones to reduce false positives."
- number: "UI Changes (Thanks to Choco for UI Changes)"
icon: ""
items:
- "The top part of the main screen has gotten a makeover. You can adjust the colors of the gradiant in the Color settings of Lightless."
- "Settings have gotten some changes as well to make this change more universal, and will use the same color settings."
- "The particle effects of the gradient are toggleable in 'Settings -> UI -> Behavior"
- "Instead of showing download/upload on bottom of Main UI, it will show VRAM usage and triangles with their optimization options next to it"
- number: "LightFinder / ShellFinder"
icon: ""
items:
- "UI Changes that follow our new design follow the color codes for the Gradient top as the main screen does."
- "A list of players using LightFinder near you is now available."
- "Improved the look of ShellFinder; a new pop-up for the join screen is included. This will be merged into more spots later."
- number: "Syncing Changes"
icon: ""
items:
- "Fixed a bottleneck that caused hitching for some users."
- "Fixed a bug where files in the downscale directory were not being deleted correctly."
- "Improved performance tracking by tracking both original and effective triangle counts."
- "Improved owned object detection."
- "Reverted collection work to old way to mitigate the syncing and VFX issues."
- "Fixed minion/mount/pet tracking to validate against player-related."
- "Added timeout support to Wait For Fully Loaded."
- "Enhanced pair handling to support model decimation. (Effective Triangles)."
- "Improved downloads through atomization."
- "Improved data management by only pushing to online pairs."
- number: "Syncshell Admin Panel changes"
icon: ""
items:
- "Changes to banned userlist to allow for preemptive banning of users."
- "Fixed when you are the owner, the buttons aren't overflowing into the side."
- "Pruning has been fixed not to include online users. It will only focus on offline users now."
- "Fixed that moderators can finally broadcast the syncshell."
- number: "Bug Fixes"
icon: ""
items:
- "Fixed a bug in the client CI/CD workflow where the plugin was contained twice in the zip. This will cut down on overall plugin size."
- "Added new flags for certain ImGUI windows to fix focusing issues with Chat2."
- "Validating PTRs for the game objects to prevent crashing while switching characters."
- number: "Lifestream Plugin integration"
icon: ""
items:
- "We have added Lifestream as an optional plugin you can install to support multiple future implementations >:3. In the near future, you'll be able to go straight to your pair using the Lifestream plugin in as easy as one click. We are also cooking something up for now; it will simply show as an optional plugin."
- "Integrated Lifestream to Location Sharing to easily teleport to all plots/apartments, and most maps."
- number: "Q1 Roadmap"
icon: ""
items:
- "Diagnostics Window - Est. Feb"
- "Ability to set a location as a 'Home' in syncshells - Est. Mid-Late Feb"
- "Lifestream support for Syncshell Homes - Est. Mid-Late Feb"
- "Community-oriented feature - In Refinement (est. Mar/Apr)"
- name: "v2.0.2"
tagline: "Last update of 2025!... ... ... If Nothing breaks"
date: "December 28 2025"
# be sure to set this every new version
isCurrent: true
versions:
- number: "Chat"
icon: ""

View File

@@ -11,8 +11,6 @@ credits:
role: "Developer"
- name: "Kenny"
role: "Developer"
- name: "Tsubasa"
role: "Developer"
- name: "Zura"
role: "Developer"
- name: "Additional Contributors"

View File

@@ -92,7 +92,7 @@ public sealed class PenumbraTexture : PenumbraBase
{
token.ThrowIfCancellationRequested();
logger.LogDebug("Converting texture {Input} -> {Output} ({Target})", job.InputFile, job.OutputFile, job.TargetType);
logger.LogInformation("Converting texture {Input} -> {Output} ({Target})", job.InputFile, job.OutputFile, job.TargetType);
var convertTask = _convertTextureFile.Invoke(job.InputFile, job.OutputFile, job.TargetType, job.IncludeMipMaps);
await convertTask.ConfigureAwait(false);

View File

@@ -3,7 +3,7 @@
<PropertyGroup>
<Authors></Authors>
<Company></Company>
<Version>2.1.0</Version>
<Version>2.0.3</Version>
<Description></Description>
<Copyright></Copyright>
<PackageProjectUrl>https://github.com/Light-Public-Syncshells/LightlessClient</PackageProjectUrl>

View File

@@ -182,12 +182,14 @@ public sealed class GameObjectHandler : DisposableMediatorSubscriberBase, IHighP
if (nextAddr != IntPtr.Zero && !PtrGuard.LooksLikePtr(nextAddr))
{
Logger.LogWarning("[{this}] _getAddress returned non-pointer: 0x{addr:X}", this, (ulong)nextAddr);
nextAddr = IntPtr.Zero;
}
if (nextAddr != IntPtr.Zero &&
!PtrGuard.IsReadable(nextAddr, (nuint)sizeof(FFXIVClientStructs.FFXIV.Client.Game.Object.GameObject)))
{
Logger.LogWarning("[{this}] Address not readable: 0x{addr:X}", this, (ulong)nextAddr);
nextAddr = IntPtr.Zero;
}

View File

@@ -125,8 +125,6 @@ public sealed class Plugin : IDalamudPlugin
services.AddSingleton<FileTransferOrchestrator>();
services.AddSingleton<LightlessPlugin>();
services.AddSingleton<LightlessProfileManager>();
services.AddSingleton<TextureProcessingQueue>();
services.AddSingleton<ModelProcessingQueue>();
services.AddSingleton<TextureCompressionService>();
services.AddSingleton<TextureDownscaleService>();
services.AddSingleton<ModelDecimationService>();

View File

@@ -1,93 +0,0 @@
using Microsoft.Extensions.Logging;
using System.Collections.Concurrent;
namespace LightlessSync.Services;
public sealed class AssetProcessingQueue : IDisposable
{
private readonly BlockingCollection<WorkItem> _queue = new();
private readonly Thread _worker;
private readonly ILogger _logger;
private bool _disposed;
public AssetProcessingQueue(ILogger logger, string name)
{
_logger = logger;
_worker = new Thread(Run)
{
IsBackground = true,
Name = string.IsNullOrWhiteSpace(name) ? "LightlessSync.AssetProcessing" : name
};
_worker.Start();
}
public Task Enqueue(Func<CancellationToken, Task> work, CancellationToken token = default)
{
if (work is null)
{
throw new ArgumentNullException(nameof(work));
}
var completion = new TaskCompletionSource<object?>(TaskCreationOptions.RunContinuationsAsynchronously);
if (token.IsCancellationRequested)
{
completion.TrySetCanceled(token);
return completion.Task;
}
if (_queue.IsAddingCompleted || _disposed)
{
completion.TrySetException(new ObjectDisposedException(nameof(AssetProcessingQueue)));
return completion.Task;
}
_queue.Add(new WorkItem(work, token, completion));
return completion.Task;
}
private void Run()
{
foreach (var item in _queue.GetConsumingEnumerable())
{
if (item.Token.IsCancellationRequested)
{
item.Completion.TrySetCanceled(item.Token);
continue;
}
try
{
item.Work(item.Token).GetAwaiter().GetResult();
item.Completion.TrySetResult(null);
}
catch (OperationCanceledException ex)
{
var token = ex.CancellationToken.IsCancellationRequested ? ex.CancellationToken : item.Token;
item.Completion.TrySetCanceled(token);
}
catch (Exception ex)
{
_logger.LogWarning(ex, "Asset processing job failed.");
item.Completion.TrySetException(ex);
}
}
}
public void Dispose()
{
if (_disposed)
{
return;
}
_disposed = true;
_queue.CompleteAdding();
_worker.Join(TimeSpan.FromSeconds(2));
_queue.Dispose();
}
private readonly record struct WorkItem(
Func<CancellationToken, Task> Work,
CancellationToken Token,
TaskCompletionSource<object?> Completion);
}

View File

@@ -2104,16 +2104,6 @@ internal static class MdlDecimator
}
}
if (boneWeights != null
&& blendWeightEncoding == BlendWeightEncoding.Default
&& format.BlendWeightsElement is { } blendWeightsElement
&& (MdlFile.VertexType)blendWeightsElement.Type == MdlFile.VertexType.UShort4
&& ShouldTreatWeightsAsByteNormalized(boneWeights))
{
RescaleUShortAsByteWeights(boneWeights);
blendWeightEncoding = BlendWeightEncoding.UShortAsByte;
}
decoded = new DecodedMeshData(positions, normals, tangents, tangents2, colors, boneWeights, uvChannels, positionWs, normalWs, blendWeightEncoding);
return true;
}
@@ -3423,44 +3413,6 @@ internal static class MdlDecimator
return ToUShortNormalized(normalized);
}
private static bool ShouldTreatWeightsAsByteNormalized(BoneWeight[] weights)
{
const float maxByteUnorm = byte.MaxValue / (float)ushort.MaxValue;
var maxWeight = 0f;
for (var i = 0; i < weights.Length; i++)
{
var weight = weights[i];
maxWeight = Math.Max(maxWeight, weight.weight0);
maxWeight = Math.Max(maxWeight, weight.weight1);
maxWeight = Math.Max(maxWeight, weight.weight2);
maxWeight = Math.Max(maxWeight, weight.weight3);
if (maxWeight > maxByteUnorm)
{
return false;
}
}
return maxWeight > 0f;
}
private static void RescaleUShortAsByteWeights(BoneWeight[] weights)
{
var scale = ushort.MaxValue / (float)byte.MaxValue;
for (var i = 0; i < weights.Length; i++)
{
var weight = weights[i];
weights[i] = new BoneWeight(
weight.index0,
weight.index1,
weight.index2,
weight.index3,
weight.weight0 * scale,
weight.weight1 * scale,
weight.weight2 * scale,
weight.weight3 * scale);
}
}
private static void NormalizeWeights(float[] weights)
{
var sum = weights.Sum();

View File

@@ -1,7 +1,6 @@
using LightlessSync.FileCache;
using LightlessSync.LightlessConfiguration;
using LightlessSync.LightlessConfiguration.Configurations;
using LightlessSync.Services;
using LightlessSync.Utils;
using Microsoft.Extensions.Logging;
using System.Collections.Concurrent;
@@ -20,7 +19,6 @@ public sealed class ModelDecimationService
private readonly FileCacheManager _fileCacheManager;
private readonly PlayerPerformanceConfigService _performanceConfigService;
private readonly XivDataStorageService _xivDataStorageService;
private readonly ModelProcessingQueue _processingQueue;
private readonly SemaphoreSlim _decimationSemaphore = new(MaxConcurrentJobs);
private readonly TaskRegistry<string> _decimationDeduplicator = new();
@@ -32,15 +30,13 @@ public sealed class ModelDecimationService
LightlessConfigService configService,
FileCacheManager fileCacheManager,
PlayerPerformanceConfigService performanceConfigService,
XivDataStorageService xivDataStorageService,
ModelProcessingQueue processingQueue)
XivDataStorageService xivDataStorageService)
{
_logger = logger;
_configService = configService;
_fileCacheManager = fileCacheManager;
_performanceConfigService = performanceConfigService;
_xivDataStorageService = xivDataStorageService;
_processingQueue = processingQueue;
}
public void ScheduleDecimation(string hash, string filePath, string? gamePath = null)
@@ -57,9 +53,9 @@ public sealed class ModelDecimationService
_logger.LogDebug("Queued model decimation for {Hash}", hash);
_decimationDeduplicator.GetOrStart(hash, () => _processingQueue.Enqueue(async token =>
_decimationDeduplicator.GetOrStart(hash, async () =>
{
await _decimationSemaphore.WaitAsync(token).ConfigureAwait(false);
await _decimationSemaphore.WaitAsync().ConfigureAwait(false);
try
{
await DecimateInternalAsync(hash, filePath).ConfigureAwait(false);
@@ -73,7 +69,7 @@ public sealed class ModelDecimationService
{
_decimationSemaphore.Release();
}
}, CancellationToken.None));
});
}
public void ScheduleBatchDecimation(string hash, string filePath, ModelDecimationSettings settings)
@@ -93,9 +89,9 @@ public sealed class ModelDecimationService
_logger.LogInformation("Queued batch model decimation for {Hash}", hash);
_decimationDeduplicator.GetOrStart(hash, () => _processingQueue.Enqueue(async token =>
_decimationDeduplicator.GetOrStart(hash, async () =>
{
await _decimationSemaphore.WaitAsync(token).ConfigureAwait(false);
await _decimationSemaphore.WaitAsync().ConfigureAwait(false);
try
{
await DecimateInternalAsync(hash, filePath, settings, allowExisting: false, destinationOverride: filePath, registerDecimatedPath: false).ConfigureAwait(false);
@@ -109,7 +105,7 @@ public sealed class ModelDecimationService
{
_decimationSemaphore.Release();
}
}, CancellationToken.None));
});
}
public bool ShouldScheduleDecimation(string hash, string filePath, string? gamePath = null)

View File

@@ -1,19 +0,0 @@
using Microsoft.Extensions.Logging;
namespace LightlessSync.Services;
public sealed class ModelProcessingQueue : IDisposable
{
private readonly AssetProcessingQueue _queue;
public ModelProcessingQueue(ILogger<ModelProcessingQueue> logger)
{
_queue = new AssetProcessingQueue(logger, "LightlessSync.ModelProcessing");
}
public Task Enqueue(Func<CancellationToken, Task> work, CancellationToken token = default)
=> _queue.Enqueue(work, token);
public void Dispose()
=> _queue.Dispose();
}

View File

@@ -8,7 +8,6 @@ using System.Threading;
using OtterTex;
using OtterImage = OtterTex.Image;
using LightlessSync.LightlessConfiguration;
using LightlessSync.Services;
using LightlessSync.Utils;
using LightlessSync.FileCache;
using Microsoft.Extensions.Logging;
@@ -34,7 +33,6 @@ public sealed class TextureDownscaleService
private readonly PlayerPerformanceConfigService _playerPerformanceConfigService;
private readonly FileCacheManager _fileCacheManager;
private readonly TextureCompressionService _textureCompressionService;
private readonly TextureProcessingQueue _processingQueue;
private readonly TaskRegistry<string> _downscaleDeduplicator = new();
private readonly ConcurrentDictionary<string, string> _downscaledPaths = new(StringComparer.OrdinalIgnoreCase);
@@ -75,15 +73,13 @@ public sealed class TextureDownscaleService
LightlessConfigService configService,
PlayerPerformanceConfigService playerPerformanceConfigService,
FileCacheManager fileCacheManager,
TextureCompressionService textureCompressionService,
TextureProcessingQueue processingQueue)
TextureCompressionService textureCompressionService)
{
_logger = logger;
_configService = configService;
_playerPerformanceConfigService = playerPerformanceConfigService;
_fileCacheManager = fileCacheManager;
_textureCompressionService = textureCompressionService;
_processingQueue = processingQueue;
}
public void ScheduleDownscale(string hash, string filePath, TextureMapKind mapKind)
@@ -94,7 +90,7 @@ public sealed class TextureDownscaleService
if (!filePath.EndsWith(".tex", StringComparison.OrdinalIgnoreCase)) return;
if (_downscaleDeduplicator.TryGetExisting(hash, out _)) return;
_downscaleDeduplicator.GetOrStart(hash, () => _processingQueue.Enqueue(async token =>
_downscaleDeduplicator.GetOrStart(hash, async () =>
{
TextureMapKind mapKind;
try
@@ -108,7 +104,7 @@ public sealed class TextureDownscaleService
}
await DownscaleInternalAsync(hash, filePath, mapKind).ConfigureAwait(false);
}, CancellationToken.None));
});
}
public bool ShouldScheduleDownscale(string filePath)
@@ -386,12 +382,6 @@ public sealed class TextureDownscaleService
{
var isCompressed = sourceFormat.IsCompressed();
var targetFormat = isCompressed ? sourceFormat : DXGIFormat.B8G8R8A8UNorm;
_logger.LogDebug(
"Downscale convert target {TargetFormat} (source {SourceFormat}, compressed {IsCompressed}, penumbraFallback {PenumbraFallback})",
targetFormat,
sourceFormat,
isCompressed,
attemptPenumbraFallback);
try
{
result = source.Convert(targetFormat);
@@ -443,7 +433,6 @@ public sealed class TextureDownscaleService
{
try
{
_logger.LogDebug("Downscale Penumbra re-encode target {Target} for {Hash}.", target, hash);
using var uncompressed = resizedScratch.Convert(DXGIFormat.B8G8R8A8UNorm);
TexFileHelper.Save(destination, uncompressed);
}

View File

@@ -1,19 +0,0 @@
using Microsoft.Extensions.Logging;
namespace LightlessSync.Services;
public sealed class TextureProcessingQueue : IDisposable
{
private readonly AssetProcessingQueue _queue;
public TextureProcessingQueue(ILogger<TextureProcessingQueue> logger)
{
_queue = new AssetProcessingQueue(logger, "LightlessSync.TextureProcessing");
}
public Task Enqueue(Func<CancellationToken, Task> work, CancellationToken token = default)
=> _queue.Enqueue(work, token);
public void Dispose()
=> _queue.Dispose();
}

View File

@@ -56,7 +56,6 @@ public class DataAnalysisUi : WindowMediatorSubscriberBase
private readonly ModelDecimationService _modelDecimationService;
private readonly TextureCompressionService _textureCompressionService;
private readonly TextureMetadataHelper _textureMetadataHelper;
private readonly TextureProcessingQueue _processingQueue;
private readonly List<TextureRow> _textureRows = new();
private readonly Dictionary<string, TextureCompressionTarget> _textureSelections = new(StringComparer.OrdinalIgnoreCase);
@@ -138,8 +137,7 @@ public class DataAnalysisUi : WindowMediatorSubscriberBase
LightlessConfigService configService,
PlayerPerformanceConfigService playerPerformanceConfig, TransientResourceManager transientResourceManager,
TransientConfigService transientConfigService, ModelDecimationService modelDecimationService,
TextureCompressionService textureCompressionService, TextureMetadataHelper textureMetadataHelper,
TextureProcessingQueue processingQueue)
TextureCompressionService textureCompressionService, TextureMetadataHelper textureMetadataHelper)
: base(logger, mediator, "Lightless Character Data Analysis", performanceCollectorService)
{
_characterAnalyzer = characterAnalyzer;
@@ -152,7 +150,6 @@ public class DataAnalysisUi : WindowMediatorSubscriberBase
_modelDecimationService = modelDecimationService;
_textureCompressionService = textureCompressionService;
_textureMetadataHelper = textureMetadataHelper;
_processingQueue = processingQueue;
Mediator.Subscribe<CharacterDataAnalyzedMessage>(this, (_) =>
{
_hasUpdate = true;
@@ -3719,10 +3716,7 @@ public class DataAnalysisUi : WindowMediatorSubscriberBase
_conversionCurrentFileProgress = 0;
_conversionFailed = false;
var conversionToken = _conversionCancellationTokenSource.Token;
_conversionTask = _processingQueue.Enqueue(
queueToken => RunTextureConversionAsync(requests, queueToken),
conversionToken);
_conversionTask = RunTextureConversionAsync(requests, _conversionCancellationTokenSource.Token);
_showModal = true;
}