Logo with title ".Blog"

Briefs

Low-effort content for certain microblogging platforms.

Responsive design is easy! Just start with the smallest possible size, then scale up to fit the viewport.

Fonts

“I’ll just make my own web-compatible bitmap font. It will be easy.”

Given an array of integers representing the widths of table columns, here is a formula that decides in-place whether a column is considered significantly larger than the others. I use this to decide whether a column should be scaled down to allow the table to fit a maximum width.

T := Sum(array)
L := Length(array)
i := array[index]

big := i/T > (1 - i/T) / (L-1)

It basically compares the proportion of the current column with the average proportion of the rest of the table.

Better formula:

i/T     > (1 - i/T)       / (L-1)
i/T * T > (1 - i/T) * T   / (L-1)
i/T     > (1*T - i/T * T) / (L-1)
i       > (T - i)         / (L-1)

Now I have a decent-looking but crudely-implemented way to render tables in the terminal.

Unions

I’d love to see how many garbage union assets Studio has uploaded on my behalf.

Me, who types in a separate editor and pastes the result into chat out of spite for the typing status.

UniqueId

The format of the UniqueId type for rbxl and rbxlx files.

// Binary format.
type UniqueId struct {
	// All big-endian.
	Sequence  uint32
	Timestamp uint32
	Random    int64  // Zigzag encoded
}
// Interleaved


// XML hash
//
// [random        ][time  ][seq   ]
// 0123456789abcdef0123456789abcdef
//
// Not zigzag encoded!

Boring Facts: UniqueId has one more sequential component that increments every time an instance is created. If this value manages to overflow, the timestamp component is updated. To generate a duplicate ID, you would have to produce over 4 billion instances within 1 second.

GetDebugId

Boring Facts: The number returned by GetDebugId is a signed 32-bit integer that will overflow if more than 2^31 instances have been created.

Boring Facts: The UniqueId type also contains an apparently random sequence of bytes. However, between serialization in the binary and XML formats, there is a shift by one bit. It is possible that this is an implementation error. There turns out to be no errors. When naively comparing the bytes of the two formats, they appear to be shifted by one bit. The reason is that, in XML, the random portion is converted directly to bytes. But in the binary format, zigzag encoding is used.

Boring Facts: The UniqueId type found in Roblox place files contains a timestamp with the epoch set at 2021-01-01. This can be used to determine when an instance was created, per studio session.

Ancestor

Quick way to grab the nearest ScreenGui from a descendant script:

local screen = script:FindFirstAncestorWhichIsA("ScreenGui")

Very excited about how rbxmk documentation is coming together. All of it is compiled with the program, so it can be explored from the terminal. The endgame is to be able to export the entire collection of files to be used for generating a documentation website.

Protip: Search for GlobalSettings_13.xml in your file system. This contains settings for Studio. If you set the “LocalAssetsFolder” setting to a directory, files in that directory can be accessed through rbxasset://. Use this to work on audio before uploading it.

Megaphone

There goes my carefully curated list of Arsenal megaphone spam.

Text-wrapping

Getting text to wrap correctly is surprisingly difficult. I scream internally at the thought of having to deal with double-width characters.

Install

You can tell that a microsoft product is involved when the install process takes 200 times longer than it should.