(kemona_halftau)
i dont think ive mentioned it here yet but ive been working on a game since around november 2024 and i finally decided to make it open source (its my first codeberg project too)
https://codeberg.org/kemona_halftau/OpenDiepix5
this is not an original game, its a clone of another (semi-popular) game which has been heavily enshittified recently (although some of the mechanics are completely different)
the code is a disaster but im slowly cleaning it up over time (the server was originally written in javascript in 2024 when i didnt know much about writing code and i rushed porting the entire codebase to c# out of frustration in 2025)
(kemona_halftau)
@noisytoot i dont think so unfortunately
my /tmp is on a ramdisk so it clears itself upon reboot
@kemona_halftau for reasons™ (dotnet isn’t bootstrappable so it’s not packaged in guix) I’m running dotnet stuff on a server that doesn’t often reboot so stuff cluttering up /tmp is annoying. as a workaround I’ll wrap it in a user/mount namespace and give it its own private /tmp (which of course would break anything that relies on a shared /tmp if I use it for dotnet run but I don’t think OpenDiepix5 does that anyway):
/* SPDX-License-Identifier: GPL-3.0-or-later */
#define _GNU_SOURCE
#include <stdio.h>
#include <unistd.h>
#include <sched.h>
#include <errno.h>
#include <sys/mount.h>
void write_proc_maps(uid_t uid, gid_t gid) {
FILE *fp;
fp = fopen("/proc/self/setgroups", "w");
if (fp) {
fprintf(fp, "deny");
fclose(fp);
} else perror("fopen setgroups");
fp = fopen("/proc/self/uid_map", "w");
if (fp) {
fprintf(fp, "%d %d 1", uid, uid);
fclose(fp);
} else perror("fopen uid_map");
fp = fopen("/proc/self/gid_map", "w");
if (fp) {
fprintf(fp, "%d %d 1", gid, gid);
fclose(fp);
} else perror("fopen gid_map");
}
int main(int argc, char **argv) {
if (argc < 2) {
fprintf(stderr, "Error: Not enough arguments: %d.\n", argc);
return 1;
}
uid_t uid = geteuid();
gid_t gid = getegid();
if (unshare(CLONE_NEWUSER | CLONE_NEWNS)) {
perror("unshare");
return errno;
}
write_proc_maps(uid, gid);
if (mount("none", "/tmp", "tmpfs", 0, NULL)) {
perror("mount");
return errno;
}
execvp(argv[1], &argv[1]);
perror("execvp");
return errno;
}
(kemona_halftau)
i’ll try and see if i can host a server for this publicly if any of you want to try it out
(kemona_halftau)
@noisytoot thats to be expected
the client is very laggy in its current state, theres lots of unoptimized code and really bad inefficient o(n^2) loops over entities and chunks, its kinda playable in normal firefox though without the overhead of resistfingerprinting or canvasblocker
one day i’ll get around to rewriting the client
(kemona_halftau)
@noisytoot i would add unix sockets if they were possible in dotnet (i cant bind a socket to a UnixDomainSocketEndPoint no matter what i do, ive even tried casting it to a normal EndPoint and nothing happens)
thats more of a dotnet problem though
also im still in the process of completely rewriting the web server to be properly multithreaded because the whole server stalls when there are too many clients connected
(kemona_halftau)
@noisytoot have a look at the source code does it look like i remotely know what im doing /lh
(kemona_halftau)
@noisytoot i dont know why i still use utf-8 with bom
i think one of the text editors i originally used a decade ago automatically prepended \ufeff before any text file if it contained any utf-8 character requiring multiple bytes to represent, so i started adding them out of habit and i never stopped
(kemona_halftau)
@noisytoot if the text editor allows for it, i enable it in the editor
i have not used an editor which does not allow for it yet, not including windows 8.1 notepad
(kemona_halftau)
@noisytoot also i figured out unix sockets in dotnet8. although for some reason the file descriptor number increases by 2 each time one is constructed (perhaps internally it opens the file path, leaves the file open, creates a socket, and then closes the file, perhaps to test if it is a fifo?). i might try directly invoking socket-related things from libc (something i need to do anyway because dotnet’s socket api doesnt have any way of polling multiple file descriptors without using select, which only accepts file descriptor numbers under a hard limit) (also dotnet’s socket api seems to be heavily tied to very weird aspects of winsock/winsock2, which makes sense considering dotnet is microsoft)
(kemona_halftau)
@noisytoot supposedly dotnet10 fixes this but dotnet10 has llm-generated code and i’d rather not depend on something that has llm-generated code. at least some versions of dotnet8 are slop-free
(kemona_halftau)
@noisytoot ive used ed once, but very briefly
for shell scripting it rarely matters because if i ever use a unicode character it is always escaped within a string (so the file ends up only containing ascii characters, and the bom is never auto-inserted)
(kemona_halftau)
@noisytoot a fairly recent version of mono should work just fine considering that there are no dependencies on anything else
i use a lot of really weird modern c# syntax for some things but it shouldnt be terribly hard to rewrite those parts to use older syntax (from what i can remember, just initializers for collections and some multithreading/async control flow)
> csc
Cannot open assembly '/gnu/store/pyz8m7q5129yymqxayx0qk6p616qbh3m-mono-6.12.0.206/lib/mono/4.5/csc.exe': No such file or directory.
I think the Guix mono package is broken (the csharp repl works though) so I can’t really try now
(kemona_halftau)
@noisytoot i dont know whether mono supports square-bracket inline array initialization, but it appears as though i dont even consistenly use any particular style of collection initialization whatsoever lol
(kemona_halftau)
@noisytoot https://codeberg.org/kemona_halftau/OpenDiepix5/commit/285b4028e1f017f167df7034bb7612bf217e1653 the solution was to use the “Unspecified” protocol type, otherwise it would try to use tcp which wouldnt work
i also added configuring listening over multiple endpoints (which was already a feature of lazyserver.cs, except it went unused)