From 3fd960168dc87b4c98c7a0614106c6e03bf0b766 Mon Sep 17 00:00:00 2001 From: LucHeart Date: Wed, 8 Oct 2025 17:06:52 +0200 Subject: [PATCH 1/2] make _Any react to all remote commands --- ShockOsc/Services/OscHandler.cs | 51 ++++++++++++++++++++++++++----- ShockOsc/ShockOSCModule.cs | 53 ++++++++++++++++++++------------- 2 files changed, 76 insertions(+), 28 deletions(-) diff --git a/ShockOsc/Services/OscHandler.cs b/ShockOsc/Services/OscHandler.cs index 49ba624..8d6b4ea 100644 --- a/ShockOsc/Services/OscHandler.cs +++ b/ShockOsc/Services/OscHandler.cs @@ -1,5 +1,7 @@ +using System.Collections.Concurrent; using Microsoft.Extensions.Logging; using OpenShock.Desktop.ModuleBase.Config; +using OpenShock.Desktop.ModuleBase.Models; using OpenShock.ShockOSC.Config; using OpenShock.ShockOSC.OscChangeTracker; using OpenShock.ShockOSC.Utils; @@ -13,6 +15,8 @@ public sealed class OscHandler private readonly ChangeTrackedOscParam _paramAnyCooldownPercentage; private readonly ChangeTrackedOscParam _paramAnyIntensity; + private readonly ConcurrentDictionary _lastControlLogs = new(); + private readonly ILogger _logger; private readonly OscClient _oscClient; private readonly IModuleConfig _moduleConfig; @@ -71,10 +75,11 @@ await _oscClient.SendGameMessage("/input/Voice", false) public async Task SendParams() { // TODO: maybe force resend on avatar change - var anyActive = false; + + await UpdateAnyActive(); + var anyCooldown = false; var anyCooldownPercentage = 0f; - var anyIntensity = 0f; foreach (var shocker in _shockOscData.ProgramGroups.Values) { @@ -99,16 +104,46 @@ public async Task SendParams() await shocker.ParamCooldown.SetValue(onCoolDown); await shocker.ParamCooldownPercentage.SetValue(cooldownPercentage); await shocker.ParamIntensity.SetValue(intensity); - - if (isActive) anyActive = true; + if (onCoolDown) anyCooldown = true; anyCooldownPercentage = MathF.Max(anyCooldownPercentage, cooldownPercentage); - anyIntensity = MathF.Max(anyIntensity, intensity); } - - await _paramAnyActive.SetValue(anyActive); + await _paramAnyCooldown.SetValue(anyCooldown); await _paramAnyCooldownPercentage.SetValue(anyCooldownPercentage); - await _paramAnyIntensity.SetValue(anyIntensity); } + + private async Task UpdateAnyActive() + { + var now = DateTimeOffset.UtcNow; + var anyActive = false; + var maxIntensity = 0f; + + foreach (var logEntry in _lastControlLogs.Values) + { + if(logEntry.ControlLog.Type != ControlType.Shock) continue; + var activeUntil = logEntry.Timestamp.AddMilliseconds(logEntry.ControlLog.Duration); + + if (activeUntil < now) continue; + + anyActive = true; + var intensity = MathUtils.Saturate(logEntry.ControlLog.Intensity / 100f); + maxIntensity = MathF.Max(maxIntensity, intensity); + } + + await _paramAnyActive.SetValue(anyActive); + await _paramAnyIntensity.SetValue(maxIntensity); + } + + public void SetLastControlCommand(LastControlLogEntry controlLogs) + { + _lastControlLogs[controlLogs.ControlLog.Shocker.Id] = controlLogs; + } + + public class LastControlLogEntry + { + public required DateTimeOffset Timestamp { get; set; } + public required ControlLog ControlLog { get; set; } + } + } \ No newline at end of file diff --git a/ShockOsc/ShockOSCModule.cs b/ShockOsc/ShockOSCModule.cs index 16c8efd..50ed34e 100644 --- a/ShockOsc/ShockOSCModule.cs +++ b/ShockOsc/ShockOSCModule.cs @@ -10,9 +10,11 @@ using OpenShock.ShockOSC.Services; using OpenShock.ShockOSC.Ui.Pages.Dash.Tabs; using OscQueryLibrary; + // ReSharper disable InconsistentNaming -[assembly:DesktopModule(typeof(ShockOSCModule), "openshock.shockosc", "ShockOSC")] +[assembly: DesktopModule(typeof(ShockOSCModule), "openshock.shockosc", "ShockOSC")] + namespace OpenShock.ShockOSC; public sealed class ShockOSCModule : DesktopModuleBase, IAsyncDisposable @@ -50,16 +52,14 @@ public sealed class ShockOSCModule : DesktopModuleBase, IAsyncDisposable public override async Task Setup() { - var config = await ModuleInstanceManager.GetModuleConfig(); ModuleServiceProvider = BuildServices(config); - } private IServiceProvider BuildServices(IModuleConfig config) { var loggerFactory = ModuleInstanceManager.AppServiceProvider.GetRequiredService(); - + var services = new ServiceCollection(); services.AddSingleton(loggerFactory); @@ -71,45 +71,58 @@ private IServiceProvider BuildServices(IModuleConfig config) services.AddSingleton(); services.AddSingleton(); services.AddSingleton(); - + services.AddSingleton(_ => { var listenAddress = config.Config.Osc.QuestSupport ? IPAddress.Any : IPAddress.Loopback; return new OscQueryServer("ShockOSC", listenAddress); }); - + services.AddSingleton(); services.AddSingleton(); - - + + return services.BuildServiceProvider(); - } + } public override async Task Start() { var config = ModuleServiceProvider.GetRequiredService>(); await ModuleServiceProvider.GetRequiredService().Start(); - + if (config.Config.Osc.OscQuery) ModuleServiceProvider.GetRequiredService().Start(); - + var chatboxService = ModuleServiceProvider.GetRequiredService(); + var oscHandler = ModuleServiceProvider.GetRequiredService(); - _onRemoteControlSubscription = await ModuleInstanceManager.OpenShock.Control.OnRemoteControlledShocker.SubscribeAsync(async args => - { - foreach (var controlLog in args.Logs) + _onRemoteControlSubscription = + await ModuleInstanceManager.OpenShock.Control.OnRemoteControlledShocker.SubscribeAsync(async args => { - await chatboxService.SendRemoteControlMessage(controlLog.Shocker.Name, args.Sender.Name, - args.Sender.CustomName, controlLog.Intensity, controlLog.Duration, controlLog.Type); - } - }); + // Dont do anything if there are no logs + if (args.Logs.Count <= 0) return; + + foreach (var controlLog in args.Logs) + { + await chatboxService.SendRemoteControlMessage(controlLog.Shocker.Name, args.Sender.Name, + args.Sender.CustomName, controlLog.Intensity, controlLog.Duration, controlLog.Type); + + var now = DateTimeOffset.UtcNow; + + oscHandler.SetLastControlCommand(new OscHandler.LastControlLogEntry() + { + ControlLog = controlLog, + Timestamp = now, + }); + } + }); } - + private bool _disposed; public async ValueTask DisposeAsync() { - if(_disposed) return; + if (_disposed) return; _disposed = true; if (_onRemoteControlSubscription != null) await _onRemoteControlSubscription.DisposeAsync(); From 74f62d3cad8d0e8e6926c1da098abbb3bc04101e Mon Sep 17 00:00:00 2001 From: LucHeart Date: Wed, 8 Oct 2025 17:14:59 +0200 Subject: [PATCH 2/2] update nuget packages --- ShockOsc/ShockOsc.csproj | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ShockOsc/ShockOsc.csproj b/ShockOsc/ShockOsc.csproj index 87b7c43..50faca7 100644 --- a/ShockOsc/ShockOsc.csproj +++ b/ShockOsc/ShockOsc.csproj @@ -31,12 +31,12 @@ - + - - + +