Conversation

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)

3
1
0
@kemona_halftau do you know if there's a way to make dotnet not litter my /tmp with temporary files that it never cleans up?
1
0
0

@noisytoot i dont think so unfortunately
my /tmp is on a ramdisk so it clears itself upon reboot

1
0
0

@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;
}
0
0
0

i’ll try and see if i can host a server for this publicly if any of you want to try it out

0
0
0
@kemona_halftau for some reason performance in Firefox/LibreWolf is really terrible. I was getting 15-17 FPS on the fastest graphics setting and then I tried in Epiphany/GNOME Web and got >25 FPS on the fabulous graphics setting

also is there a way to listen on a unix socket instead of a TCP port?
1
0
1

@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

1
0
1

@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

1
0
1

@noisytoot have a look at the source code does it look like i remotely know what im doing /lh

1
0
1
@kemona_halftau it can't be worse than some of the other code I've seen (like a struct in C with 287 numbered boolean members because the author apparently must have forgotten about arrays)
1
0
0
@kemona_halftau I wonder why you used a BOM with UTF-8 though. I'm assuming it's a weird microsoft/dotnet thing
0
0
0