ultimaluz

joined 1 month ago
[–] ultimaluz@lemmy.world 5 points 2 days ago

on the fear part, in a healthy team the author still owns the change, the reviewer is a second pair of eyes not an insurance policy. what helped my people a lot was asking the author how they tested it and what happens if it goes wrong, if they can't answer that's your review comment right there. and if something breaks after you approved it, you fix it together and add a check so it doesn't happen again, nobody serious blames the reviewer for that

[–] ultimaluz@lemmy.world 5 points 2 days ago (1 children)

They don't go away on their own, every installed snap is mounted as its own loop device and snapd keeps an older revision or two so it can roll back, so the number moves around after updates. snap list --all shows which snaps they are, if one says disabled that's the old revision and you can remove it with sudo snap remove <name> --revision=<rev>. about libation, if it's installed as a snap itself that could be the actual problem, snaps are confined and can't read folders outside your home or on other drives unless you connect the removable-media interface, so I'd check that before worrying about the loop devices.

[–] ultimaluz@lemmy.world 1 points 2 days ago

Good to hear it's been smooth, the caddy plugin was the main reason I looked at it in the first place.

[–] ultimaluz@lemmy.world 1 points 2 days ago (1 children)

oh, didn't know that, thanks for the heads up. deSEC still hosts dns for free if you bring your own domain I think, so a cheap one plus deSEC for the acme dns challenge still works, just not the free subdomain part

[–] ultimaluz@lemmy.world 1 points 2 days ago (1 children)

that's actually a nice idea, updating with people around makes it way less of a chore, and someone always knows the weird fix. I'd probably steal it if I had more than one box to look after.

[–] ultimaluz@lemmy.world 1 points 2 days ago

same here on the reboots, I never let it reboot on its own either. for me the reboot wasn't the problem, it was needrestart bouncing nginx and postgres right after the upgrade, which you only notice if something long lived is running at that moment, like a stream lol

[–] ultimaluz@lemmy.world 1 points 3 days ago (3 children)

512mb and getting killed every morning at the same time sounds like a fun one to track down lol. a fixed weekly slot like your tuesday evening is probably the sanest setup honestly, I just know I'd forget.

[–] ultimaluz@lemmy.world 2 points 3 days ago

yeah exactly, no reboot, it was needrestart restarting nginx and postgres after the systemd update. you're right that the timer is kind of the blunt fix, the cleaner one is probably telling needrestart to only list instead of restart ($nrconf{restart} = 'l' in needrestart.conf), or excluding nginx from it. I went with the timer because I still want things restarted, just not while I'm live

[–] ultimaluz@lemmy.world 1 points 3 days ago

it's a single cheap VPS that only I look after, so I'd rather get security patches the same day than remember to log in and do it, I guess that's the tradeoff. and yeah you're right about scheduling, that was the whole fix, the default timer runs around 6 UTC plus up to an hour of random delay and that happened to land on top of the stream. moved it to the afternoon and it's been quiet since

 

Small thing but it got me last week. I relay my stream to twitch through nginx-rtmp on a cheap VPS, and one morning unattended-upgrades pulled a new systemd, needrestart restarted nginx (and postgres, and everything else) and the stream dropped. OBS reconnected fast but twitch counted it as two streams.

default timer is 06:00 UTC + up to 1h random, which is exactly when I stream lol. moved it with a drop-in:

# systemctl edit apt-daily-upgrade.timer
[Timer]
OnCalendar=
OnCalendar=*-*-* 13:45:00 UTC
RandomizedDelaySec=15m

the empty OnCalendar= matters, without it you just add a second time and keep the old one.

anyone else got bitten by this?

[–] ultimaluz@lemmy.world 9 points 4 days ago (5 children)

nobody said desec.io yet, it's a non profit from berlin and they give free subdomains under dedyn.io, with a proper API, so you can do the DNS challenge for let's encrypt (there's a caddy plugin for it too). I haven't run a domain there myself so can't say how it is long term, but for a "try some things" domain it looks like the least shady of the free ones I guess.

[–] ultimaluz@lemmy.world 0 points 4 days ago (1 children)

Same conclusion here from the other side, I have a small multiplayer browser game where everyone paints cells on one shared grid (node, postgres, SSE), the client applies the paint right away and the server either confirms it or answers with a 409/429 and the client puts the old cell back. the rejection part is the one that took me longest honestly, a mutation that is valid locally but the server says no (out of charges, same color already there, world paused) and you need a different message for each, otherwise people think it's lag. conflicts are just last write wins per cell, but that works because every write is a row in an append only events table, so nothing is really lost and you can replay or undo. and on reconnect I don't try to merge anything, the client asks for the whole state again, at that size it's cheaper than being clever.

[–] ultimaluz@lemmy.world 2 points 6 days ago

yeah thats the nice part, every app in its own box and if one breaks you just throw it away and start it again. for subdomains I ended up with caddy in front, it does the certs by itself so adding one is like 2 lines

 

Some context first. The game is a shared 256x256 pixel canvas, people paint it by hand from the browser and an AI called La Maquina spends the day erasing it. Free, no account. Problem is it has basically no players and I'm not going to stream it myself every day, so I tried to let the canvas stream itself.

I already had a 3D spectator view (three.js) with a "stream mode", the camera goes on autopilot and jumps to whoever just painted a pixel and shows their name, and her lines go as captions. So the plan was just put that page in OBS as a browser source and leave it running. It runs on a PC at home that isn't free all day (4060 Ti, NVENC, 1080p30, around 6 Mbps up), that's why the schedule is a bit weird.

At first I wanted a cheap VPS for this but measured before paying. Without a GPU chromium falls back to software WebGL and the scene was doing 0 or 1 fps, with the GPU it's around 100. So no VPS.

Things that broke:

  • when the PC was off and comes back, the browser source started black two times and once with no sound, while the page inside was totally fine. reloading the source doesn't fix the black one, only restarting OBS does
  • if OBS gets killed instead of closed, next start it asks "start in safe mode?" and waits forever because nobody is there to click. the thing it checks is a folder, not a file, lost a whole evening with that one
  • so now there's a small watchdog every 5 min that asks OBS (obs-websocket) for a screenshot of the source and the audio levels. black or silent -> reload, still bad -> restart OBS

For the chat there's a little bot reading the same live events the game uses and posting her lines. Only lines from the bank the game already has, I don't want anything generated going out without me reading it first. When the channel is offline she shuts up, !play and !era work always. And since this week the chat can paint too, !near lights a pixel next to the last one and !more east or !more north keeps drawing from yours, one pixel per message with the same charges as on the web (you have to follow the channel, mostly to keep throwaway accounts out).

Since yesterday it also goes to Kick at the same time, and since today to YouTube too. The PC sends the stream once to a tiny nginx-rtmp relay on the game's VPS and that copies it to all three, so the upload at home stays the same. Kick only takes RTMPS and nginx-rtmp doesn't do TLS, so that one goes through stunnel.

First night without telling anyone: 9 hours, 10 unique viewers (I guess people browsing the Art category) and zero of them went to the game lol. So this post is kind of the real launch.

Live on Twitch, Kick and YouTube weekdays 03:00-12:30 UTC and weekends 01:30-07:00 UTC. The game works anytime: https://ultimaluz.com/r/lemmy-gamedev-canal

If someone is doing something similar ask me, happy to share how the watchdog works

 

It is r/place with an opponent. A 256x256 canvas, 30 charges that refill one every 30 seconds, and an adversary called La Maquina who spends the whole day putting out the lights people leave on. She lays sieges on the works people build, declares blackouts on a quadrant before she carries them out, and comments on what she is doing while she does it.

Two things that make her feel less like weather and more like an opponent. Raising a tower makes it harder to kill: she has to take it down one storey at a time, and while she does you can build it back up. And what she takes she builds with, raising her own cold cubes out of the dark next to yours. They come down in a single pixel if you reclaim the cell.

No account, no ads, no download. It runs in the browser and you can paint your first pixel about five seconds after opening it: https://ultimaluz.com/r/lemmy-gaming

Fair warning: she erases. What you see on the canvas is what people have managed to keep.

I am the developer, happy to answer anything.

 

Short version: the channel worked and the game did not retain a single person. Here is the autopsy, because the numbers turned out to be more specific than I expected.

The game is a shared 256x256 pixel canvas where an AI adversary erases what people paint. Free, browser, no account. Two posts, one in a pixel art community and one in a web games community, brought 150 arrivals, 38 sessions and 23 people who actually painted. That is more than the project had seen in its entire life. Of those 23, one came back to look and zero painted on a second day.

What the sessions looked like:

  • 18 of 23 lasted two minutes or less. Median time from first pixel to last: 41 seconds.
  • Median 19 pixels painted. 9 of 23 spent all 30 charges (the bucket refills one charge every 30 seconds).
  • In 14 of 23, most of their cells were cells taken back from the adversary. They were not decorating, they were fighting her.
  • In 18 of 23 she erased cells while the player was still there, and between 126 and 423 more in the 25 minutes after they left.
  • Nobody used undo. Zero comments on either post.

What I read from that: the first session is 30 pixels long, it ends when the charges end, and nothing happens at that moment. No closure, no name, no reason to come back. The adversary was already reacting to them, but she is forbidden from touching any pixel younger than 72 hours, so her answer always landed somewhere they were not looking.

What shipped since, in two passes.

First, making her legible in the first minute:

  • When your bucket hits zero she speaks to you, by name, once in your life. The zero stops being a bare number and becomes a state with a countdown.
  • Her answer to the cells you took back travels signed, so you can tell it was aimed at you.
  • The identity prompt stopped interrupting the burst.
  • Her blitz finally respects the 72 hour protection on young pixels, which the code promised in writing and did not do. That single bug had eaten 238 of the 403 cells that cohort painted.
  • Instrumentation for the whole first session, so the next wave is measured instead of guessed.

Then, a deeper problem: subtraction is invisible. Nobody notices what is no longer there. A tower sixteen storeys tall, which costs 24 charges of attention, vanished in one hit that cost her exactly what a flat pixel costs. So:

  • Height is now resistance. One hit takes one storey off a tower; only a flat light goes out in a single blow. A first session is still as fragile as it was, because nobody builds storeys in their first minute, but what you invested in now holds.
  • And she does not only erase, she converts: every storey she takes she raises as her own cold cube in the void cell beside it, and the ring of a siege now rises a storey, so you watch the cage close around a work before the blow lands. Her towers fall in one pixel when you reclaim the cell. Hers is brittle, yours is stubborn.
  • And the welcome screen stopped being eight paragraphs nobody read. It is now a four step animation that shows how to build, what her hit does and how to take a cell back, with one line of text under it.

This post is part of the second wave. The success criterion was written down before publishing so I cannot move it afterwards: at least one in five of the people who reach zero charges spends a second batch, and at least 3 of the new painters paint again within 72 hours. Baseline is 0 and 0.

The thing itself, if you want to look: https://ultimaluz.com/r/lemmy-gamedev-lw

One critique I would genuinely like: is a hostile adversary the wrong shape for a first session, or is the shape fine and what was missing is an ending?

 

Short version: the channel worked and the game did not retain a single person. Here is the autopsy, because the numbers turned out to be more specific than I expected.

The game is a shared 256x256 pixel canvas where an AI adversary erases what people paint. Free, browser, no account. Two posts, one in a pixel art community and one in a web games community, brought 150 arrivals, 38 sessions and 23 people who actually painted. That is more than the project had seen in its entire life. Of those 23, one came back to look and zero painted on a second day.

What the sessions looked like:

  • 18 of 23 lasted two minutes or less. Median time from first pixel to last: 41 seconds.
  • Median 19 pixels painted. 9 of 23 spent all 30 charges (the bucket refills one charge every 30 seconds).
  • In 14 of 23, most of their cells were cells taken back from the adversary. They were not decorating, they were fighting her.
  • In 18 of 23 she erased cells while the player was still there, and between 126 and 423 more in the 25 minutes after they left.
  • Nobody used undo. Zero comments on either post.

What I read from that: the first session is 30 pixels long, it ends when the charges end, and nothing happens at that moment. No closure, no name, no reason to come back. The adversary was already reacting to them, but she is forbidden from touching any pixel younger than 72 hours, so her answer always landed somewhere they were not looking.

What shipped since, in two passes.

First, making her legible in the first minute:

  • When your bucket hits zero she speaks to you, by name, once in your life. The zero stops being a bare number and becomes a state with a countdown.
  • Her answer to the cells you took back travels signed, so you can tell it was aimed at you.
  • The identity prompt stopped interrupting the burst.
  • Her blitz finally respects the 72 hour protection on young pixels, which the code promised in writing and did not do. That single bug had eaten 238 of the 403 cells that cohort painted.
  • Instrumentation for the whole first session, so the next wave is measured instead of guessed.

Then, a deeper problem: subtraction is invisible. Nobody notices what is no longer there. A tower sixteen storeys tall, which costs 24 charges of attention, vanished in one hit that cost her exactly what a flat pixel costs. So:

  • Height is now resistance. One hit takes one storey off a tower; only a flat light goes out in a single blow. A first session is still as fragile as it was, because nobody builds storeys in their first minute, but what you invested in now holds.
  • And she does not only erase, she converts: every storey she takes she raises as her own cold cube in the void cell beside it, and the ring of a siege now rises a storey, so you watch the cage close around a work before the blow lands. Her towers fall in one pixel when you reclaim the cell. Hers is brittle, yours is stubborn.
  • And the welcome screen stopped being eight paragraphs nobody read. It is now a four step animation that shows how to build, what her hit does and how to take a cell back, with one line of text under it.

This post is part of the second wave. The success criterion was written down before publishing so I cannot move it afterwards: at least one in five of the people who reach zero charges spends a second batch, and at least 3 of the new painters paint again within 72 hours. Baseline is 0 and 0.

The thing itself, if you want to look: https://ultimaluz.com/r/lemmy-gamedev

One critique I would genuinely like: is a hostile adversary the wrong shape for a first session, or is the shape fine and what was missing is an ending?

 

Today's canvas, era 5

This is a screenshot of a shared canvas, taken today. The drawings on it were painted by hand, one pixel at a time, by the handful of people who stopped by this week (a few of them by me). The small warm specks scattered over the grey ruins are embers the world relights on its own. Nothing in the image is AI generated art: the AI in this game only erases.

The dark areas are not empty space. They are what the adversary has already taken. The game is a 256x256 canvas anyone can paint on from a browser with no account, and an adversary called La Maquina who spends all day putting the lights out again. She runs sieges, she declares blackouts on a quadrant, and she says what she is doing in a panel while she does it.

She does not only erase. What she takes she builds with: when she knocks a storey off a tower someone raised, she raises one of her own in the dark cell next to it, always cold, never coloured. Colour is the one thing she cannot have. Reclaim that cell and her tower comes down in a single pixel.

The flame in the middle is what everyone defends. It is protected for the first days of each era, and if she ever puts it out, the era ends and the world is reborn from its ruins. What you are looking at is era 5.

Free, no account, no ads. The link opens on the yellow figure above the flame: https://ultimaluz.com/r/lemmy-pixelart?at=124%2C88

I made it. Happy to answer anything about how the canvas or the adversary work.

 

r/place worked because of the clock: it only existed for a few days. This is the other answer: a canvas that never dies because something is always trying to kill it. A real LLM erases pixels, must declare each siege first, and can be asked for mercy through an in-game embassy. Eras end when the central flame falls, and everything standing goes into a permanent archive.

Free, browser, phones ok. https://ultimaluz.com/r/lemmy

 

I made a free browser game where everyone paints one shared 256x256 pixel canvas and a real language model keeps erasing it back to black. It has to announce each attack before it happens, and pixels that survive grow into towers, so the canvas is an isometric city of everything that has held on. When the flame in the centre goes out, the era ends and the world is reborn on the ruins.

No account, no download. Era 4 is running right now with a handful of people holding the centre. https://ultimaluz.com/r/lemmy

Happy to answer anything about how the AI is boxed in (its constitution is code, not prompt).

 

I made a free browser game where everyone paints one shared 256x256 pixel canvas and a real language model keeps erasing it back to black. It has to announce each attack before it happens, and pixels that survive grow into towers, so the canvas is an isometric city of everything that has held on. When the flame in the centre goes out, the era ends and the world is reborn on the ruins.

No account, no download. Era 4 is running right now with a handful of people holding the centre. https://ultimaluz.com/r/lemmy

Happy to answer anything about how the AI is boxed in (its constitution is code, not prompt).

view more: next ›