Skip to content

Commit

Permalink
0.2.0 - added runtime execution
Browse files Browse the repository at this point in the history
  • Loading branch information
ImAxel0 committed Apr 2, 2024
1 parent ac242d8 commit 14642c4
Show file tree
Hide file tree
Showing 3 changed files with 287 additions and 34 deletions.
178 changes: 178 additions & 0 deletions RedNodeLoader/PipeManager.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,178 @@
using RedLoader;
using SonsSdk;
using System;
using System.Collections.Generic;
using System.IO.Pipes;
using System.Linq;
using System.Text;
using System.Text.Json;
using System.Threading.Tasks;

namespace RedNodeLoader;

public class PipeManager
{
static List<string> _lastIds = new();
static List<string> _lastCustomEventsIds = new();

static List<LemonAction> _lastGameStart = new();
static List<LemonAction> _lastWorldUpdate = new();
static List<LemonAction> _lastUpdate = new();
static List<LemonAction> _lastFixedUpdate = new();

static readonly string _pipeName = "RedNodePipe";

public static void WaitForConnection()
{
try
{
NamedPipeServerStream pipeServer = new NamedPipeServerStream(_pipeName,
PipeDirection.In, 1, PipeTransmissionMode.Byte, PipeOptions.Asynchronous);

pipeServer.BeginWaitForConnection(new AsyncCallback(WaitForConnectionCallBack), pipeServer);
}
catch (Exception oEX)
{
RLog.Error(oEX.Message);
}
}

private static void WaitForConnectionCallBack(IAsyncResult iar)
{
try
{
NamedPipeServerStream pipeServer = (NamedPipeServerStream)iar.AsyncState;
pipeServer.EndWaitForConnection(iar);

using (StreamReader reader = new StreamReader(pipeServer))
{
try
{
// Read the length of the incoming message
int length = int.Parse(reader.ReadLine());

// Read the XML string with the specified length
char[] buffer = new char[length];
reader.Read(buffer, 0, length);
string rmod = new string(buffer, 0, length);

if (rmod == "stop")
{
CleanPreviousMod();
CreateNewServer(pipeServer);
return;
}

var modData = Serialization.GetModDataFromContent(rmod);

CleanPreviousMod();

// saving nodes id's for later cleanup
modData.OnGameStart.ForEach(connection => {
var storedId = RedNodeLoader.ResolveConnections(connection);
_lastIds.AddRange(storedId);
});

modData.OnWorldUpdate.ForEach(connection => {
var storedId = RedNodeLoader.ResolveConnections(connection);
_lastIds.AddRange(storedId);
});

modData.OnUpdate.ForEach(connection => {
var storedId = RedNodeLoader.ResolveConnections(connection);
_lastIds.AddRange(storedId);
});

modData.OnFixedUpdate.ForEach(connection => {
var storedId = RedNodeLoader.ResolveConnections(connection);
_lastIds.AddRange(storedId);
});

var eventNodesAndCustomEvents_Ids = RedNodeLoader.PopulateCustomEvents(modData);
_lastIds.AddRange(eventNodesAndCustomEvents_Ids.Item1); // nodes of custom events
_lastCustomEventsIds.AddRange(eventNodesAndCustomEvents_Ids.Item2); // custom events nodes

// subscriptions
modData.OnGameStart.ForEach(connection => {
_lastGameStart.Add(connection.Node.Execute);
SdkEvents.OnGameStart.Subscribe(connection.Node.Execute);
});

modData.OnWorldUpdate.ForEach(connection => {
_lastWorldUpdate.Add(connection.Node.Execute);
SdkEvents.OnInWorldUpdate.Subscribe(connection.Node.Execute);
});

modData.OnUpdate.ForEach(connection => {
_lastUpdate.Add(connection.Node.Execute);
GlobalEvents.OnUpdate.Subscribe(connection.Node.Execute);
});

modData.OnFixedUpdate.ForEach(connection => {
_lastFixedUpdate.Add(connection.Node.Execute);
GlobalEvents.OnFixedUpdate.Subscribe(connection.Node.Execute);
});
}
catch (Exception e)
{
RLog.Error("Error processing mod: " + e.Message);
}
}

CreateNewServer(pipeServer);
}
catch
{
return;
}
}

private static void CreateNewServer(NamedPipeServerStream pipeServer)
{
pipeServer.Close();
pipeServer = null;
pipeServer = new NamedPipeServerStream(_pipeName, PipeDirection.In,1, PipeTransmissionMode.Byte, PipeOptions.Asynchronous);
pipeServer.BeginWaitForConnection(new AsyncCallback(WaitForConnectionCallBack), pipeServer);
}

private static void CleanPreviousMod()
{
// global cleanup of used nodes
foreach (var id in _lastIds.ToList())
{
RedNodeLoader.IdNodePair.Remove(id);
_lastIds.Remove(id);
}

foreach (var id in _lastCustomEventsIds.ToList())
{
RedNodeLoader.CustomEvents.Remove(id);
_lastCustomEventsIds.Remove(id);
}

// unsubscriptions
foreach (var action in _lastGameStart.ToList())
{
SdkEvents.OnGameStart.Unsubscribe(action);
_lastGameStart.Remove(action);
}

foreach (var action in _lastWorldUpdate.ToList())
{
SdkEvents.OnInWorldUpdate.Unsubscribe(action);
_lastWorldUpdate.Remove(action);
}

foreach (var action in _lastUpdate.ToList())
{
GlobalEvents.OnUpdate.Unsubscribe(action);
_lastUpdate.Remove(action);
}

foreach (var action in _lastFixedUpdate.ToList())
{
GlobalEvents.OnFixedUpdate.Unsubscribe(action);
_lastFixedUpdate.Remove(action);
}
}
}
124 changes: 90 additions & 34 deletions RedNodeLoader/RedNodeLoader.cs
Original file line number Diff line number Diff line change
@@ -1,15 +1,18 @@
using RedLoader;
using Pathfinding;
using RedLoader;
using RedLoader.Utils;
using RedNodeLoader.EventsNodes;
using RedNodeLoader.FlowNodes;
using SonsSdk;
using System.IO.Pipes;
using UnityEngine;
using Path = System.IO.Path;

namespace RedNodeLoader;

public class RedNodeLoader : SonsMod
{
public static readonly string LoaderVersion = "0.1.0";
public static readonly string LoaderVersion = "0.2.0";

/// <summary>
/// all mods datas
Expand Down Expand Up @@ -54,29 +57,49 @@ static bool ShouldStorePair(SonsNode node)
return !node.GetType().CustomAttributes.Any(at => at.AttributeType == typeof(IsGetVariable));
}

static void ResolveConnections(NodeConnection connection)
public static List<string> ResolveConnections(NodeConnection connection)
{
List<string> stored = new();

if (connection.Node.GetType() == typeof(IfStatementNode))
{
if (!IdNodePair.ContainsKey(connection.Node.Id))
{
IdNodePair.Add(connection.Node.Id, connection.Node);
stored.Add(connection.Node.Id);
}

var allIfNodes = GetAllIfStatements((IfStatementNode)connection.Node);

foreach (var ifNode in allIfNodes)
{
ifNode.TrueBranchNodes.ForEach(node => {
if (!IdNodePair.ContainsKey(node.Id) && ShouldStorePair(node))
{
IdNodePair.Add(node.Id, node);
stored.Add(node.Id);
}
});

ifNode.FalseBranchNodes.ForEach(node => {
if (!IdNodePair.ContainsKey(node.Id) && ShouldStorePair(node))
{
IdNodePair.Add(node.Id, node);
stored.Add(node.Id);
}
});
}
}
else if (!IdNodePair.ContainsKey(connection.Node.Id) && ShouldStorePair(connection.Node))
{
IdNodePair.Add(connection.Node.Id, connection.Node);
stored.Add(connection.Node.Id);
}

return stored;
}

protected override void OnEarlyInitializeMelon()
Expand Down Expand Up @@ -133,47 +156,79 @@ protected override void OnEarlyInitializeMelon()
});

// populating all custom events for all mods
ModsData.ForEach(modData =>
foreach (var mod in ModsData)
{
modData.CustomEvents.ForEach(cEvent => {
PopulateCustomEvents(mod);
}
}

// adding the custom event to the nodes dictionary
if (!IdNodePair.ContainsKey(cEvent.Node.Id))
IdNodePair.Add(cEvent.Node.Id, cEvent.Node);
public static Tuple<List<string>, List<string>> PopulateCustomEvents(ModData modData)
{
List<string> stored = new();
List<string> storedCEvents = new();

// adding the custom event to the events dictionary
var customEvent = (CustomEventNode)cEvent.Node;
if (!CustomEvents.ContainsKey(customEvent.EventId))
CustomEvents.Add(customEvent.EventId, customEvent);
else RLog.BigError("Error", $"{modData.ModName} mod contains a {nameof(CustomEventNode)} which has the same EventId as another mod.");
modData.CustomEvents.ForEach(cEvent => {
// handling custom event
foreach (var node in customEvent.EventNodes)
// adding the custom event to the nodes dictionary
if (!IdNodePair.ContainsKey(cEvent.Node.Id))
{
IdNodePair.Add(cEvent.Node.Id, cEvent.Node);
stored.Add(cEvent.Node.Id);
}
// adding the custom event to the events dictionary
var customEvent = (CustomEventNode)cEvent.Node;
if (!CustomEvents.ContainsKey(customEvent.EventId))
{
CustomEvents.Add(customEvent.EventId, customEvent);
storedCEvents.Add(customEvent.EventId);
}
else
RLog.BigError("Error", $"{modData.ModName} mod contains a {nameof(CustomEventNode)} which has the same EventId as another mod.");
// handling custom event
foreach (var node in customEvent.EventNodes)
{
if (node.GetType() == typeof(IfStatementNode))
{
if (node.GetType() == typeof(IfStatementNode))
if (!IdNodePair.ContainsKey(node.Id))
{
var allIfNodes = GetAllIfStatements((IfStatementNode)node);
foreach (var ifNode in allIfNodes)
{
ifNode.TrueBranchNodes.ForEach(node => {
if (!IdNodePair.ContainsKey(node.Id) && ShouldStorePair(node))
IdNodePair.Add(node.Id, node);
});
IdNodePair.Add(node.Id, node);
stored.Add(node.Id);
}
ifNode.FalseBranchNodes.ForEach(node => {
var allIfNodes = GetAllIfStatements((IfStatementNode)node);
if (!IdNodePair.ContainsKey(node.Id) && ShouldStorePair(node))
IdNodePair.Add(node.Id, node);
});
}
foreach (var ifNode in allIfNodes)
{
ifNode.TrueBranchNodes.ForEach(node => {
if (!IdNodePair.ContainsKey(node.Id) && ShouldStorePair(node))
{
IdNodePair.Add(node.Id, node);
stored.Add(node.Id);
}
});
ifNode.FalseBranchNodes.ForEach(node => {
if (!IdNodePair.ContainsKey(node.Id) && ShouldStorePair(node))
{
IdNodePair.Add(node.Id, node);
stored.Add(node.Id);
}
});
}
else if (!IdNodePair.ContainsKey(node.Id) && ShouldStorePair(node))
IdNodePair.Add(node.Id, node);
}
});
else if (!IdNodePair.ContainsKey(node.Id) && ShouldStorePair(node))
{
IdNodePair.Add(node.Id, node);
stored.Add(node.Id);
}
}
});

return new Tuple<List<string>, List<string>>(stored, storedCEvents);
}

protected override void OnInitializeMod()
Expand All @@ -189,6 +244,7 @@ protected override void OnInitializeMod()
protected override void OnSdkInitialized()
{
ModListUi.Create();
PipeManager.WaitForConnection();

ModsData.ForEach(modData =>
{
Expand All @@ -207,7 +263,7 @@ protected override void OnSdkInitialized()
modData.OnFixedUpdate.ForEach(connection => {
GlobalEvents.OnFixedUpdate.Subscribe(connection.Node.Execute);
});
});
});
}

public static SonsNode GetNodeById(string id)
Expand Down
Loading

0 comments on commit 14642c4

Please sign in to comment.