And on the sixth day God rested, for the damn servers were down anyway.
Briefs
Low-effort content for certain microblogging platforms.
Hipsters, soon: I only consume works from meat-based authors.
Investors: How make number go bigger?
Roblox:
https://devforum.roblox.com/t/beta-update-new-experiences-have-team-create-enabled/2172232

For comparison, stats as displayed on 2022-11-15:

Idiot theory: Roblox made a bad-faith measurement of developers/experiences in Q2, with the stats from Q3 (above) being more accurate. To address number go down, they’re pushing Team Create hard to make number go big again.
Write good code to write good code.
There goes a productive day. Thanks, The Cloud™.
ProximityPrompts make for great general proximity detectors.
The proximity signals are client-only, so validation is still required. But it’s a fast and simple solution for detection. I like to think that it’s been optimized for large numbers of prompts spread across the workspace, so it’d be a winner in that case.
Author’s Note: The tweet this post was derived from was blessed by The Algorithm for some reason.
Using :Once()
on a RemoteEvent will cause the first queued event to be
received and all other queued events to be discarded.
This is a design flaw: connecting to a signal must not fire the signal, which
remotes do. To avoid losing events, the workaround is to enforce a remote to
have exactly one consumer. By this logic, :Once()
isn’t allowed, because it
adds the one consumer then immediately removes it.
The problem is that connecting to the signal fires it and drains the queue. You literally cannot connect multiple listeners without one of them missing the queued events. The only option is a wrapper with one listener that dispatches to multiple listeners.
There are several solutions to the problem. The most backward compatible would be to trigger the dequeue on the first connection as usual, but defer it so that other connections in the same frame have a chance to connect.
Random graph generation. Blue vertices have unexplored edges, while green ones are completely explored. Occasionally connects a new vertex to a nearby existing vertex, forming a loop. Rarely creates a long loop by connecting to the most distant vertex.
The graph is represented by a force-directed graph that moves the vertices around to make them easier to visualize. The actual graph is dimensionless, with the vertices having no 2D or 3D position.
A problem with streaming on Roblox is that a client can just move the camera anywhere, and the server will happily stream whatever is at that location, even if the player is not meant to be there. Developers need to be able to exclude areas from being streamed to certain clients.
2023-01-16 23:14: As a follow up, it turns out to be possible with the Player.ReplicationFocus property. Setting it to a dummy part gives the server the opportunity to deny streaming in. The position of the dummy part matches the character, except when the character moves to an undesired location.
Having some fun with LÖVE.
Here’s a view of the chunk buffer demonstrating simplified chunk loading:
The white area is the viewport. Chunks are updated only when the focus leaves the yellow area. Each corner of the blue area determines which chunks are loaded.
First AI came for the writers
And nothing was said about the writers because they didn’t make any pretty pictures to look at.
Then AI came for the artists
And nothing was said about the writers because they didn’t make any pretty pictures to look at.
You can’t spell futility without utility! winks double snap-pointing gesture winning smile with single sparkle accompanied by “ting” sound
Hope you check dependency diffs before bumping them.
Maintainers Not So Impressed After Influx of Bug Reports Deriving From Copilot Having No Idea What It’s Talking About
It’s current year and we’re still hell-bent on punishing players for not playing our games correctly instead of just shoving them into their own world where they can play however they like.
It seems like AI is really good at appearing correct at a glance. It’s almost like it’s being trained by humans that are just skimming the results.
For future reference, my blog is just a git repo, so any changes will be visible at https://github.com/Anaminus/blog
I’ve been thinking about an implementation of the binary rbxl format where chunks can decode in any order, and empty space is allowed between chunks, which would enable efficient partial modifications to files.
I have reservations about using retweets/boosts/likes/favorites, but Mastodon seems to be less psychotic about them, so I might use them more there.
When a software’s design is poorly understood, the only thing users have to go off of is whatever they’re allowed to do.
Janitor/Maid/etc are different conveniences built on the same core principal: finalization is established near initialization. I continue to assert that maid is a pattern, so the best solution is to either roll your own, or pick whatever best suits your needs.
Here’s my implementation, which represents my current theory on the matter:
https://github.com/Anaminus/roblox-library/tree/master/modules/Maid
As for memory leaks, no library will save you from having the wrong mindset about memory management. Maids and Janitors are just one of the many possible answers to “What am I going to do about this thing I just created once I no longer need it?”
I normally do PascalCase for public, and camelCase for private. But since Roblox’s convention for modules is module.camelCase, I match that instead. So the difference becomes unexportedFunction vs module.exportedFunction, and PascalCase just isn’t used for top-level functions.
Lately I’ve found that Blender has been making up for shortcomings with other software that have nothing to do with modeling.
A perfectly correct but dead project is better than a mostly correct but living project only if the project is already completely finished.
So much software to write, so little brain to write them.
parody? parodeez nutz
The author would like to formally apologize to his friends, family, and followers for having posted this.
Why do we use immediate mode libraries on top of retained mode APIs on top of immediate mode graphics?
my favorite part of roact is how you can instantly tell when it’s being used by the complete lack of keyboard support and the general feeling of sluggishness
It would run much better with a proper component implementation.
Of course, but it wasn’t done that way. Why not? Maybe it’s because Roact makes it easy to do the wrong thing. Or hard to do the right thing. Or both.
My beef with transpiling is writing in one language and receiving errors in another language. Or worse, having to mentally map one to the other while stepping through a debugger. It’s not worth it if the productivity gained during writing is lost during debugging.
I feel like a problem with modules is that a module’s namespace can’t be divided further than one ModuleScript. It would be nice if there were some kind of Package object, where all child ModuleScripts shared the same environment.
Rewriting Binstruct to be more ergonomic. Also added support for recursive type definitions, which is implemented in the VM as subroutines. Continues to be my favorite module to write.

Rewrote Binstruct’s union type to work like an if statement. Here’s what parsing a value for serialized attributes looks like.

Because type definitions in Binstruct are just tables, it’s really easy to create abstractions to make defining types more ergonomic. This is an example of a builder that allows advanced functions to be added to a definition more easily.

The builder in action. The decode/encode functions convert between a finalized value and an intermediate representation that is more easily digested by the codec, though this representation is often useful enough on its own.

All good data formats have a version number. Here’s a constructor that applies versioning to any type. It uses a union to match a version to one of a number of types. The version is also available as a “global”, allowing the value to be inspected from anywhere in the structure.

Type smuggling:
type T = typeof(require(...))
Allows you to get types from a module without requiring it. Does not work with exported types.
To get around exporting, types can be smuggled through the returned table.
local export = {}
-- Innocent module stuff.
function export.new()
end
-- Some types. Must require
-- the module in order to get.
export type Foo = string | number
export type Bar = () -> boolean
-- Smuggle them through
-- the returned table.
export._Foo = (nil::any)::Foo
export._Bar = (nil::any)::Bar
return export
This is incredibly useful for smuggling types from a server module in a client module so the data the client is going to receive from the server via a remote can be fully typed.
So nothing breaks on the client even though the modules containing the server types aren’t replicated, because types don’t matter at runtime. Interesting approach.