✅ Windows Development NamedPipeServerStream in dll halting communications with client

Hi All, I have a C# dll that I am making to side load with a game in roder to expotr data from the game to be processed by a python machine learning algorithm. Right now I am trying to use a NamedPipeServerStream but I am having unexpected issues with communications suddenly halting with no explanation as to why.
C#
public static void Write()
{
try
{
while (true)
{
string local = null;
byte[] bytes;
lock (Gary)
{
local = data + "\n";
}
bytes = Encoding.UTF8.GetBytes(local);
pipeServer.Write(bytes, 0, bytes.Length);
pipeServer.Flush(); // Flush the pipe to ensure all data is sent
Log("Wrote", "write_log.txt");
Thread.Sleep(3); // Sleep for a short time to prevent high CPU usage
}
}
catch (Exception ex)
{
Log($"Error in Write: {ex.Message}", "write_log.txt");
}

}

public static void Read()
{
var sb = new StringBuilder();
while (true)
{
Log("Reading", "read_log.txt");
int b = pipeServer.ReadByte(); // ReadByte blocks until a byte is available, returns -1 if the pipe is closed
Log("Read","read_log.txt");
if (b == -1)
{
Log("Pipe Closed","read_log.txt");
break; // pipe closed
}
if (b == '\n')
{
// Got a full message
string data = sb.ToString().TrimEnd('\r');
var parts = data.Split(',');
lock (Nathaniel)
{
for (int i = 0; i < input.Length && i < parts.Length; i++) input[i] = parts[i] == "1";
}
sb.Clear();
Log("Read full string", "read_log.txt");
}
else
{
sb.Append((char)b);
}
}
}
C#
public static void Write()
{
try
{
while (true)
{
string local = null;
byte[] bytes;
lock (Gary)
{
local = data + "\n";
}
bytes = Encoding.UTF8.GetBytes(local);
pipeServer.Write(bytes, 0, bytes.Length);
pipeServer.Flush(); // Flush the pipe to ensure all data is sent
Log("Wrote", "write_log.txt");
Thread.Sleep(3); // Sleep for a short time to prevent high CPU usage
}
}
catch (Exception ex)
{
Log($"Error in Write: {ex.Message}", "write_log.txt");
}

}

public static void Read()
{
var sb = new StringBuilder();
while (true)
{
Log("Reading", "read_log.txt");
int b = pipeServer.ReadByte(); // ReadByte blocks until a byte is available, returns -1 if the pipe is closed
Log("Read","read_log.txt");
if (b == -1)
{
Log("Pipe Closed","read_log.txt");
break; // pipe closed
}
if (b == '\n')
{
// Got a full message
string data = sb.ToString().TrimEnd('\r');
var parts = data.Split(',');
lock (Nathaniel)
{
for (int i = 0; i < input.Length && i < parts.Length; i++) input[i] = parts[i] == "1";
}
sb.Clear();
Log("Read full string", "read_log.txt");
}
else
{
sb.Append((char)b);
}
}
}
Above are my Read and Write functions (I am avoiding using StreamReaders and StreamWriters) that run in seperate threads to preserve performance at the core of the main dll. My python client is in my first reply. When the program starts I get two data transmissions that are picked up by the client and one full read by the C# dll but then reading and writing stops on the C# side and as such the python also stops. I need serious help here as I have been bashing my head against a wall for days trying to figure it out. My assumptions is maybe the threads are being killed by some lurking AV process maybe?
131 Replies
Frozen Breadstick
import time

pipe_name = r'\\.\pipe\RobotControlPipe'
waitingForResponse = True

# Wait until the pipe server (C#) creates the pipe and is ready
while True:
try:
pipe = open(pipe_name, 'r+b', buffering=0)
break
except FileNotFoundError:
print("Waiting for pipe server...")
time.sleep(0.1)

print("Connected to pipe!")
cmdNum = 0

while True:
cmdNum+=1
try:
dataTemp = pipe.readline()
noData = False
if dataTemp == b'':
noData = True
print("No Data")

data = dataTemp
# Decode bytes to string and strip newline
data_str = data.decode().strip()
parts = data_str.split(',')

# Unpack into individual variables
if not noData:
try:
jump_state = int(parts[0])
pos_x = float(parts[1])
pos_y = float(parts[2])
vel_x = float(parts[3])
vel_y = float(parts[4])
state = float(parts[5])
print(f"Jump: {jump_state}, Pos: ({pos_x}, {pos_y}), Vel: ({vel_x}, {vel_y}), Game State:{state}")

except (IndexError, ValueError, NameError) as e:
print("Error parsing data:", data_str, "->", e)
cmd1 = "0,0,0,1,0,0,0"
cmd2 = "0,0,1,0,0,0,0"
# if cmdNum < 10000:
# pipe.write((cmd1 + "\n").encode())
# else:
# pipe.write((cmd2 + "\n").encode())
pipe.write((cmd1 + "\n").encode())
pipe.flush()

except Exception as e:
print("Exception (probably broken pipe):", e)
time.sleep(0.01)
import time

pipe_name = r'\\.\pipe\RobotControlPipe'
waitingForResponse = True

# Wait until the pipe server (C#) creates the pipe and is ready
while True:
try:
pipe = open(pipe_name, 'r+b', buffering=0)
break
except FileNotFoundError:
print("Waiting for pipe server...")
time.sleep(0.1)

print("Connected to pipe!")
cmdNum = 0

while True:
cmdNum+=1
try:
dataTemp = pipe.readline()
noData = False
if dataTemp == b'':
noData = True
print("No Data")

data = dataTemp
# Decode bytes to string and strip newline
data_str = data.decode().strip()
parts = data_str.split(',')

# Unpack into individual variables
if not noData:
try:
jump_state = int(parts[0])
pos_x = float(parts[1])
pos_y = float(parts[2])
vel_x = float(parts[3])
vel_y = float(parts[4])
state = float(parts[5])
print(f"Jump: {jump_state}, Pos: ({pos_x}, {pos_y}), Vel: ({vel_x}, {vel_y}), Game State:{state}")

except (IndexError, ValueError, NameError) as e:
print("Error parsing data:", data_str, "->", e)
cmd1 = "0,0,0,1,0,0,0"
cmd2 = "0,0,1,0,0,0,0"
# if cmdNum < 10000:
# pipe.write((cmd1 + "\n").encode())
# else:
# pipe.write((cmd2 + "\n").encode())
pipe.write((cmd1 + "\n").encode())
pipe.flush()

except Exception as e:
print("Exception (probably broken pipe):", e)
time.sleep(0.01)
Here is the python client
Frozen Breadstick
Here is the full file if anyone wants to see
jcotton42
jcotton422w ago
what has debugging told you? (also, do yourself a favor, and ditch the cutesy lock names, you're just setting yourself up for confusion later)
Frozen Breadstick
Hey man, don't diss gary Nah but I will From my understanding at this point, it writes successfully twice, and then writing just stops Which makes me think that threads are being killed That's what I see in the log
jcotton42
jcotton422w ago
will debug it?
Frozen Breadstick
will change the names of the locks When you say debug do you mean add breakpoints? because I can't do that in my current config
jcotton42
jcotton422w ago
yes
Frozen Breadstick
it get's sideloaded with a game and the game crashes if I try to apply break points
jcotton42
jcotton422w ago
ah
Frozen Breadstick
Yeah, makes it tough, which is why im logging everything And it is also a dll, I can't really run it independently
jcotton42
jcotton422w ago
one thing i would try is removing the locks rather than using a static that you're locking around, instead use a BlockingCollection
Frozen Breadstick
BlockingCollection let me search that up It seems useful, my only thing is that I don't want to queue data, I just want to transmit the current data It looks like a BlockingCollection is list like
ero
ero2w ago
I see so much wrong here but don't have the confidence to give any concrete advice. The fact you're running writing and reading on the same server on two separate threads in endless loops makes me doubt the data is being transferred correctly at all
Frozen Breadstick
Why would that be? It's an InOut stream
ero
ero2w ago
The way you're serializing the data is weird, the fact you're not using streamwriter/reader is weird, the lock seems completely misplaced (someone correct me)
Frozen Breadstick
I am open to as much advice as you can give, I never learnt C# formally The Write and Read functions are in a seperate thread, and the main thread runs PlayerUpdate and accesses those resources so I need to lock them, otherwise the dll crashes instantly
ero
ero2w ago
But where you put the lock is completely bogus To me
Frozen Breadstick
I lock the data when I access it? I thought that was right
ero
ero2w ago
You're accessing locals only
Frozen Breadstick
C#
lock (Gary)
{
data = $"{jumpState},{pos.X},{pos.Y},{vel.X},{vel.Y},{gameState}";
}

lock (Nathaniel)
{
player.jumpDown = input[0];
player.slideDown = input[1];
player.leftDown = input[2];
player.rightDown = input[3];
player.grappleDown = input[4];
player.boostDown = input[5];
player.itemDown = input[6];
}
C#
lock (Gary)
{
data = $"{jumpState},{pos.X},{pos.Y},{vel.X},{vel.Y},{gameState}";
}

lock (Nathaniel)
{
player.jumpDown = input[0];
player.slideDown = input[1];
player.leftDown = input[2];
player.rightDown = input[3];
player.grappleDown = input[4];
player.boostDown = input[5];
player.itemDown = input[6];
}
In player update, the main thread
C#
{
for (int i = 0; i < input.Length && i < parts.Length; i++) input[i] = parts[i] == "1";
}
C#
{
for (int i = 0; i < input.Length && i < parts.Length; i++) input[i] = parts[i] == "1";
}
C#
lock (Gary)
{
local = data + "\n";
}
C#
lock (Gary)
{
local = data + "\n";
}
jcotton42
jcotton422w ago
they're locking around read/write of data and input, both of which are static
Frozen Breadstick
Asa for the stream reader and writer, they were causing issues
ero
ero2w ago
Hm. Would be more clear if a proper naming convention was followed, but unrelated I suppose
Frozen Breadstick
I have gotten successful results encoding them myself. It just only works twice before dying YEs yes i know im sorry I havent really done a lot of windows development and game based dev so this is a bit foreign to me Like as in I am not a veteran I can switch back to a StreamReader and StreamWriter but that still begs the question as to why it's suddenly halting I am wondering if it would be better to use a TCP/UDP socket but it is not as fast as a pipe
ero
ero2w ago
I would really need to have all of this in front of me to test for myself. I just see a major issue in writing this data so often while the python side has to do much more work (sending as well), which to me means it simply cannot keep up The way I would implement this is by making the client ask for data (send request, wait for response with data), but I'm sure there's ways without that Maybe look into BeginRead?
Frozen Breadstick
I tried to implement a flag based system Have it be, data is sent, then we wait for a response once we read a resnponse then we send a new packet
ero
ero2w ago
You should probably move sending data to an actual Unity method that runs within the frame rate of the game. So something like their Update method in a MonoBrhaviour Instead of just on a random thread
Frozen Breadstick
I did not code the game
ero
ero2w ago
You're modding it
Frozen Breadstick
Yes
ero
ero2w ago
You can do that
Frozen Breadstick
I am coding a dll in Visual Studio The game doesn't have an official mod support
using SRPlayer = _MXY9EldIZvy8vwVKj9_8Ql5FrpIXR9t7Lm01azYMwjSsOOs_Niu5asGaYW4Wa0w;
using SRPlayer = _MXY9EldIZvy8vwVKj9_8Ql5FrpIXR9t7Lm01azYMwjSsOOs_Niu5asGaYW4Wa0w;
hence we access obfuscated objects But that is not the issue, I know the data is retrieved successfully Actually I wouldn't even need to do it that way
ero
ero2w ago
The issue is more that you're not getting accurate data. You might skip a frame of the game, or might send the data from the same frame twice
Frozen Breadstick
What I might do is implement read and write in a single thread as Read is blocking so it won't write until it has received a response
ero
ero2w ago
If you expect to always read once and then immediately write once, then you should just do that, yes I expected you wanted to individually listen and individually write whenever you want
Frozen Breadstick
That is what I wanted
ero
ero2w ago
But the python side really doesn't suggest that
Frozen Breadstick
but I think this will work too If I could thread python then I would but then I have to implement multiprocessing
jborean
jborean2w ago
you can thread python
Frozen Breadstick
Yes, but it doesn't ACTUALLY run on seperate threads
jborean
jborean2w ago
the GIL doesn't apply with waiting for I/O so it won't block the thread
Frozen Breadstick
Wait actually?
jborean
jborean2w ago
Yep, the underlying CPython call to wait for the data will release the GIL allowing the other thread to run whatever it wants
Frozen Breadstick
:|
jborean
jborean2w ago
There's also asyncio to use await
Frozen Breadstick
The pipe server on the C# side is not async, but I think that shouldnt affect the python client Man this shit hard
jborean
jborean2w ago
multi threading is hard but I'm unsure from a glance why you actually need it
Frozen Breadstick
I need it on the C# side because the main PlayerUpdate thread can't be blocking and absolutely cannot take very long Otherwise it physically slows down the game Which is why I thread Write and Read in C#
ero
ero2w ago
Difficult to believe that writing to a stream is that slow
Frozen Breadstick
I had it in the main thread and it brought the game down from 300 to 60 fps
jborean
jborean2w ago
Using a .NET task will also allow you to avoid a thread, at least an explicit one, it'll rely on the threadpool to complete
Frozen Breadstick
Not sure what this is sorry
jborean
jborean2w ago
Pipes and StreamReader/Writer can be asynchronous in C# allowing you use async/Tasks on the C# side. Use a new enough .NET version and it'll also support cancellation tokens
Frozen Breadstick
I am using 4.7.2
jborean
jborean2w ago
There's your first problem 🙂
Frozen Breadstick
Cant update Old game I would if I could
jborean
jborean2w ago
I believe you can still use async here with net472 I could be wrong but IIRC named pipes don't like you reading and writing on separate threads on the same pipe. It's been a while since I tested it but I recall having some troubles with it
Frozen Breadstick
I had issues with async but I can try it again Hm, I will try implement them on the same thread
ero
ero2w ago
...or use two pipes
Frozen Breadstick
Can I do that?
ero
ero2w ago
That's what we've been saying
jborean
jborean2w ago
yep use as many as you want
Frozen Breadstick
I think I misunderstood
ero
ero2w ago
A stream doesn't have an output lane and an input lane. Your write thread is clogging up the stream buffer, and your read thread is trying to consume it immediately (someone correct me?) There's all sorts of conflicts going on
jborean
jborean2w ago
A named pipe can be bidirectional but I still recall having troubles trying to read and write on the same pipe end at the same time
Frozen Breadstick
I seeeee I thought if I marked it bidirectional it would manage two seperate lanes Ok I am trying now with two seperate pipes
jborean
jborean2w ago
If you are writing data and expect a response only after writing it, then do the read in the same action If you have read/writes independent from each other then I would recommend two different pipes
ero
ero2w ago
Also we never saw the logs btw Just, you know Would have been good
Frozen Breadstick
I am trying with two rq, lemme see if I can make it work
jborean
jborean2w ago
Looking at the docs, .NET 4.7.2 supports ReadLineAsync, WriteLineAsync and a pipe created Asynchronously. The only thing you miss out is cancellation support but you don't have that anyway with manual threading
Frozen Breadstick
Ok this shit wont even get past the initialisation now
import time

write_pipe_name = r'\\.\pipe\WriteRobotControl'
read_pipe_name = r'\\.\pipe\ReadRobotControl'
waitingForResponse = True

# Wait until the pipe server (C#) creates the pipe and is ready
while True:
try:
pipe_to_read = open(write_pipe_name, 'rb', buffering=0)
break
except FileNotFoundError:
print("Waiting for write server...")
time.sleep(0.1)

print("Found Write Server - Connected")

while True:
try:
pipe_to_write = open(read_pipe_name, 'wb', buffering=0)
break
except FileNotFoundError:
print("Waiting for read server...")
time.sleep(0.1)

print("Connected to pipes!")
import time

write_pipe_name = r'\\.\pipe\WriteRobotControl'
read_pipe_name = r'\\.\pipe\ReadRobotControl'
waitingForResponse = True

# Wait until the pipe server (C#) creates the pipe and is ready
while True:
try:
pipe_to_read = open(write_pipe_name, 'rb', buffering=0)
break
except FileNotFoundError:
print("Waiting for write server...")
time.sleep(0.1)

print("Found Write Server - Connected")

while True:
try:
pipe_to_write = open(read_pipe_name, 'wb', buffering=0)
break
except FileNotFoundError:
print("Waiting for read server...")
time.sleep(0.1)

print("Connected to pipes!")
this is how I connect
C#
private static NamedPipeServerStream writePipe;
private static NamedPipeServerStream readPipe;
private static StreamWriter pipeWriter;
private static StreamReader pipeReader;
private static bool waitingForResponse = false;
private static bool responseRequired = true;

private static Thread writerThread;
private static Thread readerThread;
private static Thread RWThread;

public static readonly object Nathaniel = new object(); // Nathaniel is just a nice guy who helps us lock resources so we dont have memory based errors
public static readonly object Gary = new object(); // Gary is Nathaniels friend, he does a similar job

public static void Log(string message, string file)
{
string logPath = Path.Combine(dllFolder, file);
File.AppendAllText(logPath, $"[{DateTime.Now:HH:mm:ss}] {message}\n");
}

public static void PlayerInit(SRPlayer player)
{
Log("PlayerInit", "init_log.txt");
SRPlayer.disableInputPolling = true; // Disable input polling to prevent the game from overwriting our input
if (writePipe == null && readPipe == null)
{
writePipe = new NamedPipeServerStream("WriteRobotControl", PipeDirection.Out, 1, PipeTransmissionMode.Message, PipeOptions.None);
readPipe = new NamedPipeServerStream("ReadRobotControl", PipeDirection.In, 1, PipeTransmissionMode.Message, PipeOptions.None);
writePipe.WaitForConnection(); // Wait for the client to connect (No failsafe currently, ensure client is running first)
readPipe.WaitForConnection(); // Wait for the client to connect (No failsafe currently, ensure client is running first)
gameState = 0;
lock (Gary)
{
data = $"{0},{0},{0},{0},{0},{gameState}";
}
Log("Pipe connected","init_log.txt");
writerThread = new Thread(Write) { IsBackground = true };
writerThread.Start();
readerThread = new Thread(Read) { IsBackground = true };
readerThread.Start();
Log("Reader and Writer threads started", "init_log.txt");
}
}
C#
private static NamedPipeServerStream writePipe;
private static NamedPipeServerStream readPipe;
private static StreamWriter pipeWriter;
private static StreamReader pipeReader;
private static bool waitingForResponse = false;
private static bool responseRequired = true;

private static Thread writerThread;
private static Thread readerThread;
private static Thread RWThread;

public static readonly object Nathaniel = new object(); // Nathaniel is just a nice guy who helps us lock resources so we dont have memory based errors
public static readonly object Gary = new object(); // Gary is Nathaniels friend, he does a similar job

public static void Log(string message, string file)
{
string logPath = Path.Combine(dllFolder, file);
File.AppendAllText(logPath, $"[{DateTime.Now:HH:mm:ss}] {message}\n");
}

public static void PlayerInit(SRPlayer player)
{
Log("PlayerInit", "init_log.txt");
SRPlayer.disableInputPolling = true; // Disable input polling to prevent the game from overwriting our input
if (writePipe == null && readPipe == null)
{
writePipe = new NamedPipeServerStream("WriteRobotControl", PipeDirection.Out, 1, PipeTransmissionMode.Message, PipeOptions.None);
readPipe = new NamedPipeServerStream("ReadRobotControl", PipeDirection.In, 1, PipeTransmissionMode.Message, PipeOptions.None);
writePipe.WaitForConnection(); // Wait for the client to connect (No failsafe currently, ensure client is running first)
readPipe.WaitForConnection(); // Wait for the client to connect (No failsafe currently, ensure client is running first)
gameState = 0;
lock (Gary)
{
data = $"{0},{0},{0},{0},{0},{gameState}";
}
Log("Pipe connected","init_log.txt");
writerThread = new Thread(Write) { IsBackground = true };
writerThread.Start();
readerThread = new Thread(Read) { IsBackground = true };
readerThread.Start();
Log("Reader and Writer threads started", "init_log.txt");
}
}
It can't connect to the servers
jborean
jborean2w ago
So what do the logs show it is getting to? Is C# seeing the client's connecting, is Python not connecting to any pipe?
Frozen Breadstick
It is not connecting to any pipe oh my god hang on hang on hang on
C#
writePipe = new NamedPipeServerStream("WriteRobotControl", PipeDirection.Out, 1, PipeTransmissionMode.Message, PipeOptions.None);
writePipe.WaitForConnection(); // Wait for the client to connect (No failsafe currently, ensure client is running first)
readPipe = new NamedPipeServerStream("ReadRobotControl", PipeDirection.In, 1, PipeTransmissionMode.Message, PipeOptions.None);
readPipe.WaitForConnection(); // Wait for the client to connect (No failsafe currently, ensure client is running first)
C#
writePipe = new NamedPipeServerStream("WriteRobotControl", PipeDirection.Out, 1, PipeTransmissionMode.Message, PipeOptions.None);
writePipe.WaitForConnection(); // Wait for the client to connect (No failsafe currently, ensure client is running first)
readPipe = new NamedPipeServerStream("ReadRobotControl", PipeDirection.In, 1, PipeTransmissionMode.Message, PipeOptions.None);
readPipe.WaitForConnection(); // Wait for the client to connect (No failsafe currently, ensure client is running first)
I just had to do this instead of connection after making them both This might be working If this works I can finally stop coding C# and just focus on the reinforcement learning in python
jborean
jborean2w ago
I would recommend also using the Byte transmission mode and just making sure you use StreamReader and StreamWriter to read and write lines instead I can't say I've ever had the need of using Message mode as it has some funky semantics when it comes to the underlying read/writes
Frozen Breadstick
OH MY GOD IT WORKS THANK GOD I did do this but it was causing issues
ero
ero2w ago
And use like json to serialize the data instead of some custom format It should work just fine All it does is add a line break to the end of your input
Frozen Breadstick
I will try switch over now that I have got it working I just decode a string I didnt htink that was that bad with a comma delimiter
ero
ero2w ago
Just make sure to also readline on the python side. It might assume \n though. StreamWriter likely writes \r\n
Frozen Breadstick
I am using readline use .strip() in python gets rid of \r\n in any case I will try switch to a StreamWriter and StreamReader
jborean
jborean2w ago
excuse the pwsh here but it shows the .NET types and calls make here
No description
Frozen Breadstick
I do see
jborean
jborean2w ago
using json is a nice next step as you don't need to worry about escaping the delimiter values, the serialization can easily convert to a structured value dealing with the escaping all for you on both sides
Frozen Breadstick
Lemme get a StreamWriter and Reader going first then I will do json ok StreamWriter and Reader working what are you guys suggesting with json? @jborean
jborean
jborean2w ago
for python a simple json.loads(read_line)
Frozen Breadstick
how do I encode as json on this side tho
jborean
jborean2w ago
for C# there's System.Text.Json that should have a compatible package for net472 or netstandard2.0, otherwise newtonsoft.json
ero
ero2w ago
Unity should have built-in JSON stuff
Frozen Breadstick
I am in Visutal Studio
ero
ero2w ago
Doesn't matter? You're writing a mod You have access to all the unity stuff you need
Frozen Breadstick
I don't have Unity stuff installed I do not believe this game was made with unity
ero
ero2w ago
The game comes with it Oh, I thought it was
Frozen Breadstick
I dont believe so It is SpeedRunners
ero
ero2w ago
Oh it's xna
Frozen Breadstick
yeah
ero
ero2w ago
I guess stj then
Frozen Breadstick
So how are you suggesting I format it? Like this?
C#
using System.Text.Json;

var data = new
{
jump = jumpState,
posX = pos.X,
posY = pos.Y,
velX = vel.X,
velY = vel.Y,
game = gameState
};

string json = JsonSerializer.Serialize(data);
C#
using System.Text.Json;

var data = new
{
jump = jumpState,
posX = pos.X,
posY = pos.Y,
velX = vel.X,
velY = vel.Y,
game = gameState
};

string json = JsonSerializer.Serialize(data);
just as a dumb example then on the python end I use json.loads(the_data_that_was_read_in)
jborean
jborean2w ago
structure it however you wish
ero
ero2w ago
Maybe not an anonymous object... I'd definitely make this a struct type A record even
Frozen Breadstick
C#
public class GameData
{
public bool JumpState { get; set; }
public float PosX { get; set; }
public float PosY { get; set; }
public float VelX { get; set; }
public float VelY { get; set; }
public int GameState { get; set; }
}
C#
public class GameData
{
public bool JumpState { get; set; }
public float PosX { get; set; }
public float PosY { get; set; }
public float VelX { get; set; }
public float VelY { get; set; }
public int GameState { get; set; }
}
so this first then create a new GameData object
ero
ero2w ago
A struct specifically, not a class
readonly record struct Data(
bool Jumping,
float PosX,
...);
readonly record struct Data(
bool Jumping,
float PosX,
...);
But for this you probably need to include PolySharp And bump the langversion
Frozen Breadstick
hang on back up a sec 1. Why does it need to be a "record" 2. What is PolySharp 3. What do you mean by bump the langversion
ero
ero2w ago
It doesn't, records are just shorter lol
Frozen Breadstick
ah gotcha
ero
ero2w ago
The alternative is
readonly struct Data
{
public Data(
bool jumping,
...)
{
Jumping = jumping;
...
}

public bool Jumping { get; }
}
readonly struct Data
{
public Data(
bool jumping,
...)
{
Jumping = jumping;
...
}

public bool Jumping { get; }
}
Frozen Breadstick
Does record exist in 4.7.2
ero
ero2w ago
I say don't bother, the gain isn't worth it In your case you can probably just go with a mutable type (leave the set and just assign them in the object initializer)
Frozen Breadstick
also System.Text.Json doesn't exist :|
ero
ero2w ago
Basically just replace class with struct here and call it a day You need to include it as a package
Frozen Breadstick
C#
public struct GameData // This class is used to store the game data that is sent to the pipe
{
public int Jump { get; set; }
public float PosX { get; set; }
public float PosY { get; set; }
public float VelX { get; set; }
public float VelY { get; set; }
public int Game { get; set; }
}
C#
public struct GameData // This class is used to store the game data that is sent to the pipe
{
public int Jump { get; set; }
public float PosX { get; set; }
public float PosY { get; set; }
public float VelX { get; set; }
public float VelY { get; set; }
public int Game { get; set; }
}
C#
var game = new GameData
{
Jump = jumpState,
PosX = pos.X,
PosY = pos.Y,
VelX = vel.X,
VelY = vel.Y,
Game = gameState
};
C#
var game = new GameData
{
Jump = jumpState,
PosX = pos.X,
PosY = pos.Y,
VelX = vel.X,
VelY = vel.Y,
Game = gameState
};
I had using System.Text.Json
ero
ero2w ago
That's not including a package
Frozen Breadstick
I see I did it hooray ok now my only question is what this will look like on the python side
ero
ero2w ago
.
Frozen Breadstick
No but as in, the data itself it is not a json format now* @ero
while True:
cmdNum+=1
try:
dataTemp = pipe_to_read.readline()
noData = False
if dataTemp == b'':
noData = True
print("No Data")

data = dataTemp
# Decode bytes to string and strip newline
game = json.loads(data)

# Unpack into individual variables
if not noData:
try:
jump_state = game["Jump"]
pos_x = game["PosX"]
pos_y = game["PosY"]
vel_x = game["VelX"]
vel_y = game["VelY"]
state = game["Game"]
print(f"Jump: {jump_state}, Pos: ({pos_x}, {pos_y}), Vel: ({vel_x}, {vel_y}), Game State:{state}")

except (IndexError, ValueError, NameError) as e:
print("Error parsing data:", data, "->", e)
while True:
cmdNum+=1
try:
dataTemp = pipe_to_read.readline()
noData = False
if dataTemp == b'':
noData = True
print("No Data")

data = dataTemp
# Decode bytes to string and strip newline
game = json.loads(data)

# Unpack into individual variables
if not noData:
try:
jump_state = game["Jump"]
pos_x = game["PosX"]
pos_y = game["PosY"]
vel_x = game["VelX"]
vel_y = game["VelY"]
state = game["Game"]
print(f"Jump: {jump_state}, Pos: ({pos_x}, {pos_y}), Vel: ({vel_x}, {vel_y}), Game State:{state}")

except (IndexError, ValueError, NameError) as e:
print("Error parsing data:", data, "->", e)
is this correct in terms of getting the data from the C# json transmission
ero
ero2w ago
Does it work?
Frozen Breadstick
I just wanted to ask before testing it because there is a bug with the API at the moment that if something crashes I have to reaquire some files At this point it's just QOL
ero
ero2w ago
I'm not the right person to ask, I don't know python
Frozen Breadstick
Thank you all for all your help You have been great
jborean
jborean2w ago
Yep it just becomes a dict and you lookup keys with value["key"]
Frozen Breadstick
gotcha And I assume similarly the other way around, I just create stuff in python and use json.dumps? honestly
jborean
jborean2w ago
yep
Frozen Breadstick
For such a small usecase is it even worth using json
jborean
jborean2w ago
you can dump it straight to the pipe as well to avoid the extra allocation but this is getting into micro optimisation territory here
Frozen Breadstick
pipe.write(json.dumps(cmd).encode()) ? @jborean
jumpDown = False
slideDown = False
leftDown = False
rightDown = False
grappleDown = False
boostDown = False
itemDown = False

cmd = {
"Jump": jumpDown,
"Slide": slideDown,
"Left": leftDown,
"Right": rightDown,
"Grapple": grappleDown,
"Boost": boostDown,
"Item": itemDown
}
jumpDown = False
slideDown = False
leftDown = False
rightDown = False
grappleDown = False
boostDown = False
itemDown = False

cmd = {
"Jump": jumpDown,
"Slide": slideDown,
"Left": leftDown,
"Right": rightDown,
"Grapple": grappleDown,
"Boost": boostDown,
"Item": itemDown
}
jborean
jborean2w ago
json.dump(result, pipe)
json.dump(result, pipe)
it will convert the value of result and write it to the fd represented by pipe
Frozen Breadstick
ah i see I still call pipe.flush() tho yes?
jborean
jborean2w ago
most likely you probably also want a newline as well, I can't remember if json.dump has an optino to expose that doesn't look like it so you'll have to do it after
json.dump(cmd, pipe)
pipe.write("\n")
pipe.flush()
json.dump(cmd, pipe)
pipe.write("\n")
pipe.flush()
Frozen Breadstick
Cool and on the C# is there like a deserialisation?
jborean
jborean2w ago
yep JsonSerializer.Deserialize<T>(value), you provide the class as T and it'll do it for you
Frozen Breadstick
T is the struct to deserliase to and value is a string
jborean
jborean2w ago
yep
Frozen Breadstick
how fast is the deserialiser Shit man I am getting compatibility errors Which version of System.Text.Json should I use for .NET 4.7.2 I dropped json I will figure it out in future it's simple to migrate to but it causes like 15 errors due to version differences

Did you find this page helpful?