Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add SoloTogether and BunnyExtinction #6

Open
wants to merge 26 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
b230b04
Fullmetal: Fixed toybox crash
MicrowaveBunny Sep 5, 2024
3cceff0
SoloTogether: Added SoloTogether
MicrowaveBunny Sep 5, 2024
f873b2d
[Hyperbolic+] Added
MicrowaveBunny Sep 8, 2024
034db27
Hyperbolic+: Added support for basic patterns
MicrowaveBunny Sep 9, 2024
6d33406
Hyperbolic+: Organized all bps
MicrowaveBunny Sep 10, 2024
dcd2eba
Hyperbolic+: Added basic patterns
MicrowaveBunny Sep 13, 2024
5f0c408
BEX: Added BEX
MicrowaveBunny Sep 13, 2024
637b3c3
H+: Added Bullet Time Compatibility
MicrowaveBunny Sep 13, 2024
7d9afe2
H+: Added new mix support
MicrowaveBunny Sep 13, 2024
4e8344e
H+: Timed All Boss Mixes
MicrowaveBunny Sep 13, 2024
834bcec
BEX: Fixed duplicate revive hook
MicrowaveBunny Sep 14, 2024
a17f342
BEX: Fixed diffswitch issue
MicrowaveBunny Sep 18, 2024
39cde2d
BEX: limited item hp
MicrowaveBunny Sep 18, 2024
c6fa165
BEX: Lowered max speed
MicrowaveBunny Sep 18, 2024
0b79232
Updated README's
MicrowaveBunny Sep 18, 2024
ca39284
FM: Cleaning up hooks
MicrowaveBunny Sep 18, 2024
6e2d632
BEX: Added an InBattle flag
MicrowaveBunny Sep 18, 2024
c3a4746
BEX: Added Steelheart compatibility
MicrowaveBunny Sep 19, 2024
8c7de40
Cleanup Config Setup
MicrowaveBunny Sep 19, 2024
0c334e0
BEX: Limit multSpeed
MicrowaveBunny Sep 19, 2024
4873f8f
BEX: Fixed invuln bugs
MicrowaveBunny Sep 19, 2024
aa1c46f
BEX: Fixed multiplayer crash
MicrowaveBunny Sep 20, 2024
425feb8
FM: Fix generation
MicrowaveBunny Sep 20, 2024
77ad5a5
ST: Fix config update
MicrowaveBunny Sep 28, 2024
f04fef5
BEX: Fix invuln procs
MicrowaveBunny Sep 28, 2024
f1e86d1
ST: Update version number
MicrowaveBunny Sep 28, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions RNSReloaded.BunnyExtinction/Config/Config.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
using System.ComponentModel;

namespace RNSReloaded.BunnyExtinction.Config;

public class Config : Configurable<Config> {
[DisplayName("Infernal BBQ")]
[Description("Enables extra challenges. For players seeking extreme, merciless thrills. Or masochists")]
[DefaultValue(false)]
public bool InfernalBBQ { get; set; } = false;
}
99 changes: 99 additions & 0 deletions RNSReloaded.BunnyExtinction/Config/Configurable.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
using System.ComponentModel;
using System.Diagnostics;
using System.Text.Json;
using System.Text.Json.Serialization;
using Reloaded.Mod.Interfaces;

namespace RNSReloaded.BunnyExtinction.Config;

// ReSharper disable StaticMemberInGenericType
public class Configurable<TParentType> : IUpdatableConfigurable where TParentType : Configurable<TParentType>, new() {
public static JsonSerializerOptions SerializerOptions { get; } = new JsonSerializerOptions() {
Converters = {new JsonStringEnumConverter()},
WriteIndented = true
};

[Browsable(false)] public event Action<IUpdatableConfigurable>? ConfigurationUpdated;
[JsonIgnore] [Browsable(false)] public string? FilePath { get; private set; }
[JsonIgnore] [Browsable(false)] public string? ConfigName { get; private set; }
[JsonIgnore] [Browsable(false)] private FileSystemWatcher? ConfigWatcher { get; set; }

private void Initialize(string filePath, string configName) {
this.FilePath = filePath;
this.ConfigName = configName;

this.MakeConfigWatcher();
this.Save = this.OnSave;
}

public void DisposeEvents() {
this.ConfigWatcher?.Dispose();
this.ConfigurationUpdated = null;
}

[JsonIgnore] [Browsable(false)] public Action? Save { get; private set; }
[Browsable(false)] private static readonly object ReadLock = new object();

public static TParentType FromFile(string filePath, string configName) => ReadFrom(filePath, configName);

private void MakeConfigWatcher() {
this.ConfigWatcher =
new FileSystemWatcher(Path.GetDirectoryName(this.FilePath)!, Path.GetFileName(this.FilePath)!);
this.ConfigWatcher.Changed += (_, _) => this.OnConfigurationUpdated();
this.ConfigWatcher.EnableRaisingEvents = true;
}

private void OnConfigurationUpdated() {
lock (ReadLock) {
// Note: External program might still be writing to file while this is being executed, so we need to keep retrying.
var newConfig = TryGetValue(() => ReadFrom(this.FilePath!, this.ConfigName!), 250, 2);
newConfig.ConfigurationUpdated = this.ConfigurationUpdated;

this.DisposeEvents();

newConfig.ConfigurationUpdated?.Invoke(newConfig);
}
}

private void OnSave() {
var parent = (TParentType) this;
File.WriteAllText(this.FilePath!, JsonSerializer.Serialize(parent, SerializerOptions));
}

private static TParentType ReadFrom(string filePath, string configName) {
var result = (File.Exists(filePath)
? JsonSerializer.Deserialize<TParentType>(File.ReadAllBytes(filePath), SerializerOptions)
: new TParentType()) ?? new TParentType();

result.Initialize(filePath, configName);
return result;
}

private static T TryGetValue<T>(Func<T> getValue, int timeout, int sleepTime, CancellationToken token = default)
where T : new() {
var watch = new Stopwatch();
watch.Start();
var valueSet = false;
var value = new T();

while (watch.ElapsedMilliseconds < timeout) {
if (token.IsCancellationRequested)
return value;

try {
value = getValue();
valueSet = true;
break;
} catch (Exception) {
// ignored
}

Thread.Sleep(sleepTime);
}

if (valueSet == false)
throw new Exception($"Timeout limit {timeout} exceeded.");

return value;
}
}
51 changes: 51 additions & 0 deletions RNSReloaded.BunnyExtinction/Config/Configurator.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
using Reloaded.Mod.Interfaces;

namespace RNSReloaded.BunnyExtinction.Config;

public class Configurator : IConfiguratorV3 {
public string? ModFolder { get; private set; }
public string? ConfigFolder { get; private set; }
public ConfiguratorContext Context { get; private set; }
public IUpdatableConfigurable[] Configurations => this.configurations ?? this.MakeConfigurations();

private IUpdatableConfigurable[]? configurations;

private IUpdatableConfigurable[] MakeConfigurations() {
var filePath = Path.Combine(this.ConfigFolder!, "Config.json");
const string configName = "Default Config";

this.configurations = [Configurable<Config>.FromFile(filePath, configName)];

// Add self-updating to configurations.
for (var x = 0; x < this.Configurations.Length; x++) {
var xCopy = x;
this.Configurations[x].ConfigurationUpdated += configurable => {
this.Configurations[xCopy] = configurable;
};
}

return this.configurations;
}

public Configurator() { }
public Configurator(string configDirectory) : this() {
this.ConfigFolder = configDirectory;
}

public void Migrate(string oldDirectory, string newDirectory) { }

public TType GetConfiguration<TType>(int index) => (TType) this.Configurations[index];

public void SetConfigDirectory(string configDirectory) => this.ConfigFolder = configDirectory;

public void SetContext(in ConfiguratorContext context) => this.Context = context;

// ReSharper disable once CoVariantArrayConversion
public IConfigurable[] GetConfigurations() => this.Configurations;

public bool TryRunCustomConfiguration() => false;

public void SetModDirectory(string modDirectory) {
this.ModFolder = modDirectory;
}
}
Loading