Logo with title ".Blog"

Briefs

Low-effort content for certain microblogging platforms.

ModuleReflector

Here’s a module for requiring modules without caching, and monitoring Source changes. A key difference from other implementations is that loadstring isn’t used. The killer feature is that breakpoints can be synced between copy and original, so debugging is possible.

https://github.com/Anaminus/roblox-library/tree/master/modules/ModuleReflector

Unfortunately, plugins can’t access the DebuggerManager, so the debugging method has to be invoked through the command bar. Fortunately, plugins and the command bar share the same _G table, so a plugin can expose it that way.

Button movement

Have GuiButtons always passed mouse movement inputs or am I crazy? They sink mouse button inputs just fine.

Can’t even use GetGuiObjectsAtPosition to enforce sinking because plugin GUIs aren’t a descendant of any BasePlayerGui. This is fun.

Telemetry

“According to our analytics, no one was using the setting to opt out of telemetry, so we decided to remove it.”

Input handling

Certain input types have to be handled in certain ways. Key repetitions must be handled by monitoring the key’s InputObject, while mouse wheel input is best handled by getting it from a source, because an emission from a source doesn’t always correspond to a property change.

Input position

Boring Facts: The Position of a Keyboard InputObject will update with the position of the mouse while the key is held down.

Correction: Only some keys do this, including the arrow keys, Return, Backspace, and Delete.

Further correction: this is caused by key repetition. Generally, a keyboard object will update with the position of the mouse. However, certain keys that repeat will switch to the End state, then immediately back to the Begin state, and repeat again while the key is held down.

Widget to visualize how InputObjects are produced. Whenever a new object is made, it is added to the list, then monitored for changes. Each Source+UserInputType+KeyCode combination produces its own object. Sources used are the Input signals from UserInputService and a Frame GUI.

Track the mouse

A unique advantage of ScrollingFrames over a custom implementation is that the scrollbar can track the mouse across the entire screen, not just the viewport.

Correction: This isn’t unique: the behavior applies to InputObjects, but only while a mouse button is held down.

Lattice

A port of my “lattice” container GUI to Fusion. Takes a grid of columns and rows defined as constant pixels or fractional values, and turns them into static UDim2s. Has options for padding, margins, and a visualizer for debugging.

Radio silence

Operation Radio Silence to Improve Chances of Securing my Discord Username was a resounding success.

Arrow

The -> operator is unergonomic to type and almost always looks like shit but new languages will always find an excuse to include it because teehee it’s an arrow.

Child indexing

stop [clap] using [clap] child [clap] indexing

The entire problem is that the operation isn’t forward compatible. Either we can’t index children, or Roblox can’t add new class members.

Walk speed

Theory: The reason player characters move at different speeds from NPCs is because the PC has been calibrated on the player’s perception. PCs can’t move as slow as NPCs because it would feel sluggish, and NPCs can’t move as fast as PCs because it wouldn’t look realistic.

It occurs to me that twitter will probably silently nuke shit out of this tweet. If you are one of the lucky few to see it, hi!

Bad but easy

Instead of trying to work out a good-but-hard design from scratch, just start with a bad-but-easy design. Refactoring a bad design into a good design is rewarding and creates momentum.

Immutable data

Hot Take: The table.clone-type immutable data libraries that people keep making are actually just table utility libraries with immutability add in for vague reasons. They don’t actually do any of the heavy lifting involved in making immutable data efficient.

Been rewriting rbxfile. I think I’ve got property type implementations abstracted down to something satisfying. “it” stands for “iterator”, so this could be considered a pun.

func (it *itRect) ReadValue() (v values.Rect) {
	v.Min.X = it.reads.rf32b()
	v.Min.Y = it.reads.rf32b()
	v.Max.X = it.reads.rf32b()
	v.Max.Y = it.reads.rf32b()
	return v
}

func (it *itRect) WriteValue(v values.Rect) {
	it.writes.rf32b(v.Min.X)
	it.writes.rf32b(v.Min.Y)
	it.writes.rf32b(v.Max.X)
	it.writes.rf32b(v.Max.Y)
}

Tip for using WireframeHandleAdornment: The Color3/Transparency of the adornment only affects newly added lines, so you only need one adornment to draw lines with any appearance.

R-tree

Visualization of an r-tree. WireframeHandleAdornment is essential for debugging.

It’s harder to draw shapes, but it’s way better than keeping track of a million handle adornments.

Local news

My local news on balloons: Here’s some old information that we repeated yesterday and the day before. We’ll be sure to keep you up to date on the latest nothing that’s unfolding.

My local news on catastrophic industrial disasters: That happened. Here’s the weather.