Skip to content

Commit f68528a

Browse files
committed
Merge branch 'dev'
2 parents 2086f12 + 1aa4f18 commit f68528a

File tree

12 files changed

+201
-100
lines changed

12 files changed

+201
-100
lines changed

VRCOSC.Desktop/VRCOSC.Desktop.csproj

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,12 @@
66
<ApplicationIcon>game.ico</ApplicationIcon>
77
<ApplicationManifest>app.manifest</ApplicationManifest>
88
<Version>0.0.0</Version>
9-
<FileVersion>2024.102.0</FileVersion>
9+
<FileVersion>2024.220.0</FileVersion>
1010
<Title>VRCOSC</Title>
1111
<Authors>VolcanicArts</Authors>
1212
<Company>VolcanicArts</Company>
1313
<Nullable>enable</Nullable>
14-
<AssemblyVersion>2024.102.0</AssemblyVersion>
14+
<AssemblyVersion>2024.220.0</AssemblyVersion>
1515
</PropertyGroup>
1616
<ItemGroup Label="Project References">
1717
<ProjectReference Include="..\VRCOSC.Game\VRCOSC.Game.csproj" />

VRCOSC.Game/App/AppManager.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
using VRCOSC.Game.OpenVR.Metadata;
2323
using VRCOSC.Game.OSC;
2424
using VRCOSC.Game.OSC.VRChat;
25+
using VRCOSC.Game.Util;
2526

2627
namespace VRCOSC.Game.App;
2728

@@ -146,6 +147,7 @@ private void initialiseDelayedTasks()
146147
Scheduler.AddDelayed(checkForOpenVR, openvr_check_interval.TotalMilliseconds, true);
147148
Scheduler.AddDelayed(checkForVRChat, vrchat_check_interval.TotalMilliseconds, true);
148149
Scheduler.AddDelayed(checkForOscjson, oscjson_check_interval.TotalMilliseconds, true);
150+
Scheduler.AddDelayed(CurrentWorldExtractor.UpdateCurrentWorld, 2500, true);
149151
checkForOscjson();
150152
}
151153

VRCOSC.Game/Config/VRCOSCConfigManager.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ protected override void InitialiseDefaults()
3535
SetDefault(VRCOSCSetting.UIScale, 1f);
3636
SetDefault(VRCOSCSetting.StartInTray, false);
3737
SetDefault(VRCOSCSetting.TrayOnClose, false);
38+
SetDefault(VRCOSCSetting.ChatboxWorldBlock, true);
3839
}
3940
}
4041

@@ -54,5 +55,6 @@ public enum VRCOSCSetting
5455
WindowState,
5556
UIScale,
5657
StartInTray,
57-
TrayOnClose
58+
TrayOnClose,
59+
ChatboxWorldBlock
5860
}

VRCOSC.Game/Graphics/Settings/GeneralSection.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ protected override void GenerateItems()
3333
AddDropdown("Theme", "Select a theme and restart to see the effect", ConfigManager.GetBindable<VRCOSCTheme>(VRCOSCSetting.Theme));
3434
AddFloatSlider("UI Scaling", "Change the UI scale multiplier", uiScaleBindableNumber);
3535
AddTextBox<IntTextBox, int>("ChatBox Update Rate", "The ChatBox update rate (milliseconds)", ConfigManager.GetBindable<int>(VRCOSCSetting.ChatBoxTimeSpan), chatbox_timespan_url);
36+
AddToggle("ChatBox Blacklist", "Blocks the ChatBox from being used when in common club/event worlds", ConfigManager.GetBindable<bool>(VRCOSCSetting.ChatboxWorldBlock), "https://github.com/cyberkitsune/chatbox-club-blacklist/blob/master/npblacklist.json");
3637
AddToggle("Tray on close", "Tells VRCOSC to minimise to the tray when the X is pressed", ConfigManager.GetBindable<bool>(VRCOSCSetting.TrayOnClose));
3738
}
3839
}

VRCOSC.Game/Managers/ChatBoxManager.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
using VRCOSC.Game.ChatBox.Serialisation.V1;
1515
using VRCOSC.Game.OSC.VRChat;
1616
using VRCOSC.Game.Serialisation;
17+
using VRCOSC.Game.Util;
1718

1819
namespace VRCOSC.Game.Managers;
1920

@@ -146,7 +147,7 @@ public Clip CreateClip()
146147

147148
public void Update()
148149
{
149-
if (sendAllowed)
150+
if (sendAllowed && !CurrentWorldExtractor.IsCurrentWorldBlacklisted)
150151
{
151152
appManager.ModuleManager.ChatBoxUpdate();
152153

VRCOSC.Game/Modules/Module.cs

Lines changed: 29 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -446,37 +446,44 @@ protected void SendParameter<T>(Enum lookup, T value) where T : struct
446446

447447
internal virtual void OnParameterReceived(VRChatOscMessage message)
448448
{
449-
var receivedParameter = new ReceivedParameter(message.ParameterName, message.ParameterValue);
450-
451449
try
452450
{
453-
OnAnyParameterReceived(receivedParameter);
454-
}
455-
catch (Exception e)
456-
{
457-
PushException(e);
458-
}
451+
var receivedParameter = new ReceivedParameter(message.ParameterName, message.ParameterValue);
459452

460-
var parameterName = Parameters.Values.FirstOrDefault(moduleParameter => parameterNameRegex[moduleParameter.ParameterName].IsMatch(receivedParameter.Name))?.ParameterName;
461-
if (parameterName is null) return;
453+
try
454+
{
455+
OnAnyParameterReceived(receivedParameter);
456+
}
457+
catch (Exception e)
458+
{
459+
PushException(e);
460+
}
462461

463-
if (!parameterNameEnum.TryGetValue(parameterName, out var lookup)) return;
462+
var parameterName = Parameters.Values.FirstOrDefault(moduleParameter => parameterNameRegex[moduleParameter.ParameterName].IsMatch(receivedParameter.Name))?.ParameterName;
463+
if (string.IsNullOrEmpty(parameterName)) return;
464464

465-
var parameterData = Parameters[lookup];
465+
if (!parameterNameEnum.TryGetValue(parameterName, out var lookup)) return;
466466

467-
if (!parameterData.Mode.HasFlagFast(ParameterMode.Read)) return;
467+
var parameterData = Parameters[lookup];
468468

469-
if (!receivedParameter.IsValueType(parameterData.ExpectedType))
470-
{
471-
Log($"Cannot accept input parameter. `{lookup}` expects type `{parameterData.ExpectedType}` but received type `{receivedParameter.Value.GetType()}`");
472-
return;
473-
}
469+
if (!parameterData.Mode.HasFlagFast(ParameterMode.Read)) return;
474470

475-
var registeredParameter = new RegisteredParameter(receivedParameter, lookup, parameterData);
471+
if (!receivedParameter.IsValueType(parameterData.ExpectedType))
472+
{
473+
Log($"Cannot accept input parameter. `{lookup}` expects type `{parameterData.ExpectedType}` but received type `{receivedParameter.Value.GetType()}`");
474+
return;
475+
}
476476

477-
try
478-
{
479-
ModuleParameterReceived(registeredParameter);
477+
var registeredParameter = new RegisteredParameter(receivedParameter, lookup, parameterData);
478+
479+
try
480+
{
481+
ModuleParameterReceived(registeredParameter);
482+
}
483+
catch (Exception e)
484+
{
485+
PushException(e);
486+
}
480487
}
481488
catch (Exception e)
482489
{

VRCOSC.Game/OSC/VRChat/VRChatOscMessage.cs

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
// Copyright (c) VolcanicArts. Licensed under the GPL-3.0 License.
22
// See the LICENSE file in the repository root for full license text.
33

4+
using System;
45
using VRCOSC.Game.OSC.Client;
56

67
namespace VRCOSC.Game.OSC.VRChat;
@@ -11,7 +12,22 @@ public class VRChatOscMessage : OscMessage
1112
public bool IsAvatarParameter => Address.StartsWith(VRChatOscConstants.ADDRESS_AVATAR_PARAMETERS_PREFIX);
1213

1314
private string? parameterName;
14-
public string ParameterName => parameterName ??= Address[(VRChatOscConstants.ADDRESS_AVATAR_PARAMETERS_PREFIX.Length + 1)..];
15+
16+
public string ParameterName
17+
{
18+
get
19+
{
20+
try
21+
{
22+
return parameterName ??= Address[(VRChatOscConstants.ADDRESS_AVATAR_PARAMETERS_PREFIX.Length + 1)..];
23+
}
24+
// This should never be possible if ParameterName is only called after IsAvatarParameter, but sometimes there's a corrupt address?
25+
catch (Exception)
26+
{
27+
return string.Empty;
28+
}
29+
}
30+
}
1531

1632
public object ParameterValue => Values[0];
1733

Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
// Copyright (c) VolcanicArts. Licensed under the GPL-3.0 License.
2+
// See the LICENSE file in the repository root for full license text.
3+
4+
using System;
5+
using System.Collections.Generic;
6+
using System.IO;
7+
using System.Linq;
8+
using System.Net.Http;
9+
using System.Text.RegularExpressions;
10+
using System.Threading.Tasks;
11+
using Newtonsoft.Json;
12+
using osu.Framework.Logging;
13+
14+
namespace VRCOSC.Game.Util;
15+
16+
public static class CurrentWorldExtractor
17+
{
18+
private const string blacklist_url = "https://github.com/cyberkitsune/chatbox-club-blacklist/raw/master/npblacklist.json";
19+
private static readonly string logfile_location = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData).Replace("Roaming", "LocalLow"), "VRChat", "VRChat");
20+
private const string logfile_pattern = "output_log_*";
21+
private static readonly Regex world_regex = new("Fetching world information for (wrld_.*)");
22+
23+
private static Blacklist? blacklist;
24+
private static IEnumerable<string>? ids;
25+
26+
public static bool IsCurrentWorldBlacklisted { get; private set; }
27+
public static string? CurrentWorldId { get; private set; }
28+
29+
public static async void UpdateCurrentWorld()
30+
{
31+
await requestBlacklist();
32+
33+
if (blacklist is null || ids is null)
34+
{
35+
IsCurrentWorldBlacklisted = false;
36+
return;
37+
}
38+
39+
var newCurrentWorldId = await getCurrentWorldId();
40+
if (newCurrentWorldId == CurrentWorldId) return;
41+
42+
CurrentWorldId = newCurrentWorldId;
43+
Logger.Log($"World change detected: {CurrentWorldId}");
44+
45+
if (CurrentWorldId is null)
46+
{
47+
IsCurrentWorldBlacklisted = false;
48+
return;
49+
}
50+
51+
IsCurrentWorldBlacklisted = ids.Contains(CurrentWorldId);
52+
Logger.Log($"Is world blacklisted?: {IsCurrentWorldBlacklisted}");
53+
}
54+
55+
private static async Task requestBlacklist()
56+
{
57+
try
58+
{
59+
if (blacklist is not null) return;
60+
61+
using var client = new HttpClient();
62+
63+
var response = await client.GetAsync(blacklist_url);
64+
response.EnsureSuccessStatusCode();
65+
66+
var content = await response.Content.ReadAsStringAsync();
67+
blacklist = JsonConvert.DeserializeObject<Blacklist>(content);
68+
if (blacklist is null) return;
69+
70+
ids = blacklist.Worlds.Select(world => world.ID);
71+
}
72+
catch (Exception)
73+
{
74+
blacklist = null;
75+
ids = null;
76+
}
77+
}
78+
79+
private static async Task<string?> getCurrentWorldId()
80+
{
81+
try
82+
{
83+
var logFile = Directory.GetFiles(logfile_location, logfile_pattern).MaxBy(d => new FileInfo(d).CreationTime);
84+
if (logFile is null) return null;
85+
86+
using var fileStream = new FileStream(logFile, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
87+
using var textReader = new StreamReader(fileStream);
88+
var content = await textReader.ReadToEndAsync();
89+
90+
var latestWorld = world_regex.Matches(content).LastOrDefault()?.Groups.Values.LastOrDefault();
91+
if (latestWorld is null) return null;
92+
93+
var latestWorldId = latestWorld.Captures.FirstOrDefault();
94+
if (latestWorldId is null) return null;
95+
96+
return latestWorldId.Value;
97+
}
98+
catch (Exception)
99+
{
100+
return null;
101+
}
102+
}
103+
}
104+
105+
public class Blacklist
106+
{
107+
[JsonProperty("worlds")]
108+
public List<BlacklistedWorld> Worlds = new();
109+
}
110+
111+
public class BlacklistedWorld
112+
{
113+
[JsonProperty("id")]
114+
public string ID = null!;
115+
}

VRCOSC.Game/VRCOSC.Game.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
<Nullable>enable</Nullable>
55
<LangVersion>11</LangVersion>
66
<PackageId>VolcanicArts.VRCOSC.SDK</PackageId>
7-
<Version>2023.1007.0</Version>
7+
<Version>2024.220.0</Version>
88
<Title>VRCOSC SDK</Title>
99
<Authors>VolcanicArts</Authors>
1010
<Description>SDK for creating custom modules with VRCOSC</Description>

VRCOSC.Modules/Maths/MathsModule.cs

Lines changed: 2 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@ namespace VRCOSC.Modules.Maths;
1313
[ModuleAuthor("VolcanicArts")]
1414
public class MathsModule : AvatarModule
1515
{
16-
private readonly Dictionary<string, ReceivedParameter> parameterValues = new();
1716
private readonly Dictionary<string, MathsEquationInstance> instances = new();
1817
private readonly List<PrimitiveElement> elements = new();
1918

@@ -37,7 +36,6 @@ protected override void CreateAttributes()
3736

3837
protected override void OnModuleStart()
3938
{
40-
parameterValues.Clear();
4139
instances.Clear();
4240
elements.Clear();
4341

@@ -50,11 +48,9 @@ protected override void OnModuleStart()
5048

5149
protected override async void OnAnyParameterReceived(ReceivedParameter parameter)
5250
{
53-
parameterValues[parameter.Name] = parameter;
54-
5551
if (!instances.TryGetValue(parameter.Name, out var instance)) return;
5652

57-
var expression = new Expression(instance.Equation.Value, parameterValues.Values.Select(createArgumentForParameterValue).Concat(elements).ToArray());
53+
var expression = new Expression(instance.Equation.Value, elements.ToArray());
5854
expression.disableImpliedMultiplicationMode();
5955

6056
foreach (var missingArgument in expression.getMissingUserDefinedArguments())
@@ -89,15 +85,6 @@ protected override async void OnAnyParameterReceived(ReceivedParameter parameter
8985
SendParameter(instance.OutputParameter.Value, finalValue);
9086
}
9187

92-
private static PrimitiveElement createArgumentForParameterValue(ReceivedParameter parameter)
93-
{
94-
if (parameter.IsValueType<bool>()) return new Argument(parameter.Name, parameter.ValueAs<bool>() ? 1 : 0);
95-
if (parameter.IsValueType<int>()) return new Argument(parameter.Name, parameter.ValueAs<int>());
96-
if (parameter.IsValueType<float>()) return new Argument(parameter.Name, parameter.ValueAs<float>());
97-
98-
throw new InvalidOperationException("Unknown parameter type");
99-
}
100-
10188
private object convertToOutputType(double value, TypeCode valueType)
10289
{
10390
try
@@ -112,7 +99,7 @@ private object convertToOutputType(double value, TypeCode valueType)
11299
}
113100
catch (Exception e)
114101
{
115-
Log($"Warning. Value {value}. " + e.Message);
102+
Log($"Output error for value '{value}': '{e.Message}'");
116103

117104
return valueType switch
118105
{

0 commit comments

Comments
 (0)