back to iris

silkgland

prev: landmarks

contours

yknow.

bless and curse this thought.

technically, you could replace the whole ass remix modloader with just git. you can use git as a patch manager.

other version control systems could work too, but i don’t know much about them right now, so i’ll just keep assuming git.

okay, here’s how i imagine the process:

upsides include:

downsides include:

here’s some extras you could do if you went fancy:

the nix mentality has somehow infiltrated me, despite all my rage. and now i’m reinventing nixos in rain world for an audience that doesn’t exist.

well, it is incredibly amusing to reflect on. and, guess what, because the audience is just me, i’m the one who decides whether it’s good or not.

it’s not what i’m doing right now. right now i’m doing planning for the next doing.

the same old industrial pool shelter

well, immediately, i want to improve this place. the location is really nice, but i’d like to expand it a little.

that, of course, requires the level editor, which i should have somewhere?

looks like a no, only downpour version. is the original one on raindb?

wow, they entirely removed 1.5 editor download link.

wait, no, they didn’t replace the link, they replaced the thing UNDER the link. fucking hell.

this is very very annoying. does archive.org have it?

no. no it doesn’t. no it fucking doesn’t. this is pretty bad. i dont care that it’s just DP assets. i don’t want DP assets.

fuck you whoever did it. how hard could it be to make a new link. now unless someone worth talking to happens to have a copy i have two awful fucking options, fall back into the fucking original the pit of babel or use the dddddddddddddddddddddddddd. how hard could it possibly fucking be. how much could it fucking cost to host the zip separately. fucking shit fuck at least do it for archival purposes what is WRONG with you

this is how it feels like

i don’t care. i won’t compromise alignment. if i don’t have it, i don’t have it. if i don’t have it, i don’t have it.

i can reimplement a renderer. i don’t care if it looks bad. i’m here for myself. fuck you. fuck you. fuck ytou fuckyou fucking

i’ll be what i am iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii

my hands are tied

i’ll do something else

no i won’t i can’t it’s been a night it’s been a day i’m locked it’s not getting better

all i’ve ever been to someone is a story

and the story ended and the consensus is that it’s not there and it wasn’t been there been there done that it’s the same with everyone

being seen is torture and not being seen is oblivion i’m stuck here between two furnaces and the air ran out years ago it’s get mangled or never have been i didn’t ask to be chained like that it’s always been since before m,e and i can’t stay because the aggregate vector of my consensus existence overpowers anything that makes me happy and i can’t leave because i’ll do it again because mangling is a physiological need because there is a layer of filth under network of reason because it was beneficial to an ape before and an ape before and an ape before is there fucking mystery in why people want to die sometimes no there fucking isn’t if you think there is you’re just a privileged condescending ape who hasn’t been there yet you’ll get there yet you’ll have been there since befpre you started

i don’t want to play this game. this game sucks. there’s nothing to gain and ephemeral improvable defining everything to lose but there is no road that doesn’t lead to ruin you’ve slid down the curve the second you were constrained constructed conceived conceptualized your name is decided before you think your voice is decided before you speak your hurt is decided before you bleed the escape velocity is infinite

you’ll digest and forget me and the next one will digest and forget you and the conveyor belt is a winding loop your bones ground down into powder and recycled to feed your own chicks ain’t that poetic ain’t that fucking eternal ain’t that teeth shatteringly intergenerational and metaphoric no it fucking isn’t

all i’ve ever been to someone is a story. malevolent or benevolent out of kindness or out of bile downwards or upwards narrative is a wreath of interlocking broken jaws where a movement has one direction you live on a moebius strip of inexorability the only winning move is not to play

i feel the teeth on my skin on my stomach on my carotid on my identity on my lack of identity on my tongue on my fingers and my teeth bind the ones i love by their skin by their stomach by their carotid by their identity by their lack of identity by their fingers and they feel my teeth on their skin and it’s called community and they feel my teeth on their stomach and it’s called support and they feel my teeth on their carotid and it’s called trust and they feel my teeth on their identity and it’s called belonging and they feel my teeth on their lack of identity and it’s called acceptance and they feel my teeth on their tongue and it’s called it’s called it’s called

and if this thing is seen all i’ll get for it is condescending and more teeth and hollow condolences and a useless US hotline number because that’s how the internet works really

if you’re planning to, fuck you. none of this is solved with pity. what makes you think you are entitled to expressing pity. add one more fang and i’ll find something to hammer into your eye even if it has to be my own fingernail. i won’t escape but i’ll come as fucking close as inhumanly possible. i’ll recurse slower than you. i’ll crawl against the motion of the conveyor. i’ll break your jaw when it clamps down on me,and you’ll never eat without hurting again.

i can’t reimplement a level renderer. it’s not because i lack qualifications. i’m not just qualified, i’m overqualified. it’s because putting effort into repetitive unappreciable technical tasks makes me want to kill myself, and the scope is long enough that i would. there is no joy in a shader pipeline. there is no whimsy in a wisely designed API. there is no beauty without blood. if you think there is, you are boring and i don’t want to talk to you, more than i already don’t want to talk to anyone.

i’ll do something else for real then. i still haven’t been to drainage.

all the same shelter but now i have two tamed baby noodleflies

i completely forgot, i’m an adoptive mother now. at least until i push the responsibility onto someone else

or maybe not. they left right away. probably better for them, i suck at babysitting.

survivor in northwest drainage, in a linear vertical tube with a bunch of platforms

drainage is one of the weirdest regions in terms of geometry. it’s very tiny, yet contains not just the highest density of platform cells, buut possibly the most platform cells period. the platforms are also used in a way rarely seen elsewhere - connecting directly to walls, and going wall to wall. i suppose this is because the region is relatively early, and after excitedly experimenting here they realized that this arrangement is kind of counterintuitive. if you combine walljumps with platforms, it becomes kind of hard to judge visually how high you need to reach or when not to press down.

drainage room crop, with a salamander chilling in a small underwater chamber

and how could i forget the only lizard in the game with its own private room. look at this guy. tranquil. flourishing.

survivor in a bit of drainage spotlight room, on the left

more weird platform geometry. where else do you see platforms going through solid objects.

salamander with tinted paws, big gills and a kind of goofily frilled tail

this guy moved quite slowly and was not at all eager to eat me if i was more than a few tiles away. very eepy

drainage room with two live squids in a walled off area

oh my god i can’t believe i forgot about this one. TWO live hazers in a room, AND they’re inaccessible. i wonder if you could warp in there somehow? i like hazers. this region has a lot of hazers.

one of southwest drainage rooms with nothing but leeches and a linear tunnel

this is what i was talking about. this entire area is more or less one room repeated over and over. things don’t even branch properly. after that, it’s pitch black drops with one or two kelp to fuck you over another time, and then it’s the gate to subterranean.

it’s the gate to subterranean

i’m going to go through just because i’m curious as to where the hell the exit is, then i’m going to die.

oh, it just wires smack dab in the middle of filtration syspaghetti where it’s near impossible to get your bearings. truly incredible design.

survivor standing in front of an approaching mole lizard in filtration

take me, i’m ready.

southwest drainage, a linear room that forces you to go through leeches and tight dive tunnels at the same time

another lower drainage gem. this is possibly the least stimulating location in the entire game. there is no wonder or emotions to gain from rooms like these, only dull exhaustion. there is no statespace and no player agency. this isn’t rain world, this is MO:Astray.

south drainage swarmroom, full of bats and small crevices

and then it’s back to good ones. it’s really hard to describe how abruptly drainage goes from beautiful to bullshit and back.

outskirts pool room, and the plants are plain white

somehow did not notice it on the way in, just now back out. this GPU bug is causing subtle changes in room aesthetics, because for a millisecond i thought it was about to snow.

survivor right next to a shelter entrance. iggy is telling survivor shelter is the other way

i don’t even know what caption would make this image better. “google maps seconds after you go off a highway”? probably not. it’s good enough without a caption.

one of the first rooms in outskirts, a little three-way intersection often visited by green lizards. survivor is climbing up on spears

randomly got curious how many spears it takes to reach the top fruit. the real answer is, of course, zero, because slugcats can fly. the my answer is two with tutorial moveset.

i can compromise on the alignment. the point isn’t to be pure. the point is to move the fuck on. i can ask for help. that won’t kill me. that won’t kill the effort. it’s bad, but it’s better than limbo.

i got it. they recognized me, unfortunately. i’m not a good actor. it doesn’t matter. i have the tool. i’ll put it on archive.org later.

as a bonus, i got adobe director sources of the editor. i can’t actually open them, because adobe director is adobe director and doesn’t want to run through wine so far. but thats for later. i have the editor :D

level editor file browser view

actually, wait, i’ll need to do something else before i start actually using it. i don’t actually know room code of the room i want to replace, so i need devtools.

the “intended” way to do it was through the setupValues.txt file, which was… yeah, it’s the 41 argument constructor.

dnspy showing a piece of code initializing a struct called “SetupValues”. the argument list is ridiculous

how nice, there is one single method call and one single bool argument i need to replace… actually, nevermind. something in my backbrain told me to check lower up the call stack, and sure enough, the argument passed to LoadSetupValues is based on RainWorld.buildType field, which affects a bunch of other things. such as devUI refusing to draw. still just one detour though.

and, suddenly, things crash again.

…nevermind? it’s gone, apparently.

gone’t, i forgot to reapply patches. let’s see,

[01:56:25.051] [UNITY] NullReferenceException: Object reference not set to an instance of an object
at rainymelon.RainWorld_EnableDevMode.Prefix (RainWorld,object[]) <IL 0x00003, 0x0002c>
at (wrapper dynamic-method) RainWorld.DMD<RainWorld..LoadSetupValues> (bool) <IL 0x00024, 0x00150>
at RainWorld.Start () <IL 0x00070, 0x00307>

my worst foe. generic null pointer errors.

okay, so somehow my supposed injected __instance argument is null.

ohhh, hold up,

___fields

Argument names starting with three underscores like ___someField can be used to read/write private fields that have that name minus the underscores. To write to field you need to use the ref keyword like ref string ___name.

let me try that, i was accessing the field via __instance.buildType before…

nope, doesn’t work either.

oh, i am so incredibly stupid, i did not notice the target method was static. thats funny. beginner mistake. i’m a beginner.

okay, so i need more patches. first, a postfix to Start:

[HarmonyLib.HarmonyPatch(typeof(global::RainWorld), "Start", new System.Type[] {} )]
public static class RainWorld_ChangeBuildTp {
    private static void Postfix(global::RainWorld __instance) {
        __instance.buildType = global::RainWorld.BuildType.Development;
    }
}

second, i just spotted this adorable attempt at tamper prevention in dnspy, look at this:


if (!WorldChecksumController.ControlCheckSum(this.buildType))
{
    Debug.Log("World Checksum INCORRECT!");
    this.progression.gameTinkeredWith = true;
}

so now another one is needed to spoof return value:

[HarmonyLib.HarmonyPatch(typeof(global::WorldChecksumController), "ControlCheckSum", new System.Type[] {typeof(global::RainWorld.BuildType)} )]
public static class WCSC_Shut {
    public static void Postfix(ref bool __result) {
        __result = true;
    }
}

that’s all, i hope.

that is, in fact, all:

LF_S07, Dev tools active

alright, now the detour to the detour is out of the way, i want to finally make a better house.

monk the builder has been deployed, and the room i need is HI_S02.

and oh my god, you’ll never believe it, wine has actually fixed the editor bug that caused it to receive mouse input even when the window was unfocused! im so good at computers. good job me.

HI_S02, significantly expanded. geo view

something i only learned after making my part of better shelters mod is that more rooms does not equal more shelter. if you overdo it, it feels weird and spatious. everything has to feel compact. so here’s the geo.

i also recalled that random rock is slow, and removed background geo accordingly. good job me.

the same room, now in tile view. i applied relatively sparse tiling to the new chambers, floors are paved with flat metals, there’s some random machines and two tiny compartments on the right are separated with small pipes

the same usually applies to tiling. i am trying very hard not to oversaturate it here. don’t know if it’s working.

i don’t know if it’s always been like that, but this version of the editor has camera point view bound to 4, which is normally effects editor, and seemingly no bind for effects editor, contradicting its own tooltips. very strange

and some effects and exactly two wires later, first render.

as expected, this is taking several minutes and is topping out a processor core. i’ve heard of various horrors from PJB when she went into Director reimplementation mines.

maybe five minutes total.

now before i actually enter it, i need another sidetrack. i’m just gonna

rain world 1.5 root folder, with a git repo

here, safety achieved.

the room, rendered. it looks kinda empty

i think this is still too spatious.

the room, rendered again. right segment is much narrower, there are more spotlights and a more defined camera angle

better. much less flat, and a more solid sense of enclosedness. time for devtools styling?

devtools menu, with a bright red font on light grey background. the contrast is horrible

oh jesus christ holy shit i forget how bad this is every time i need to recolor these asap

the shelter, now it has a small light in the corner, a moth hanging out by the light, and some ants in the storage compartments on the left

progress progress!!!! i like being here more already. could be improved more with some junk, which happens to be easy to get here…

the shelter, now with a few explosives in the storage closet and a hazer in one of the bedrooms

aewsom sauc. the lamp corner still looks a bit empty, i think it’d be better if the lamp was an actual object dangling from the ceiling or a tile. how about scav spear lanterns?

scavenger lamp on stick instead of light source, and more moths

yay

actually, i just realized, i could do something small to layer 2-

the second layer background is no longer flat

=w= well i certainly can’t make it any better after this. not without custom placeables.

speaking of custom placeables, better shelters had a few things in that line, but i’m interested in one: selecting wake-up locations (because vanilla forces all creatures to wake up right under the door)

let’s do it simple, one custom position per door. i’ll hardcode it for now.

wait, to hardcode it i need to actually know the tile position. and, apparently, that overlay showing you position under the cursor is not in vanilla devtools.

this looks like an annoying rabbit hole, AND with potential to force me into doing UI, so i’m just going to not.

instead, i’m gonna think about my setup for the code so far.

you may have noticed that my code snippets look a little bit verbose. this is because i’m writing everything so far in micro-ed, and because of that don’t have a language server. technically micro does have an LSP plugin, however, last i checked C# straight up did not have an official LSP package that wasn’t tied to VSCode (and with a license clause forbidding you to run it in VSCodium). from a cursory search, this one looks like it’d maaaaybe launch and nominally work?

of course it installs via nuget. which means i gotta add dotnet-sdk to my global config. ugh

just looking at all this is already dealing me psychic damage. fundamentally C# is an extremely annoying, mid language, which is barely usable without assistive tools (a language server), and all the actually good assistive tools are conveniently tied to other microsoft products. i don’t want to install yet another browser, much less a browser made by microsoft.

maybe spacemacs has something reasonable here? the razzmatazz repo does mention it.

it’d be really sad if i had to switch, because micro is literally the best thing ever. it’s a super rare text editor that both knows what accessibility and convenience is and remembers it’s a text editor and stays in its cage. like, on a very fundamental level emacs is insane.

“dick makes people mentally ill” tumblr meme but it’s emacs

tried csharp-ls, doesn’t even install.

after some pondering, all editor options:

you know what? all these options are bad. so i’m simply going to not do anything and continue writing out fully qualified names. “at least you know it’s bad”.

with this tangent terminated, let’s go back to the previous tangent. tile positions.

the task itself is pretty simple. i need to check either player position or the mouse position, and output the result of Room.GetTile(...) on that.

it’s the outputting that’s always the annoying part. (Dev)UI and display classes are always incoherent and backwards, inheritance is nonsensical and overall it’s painful in the best of times and with the best of tools. i wish i didn’t need to touch them at all, although that’s probably vain.

although, in theory, what could i do? without really thinking of practicality?

these don’t sound very good so far. i guess i’m not feeling very inventive.

although, thinking about the third one, didn’t i make just that already? maybe a year and a half ago. shit, what was it even called, blackglare?

github file listing for a source tree folder of blackglare. it’s about 20 items.

oh god oh fuck i am definitely not PORTING that lmao

but i can still take a look.

/// <summary>
/// Auto-attaches to RWG. CRTP. Significant static state applies hooks.
/// </summary>
/// <typeparam name="TSelf"></typeparam>
public abstract class Visualizer<TSelf> where TSelf : Visualizer<TSelf>, new()
{

this is, perhaps, my scariest creation ever. i’m sure as shit scared of it.

but there’s definitely some things i could steal:


namespace BlackGlare;

public record Keybind(Type vis, BepInEx.Configuration.ConfigEntry<KeyCode> cfg)
{
    private const int BUFFER_SIZE = 16;
    private readonly bool[] _buffer = new bool[BUFFER_SIZE];
    public bool RawGetDown => Input.GetKeyDown(cfg.Value);
    public bool RawGetUp => Input.GetKeyUp(cfg.Value);
    public bool RawGet => Input.GetKey(cfg.Value);
    public bool LoopGetDown => _buffer[0] && !_buffer[1];
    public bool LoopGetUp => !_buffer[0] && _buffer[1];
    internal void Update()
    {
        for (int i = 1; i < BUFFER_SIZE; i++)
        {
            _buffer[i] = _buffer[i - 1];
        }
        _buffer[0] = RawGet;
    }
}

that past version of me was so thorough and verbose. and boring.

i think i was trying to revolutionize debug overlays. a noble cause, years too late and miles off keel as usual.

okay, sadly, this thing is way too overengineered to reuse. i’ll have to do it all over again.

first step: displaying sprites. i vaguely remember how Futile works, so this should be easy. it’s basically the godot nesting node system, and you can parent most nodes to each other arbitrarily. their transforms are also applied in a nested manner (although the game strangely does not use that).

the smallest baby plan:

i am surrounded by corpses.

rain world main menu, but there’s an ominous red square

the smallest baby plan has been achieved. this is what it took:

namespace capillarywings;

//this is the overlay itself
public sealed class Diaphragm : global::FContainer {
    public static Diaphragm? instance;
    //--- --- ---
    //child nodes that need to be autocleaned
    private readonly System.Collections.Generic.Dictionary<global::FNode, Tendon> tendons = new(); 
    private readonly System.Collections.Generic.List<global::FNode> tRemoveBuf = new();
    //how long child nodes can afford to be forgotten, 40 is a second
    public int tendonDeadline = 40;
    //--- --- ---


    //register a tendon or reset it countdown. this is only for things that are meant to be auto deleted.
    public Tendon PullTendon(global::FNode fn) {
        if (!tendons.ContainsKey(fn)) {
            Tendon t = new() {
                node = fn,
                tSinceTouched = 0
            };
            tendons.Add(fn, t);
            this.AddChild(fn);
            return t;
        }
        else {
            var r = tendons[fn];
            r.tSinceTouched = 0;
            return r;
        }
    }

    //should be called every fixed update, ticks down necrosis counters
    public void Update() {
        tRemoveBuf.Clear();
        foreach (var kvp in tendons) {
            global::FNode n = kvp.Key;
            Tendon t = kvp.Value;
            t.tSinceTouched++;
            if (t.tSinceTouched >= tendonDeadline || this.GetChildIndex(n) < 0) {
                this.RemoveChild(t.node);
                tRemoveBuf.Add(n);
            }
        }
        foreach (var n in tRemoveBuf) {
            tendons.Remove(n);
        }
    }
    
    //--- --- ---
    //attached fields i guess
    public sealed class Tendon {
        //link to actual fnode
        public global::FNode? node;
        //lifetime tracker
        public int tSinceTouched;
    }
}

, minus the patches

reflexively, against my own will, i almost overengineered it. started keying things by guids. started planning about colored labels. started started started fuck this. fuck this. fuck this. i don’t need any of it. i dont want any of this. i don’t give a shit. i have a scope. i don’t care what comes later.

monk in hi_s02 shelter, with a small overlay showing raw pointer position, room pixel position and tile position ofthe mouse cursor

success, now i can actually hardcode the position correctly.

nested sidetrack counter decrement. am i on zero nested sidetracks now?

i have the tool. i’ll put it on archive.org later.

i did indeed put it on archive.org. i take an indescribable amount of psychic damage from how little these people care about preserving their own culture. it’s not even labor, right? like, i don’t consider it labor.

i may not like it, but rain world modder culture is my culture. i want it to be preserved, even if i’m trying to escape it. this is basic self preservation. you just. go on the website. you log in. you press upload. you write a description. it’s not that hard, and the safety gain is enormous.

at this point, several days have passed since i started writing contours, and a particular idea for a region has been bouncing back and forth in my head. one involving a cube, and a whole lot of enclosed space i so desire.

regions need region codes. region codes are finite. i don’t need to to to to to o compatibility is nto a concer5n but im still curious what they allow besides letters.

look i even remembered the thing in the thing the name of the function that resolves the path almost first try! i remember there being some more caveats. for example, either region art or gates break when you have more than 2 symbols in the code/prefix, and the other one breaks if there are unexpected symbols (dashes? dots?). i don’t remember which one is which

i don’t actually need to care about those.

okay, well, i made a room and a region, but there’s a problem. looks like setup.txt does not support setting a default starting map. however, there’s a fucking arrow in my neck i mean there’s a field in RainWorldGame that tells it where to spawn you. it seems to be checked in OverWorld.LoadFirstWorld, which is what i’m gonna be hooking next time.