Releases: Cecil-Libraries/Cecil-Bridge
v1.0.0
NUGET Package Link: https://www.nuget.org/packages/Cecil.Bridge
Changelog
Initial Release
THIS VERSIONS README;
Cecil Bridge
Copyright 2026 Cecil Libraries Organization and the Founder(s) Chaosyr
FAQ's/Project Intro
What is Cecil Libraries?
Cecil Libraries are a group of libraries in which extend functionality to many API and provide utilities as a Pseudo-API for several necessity's.
Who is Cecil?
Both a Member of the Vessel Chaosyr, and the Mascot of our Libraries. Mascot wise she is as originally described by Chaosyr "10ft tall, raven, succubus, whom is Bi, Poly, and a Femboy". That's as far as we are with her at the moment, if more details arrive it will be on the Organizations main page, figured we'd fill in for the case anyone's wondering what the logo stems from.
What is this Library for?
This library is primarily for enabling the ability to send messages back and forth between 2 different runtimes. This is intended for usage in the case where you need Modern API's back in a runtime using a severely outdated net version. For example, in the case where you need DSharp+ [net9.0 library] in a BepInEx mod [in this example on netframework3.5]. It's pretty simple to do and use, as long as you have a way of mapping paths for both ends so they can communicate, and having a way they can reach a text file that they would both read, note the library in present wont make the file.
Library Documentation (Bridge)
This will probably be easier to navigate through in the GitHub's Wiki, however this will just be as in depth as the Wiki will be, so everything you need will be within this very file, the Code is also fully commented if you wish to jump straight into coding. If any explanations are weaker than other let us know so we can fix it up!
Initializing a Sender
To initialize a Sender, all you really need is a Path to the other end that you are intending to reach. But let me explain how the Sender is utilized within the Messenger system. The Sender affectively is a path associated with the question of Where do we send the message off to. It's an Object so that it can more easily be changed and for the case that it would be good to have functions under the Sender itself as well.
How do I initialize the Sender?
Well to Initialize it all you really need to do is this;
Sender sender = new Sender([INSERT FULL PATH TO DLL]);In present you will need to make the logic for fetching the path, it will become much easier when we make Cecil.Pathing_Utils. But while I'm at it here are some useful functions to help guide you;
Assembly assembly = Assembly.GetExecutingAssembly();
string DLLPath = Path.GetDirectoryName(assembly.Location);The above gets the full DLLPath to where the DLL is located.
Initializing a Receiver
To initialize a Receiver, again all you really need is a Path, this time to the executing run time. The Receiver is used in the Messenger as a Where do messages we send out return back to, this doesn't have to be this run time for record, but its intended for the current runtime running the code to send the message. It's also a Object for the case where we would want to have functions associated with the Receiver itself.
How do I initialize the Receiver?
To initialize it what you do once more is pretty much just this;
Receiver receiver = new Receiver([INSERT FULL PATH TO DLL]);In present you will need to make the logic for fetching the path, unless you are running from the DLL the messenger will receive the message back from, we'll have better Pathing utilities in our planned library for pathing! But for getting the current executing run time heres what we do;
Assembly assembly = Assembly.GetExecutingAssembly();
string DLLPath = Path.GetDirectoryName(assembly.Location);
Receiver receiver = new Receiver(DLLPath + "\\Orpheon_Bot.dll");What this does is fetches the full path from the executing run time, than appends the DLL in which it will receive to, in this case Orpheon_Bot.dll.
Initializing and Working with the Messenger
Now this is the not so simple and somewhat complex core component to this whole bridge; the Messenger. It's job is to send messages to the Sender and track when a Message is sent either to it or back to it. Pinging for the message is logic you will need to create in present until we have one built into the project.
How do I initialize the Messenger?
For this one its again just a Object creation;
Messenger messenger = new Messenger([YOUR SENDER], [YOUR RECEIVER], [PATH TO THE TEXT FILE IN WHICH THIS WILL SEND AND RECEIVE MESSAGES]);Again you'll need to do the pathing logic yourself, and will need to create the path to the destination wanted. Before we move on let me show you how messages are shown in present;
SendsTo;Mesage;Key;SendBackTo
"C:\Program Files (x86)\Steam\steamapps\common\Pony Island\Orpheon\Orpheon_Bot.dll";"eDJ6RCthdml0bEpLbG1wWjFhMlF4L2d6Sno4aUJITmpMblNZVUtzOWtyNENEemtZOWFyM1pNWStQekVpa1RWemVZc0pZMFJmUUFocHRNQ1Q3UXRiNXRBc0dhU0svNUdFdVp3MnZyOFVJaVVMNUk4WFQ0ZGpIRDhNL2xFZitOSkJoS0w2WTlJaFVWU0FKTk1zRDdtbFRBPT0gQXBwbGU=";"x2zD+avitlJKlmpZ1a2Qx/gzJz8iBHNjLnSYUKs9kr4CDzkY9ar3ZMY+PzEikTVzeYsJY0RfQAhptMCT7Qtb5tAsGaSK/5GEuZw2vr8UIiUL5I8XT4djHD8M/lEf+NJBhKL6Y9IhUVSAJNMsD7mlTA==";"C:\Program Files (x86)\Steam\steamapps\common\Pony Island\BepInEx\plugins\Challenges\Pony Island Challenge Runs.dll"The key on line 1 should help with how to read this but essentially, SendsTo is the string passed in from the Sender e.g. the Path, Message is the Base64 message mixed in with a Key, Key is the base64 key so the system can decrypt the messages, and lastly the end path is where messages will be sent to after the Receiver for where the message was sent does its job if that makes sense.
How do I utilize the Messenger?
To utilize there are a few functionalities you will need to know, let's go through each one!
Object Variables;
These are some variables that would be good to know if your using the Messenger system!
Sender
The sender of the messenger.
Receiver
The receiver of the messenger.
Message
This is the variable in which the received decrypted message will be found within.
MutualFilePath
This is the mutual file path referenced by the Sender and Receiver
Private Object Variables
These are some of the private variables used within the Messenger to help do its job.
PreviousLine
Internal variable used for checking whether the prior received message is the same as the current one.
RetPeices (more or less a sub record)
This is used for certain returns across the class since the lovely Tupples dont exist in this framework. This is used to transfer the key and message back to the function checking for them.
Functions of the Messenger
This is the core section that you'll need for using the Messenger!
Public Void SendMessage(string Message)
This is the function that essentially starts the chain for sending a message. It takes a string representing the exact message you want to send across, all sending and receiving is done via strings.
Private RetPieces EncryptMessage(string Message)
This method essentially makes a random key of byte of size 32-128, encrypts it to Base64, than gets the byte form of the message with the key in front, than takes those bytes and turns it into base64 and returns the base64 key and message.
Private Void StoreMessage(Receiver receiver, RetPeices ret, Sender sender)
This will create or overwrite the messenger file given, and chuck in the key for user reading, and the message sender.SendsTo, message, key, receiver.ReceivesFrom to be read by the receiving end.
Public Bool ReceiveMessage()
This is a check for if a message has been received, and if so, it follows through with the logic of setting the Messengers message to the received message.
Private String DecryptMessage(String message, String key)
This is a method used to Decrypt the message from Base64 and return it back to the receiving check.
How could I ping for Updates in the messenger?
Well there's 2 options we have made in present one a ASYNC the other a Courotine (the Courotine less tested). Mind you the first is written in .NET 9 while the latter is .NET Framework3.5.
Net9.0 Async example
public static string waitForMessageAndReturn(Messenger messenger)
{
while (!messenger.ReceiveMessage())
{
Thread.Sleep(100);
}
return messenger.message;
}
public static async Task RunWaiting(Messenger messenger)
{
while (true) {
string message = waitForMessageAndReturn(messenger);
if (message.Contains("Apple"))
{
Console.WriteLine("Received Key 'Apple'.");
messenger.SendMessage("Heeding your call sir! Here's your key [Bannana]");
} else {
Console.WriteLine("Received invalid Key.");
}
}
}You may notice there are 2 functions, and thats absolutely intentional!
WaitForMessageAndReturn() in this example is a function that essentially says Hey when im called let me indefinitely check if theres a message, and if I see one return the decrypted message to the function that called me.
RunWaiting() is a Async method which runs in the background while the rest of the code base runs, what does it do? well it Pings for a message return indefintely and when it gets one it checks the message for a Key for example here Apple than decides what to do in this case say it received the key and send a message back. It can be as complex as needed, it can even be broken into sub functions, classes and modules, this is just a baseline!!
Oh yeah bonus, to call it, it is as simple as RunWaiting(messenger); in your Awake or however you w...