HNHacker News
TopNewBestAskShowJobs

skitter

759 karma · joined February 5, 2020

submissionscomments
skitter··on The Case for Memory Safe Roadmaps
C++ makes it very difficult to write safe interfaces. You can't expose references, nor spans, nor variants, no shared_ptrs to things that can't be thread-safely overwritten, nor any standard library containers nor a lot of other things. And even if you only use whatever few interfaces remain safe, the interfaces you create are unsafe by default too. As a result, these unsafe interfaces are everywhere.

I'd contend that using Rust for anything nontrivial results in MaybeUninit & co being common.

skitter··on Murder is a pixel art ECS game engine in C#
Could you elaborate on the differences?
skitter··on Murder is a pixel art ECS game engine in C#
One of the commonly mentioned performance advantages of ECSs is the structure of arrays style, which Murder isn't using, so I'm guessing that they're using ECS less for performance reasons and more because they favor the programming style.
skitter··on Murder is a pixel art ECS game engine in C#
New game engines and ECS frameworks are cool to see. Taking a look at the ECS part, Bang, here's an example of a component abridged/adapted from their Ludum Dare entry:

    internal readonly struct CarComponent : IComponent {
        public readonly float Speed = 100f;
        [Slider(1,20f)] public readonly float Mass = 1;
        public CarComponent() {}
    }
and of a system:

    [Filter(typeof(CarComponent), typeof(AgentImpulseComponent))]
    [Filter(ContextAccessorFilter.NoneOf, typeof(DisableAgentComponent), typeof(CarEngineStoppedComponent) )]
    internal class CarMoverSystem : IFixedUpdateSystem {
        public void FixedUpdate(Context context) {
            foreach (var e in context.Entities) {
                var car = e.GetComponent<CarComponent>();                
                Vector2 startVelocity = e.TryGetVelocity()?.Velocity ?? Vector2.Zero;
                var result = DoSomeCalculations(car, startVelocity);
                e.RemoveFriction();
                e.SetVelocity(result);
            }
        }
    }
Looks a bit like DOTS (but I haven't really tried that one either). A system is a class, and which interface it implements determines when it runs. Haven't seen yet where systems are get added to the game / how systems of the same kind get ordered. I'm also curious how a system that does multiple different querries (e.g. one for cars and one for obstacles) looks like.

Bang seems to use source code generators – unlike the generic GetComponent<T> above, TryGetVelocity, RemoveFriction and SetVelocity seem to be generated based on the existence of the Velocity and Friction components. I'm not sure why that is, maybe to cache the component id?

This isn't an archetype-based framework, instead each entity stores a dictionary of component id => component and each system tracks what entities match (also, each entity stores hooks for e.g. when a component gets added, which is used update which systems know about this entity). I don't know how good that's for performance, but for plenty of games performance isn't as important as ease of development.

Also looks like changes are applied immediately. Does this mean that if a system add/remove a component to an entity that affects whether the entity matches the systems filter, it depends on the entity id whether the system processes the entity the same tick?

skitter··on The Fediverse is an opportunity learned societies can't ignore
Only to the extent that different instances choose to federate with Threads, of course.
skitter··on Storing data in pointers
Because Rust strings are utf-8, not all byte sequences are valid strings, so you can actually store a 24-byte string inline (which is what compact_str does).
skitter··on Roc – A fast, friendly, functional language
Neat, looks like the website got an overhaul.

I like Roc's approach of detecting errors statically but still trying to let you run the code. If a snippet is work in progress and has an unused variable, Go or Zig will refuse to compile it. Yes, an unused variable indicates a problem, which is why it's not going to pass any sensible CI setup and make its way into production, but that doesn't mean I should be disallowed from checking whether what I've got so far works. Roc allows¹ running a program with type errors as long as you don't execute a code path affected by them, which I imagine is very useful for refactoring.

The platform approach is also interesting, but I don't know how it will play into code reuse. I guess the different io/platform interfaces might not be quite as big of a problem in a pure functional language? I'm not experienced enough to tell.

¹: I haven't checked how successful it is, given it's immaturity I expect there to be issues

skitter··on datetime.utcnow() is now deprecated
It does, which is great. Note however that Go times can be either wall-time or (wall-time, monotonic time), which have different semantics and are both represented by the same type.
skitter··on datetime.utcnow() is now deprecated
> Then it is UTC

You're absolutely right that it should be, but the problem is that it isn't – Python treats these as belonging to the local time zone.

skitter··on B-trees in Factorio
> BSTs however are not good for disk based storage.

The listed reasons also apply to in-memory storage – searching a btree node is faster than doing the equivalent amount of pointer traversals for a binary tree. Of course this comes at the cost of increased implementation complexity, but unless you're using C, you're probably not implementing your own tree-based map.

You can then use different variants such as packing more entries into interior nodes by only storing values in the leafs (assuming you're making a map and not just a set, that is). If you then link neighboring nodes, you basically have a skip list.

skitter··on Use Timestamps
Timestamps aren't necessarily monotonic anyways – what if the system time changes?
skitter··on Rust without crates.io
My experience of using the AUR is that a decent part of the packages I try to install fail to build, which is certainly pretty secure.
skitter··on C++23: Removing garbage collection support
It was in the spec but never implemented, so it's obly a feature of C++ if you take the stance that there are no real implementations of C++.
skitter··on Six Great Features with the Upcoming Linux 6.6 Kernel
Are abstraction layers still disallowed if they are only able to load GPL code?
skitter··on In search of the least viewed article on Wikipedia (2022)
Me likewise – it makes me happy that there's an 800 word article about a pond that used to exist for less than 200 years in my town.
skitter··on Should you be scared of Unix signals? (2016)
In this case that's before the next bytecode executes. The write syscall gets interrupted and returns EINTR, then cpython checks what signal was caught and executes the signal handler, before trying to do the remaining write:

https://github.com/python/cpython/blob/5f7aba938cf5007b6f954...

Here's even a test for it: https://github.com/python/cpython/blob/5f7aba938cf5007b6f954...

skitter··on Should you be scared of Unix signals? (2016)
Uh, that Examples section calls print inside the signal handler. Python's IO stack is non-reentrant. I hope nobody follows these examples and gets exceptions at runtime because of it.
skitter··on Escape analysis hates copy elision (2021)
That's not about 'using' a reference, it's about constructing an invalid value – no different than doing transmute::<u32,char>(0x110000). See https://www.ralfj.de/blog/2020/07/15/unused-data.html for an explanation why it's UB.
skitter··on How LSP could have been better
That's doable in LSP - the server knows about the selection, not just the cursor position. E.g. if I use rust-analyzer (in Helix, so there aren't any protocol extension in play), select an expression and request hover info, rust-analyzer shows the expression's type.
skitter··on Berry is a ultra-lightweight dynamically typed embedded scripting language
> Systems are the one aspect that for me are hardest to get my head

In an ECS architecture, the world is a database of entities, which are just identifiers, which have components associated with them. Systems is simply code that query this database and operate on the returned data. For example, if you want burning entities to set burnable entities on fire, you might write a system like this, using Bevy as an example:

    fn fire_spread(mut commands: Commands, burning: Query<&Collider, With<Burning>>, flammable: Query<(Entity, &Collider), With<Flammable>>) {
        for col_1 in &burning {
            for (flammable_entity, col_2) in &flammable {
                if col_1.touches(col_2) {
                    commands.entity(flammable_entity).insert(Burning)
                }
            }
        }
    }
The Commands here exists to defer archetype moves – otherwise what should the query do if you added Burning to an entity while the query was running? And of course in a real game, you might want to use a spatial query so time complexity isn't m×n. You could then run this system every tick:

    app.add_systems(Update, fire_spread)
If you're familiar with C++, I can also recommend you check out https://www.flecs.dev/flecs/
skitter··on Berry is a ultra-lightweight dynamically typed embedded scripting language
That page seems to be more about the entity-component architecture (entities are composed of components, which define data and behavior for one aspect of the game) then about entity-component-systems architecture (entities are composed of components, which are pure data; systems can query this database). Traditional Unity, as that site points out, is EC; Unity DOTS is ECS. Not sure why the site would be the bible on the topic either as it only some surface-level information and links (and hasn't been kept up to date much).
skitter··on Glibc dynamic loader hit by a nasty local privilege escalation vulnerability
The vulnerable piece of code didn't need memory unsafety. Sure, __minimal_malloc does, but the bug was in mundane string handling.
skitter··on Glibc dynamic loader hit by a nasty local privilege escalation vulnerability
And some people say string handling in C is easy. Maybe using memory unsafe languages for anything security related isn't such a good idea after all…
skitter··on What every software developer must know about Unicode in 2023
'Character' doesn't have a single meaning. ZWJ is a character according to definitions (2) and (3) in https://unicode.org/glossary/#character
skitter··on Python 3.12
Eh, you still can't pass Python objects between them. This just means that if you run multiple instances of Python, you can do so in the same process. If you use the C api.
skitter··on That's a Lot of YAML
Hm, what JSON documents have a different meaning in YAML? I'd have hoped that with all names & strings being quoted and leading zeros being disallowed, that wouldn't be the case.
skitter··on Exploring Linux command-line space time
Thanks for the clarification. I was questioning my sanity, because collect2 as described in the doc sounds not just hacky, but also like a waste of compile time.
skitter··on Exploring Linux command-line space time
Wow, Collect2 sounds kinda hacky based on the linked documentation¹:

- There is user code that needs to run before main. With C/C++ allowing separate compilation, the compiler invocation that creates the entrypoint doesn't know about all of these static constructors.

- Therefore Collect2 pretends to be ld; when invoked, it tries to call the real ld and examines its output

- It creates a c file with a table containing any constructor symbols it finds, then compiles that

- Finally it links the program again, together with the new object file

¹: https://gcc.gnu.org/onlinedocs/gccint/Collect2.html

skitter··on Archaeologists find 500-year-old board game carved in ruins of Polish castle
It's well known in Germany under the name Mill, but I cannot recall the last time I've seen anyone actually play it.
skitter··on The WebP 0day
Mozilla has an interesting sandboxing strategy: They compile some of the C/C++ parts of Firefox (e.g. the ogg parser) to Wasm and then back to C. Because Wasm is memory safe, the resulting C is too.
← PreviousPage 3 of 8Next →