Skip to content

Commit a2474c5

Browse files
committed
Initial Commit - 1.0.0 - We can do math in Resonite now!
1 parent c755099 commit a2474c5

4 files changed

Lines changed: 214 additions & 0 deletions

File tree

Numantics.sln

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
2+
Microsoft Visual Studio Solution File, Format Version 12.00
3+
# Visual Studio Version 17
4+
VisualStudioVersion = 17.9.34728.123
5+
MinimumVisualStudioVersion = 10.0.40219.1
6+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "R-Numantics", "Numantics\R-Numantics.csproj", "{659110F4-88CB-4FF4-A510-08BB64DB6ACD}"
7+
EndProject
8+
Global
9+
GlobalSection(SolutionConfigurationPlatforms) = preSolution
10+
Debug|Any CPU = Debug|Any CPU
11+
Release|Any CPU = Release|Any CPU
12+
EndGlobalSection
13+
GlobalSection(ProjectConfigurationPlatforms) = postSolution
14+
{659110F4-88CB-4FF4-A510-08BB64DB6ACD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
15+
{659110F4-88CB-4FF4-A510-08BB64DB6ACD}.Debug|Any CPU.Build.0 = Debug|Any CPU
16+
{659110F4-88CB-4FF4-A510-08BB64DB6ACD}.Release|Any CPU.ActiveCfg = Release|Any CPU
17+
{659110F4-88CB-4FF4-A510-08BB64DB6ACD}.Release|Any CPU.Build.0 = Release|Any CPU
18+
EndGlobalSection
19+
GlobalSection(SolutionProperties) = preSolution
20+
HideSolutionNode = FALSE
21+
EndGlobalSection
22+
GlobalSection(ExtensibilityGlobals) = postSolution
23+
SolutionGuid = {3233EE7F-A063-4809-BB99-E11F485CD842}
24+
EndGlobalSection
25+
EndGlobal

Numantics/Numantics.cs

Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
using System;
2+
using System.Reflection;
3+
using Elements.Core;
4+
using FrooxEngine;
5+
using FrooxEngine.Undo;
6+
using HarmonyLib;
7+
using ResoniteModLoader;
8+
using System.Globalization;
9+
using System.Data;
10+
11+
namespace Numantics {
12+
public class Numantics : ResoniteMod {
13+
internal const string VERSION_CONSTANT = "1.0.0";
14+
public override string Name => "Numantics";
15+
public override string Author => "NalaTheThird";
16+
public override string Version => VERSION_CONSTANT;
17+
public override string Link => "https://github.com/nalathethird/R-Numantics";
18+
19+
[AutoRegisterConfigKey]
20+
private static readonly ModConfigurationKey<bool> EnableValueFieldMath =
21+
new ModConfigurationKey<bool>("enable_math", "Enable math processing in input fields", () => true);
22+
23+
[AutoRegisterConfigKey]
24+
private static readonly ModConfigurationKey<bool> IncludeStrings =
25+
new ModConfigurationKey<bool>("include_strings", "Allow math to be calculated in string fields - slightly dangerous, be careful!", () => false);
26+
27+
[AutoRegisterConfigKey]
28+
private static readonly ModConfigurationKey<bool> VerboseLogging =
29+
new ModConfigurationKey<bool>("verbose_logging", "Enable verbose logging for debugging", () => false);
30+
31+
private static ModConfiguration Config;
32+
33+
public override void OnEngineInit() {
34+
Config = GetConfiguration();
35+
Config.Save(true);
36+
37+
var harmony = new Harmony("com.nalathethird.Numantics");
38+
harmony.PatchAll();
39+
Msg("Harmony patches applied - happy mathing!");
40+
}
41+
42+
[HarmonyPatch(typeof(TextEditor))]
43+
[HarmonyPatch("OnFinished")]
44+
class TextEditor_OnFinished_Patch {
45+
static void Prefix(TextEditor __instance) {
46+
try {
47+
bool verbose = Config?.GetValue(VerboseLogging) ?? false;
48+
49+
if (verbose) Msg("OnFinished called");
50+
51+
if (__instance?.Text?.Target == null) {
52+
if (verbose) Msg("TextEditor or Text.Target is null, skipping");
53+
return;
54+
}
55+
56+
if (Config == null) {
57+
Warn("Config is null, cannot proceed");
58+
return;
59+
}
60+
61+
if (!Config.GetValue(EnableValueFieldMath)) {
62+
if (verbose) Msg("Math evaluation is disabled in config");
63+
return;
64+
}
65+
66+
string text = __instance.Text.Target.Text;
67+
if (verbose) Msg($"Input text: '{text}'");
68+
69+
if (string.IsNullOrWhiteSpace(text)) {
70+
if (verbose) Msg("Text is null or whitespace, skipping");
71+
return;
72+
}
73+
74+
string exprText = text
75+
.Replace("x", "*")
76+
.Replace("d", "/")
77+
.Replace("a", "+")
78+
.Replace("s", "-");
79+
80+
if (verbose && exprText != text) {
81+
Msg($" Replaced operators: '{text}' => '{exprText}'");
82+
}
83+
84+
if (TryEvaluateExpression(exprText, out string result, verbose)) {
85+
Msg($"SUCCESS - Evaluated '{text}' => '{result}'");
86+
87+
__instance.Text.Target.Text = result;
88+
89+
if (verbose) Msg($"Updated Text.Target.Text to '{result}'");
90+
} else {
91+
if (verbose) Msg($"Not a math expression or evaluation failed: '{exprText}'");
92+
}
93+
} catch (Exception e) {
94+
Error($"Exception in OnFinished patch: {e.Message}");
95+
Error($"Stack trace: {e.StackTrace}");
96+
}
97+
}
98+
99+
private static bool TryEvaluateExpression(string input, out string result, bool verbose) {
100+
result = input;
101+
102+
if (!(input.Contains("+") || input.Contains("-") || input.Contains("*") || input.Contains("/"))) {
103+
if (verbose) Msg("No math operators found in input");
104+
return false;
105+
}
106+
107+
try {
108+
if (verbose) Msg($"Attempting to parse expression: '{input}'");
109+
var table = new DataTable();
110+
var evaluated = table.Compute(input, "");
111+
double resultValue = Convert.ToDouble(evaluated);
112+
113+
if (verbose) Msg($"Evaluated to: {resultValue}");
114+
115+
result = resultValue.ToString(CultureInfo.InvariantCulture);
116+
return true;
117+
} catch (Exception ex) {
118+
Warn($"Expression evaluation failed for '{input}': {ex.Message}");
119+
if (verbose) Warn($"Exception type: {ex.GetType().Name}");
120+
return false;
121+
}
122+
}
123+
}
124+
}
125+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
using System.Reflection;
2+
3+
[assembly: AssemblyTitle("Numantics")]
4+
[assembly: AssemblyProduct("Numantics")]
5+
[assembly: AssemblyDescription("A Resonite mod to calculate numerical values using symbols to equal a final value (ie. 5x4 - 30)")]
6+
[assembly: AssemblyCompany("NalaTheThird")]
7+
[assembly: AssemblyCopyright("Copyright © 2025 NalaTheThird")]
8+
[assembly: AssemblyVersion(Numantics.Numantics.VERSION_CONSTANT)]
9+
[assembly: AssemblyFileVersion(Numantics.Numantics.VERSION_CONSTANT)]

Numantics/R-Numantics.csproj

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
<PropertyGroup>
3+
<RootNamespace>Numantics</RootNamespace>
4+
<AssemblyName>Numantics</AssemblyName>
5+
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
6+
<TargetFramework>net9.0</TargetFramework>
7+
<FileAlignment>512</FileAlignment>
8+
<LangVersion>12.0</LangVersion>
9+
<Nullable>enable</Nullable>
10+
<Deterministic>true</Deterministic>
11+
<!-- Change CopyToMods to true if you'd like builds to be moved into the Mods folder automatically-->
12+
<CopyToMods Condition="'$(CopyToMods)'==''">true</CopyToMods>
13+
<DebugType Condition="'$(Configuration)'=='Debug'">embedded</DebugType>
14+
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
15+
</PropertyGroup>
16+
17+
<PropertyGroup Condition="'$(ResonitePath)'==''">
18+
<!-- If you don't want to provide a ResonitePath in dotnet build, you can specify one here -->
19+
<ResonitePath>$(MSBuildThisFileDirectory)Resonite/</ResonitePath>
20+
<ResonitePath Condition="Exists('E:\SteamLibrary\steamapps\common\Resonite\')">E:\SteamLibrary\steamapps\common\Resonite\</ResonitePath>
21+
<ResonitePath Condition="Exists('$(HOME)/.steam/steam/steamapps/common/Resonite/')">$(HOME)/.steam/steam/steamapps/common/Resonite/</ResonitePath>
22+
</PropertyGroup>
23+
24+
<ItemGroup>
25+
<Compile Remove="EngineRefs\**" />
26+
<EmbeddedResource Remove="EngineRefs\**" />
27+
<None Remove="EngineRefs\**" />
28+
</ItemGroup>
29+
30+
<ItemGroup>
31+
<None Remove=".txt" />
32+
</ItemGroup>
33+
34+
<ItemGroup>
35+
<Reference Include="0Harmony">
36+
<HintPath>E:\SteamLibrary\steamapps\common\Resonite\rml_libs\0Harmony.dll</HintPath>
37+
</Reference>
38+
<Reference Include="Elements.Core">
39+
<HintPath>E:\SteamLibrary\steamapps\common\Resonite\Elements.Core.dll</HintPath>
40+
</Reference>
41+
<Reference Include="FrooxEngine">
42+
<HintPath>E:\SteamLibrary\steamapps\common\Resonite\FrooxEngine.dll</HintPath>
43+
</Reference>
44+
<Reference Include="Renderite.Shared">
45+
<HintPath>E:\SteamLibrary\steamapps\common\Resonite\Renderite.Shared.dll</HintPath>
46+
</Reference>
47+
<Reference Include="ResoniteModLoader">
48+
<HintPath>E:\SteamLibrary\steamapps\common\Resonite\Libraries\ResoniteModLoader.dll</HintPath>
49+
</Reference>
50+
</ItemGroup>
51+
<Target Name="PostBuild" AfterTargets="PostBuildEvent" Condition="'$(CopyToMods)'=='true'">
52+
<Message Text="Attempting to copy $(TargetFileName) to $(ResonitePath)rml_mods" Importance="high" />
53+
<Copy SourceFiles="$(TargetDir)$(TargetFileName)" DestinationFolder="$(ResonitePath)rml_mods" ContinueOnError="true" />
54+
</Target>
55+
</Project>

0 commit comments

Comments
 (0)