<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <title>Matthew Berger</title>
  <link href="https://matthewberger.dev/articles/" rel="alternate"/>
  <link href="https://matthewberger.dev/articles/atom.xml" rel="self"/>
  <id>https://matthewberger.dev/articles/</id>
  <updated>2026-08-09T00:00:00+00:00</updated>
  <author>
    <name>Matthew J. Berger</name>
  </author>
  <subtitle>Experienced software engineer with a passion for graphics and Rust</subtitle>
  <entry>
    <title>Build your own ECS (part 3), change detection, events, tags, and commands</title>
    <link href="https://matthewberger.dev/articles/posts/build-your-own-ecs-events-changes-tags-commands/" rel="alternate"/>
    <id>https://matthewberger.dev/articles/posts/build-your-own-ecs-events-changes-tags-commands/</id>
    <updated>2026-08-09T00:00:00+00:00</updated>
    <summary type="text">The four subsystems that turn the storage layer into something a real game engine can sit on top of. A watermark-based change detector, double-buffered events, sparse-set tags, and a deferred command buffer.</summary>
    <content type="html">&lt;p&gt;&lt;em&gt;This is part 3 of 3 of a series.&lt;/em&gt; ← &lt;a href=&quot;@/posts/2026-08-02-build-your-own-ecs-structural-change.md&quot;&gt;Structural change and queries&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;@/posts/2026-08-02-build-your-own-ecs-structural-change.md&quot;&gt;Part 2&lt;/a&gt; finished with a working archetype ECS. Spawn into an archetype, add and remove components at runtime, query and iterate by component combination, despawn safely. The storage is solid, the routing is fast, and you could build a small game on it. What you could not do was build a &lt;em&gt;frame loop&lt;/em&gt; on it. The missing pieces are the things systems use to talk to each other and to the world structurally.&lt;/p&gt;
&lt;p&gt;This post adds four pieces. Change detection records what moved so other systems can do incremental work instead of touching everything each frame. Events let one system message another across the schedule without coupling them. Sparse-set tags carry markers that flip too often to live in the archetype mask. Command buffers queue mutations during iteration so the loop does not invalidate itself. A small system schedule at the end runs the four in order.&lt;/p&gt;
&lt;p&gt;By the end of the post you have an ECS kernel that closely mirrors what production libraries expose, in about 825 lines of Rust.&lt;/p&gt;
&lt;p&gt;Start from the file at the end of part 2.&lt;/p&gt;
&lt;h2 id=&quot;change-detection-by-watermark&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#change-detection-by-watermark&quot;&gt;#&lt;/a&gt;Change detection by watermark&lt;/h2&gt;
&lt;p&gt;The render system wants to push transforms to the GPU only for entities that moved this frame. Recording &quot;which slot was written&quot; needs to cost less than the work that prompted the write, or the bookkeeping becomes more expensive than the thing it is tracking. A &lt;code&gt;HashSet&amp;lt;Entity&amp;gt;&lt;/code&gt; of dirty entities would work but every mutation would touch a hashmap, which fails the cost test.&lt;/p&gt;
&lt;p&gt;The cheaper shape is a parallel &lt;code&gt;Vec&amp;lt;u32&amp;gt;&lt;/code&gt; of tick stamps next to each component vec, indexed in lockstep with &lt;code&gt;entities&lt;/code&gt;. Every mutation writes the current frame&apos;s tick into the slot. To find what changed since last frame, walk the stamps and ask whose value is greater than the watermark from the end of the previous frame. No clearing pass between frames. The watermark moves and the old stamps are stale relative to it without ever being touched.&lt;/p&gt;
&lt;div class=&quot;bamboo-code-block&quot; data-bamboo-code data-bamboo-lang=&quot;rust&quot;&gt;&lt;div class=&quot;bamboo-code-toolbar&quot;&gt;&lt;button type=&quot;button&quot; class=&quot;bamboo-code-button&quot; data-bamboo-line-toggle aria-label=&quot;Toggle line numbers&quot; aria-pressed=&quot;false&quot; title=&quot;Toggle line numbers&quot;&gt;&lt;svg class=&quot;bamboo-code-icon&quot; viewBox=&quot;0 0 20 20&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;1.6&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M4 5h2M4 10h2M4 15h2&quot; stroke-linecap=&quot;round&quot;/&gt;&lt;path d=&quot;M9 5h7M9 10h7M9 15h7&quot; stroke-linecap=&quot;round&quot;/&gt;&lt;/svg&gt;&lt;/button&gt;&lt;button type=&quot;button&quot; class=&quot;bamboo-code-button&quot; data-bamboo-copy aria-label=&quot;Copy code&quot; title=&quot;Copy code&quot;&gt;&lt;svg class=&quot;bamboo-code-icon bamboo-code-icon-copy&quot; viewBox=&quot;0 0 20 20&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;1.6&quot; aria-hidden=&quot;true&quot;&gt;&lt;rect x=&quot;7&quot; y=&quot;3&quot; width=&quot;10&quot; height=&quot;12&quot; rx=&quot;2&quot;/&gt;&lt;path d=&quot;M5 7v8a2 2 0 0 0 2 2h6&quot;/&gt;&lt;/svg&gt;&lt;svg class=&quot;bamboo-code-icon bamboo-code-icon-check&quot; viewBox=&quot;0 0 20 20&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;2&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M4 10l4 4 8-8&quot; stroke-linecap=&quot;round&quot; stroke-linejoin=&quot;round&quot;/&gt;&lt;/svg&gt;&lt;/button&gt;&lt;/div&gt;&lt;pre style=&quot;background-color:#2b303b;color:#c0c5ce;&quot;&gt;&lt;code class=&quot;language-rust&quot;&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;#[&lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;derive&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(Default)]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub struct &lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;ComponentArrays {
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;mask&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u64&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;entities&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;: Vec&amp;lt;Entity&amp;gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;positions&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;: Vec&amp;lt;Position&amp;gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;positions_changed&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;: Vec&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u32&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;&amp;gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;velocities&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;: Vec&amp;lt;Velocity&amp;gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;velocities_changed&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;: Vec&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u32&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;&amp;gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;For every component vec we add a parallel &lt;code&gt;Vec&amp;lt;u32&amp;gt;&lt;/code&gt;. The convention is &lt;code&gt;positions[i]&lt;/code&gt;, &lt;code&gt;positions_changed[i]&lt;/code&gt;, and &lt;code&gt;entities[i]&lt;/code&gt; always describe the same entity slot.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;World&lt;/code&gt; grows two counters.&lt;/p&gt;
&lt;div class=&quot;bamboo-code-block&quot; data-bamboo-code data-bamboo-lang=&quot;rust&quot;&gt;&lt;div class=&quot;bamboo-code-toolbar&quot;&gt;&lt;button type=&quot;button&quot; class=&quot;bamboo-code-button&quot; data-bamboo-line-toggle aria-label=&quot;Toggle line numbers&quot; aria-pressed=&quot;false&quot; title=&quot;Toggle line numbers&quot;&gt;&lt;svg class=&quot;bamboo-code-icon&quot; viewBox=&quot;0 0 20 20&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;1.6&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M4 5h2M4 10h2M4 15h2&quot; stroke-linecap=&quot;round&quot;/&gt;&lt;path d=&quot;M9 5h7M9 10h7M9 15h7&quot; stroke-linecap=&quot;round&quot;/&gt;&lt;/svg&gt;&lt;/button&gt;&lt;button type=&quot;button&quot; class=&quot;bamboo-code-button&quot; data-bamboo-copy aria-label=&quot;Copy code&quot; title=&quot;Copy code&quot;&gt;&lt;svg class=&quot;bamboo-code-icon bamboo-code-icon-copy&quot; viewBox=&quot;0 0 20 20&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;1.6&quot; aria-hidden=&quot;true&quot;&gt;&lt;rect x=&quot;7&quot; y=&quot;3&quot; width=&quot;10&quot; height=&quot;12&quot; rx=&quot;2&quot;/&gt;&lt;path d=&quot;M5 7v8a2 2 0 0 0 2 2h6&quot;/&gt;&lt;/svg&gt;&lt;svg class=&quot;bamboo-code-icon bamboo-code-icon-check&quot; viewBox=&quot;0 0 20 20&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;2&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M4 10l4 4 8-8&quot; stroke-linecap=&quot;round&quot; stroke-linejoin=&quot;round&quot;/&gt;&lt;/svg&gt;&lt;/button&gt;&lt;/div&gt;&lt;pre style=&quot;background-color:#2b303b;color:#c0c5ce;&quot;&gt;&lt;code class=&quot;language-rust&quot;&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;#[&lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;derive&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(Default)]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub struct &lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;World {
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;allocator&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;: EntityAllocator,
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;entity_locations&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;: EntityLocations,
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;tables&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;: Vec&amp;lt;ComponentArrays&amp;gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;table_lookup&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;: HashMap&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u64&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;usize&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;&amp;gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;table_edges&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;: Vec&amp;lt;TableEdges&amp;gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;query_cache&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;: HashMap&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u64&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;, Vec&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;usize&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;&amp;gt;&amp;gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;current_tick&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u32&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;last_tick&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u32&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;current_tick&lt;/code&gt; is the value we stamp into a slot when it is modified. &lt;code&gt;last_tick&lt;/code&gt; is the watermark. Slots stamped &lt;em&gt;after&lt;/em&gt; &lt;code&gt;last_tick&lt;/code&gt; are considered changed. The frame-advance function moves both.&lt;/p&gt;
&lt;div class=&quot;bamboo-code-block&quot; data-bamboo-code data-bamboo-lang=&quot;rust&quot;&gt;&lt;div class=&quot;bamboo-code-toolbar&quot;&gt;&lt;button type=&quot;button&quot; class=&quot;bamboo-code-button&quot; data-bamboo-line-toggle aria-label=&quot;Toggle line numbers&quot; aria-pressed=&quot;false&quot; title=&quot;Toggle line numbers&quot;&gt;&lt;svg class=&quot;bamboo-code-icon&quot; viewBox=&quot;0 0 20 20&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;1.6&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M4 5h2M4 10h2M4 15h2&quot; stroke-linecap=&quot;round&quot;/&gt;&lt;path d=&quot;M9 5h7M9 10h7M9 15h7&quot; stroke-linecap=&quot;round&quot;/&gt;&lt;/svg&gt;&lt;/button&gt;&lt;button type=&quot;button&quot; class=&quot;bamboo-code-button&quot; data-bamboo-copy aria-label=&quot;Copy code&quot; title=&quot;Copy code&quot;&gt;&lt;svg class=&quot;bamboo-code-icon bamboo-code-icon-copy&quot; viewBox=&quot;0 0 20 20&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;1.6&quot; aria-hidden=&quot;true&quot;&gt;&lt;rect x=&quot;7&quot; y=&quot;3&quot; width=&quot;10&quot; height=&quot;12&quot; rx=&quot;2&quot;/&gt;&lt;path d=&quot;M5 7v8a2 2 0 0 0 2 2h6&quot;/&gt;&lt;/svg&gt;&lt;svg class=&quot;bamboo-code-icon bamboo-code-icon-check&quot; viewBox=&quot;0 0 20 20&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;2&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M4 10l4 4 8-8&quot; stroke-linecap=&quot;round&quot; stroke-linejoin=&quot;round&quot;/&gt;&lt;/svg&gt;&lt;/button&gt;&lt;/div&gt;&lt;pre style=&quot;background-color:#2b303b;color:#c0c5ce;&quot;&gt;&lt;code class=&quot;language-rust&quot;&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl &lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;World {
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub fn &lt;/span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;step&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(&amp;amp;&lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;.last_tick = &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;.current_tick;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;.current_tick = &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;.current_tick.&lt;/span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;wrapping_add&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;After &lt;code&gt;step()&lt;/code&gt;, &lt;code&gt;last_tick&lt;/code&gt; is what &lt;code&gt;current_tick&lt;/code&gt; was a moment ago, and &lt;code&gt;current_tick&lt;/code&gt; is one higher. Slots stamped during the just-finished frame have ticks &lt;code&gt;== last_tick&lt;/code&gt;, which fails the &lt;code&gt;&amp;gt; last_tick&lt;/code&gt; check, so they no longer count as changed. Slots modified in the new frame will get the new &lt;code&gt;current_tick&lt;/code&gt;, which is &lt;code&gt;&amp;gt; last_tick&lt;/code&gt;, so they will. No clearing.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;wrapping_add&lt;/code&gt; here is a corner this design papers over. After &lt;code&gt;2^32&lt;/code&gt; frames the tick rolls back to zero, and a slot stamped at the old &lt;code&gt;u32::MAX&lt;/code&gt; suddenly looks ancient when &lt;code&gt;last_tick&lt;/code&gt; is also &lt;code&gt;u32::MAX&lt;/code&gt;. At 60 frames per second that is about 2.3 years of continuous runtime, fine for a game and not fine for a long-running server. A production engine either widens the tick to &lt;code&gt;u64&lt;/code&gt; or runs a periodic rebasing pass that subtracts the watermark from every stamp.&lt;/p&gt;
&lt;p&gt;Every place that pushes to a component vec also needs to push to its &lt;code&gt;_changed&lt;/code&gt; vec, and every place that modifies an existing slot needs to stamp the current tick. Spawn first.&lt;/p&gt;
&lt;div class=&quot;bamboo-code-block&quot; data-bamboo-code data-bamboo-lang=&quot;rust&quot;&gt;&lt;div class=&quot;bamboo-code-toolbar&quot;&gt;&lt;button type=&quot;button&quot; class=&quot;bamboo-code-button&quot; data-bamboo-line-toggle aria-label=&quot;Toggle line numbers&quot; aria-pressed=&quot;false&quot; title=&quot;Toggle line numbers&quot;&gt;&lt;svg class=&quot;bamboo-code-icon&quot; viewBox=&quot;0 0 20 20&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;1.6&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M4 5h2M4 10h2M4 15h2&quot; stroke-linecap=&quot;round&quot;/&gt;&lt;path d=&quot;M9 5h7M9 10h7M9 15h7&quot; stroke-linecap=&quot;round&quot;/&gt;&lt;/svg&gt;&lt;/button&gt;&lt;button type=&quot;button&quot; class=&quot;bamboo-code-button&quot; data-bamboo-copy aria-label=&quot;Copy code&quot; title=&quot;Copy code&quot;&gt;&lt;svg class=&quot;bamboo-code-icon bamboo-code-icon-copy&quot; viewBox=&quot;0 0 20 20&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;1.6&quot; aria-hidden=&quot;true&quot;&gt;&lt;rect x=&quot;7&quot; y=&quot;3&quot; width=&quot;10&quot; height=&quot;12&quot; rx=&quot;2&quot;/&gt;&lt;path d=&quot;M5 7v8a2 2 0 0 0 2 2h6&quot;/&gt;&lt;/svg&gt;&lt;svg class=&quot;bamboo-code-icon bamboo-code-icon-check&quot; viewBox=&quot;0 0 20 20&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;2&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M4 10l4 4 8-8&quot; stroke-linecap=&quot;round&quot; stroke-linejoin=&quot;round&quot;/&gt;&lt;/svg&gt;&lt;/button&gt;&lt;/div&gt;&lt;pre style=&quot;background-color:#2b303b;color:#c0c5ce;&quot;&gt;&lt;code class=&quot;language-rust&quot;&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl &lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;World {
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub fn &lt;/span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;spawn&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(&amp;amp;&lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;mask&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u64&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;) -&amp;gt; Entity {
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt; entity = &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;.allocator.&lt;/span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;allocate&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;();
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt; table_index = &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;get_or_create_table&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(mask);
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt; current_tick = &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;.current_tick;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt; table = &amp;amp;&lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;.tables[table_index];
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt; array_index = table.entities.&lt;/span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;len&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;();
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        table.entities.&lt;/span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;push&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(entity);
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;if&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt; mask &amp;amp; &lt;/span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;POSITION &lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;!= &lt;/span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0 &lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;            table.positions.&lt;/span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;push&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(Position::default());
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;            table.positions_changed.&lt;/span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;push&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(current_tick);
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;if&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt; mask &amp;amp; &lt;/span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;VELOCITY &lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;!= &lt;/span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0 &lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;            table.velocities.&lt;/span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;push&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(Velocity::default());
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;            table.velocities_changed.&lt;/span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;push&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(current_tick);
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;.entity_locations.&lt;/span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;set&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(entity, table_index, array_index);
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        entity
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The mutable getters stamp the slot when handed out.&lt;/p&gt;
&lt;div class=&quot;bamboo-code-block&quot; data-bamboo-code data-bamboo-lang=&quot;rust&quot;&gt;&lt;div class=&quot;bamboo-code-toolbar&quot;&gt;&lt;button type=&quot;button&quot; class=&quot;bamboo-code-button&quot; data-bamboo-line-toggle aria-label=&quot;Toggle line numbers&quot; aria-pressed=&quot;false&quot; title=&quot;Toggle line numbers&quot;&gt;&lt;svg class=&quot;bamboo-code-icon&quot; viewBox=&quot;0 0 20 20&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;1.6&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M4 5h2M4 10h2M4 15h2&quot; stroke-linecap=&quot;round&quot;/&gt;&lt;path d=&quot;M9 5h7M9 10h7M9 15h7&quot; stroke-linecap=&quot;round&quot;/&gt;&lt;/svg&gt;&lt;/button&gt;&lt;button type=&quot;button&quot; class=&quot;bamboo-code-button&quot; data-bamboo-copy aria-label=&quot;Copy code&quot; title=&quot;Copy code&quot;&gt;&lt;svg class=&quot;bamboo-code-icon bamboo-code-icon-copy&quot; viewBox=&quot;0 0 20 20&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;1.6&quot; aria-hidden=&quot;true&quot;&gt;&lt;rect x=&quot;7&quot; y=&quot;3&quot; width=&quot;10&quot; height=&quot;12&quot; rx=&quot;2&quot;/&gt;&lt;path d=&quot;M5 7v8a2 2 0 0 0 2 2h6&quot;/&gt;&lt;/svg&gt;&lt;svg class=&quot;bamboo-code-icon bamboo-code-icon-check&quot; viewBox=&quot;0 0 20 20&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;2&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M4 10l4 4 8-8&quot; stroke-linecap=&quot;round&quot; stroke-linejoin=&quot;round&quot;/&gt;&lt;/svg&gt;&lt;/button&gt;&lt;/div&gt;&lt;pre style=&quot;background-color:#2b303b;color:#c0c5ce;&quot;&gt;&lt;code class=&quot;language-rust&quot;&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl &lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;World {
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub fn &lt;/span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;get_position_mut&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(&amp;amp;&lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;entity&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;: Entity) -&amp;gt; Option&amp;lt;&amp;amp;&lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt; Position&amp;gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let &lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(table_index, array_index) = &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;.entity_locations.&lt;/span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;get&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(entity)?;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt; current_tick = &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;.current_tick;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt; table = &amp;amp;&lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;.tables[table_index];
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;if&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt; table.mask &amp;amp; &lt;/span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;POSITION &lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;== &lt;/span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0 &lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;            &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;return &lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;None;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        table.positions_changed[array_index] = current_tick;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        Some(&amp;amp;&lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt; table.positions[array_index])
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub fn &lt;/span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;get_velocity_mut&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(&amp;amp;&lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;entity&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;: Entity) -&amp;gt; Option&amp;lt;&amp;amp;&lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt; Velocity&amp;gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let &lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(table_index, array_index) = &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;.entity_locations.&lt;/span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;get&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(entity)?;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt; current_tick = &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;.current_tick;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt; table = &amp;amp;&lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;.tables[table_index];
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;if&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt; table.mask &amp;amp; &lt;/span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;VELOCITY &lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;== &lt;/span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0 &lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;            &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;return &lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;None;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        table.velocities_changed[array_index] = current_tick;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        Some(&amp;amp;&lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt; table.velocities[array_index])
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This is conservative. We stamp the slot whether or not the caller actually modifies the data. The alternative (only stamp on actual write) would require wrapping the returned reference in a guard type that stamps in its &lt;code&gt;Drop&lt;/code&gt;, which is more machinery than the savings justify.&lt;/p&gt;
&lt;p&gt;Several functions need updating to keep the &lt;code&gt;_changed&lt;/code&gt; vecs in lockstep with their component vec counterparts. &lt;code&gt;despawn&lt;/code&gt;, &lt;code&gt;move_entity&lt;/code&gt;, &lt;code&gt;set_position&lt;/code&gt;, and &lt;code&gt;set_velocity&lt;/code&gt; all need the right pushes, swap_removes, and tick stamps. Every &lt;code&gt;push&lt;/code&gt; to &lt;code&gt;positions&lt;/code&gt; gets a matching &lt;code&gt;push&lt;/code&gt; to &lt;code&gt;positions_changed&lt;/code&gt;. Every &lt;code&gt;swap_remove&lt;/code&gt; from &lt;code&gt;positions&lt;/code&gt; gets a matching &lt;code&gt;swap_remove&lt;/code&gt; from &lt;code&gt;positions_changed&lt;/code&gt;. Every direct write to &lt;code&gt;positions[index]&lt;/code&gt; gets a &lt;code&gt;positions_changed[index] = current_tick&lt;/code&gt; next to it. The full file at the end of the post shows every site updated.&lt;/p&gt;
&lt;p&gt;One small redundancy lives in &lt;code&gt;set_position&lt;/code&gt;&apos;s migration path. It calls &lt;code&gt;add_components&lt;/code&gt;, which calls &lt;code&gt;move_entity&lt;/code&gt;, which already pushes &lt;code&gt;positions_changed.push(current_tick)&lt;/code&gt; for the new slot. &lt;code&gt;set_position&lt;/code&gt; then re-fetches the location and writes &lt;code&gt;positions_changed[array_index] = current_tick&lt;/code&gt; over the just-pushed value. The store is idempotent and the redundancy keeps the post-migration write path identical to the fast no-migration path. If you want to optimize it, you can branch on whether migration happened. The save is not worth the branch.&lt;/p&gt;
&lt;p&gt;There is a real catch the inner-loop authors need to know about. The &lt;code&gt;for_each_mut&lt;/code&gt; callback from part 2 hands the caller a raw &lt;code&gt;&amp;amp;mut ComponentArrays&lt;/code&gt;, direct access to the component vecs, no auto-stamping. A system that writes through that callback does &lt;em&gt;not&lt;/em&gt; trigger change detection. The slot&apos;s tick stays at whatever value it had before. This is the speed-versus-bookkeeping trade-off. Ergonomic single-entity accessors (&lt;code&gt;set_position&lt;/code&gt;, &lt;code&gt;get_position_mut&lt;/code&gt;) stamp for you. Hot inner loops keep the raw access and stamp manually when they actually change something. We will see both shapes in the demo.&lt;/p&gt;
&lt;p&gt;The new query, &quot;iterate over entities whose components changed since last frame&quot;, is the same as &lt;code&gt;for_each_mut&lt;/code&gt; but with an extra check.&lt;/p&gt;
&lt;div class=&quot;bamboo-code-block&quot; data-bamboo-code data-bamboo-lang=&quot;rust&quot;&gt;&lt;div class=&quot;bamboo-code-toolbar&quot;&gt;&lt;button type=&quot;button&quot; class=&quot;bamboo-code-button&quot; data-bamboo-line-toggle aria-label=&quot;Toggle line numbers&quot; aria-pressed=&quot;false&quot; title=&quot;Toggle line numbers&quot;&gt;&lt;svg class=&quot;bamboo-code-icon&quot; viewBox=&quot;0 0 20 20&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;1.6&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M4 5h2M4 10h2M4 15h2&quot; stroke-linecap=&quot;round&quot;/&gt;&lt;path d=&quot;M9 5h7M9 10h7M9 15h7&quot; stroke-linecap=&quot;round&quot;/&gt;&lt;/svg&gt;&lt;/button&gt;&lt;button type=&quot;button&quot; class=&quot;bamboo-code-button&quot; data-bamboo-copy aria-label=&quot;Copy code&quot; title=&quot;Copy code&quot;&gt;&lt;svg class=&quot;bamboo-code-icon bamboo-code-icon-copy&quot; viewBox=&quot;0 0 20 20&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;1.6&quot; aria-hidden=&quot;true&quot;&gt;&lt;rect x=&quot;7&quot; y=&quot;3&quot; width=&quot;10&quot; height=&quot;12&quot; rx=&quot;2&quot;/&gt;&lt;path d=&quot;M5 7v8a2 2 0 0 0 2 2h6&quot;/&gt;&lt;/svg&gt;&lt;svg class=&quot;bamboo-code-icon bamboo-code-icon-check&quot; viewBox=&quot;0 0 20 20&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;2&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M4 10l4 4 8-8&quot; stroke-linecap=&quot;round&quot; stroke-linejoin=&quot;round&quot;/&gt;&lt;/svg&gt;&lt;/button&gt;&lt;/div&gt;&lt;pre style=&quot;background-color:#2b303b;color:#c0c5ce;&quot;&gt;&lt;code class=&quot;language-rust&quot;&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl &lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;World {
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub fn &lt;/span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;for_each_mut_changed&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;&amp;lt;F&amp;gt;(&amp;amp;&lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;include&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u64&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;exclude&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u64&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;f&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;: F)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;where
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        F: FnMut(Entity, &amp;amp;&lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt; ComponentArrays, &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;usize&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;),
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    {
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt; since_tick = &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;.last_tick;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt; table_indices: Vec&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;usize&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;&amp;gt; = &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;cached_tables&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(include).&lt;/span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;to_vec&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;();
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;for&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt; table_index in table_indices {
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;            &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt; table = &amp;amp;&lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;.tables[table_index];
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;            &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;if&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt; table.mask &amp;amp; exclude != &lt;/span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0 &lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;                &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;continue&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;            }
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;            &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;for&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt; array_index in &lt;/span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;..table.entities.&lt;/span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;len&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;                &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let mut&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt; changed = &lt;/span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;false&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;                &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;if&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt; include &amp;amp; &lt;/span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;POSITION &lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;!= &lt;/span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;                    &amp;amp;&amp;amp; table.mask &amp;amp; &lt;/span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;POSITION &lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;!= &lt;/span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;                    &amp;amp;&amp;amp; table.positions_changed[array_index] &amp;gt; since_tick
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;                {
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;                    changed = &lt;/span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;true&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;                }
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;                &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;if&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt; include &amp;amp; &lt;/span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;VELOCITY &lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;!= &lt;/span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;                    &amp;amp;&amp;amp; table.mask &amp;amp; &lt;/span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;VELOCITY &lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;!= &lt;/span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;                    &amp;amp;&amp;amp; table.velocities_changed[array_index] &amp;gt; since_tick
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;                {
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;                    changed = &lt;/span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;true&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;                }
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;                &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;if&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt; changed {
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;                    &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt; entity = table.entities[array_index];
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;                    &lt;/span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;f&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(entity, table, array_index);
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;                }
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;            }
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;A slot is considered changed if &lt;em&gt;any&lt;/em&gt; of the queried components have a tick newer than the watermark. For a renderer that wants &quot;every entity whose position changed&quot;, this fires only on the slots with fresh position stamps. For a system that wants &quot;every entity whose position OR velocity changed&quot;, it fires when either is fresh. Combining changed-ness across components with OR rather than AND is the natural fit, because the typical use case is &quot;redraw this entity if anything about its visual representation moved.&quot;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;step()&lt;/code&gt; runs at the end of the frame. Until you call &lt;code&gt;step()&lt;/code&gt;, every modification this frame still counts as changed. Call &lt;code&gt;step()&lt;/code&gt; once per frame at the end, after every system has had a chance to read the changes from this frame.&lt;/p&gt;
&lt;h2 id=&quot;events&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#events&quot;&gt;#&lt;/a&gt;Events&lt;/h2&gt;
&lt;p&gt;A collision system finds two entities that overlap and the damage system needs to know. Calling damage methods from inside the collision loop couples the two together. Scribbling a pending-damage component on one of the entities works for one-off cases and turns into a mess when ten systems want to broadcast. The clean shape is a queue. The collision system writes &lt;code&gt;CollisionEvent&lt;/code&gt;s without naming a receiver. The damage system reads them without naming a sender.&lt;/p&gt;
&lt;p&gt;The tricky part is lifetime. The queue cannot empty itself the moment an event is written because a system reading later in the same frame would miss it. It cannot keep events forever because nothing would ever drain. The compromise here is a two-frame rule. An event sent on frame N is readable through the end of frame N+1 and gone by the start of frame N+2. Every system gets a full frame to react regardless of schedule order, and memory is bounded at twice the per-frame volume.&lt;/p&gt;
&lt;p&gt;Implementation, double-buffered.&lt;/p&gt;
&lt;div class=&quot;bamboo-code-block&quot; data-bamboo-code data-bamboo-lang=&quot;rust&quot;&gt;&lt;div class=&quot;bamboo-code-toolbar&quot;&gt;&lt;button type=&quot;button&quot; class=&quot;bamboo-code-button&quot; data-bamboo-line-toggle aria-label=&quot;Toggle line numbers&quot; aria-pressed=&quot;false&quot; title=&quot;Toggle line numbers&quot;&gt;&lt;svg class=&quot;bamboo-code-icon&quot; viewBox=&quot;0 0 20 20&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;1.6&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M4 5h2M4 10h2M4 15h2&quot; stroke-linecap=&quot;round&quot;/&gt;&lt;path d=&quot;M9 5h7M9 10h7M9 15h7&quot; stroke-linecap=&quot;round&quot;/&gt;&lt;/svg&gt;&lt;/button&gt;&lt;button type=&quot;button&quot; class=&quot;bamboo-code-button&quot; data-bamboo-copy aria-label=&quot;Copy code&quot; title=&quot;Copy code&quot;&gt;&lt;svg class=&quot;bamboo-code-icon bamboo-code-icon-copy&quot; viewBox=&quot;0 0 20 20&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;1.6&quot; aria-hidden=&quot;true&quot;&gt;&lt;rect x=&quot;7&quot; y=&quot;3&quot; width=&quot;10&quot; height=&quot;12&quot; rx=&quot;2&quot;/&gt;&lt;path d=&quot;M5 7v8a2 2 0 0 0 2 2h6&quot;/&gt;&lt;/svg&gt;&lt;svg class=&quot;bamboo-code-icon bamboo-code-icon-check&quot; viewBox=&quot;0 0 20 20&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;2&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M4 10l4 4 8-8&quot; stroke-linecap=&quot;round&quot; stroke-linejoin=&quot;round&quot;/&gt;&lt;/svg&gt;&lt;/button&gt;&lt;/div&gt;&lt;pre style=&quot;background-color:#2b303b;color:#c0c5ce;&quot;&gt;&lt;code class=&quot;language-rust&quot;&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;#[&lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;derive&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(Clone)]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub struct &lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;EventQueue&amp;lt;T&amp;gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;current&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;: Vec&amp;lt;T&amp;gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;previous&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;: Vec&amp;lt;T&amp;gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;&amp;lt;T&amp;gt; Default &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;for &lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;EventQueue&amp;lt;T&amp;gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;/span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;default&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;() -&amp;gt; &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self &lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self &lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;            current: Vec::new(),
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;            previous: Vec::new(),
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;&amp;lt;T&amp;gt; EventQueue&amp;lt;T&amp;gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub fn &lt;/span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;send&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(&amp;amp;&lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;event&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;: T) {
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;.current.&lt;/span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;push&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(event);
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub fn &lt;/span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;read&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(&amp;amp;&lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;) -&amp;gt; impl Iterator&amp;lt;Item = &amp;amp;T&amp;gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;.previous.&lt;/span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;iter&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;().&lt;/span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;chain&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;.current.&lt;/span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;iter&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;())
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub fn &lt;/span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;drain&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(&amp;amp;&lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;) -&amp;gt; impl Iterator&amp;lt;Item = T&amp;gt; + &amp;#39;_ {
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;.previous.&lt;/span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;drain&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(..).&lt;/span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;chain&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;.current.&lt;/span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;drain&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(..))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub fn &lt;/span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;update&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(&amp;amp;&lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;.previous.&lt;/span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;clear&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;();
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        std::mem::swap(&amp;amp;&lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;.current, &amp;amp;&lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;.previous);
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub fn &lt;/span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;len&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(&amp;amp;&lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;) -&amp;gt; &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;usize &lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;.current.&lt;/span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;len&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;() + &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;.previous.&lt;/span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;len&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;()
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub fn &lt;/span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;is_empty&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(&amp;amp;&lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;) -&amp;gt; &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;bool &lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;.current.&lt;/span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;is_empty&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;() &amp;amp;&amp;amp; &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;.previous.&lt;/span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;is_empty&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;()
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;send&lt;/code&gt; pushes into the current buffer. &lt;code&gt;read&lt;/code&gt; yields everything in both buffers (previous first, then current, the order events were sent). &lt;code&gt;update&lt;/code&gt; clears the previous buffer and swaps the current into its place, so the next call starts with &lt;code&gt;previous&lt;/code&gt; holding what was just sent and &lt;code&gt;current&lt;/code&gt; empty. Two &lt;code&gt;update&lt;/code&gt; calls between a &lt;code&gt;send&lt;/code&gt; and a &lt;code&gt;read&lt;/code&gt; will lose the event.&lt;/p&gt;
&lt;p&gt;Each event type gets its own queue, stored as a field on the &lt;code&gt;World&lt;/code&gt;.&lt;/p&gt;
&lt;div class=&quot;bamboo-code-block&quot; data-bamboo-code data-bamboo-lang=&quot;rust&quot;&gt;&lt;div class=&quot;bamboo-code-toolbar&quot;&gt;&lt;button type=&quot;button&quot; class=&quot;bamboo-code-button&quot; data-bamboo-line-toggle aria-label=&quot;Toggle line numbers&quot; aria-pressed=&quot;false&quot; title=&quot;Toggle line numbers&quot;&gt;&lt;svg class=&quot;bamboo-code-icon&quot; viewBox=&quot;0 0 20 20&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;1.6&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M4 5h2M4 10h2M4 15h2&quot; stroke-linecap=&quot;round&quot;/&gt;&lt;path d=&quot;M9 5h7M9 10h7M9 15h7&quot; stroke-linecap=&quot;round&quot;/&gt;&lt;/svg&gt;&lt;/button&gt;&lt;button type=&quot;button&quot; class=&quot;bamboo-code-button&quot; data-bamboo-copy aria-label=&quot;Copy code&quot; title=&quot;Copy code&quot;&gt;&lt;svg class=&quot;bamboo-code-icon bamboo-code-icon-copy&quot; viewBox=&quot;0 0 20 20&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;1.6&quot; aria-hidden=&quot;true&quot;&gt;&lt;rect x=&quot;7&quot; y=&quot;3&quot; width=&quot;10&quot; height=&quot;12&quot; rx=&quot;2&quot;/&gt;&lt;path d=&quot;M5 7v8a2 2 0 0 0 2 2h6&quot;/&gt;&lt;/svg&gt;&lt;svg class=&quot;bamboo-code-icon bamboo-code-icon-check&quot; viewBox=&quot;0 0 20 20&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;2&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M4 10l4 4 8-8&quot; stroke-linecap=&quot;round&quot; stroke-linejoin=&quot;round&quot;/&gt;&lt;/svg&gt;&lt;/button&gt;&lt;/div&gt;&lt;pre style=&quot;background-color:#2b303b;color:#c0c5ce;&quot;&gt;&lt;code class=&quot;language-rust&quot;&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;#[&lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;derive&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(Debug, Clone)]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub struct &lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;CollisionEvent {
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;entity_a&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;: Entity,
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;entity_b&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;: Entity,
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;#[&lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;derive&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(Default)]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub struct &lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;World {
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;allocator&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;: EntityAllocator,
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;entity_locations&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;: EntityLocations,
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;tables&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;: Vec&amp;lt;ComponentArrays&amp;gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;table_lookup&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;: HashMap&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u64&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;usize&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;&amp;gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;table_edges&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;: Vec&amp;lt;TableEdges&amp;gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;query_cache&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;: HashMap&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u64&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;, Vec&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;usize&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;&amp;gt;&amp;gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;current_tick&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u32&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;last_tick&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u32&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;collisions&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;: EventQueue&amp;lt;CollisionEvent&amp;gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl &lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;World {
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub fn &lt;/span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;send_collision&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(&amp;amp;&lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;event&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;: CollisionEvent) {
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;.collisions.&lt;/span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;send&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(event);
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub fn &lt;/span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;read_collisions&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(&amp;amp;&lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;) -&amp;gt; impl Iterator&amp;lt;Item = &amp;amp;CollisionEvent&amp;gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;.collisions.&lt;/span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;read&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;()
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub fn &lt;/span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;drain_collisions&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(&amp;amp;&lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;) -&amp;gt; impl Iterator&amp;lt;Item = CollisionEvent&amp;gt; + &amp;#39;_ {
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;.collisions.&lt;/span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;drain&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;()
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The familiar fan-out. One set of methods per event type, hand-written here. A macro would generate them. The cost is the same as for component accessors.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;step()&lt;/code&gt; advances each event queue. It is the same &lt;code&gt;step()&lt;/code&gt; that advances the tick.&lt;/p&gt;
&lt;div class=&quot;bamboo-code-block&quot; data-bamboo-code data-bamboo-lang=&quot;rust&quot;&gt;&lt;div class=&quot;bamboo-code-toolbar&quot;&gt;&lt;button type=&quot;button&quot; class=&quot;bamboo-code-button&quot; data-bamboo-line-toggle aria-label=&quot;Toggle line numbers&quot; aria-pressed=&quot;false&quot; title=&quot;Toggle line numbers&quot;&gt;&lt;svg class=&quot;bamboo-code-icon&quot; viewBox=&quot;0 0 20 20&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;1.6&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M4 5h2M4 10h2M4 15h2&quot; stroke-linecap=&quot;round&quot;/&gt;&lt;path d=&quot;M9 5h7M9 10h7M9 15h7&quot; stroke-linecap=&quot;round&quot;/&gt;&lt;/svg&gt;&lt;/button&gt;&lt;button type=&quot;button&quot; class=&quot;bamboo-code-button&quot; data-bamboo-copy aria-label=&quot;Copy code&quot; title=&quot;Copy code&quot;&gt;&lt;svg class=&quot;bamboo-code-icon bamboo-code-icon-copy&quot; viewBox=&quot;0 0 20 20&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;1.6&quot; aria-hidden=&quot;true&quot;&gt;&lt;rect x=&quot;7&quot; y=&quot;3&quot; width=&quot;10&quot; height=&quot;12&quot; rx=&quot;2&quot;/&gt;&lt;path d=&quot;M5 7v8a2 2 0 0 0 2 2h6&quot;/&gt;&lt;/svg&gt;&lt;svg class=&quot;bamboo-code-icon bamboo-code-icon-check&quot; viewBox=&quot;0 0 20 20&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;2&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M4 10l4 4 8-8&quot; stroke-linecap=&quot;round&quot; stroke-linejoin=&quot;round&quot;/&gt;&lt;/svg&gt;&lt;/button&gt;&lt;/div&gt;&lt;pre style=&quot;background-color:#2b303b;color:#c0c5ce;&quot;&gt;&lt;code class=&quot;language-rust&quot;&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl &lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;World {
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub fn &lt;/span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;step&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(&amp;amp;&lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;.collisions.&lt;/span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;update&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;();
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;.last_tick = &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;.current_tick;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;.current_tick = &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;.current_tick.&lt;/span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;wrapping_add&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The order is intentional. Update events first, then advance the tick. By the time the new frame begins, both have rolled over.&lt;/p&gt;
&lt;h2 id=&quot;sparse-set-tags&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#sparse-set-tags&quot;&gt;#&lt;/a&gt;Sparse-set tags&lt;/h2&gt;
&lt;p&gt;A tag is a &lt;code&gt;HashSet&amp;lt;Entity&amp;gt;&lt;/code&gt;. Insert, remove, and membership check are all O(1). Iteration over &quot;all entities with this tag&quot; yields directly from the set. The reason a tag is a hash set instead of a bit in the archetype mask is the migration cost. A bit in the mask means flipping the tag triggers &lt;code&gt;move_entity&lt;/code&gt;, which pulls every other component off the entity, pushes them into a new table, and compacts the old slot. For markers that flip often (the &quot;selected&quot; tag in an RTS, a frame-local &quot;took damage this frame&quot; flag, an enemy alertness state), the migration is pure waste compared to a hash insert.&lt;/p&gt;
&lt;p&gt;The masking approach is not wrong for tags that rarely change. &lt;code&gt;Player&lt;/code&gt; and &lt;code&gt;Enemy&lt;/code&gt; are reasonable as archetype bits if those identities are set once at spawn and never updated. The reason this kernel puts them in a &lt;code&gt;HashSet&lt;/code&gt; anyway is uniformity. Code that wants to ask &quot;is this entity a player&quot; should not need to know whether the answer comes from a mask check or a hash lookup.&lt;/p&gt;
&lt;div class=&quot;bamboo-code-block&quot; data-bamboo-code data-bamboo-lang=&quot;rust&quot;&gt;&lt;div class=&quot;bamboo-code-toolbar&quot;&gt;&lt;button type=&quot;button&quot; class=&quot;bamboo-code-button&quot; data-bamboo-line-toggle aria-label=&quot;Toggle line numbers&quot; aria-pressed=&quot;false&quot; title=&quot;Toggle line numbers&quot;&gt;&lt;svg class=&quot;bamboo-code-icon&quot; viewBox=&quot;0 0 20 20&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;1.6&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M4 5h2M4 10h2M4 15h2&quot; stroke-linecap=&quot;round&quot;/&gt;&lt;path d=&quot;M9 5h7M9 10h7M9 15h7&quot; stroke-linecap=&quot;round&quot;/&gt;&lt;/svg&gt;&lt;/button&gt;&lt;button type=&quot;button&quot; class=&quot;bamboo-code-button&quot; data-bamboo-copy aria-label=&quot;Copy code&quot; title=&quot;Copy code&quot;&gt;&lt;svg class=&quot;bamboo-code-icon bamboo-code-icon-copy&quot; viewBox=&quot;0 0 20 20&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;1.6&quot; aria-hidden=&quot;true&quot;&gt;&lt;rect x=&quot;7&quot; y=&quot;3&quot; width=&quot;10&quot; height=&quot;12&quot; rx=&quot;2&quot;/&gt;&lt;path d=&quot;M5 7v8a2 2 0 0 0 2 2h6&quot;/&gt;&lt;/svg&gt;&lt;svg class=&quot;bamboo-code-icon bamboo-code-icon-check&quot; viewBox=&quot;0 0 20 20&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;2&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M4 10l4 4 8-8&quot; stroke-linecap=&quot;round&quot; stroke-linejoin=&quot;round&quot;/&gt;&lt;/svg&gt;&lt;/button&gt;&lt;/div&gt;&lt;pre style=&quot;background-color:#2b303b;color:#c0c5ce;&quot;&gt;&lt;code class=&quot;language-rust&quot;&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;#[&lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;derive&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(Default)]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub struct &lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;World {
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;allocator&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;: EntityAllocator,
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;entity_locations&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;: EntityLocations,
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;tables&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;: Vec&amp;lt;ComponentArrays&amp;gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;table_lookup&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;: HashMap&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u64&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;usize&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;&amp;gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;table_edges&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;: Vec&amp;lt;TableEdges&amp;gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;query_cache&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;: HashMap&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u64&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;, Vec&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;usize&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;&amp;gt;&amp;gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;current_tick&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u32&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;last_tick&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u32&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;collisions&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;: EventQueue&amp;lt;CollisionEvent&amp;gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;players&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;: std::collections::HashSet&amp;lt;Entity&amp;gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;enemies&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;: std::collections::HashSet&amp;lt;Entity&amp;gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl &lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;World {
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub fn &lt;/span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;add_player&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(&amp;amp;&lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;entity&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;: Entity) {
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;if &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;.entity_locations.&lt;/span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;get&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(entity).&lt;/span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;is_some&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;            &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;.players.&lt;/span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;insert&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(entity);
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub fn &lt;/span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;remove_player&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(&amp;amp;&lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;entity&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;: Entity) -&amp;gt; &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;bool &lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;.players.&lt;/span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;remove&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(&amp;amp;entity)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub fn &lt;/span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;has_player&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(&amp;amp;&lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;entity&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;: Entity) -&amp;gt; &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;bool &lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;.players.&lt;/span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;contains&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(&amp;amp;entity)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub fn &lt;/span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;query_players&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(&amp;amp;&lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;) -&amp;gt; impl Iterator&amp;lt;Item = Entity&amp;gt; + &amp;#39;_ {
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;.players.&lt;/span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;iter&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;().&lt;/span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;copied&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;()
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub fn &lt;/span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;add_enemy&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(&amp;amp;&lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;entity&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;: Entity) {
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;if &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;.entity_locations.&lt;/span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;get&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(entity).&lt;/span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;is_some&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;            &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;.enemies.&lt;/span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;insert&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(entity);
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub fn &lt;/span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;remove_enemy&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(&amp;amp;&lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;entity&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;: Entity) -&amp;gt; &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;bool &lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;.enemies.&lt;/span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;remove&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(&amp;amp;entity)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub fn &lt;/span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;has_enemy&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(&amp;amp;&lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;entity&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;: Entity) -&amp;gt; &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;bool &lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;.enemies.&lt;/span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;contains&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(&amp;amp;entity)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub fn &lt;/span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;query_enemies&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(&amp;amp;&lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;) -&amp;gt; impl Iterator&amp;lt;Item = Entity&amp;gt; + &amp;#39;_ {
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;.enemies.&lt;/span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;iter&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;().&lt;/span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;copied&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;()
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Insertion and removal are O(1) hash operations with no archetype touch. Querying &quot;all players&quot; yields directly from the set. Combined queries (a &lt;code&gt;for_each&lt;/code&gt; over &lt;code&gt;POSITION | VELOCITY&lt;/code&gt; plus a &lt;code&gt;has_player&lt;/code&gt; filter) walk the tables and check the tag set per entity, which is a cheap hash lookup.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;despawn&lt;/code&gt; needs to clear the entity out of every tag set, otherwise stale entity handles will accumulate in the sets. Add these lines to the existing &lt;code&gt;despawn&lt;/code&gt;.&lt;/p&gt;
&lt;div class=&quot;bamboo-code-block&quot; data-bamboo-code data-bamboo-lang=&quot;rust&quot;&gt;&lt;div class=&quot;bamboo-code-toolbar&quot;&gt;&lt;button type=&quot;button&quot; class=&quot;bamboo-code-button&quot; data-bamboo-line-toggle aria-label=&quot;Toggle line numbers&quot; aria-pressed=&quot;false&quot; title=&quot;Toggle line numbers&quot;&gt;&lt;svg class=&quot;bamboo-code-icon&quot; viewBox=&quot;0 0 20 20&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;1.6&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M4 5h2M4 10h2M4 15h2&quot; stroke-linecap=&quot;round&quot;/&gt;&lt;path d=&quot;M9 5h7M9 10h7M9 15h7&quot; stroke-linecap=&quot;round&quot;/&gt;&lt;/svg&gt;&lt;/button&gt;&lt;button type=&quot;button&quot; class=&quot;bamboo-code-button&quot; data-bamboo-copy aria-label=&quot;Copy code&quot; title=&quot;Copy code&quot;&gt;&lt;svg class=&quot;bamboo-code-icon bamboo-code-icon-copy&quot; viewBox=&quot;0 0 20 20&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;1.6&quot; aria-hidden=&quot;true&quot;&gt;&lt;rect x=&quot;7&quot; y=&quot;3&quot; width=&quot;10&quot; height=&quot;12&quot; rx=&quot;2&quot;/&gt;&lt;path d=&quot;M5 7v8a2 2 0 0 0 2 2h6&quot;/&gt;&lt;/svg&gt;&lt;svg class=&quot;bamboo-code-icon bamboo-code-icon-check&quot; viewBox=&quot;0 0 20 20&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;2&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M4 10l4 4 8-8&quot; stroke-linecap=&quot;round&quot; stroke-linejoin=&quot;round&quot;/&gt;&lt;/svg&gt;&lt;/button&gt;&lt;/div&gt;&lt;pre style=&quot;background-color:#2b303b;color:#c0c5ce;&quot;&gt;&lt;code class=&quot;language-rust&quot;&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;.players.&lt;/span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;remove&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(&amp;amp;entity);
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;.enemies.&lt;/span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;remove&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(&amp;amp;entity);
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The name &quot;sparse set&quot; comes from the data structure traditionally used here. An array of slot pointers indexed by entity id (so checking membership is an array access), plus a packed list of present entities (so iteration is dense). A &lt;code&gt;HashSet&lt;/code&gt; is the simplified version. For a real engine with millions of entities and many tag types, the sparse-set proper is faster, but it has the same external API.&lt;/p&gt;
&lt;h2 id=&quot;command-buffers&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#command-buffers&quot;&gt;#&lt;/a&gt;Command buffers&lt;/h2&gt;
&lt;p&gt;Iterating over entities while spawning, despawning, or restructuring them is impossible to do safely with direct calls. The iteration borrows the world, so any mutation requires giving up the borrow first. The standard workaround is to queue the operations and apply them later.&lt;/p&gt;
&lt;p&gt;The queue is an enum of every operation the world supports.&lt;/p&gt;
&lt;div class=&quot;bamboo-code-block&quot; data-bamboo-code data-bamboo-lang=&quot;rust&quot;&gt;&lt;div class=&quot;bamboo-code-toolbar&quot;&gt;&lt;button type=&quot;button&quot; class=&quot;bamboo-code-button&quot; data-bamboo-line-toggle aria-label=&quot;Toggle line numbers&quot; aria-pressed=&quot;false&quot; title=&quot;Toggle line numbers&quot;&gt;&lt;svg class=&quot;bamboo-code-icon&quot; viewBox=&quot;0 0 20 20&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;1.6&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M4 5h2M4 10h2M4 15h2&quot; stroke-linecap=&quot;round&quot;/&gt;&lt;path d=&quot;M9 5h7M9 10h7M9 15h7&quot; stroke-linecap=&quot;round&quot;/&gt;&lt;/svg&gt;&lt;/button&gt;&lt;button type=&quot;button&quot; class=&quot;bamboo-code-button&quot; data-bamboo-copy aria-label=&quot;Copy code&quot; title=&quot;Copy code&quot;&gt;&lt;svg class=&quot;bamboo-code-icon bamboo-code-icon-copy&quot; viewBox=&quot;0 0 20 20&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;1.6&quot; aria-hidden=&quot;true&quot;&gt;&lt;rect x=&quot;7&quot; y=&quot;3&quot; width=&quot;10&quot; height=&quot;12&quot; rx=&quot;2&quot;/&gt;&lt;path d=&quot;M5 7v8a2 2 0 0 0 2 2h6&quot;/&gt;&lt;/svg&gt;&lt;svg class=&quot;bamboo-code-icon bamboo-code-icon-check&quot; viewBox=&quot;0 0 20 20&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;2&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M4 10l4 4 8-8&quot; stroke-linecap=&quot;round&quot; stroke-linejoin=&quot;round&quot;/&gt;&lt;/svg&gt;&lt;/button&gt;&lt;/div&gt;&lt;pre style=&quot;background-color:#2b303b;color:#c0c5ce;&quot;&gt;&lt;code class=&quot;language-rust&quot;&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub enum &lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;Command {
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    Spawn { mask: &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u64 &lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;},
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    Despawn { entity: Entity },
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    AddComponents { entity: Entity, mask: &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u64 &lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;},
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    RemoveComponents { entity: Entity, mask: &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u64 &lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;},
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    SetPosition { entity: Entity, value: Position },
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    SetVelocity { entity: Entity, value: Velocity },
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    AddPlayer { entity: Entity },
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    RemovePlayer { entity: Entity },
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    AddEnemy { entity: Entity },
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    RemoveEnemy { entity: Entity },
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Each operation that can be deferred has a variant. The component-specific &lt;code&gt;Set*&lt;/code&gt; variants carry the typed payload, because that information would otherwise be erased.&lt;/p&gt;
&lt;p&gt;The buffer is a &lt;code&gt;Vec&amp;lt;Command&amp;gt;&lt;/code&gt; on the world, populated by queue methods and drained by &lt;code&gt;apply_commands&lt;/code&gt;.&lt;/p&gt;
&lt;div class=&quot;bamboo-code-block&quot; data-bamboo-code data-bamboo-lang=&quot;rust&quot;&gt;&lt;div class=&quot;bamboo-code-toolbar&quot;&gt;&lt;button type=&quot;button&quot; class=&quot;bamboo-code-button&quot; data-bamboo-line-toggle aria-label=&quot;Toggle line numbers&quot; aria-pressed=&quot;false&quot; title=&quot;Toggle line numbers&quot;&gt;&lt;svg class=&quot;bamboo-code-icon&quot; viewBox=&quot;0 0 20 20&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;1.6&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M4 5h2M4 10h2M4 15h2&quot; stroke-linecap=&quot;round&quot;/&gt;&lt;path d=&quot;M9 5h7M9 10h7M9 15h7&quot; stroke-linecap=&quot;round&quot;/&gt;&lt;/svg&gt;&lt;/button&gt;&lt;button type=&quot;button&quot; class=&quot;bamboo-code-button&quot; data-bamboo-copy aria-label=&quot;Copy code&quot; title=&quot;Copy code&quot;&gt;&lt;svg class=&quot;bamboo-code-icon bamboo-code-icon-copy&quot; viewBox=&quot;0 0 20 20&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;1.6&quot; aria-hidden=&quot;true&quot;&gt;&lt;rect x=&quot;7&quot; y=&quot;3&quot; width=&quot;10&quot; height=&quot;12&quot; rx=&quot;2&quot;/&gt;&lt;path d=&quot;M5 7v8a2 2 0 0 0 2 2h6&quot;/&gt;&lt;/svg&gt;&lt;svg class=&quot;bamboo-code-icon bamboo-code-icon-check&quot; viewBox=&quot;0 0 20 20&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;2&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M4 10l4 4 8-8&quot; stroke-linecap=&quot;round&quot; stroke-linejoin=&quot;round&quot;/&gt;&lt;/svg&gt;&lt;/button&gt;&lt;/div&gt;&lt;pre style=&quot;background-color:#2b303b;color:#c0c5ce;&quot;&gt;&lt;code class=&quot;language-rust&quot;&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;#[&lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;derive&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(Default)]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub struct &lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;World {
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;allocator&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;: EntityAllocator,
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;entity_locations&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;: EntityLocations,
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;tables&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;: Vec&amp;lt;ComponentArrays&amp;gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;table_lookup&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;: HashMap&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u64&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;usize&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;&amp;gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;table_edges&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;: Vec&amp;lt;TableEdges&amp;gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;query_cache&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;: HashMap&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u64&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;, Vec&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;usize&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;&amp;gt;&amp;gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;current_tick&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u32&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;last_tick&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u32&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;collisions&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;: EventQueue&amp;lt;CollisionEvent&amp;gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;players&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;: std::collections::HashSet&amp;lt;Entity&amp;gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;enemies&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;: std::collections::HashSet&amp;lt;Entity&amp;gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;command_buffer&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;: Vec&amp;lt;Command&amp;gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl &lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;World {
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub fn &lt;/span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;queue_spawn&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(&amp;amp;&lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;mask&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u64&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;.command_buffer.&lt;/span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;push&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(Command::Spawn { mask });
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub fn &lt;/span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;queue_despawn&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(&amp;amp;&lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;entity&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;: Entity) {
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;.command_buffer.&lt;/span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;push&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(Command::Despawn { entity });
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub fn &lt;/span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;queue_add_components&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(&amp;amp;&lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;entity&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;: Entity, &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;mask&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u64&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;.command_buffer
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;            .&lt;/span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;push&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(Command::AddComponents { entity, mask });
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub fn &lt;/span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;queue_remove_components&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(&amp;amp;&lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;entity&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;: Entity, &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;mask&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u64&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;.command_buffer
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;            .&lt;/span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;push&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(Command::RemoveComponents { entity, mask });
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub fn &lt;/span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;queue_set_position&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(&amp;amp;&lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;entity&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;: Entity, &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;value&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;: Position) {
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;.command_buffer
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;            .&lt;/span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;push&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(Command::SetPosition { entity, value });
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub fn &lt;/span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;queue_set_velocity&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(&amp;amp;&lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;entity&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;: Entity, &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;value&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;: Velocity) {
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;.command_buffer
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;            .&lt;/span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;push&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(Command::SetVelocity { entity, value });
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub fn &lt;/span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;queue_add_player&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(&amp;amp;&lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;entity&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;: Entity) {
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;.command_buffer.&lt;/span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;push&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(Command::AddPlayer { entity });
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub fn &lt;/span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;queue_remove_player&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(&amp;amp;&lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;entity&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;: Entity) {
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;.command_buffer.&lt;/span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;push&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(Command::RemovePlayer { entity });
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub fn &lt;/span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;queue_add_enemy&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(&amp;amp;&lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;entity&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;: Entity) {
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;.command_buffer.&lt;/span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;push&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(Command::AddEnemy { entity });
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub fn &lt;/span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;queue_remove_enemy&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(&amp;amp;&lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;entity&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;: Entity) {
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;.command_buffer.&lt;/span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;push&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(Command::RemoveEnemy { entity });
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub fn &lt;/span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;apply_commands&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(&amp;amp;&lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt; commands = std::mem::take(&amp;amp;&lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;.command_buffer);
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;for&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt; command in commands {
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;            &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;match&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt; command {
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;                Command::Spawn { mask } =&amp;gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;                    &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;spawn&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(mask);
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;                }
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;                Command::Despawn { entity } =&amp;gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;                    &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;despawn&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(entity);
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;                }
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;                Command::AddComponents { entity, mask } =&amp;gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;                    &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;add_components&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(entity, mask);
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;                }
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;                Command::RemoveComponents { entity, mask } =&amp;gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;                    &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;remove_components&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(entity, mask);
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;                }
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;                Command::SetPosition { entity, value } =&amp;gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;                    &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;set_position&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(entity, value);
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;                }
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;                Command::SetVelocity { entity, value } =&amp;gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;                    &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;set_velocity&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(entity, value);
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;                }
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;                Command::AddPlayer { entity } =&amp;gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;                    &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;add_player&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(entity);
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;                }
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;                Command::RemovePlayer { entity } =&amp;gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;                    &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;remove_player&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(entity);
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;                }
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;                Command::AddEnemy { entity } =&amp;gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;                    &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;add_enemy&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(entity);
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;                }
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;                Command::RemoveEnemy { entity } =&amp;gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;                    &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;remove_enemy&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(entity);
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;                }
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;            }
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;mem::take&lt;/code&gt; swaps the buffer out so the loop iterates over an owned &lt;code&gt;Vec&amp;lt;Command&amp;gt;&lt;/code&gt; while leaving an empty buffer in place. This matters because some commands invoke methods that might themselves enqueue more commands. If we held a borrow into the buffer while iterating, those nested enqueues would not compile. With &lt;code&gt;mem::take&lt;/code&gt;, nested commands are appended to the new buffer and will be picked up by the next &lt;code&gt;apply_commands&lt;/code&gt; call.&lt;/p&gt;
&lt;p&gt;The dispatch is a giant &lt;code&gt;match&lt;/code&gt;, typed at compile time, no &lt;code&gt;dyn&lt;/code&gt;, no allocation per command beyond the vec push. The enum variants are the documentation of what can be deferred.&lt;/p&gt;
&lt;h2 id=&quot;resources&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#resources&quot;&gt;#&lt;/a&gt;Resources&lt;/h2&gt;
&lt;p&gt;Some state belongs to the world, not to any specific entity. Delta time. The input snapshot for this frame. The time of day. The score. None of these have a sensible owner among the entities, but most systems in the schedule need to read or write at least one of them. The shape that holds this kind of state is a &lt;code&gt;Resources&lt;/code&gt; struct attached to the world.&lt;/p&gt;
&lt;div class=&quot;bamboo-code-block&quot; data-bamboo-code data-bamboo-lang=&quot;rust&quot;&gt;&lt;div class=&quot;bamboo-code-toolbar&quot;&gt;&lt;button type=&quot;button&quot; class=&quot;bamboo-code-button&quot; data-bamboo-line-toggle aria-label=&quot;Toggle line numbers&quot; aria-pressed=&quot;false&quot; title=&quot;Toggle line numbers&quot;&gt;&lt;svg class=&quot;bamboo-code-icon&quot; viewBox=&quot;0 0 20 20&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;1.6&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M4 5h2M4 10h2M4 15h2&quot; stroke-linecap=&quot;round&quot;/&gt;&lt;path d=&quot;M9 5h7M9 10h7M9 15h7&quot; stroke-linecap=&quot;round&quot;/&gt;&lt;/svg&gt;&lt;/button&gt;&lt;button type=&quot;button&quot; class=&quot;bamboo-code-button&quot; data-bamboo-copy aria-label=&quot;Copy code&quot; title=&quot;Copy code&quot;&gt;&lt;svg class=&quot;bamboo-code-icon bamboo-code-icon-copy&quot; viewBox=&quot;0 0 20 20&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;1.6&quot; aria-hidden=&quot;true&quot;&gt;&lt;rect x=&quot;7&quot; y=&quot;3&quot; width=&quot;10&quot; height=&quot;12&quot; rx=&quot;2&quot;/&gt;&lt;path d=&quot;M5 7v8a2 2 0 0 0 2 2h6&quot;/&gt;&lt;/svg&gt;&lt;svg class=&quot;bamboo-code-icon bamboo-code-icon-check&quot; viewBox=&quot;0 0 20 20&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;2&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M4 10l4 4 8-8&quot; stroke-linecap=&quot;round&quot; stroke-linejoin=&quot;round&quot;/&gt;&lt;/svg&gt;&lt;/button&gt;&lt;/div&gt;&lt;pre style=&quot;background-color:#2b303b;color:#c0c5ce;&quot;&gt;&lt;code class=&quot;language-rust&quot;&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;#[&lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;derive&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(Default)]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub struct &lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;Resources {
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;delta_time&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;f32&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;game_time&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;f32&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;#[&lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;derive&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(Default)]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub struct &lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;World {
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;allocator&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;: EntityAllocator,
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;entity_locations&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;: EntityLocations,
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;tables&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;: Vec&amp;lt;ComponentArrays&amp;gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;table_lookup&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;: HashMap&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u64&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;usize&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;&amp;gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;table_edges&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;: Vec&amp;lt;TableEdges&amp;gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;query_cache&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;: HashMap&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u64&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;, Vec&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;usize&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;&amp;gt;&amp;gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;current_tick&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u32&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;last_tick&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u32&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;collisions&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;: EventQueue&amp;lt;CollisionEvent&amp;gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;players&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;: HashSet&amp;lt;Entity&amp;gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;enemies&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;: HashSet&amp;lt;Entity&amp;gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;command_buffer&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;: Vec&amp;lt;Command&amp;gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;resources&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;: Resources,
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;A system reads from resources by accessing &lt;code&gt;world.resources.delta_time&lt;/code&gt; and writes by assigning to &lt;code&gt;world.resources.game_time = ...&lt;/code&gt;. No accessor functions, no per-resource fan-out. The freecs macro shown later in the post generates the same shape from a &lt;code&gt;Resources { delta_time: f32 }&lt;/code&gt; block at the macro site. We are building the hand-written equivalent.&lt;/p&gt;
&lt;h2 id=&quot;a-trivial-schedule&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#a-trivial-schedule&quot;&gt;#&lt;/a&gt;A trivial schedule&lt;/h2&gt;
&lt;p&gt;Systems are functions that take &lt;code&gt;&amp;amp;mut World&lt;/code&gt;. A schedule is a list of named systems run in order each frame. For an introductory build we will not need anything more complicated.&lt;/p&gt;
&lt;div class=&quot;bamboo-code-block&quot; data-bamboo-code data-bamboo-lang=&quot;rust&quot;&gt;&lt;div class=&quot;bamboo-code-toolbar&quot;&gt;&lt;button type=&quot;button&quot; class=&quot;bamboo-code-button&quot; data-bamboo-line-toggle aria-label=&quot;Toggle line numbers&quot; aria-pressed=&quot;false&quot; title=&quot;Toggle line numbers&quot;&gt;&lt;svg class=&quot;bamboo-code-icon&quot; viewBox=&quot;0 0 20 20&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;1.6&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M4 5h2M4 10h2M4 15h2&quot; stroke-linecap=&quot;round&quot;/&gt;&lt;path d=&quot;M9 5h7M9 10h7M9 15h7&quot; stroke-linecap=&quot;round&quot;/&gt;&lt;/svg&gt;&lt;/button&gt;&lt;button type=&quot;button&quot; class=&quot;bamboo-code-button&quot; data-bamboo-copy aria-label=&quot;Copy code&quot; title=&quot;Copy code&quot;&gt;&lt;svg class=&quot;bamboo-code-icon bamboo-code-icon-copy&quot; viewBox=&quot;0 0 20 20&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;1.6&quot; aria-hidden=&quot;true&quot;&gt;&lt;rect x=&quot;7&quot; y=&quot;3&quot; width=&quot;10&quot; height=&quot;12&quot; rx=&quot;2&quot;/&gt;&lt;path d=&quot;M5 7v8a2 2 0 0 0 2 2h6&quot;/&gt;&lt;/svg&gt;&lt;svg class=&quot;bamboo-code-icon bamboo-code-icon-check&quot; viewBox=&quot;0 0 20 20&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;2&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M4 10l4 4 8-8&quot; stroke-linecap=&quot;round&quot; stroke-linejoin=&quot;round&quot;/&gt;&lt;/svg&gt;&lt;/button&gt;&lt;/div&gt;&lt;pre style=&quot;background-color:#2b303b;color:#c0c5ce;&quot;&gt;&lt;code class=&quot;language-rust&quot;&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub type &lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;SystemFn = Box&amp;lt;dyn FnMut(&amp;amp;&lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt; World)&amp;gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;#[&lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;derive&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(Default)]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub struct &lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;Schedule {
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;systems&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;: Vec&amp;lt;(&amp;amp;&lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;&amp;#39;static str&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;, SystemFn)&amp;gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl &lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;Schedule {
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub fn &lt;/span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;add&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;&amp;lt;F&amp;gt;(&amp;amp;&lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;name&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;: &amp;amp;&lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;&amp;#39;static str&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;system&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;: F) -&amp;gt; &amp;amp;&lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut Self
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;where
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        F: FnMut(&amp;amp;&lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt; World) + &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;&amp;#39;static&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    {
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;.systems.&lt;/span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;push&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;((name, Box::new(system)));
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub fn &lt;/span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;run&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(&amp;amp;&lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;world&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;: &amp;amp;&lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt; World) {
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;for &lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(_, system) in &amp;amp;&lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;.systems {
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;            &lt;/span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;system&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(world);
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The named entries are for introspection. You can print the system list, find a system by name, swap one out. A production schedule grows hooks for ordering constraints, parallel execution, and conditional running, but for the purpose of this series, an ordered list is enough to drive a frame loop.&lt;/p&gt;
&lt;h2 id=&quot;what-we-built&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#what-we-built&quot;&gt;#&lt;/a&gt;What we built&lt;/h2&gt;
&lt;div class=&quot;bamboo-code-block&quot; data-bamboo-code&gt;&lt;div class=&quot;bamboo-code-toolbar&quot;&gt;&lt;button type=&quot;button&quot; class=&quot;bamboo-code-button&quot; data-bamboo-line-toggle aria-label=&quot;Toggle line numbers&quot; aria-pressed=&quot;false&quot; title=&quot;Toggle line numbers&quot;&gt;&lt;svg class=&quot;bamboo-code-icon&quot; viewBox=&quot;0 0 20 20&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;1.6&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M4 5h2M4 10h2M4 15h2&quot; stroke-linecap=&quot;round&quot;/&gt;&lt;path d=&quot;M9 5h7M9 10h7M9 15h7&quot; stroke-linecap=&quot;round&quot;/&gt;&lt;/svg&gt;&lt;/button&gt;&lt;button type=&quot;button&quot; class=&quot;bamboo-code-button&quot; data-bamboo-copy aria-label=&quot;Copy code&quot; title=&quot;Copy code&quot;&gt;&lt;svg class=&quot;bamboo-code-icon bamboo-code-icon-copy&quot; viewBox=&quot;0 0 20 20&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;1.6&quot; aria-hidden=&quot;true&quot;&gt;&lt;rect x=&quot;7&quot; y=&quot;3&quot; width=&quot;10&quot; height=&quot;12&quot; rx=&quot;2&quot;/&gt;&lt;path d=&quot;M5 7v8a2 2 0 0 0 2 2h6&quot;/&gt;&lt;/svg&gt;&lt;svg class=&quot;bamboo-code-icon bamboo-code-icon-check&quot; viewBox=&quot;0 0 20 20&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;2&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M4 10l4 4 8-8&quot; stroke-linecap=&quot;round&quot; stroke-linejoin=&quot;round&quot;/&gt;&lt;/svg&gt;&lt;/button&gt;&lt;/div&gt;&lt;pre style=&quot;background-color:#2b303b;color:#c0c5ce;&quot;&gt;&lt;code&gt;&lt;span class=&quot;bamboo-line&quot;&gt;World  (new fields)
&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;├── current_tick: u32                       stamped on writes
&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;├── last_tick: u32                          watermark for changed-since checks
&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;├── collisions: EventQueue&amp;lt;CollisionEvent&amp;gt;  double-buffered messages
&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;├── players: HashSet&amp;lt;Entity&amp;gt;                sparse-set tag, no archetype touch
&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;├── enemies: HashSet&amp;lt;Entity&amp;gt;                sparse-set tag
&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;├── command_buffer: Vec&amp;lt;Command&amp;gt;            deferred structural changes
&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;└── resources: Resources                    global state, not per-entity
&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;ComponentArrays  (new fields)
&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;├── positions_changed: Vec&amp;lt;u32&amp;gt;             parallel tick array
&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;└── velocities_changed: Vec&amp;lt;u32&amp;gt;            parallel tick array
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;New operations on &lt;code&gt;World&lt;/code&gt;. &lt;code&gt;step&lt;/code&gt; to advance the frame, &lt;code&gt;for_each_mut_changed&lt;/code&gt; to iterate only the slots touched since last step, &lt;code&gt;send_collision&lt;/code&gt;/&lt;code&gt;read_collisions&lt;/code&gt;/&lt;code&gt;drain_collisions&lt;/code&gt; for cross-system messaging, the tag set with &lt;code&gt;add_player&lt;/code&gt;/&lt;code&gt;remove_player&lt;/code&gt;/&lt;code&gt;has_player&lt;/code&gt;/&lt;code&gt;query_players&lt;/code&gt; (and the same for enemy), the command-buffer methods &lt;code&gt;queue_spawn&lt;/code&gt;/&lt;code&gt;queue_despawn&lt;/code&gt;/&lt;code&gt;queue_set_position&lt;/code&gt;/... and &lt;code&gt;apply_commands&lt;/code&gt; to flush them, plus direct field access on &lt;code&gt;world.resources&lt;/code&gt; for global state. A &lt;code&gt;Schedule&lt;/code&gt; struct that runs systems in order each frame.&lt;/p&gt;
&lt;h2 id=&quot;where-the-abstractions-stop-being-free&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#where-the-abstractions-stop-being-free&quot;&gt;#&lt;/a&gt;Where the abstractions stop being free&lt;/h2&gt;
&lt;p&gt;We have been doing fan-out by hand for three posts now. Every component type adds a long list of edits.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;a field on &lt;code&gt;ComponentArrays&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;a parallel &lt;code&gt;_changed&lt;/code&gt; field&lt;/li&gt;
&lt;li&gt;a mask constant&lt;/li&gt;
&lt;li&gt;a &lt;code&gt;match&lt;/code&gt; arm in &lt;code&gt;component_index&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;a bit-position constant inside &lt;code&gt;COMPONENT_COUNT&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;a push site in &lt;code&gt;spawn&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;two push sites in &lt;code&gt;move_entity&lt;/code&gt; (take from source, push to dest)&lt;/li&gt;
&lt;li&gt;two &lt;code&gt;swap_remove&lt;/code&gt; sites (one in &lt;code&gt;despawn&lt;/code&gt;, one in &lt;code&gt;move_entity&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;two component bits in the edge-graph loop inside &lt;code&gt;get_or_create_table&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;four accessor functions (&lt;code&gt;get&lt;/code&gt;, &lt;code&gt;get_mut&lt;/code&gt;, &lt;code&gt;set&lt;/code&gt;, &lt;code&gt;entity_has_*&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;a branch in &lt;code&gt;for_each_mut_changed&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Adding a tenth component is editing thirty-something call sites, and any one of them being wrong is a silent correctness bug. This is the reason every production ECS in Rust ships with a macro layer.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/matthewjberger/freecs&quot;&gt;freecs&lt;/a&gt; is what these three posts scale to. Same data layout, same archetype graph, same query cache, same watermark change detection. The difference is a single declarative &lt;code&gt;macro_rules!&lt;/code&gt; macro on top that takes one component declaration and writes the entire fan-out for you. The whole equivalent of what we built collapses to one block.&lt;/p&gt;
&lt;div class=&quot;bamboo-code-block&quot; data-bamboo-code data-bamboo-lang=&quot;rust&quot;&gt;&lt;div class=&quot;bamboo-code-toolbar&quot;&gt;&lt;button type=&quot;button&quot; class=&quot;bamboo-code-button&quot; data-bamboo-line-toggle aria-label=&quot;Toggle line numbers&quot; aria-pressed=&quot;false&quot; title=&quot;Toggle line numbers&quot;&gt;&lt;svg class=&quot;bamboo-code-icon&quot; viewBox=&quot;0 0 20 20&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;1.6&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M4 5h2M4 10h2M4 15h2&quot; stroke-linecap=&quot;round&quot;/&gt;&lt;path d=&quot;M9 5h7M9 10h7M9 15h7&quot; stroke-linecap=&quot;round&quot;/&gt;&lt;/svg&gt;&lt;/button&gt;&lt;button type=&quot;button&quot; class=&quot;bamboo-code-button&quot; data-bamboo-copy aria-label=&quot;Copy code&quot; title=&quot;Copy code&quot;&gt;&lt;svg class=&quot;bamboo-code-icon bamboo-code-icon-copy&quot; viewBox=&quot;0 0 20 20&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;1.6&quot; aria-hidden=&quot;true&quot;&gt;&lt;rect x=&quot;7&quot; y=&quot;3&quot; width=&quot;10&quot; height=&quot;12&quot; rx=&quot;2&quot;/&gt;&lt;path d=&quot;M5 7v8a2 2 0 0 0 2 2h6&quot;/&gt;&lt;/svg&gt;&lt;svg class=&quot;bamboo-code-icon bamboo-code-icon-check&quot; viewBox=&quot;0 0 20 20&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;2&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M4 10l4 4 8-8&quot; stroke-linecap=&quot;round&quot; stroke-linejoin=&quot;round&quot;/&gt;&lt;/svg&gt;&lt;/button&gt;&lt;/div&gt;&lt;pre style=&quot;background-color:#2b303b;color:#c0c5ce;&quot;&gt;&lt;code class=&quot;language-rust&quot;&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;freecs::{ecs, Entity};
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;#[&lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;derive&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(Default, Clone)] &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub struct &lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;Position { &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;x&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;f32&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;y&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;f32 &lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;#[&lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;derive&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(Default, Clone)] &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub struct &lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;Velocity { &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;x&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;f32&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;y&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;f32 &lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;#[&lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;derive&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(Debug, Clone)]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub struct &lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;CollisionEvent {
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;entity_a&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;: Entity,
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;entity_b&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;: Entity,
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;ecs! {
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    World {
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        position: Position =&amp;gt; &lt;/span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;POSITION&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        velocity: Velocity =&amp;gt; &lt;/span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;VELOCITY&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    Tags {
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        player =&amp;gt; &lt;/span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;PLAYER&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        enemy =&amp;gt; &lt;/span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;ENEMY&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    Events {
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        collision: CollisionEvent,
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    Resources {
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        delta_time: &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;f32&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;That declaration generates the &lt;code&gt;World&lt;/code&gt; struct, the &lt;code&gt;ComponentArrays&lt;/code&gt;, every typed accessor (&lt;code&gt;get_position&lt;/code&gt;, &lt;code&gt;set_position&lt;/code&gt;, &lt;code&gt;get_position_mut&lt;/code&gt;, &lt;code&gt;modify_position&lt;/code&gt; for closure-style mutation, &lt;code&gt;add_position&lt;/code&gt; for adding a defaulted component, &lt;code&gt;entity_has_position&lt;/code&gt;, and others), &lt;code&gt;add_components&lt;/code&gt; and &lt;code&gt;remove_components&lt;/code&gt; with the typed mask helpers, the tag set with its own &lt;code&gt;add_player&lt;/code&gt;/&lt;code&gt;has_player&lt;/code&gt;/&lt;code&gt;query_player&lt;/code&gt;, the double-buffered event queue with &lt;code&gt;send_collision&lt;/code&gt;/&lt;code&gt;drain_collision&lt;/code&gt;/&lt;code&gt;read_collision&lt;/code&gt;, the command buffer with typed &lt;code&gt;queue_set_position&lt;/code&gt; variants, the table-edge cache, the query cache, and the change-detection tick stamps. The &lt;code&gt;Schedule&lt;/code&gt; type is a separate piece of the crate and works the same way as the one we built.&lt;/p&gt;
&lt;p&gt;The scaling answer the hand-built version does not give is right here. Adding &lt;code&gt;health: Health =&amp;gt; HEALTH,&lt;/code&gt; to the declaration writes the entire per-component fan-out for &lt;code&gt;Health&lt;/code&gt; automatically, every accessor, every storage site, every cache update. Adding a new event type or a new tag is one line. The eleven edits per component become zero edits, and a kernel that handles two component types and one event type handles fifty of each the same way.&lt;/p&gt;
&lt;p&gt;Using it from a system looks like the following.&lt;/p&gt;
&lt;div class=&quot;bamboo-code-block&quot; data-bamboo-code data-bamboo-lang=&quot;rust&quot;&gt;&lt;div class=&quot;bamboo-code-toolbar&quot;&gt;&lt;button type=&quot;button&quot; class=&quot;bamboo-code-button&quot; data-bamboo-line-toggle aria-label=&quot;Toggle line numbers&quot; aria-pressed=&quot;false&quot; title=&quot;Toggle line numbers&quot;&gt;&lt;svg class=&quot;bamboo-code-icon&quot; viewBox=&quot;0 0 20 20&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;1.6&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M4 5h2M4 10h2M4 15h2&quot; stroke-linecap=&quot;round&quot;/&gt;&lt;path d=&quot;M9 5h7M9 10h7M9 15h7&quot; stroke-linecap=&quot;round&quot;/&gt;&lt;/svg&gt;&lt;/button&gt;&lt;button type=&quot;button&quot; class=&quot;bamboo-code-button&quot; data-bamboo-copy aria-label=&quot;Copy code&quot; title=&quot;Copy code&quot;&gt;&lt;svg class=&quot;bamboo-code-icon bamboo-code-icon-copy&quot; viewBox=&quot;0 0 20 20&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;1.6&quot; aria-hidden=&quot;true&quot;&gt;&lt;rect x=&quot;7&quot; y=&quot;3&quot; width=&quot;10&quot; height=&quot;12&quot; rx=&quot;2&quot;/&gt;&lt;path d=&quot;M5 7v8a2 2 0 0 0 2 2h6&quot;/&gt;&lt;/svg&gt;&lt;svg class=&quot;bamboo-code-icon bamboo-code-icon-check&quot; viewBox=&quot;0 0 20 20&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;2&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M4 10l4 4 8-8&quot; stroke-linecap=&quot;round&quot; stroke-linejoin=&quot;round&quot;/&gt;&lt;/svg&gt;&lt;/button&gt;&lt;/div&gt;&lt;pre style=&quot;background-color:#2b303b;color:#c0c5ce;&quot;&gt;&lt;code class=&quot;language-rust&quot;&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;fn &lt;/span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;physics_system&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;world&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;: &amp;amp;&lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt; World) {
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt; dt = world.resources.delta_time;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    world.&lt;/span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;query_mut&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;()
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        .&lt;/span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;with&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;POSITION &lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;| &lt;/span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;VELOCITY&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        .&lt;/span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;iter&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(|&lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;_entity&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;table&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;index&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;| {
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;            table.position[index].x += table.velocity[index].x * dt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;            table.position[index].y += table.velocity[index].y * dt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        });
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;freecs also generates a few things this series does not build directly. &lt;code&gt;modify_position(entity, f)&lt;/code&gt; mutates a component through a closure that releases the borrow at the end of the call, so you can write &lt;code&gt;world.modify_position(entity, |p| p.x += 1.0)&lt;/code&gt; and access the world again on the next line without an explicit drop. &lt;code&gt;spawn_batch(mask, count, init)&lt;/code&gt; reserves capacity for N entities and runs an init closure on each freshly-pushed slot in one call, which is the primitive a real game uses for bullet spawning, particle systems, and level loading. &lt;code&gt;par_for_each_mut&lt;/code&gt; parallelizes iteration via Rayon when the entity count and per-entity work both justify the overhead. Slice iteration (&lt;code&gt;iter_position_slices_mut&lt;/code&gt;) hands out &lt;code&gt;&amp;amp;mut [Position]&lt;/code&gt; for SIMD-friendly inner loops. The multi-world form &lt;code&gt;ecs! { Game { CoreWorld { ... } RenderWorld { ... } } }&lt;/code&gt; splits components across logical worlds with a shared entity allocator when the 64-component-per-world ceiling is not enough. Each of these is a mechanical extension of the kernel from this series, layered on without changing how the data is stored.&lt;/p&gt;
&lt;p&gt;The macro design itself is not in this series. Once the kernel underneath exists, writing a macro to stamp out the per-component fan-out is mechanical, and freecs already does it. The production version is on crates.io if you want to use it rather than rebuild it. The source is at &lt;a href=&quot;https://github.com/matthewjberger/freecs&quot;&gt;matthewjberger/freecs&lt;/a&gt; if you want to see how the macro arms work.&lt;/p&gt;
&lt;h2 id=&quot;where-the-engine-goes-from-here&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#where-the-engine-goes-from-here&quot;&gt;#&lt;/a&gt;Where the engine goes from here&lt;/h2&gt;
&lt;p&gt;The ECS is the bottom of the stack. A game engine adds rendering, asset loading, input, audio, scene serialization, scripting hooks, and so on. Each of these is most naturally expressed as components plus systems. The renderer is a system that reads &lt;code&gt;Transform + Mesh + Material&lt;/code&gt; and submits draw calls. The asset loader is a system that watches a &lt;code&gt;Pending&amp;lt;Texture&amp;gt;&lt;/code&gt; component and replaces it with &lt;code&gt;Loaded&amp;lt;Texture&amp;gt;&lt;/code&gt; when the file is ready. Scene serialization is a function that walks &lt;code&gt;for_each(ALL, ...)&lt;/code&gt; and emits the components per entity.&lt;/p&gt;
&lt;p&gt;The ECS does not solve any of those problems. It makes each of them small and self-contained instead of tangled with everything else.&lt;/p&gt;
&lt;h2 id=&quot;the-full-file&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#the-full-file&quot;&gt;#&lt;/a&gt;The full file&lt;/h2&gt;
&lt;p&gt;The complete file is around 825 lines and lives as a &lt;a href=&quot;https://gist.github.com/matthewjberger/4578b6d03514523f5f345951c7395b40&quot;&gt;gist&lt;/a&gt;. It compiles standalone in a fresh Cargo project. The &lt;code&gt;main&lt;/code&gt; function spawns a player, an enemy, and a landmark, runs a schedule of four systems for four frames, queues a despawn from inside a system at frame two, and exercises change detection, events, tags, and the command buffer in the process.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;cargo run&lt;/code&gt; produces four frames of output. Frames 0 and 1 print position-redraw lines for the player and enemy as they close in on each other, with no collision yet because they are still more than one unit apart. Frame 2 prints a collision line followed by both redraw lines as the two entities meet at the same x, and the main loop queues the enemy for despawn at the end of the frame. Frame 3 prints only the player&apos;s redraw, since the enemy is gone and the landmark has not moved since spawn. The render-changed system never prints the landmark because nothing has touched its position since the initial &lt;code&gt;set_position&lt;/code&gt; write, which means its tick stamp stayed at zero while the watermark advanced past it.&lt;/p&gt;
&lt;p&gt;One subtlety to call out in &lt;code&gt;collision_system&lt;/code&gt;. It collects positions into a &lt;code&gt;Vec&amp;lt;(Entity, Position)&amp;gt;&lt;/code&gt; before doing the O(N^2) check rather than reading them through &lt;code&gt;world.get_position&lt;/code&gt; during the inner loop. The reason is the borrow checker. We cannot hold immutable borrows of &lt;code&gt;world&lt;/code&gt; across the mutable call to &lt;code&gt;world.send_collision&lt;/code&gt; later in the same iteration. Collecting up front releases all the read borrows before any of the writes begin. A reader copying this pattern should know that is what the up-front &lt;code&gt;collect()&lt;/code&gt; is doing.&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;freecs lives at &lt;a href=&quot;https://github.com/matthewjberger/freecs&quot;&gt;matthewjberger/freecs&lt;/a&gt; and on crates.io as &lt;code&gt;freecs&lt;/code&gt;. It is what &lt;a href=&quot;https://github.com/matthewjberger/nightshade&quot;&gt;nightshade&lt;/a&gt;, my game engine, uses for every subsystem that touches entities. Transforms, scene graph, rendering, asset loading, input, audio, scripting, all of it goes through the same World. Once the ECS is in place, the rest of the engine is systems on top.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Build your own ECS (part 2), structural change and queries</title>
    <link href="https://matthewberger.dev/articles/posts/build-your-own-ecs-structural-change/" rel="alternate"/>
    <id>https://matthewberger.dev/articles/posts/build-your-own-ecs-structural-change/</id>
    <updated>2026-08-02T00:00:00+00:00</updated>
    <summary type="text">Adding and removing components at runtime by migrating entities between archetypes, walking tables to satisfy queries, and the two caches that make both operations fast.</summary>
    <content type="html">&lt;p&gt;&lt;em&gt;This is part 2 of 3 of a series.&lt;/em&gt; ← &lt;a href=&quot;@/posts/2026-07-26-build-your-own-ecs-archetype-storage.md&quot;&gt;Archetype storage&lt;/a&gt; | Next → &lt;a href=&quot;@/posts/2026-08-09-build-your-own-ecs-events-changes-tags-commands.md&quot;&gt;Change detection, events, tags, and commands&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;@/posts/2026-07-26-build-your-own-ecs-archetype-storage.md&quot;&gt;Part 1&lt;/a&gt; built the storage. Generational entity handles, archetype tables, and the routing layer that ties them together. By the end of it you could spawn entities into a specific archetype, read and write their components, and despawn them safely. What you could &lt;em&gt;not&lt;/em&gt; do was change an entity&apos;s components after spawn time, and you had no way to ask the world &quot;give me every entity that has X.&quot;&lt;/p&gt;
&lt;p&gt;This post fixes both. The core mechanic is the same as before. Archetypes are defined by their component set, so changing an entity&apos;s component set means physically moving the entity to a different table. Once that move is in place, queries are almost trivial. They are a walk over the tables whose mask satisfies the query.&lt;/p&gt;
&lt;p&gt;The naive implementations of both operations are O(N) in the number of tables, which is fine until you have a few dozen archetypes and several hundred queries per frame. The second half of the post adds two caches, an archetype graph for migration and a query cache for iteration, that turn both operations into near-constant time without changing the surface API.&lt;/p&gt;
&lt;p&gt;Start from the file at the end of part 1. We will add to it.&lt;/p&gt;
&lt;h2 id=&quot;adding-a-component-means-moving-the-entity&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#adding-a-component-means-moving-the-entity&quot;&gt;#&lt;/a&gt;Adding a component means moving the entity&lt;/h2&gt;
&lt;p&gt;If an entity is in a table with mask &lt;code&gt;POSITION&lt;/code&gt;, and we want to add &lt;code&gt;VELOCITY&lt;/code&gt; to it, the entity needs to end up in a table with mask &lt;code&gt;POSITION | VELOCITY&lt;/code&gt;. There is no in-place option. The &lt;code&gt;POSITION&lt;/code&gt;-only table has no &lt;code&gt;velocities&lt;/code&gt; vec to push into, and the &lt;code&gt;velocities&lt;/code&gt; slot is only present in tables whose mask includes the velocity bit. So adding a component is mechanically a migration.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Find or create the destination table.&lt;/li&gt;
&lt;li&gt;Take each existing component value out of the source table at the entity&apos;s slot.&lt;/li&gt;
&lt;li&gt;Push those values, plus defaults for the newly-added components, into the destination table.&lt;/li&gt;
&lt;li&gt;Update the entity&apos;s location to point at the destination table.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;swap_remove&lt;/code&gt; the entity&apos;s slot from the source table, updating the swapped-in entity&apos;s location.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Step 2 is the interesting one. We do not want to clone the components. A &lt;code&gt;Position&lt;/code&gt; may be cheap to clone, but the same machinery has to handle &lt;code&gt;Vec&amp;lt;Mesh&amp;gt;&lt;/code&gt; and &lt;code&gt;Box&amp;lt;MaterialHandle&amp;gt;&lt;/code&gt; and other components that are expensive or impossible to clone. We also do not want to allocate. The standard library has the tool we need. &lt;code&gt;std::mem::take&lt;/code&gt; swaps a value out, leaving &lt;code&gt;Default::default()&lt;/code&gt; in its place. This is why every component must implement &lt;code&gt;Default&lt;/code&gt;. Not because spawning needs defaults (though it does), but because migration needs them.&lt;/p&gt;
&lt;div class=&quot;bamboo-code-block&quot; data-bamboo-code data-bamboo-lang=&quot;rust&quot;&gt;&lt;div class=&quot;bamboo-code-toolbar&quot;&gt;&lt;button type=&quot;button&quot; class=&quot;bamboo-code-button&quot; data-bamboo-line-toggle aria-label=&quot;Toggle line numbers&quot; aria-pressed=&quot;false&quot; title=&quot;Toggle line numbers&quot;&gt;&lt;svg class=&quot;bamboo-code-icon&quot; viewBox=&quot;0 0 20 20&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;1.6&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M4 5h2M4 10h2M4 15h2&quot; stroke-linecap=&quot;round&quot;/&gt;&lt;path d=&quot;M9 5h7M9 10h7M9 15h7&quot; stroke-linecap=&quot;round&quot;/&gt;&lt;/svg&gt;&lt;/button&gt;&lt;button type=&quot;button&quot; class=&quot;bamboo-code-button&quot; data-bamboo-copy aria-label=&quot;Copy code&quot; title=&quot;Copy code&quot;&gt;&lt;svg class=&quot;bamboo-code-icon bamboo-code-icon-copy&quot; viewBox=&quot;0 0 20 20&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;1.6&quot; aria-hidden=&quot;true&quot;&gt;&lt;rect x=&quot;7&quot; y=&quot;3&quot; width=&quot;10&quot; height=&quot;12&quot; rx=&quot;2&quot;/&gt;&lt;path d=&quot;M5 7v8a2 2 0 0 0 2 2h6&quot;/&gt;&lt;/svg&gt;&lt;svg class=&quot;bamboo-code-icon bamboo-code-icon-check&quot; viewBox=&quot;0 0 20 20&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;2&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M4 10l4 4 8-8&quot; stroke-linecap=&quot;round&quot; stroke-linejoin=&quot;round&quot;/&gt;&lt;/svg&gt;&lt;/button&gt;&lt;/div&gt;&lt;pre style=&quot;background-color:#2b303b;color:#c0c5ce;&quot;&gt;&lt;code class=&quot;language-rust&quot;&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl &lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;World {
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub fn &lt;/span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;move_entity&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        &amp;amp;&lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;entity&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;: Entity,
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;from_table&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;usize&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;from_index&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;usize&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;to_table&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;usize&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    ) {
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt; from_mask = &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;.tables[from_table].mask;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt; position = &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;if&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt; from_mask &amp;amp; &lt;/span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;POSITION &lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;!= &lt;/span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0 &lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;            Some(std::mem::take(&amp;amp;&lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;.tables[from_table].positions[from_index]))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        } &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;else &lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;            None
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        };
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt; velocity = &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;if&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt; from_mask &amp;amp; &lt;/span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;VELOCITY &lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;!= &lt;/span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0 &lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;            Some(std::mem::take(&amp;amp;&lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;.tables[from_table].velocities[from_index]))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        } &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;else &lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;            None
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        };
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt; to_array_index = {
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;            &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt; to = &amp;amp;&lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;.tables[to_table];
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;            &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt; array_index = to.entities.&lt;/span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;len&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;();
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;            to.entities.&lt;/span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;push&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(entity);
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;            &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;if&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt; to.mask &amp;amp; &lt;/span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;POSITION &lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;!= &lt;/span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0 &lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;                to.positions.&lt;/span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;push&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(position.&lt;/span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;unwrap_or_default&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;());
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;            }
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;            &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;if&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt; to.mask &amp;amp; &lt;/span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;VELOCITY &lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;!= &lt;/span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0 &lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;                to.velocities.&lt;/span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;push&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(velocity.&lt;/span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;unwrap_or_default&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;());
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;            }
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;            array_index
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        };
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;.entity_locations.&lt;/span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;set&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(entity, to_table, to_array_index);
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt; from = &amp;amp;&lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;.tables[from_table];
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt; last_index = from.entities.&lt;/span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;len&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;() - &lt;/span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt; swapped = &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;if&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt; from_index &amp;lt; last_index {
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;            Some(from.entities[last_index])
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        } &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;else &lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;            None
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        };
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        from.entities.&lt;/span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;swap_remove&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(from_index);
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;if&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt; from.mask &amp;amp; &lt;/span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;POSITION &lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;!= &lt;/span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0 &lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;            from.positions.&lt;/span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;swap_remove&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(from_index);
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;if&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt; from.mask &amp;amp; &lt;/span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;VELOCITY &lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;!= &lt;/span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0 &lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;            from.velocities.&lt;/span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;swap_remove&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(from_index);
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;if let &lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;Some(moved) = swapped {
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;            &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;.entity_locations.&lt;/span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;set&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(moved, from_table, from_index);
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The first block pulls every component the source table holds out of the entity&apos;s slot, leaving &lt;code&gt;Default::default()&lt;/code&gt; behind temporarily. The second block pushes those values into the destination table, defaulting any components that are present in the destination but were not in the source. The third block compacts the source table with the same swap-remove dance as despawn.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;unwrap_or_default()&lt;/code&gt; is what makes adding a brand-new component to an entity work. The source table did not have a velocity, so &lt;code&gt;velocity&lt;/code&gt; is &lt;code&gt;None&lt;/code&gt;. The destination has velocity, so we push a default. The same line handles the case where the destination has a component the source already had. &lt;code&gt;Some(value).unwrap_or_default()&lt;/code&gt; is &lt;code&gt;value&lt;/code&gt;, no default involved.&lt;/p&gt;
&lt;p&gt;One precondition &lt;code&gt;move_entity&lt;/code&gt; does not check. &lt;code&gt;from_table != to_table&lt;/code&gt;. The bottom &lt;code&gt;swap_remove&lt;/code&gt; block would clobber the slot we just pushed if they were the same. The public callers &lt;code&gt;add_components&lt;/code&gt; and &lt;code&gt;remove_components&lt;/code&gt; short-circuit on no-op masks before they reach &lt;code&gt;move_entity&lt;/code&gt;, so the precondition holds in practice. A reader copying &lt;code&gt;move_entity&lt;/code&gt; somewhere else should re-establish it with an assert or an early return.&lt;/p&gt;
&lt;h2 id=&quot;add-components-and-remove-components&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#add-components-and-remove-components&quot;&gt;#&lt;/a&gt;add_components and remove_components&lt;/h2&gt;
&lt;p&gt;With &lt;code&gt;move_entity&lt;/code&gt; in place, the public operations are short.&lt;/p&gt;
&lt;div class=&quot;bamboo-code-block&quot; data-bamboo-code data-bamboo-lang=&quot;rust&quot;&gt;&lt;div class=&quot;bamboo-code-toolbar&quot;&gt;&lt;button type=&quot;button&quot; class=&quot;bamboo-code-button&quot; data-bamboo-line-toggle aria-label=&quot;Toggle line numbers&quot; aria-pressed=&quot;false&quot; title=&quot;Toggle line numbers&quot;&gt;&lt;svg class=&quot;bamboo-code-icon&quot; viewBox=&quot;0 0 20 20&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;1.6&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M4 5h2M4 10h2M4 15h2&quot; stroke-linecap=&quot;round&quot;/&gt;&lt;path d=&quot;M9 5h7M9 10h7M9 15h7&quot; stroke-linecap=&quot;round&quot;/&gt;&lt;/svg&gt;&lt;/button&gt;&lt;button type=&quot;button&quot; class=&quot;bamboo-code-button&quot; data-bamboo-copy aria-label=&quot;Copy code&quot; title=&quot;Copy code&quot;&gt;&lt;svg class=&quot;bamboo-code-icon bamboo-code-icon-copy&quot; viewBox=&quot;0 0 20 20&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;1.6&quot; aria-hidden=&quot;true&quot;&gt;&lt;rect x=&quot;7&quot; y=&quot;3&quot; width=&quot;10&quot; height=&quot;12&quot; rx=&quot;2&quot;/&gt;&lt;path d=&quot;M5 7v8a2 2 0 0 0 2 2h6&quot;/&gt;&lt;/svg&gt;&lt;svg class=&quot;bamboo-code-icon bamboo-code-icon-check&quot; viewBox=&quot;0 0 20 20&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;2&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M4 10l4 4 8-8&quot; stroke-linecap=&quot;round&quot; stroke-linejoin=&quot;round&quot;/&gt;&lt;/svg&gt;&lt;/button&gt;&lt;/div&gt;&lt;pre style=&quot;background-color:#2b303b;color:#c0c5ce;&quot;&gt;&lt;code class=&quot;language-rust&quot;&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl &lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;World {
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub fn &lt;/span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;add_components&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(&amp;amp;&lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;entity&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;: Entity, &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;mask&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u64&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;) -&amp;gt; &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;bool &lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let &lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;Some((table_index, array_index)) = &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;.entity_locations.&lt;/span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;get&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(entity) &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;else &lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;            &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;return &lt;/span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;false&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        };
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt; current_mask = &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;.tables[table_index].mask;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;if&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt; current_mask &amp;amp; mask == mask {
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;            &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;return &lt;/span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;true&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt; new_mask = current_mask | mask;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt; new_table_index = &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;get_or_create_table&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(new_mask);
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;move_entity&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(entity, table_index, array_index, new_table_index);
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;true
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub fn &lt;/span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;remove_components&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(&amp;amp;&lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;entity&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;: Entity, &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;mask&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u64&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;) -&amp;gt; &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;bool &lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let &lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;Some((table_index, array_index)) = &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;.entity_locations.&lt;/span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;get&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(entity) &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;else &lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;            &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;return &lt;/span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;false&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        };
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt; current_mask = &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;.tables[table_index].mask;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;if&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt; current_mask &amp;amp; mask == &lt;/span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0 &lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;            &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;return &lt;/span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;true&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt; new_mask = current_mask &amp;amp; !mask;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt; new_table_index = &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;get_or_create_table&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(new_mask);
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;move_entity&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(entity, table_index, array_index, new_table_index);
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;true
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Both short-circuit when the operation would be a no-op. Adding components that the entity already has does nothing. Removing components the entity does not have does nothing. The mask test happens before we do any work, so an idempotent call costs a vec lookup and a bitwise check.&lt;/p&gt;
&lt;p&gt;Both accept a multi-component mask. If we had a third component &lt;code&gt;HEALTH&lt;/code&gt;, then &lt;code&gt;add_components(entity, VELOCITY | HEALTH)&lt;/code&gt; would do a single migration to the table for &lt;code&gt;current_mask | VELOCITY | HEALTH&lt;/code&gt;. Two separate calls would do two migrations and re-copy the unchanged components twice. One combined call is meaningfully faster.&lt;/p&gt;
&lt;p&gt;While we are here, a couple of conveniences. A &lt;code&gt;set_position&lt;/code&gt; that adds the component if it is missing makes scripting code much nicer to write. A spawn variant that takes an initial value avoids the &lt;code&gt;spawn(...); world.get_position_mut(e).unwrap() = ...&lt;/code&gt; two-step.&lt;/p&gt;
&lt;div class=&quot;bamboo-code-block&quot; data-bamboo-code data-bamboo-lang=&quot;rust&quot;&gt;&lt;div class=&quot;bamboo-code-toolbar&quot;&gt;&lt;button type=&quot;button&quot; class=&quot;bamboo-code-button&quot; data-bamboo-line-toggle aria-label=&quot;Toggle line numbers&quot; aria-pressed=&quot;false&quot; title=&quot;Toggle line numbers&quot;&gt;&lt;svg class=&quot;bamboo-code-icon&quot; viewBox=&quot;0 0 20 20&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;1.6&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M4 5h2M4 10h2M4 15h2&quot; stroke-linecap=&quot;round&quot;/&gt;&lt;path d=&quot;M9 5h7M9 10h7M9 15h7&quot; stroke-linecap=&quot;round&quot;/&gt;&lt;/svg&gt;&lt;/button&gt;&lt;button type=&quot;button&quot; class=&quot;bamboo-code-button&quot; data-bamboo-copy aria-label=&quot;Copy code&quot; title=&quot;Copy code&quot;&gt;&lt;svg class=&quot;bamboo-code-icon bamboo-code-icon-copy&quot; viewBox=&quot;0 0 20 20&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;1.6&quot; aria-hidden=&quot;true&quot;&gt;&lt;rect x=&quot;7&quot; y=&quot;3&quot; width=&quot;10&quot; height=&quot;12&quot; rx=&quot;2&quot;/&gt;&lt;path d=&quot;M5 7v8a2 2 0 0 0 2 2h6&quot;/&gt;&lt;/svg&gt;&lt;svg class=&quot;bamboo-code-icon bamboo-code-icon-check&quot; viewBox=&quot;0 0 20 20&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;2&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M4 10l4 4 8-8&quot; stroke-linecap=&quot;round&quot; stroke-linejoin=&quot;round&quot;/&gt;&lt;/svg&gt;&lt;/button&gt;&lt;/div&gt;&lt;pre style=&quot;background-color:#2b303b;color:#c0c5ce;&quot;&gt;&lt;code class=&quot;language-rust&quot;&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl &lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;World {
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub fn &lt;/span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;set_position&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(&amp;amp;&lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;entity&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;: Entity, &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;value&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;: Position) {
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let &lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;Some((table_index, array_index)) = &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;.entity_locations.&lt;/span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;get&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(entity) &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;else &lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;            &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;return&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        };
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;if &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;.tables[table_index].mask &amp;amp; &lt;/span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;POSITION &lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;!= &lt;/span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0 &lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;            &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;.tables[table_index].positions[array_index] = value;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;            &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;return&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;add_components&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(entity, &lt;/span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;POSITION&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;if let &lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;Some((table_index, array_index)) = &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;.entity_locations.&lt;/span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;get&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(entity) {
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;            &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;.tables[table_index].positions[array_index] = value;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub fn &lt;/span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;set_velocity&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(&amp;amp;&lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;entity&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;: Entity, &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;value&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;: Velocity) {
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let &lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;Some((table_index, array_index)) = &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;.entity_locations.&lt;/span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;get&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(entity) &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;else &lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;            &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;return&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        };
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;if &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;.tables[table_index].mask &amp;amp; &lt;/span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;VELOCITY &lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;!= &lt;/span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0 &lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;            &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;.tables[table_index].velocities[array_index] = value;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;            &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;return&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;add_components&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(entity, &lt;/span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;VELOCITY&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;if let &lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;Some((table_index, array_index)) = &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;.entity_locations.&lt;/span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;get&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(entity) {
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;            &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;.tables[table_index].velocities[array_index] = value;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The structure is the same for both. Fast path if the component is already present, otherwise migrate and then write. The location must be re-fetched after migration because the entity is no longer in the same table.&lt;/p&gt;
&lt;p&gt;A second convenience worth adding is a builder that spawns an entity with a chosen set of components in one call. So far every spawn that wants specific component values has been a two-step. Call &lt;code&gt;world.spawn(POSITION | VELOCITY)&lt;/code&gt; to get an entity, then write &lt;code&gt;world.get_position_mut(entity).unwrap() = Position { x: 1.0, y: 2.0 }&lt;/code&gt; and the same for velocity. That works and it reads awkwardly. The default values the spawn put in exist only to be overwritten on the next line.&lt;/p&gt;
&lt;p&gt;A small builder collapses it.&lt;/p&gt;
&lt;div class=&quot;bamboo-code-block&quot; data-bamboo-code data-bamboo-lang=&quot;rust&quot;&gt;&lt;div class=&quot;bamboo-code-toolbar&quot;&gt;&lt;button type=&quot;button&quot; class=&quot;bamboo-code-button&quot; data-bamboo-line-toggle aria-label=&quot;Toggle line numbers&quot; aria-pressed=&quot;false&quot; title=&quot;Toggle line numbers&quot;&gt;&lt;svg class=&quot;bamboo-code-icon&quot; viewBox=&quot;0 0 20 20&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;1.6&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M4 5h2M4 10h2M4 15h2&quot; stroke-linecap=&quot;round&quot;/&gt;&lt;path d=&quot;M9 5h7M9 10h7M9 15h7&quot; stroke-linecap=&quot;round&quot;/&gt;&lt;/svg&gt;&lt;/button&gt;&lt;button type=&quot;button&quot; class=&quot;bamboo-code-button&quot; data-bamboo-copy aria-label=&quot;Copy code&quot; title=&quot;Copy code&quot;&gt;&lt;svg class=&quot;bamboo-code-icon bamboo-code-icon-copy&quot; viewBox=&quot;0 0 20 20&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;1.6&quot; aria-hidden=&quot;true&quot;&gt;&lt;rect x=&quot;7&quot; y=&quot;3&quot; width=&quot;10&quot; height=&quot;12&quot; rx=&quot;2&quot;/&gt;&lt;path d=&quot;M5 7v8a2 2 0 0 0 2 2h6&quot;/&gt;&lt;/svg&gt;&lt;svg class=&quot;bamboo-code-icon bamboo-code-icon-check&quot; viewBox=&quot;0 0 20 20&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;2&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M4 10l4 4 8-8&quot; stroke-linecap=&quot;round&quot; stroke-linejoin=&quot;round&quot;/&gt;&lt;/svg&gt;&lt;/button&gt;&lt;/div&gt;&lt;pre style=&quot;background-color:#2b303b;color:#c0c5ce;&quot;&gt;&lt;code class=&quot;language-rust&quot;&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;#[&lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;derive&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(Default)]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub struct &lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;EntityBuilder {
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;position&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;: Option&amp;lt;Position&amp;gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;velocity&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;: Option&amp;lt;Velocity&amp;gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl &lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;EntityBuilder {
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub fn &lt;/span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;new&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;() -&amp;gt; &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self &lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;::default()
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub fn &lt;/span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;with_position&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;value&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;: Position) -&amp;gt; &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self &lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;.position = Some(value);
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub fn &lt;/span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;with_velocity&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;value&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;: Velocity) -&amp;gt; &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;Self &lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;.velocity = Some(value);
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub fn &lt;/span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;spawn&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;world&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;: &amp;amp;&lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt; World) -&amp;gt; Entity {
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let mut&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt; mask = &lt;/span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u64&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;if &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;.position.&lt;/span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;is_some&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;            mask |= &lt;/span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;POSITION&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;if &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;.velocity.&lt;/span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;is_some&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;            mask |= &lt;/span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;VELOCITY&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt; entity = world.&lt;/span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;spawn&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(mask);
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;if let &lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;Some(value) = &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;.position {
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;            world.&lt;/span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;set_position&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(entity, value);
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;if let &lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;Some(value) = &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;.velocity {
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;            world.&lt;/span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;set_velocity&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(entity, value);
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        entity
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Usage:&lt;/p&gt;
&lt;div class=&quot;bamboo-code-block&quot; data-bamboo-code data-bamboo-lang=&quot;rust&quot;&gt;&lt;div class=&quot;bamboo-code-toolbar&quot;&gt;&lt;button type=&quot;button&quot; class=&quot;bamboo-code-button&quot; data-bamboo-line-toggle aria-label=&quot;Toggle line numbers&quot; aria-pressed=&quot;false&quot; title=&quot;Toggle line numbers&quot;&gt;&lt;svg class=&quot;bamboo-code-icon&quot; viewBox=&quot;0 0 20 20&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;1.6&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M4 5h2M4 10h2M4 15h2&quot; stroke-linecap=&quot;round&quot;/&gt;&lt;path d=&quot;M9 5h7M9 10h7M9 15h7&quot; stroke-linecap=&quot;round&quot;/&gt;&lt;/svg&gt;&lt;/button&gt;&lt;button type=&quot;button&quot; class=&quot;bamboo-code-button&quot; data-bamboo-copy aria-label=&quot;Copy code&quot; title=&quot;Copy code&quot;&gt;&lt;svg class=&quot;bamboo-code-icon bamboo-code-icon-copy&quot; viewBox=&quot;0 0 20 20&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;1.6&quot; aria-hidden=&quot;true&quot;&gt;&lt;rect x=&quot;7&quot; y=&quot;3&quot; width=&quot;10&quot; height=&quot;12&quot; rx=&quot;2&quot;/&gt;&lt;path d=&quot;M5 7v8a2 2 0 0 0 2 2h6&quot;/&gt;&lt;/svg&gt;&lt;svg class=&quot;bamboo-code-icon bamboo-code-icon-check&quot; viewBox=&quot;0 0 20 20&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;2&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M4 10l4 4 8-8&quot; stroke-linecap=&quot;round&quot; stroke-linejoin=&quot;round&quot;/&gt;&lt;/svg&gt;&lt;/button&gt;&lt;/div&gt;&lt;pre style=&quot;background-color:#2b303b;color:#c0c5ce;&quot;&gt;&lt;code class=&quot;language-rust&quot;&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt; mover = EntityBuilder::new()
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    .&lt;/span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;with_position&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(Position { x: &lt;/span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1.0&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;, y: &lt;/span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;2.0 &lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;})
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    .&lt;/span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;with_velocity&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(Velocity { x: &lt;/span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0.5&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;, y: &lt;/span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0.25 &lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;})
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    .&lt;/span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;spawn&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(&amp;amp;&lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt; world);
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The builder figures out the archetype mask from which fields were set, calls &lt;code&gt;world.spawn(mask)&lt;/code&gt; to create the entity in the right archetype directly, then writes each value through &lt;code&gt;world.set_position&lt;/code&gt; and &lt;code&gt;world.set_velocity&lt;/code&gt;. Going through the public setters rather than reaching into the tables directly means that any bookkeeping the setters do (the change-detection tick stamping we add in part 3, for example) the builder picks up automatically with no extra wiring.&lt;/p&gt;
&lt;h2 id=&quot;queries&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#queries&quot;&gt;#&lt;/a&gt;Queries&lt;/h2&gt;
&lt;p&gt;A query is &quot;give me every entity that has at least this set of components.&quot; With archetype storage it is a walk over the tables. For each table, if its mask is a superset of the query mask, every entity in it satisfies the query. The mask comparison &lt;code&gt;table.mask &amp;amp; query_mask == query_mask&lt;/code&gt; is one CPU instruction.&lt;/p&gt;
&lt;p&gt;The simplest entity-yielding query is an iterator.&lt;/p&gt;
&lt;div class=&quot;bamboo-code-block&quot; data-bamboo-code data-bamboo-lang=&quot;rust&quot;&gt;&lt;div class=&quot;bamboo-code-toolbar&quot;&gt;&lt;button type=&quot;button&quot; class=&quot;bamboo-code-button&quot; data-bamboo-line-toggle aria-label=&quot;Toggle line numbers&quot; aria-pressed=&quot;false&quot; title=&quot;Toggle line numbers&quot;&gt;&lt;svg class=&quot;bamboo-code-icon&quot; viewBox=&quot;0 0 20 20&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;1.6&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M4 5h2M4 10h2M4 15h2&quot; stroke-linecap=&quot;round&quot;/&gt;&lt;path d=&quot;M9 5h7M9 10h7M9 15h7&quot; stroke-linecap=&quot;round&quot;/&gt;&lt;/svg&gt;&lt;/button&gt;&lt;button type=&quot;button&quot; class=&quot;bamboo-code-button&quot; data-bamboo-copy aria-label=&quot;Copy code&quot; title=&quot;Copy code&quot;&gt;&lt;svg class=&quot;bamboo-code-icon bamboo-code-icon-copy&quot; viewBox=&quot;0 0 20 20&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;1.6&quot; aria-hidden=&quot;true&quot;&gt;&lt;rect x=&quot;7&quot; y=&quot;3&quot; width=&quot;10&quot; height=&quot;12&quot; rx=&quot;2&quot;/&gt;&lt;path d=&quot;M5 7v8a2 2 0 0 0 2 2h6&quot;/&gt;&lt;/svg&gt;&lt;svg class=&quot;bamboo-code-icon bamboo-code-icon-check&quot; viewBox=&quot;0 0 20 20&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;2&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M4 10l4 4 8-8&quot; stroke-linecap=&quot;round&quot; stroke-linejoin=&quot;round&quot;/&gt;&lt;/svg&gt;&lt;/button&gt;&lt;/div&gt;&lt;pre style=&quot;background-color:#2b303b;color:#c0c5ce;&quot;&gt;&lt;code class=&quot;language-rust&quot;&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl &lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;World {
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub fn &lt;/span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;query_entities&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(&amp;amp;&lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;mask&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u64&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;) -&amp;gt; impl Iterator&amp;lt;Item = Entity&amp;gt; + &amp;#39;_ {
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;.tables
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;            .&lt;/span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;iter&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;()
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;            .&lt;/span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;filter&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;move &lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;|table| table.mask &amp;amp; mask == mask)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;            .&lt;/span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;flat_map&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(|&lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;table&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;| table.entities.&lt;/span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;iter&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;().&lt;/span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;copied&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;())
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Using it.&lt;/p&gt;
&lt;div class=&quot;bamboo-code-block&quot; data-bamboo-code data-bamboo-lang=&quot;rust&quot;&gt;&lt;div class=&quot;bamboo-code-toolbar&quot;&gt;&lt;button type=&quot;button&quot; class=&quot;bamboo-code-button&quot; data-bamboo-line-toggle aria-label=&quot;Toggle line numbers&quot; aria-pressed=&quot;false&quot; title=&quot;Toggle line numbers&quot;&gt;&lt;svg class=&quot;bamboo-code-icon&quot; viewBox=&quot;0 0 20 20&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;1.6&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M4 5h2M4 10h2M4 15h2&quot; stroke-linecap=&quot;round&quot;/&gt;&lt;path d=&quot;M9 5h7M9 10h7M9 15h7&quot; stroke-linecap=&quot;round&quot;/&gt;&lt;/svg&gt;&lt;/button&gt;&lt;button type=&quot;button&quot; class=&quot;bamboo-code-button&quot; data-bamboo-copy aria-label=&quot;Copy code&quot; title=&quot;Copy code&quot;&gt;&lt;svg class=&quot;bamboo-code-icon bamboo-code-icon-copy&quot; viewBox=&quot;0 0 20 20&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;1.6&quot; aria-hidden=&quot;true&quot;&gt;&lt;rect x=&quot;7&quot; y=&quot;3&quot; width=&quot;10&quot; height=&quot;12&quot; rx=&quot;2&quot;/&gt;&lt;path d=&quot;M5 7v8a2 2 0 0 0 2 2h6&quot;/&gt;&lt;/svg&gt;&lt;svg class=&quot;bamboo-code-icon bamboo-code-icon-check&quot; viewBox=&quot;0 0 20 20&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;2&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M4 10l4 4 8-8&quot; stroke-linecap=&quot;round&quot; stroke-linejoin=&quot;round&quot;/&gt;&lt;/svg&gt;&lt;/button&gt;&lt;/div&gt;&lt;pre style=&quot;background-color:#2b303b;color:#c0c5ce;&quot;&gt;&lt;code class=&quot;language-rust&quot;&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;for&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt; entity in world.&lt;/span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;query_entities&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;POSITION &lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;| &lt;/span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;VELOCITY&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt; position = world.&lt;/span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;get_position&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(entity).&lt;/span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;unwrap&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;();
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt; velocity = world.&lt;/span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;get_velocity&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(entity).&lt;/span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;unwrap&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;();
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    println!(&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;{entity:?}&lt;/span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;: (&lt;/span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;{}&lt;/span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;{}&lt;/span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;) v=(&lt;/span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;{}&lt;/span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;{}&lt;/span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;&amp;quot;, position.x, position.y, velocity.x, velocity.y);
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This works, and for read-only loops it is the most ergonomic API. But it pays for each component access by going through the location map. For tight inner loops (the physics step, the AI tick) you want direct access to the underlying vecs, where the index into one vec is the index into the others. The pattern is a callback that gets called with the entity, the table, and the slot index.&lt;/p&gt;
&lt;div class=&quot;bamboo-code-block&quot; data-bamboo-code data-bamboo-lang=&quot;rust&quot;&gt;&lt;div class=&quot;bamboo-code-toolbar&quot;&gt;&lt;button type=&quot;button&quot; class=&quot;bamboo-code-button&quot; data-bamboo-line-toggle aria-label=&quot;Toggle line numbers&quot; aria-pressed=&quot;false&quot; title=&quot;Toggle line numbers&quot;&gt;&lt;svg class=&quot;bamboo-code-icon&quot; viewBox=&quot;0 0 20 20&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;1.6&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M4 5h2M4 10h2M4 15h2&quot; stroke-linecap=&quot;round&quot;/&gt;&lt;path d=&quot;M9 5h7M9 10h7M9 15h7&quot; stroke-linecap=&quot;round&quot;/&gt;&lt;/svg&gt;&lt;/button&gt;&lt;button type=&quot;button&quot; class=&quot;bamboo-code-button&quot; data-bamboo-copy aria-label=&quot;Copy code&quot; title=&quot;Copy code&quot;&gt;&lt;svg class=&quot;bamboo-code-icon bamboo-code-icon-copy&quot; viewBox=&quot;0 0 20 20&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;1.6&quot; aria-hidden=&quot;true&quot;&gt;&lt;rect x=&quot;7&quot; y=&quot;3&quot; width=&quot;10&quot; height=&quot;12&quot; rx=&quot;2&quot;/&gt;&lt;path d=&quot;M5 7v8a2 2 0 0 0 2 2h6&quot;/&gt;&lt;/svg&gt;&lt;svg class=&quot;bamboo-code-icon bamboo-code-icon-check&quot; viewBox=&quot;0 0 20 20&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;2&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M4 10l4 4 8-8&quot; stroke-linecap=&quot;round&quot; stroke-linejoin=&quot;round&quot;/&gt;&lt;/svg&gt;&lt;/button&gt;&lt;/div&gt;&lt;pre style=&quot;background-color:#2b303b;color:#c0c5ce;&quot;&gt;&lt;code class=&quot;language-rust&quot;&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl &lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;World {
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub fn &lt;/span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;for_each&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;&amp;lt;F&amp;gt;(&amp;amp;&lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;include&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u64&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;exclude&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u64&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;f&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;: F)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;where
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        F: FnMut(Entity, &amp;amp;ComponentArrays, &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;usize&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;),
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    {
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;for&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt; table in &amp;amp;&lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;.tables {
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;            &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;if&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt; table.mask &amp;amp; include != include || table.mask &amp;amp; exclude != &lt;/span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0 &lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;                &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;continue&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;            }
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;            &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;for&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt; array_index in &lt;/span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;..table.entities.&lt;/span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;len&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;                &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt; entity = table.entities[array_index];
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;                &lt;/span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;f&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(entity, table, array_index);
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;            }
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub fn &lt;/span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;for_each_mut&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;&amp;lt;F&amp;gt;(&amp;amp;&lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;include&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u64&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;exclude&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u64&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;f&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;: F)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;where
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        F: FnMut(Entity, &amp;amp;&lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt; ComponentArrays, &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;usize&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;),
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    {
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;for&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt; table in &amp;amp;&lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;.tables {
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;            &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;if&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt; table.mask &amp;amp; include != include || table.mask &amp;amp; exclude != &lt;/span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0 &lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;                &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;continue&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;            }
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;            &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;for&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt; array_index in &lt;/span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;..table.entities.&lt;/span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;len&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;                &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt; entity = table.entities[array_index];
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;                &lt;/span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;f&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(entity, table, array_index);
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;            }
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The physics step then looks like the following.&lt;/p&gt;
&lt;div class=&quot;bamboo-code-block&quot; data-bamboo-code data-bamboo-lang=&quot;rust&quot;&gt;&lt;div class=&quot;bamboo-code-toolbar&quot;&gt;&lt;button type=&quot;button&quot; class=&quot;bamboo-code-button&quot; data-bamboo-line-toggle aria-label=&quot;Toggle line numbers&quot; aria-pressed=&quot;false&quot; title=&quot;Toggle line numbers&quot;&gt;&lt;svg class=&quot;bamboo-code-icon&quot; viewBox=&quot;0 0 20 20&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;1.6&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M4 5h2M4 10h2M4 15h2&quot; stroke-linecap=&quot;round&quot;/&gt;&lt;path d=&quot;M9 5h7M9 10h7M9 15h7&quot; stroke-linecap=&quot;round&quot;/&gt;&lt;/svg&gt;&lt;/button&gt;&lt;button type=&quot;button&quot; class=&quot;bamboo-code-button&quot; data-bamboo-copy aria-label=&quot;Copy code&quot; title=&quot;Copy code&quot;&gt;&lt;svg class=&quot;bamboo-code-icon bamboo-code-icon-copy&quot; viewBox=&quot;0 0 20 20&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;1.6&quot; aria-hidden=&quot;true&quot;&gt;&lt;rect x=&quot;7&quot; y=&quot;3&quot; width=&quot;10&quot; height=&quot;12&quot; rx=&quot;2&quot;/&gt;&lt;path d=&quot;M5 7v8a2 2 0 0 0 2 2h6&quot;/&gt;&lt;/svg&gt;&lt;svg class=&quot;bamboo-code-icon bamboo-code-icon-check&quot; viewBox=&quot;0 0 20 20&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;2&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M4 10l4 4 8-8&quot; stroke-linecap=&quot;round&quot; stroke-linejoin=&quot;round&quot;/&gt;&lt;/svg&gt;&lt;/button&gt;&lt;/div&gt;&lt;pre style=&quot;background-color:#2b303b;color:#c0c5ce;&quot;&gt;&lt;code class=&quot;language-rust&quot;&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;world.&lt;/span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;for_each_mut&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;POSITION &lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;| &lt;/span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;VELOCITY&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;, |&lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;_entity&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;table&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;index&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;| {
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    table.positions[index].x += table.velocities[index].x;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    table.positions[index].y += table.velocities[index].y;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;});
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;include&lt;/code&gt; is the mask of components the entity must have. &lt;code&gt;exclude&lt;/code&gt; is the mask of components the entity must &lt;em&gt;not&lt;/em&gt; have, useful for &quot;every entity with &lt;code&gt;POSITION&lt;/code&gt; that is not a &lt;code&gt;PLAYER&lt;/code&gt;&quot; once we have tags. Passing &lt;code&gt;0&lt;/code&gt; for exclude is the common case.&lt;/p&gt;
&lt;p&gt;The closure receives the whole &lt;code&gt;ComponentArrays&lt;/code&gt;, not a tuple of &lt;code&gt;&amp;amp;mut Position, &amp;amp;mut Velocity&lt;/code&gt;. The reason is the same as the earlier complaint about boilerplate. Extracting tuples of borrowed components requires either generics with associated types or a macro, and we are deliberately doing neither. Direct table access is uglier at the call site but stays trivial in the implementation.&lt;/p&gt;
&lt;h2 id=&quot;making-the-migration-fast&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#making-the-migration-fast&quot;&gt;#&lt;/a&gt;Making the migration fast&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;add_components(entity, VELOCITY)&lt;/code&gt; currently does this.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Look up the entity&apos;s current table via the location map (&lt;code&gt;entity_locations.get&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;Compute &lt;code&gt;new_mask = current_mask | VELOCITY&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Look up the destination table by mask (&lt;code&gt;get_or_create_table&lt;/code&gt;, which hits &lt;code&gt;table_lookup&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;Migrate.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Step 3 is the slow one. It is a hashmap lookup, and it fires on every structural change. If a thousand entities each take and release a &quot;stunned&quot; component each frame, that is two thousand hashmap probes per frame just for the table lookups. Step 1 is already fast (vec indexed by id). The migration itself is fundamental work.&lt;/p&gt;
&lt;p&gt;Notice the structure of step 3. From a given source table, the destination after adding &lt;em&gt;any specific component&lt;/em&gt; is fixed. The table for &lt;code&gt;POSITION&lt;/code&gt; plus the velocity bit is always the table for &lt;code&gt;POSITION | VELOCITY&lt;/code&gt;. So we can store, on each table, an array of &quot;if you add component bit N, here is the destination table index&quot;, and another for removal. Lookup becomes an array index, no hashing.&lt;/p&gt;
&lt;div class=&quot;bamboo-code-block&quot; data-bamboo-code data-bamboo-lang=&quot;rust&quot;&gt;&lt;div class=&quot;bamboo-code-toolbar&quot;&gt;&lt;button type=&quot;button&quot; class=&quot;bamboo-code-button&quot; data-bamboo-line-toggle aria-label=&quot;Toggle line numbers&quot; aria-pressed=&quot;false&quot; title=&quot;Toggle line numbers&quot;&gt;&lt;svg class=&quot;bamboo-code-icon&quot; viewBox=&quot;0 0 20 20&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;1.6&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M4 5h2M4 10h2M4 15h2&quot; stroke-linecap=&quot;round&quot;/&gt;&lt;path d=&quot;M9 5h7M9 10h7M9 15h7&quot; stroke-linecap=&quot;round&quot;/&gt;&lt;/svg&gt;&lt;/button&gt;&lt;button type=&quot;button&quot; class=&quot;bamboo-code-button&quot; data-bamboo-copy aria-label=&quot;Copy code&quot; title=&quot;Copy code&quot;&gt;&lt;svg class=&quot;bamboo-code-icon bamboo-code-icon-copy&quot; viewBox=&quot;0 0 20 20&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;1.6&quot; aria-hidden=&quot;true&quot;&gt;&lt;rect x=&quot;7&quot; y=&quot;3&quot; width=&quot;10&quot; height=&quot;12&quot; rx=&quot;2&quot;/&gt;&lt;path d=&quot;M5 7v8a2 2 0 0 0 2 2h6&quot;/&gt;&lt;/svg&gt;&lt;svg class=&quot;bamboo-code-icon bamboo-code-icon-check&quot; viewBox=&quot;0 0 20 20&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;2&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M4 10l4 4 8-8&quot; stroke-linecap=&quot;round&quot; stroke-linejoin=&quot;round&quot;/&gt;&lt;/svg&gt;&lt;/button&gt;&lt;/div&gt;&lt;pre style=&quot;background-color:#2b303b;color:#c0c5ce;&quot;&gt;&lt;code class=&quot;language-rust&quot;&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub const &lt;/span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;COMPONENT_COUNT&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;usize &lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;= &lt;/span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;2&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;#[&lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;derive&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(Default, Clone)]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub struct &lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;TableEdges {
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;add_edges&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;: [Option&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;usize&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;&amp;gt;; COMPONENT_COUNT],
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;remove_edges&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;: [Option&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;usize&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;&amp;gt;; COMPONENT_COUNT],
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The array is indexed by &lt;em&gt;component bit position&lt;/em&gt;, not by mask. Bit 0 is position, bit 1 is velocity. To turn a single-bit mask into its bit position we need a small helper.&lt;/p&gt;
&lt;div class=&quot;bamboo-code-block&quot; data-bamboo-code data-bamboo-lang=&quot;rust&quot;&gt;&lt;div class=&quot;bamboo-code-toolbar&quot;&gt;&lt;button type=&quot;button&quot; class=&quot;bamboo-code-button&quot; data-bamboo-line-toggle aria-label=&quot;Toggle line numbers&quot; aria-pressed=&quot;false&quot; title=&quot;Toggle line numbers&quot;&gt;&lt;svg class=&quot;bamboo-code-icon&quot; viewBox=&quot;0 0 20 20&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;1.6&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M4 5h2M4 10h2M4 15h2&quot; stroke-linecap=&quot;round&quot;/&gt;&lt;path d=&quot;M9 5h7M9 10h7M9 15h7&quot; stroke-linecap=&quot;round&quot;/&gt;&lt;/svg&gt;&lt;/button&gt;&lt;button type=&quot;button&quot; class=&quot;bamboo-code-button&quot; data-bamboo-copy aria-label=&quot;Copy code&quot; title=&quot;Copy code&quot;&gt;&lt;svg class=&quot;bamboo-code-icon bamboo-code-icon-copy&quot; viewBox=&quot;0 0 20 20&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;1.6&quot; aria-hidden=&quot;true&quot;&gt;&lt;rect x=&quot;7&quot; y=&quot;3&quot; width=&quot;10&quot; height=&quot;12&quot; rx=&quot;2&quot;/&gt;&lt;path d=&quot;M5 7v8a2 2 0 0 0 2 2h6&quot;/&gt;&lt;/svg&gt;&lt;svg class=&quot;bamboo-code-icon bamboo-code-icon-check&quot; viewBox=&quot;0 0 20 20&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;2&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M4 10l4 4 8-8&quot; stroke-linecap=&quot;round&quot; stroke-linejoin=&quot;round&quot;/&gt;&lt;/svg&gt;&lt;/button&gt;&lt;/div&gt;&lt;pre style=&quot;background-color:#2b303b;color:#c0c5ce;&quot;&gt;&lt;code class=&quot;language-rust&quot;&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub fn &lt;/span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;component_index&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;mask&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u64&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;) -&amp;gt; Option&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;usize&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;&amp;gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;match&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt; mask {
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;POSITION &lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;=&amp;gt; Some(&lt;/span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;),
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;VELOCITY &lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;=&amp;gt; Some(&lt;/span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;),
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        _ =&amp;gt; None,
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This only handles single-bit masks. Multi-bit adds (adding more than one component in a single call) cannot be represented as a single edge in the graph, because the destination depends on the combination of bits added together. We will treat those as a slow-path miss.&lt;/p&gt;
&lt;p&gt;Storing one &lt;code&gt;TableEdges&lt;/code&gt; per table.&lt;/p&gt;
&lt;div class=&quot;bamboo-code-block&quot; data-bamboo-code data-bamboo-lang=&quot;rust&quot;&gt;&lt;div class=&quot;bamboo-code-toolbar&quot;&gt;&lt;button type=&quot;button&quot; class=&quot;bamboo-code-button&quot; data-bamboo-line-toggle aria-label=&quot;Toggle line numbers&quot; aria-pressed=&quot;false&quot; title=&quot;Toggle line numbers&quot;&gt;&lt;svg class=&quot;bamboo-code-icon&quot; viewBox=&quot;0 0 20 20&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;1.6&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M4 5h2M4 10h2M4 15h2&quot; stroke-linecap=&quot;round&quot;/&gt;&lt;path d=&quot;M9 5h7M9 10h7M9 15h7&quot; stroke-linecap=&quot;round&quot;/&gt;&lt;/svg&gt;&lt;/button&gt;&lt;button type=&quot;button&quot; class=&quot;bamboo-code-button&quot; data-bamboo-copy aria-label=&quot;Copy code&quot; title=&quot;Copy code&quot;&gt;&lt;svg class=&quot;bamboo-code-icon bamboo-code-icon-copy&quot; viewBox=&quot;0 0 20 20&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;1.6&quot; aria-hidden=&quot;true&quot;&gt;&lt;rect x=&quot;7&quot; y=&quot;3&quot; width=&quot;10&quot; height=&quot;12&quot; rx=&quot;2&quot;/&gt;&lt;path d=&quot;M5 7v8a2 2 0 0 0 2 2h6&quot;/&gt;&lt;/svg&gt;&lt;svg class=&quot;bamboo-code-icon bamboo-code-icon-check&quot; viewBox=&quot;0 0 20 20&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;2&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M4 10l4 4 8-8&quot; stroke-linecap=&quot;round&quot; stroke-linejoin=&quot;round&quot;/&gt;&lt;/svg&gt;&lt;/button&gt;&lt;/div&gt;&lt;pre style=&quot;background-color:#2b303b;color:#c0c5ce;&quot;&gt;&lt;code class=&quot;language-rust&quot;&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;#[&lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;derive&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(Default)]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub struct &lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;World {
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;allocator&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;: EntityAllocator,
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;entity_locations&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;: EntityLocations,
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;tables&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;: Vec&amp;lt;ComponentArrays&amp;gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;table_lookup&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;: HashMap&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u64&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;usize&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;&amp;gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;table_edges&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;: Vec&amp;lt;TableEdges&amp;gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The edges need to be populated. There are two ways, lazily on first traversal or eagerly when a new table is created. Eager is simpler because the edge information stays correct without ever needing to invalidate. The cost is a small scan over existing tables when a new table appears.&lt;/p&gt;
&lt;div class=&quot;bamboo-code-block&quot; data-bamboo-code data-bamboo-lang=&quot;rust&quot;&gt;&lt;div class=&quot;bamboo-code-toolbar&quot;&gt;&lt;button type=&quot;button&quot; class=&quot;bamboo-code-button&quot; data-bamboo-line-toggle aria-label=&quot;Toggle line numbers&quot; aria-pressed=&quot;false&quot; title=&quot;Toggle line numbers&quot;&gt;&lt;svg class=&quot;bamboo-code-icon&quot; viewBox=&quot;0 0 20 20&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;1.6&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M4 5h2M4 10h2M4 15h2&quot; stroke-linecap=&quot;round&quot;/&gt;&lt;path d=&quot;M9 5h7M9 10h7M9 15h7&quot; stroke-linecap=&quot;round&quot;/&gt;&lt;/svg&gt;&lt;/button&gt;&lt;button type=&quot;button&quot; class=&quot;bamboo-code-button&quot; data-bamboo-copy aria-label=&quot;Copy code&quot; title=&quot;Copy code&quot;&gt;&lt;svg class=&quot;bamboo-code-icon bamboo-code-icon-copy&quot; viewBox=&quot;0 0 20 20&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;1.6&quot; aria-hidden=&quot;true&quot;&gt;&lt;rect x=&quot;7&quot; y=&quot;3&quot; width=&quot;10&quot; height=&quot;12&quot; rx=&quot;2&quot;/&gt;&lt;path d=&quot;M5 7v8a2 2 0 0 0 2 2h6&quot;/&gt;&lt;/svg&gt;&lt;svg class=&quot;bamboo-code-icon bamboo-code-icon-check&quot; viewBox=&quot;0 0 20 20&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;2&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M4 10l4 4 8-8&quot; stroke-linecap=&quot;round&quot; stroke-linejoin=&quot;round&quot;/&gt;&lt;/svg&gt;&lt;/button&gt;&lt;/div&gt;&lt;pre style=&quot;background-color:#2b303b;color:#c0c5ce;&quot;&gt;&lt;code class=&quot;language-rust&quot;&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl &lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;World {
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub fn &lt;/span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;get_or_create_table&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(&amp;amp;&lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;mask&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u64&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;) -&amp;gt; &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;usize &lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;if let &lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;Some(&amp;amp;index) = &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;.table_lookup.&lt;/span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;get&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(&amp;amp;mask) {
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;            &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;return&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt; index;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt; new_table_index = &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;.tables.&lt;/span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;len&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;();
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;.tables.&lt;/span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;push&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(ComponentArrays {
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;            mask,
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;            ..Default::default()
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        });
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;.table_edges.&lt;/span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;push&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(TableEdges::default());
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;.table_lookup.&lt;/span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;insert&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(mask, new_table_index);
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;for&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt; component_bit in [&lt;/span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;POSITION&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;VELOCITY&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;] {
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;            &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let &lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;Some(component_index_value) = &lt;/span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;component_index&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(component_bit) &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;else &lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;                &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;continue&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;            };
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;            &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;for &lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(existing_index, existing) in &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;.tables.&lt;/span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;iter&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;().&lt;/span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;enumerate&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;                &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;if&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt; existing.mask | component_bit == mask {
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;                    &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;.table_edges[existing_index].add_edges[component_index_value] =
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;                        Some(new_table_index);
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;                }
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;                &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;if&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt; existing.mask &amp;amp; !component_bit == mask {
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;                    &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;.table_edges[existing_index].remove_edges[component_index_value] =
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;                        Some(new_table_index);
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;                }
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;            }
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;for&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt; component_bit in [&lt;/span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;POSITION&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;VELOCITY&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;] {
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;            &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let &lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;Some(component_index_value) = &lt;/span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;component_index&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(component_bit) &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;else &lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;                &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;continue&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;            };
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;            &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;if let &lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;Some(&amp;amp;dest) = &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;.table_lookup.&lt;/span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;get&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(&amp;amp;(mask | component_bit)) {
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;                &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;.table_edges[new_table_index].add_edges[component_index_value] = Some(dest);
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;            }
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;            &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;if&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt; mask &amp;amp; component_bit != &lt;/span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;                &amp;amp;&amp;amp; &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let &lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;Some(&amp;amp;dest) = &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;.table_lookup.&lt;/span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;get&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(&amp;amp;(mask &amp;amp; !component_bit))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;            {
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;                &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;.table_edges[new_table_index].remove_edges[component_index_value] = Some(dest);
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;            }
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        new_table_index
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Two loops. The first walks the existing tables and sets edges &lt;em&gt;into&lt;/em&gt; the new table from any older table that is one bit-flip away. The second walks the component bits and sets edges &lt;em&gt;out of&lt;/em&gt; the new table to any older table that is one bit-flip away in the other direction. For each component bit, the add-side destination is &lt;code&gt;mask | bit&lt;/code&gt; and the remove-side destination is &lt;code&gt;mask &amp;amp; !bit&lt;/code&gt; (only meaningful when the bit was set in &lt;code&gt;mask&lt;/code&gt;). The lookups are hashmap gets, but they happen once per bit at table-creation time rather than every time an entity migrates.&lt;/p&gt;
&lt;p&gt;The second loop exists because the first one is one-directional. A future table creation will wire its own incoming edges from the older tables that were around when it appeared, but it will not reach back and fill outgoing edges on those older tables. So the new table&apos;s outgoing edges have one opportunity to be set, and that opportunity is now. Filling them on creation makes every cached migration path hot from the moment both endpoints exist.&lt;/p&gt;
&lt;p&gt;Now &lt;code&gt;add_components&lt;/code&gt; for a single-bit mask hits the edge cache.&lt;/p&gt;
&lt;div class=&quot;bamboo-code-block&quot; data-bamboo-code data-bamboo-lang=&quot;rust&quot;&gt;&lt;div class=&quot;bamboo-code-toolbar&quot;&gt;&lt;button type=&quot;button&quot; class=&quot;bamboo-code-button&quot; data-bamboo-line-toggle aria-label=&quot;Toggle line numbers&quot; aria-pressed=&quot;false&quot; title=&quot;Toggle line numbers&quot;&gt;&lt;svg class=&quot;bamboo-code-icon&quot; viewBox=&quot;0 0 20 20&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;1.6&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M4 5h2M4 10h2M4 15h2&quot; stroke-linecap=&quot;round&quot;/&gt;&lt;path d=&quot;M9 5h7M9 10h7M9 15h7&quot; stroke-linecap=&quot;round&quot;/&gt;&lt;/svg&gt;&lt;/button&gt;&lt;button type=&quot;button&quot; class=&quot;bamboo-code-button&quot; data-bamboo-copy aria-label=&quot;Copy code&quot; title=&quot;Copy code&quot;&gt;&lt;svg class=&quot;bamboo-code-icon bamboo-code-icon-copy&quot; viewBox=&quot;0 0 20 20&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;1.6&quot; aria-hidden=&quot;true&quot;&gt;&lt;rect x=&quot;7&quot; y=&quot;3&quot; width=&quot;10&quot; height=&quot;12&quot; rx=&quot;2&quot;/&gt;&lt;path d=&quot;M5 7v8a2 2 0 0 0 2 2h6&quot;/&gt;&lt;/svg&gt;&lt;svg class=&quot;bamboo-code-icon bamboo-code-icon-check&quot; viewBox=&quot;0 0 20 20&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;2&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M4 10l4 4 8-8&quot; stroke-linecap=&quot;round&quot; stroke-linejoin=&quot;round&quot;/&gt;&lt;/svg&gt;&lt;/button&gt;&lt;/div&gt;&lt;pre style=&quot;background-color:#2b303b;color:#c0c5ce;&quot;&gt;&lt;code class=&quot;language-rust&quot;&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl &lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;World {
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub fn &lt;/span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;add_components&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(&amp;amp;&lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;entity&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;: Entity, &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;mask&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u64&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;) -&amp;gt; &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;bool &lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let &lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;Some((table_index, array_index)) = &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;.entity_locations.&lt;/span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;get&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(entity) &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;else &lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;            &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;return &lt;/span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;false&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        };
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt; current_mask = &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;.tables[table_index].mask;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;if&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt; current_mask &amp;amp; mask == mask {
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;            &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;return &lt;/span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;true&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt; cached = &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;if&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt; mask.&lt;/span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;count_ones&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;() == &lt;/span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1 &lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;            &lt;/span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;component_index&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(mask).&lt;/span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;and_then&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(|&lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;index&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;| &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;.table_edges[table_index].add_edges[index])
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        } &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;else &lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;            None
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        };
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt; new_table_index = &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;match&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt; cached {
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;            Some(index) =&amp;gt; index,
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;            None =&amp;gt; &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;get_or_create_table&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(current_mask | mask),
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        };
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;move_entity&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(entity, table_index, array_index, new_table_index);
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;true
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub fn &lt;/span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;remove_components&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(&amp;amp;&lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;entity&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;: Entity, &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;mask&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u64&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;) -&amp;gt; &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;bool &lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let &lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;Some((table_index, array_index)) = &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;.entity_locations.&lt;/span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;get&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(entity) &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;else &lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;            &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;return &lt;/span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;false&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        };
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt; current_mask = &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;.tables[table_index].mask;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;if&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt; current_mask &amp;amp; mask == &lt;/span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0 &lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;            &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;return &lt;/span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;true&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt; cached = &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;if&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt; mask.&lt;/span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;count_ones&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;() == &lt;/span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1 &lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;            &lt;/span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;component_index&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(mask)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;                .&lt;/span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;and_then&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(|&lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;index&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;| &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;.table_edges[table_index].remove_edges[index])
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        } &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;else &lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;            None
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        };
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt; new_table_index = &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;match&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt; cached {
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;            Some(index) =&amp;gt; index,
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;            None =&amp;gt; &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;get_or_create_table&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(current_mask &amp;amp; !mask),
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        };
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;move_entity&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(entity, table_index, array_index, new_table_index);
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;true
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;For a single-component add or remove, the cached array lookup replaces the hashmap lookup. Multi-component changes still hit &lt;code&gt;get_or_create_table&lt;/code&gt;, which is fine because they are rare and the hashmap is the only sensible structure for arbitrary masks. A real implementation would add a secondary cache per source table for common multi-bit transitions. The single-bit case is what fires every time a status effect is added or removed, so it earns the optimization.&lt;/p&gt;
&lt;h2 id=&quot;making-the-query-fast&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#making-the-query-fast&quot;&gt;#&lt;/a&gt;Making the query fast&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;for_each_mut(POSITION | VELOCITY, 0, ...)&lt;/code&gt; scans every table to find the ones whose mask matches. With a few dozen archetypes and a few hundred query invocations per frame, that scan adds up.&lt;/p&gt;
&lt;p&gt;The fix is the same idea as the edge cache. Memoize. Map each query mask to the list of table indices that satisfy it.&lt;/p&gt;
&lt;div class=&quot;bamboo-code-block&quot; data-bamboo-code data-bamboo-lang=&quot;rust&quot;&gt;&lt;div class=&quot;bamboo-code-toolbar&quot;&gt;&lt;button type=&quot;button&quot; class=&quot;bamboo-code-button&quot; data-bamboo-line-toggle aria-label=&quot;Toggle line numbers&quot; aria-pressed=&quot;false&quot; title=&quot;Toggle line numbers&quot;&gt;&lt;svg class=&quot;bamboo-code-icon&quot; viewBox=&quot;0 0 20 20&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;1.6&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M4 5h2M4 10h2M4 15h2&quot; stroke-linecap=&quot;round&quot;/&gt;&lt;path d=&quot;M9 5h7M9 10h7M9 15h7&quot; stroke-linecap=&quot;round&quot;/&gt;&lt;/svg&gt;&lt;/button&gt;&lt;button type=&quot;button&quot; class=&quot;bamboo-code-button&quot; data-bamboo-copy aria-label=&quot;Copy code&quot; title=&quot;Copy code&quot;&gt;&lt;svg class=&quot;bamboo-code-icon bamboo-code-icon-copy&quot; viewBox=&quot;0 0 20 20&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;1.6&quot; aria-hidden=&quot;true&quot;&gt;&lt;rect x=&quot;7&quot; y=&quot;3&quot; width=&quot;10&quot; height=&quot;12&quot; rx=&quot;2&quot;/&gt;&lt;path d=&quot;M5 7v8a2 2 0 0 0 2 2h6&quot;/&gt;&lt;/svg&gt;&lt;svg class=&quot;bamboo-code-icon bamboo-code-icon-check&quot; viewBox=&quot;0 0 20 20&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;2&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M4 10l4 4 8-8&quot; stroke-linecap=&quot;round&quot; stroke-linejoin=&quot;round&quot;/&gt;&lt;/svg&gt;&lt;/button&gt;&lt;/div&gt;&lt;pre style=&quot;background-color:#2b303b;color:#c0c5ce;&quot;&gt;&lt;code class=&quot;language-rust&quot;&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;#[&lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;derive&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(Default)]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub struct &lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;World {
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;allocator&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;: EntityAllocator,
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;entity_locations&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;: EntityLocations,
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;tables&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;: Vec&amp;lt;ComponentArrays&amp;gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;table_lookup&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;: HashMap&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u64&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;usize&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;&amp;gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;table_edges&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;: Vec&amp;lt;TableEdges&amp;gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;query_cache&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;: HashMap&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u64&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;, Vec&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;usize&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;&amp;gt;&amp;gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The cache fills on first use.&lt;/p&gt;
&lt;div class=&quot;bamboo-code-block&quot; data-bamboo-code data-bamboo-lang=&quot;rust&quot;&gt;&lt;div class=&quot;bamboo-code-toolbar&quot;&gt;&lt;button type=&quot;button&quot; class=&quot;bamboo-code-button&quot; data-bamboo-line-toggle aria-label=&quot;Toggle line numbers&quot; aria-pressed=&quot;false&quot; title=&quot;Toggle line numbers&quot;&gt;&lt;svg class=&quot;bamboo-code-icon&quot; viewBox=&quot;0 0 20 20&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;1.6&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M4 5h2M4 10h2M4 15h2&quot; stroke-linecap=&quot;round&quot;/&gt;&lt;path d=&quot;M9 5h7M9 10h7M9 15h7&quot; stroke-linecap=&quot;round&quot;/&gt;&lt;/svg&gt;&lt;/button&gt;&lt;button type=&quot;button&quot; class=&quot;bamboo-code-button&quot; data-bamboo-copy aria-label=&quot;Copy code&quot; title=&quot;Copy code&quot;&gt;&lt;svg class=&quot;bamboo-code-icon bamboo-code-icon-copy&quot; viewBox=&quot;0 0 20 20&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;1.6&quot; aria-hidden=&quot;true&quot;&gt;&lt;rect x=&quot;7&quot; y=&quot;3&quot; width=&quot;10&quot; height=&quot;12&quot; rx=&quot;2&quot;/&gt;&lt;path d=&quot;M5 7v8a2 2 0 0 0 2 2h6&quot;/&gt;&lt;/svg&gt;&lt;svg class=&quot;bamboo-code-icon bamboo-code-icon-check&quot; viewBox=&quot;0 0 20 20&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;2&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M4 10l4 4 8-8&quot; stroke-linecap=&quot;round&quot; stroke-linejoin=&quot;round&quot;/&gt;&lt;/svg&gt;&lt;/button&gt;&lt;/div&gt;&lt;pre style=&quot;background-color:#2b303b;color:#c0c5ce;&quot;&gt;&lt;code class=&quot;language-rust&quot;&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl &lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;World {
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub fn &lt;/span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;cached_tables&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(&amp;amp;&lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;mask&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u64&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;) -&amp;gt; &amp;amp;[&lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;usize&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;] {
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;if &lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;!&lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;.query_cache.&lt;/span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;contains_key&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(&amp;amp;mask) {
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;            &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt; matching: Vec&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;usize&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;&amp;gt; = &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;                .tables
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;                .&lt;/span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;iter&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;()
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;                .&lt;/span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;enumerate&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;()
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;                .&lt;/span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;filter&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(|(_, &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;table&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;)| table.mask &amp;amp; mask == mask)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;                .&lt;/span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;map&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(|(&lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;index&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;, _)| index)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;                .&lt;/span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;collect&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;();
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;            &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;.query_cache.&lt;/span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;insert&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(mask, matching);
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        &amp;amp;&lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;.query_cache[&amp;amp;mask]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;It needs to stay correct as new tables are created. The simplest invalidation strategy would be to clear the whole cache on every new table, but that is overly conservative. Most existing cache entries are still correct, and only those whose query mask is a subset of the new table&apos;s mask need updating. We can do that surgically inside &lt;code&gt;get_or_create_table&lt;/code&gt;.&lt;/p&gt;
&lt;div class=&quot;bamboo-code-block&quot; data-bamboo-code data-bamboo-lang=&quot;rust&quot;&gt;&lt;div class=&quot;bamboo-code-toolbar&quot;&gt;&lt;button type=&quot;button&quot; class=&quot;bamboo-code-button&quot; data-bamboo-line-toggle aria-label=&quot;Toggle line numbers&quot; aria-pressed=&quot;false&quot; title=&quot;Toggle line numbers&quot;&gt;&lt;svg class=&quot;bamboo-code-icon&quot; viewBox=&quot;0 0 20 20&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;1.6&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M4 5h2M4 10h2M4 15h2&quot; stroke-linecap=&quot;round&quot;/&gt;&lt;path d=&quot;M9 5h7M9 10h7M9 15h7&quot; stroke-linecap=&quot;round&quot;/&gt;&lt;/svg&gt;&lt;/button&gt;&lt;button type=&quot;button&quot; class=&quot;bamboo-code-button&quot; data-bamboo-copy aria-label=&quot;Copy code&quot; title=&quot;Copy code&quot;&gt;&lt;svg class=&quot;bamboo-code-icon bamboo-code-icon-copy&quot; viewBox=&quot;0 0 20 20&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;1.6&quot; aria-hidden=&quot;true&quot;&gt;&lt;rect x=&quot;7&quot; y=&quot;3&quot; width=&quot;10&quot; height=&quot;12&quot; rx=&quot;2&quot;/&gt;&lt;path d=&quot;M5 7v8a2 2 0 0 0 2 2h6&quot;/&gt;&lt;/svg&gt;&lt;svg class=&quot;bamboo-code-icon bamboo-code-icon-check&quot; viewBox=&quot;0 0 20 20&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;2&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M4 10l4 4 8-8&quot; stroke-linecap=&quot;round&quot; stroke-linejoin=&quot;round&quot;/&gt;&lt;/svg&gt;&lt;/button&gt;&lt;/div&gt;&lt;pre style=&quot;background-color:#2b303b;color:#c0c5ce;&quot;&gt;&lt;code class=&quot;language-rust&quot;&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl &lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;World {
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub fn &lt;/span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;invalidate_query_cache_for_new_table&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        &amp;amp;&lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;new_mask&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u64&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;new_table_index&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;usize&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    ) {
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;for &lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(query_mask, cached_tables) in &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;.query_cache.&lt;/span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;iter_mut&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;            &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;if&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt; new_mask &amp;amp; query_mask == *query_mask {
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;                cached_tables.&lt;/span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;push&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(new_table_index);
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;            }
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Called from &lt;code&gt;get_or_create_table&lt;/code&gt; right after the table is pushed.&lt;/p&gt;
&lt;div class=&quot;bamboo-code-block&quot; data-bamboo-code data-bamboo-lang=&quot;rust&quot;&gt;&lt;div class=&quot;bamboo-code-toolbar&quot;&gt;&lt;button type=&quot;button&quot; class=&quot;bamboo-code-button&quot; data-bamboo-line-toggle aria-label=&quot;Toggle line numbers&quot; aria-pressed=&quot;false&quot; title=&quot;Toggle line numbers&quot;&gt;&lt;svg class=&quot;bamboo-code-icon&quot; viewBox=&quot;0 0 20 20&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;1.6&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M4 5h2M4 10h2M4 15h2&quot; stroke-linecap=&quot;round&quot;/&gt;&lt;path d=&quot;M9 5h7M9 10h7M9 15h7&quot; stroke-linecap=&quot;round&quot;/&gt;&lt;/svg&gt;&lt;/button&gt;&lt;button type=&quot;button&quot; class=&quot;bamboo-code-button&quot; data-bamboo-copy aria-label=&quot;Copy code&quot; title=&quot;Copy code&quot;&gt;&lt;svg class=&quot;bamboo-code-icon bamboo-code-icon-copy&quot; viewBox=&quot;0 0 20 20&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;1.6&quot; aria-hidden=&quot;true&quot;&gt;&lt;rect x=&quot;7&quot; y=&quot;3&quot; width=&quot;10&quot; height=&quot;12&quot; rx=&quot;2&quot;/&gt;&lt;path d=&quot;M5 7v8a2 2 0 0 0 2 2h6&quot;/&gt;&lt;/svg&gt;&lt;svg class=&quot;bamboo-code-icon bamboo-code-icon-check&quot; viewBox=&quot;0 0 20 20&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;2&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M4 10l4 4 8-8&quot; stroke-linecap=&quot;round&quot; stroke-linejoin=&quot;round&quot;/&gt;&lt;/svg&gt;&lt;/button&gt;&lt;/div&gt;&lt;pre style=&quot;background-color:#2b303b;color:#c0c5ce;&quot;&gt;&lt;code class=&quot;language-rust&quot;&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl &lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;World {
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub fn &lt;/span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;get_or_create_table&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(&amp;amp;&lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;mask&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u64&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;) -&amp;gt; &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;usize &lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;if let &lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;Some(&amp;amp;index) = &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;.table_lookup.&lt;/span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;get&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(&amp;amp;mask) {
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;            &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;return&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt; index;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt; new_table_index = &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;.tables.&lt;/span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;len&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;();
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;.tables.&lt;/span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;push&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(ComponentArrays {
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;            mask,
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;            ..Default::default()
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        });
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;.table_edges.&lt;/span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;push&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(TableEdges::default());
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;.table_lookup.&lt;/span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;insert&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(mask, new_table_index);
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;invalidate_query_cache_for_new_table&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(mask, new_table_index);
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;for&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt; component_bit in [&lt;/span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;POSITION&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;VELOCITY&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;] {
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;            &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let &lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;Some(component_index_value) = &lt;/span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;component_index&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(component_bit) &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;else &lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;                &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;continue&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;            };
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;            &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;for &lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(existing_index, existing) in &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;.tables.&lt;/span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;iter&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;().&lt;/span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;enumerate&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;                &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;if&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt; existing.mask | component_bit == mask {
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;                    &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;.table_edges[existing_index].add_edges[component_index_value] =
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;                        Some(new_table_index);
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;                }
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;                &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;if&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt; existing.mask &amp;amp; !component_bit == mask {
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;                    &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;.table_edges[existing_index].remove_edges[component_index_value] =
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;                        Some(new_table_index);
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;                }
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;            }
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;for&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt; component_bit in [&lt;/span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;POSITION&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;VELOCITY&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;] {
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;            &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let &lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;Some(component_index_value) = &lt;/span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;component_index&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(component_bit) &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;else &lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;                &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;continue&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;            };
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;            &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;if let &lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;Some(&amp;amp;dest) = &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;.table_lookup.&lt;/span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;get&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(&amp;amp;(mask | component_bit)) {
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;                &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;.table_edges[new_table_index].add_edges[component_index_value] = Some(dest);
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;            }
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;            &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;if&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt; mask &amp;amp; component_bit != &lt;/span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;                &amp;amp;&amp;amp; &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let &lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;Some(&amp;amp;dest) = &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;.table_lookup.&lt;/span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;get&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(&amp;amp;(mask &amp;amp; !component_bit))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;            {
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;                &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;.table_edges[new_table_index].remove_edges[component_index_value] = Some(dest);
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;            }
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        new_table_index
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;for_each_mut&lt;/code&gt; consults the cache instead of scanning.&lt;/p&gt;
&lt;div class=&quot;bamboo-code-block&quot; data-bamboo-code data-bamboo-lang=&quot;rust&quot;&gt;&lt;div class=&quot;bamboo-code-toolbar&quot;&gt;&lt;button type=&quot;button&quot; class=&quot;bamboo-code-button&quot; data-bamboo-line-toggle aria-label=&quot;Toggle line numbers&quot; aria-pressed=&quot;false&quot; title=&quot;Toggle line numbers&quot;&gt;&lt;svg class=&quot;bamboo-code-icon&quot; viewBox=&quot;0 0 20 20&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;1.6&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M4 5h2M4 10h2M4 15h2&quot; stroke-linecap=&quot;round&quot;/&gt;&lt;path d=&quot;M9 5h7M9 10h7M9 15h7&quot; stroke-linecap=&quot;round&quot;/&gt;&lt;/svg&gt;&lt;/button&gt;&lt;button type=&quot;button&quot; class=&quot;bamboo-code-button&quot; data-bamboo-copy aria-label=&quot;Copy code&quot; title=&quot;Copy code&quot;&gt;&lt;svg class=&quot;bamboo-code-icon bamboo-code-icon-copy&quot; viewBox=&quot;0 0 20 20&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;1.6&quot; aria-hidden=&quot;true&quot;&gt;&lt;rect x=&quot;7&quot; y=&quot;3&quot; width=&quot;10&quot; height=&quot;12&quot; rx=&quot;2&quot;/&gt;&lt;path d=&quot;M5 7v8a2 2 0 0 0 2 2h6&quot;/&gt;&lt;/svg&gt;&lt;svg class=&quot;bamboo-code-icon bamboo-code-icon-check&quot; viewBox=&quot;0 0 20 20&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;2&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M4 10l4 4 8-8&quot; stroke-linecap=&quot;round&quot; stroke-linejoin=&quot;round&quot;/&gt;&lt;/svg&gt;&lt;/button&gt;&lt;/div&gt;&lt;pre style=&quot;background-color:#2b303b;color:#c0c5ce;&quot;&gt;&lt;code class=&quot;language-rust&quot;&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl &lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;World {
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub fn &lt;/span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;for_each_mut&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;&amp;lt;F&amp;gt;(&amp;amp;&lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;include&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u64&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;exclude&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u64&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;f&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;: F)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;where
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        F: FnMut(Entity, &amp;amp;&lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt; ComponentArrays, &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;usize&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;),
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    {
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt; table_indices: Vec&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;usize&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;&amp;gt; = &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;cached_tables&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(include).&lt;/span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;to_vec&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;();
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;for&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt; table_index in table_indices {
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;            &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt; table = &amp;amp;&lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;.tables[table_index];
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;            &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;if&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt; table.mask &amp;amp; exclude != &lt;/span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0 &lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;                &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;continue&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;            }
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;            &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;for&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt; array_index in &lt;/span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;..table.entities.&lt;/span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;len&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;                &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt; entity = table.entities[array_index];
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;                &lt;/span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;f&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(entity, table, array_index);
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;            }
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The &lt;code&gt;.to_vec()&lt;/code&gt; copy is needed because &lt;code&gt;cached_tables&lt;/code&gt; borrows the cache mutably (to fill it on miss) and then we want to borrow &lt;code&gt;self.tables&lt;/code&gt; mutably to call &lt;code&gt;f&lt;/code&gt;. A handful of &lt;code&gt;usize&lt;/code&gt; copied to the stack is cheap.&lt;/p&gt;
&lt;p&gt;The read-only &lt;code&gt;for_each&lt;/code&gt; does not have the borrow problem, but it also cannot fill the cache, because the cache write requires &lt;code&gt;&amp;amp;mut self&lt;/code&gt;. A fuller implementation would either expose a &lt;code&gt;warm_query(mask)&lt;/code&gt; method that fills the cache eagerly during setup, or use a &lt;code&gt;RefCell&lt;/code&gt; inside the cache so the read-only path can still write. The warm-up route is what production crates usually take because it avoids interior mutability on the hot read path. For this post the read-only path scans the tables every time.&lt;/p&gt;
&lt;h2 id=&quot;what-we-built&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#what-we-built&quot;&gt;#&lt;/a&gt;What we built&lt;/h2&gt;
&lt;div class=&quot;bamboo-code-block&quot; data-bamboo-code&gt;&lt;div class=&quot;bamboo-code-toolbar&quot;&gt;&lt;button type=&quot;button&quot; class=&quot;bamboo-code-button&quot; data-bamboo-line-toggle aria-label=&quot;Toggle line numbers&quot; aria-pressed=&quot;false&quot; title=&quot;Toggle line numbers&quot;&gt;&lt;svg class=&quot;bamboo-code-icon&quot; viewBox=&quot;0 0 20 20&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;1.6&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M4 5h2M4 10h2M4 15h2&quot; stroke-linecap=&quot;round&quot;/&gt;&lt;path d=&quot;M9 5h7M9 10h7M9 15h7&quot; stroke-linecap=&quot;round&quot;/&gt;&lt;/svg&gt;&lt;/button&gt;&lt;button type=&quot;button&quot; class=&quot;bamboo-code-button&quot; data-bamboo-copy aria-label=&quot;Copy code&quot; title=&quot;Copy code&quot;&gt;&lt;svg class=&quot;bamboo-code-icon bamboo-code-icon-copy&quot; viewBox=&quot;0 0 20 20&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;1.6&quot; aria-hidden=&quot;true&quot;&gt;&lt;rect x=&quot;7&quot; y=&quot;3&quot; width=&quot;10&quot; height=&quot;12&quot; rx=&quot;2&quot;/&gt;&lt;path d=&quot;M5 7v8a2 2 0 0 0 2 2h6&quot;/&gt;&lt;/svg&gt;&lt;svg class=&quot;bamboo-code-icon bamboo-code-icon-check&quot; viewBox=&quot;0 0 20 20&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;2&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M4 10l4 4 8-8&quot; stroke-linecap=&quot;round&quot; stroke-linejoin=&quot;round&quot;/&gt;&lt;/svg&gt;&lt;/button&gt;&lt;/div&gt;&lt;pre style=&quot;background-color:#2b303b;color:#c0c5ce;&quot;&gt;&lt;code&gt;&lt;span class=&quot;bamboo-line&quot;&gt;World  (new fields)
&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;├── table_edges: Vec&amp;lt;TableEdges&amp;gt;           archetype graph for O(1) migration
&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;└── query_cache: HashMap&amp;lt;u64, Vec&amp;lt;usize&amp;gt;&amp;gt;  memoized &amp;quot;which tables match this mask&amp;quot;
&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;TableEdges  (one per table, indexed by component bit position)
&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;├── add_edges: [Option&amp;lt;usize&amp;gt;; N]          which table to land in when adding bit N
&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;└── remove_edges: [Option&amp;lt;usize&amp;gt;; N]       which table to land in when removing bit N
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;New operations on &lt;code&gt;World&lt;/code&gt;. &lt;code&gt;add_components(entity, mask)&lt;/code&gt;, &lt;code&gt;remove_components(entity, mask)&lt;/code&gt;, &lt;code&gt;set_position&lt;/code&gt;/&lt;code&gt;set_velocity&lt;/code&gt; (write or add-then-write), &lt;code&gt;query_entities(mask)&lt;/code&gt;, &lt;code&gt;for_each(include, exclude, ...)&lt;/code&gt;, &lt;code&gt;for_each_mut(include, exclude, ...)&lt;/code&gt;. Migrations and queries both hit the caches on the common path and fall back to the hashmap on misses.&lt;/p&gt;
&lt;h2 id=&quot;what-is-missing&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#what-is-missing&quot;&gt;#&lt;/a&gt;What is missing&lt;/h2&gt;
&lt;p&gt;You can build a small game with what we have so far. The core loop is here. Spawn, attach components, run systems over component combinations, change components in response to events, despawn. But there are real limitations.&lt;/p&gt;
&lt;p&gt;There is no way for a system to know which entities changed. The render system has to walk every entity with a transform every frame, even if nothing moved. The networking system has to serialize every component, not just the dirty ones. Change detection (recording when each component was last modified, and offering an &quot;only iterate the recently-changed ones&quot; query) is the single biggest performance win for systems that do incremental work.&lt;/p&gt;
&lt;p&gt;There is no event system. Collision detection wants to &lt;em&gt;emit&lt;/em&gt; &quot;A hit B&quot; and have damage application &lt;em&gt;consume&lt;/em&gt; that message later in the frame. Today the only way to do this is to scribble it into a component, which is fine for one-off cases and a mess in aggregate.&lt;/p&gt;
&lt;p&gt;There is no notion of a tag. A lightweight marker like &quot;this entity is a player&quot; or &quot;this entity is selected.&quot; We could add a unit component &lt;code&gt;Player;&lt;/code&gt; and put it in the archetype mask, but then adding the player tag to an entity migrates it to a new archetype, and removing it migrates it back. For markers that change frequently (think &quot;selected&quot; in an RTS), the migration cost is wasted. The standard solution is to store tags outside the archetype storage, in a side structure.&lt;/p&gt;
&lt;p&gt;There is no way to safely make structural changes during iteration. A system iterating over enemies cannot despawn them mid-loop without invalidating the iteration. The standard solution is a command buffer. Queue the changes, apply them at the end.&lt;/p&gt;
&lt;p&gt;Part 3 adds all four (change detection, events, sparse-set tags, and command buffers) and finishes with a small system schedule that ties everything together into a frame loop.&lt;/p&gt;
&lt;h2 id=&quot;the-full-file&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#the-full-file&quot;&gt;#&lt;/a&gt;The full file&lt;/h2&gt;
&lt;p&gt;Same shape as the part 1 checkpoint, dropping into &lt;code&gt;src/main.rs&lt;/code&gt; of a fresh project. Available as a &lt;a href=&quot;https://gist.github.com/matthewjberger/20fdef019ff97edc5ae60a961fcde6ab&quot;&gt;gist&lt;/a&gt;. &lt;code&gt;cargo run&lt;/code&gt; should show the mover advancing while the landmark stays put, then both entities listed by the final &lt;code&gt;query_entities&lt;/code&gt; loop. The mover went through three archetypes during execution. &lt;code&gt;POSITION&lt;/code&gt; at spawn, &lt;code&gt;POSITION | VELOCITY&lt;/code&gt; after the add, and back to &lt;code&gt;POSITION&lt;/code&gt; after the remove. It kept its data the whole way.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Build your own ECS (part 1), archetype storage</title>
    <link href="https://matthewberger.dev/articles/posts/build-your-own-ecs-archetype-storage/" rel="alternate"/>
    <id>https://matthewberger.dev/articles/posts/build-your-own-ecs-archetype-storage/</id>
    <updated>2026-07-26T00:00:00+00:00</updated>
    <summary type="text">An ECS, built from nothing, in three posts. Part 1 lays down the storage. Generational entity handles and archetype tables in struct-of-arrays layout.</summary>
    <content type="html">&lt;p&gt;&lt;em&gt;This is part 1 of 3 of a series.&lt;/em&gt; Next → &lt;a href=&quot;@/posts/2026-08-02-build-your-own-ecs-structural-change.md&quot;&gt;Structural change and queries&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;ECS stands for Entity Component System. An entity is a handle, a small id with no data and no methods. A component is a struct of data attached to an entity, like &lt;code&gt;Position&lt;/code&gt; or &lt;code&gt;Velocity&lt;/code&gt;. A system is a function that reads or writes components on the entities that match a query, like &quot;every entity with both Position and Velocity.&quot; The data lives in components, the work happens in systems, and entities are the keys that line them up.&lt;/p&gt;
&lt;p&gt;The fast layout for an ECS groups entities by which components they have and lays out each component type as its own contiguous &lt;code&gt;Vec&lt;/code&gt;. A query for &quot;every entity with position and velocity&quot; turns into a tight loop over packed memory rather than a HashMap walk. Mutating a component is a write into a known slot, not a heap indirection. Adding a component is a one-time migration to a different bucket. This is the shape almost every fast Rust ECS uses under the hood, and the next three posts build it from scratch.&lt;/p&gt;
&lt;p&gt;End state at part 3 is around 800 lines of straightforward Rust with structural change at runtime, queries, change detection, events, sparse-set tags, deferred command buffers, and a small system schedule. No proc-macros, no &lt;code&gt;unsafe&lt;/code&gt;, only the standard library.&lt;/p&gt;
&lt;p&gt;Aimed at Rust developers who want to understand how an archetype ECS is shaped, well enough to write one or to read a production crate without guessing. If you want a finished version to drop in rather than build, &lt;a href=&quot;https://github.com/matthewjberger/freecs&quot;&gt;freecs&lt;/a&gt; is on crates.io and saves you the work.&lt;/p&gt;
&lt;p&gt;Part one covers spawn, despawn, and reading and writing components inside a fixed archetype. Runtime structural change is part two. Events, change detection, tags, and command buffers are part three. The complete file (just under 250 lines) sits at the end of this post.&lt;/p&gt;
&lt;p&gt;What gets built over the series is the kernel of &lt;a href=&quot;https://github.com/matthewjberger/freecs&quot;&gt;freecs&lt;/a&gt;, my Rust ECS crate. freecs wraps the same data layout in a declarative macro that writes the typed component accessors for you, and it is the foundation of &lt;a href=&quot;https://github.com/matthewjberger/nightshade&quot;&gt;nightshade&lt;/a&gt;, my game engine.&lt;/p&gt;
&lt;h2 id=&quot;why-this-layout&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#why-this-layout&quot;&gt;#&lt;/a&gt;Why this layout&lt;/h2&gt;
&lt;p&gt;The choice that makes the design fast is data-oriented. Object-oriented programming groups data by what kind of thing is being modeled, with the fields of a game object packed inside an instance of its class. Data-oriented design groups data by how the data gets accessed, with all the positions stored together because the physics loop iterates over positions, all the velocities stored together because it iterates them alongside. Systems become functions over arrays of data instead of methods on objects. The storage is laid out for the access pattern, not for the conceptual identity of a thing.&lt;/p&gt;
&lt;p&gt;For ten thousand entities and a physics step that reads position and velocity from each, the difference is concrete. An OOP layout pays a cache miss per access, because each object&apos;s fields live wherever the allocator put them. The DOD layout pays one cache miss per cache line of contiguous data, which holds several positions at a time. The savings compound across every iteration of every system that runs each frame.&lt;/p&gt;
&lt;p&gt;Inheritance also fails the modeling side. Real game objects are combinations of orthogonal capabilities. A destructible barrel, a chest that holds items and can be locked, a vendor that takes damage and runs an AI routine. Forcing a tree shape on that means committing to one combination and breaking the next. Composition over &lt;code&gt;Vec&amp;lt;Box&amp;lt;dyn Component&amp;gt;&amp;gt;&lt;/code&gt; per entity expresses the combinations correctly but routes every access through a v-table dispatch and a heap indirection, so it solves the modeling problem by reintroducing the cache problem.&lt;/p&gt;
&lt;p&gt;What works is to flip the storage. Group entities by which components they have, lay out each component type as its own dense &lt;code&gt;Vec&lt;/code&gt;, and the question becomes &quot;which buckets satisfy this query&quot; plus &quot;walk those buckets.&quot; Iteration is sequential reads through packed memory, which matches what the hardware prefetcher is optimized for. Adding a component triggers a one-time migration to a different bucket rather than paying a per-access cost forever.&lt;/p&gt;
&lt;p&gt;The rest of part one is how to build that shape in Rust.&lt;/p&gt;
&lt;h2 id=&quot;a-note-on-style-before-the-code-starts&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#a-note-on-style-before-the-code-starts&quot;&gt;#&lt;/a&gt;A note on style before the code starts&lt;/h2&gt;
&lt;p&gt;Everything in this series uses plain structs with public fields. The &lt;code&gt;World&lt;/code&gt; type has methods, but the fields underneath are &lt;code&gt;pub&lt;/code&gt;, and the methods are not protecting any invariants. They are there because writing &lt;code&gt;world.spawn(mask)&lt;/code&gt; is nicer than writing &lt;code&gt;spawn(&amp;amp;mut world, mask)&lt;/code&gt;. If the methods were not there, free functions would do the same job. Nothing is encapsulated for OOP reasons.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;&amp;amp;mut self&lt;/code&gt; shows up because Rust needs it for any function that mutates the world, not because the data is private. Where direct field access is more convenient than a method, just reach in.&lt;/p&gt;
&lt;h2 id=&quot;entity-handles&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#entity-handles&quot;&gt;#&lt;/a&gt;Entity handles&lt;/h2&gt;
&lt;p&gt;An &lt;code&gt;Entity&lt;/code&gt; is not an object. It owns nothing. It is a small handle the storage uses to find the components.&lt;/p&gt;
&lt;p&gt;A bare &lt;code&gt;u32&lt;/code&gt; would work, but it has a hazard. If you despawn entity &lt;code&gt;42&lt;/code&gt; and then spawn a new one, the allocator will reuse id &lt;code&gt;42&lt;/code&gt; (otherwise ids grow without bound). Now any code holding the old handle to &lt;code&gt;42&lt;/code&gt; will silently access the new entity&apos;s data. This is the ABA problem, and in a game it produces bugs that are extremely hard to diagnose because nothing crashes. Your AI just suddenly starts targeting a wall.&lt;/p&gt;
&lt;p&gt;The fix is a generation counter. Every time an id is recycled, its generation is bumped. The handle stores both the id and the generation it was minted at. The storage refuses to honor a handle whose generation does not match the current generation for that slot. Stale handles fail loudly with &lt;code&gt;None&lt;/code&gt; instead of returning the wrong data.&lt;/p&gt;
&lt;div class=&quot;bamboo-code-block&quot; data-bamboo-code data-bamboo-lang=&quot;rust&quot;&gt;&lt;div class=&quot;bamboo-code-toolbar&quot;&gt;&lt;button type=&quot;button&quot; class=&quot;bamboo-code-button&quot; data-bamboo-line-toggle aria-label=&quot;Toggle line numbers&quot; aria-pressed=&quot;false&quot; title=&quot;Toggle line numbers&quot;&gt;&lt;svg class=&quot;bamboo-code-icon&quot; viewBox=&quot;0 0 20 20&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;1.6&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M4 5h2M4 10h2M4 15h2&quot; stroke-linecap=&quot;round&quot;/&gt;&lt;path d=&quot;M9 5h7M9 10h7M9 15h7&quot; stroke-linecap=&quot;round&quot;/&gt;&lt;/svg&gt;&lt;/button&gt;&lt;button type=&quot;button&quot; class=&quot;bamboo-code-button&quot; data-bamboo-copy aria-label=&quot;Copy code&quot; title=&quot;Copy code&quot;&gt;&lt;svg class=&quot;bamboo-code-icon bamboo-code-icon-copy&quot; viewBox=&quot;0 0 20 20&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;1.6&quot; aria-hidden=&quot;true&quot;&gt;&lt;rect x=&quot;7&quot; y=&quot;3&quot; width=&quot;10&quot; height=&quot;12&quot; rx=&quot;2&quot;/&gt;&lt;path d=&quot;M5 7v8a2 2 0 0 0 2 2h6&quot;/&gt;&lt;/svg&gt;&lt;svg class=&quot;bamboo-code-icon bamboo-code-icon-check&quot; viewBox=&quot;0 0 20 20&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;2&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M4 10l4 4 8-8&quot; stroke-linecap=&quot;round&quot; stroke-linejoin=&quot;round&quot;/&gt;&lt;/svg&gt;&lt;/button&gt;&lt;/div&gt;&lt;pre style=&quot;background-color:#2b303b;color:#c0c5ce;&quot;&gt;&lt;code class=&quot;language-rust&quot;&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;#[&lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;derive&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(Default, Copy, Clone, Debug, Eq, PartialEq, Hash)]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub struct &lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;Entity {
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;id&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u32&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;generation&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u32&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;Copy&lt;/code&gt; because handles are cheap to pass around. &lt;code&gt;Eq&lt;/code&gt; and &lt;code&gt;Hash&lt;/code&gt; because we will want to put them in sets later.&lt;/p&gt;
&lt;h2 id=&quot;allocating-entities&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#allocating-entities&quot;&gt;#&lt;/a&gt;Allocating entities&lt;/h2&gt;
&lt;p&gt;The allocator hands out &lt;code&gt;Entity&lt;/code&gt; handles. It needs two things. A counter for the next never-before-used id, and a freelist of recently-freed &lt;code&gt;(id, next_generation)&lt;/code&gt; pairs to reuse.&lt;/p&gt;
&lt;div class=&quot;bamboo-code-block&quot; data-bamboo-code data-bamboo-lang=&quot;rust&quot;&gt;&lt;div class=&quot;bamboo-code-toolbar&quot;&gt;&lt;button type=&quot;button&quot; class=&quot;bamboo-code-button&quot; data-bamboo-line-toggle aria-label=&quot;Toggle line numbers&quot; aria-pressed=&quot;false&quot; title=&quot;Toggle line numbers&quot;&gt;&lt;svg class=&quot;bamboo-code-icon&quot; viewBox=&quot;0 0 20 20&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;1.6&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M4 5h2M4 10h2M4 15h2&quot; stroke-linecap=&quot;round&quot;/&gt;&lt;path d=&quot;M9 5h7M9 10h7M9 15h7&quot; stroke-linecap=&quot;round&quot;/&gt;&lt;/svg&gt;&lt;/button&gt;&lt;button type=&quot;button&quot; class=&quot;bamboo-code-button&quot; data-bamboo-copy aria-label=&quot;Copy code&quot; title=&quot;Copy code&quot;&gt;&lt;svg class=&quot;bamboo-code-icon bamboo-code-icon-copy&quot; viewBox=&quot;0 0 20 20&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;1.6&quot; aria-hidden=&quot;true&quot;&gt;&lt;rect x=&quot;7&quot; y=&quot;3&quot; width=&quot;10&quot; height=&quot;12&quot; rx=&quot;2&quot;/&gt;&lt;path d=&quot;M5 7v8a2 2 0 0 0 2 2h6&quot;/&gt;&lt;/svg&gt;&lt;svg class=&quot;bamboo-code-icon bamboo-code-icon-check&quot; viewBox=&quot;0 0 20 20&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;2&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M4 10l4 4 8-8&quot; stroke-linecap=&quot;round&quot; stroke-linejoin=&quot;round&quot;/&gt;&lt;/svg&gt;&lt;/button&gt;&lt;/div&gt;&lt;pre style=&quot;background-color:#2b303b;color:#c0c5ce;&quot;&gt;&lt;code class=&quot;language-rust&quot;&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;#[&lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;derive&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(Default)]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub struct &lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;EntityAllocator {
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;next_id&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u32&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;free&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;: Vec&amp;lt;(&lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u32&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u32&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;)&amp;gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl &lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;EntityAllocator {
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub fn &lt;/span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;allocate&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(&amp;amp;&lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;) -&amp;gt; Entity {
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;if let &lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;Some((id, generation)) = &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;.free.&lt;/span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;pop&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;            Entity { id, generation }
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        } &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;else &lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;            &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt; id = &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;.next_id;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;            &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;.next_id += &lt;/span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;            Entity { id, generation: &lt;/span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0 &lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub fn &lt;/span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;deallocate&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(&amp;amp;&lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;entity&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;: Entity) {
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;.free.&lt;/span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;push&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;((entity.id, entity.generation.&lt;/span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;wrapping_add&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;)));
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;On deallocate, we precompute the &lt;em&gt;next&lt;/em&gt; generation to be handed out for that id and stash it in the freelist. &lt;code&gt;wrapping_add(1)&lt;/code&gt; so that an id used billions of times still works (in practice this never happens, but it costs nothing). The next allocation pulls that pair off the freelist and produces a handle with the bumped generation. Old handles with the old generation will not match.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;next_id&lt;/code&gt; itself uses regular &lt;code&gt;+= 1&lt;/code&gt;. At &lt;code&gt;u32::MAX&lt;/code&gt; ever-spawned ids it will overflow, panicking in debug and wrapping in release. That is four billion unique entity ids across the lifetime of the program, only a real concern for long-running services that churn entities aggressively. A production allocator would either widen &lt;code&gt;next_id&lt;/code&gt; to &lt;code&gt;u64&lt;/code&gt; or recycle ids more aggressively. We leave it as is.&lt;/p&gt;
&lt;p&gt;A quick sanity check at this point.&lt;/p&gt;
&lt;div class=&quot;bamboo-code-block&quot; data-bamboo-code data-bamboo-lang=&quot;rust&quot;&gt;&lt;div class=&quot;bamboo-code-toolbar&quot;&gt;&lt;button type=&quot;button&quot; class=&quot;bamboo-code-button&quot; data-bamboo-line-toggle aria-label=&quot;Toggle line numbers&quot; aria-pressed=&quot;false&quot; title=&quot;Toggle line numbers&quot;&gt;&lt;svg class=&quot;bamboo-code-icon&quot; viewBox=&quot;0 0 20 20&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;1.6&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M4 5h2M4 10h2M4 15h2&quot; stroke-linecap=&quot;round&quot;/&gt;&lt;path d=&quot;M9 5h7M9 10h7M9 15h7&quot; stroke-linecap=&quot;round&quot;/&gt;&lt;/svg&gt;&lt;/button&gt;&lt;button type=&quot;button&quot; class=&quot;bamboo-code-button&quot; data-bamboo-copy aria-label=&quot;Copy code&quot; title=&quot;Copy code&quot;&gt;&lt;svg class=&quot;bamboo-code-icon bamboo-code-icon-copy&quot; viewBox=&quot;0 0 20 20&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;1.6&quot; aria-hidden=&quot;true&quot;&gt;&lt;rect x=&quot;7&quot; y=&quot;3&quot; width=&quot;10&quot; height=&quot;12&quot; rx=&quot;2&quot;/&gt;&lt;path d=&quot;M5 7v8a2 2 0 0 0 2 2h6&quot;/&gt;&lt;/svg&gt;&lt;svg class=&quot;bamboo-code-icon bamboo-code-icon-check&quot; viewBox=&quot;0 0 20 20&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;2&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M4 10l4 4 8-8&quot; stroke-linecap=&quot;round&quot; stroke-linejoin=&quot;round&quot;/&gt;&lt;/svg&gt;&lt;/button&gt;&lt;/div&gt;&lt;pre style=&quot;background-color:#2b303b;color:#c0c5ce;&quot;&gt;&lt;code class=&quot;language-rust&quot;&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let mut&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt; allocator = EntityAllocator::default();
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt; first = allocator.&lt;/span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;allocate&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;();
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;assert_eq!(first.generation, &lt;/span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;allocator.&lt;/span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;deallocate&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(first);
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt; recycled = allocator.&lt;/span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;allocate&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;();
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;assert_eq!(recycled.id, first.id);
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;assert_eq!(recycled.generation, &lt;/span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The allocator does not know whether a handle is currently valid. That bookkeeping lives elsewhere. Its job is to mint id-and-generation pairs that are unique over the lifetime of the program.&lt;/p&gt;
&lt;h2 id=&quot;components-are-just-structs&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#components-are-just-structs&quot;&gt;#&lt;/a&gt;Components are just structs&lt;/h2&gt;
&lt;p&gt;Components are plain data. No traits, no inheritance, no marker interfaces. We will start with two.&lt;/p&gt;
&lt;div class=&quot;bamboo-code-block&quot; data-bamboo-code data-bamboo-lang=&quot;rust&quot;&gt;&lt;div class=&quot;bamboo-code-toolbar&quot;&gt;&lt;button type=&quot;button&quot; class=&quot;bamboo-code-button&quot; data-bamboo-line-toggle aria-label=&quot;Toggle line numbers&quot; aria-pressed=&quot;false&quot; title=&quot;Toggle line numbers&quot;&gt;&lt;svg class=&quot;bamboo-code-icon&quot; viewBox=&quot;0 0 20 20&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;1.6&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M4 5h2M4 10h2M4 15h2&quot; stroke-linecap=&quot;round&quot;/&gt;&lt;path d=&quot;M9 5h7M9 10h7M9 15h7&quot; stroke-linecap=&quot;round&quot;/&gt;&lt;/svg&gt;&lt;/button&gt;&lt;button type=&quot;button&quot; class=&quot;bamboo-code-button&quot; data-bamboo-copy aria-label=&quot;Copy code&quot; title=&quot;Copy code&quot;&gt;&lt;svg class=&quot;bamboo-code-icon bamboo-code-icon-copy&quot; viewBox=&quot;0 0 20 20&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;1.6&quot; aria-hidden=&quot;true&quot;&gt;&lt;rect x=&quot;7&quot; y=&quot;3&quot; width=&quot;10&quot; height=&quot;12&quot; rx=&quot;2&quot;/&gt;&lt;path d=&quot;M5 7v8a2 2 0 0 0 2 2h6&quot;/&gt;&lt;/svg&gt;&lt;svg class=&quot;bamboo-code-icon bamboo-code-icon-check&quot; viewBox=&quot;0 0 20 20&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;2&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M4 10l4 4 8-8&quot; stroke-linecap=&quot;round&quot; stroke-linejoin=&quot;round&quot;/&gt;&lt;/svg&gt;&lt;/button&gt;&lt;/div&gt;&lt;pre style=&quot;background-color:#2b303b;color:#c0c5ce;&quot;&gt;&lt;code class=&quot;language-rust&quot;&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;#[&lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;derive&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(Default, Clone, Debug)]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub struct &lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;Position {
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;x&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;f32&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;y&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;f32&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;#[&lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;derive&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(Default, Clone, Debug)]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub struct &lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;Velocity {
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;x&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;f32&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;y&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;f32&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;Default&lt;/code&gt; is required because of how component migration works in part 2. We will rely on &lt;code&gt;mem::take&lt;/code&gt; to move components between archetypes without allocation, and &lt;code&gt;mem::take&lt;/code&gt; requires &lt;code&gt;Default&lt;/code&gt;. &lt;code&gt;Clone&lt;/code&gt; is convenient for tests. We are not adding any other constraint.&lt;/p&gt;
&lt;p&gt;The &quot;components are just structs&quot; rule is more important than it looks. Component types are decoupled from the storage. Any struct can become a component just by declaring its existence to the world. There is no &lt;code&gt;impl Component for Foo&lt;/code&gt; ceremony.&lt;/p&gt;
&lt;h2 id=&quot;why-hashmap-is-the-wrong-storage&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#why-hashmap-is-the-wrong-storage&quot;&gt;#&lt;/a&gt;Why HashMap is the wrong storage&lt;/h2&gt;
&lt;p&gt;Before we build the archetype storage, it is worth understanding why the obvious approach fails.&lt;/p&gt;
&lt;div class=&quot;bamboo-code-block&quot; data-bamboo-code data-bamboo-lang=&quot;rust&quot;&gt;&lt;div class=&quot;bamboo-code-toolbar&quot;&gt;&lt;button type=&quot;button&quot; class=&quot;bamboo-code-button&quot; data-bamboo-line-toggle aria-label=&quot;Toggle line numbers&quot; aria-pressed=&quot;false&quot; title=&quot;Toggle line numbers&quot;&gt;&lt;svg class=&quot;bamboo-code-icon&quot; viewBox=&quot;0 0 20 20&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;1.6&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M4 5h2M4 10h2M4 15h2&quot; stroke-linecap=&quot;round&quot;/&gt;&lt;path d=&quot;M9 5h7M9 10h7M9 15h7&quot; stroke-linecap=&quot;round&quot;/&gt;&lt;/svg&gt;&lt;/button&gt;&lt;button type=&quot;button&quot; class=&quot;bamboo-code-button&quot; data-bamboo-copy aria-label=&quot;Copy code&quot; title=&quot;Copy code&quot;&gt;&lt;svg class=&quot;bamboo-code-icon bamboo-code-icon-copy&quot; viewBox=&quot;0 0 20 20&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;1.6&quot; aria-hidden=&quot;true&quot;&gt;&lt;rect x=&quot;7&quot; y=&quot;3&quot; width=&quot;10&quot; height=&quot;12&quot; rx=&quot;2&quot;/&gt;&lt;path d=&quot;M5 7v8a2 2 0 0 0 2 2h6&quot;/&gt;&lt;/svg&gt;&lt;svg class=&quot;bamboo-code-icon bamboo-code-icon-check&quot; viewBox=&quot;0 0 20 20&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;2&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M4 10l4 4 8-8&quot; stroke-linecap=&quot;round&quot; stroke-linejoin=&quot;round&quot;/&gt;&lt;/svg&gt;&lt;/button&gt;&lt;/div&gt;&lt;pre style=&quot;background-color:#2b303b;color:#c0c5ce;&quot;&gt;&lt;code class=&quot;language-rust&quot;&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;struct &lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;NaiveWorld {
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;positions&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;: HashMap&amp;lt;Entity, Position&amp;gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;velocities&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;: HashMap&amp;lt;Entity, Velocity&amp;gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This is correct. It is also slow. To advance physics you iterate over every entity that has both a position and a velocity.&lt;/p&gt;
&lt;div class=&quot;bamboo-code-block&quot; data-bamboo-code data-bamboo-lang=&quot;rust&quot;&gt;&lt;div class=&quot;bamboo-code-toolbar&quot;&gt;&lt;button type=&quot;button&quot; class=&quot;bamboo-code-button&quot; data-bamboo-line-toggle aria-label=&quot;Toggle line numbers&quot; aria-pressed=&quot;false&quot; title=&quot;Toggle line numbers&quot;&gt;&lt;svg class=&quot;bamboo-code-icon&quot; viewBox=&quot;0 0 20 20&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;1.6&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M4 5h2M4 10h2M4 15h2&quot; stroke-linecap=&quot;round&quot;/&gt;&lt;path d=&quot;M9 5h7M9 10h7M9 15h7&quot; stroke-linecap=&quot;round&quot;/&gt;&lt;/svg&gt;&lt;/button&gt;&lt;button type=&quot;button&quot; class=&quot;bamboo-code-button&quot; data-bamboo-copy aria-label=&quot;Copy code&quot; title=&quot;Copy code&quot;&gt;&lt;svg class=&quot;bamboo-code-icon bamboo-code-icon-copy&quot; viewBox=&quot;0 0 20 20&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;1.6&quot; aria-hidden=&quot;true&quot;&gt;&lt;rect x=&quot;7&quot; y=&quot;3&quot; width=&quot;10&quot; height=&quot;12&quot; rx=&quot;2&quot;/&gt;&lt;path d=&quot;M5 7v8a2 2 0 0 0 2 2h6&quot;/&gt;&lt;/svg&gt;&lt;svg class=&quot;bamboo-code-icon bamboo-code-icon-check&quot; viewBox=&quot;0 0 20 20&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;2&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M4 10l4 4 8-8&quot; stroke-linecap=&quot;round&quot; stroke-linejoin=&quot;round&quot;/&gt;&lt;/svg&gt;&lt;/button&gt;&lt;/div&gt;&lt;pre style=&quot;background-color:#2b303b;color:#c0c5ce;&quot;&gt;&lt;code class=&quot;language-rust&quot;&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;for &lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(entity, position) in &amp;amp;&lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt; world.positions {
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;if let &lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;Some(velocity) = world.velocities.&lt;/span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;get&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(entity) {
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        position.x += velocity.x;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        position.y += velocity.y;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;For each entity, one hash lookup. The position and velocity for the same entity live at unrelated heap addresses, so each access is a cache miss. With ten thousand entities that is ten thousand hash lookups and twenty thousand probable cache misses every frame.&lt;/p&gt;
&lt;p&gt;The data we want to access together is not stored together. Fixing that is the whole point of archetypes.&lt;/p&gt;
&lt;h2 id=&quot;grouping-by-component-set&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#grouping-by-component-set&quot;&gt;#&lt;/a&gt;Grouping by component set&lt;/h2&gt;
&lt;p&gt;Group entities by &lt;em&gt;which set of components they have&lt;/em&gt;. Every entity that has exactly &lt;code&gt;Position + Velocity&lt;/code&gt; lives in one bucket. Every entity that has only &lt;code&gt;Position&lt;/code&gt; lives in another. Inside each bucket, store each component type as its own &lt;code&gt;Vec&lt;/code&gt; in slot-aligned order. The position at index &lt;code&gt;7&lt;/code&gt; and the velocity at index &lt;code&gt;7&lt;/code&gt; belong to the same entity.&lt;/p&gt;
&lt;p&gt;This is &quot;structure of arrays&quot; instead of &quot;array of structures.&quot; The physics loop becomes the following.&lt;/p&gt;
&lt;div class=&quot;bamboo-code-block&quot; data-bamboo-code data-bamboo-lang=&quot;rust&quot;&gt;&lt;div class=&quot;bamboo-code-toolbar&quot;&gt;&lt;button type=&quot;button&quot; class=&quot;bamboo-code-button&quot; data-bamboo-line-toggle aria-label=&quot;Toggle line numbers&quot; aria-pressed=&quot;false&quot; title=&quot;Toggle line numbers&quot;&gt;&lt;svg class=&quot;bamboo-code-icon&quot; viewBox=&quot;0 0 20 20&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;1.6&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M4 5h2M4 10h2M4 15h2&quot; stroke-linecap=&quot;round&quot;/&gt;&lt;path d=&quot;M9 5h7M9 10h7M9 15h7&quot; stroke-linecap=&quot;round&quot;/&gt;&lt;/svg&gt;&lt;/button&gt;&lt;button type=&quot;button&quot; class=&quot;bamboo-code-button&quot; data-bamboo-copy aria-label=&quot;Copy code&quot; title=&quot;Copy code&quot;&gt;&lt;svg class=&quot;bamboo-code-icon bamboo-code-icon-copy&quot; viewBox=&quot;0 0 20 20&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;1.6&quot; aria-hidden=&quot;true&quot;&gt;&lt;rect x=&quot;7&quot; y=&quot;3&quot; width=&quot;10&quot; height=&quot;12&quot; rx=&quot;2&quot;/&gt;&lt;path d=&quot;M5 7v8a2 2 0 0 0 2 2h6&quot;/&gt;&lt;/svg&gt;&lt;svg class=&quot;bamboo-code-icon bamboo-code-icon-check&quot; viewBox=&quot;0 0 20 20&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;2&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M4 10l4 4 8-8&quot; stroke-linecap=&quot;round&quot; stroke-linejoin=&quot;round&quot;/&gt;&lt;/svg&gt;&lt;/button&gt;&lt;/div&gt;&lt;pre style=&quot;background-color:#2b303b;color:#c0c5ce;&quot;&gt;&lt;code class=&quot;language-rust&quot;&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;for&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt; table in &lt;/span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;tables_with&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;POSITION &lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;| &lt;/span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;VELOCITY&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;for&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt; index in &lt;/span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;..table.entities.&lt;/span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;len&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        table.positions[index].x += table.velocities[index].x;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        table.positions[index].y += table.velocities[index].y;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Inside the inner loop, &lt;code&gt;positions[index]&lt;/code&gt; and &lt;code&gt;velocities[index]&lt;/code&gt; are stride-1 accesses on dense arrays the CPU prefetcher can predict. No hash lookups. No indirection. The component combination is identified by a bitmask, where each component type is assigned a bit.&lt;/p&gt;
&lt;div class=&quot;bamboo-code-block&quot; data-bamboo-code data-bamboo-lang=&quot;rust&quot;&gt;&lt;div class=&quot;bamboo-code-toolbar&quot;&gt;&lt;button type=&quot;button&quot; class=&quot;bamboo-code-button&quot; data-bamboo-line-toggle aria-label=&quot;Toggle line numbers&quot; aria-pressed=&quot;false&quot; title=&quot;Toggle line numbers&quot;&gt;&lt;svg class=&quot;bamboo-code-icon&quot; viewBox=&quot;0 0 20 20&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;1.6&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M4 5h2M4 10h2M4 15h2&quot; stroke-linecap=&quot;round&quot;/&gt;&lt;path d=&quot;M9 5h7M9 10h7M9 15h7&quot; stroke-linecap=&quot;round&quot;/&gt;&lt;/svg&gt;&lt;/button&gt;&lt;button type=&quot;button&quot; class=&quot;bamboo-code-button&quot; data-bamboo-copy aria-label=&quot;Copy code&quot; title=&quot;Copy code&quot;&gt;&lt;svg class=&quot;bamboo-code-icon bamboo-code-icon-copy&quot; viewBox=&quot;0 0 20 20&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;1.6&quot; aria-hidden=&quot;true&quot;&gt;&lt;rect x=&quot;7&quot; y=&quot;3&quot; width=&quot;10&quot; height=&quot;12&quot; rx=&quot;2&quot;/&gt;&lt;path d=&quot;M5 7v8a2 2 0 0 0 2 2h6&quot;/&gt;&lt;/svg&gt;&lt;svg class=&quot;bamboo-code-icon bamboo-code-icon-check&quot; viewBox=&quot;0 0 20 20&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;2&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M4 10l4 4 8-8&quot; stroke-linecap=&quot;round&quot; stroke-linejoin=&quot;round&quot;/&gt;&lt;/svg&gt;&lt;/button&gt;&lt;/div&gt;&lt;pre style=&quot;background-color:#2b303b;color:#c0c5ce;&quot;&gt;&lt;code class=&quot;language-rust&quot;&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub const &lt;/span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;POSITION&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u64 &lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;= &lt;/span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1 &lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;&amp;lt;&amp;lt; &lt;/span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub const &lt;/span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;VELOCITY&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u64 &lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;= &lt;/span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1 &lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;&amp;lt;&amp;lt; &lt;/span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;A &lt;code&gt;u64&lt;/code&gt; mask gives us 64 component types per world. That is the practical ceiling of this design. 64 is enough for most games. If you need more, freecs has a multi-world macro form that splits components across logical worlds with a shared entity allocator, mentioned at the end of part 3.&lt;/p&gt;
&lt;h2 id=&quot;the-archetype-table&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#the-archetype-table&quot;&gt;#&lt;/a&gt;The archetype table&lt;/h2&gt;
&lt;div class=&quot;bamboo-code-block&quot; data-bamboo-code data-bamboo-lang=&quot;rust&quot;&gt;&lt;div class=&quot;bamboo-code-toolbar&quot;&gt;&lt;button type=&quot;button&quot; class=&quot;bamboo-code-button&quot; data-bamboo-line-toggle aria-label=&quot;Toggle line numbers&quot; aria-pressed=&quot;false&quot; title=&quot;Toggle line numbers&quot;&gt;&lt;svg class=&quot;bamboo-code-icon&quot; viewBox=&quot;0 0 20 20&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;1.6&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M4 5h2M4 10h2M4 15h2&quot; stroke-linecap=&quot;round&quot;/&gt;&lt;path d=&quot;M9 5h7M9 10h7M9 15h7&quot; stroke-linecap=&quot;round&quot;/&gt;&lt;/svg&gt;&lt;/button&gt;&lt;button type=&quot;button&quot; class=&quot;bamboo-code-button&quot; data-bamboo-copy aria-label=&quot;Copy code&quot; title=&quot;Copy code&quot;&gt;&lt;svg class=&quot;bamboo-code-icon bamboo-code-icon-copy&quot; viewBox=&quot;0 0 20 20&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;1.6&quot; aria-hidden=&quot;true&quot;&gt;&lt;rect x=&quot;7&quot; y=&quot;3&quot; width=&quot;10&quot; height=&quot;12&quot; rx=&quot;2&quot;/&gt;&lt;path d=&quot;M5 7v8a2 2 0 0 0 2 2h6&quot;/&gt;&lt;/svg&gt;&lt;svg class=&quot;bamboo-code-icon bamboo-code-icon-check&quot; viewBox=&quot;0 0 20 20&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;2&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M4 10l4 4 8-8&quot; stroke-linecap=&quot;round&quot; stroke-linejoin=&quot;round&quot;/&gt;&lt;/svg&gt;&lt;/button&gt;&lt;/div&gt;&lt;pre style=&quot;background-color:#2b303b;color:#c0c5ce;&quot;&gt;&lt;code class=&quot;language-rust&quot;&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;#[&lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;derive&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(Default)]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub struct &lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;ComponentArrays {
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;mask&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u64&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;entities&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;: Vec&amp;lt;Entity&amp;gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;positions&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;: Vec&amp;lt;Position&amp;gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;velocities&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;: Vec&amp;lt;Velocity&amp;gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;mask&lt;/code&gt; records which components this table holds. &lt;code&gt;entities&lt;/code&gt; records which entity owns each slot, indexed in lockstep with the component arrays. &lt;code&gt;positions&lt;/code&gt; and &lt;code&gt;velocities&lt;/code&gt; get pushed to only when the corresponding bit is set in &lt;code&gt;mask&lt;/code&gt;, otherwise they stay empty. A table with mask &lt;code&gt;POSITION&lt;/code&gt; (bit 0 set, bit 1 clear) has entries in &lt;code&gt;positions&lt;/code&gt; and an empty &lt;code&gt;velocities&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;This struct is awkward. We are hard-coding two component fields and two corresponding masks, and adding a new component means editing this struct, the spawn code, the despawn code, the read code, the write code. A real ECS solves this with code generation. A macro stamps out the per-component fields and accessors from a single declaration. We will not do that here. The whole point of the series is to see the machine working, and a macro would hide the moving parts. The macro layer that scales this kernel cleanly to arbitrary component sets is exactly what &lt;a href=&quot;https://github.com/matthewjberger/freecs&quot;&gt;freecs&lt;/a&gt; is, and part 3 shows what its &lt;code&gt;ecs!&lt;/code&gt; declaration looks like next to the hand-rolled equivalent.&lt;/p&gt;
&lt;h2 id=&quot;routing-entities-to-their-slots&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#routing-entities-to-their-slots&quot;&gt;#&lt;/a&gt;Routing entities to their slots&lt;/h2&gt;
&lt;p&gt;We have entities (handles) and we have tables (storage). We need a way to look up &quot;given this entity, where do its components live.&quot; A &lt;code&gt;HashMap&amp;lt;Entity, (table_index, array_index)&amp;gt;&lt;/code&gt; would work, but entity ids come out of a small counter and most of them will be densely packed. A &lt;code&gt;Vec&lt;/code&gt; indexed by id is faster and just as compact.&lt;/p&gt;
&lt;div class=&quot;bamboo-code-block&quot; data-bamboo-code data-bamboo-lang=&quot;rust&quot;&gt;&lt;div class=&quot;bamboo-code-toolbar&quot;&gt;&lt;button type=&quot;button&quot; class=&quot;bamboo-code-button&quot; data-bamboo-line-toggle aria-label=&quot;Toggle line numbers&quot; aria-pressed=&quot;false&quot; title=&quot;Toggle line numbers&quot;&gt;&lt;svg class=&quot;bamboo-code-icon&quot; viewBox=&quot;0 0 20 20&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;1.6&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M4 5h2M4 10h2M4 15h2&quot; stroke-linecap=&quot;round&quot;/&gt;&lt;path d=&quot;M9 5h7M9 10h7M9 15h7&quot; stroke-linecap=&quot;round&quot;/&gt;&lt;/svg&gt;&lt;/button&gt;&lt;button type=&quot;button&quot; class=&quot;bamboo-code-button&quot; data-bamboo-copy aria-label=&quot;Copy code&quot; title=&quot;Copy code&quot;&gt;&lt;svg class=&quot;bamboo-code-icon bamboo-code-icon-copy&quot; viewBox=&quot;0 0 20 20&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;1.6&quot; aria-hidden=&quot;true&quot;&gt;&lt;rect x=&quot;7&quot; y=&quot;3&quot; width=&quot;10&quot; height=&quot;12&quot; rx=&quot;2&quot;/&gt;&lt;path d=&quot;M5 7v8a2 2 0 0 0 2 2h6&quot;/&gt;&lt;/svg&gt;&lt;svg class=&quot;bamboo-code-icon bamboo-code-icon-check&quot; viewBox=&quot;0 0 20 20&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;2&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M4 10l4 4 8-8&quot; stroke-linecap=&quot;round&quot; stroke-linejoin=&quot;round&quot;/&gt;&lt;/svg&gt;&lt;/button&gt;&lt;/div&gt;&lt;pre style=&quot;background-color:#2b303b;color:#c0c5ce;&quot;&gt;&lt;code class=&quot;language-rust&quot;&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;#[&lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;derive&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(Default, Copy, Clone)]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub struct &lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;EntityLocation {
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;generation&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u32&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;table_index&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u32&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;array_index&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u32&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;allocated&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;bool&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;#[&lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;derive&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(Default)]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub struct &lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;EntityLocations {
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;locations&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;: Vec&amp;lt;EntityLocation&amp;gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Each slot stores the generation of the entity currently at this id, the &lt;code&gt;(table, index)&lt;/code&gt; of its components, and an &lt;code&gt;allocated&lt;/code&gt; flag. The flag flips between two states. &lt;code&gt;true&lt;/code&gt; while an entity is live at this id, &lt;code&gt;false&lt;/code&gt; once that entity has been despawned. The generation lets a recycled handle be distinguished from the entity that previously held its id. The &lt;code&gt;allocated&lt;/code&gt; flag lets a fully-deallocated id be distinguished from anything live. Together they reject every stale handle.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;EntityLocation::default()&lt;/code&gt; setting &lt;code&gt;allocated: false&lt;/code&gt; is load-bearing. When &lt;code&gt;ensure_slot&lt;/code&gt; grows the backing vec, it fills the new entries with &lt;code&gt;EntityLocation::default()&lt;/code&gt;. A slot that has been grown into but never written looks identical to a despawned slot, and &lt;code&gt;get&lt;/code&gt; rejects both. We get safe defaults for free from the derive.&lt;/p&gt;
&lt;div class=&quot;bamboo-code-block&quot; data-bamboo-code data-bamboo-lang=&quot;rust&quot;&gt;&lt;div class=&quot;bamboo-code-toolbar&quot;&gt;&lt;button type=&quot;button&quot; class=&quot;bamboo-code-button&quot; data-bamboo-line-toggle aria-label=&quot;Toggle line numbers&quot; aria-pressed=&quot;false&quot; title=&quot;Toggle line numbers&quot;&gt;&lt;svg class=&quot;bamboo-code-icon&quot; viewBox=&quot;0 0 20 20&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;1.6&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M4 5h2M4 10h2M4 15h2&quot; stroke-linecap=&quot;round&quot;/&gt;&lt;path d=&quot;M9 5h7M9 10h7M9 15h7&quot; stroke-linecap=&quot;round&quot;/&gt;&lt;/svg&gt;&lt;/button&gt;&lt;button type=&quot;button&quot; class=&quot;bamboo-code-button&quot; data-bamboo-copy aria-label=&quot;Copy code&quot; title=&quot;Copy code&quot;&gt;&lt;svg class=&quot;bamboo-code-icon bamboo-code-icon-copy&quot; viewBox=&quot;0 0 20 20&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;1.6&quot; aria-hidden=&quot;true&quot;&gt;&lt;rect x=&quot;7&quot; y=&quot;3&quot; width=&quot;10&quot; height=&quot;12&quot; rx=&quot;2&quot;/&gt;&lt;path d=&quot;M5 7v8a2 2 0 0 0 2 2h6&quot;/&gt;&lt;/svg&gt;&lt;svg class=&quot;bamboo-code-icon bamboo-code-icon-check&quot; viewBox=&quot;0 0 20 20&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;2&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M4 10l4 4 8-8&quot; stroke-linecap=&quot;round&quot; stroke-linejoin=&quot;round&quot;/&gt;&lt;/svg&gt;&lt;/button&gt;&lt;/div&gt;&lt;pre style=&quot;background-color:#2b303b;color:#c0c5ce;&quot;&gt;&lt;code class=&quot;language-rust&quot;&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl &lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;EntityLocations {
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub fn &lt;/span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;ensure_slot&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(&amp;amp;&lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;id&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u32&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt; needed = id as &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;usize &lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;+ &lt;/span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;if&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt; needed &amp;gt; &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;.locations.&lt;/span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;len&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;            &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;.locations.&lt;/span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;resize&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(needed, EntityLocation::default());
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub fn &lt;/span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;get&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(&amp;amp;&lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;entity&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;: Entity) -&amp;gt; Option&amp;lt;(&lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;usize&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;usize&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;)&amp;gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt; location = &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;.locations.&lt;/span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;get&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(entity.id as &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;usize&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;)?;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;if &lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;!location.allocated || location.generation != entity.generation {
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;            &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;return &lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;None;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        Some((location.table_index as &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;usize&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;, location.array_index as &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;usize&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub fn &lt;/span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;set&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(&amp;amp;&lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;entity&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;: Entity, &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;table_index&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;usize&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;array_index&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;usize&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;ensure_slot&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(entity.id);
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;.locations[entity.id as &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;usize&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;] = EntityLocation {
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;            generation: entity.generation,
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;            table_index: table_index as &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u32&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;            array_index: array_index as &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u32&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;            allocated: &lt;/span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;true&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        };
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub fn &lt;/span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;mark_deallocated&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(&amp;amp;&lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;id&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u32&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;if let &lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;Some(location) = &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;.locations.&lt;/span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;get_mut&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(id as &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;usize&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;            location.allocated = &lt;/span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;false&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;get&lt;/code&gt; is the gatekeeper. It refuses to return a location if the slot is unallocated or if the requested entity&apos;s generation does not match. Stale handles die here. The function returns &lt;code&gt;Option&amp;lt;(usize, usize)&amp;gt;&lt;/code&gt; rather than &lt;code&gt;Option&amp;lt;&amp;amp;EntityLocation&amp;gt;&lt;/code&gt; because the caller only ever needs the table index and the array index inside it.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;ensure_slot&lt;/code&gt; resizes the backing vec to fit the requested id. We use &lt;code&gt;resize&lt;/code&gt;, not doubling, because the allocator hands out ids monotonically when the freelist is empty, so growing on demand by exact size is fine.&lt;/p&gt;
&lt;h2 id=&quot;the-world&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#the-world&quot;&gt;#&lt;/a&gt;The World&lt;/h2&gt;
&lt;div class=&quot;bamboo-code-block&quot; data-bamboo-code data-bamboo-lang=&quot;rust&quot;&gt;&lt;div class=&quot;bamboo-code-toolbar&quot;&gt;&lt;button type=&quot;button&quot; class=&quot;bamboo-code-button&quot; data-bamboo-line-toggle aria-label=&quot;Toggle line numbers&quot; aria-pressed=&quot;false&quot; title=&quot;Toggle line numbers&quot;&gt;&lt;svg class=&quot;bamboo-code-icon&quot; viewBox=&quot;0 0 20 20&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;1.6&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M4 5h2M4 10h2M4 15h2&quot; stroke-linecap=&quot;round&quot;/&gt;&lt;path d=&quot;M9 5h7M9 10h7M9 15h7&quot; stroke-linecap=&quot;round&quot;/&gt;&lt;/svg&gt;&lt;/button&gt;&lt;button type=&quot;button&quot; class=&quot;bamboo-code-button&quot; data-bamboo-copy aria-label=&quot;Copy code&quot; title=&quot;Copy code&quot;&gt;&lt;svg class=&quot;bamboo-code-icon bamboo-code-icon-copy&quot; viewBox=&quot;0 0 20 20&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;1.6&quot; aria-hidden=&quot;true&quot;&gt;&lt;rect x=&quot;7&quot; y=&quot;3&quot; width=&quot;10&quot; height=&quot;12&quot; rx=&quot;2&quot;/&gt;&lt;path d=&quot;M5 7v8a2 2 0 0 0 2 2h6&quot;/&gt;&lt;/svg&gt;&lt;svg class=&quot;bamboo-code-icon bamboo-code-icon-check&quot; viewBox=&quot;0 0 20 20&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;2&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M4 10l4 4 8-8&quot; stroke-linecap=&quot;round&quot; stroke-linejoin=&quot;round&quot;/&gt;&lt;/svg&gt;&lt;/button&gt;&lt;/div&gt;&lt;pre style=&quot;background-color:#2b303b;color:#c0c5ce;&quot;&gt;&lt;code class=&quot;language-rust&quot;&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;use &lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;std::collections::HashMap;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;#[&lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;derive&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(Default)]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub struct &lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;World {
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;allocator&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;: EntityAllocator,
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;entity_locations&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;: EntityLocations,
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;tables&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;: Vec&amp;lt;ComponentArrays&amp;gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;table_lookup&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;: HashMap&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u64&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;usize&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;&amp;gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Four fields. The allocator (so it can mint entities), the location map (so it can route), the tables (so it can store components), and a &lt;code&gt;mask&lt;/code&gt; to &lt;code&gt;table_index&lt;/code&gt; lookup so we can find the right table for a given component combination without scanning.&lt;/p&gt;
&lt;p&gt;Finding or creating a table.&lt;/p&gt;
&lt;div class=&quot;bamboo-code-block&quot; data-bamboo-code data-bamboo-lang=&quot;rust&quot;&gt;&lt;div class=&quot;bamboo-code-toolbar&quot;&gt;&lt;button type=&quot;button&quot; class=&quot;bamboo-code-button&quot; data-bamboo-line-toggle aria-label=&quot;Toggle line numbers&quot; aria-pressed=&quot;false&quot; title=&quot;Toggle line numbers&quot;&gt;&lt;svg class=&quot;bamboo-code-icon&quot; viewBox=&quot;0 0 20 20&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;1.6&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M4 5h2M4 10h2M4 15h2&quot; stroke-linecap=&quot;round&quot;/&gt;&lt;path d=&quot;M9 5h7M9 10h7M9 15h7&quot; stroke-linecap=&quot;round&quot;/&gt;&lt;/svg&gt;&lt;/button&gt;&lt;button type=&quot;button&quot; class=&quot;bamboo-code-button&quot; data-bamboo-copy aria-label=&quot;Copy code&quot; title=&quot;Copy code&quot;&gt;&lt;svg class=&quot;bamboo-code-icon bamboo-code-icon-copy&quot; viewBox=&quot;0 0 20 20&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;1.6&quot; aria-hidden=&quot;true&quot;&gt;&lt;rect x=&quot;7&quot; y=&quot;3&quot; width=&quot;10&quot; height=&quot;12&quot; rx=&quot;2&quot;/&gt;&lt;path d=&quot;M5 7v8a2 2 0 0 0 2 2h6&quot;/&gt;&lt;/svg&gt;&lt;svg class=&quot;bamboo-code-icon bamboo-code-icon-check&quot; viewBox=&quot;0 0 20 20&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;2&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M4 10l4 4 8-8&quot; stroke-linecap=&quot;round&quot; stroke-linejoin=&quot;round&quot;/&gt;&lt;/svg&gt;&lt;/button&gt;&lt;/div&gt;&lt;pre style=&quot;background-color:#2b303b;color:#c0c5ce;&quot;&gt;&lt;code class=&quot;language-rust&quot;&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl &lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;World {
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub fn &lt;/span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;get_or_create_table&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(&amp;amp;&lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;mask&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u64&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;) -&amp;gt; &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;usize &lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;if let &lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;Some(&amp;amp;index) = &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;.table_lookup.&lt;/span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;get&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(&amp;amp;mask) {
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;            &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;return&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt; index;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt; index = &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;.tables.&lt;/span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;len&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;();
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;.tables.&lt;/span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;push&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(ComponentArrays { mask, ..Default::default() });
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;.table_lookup.&lt;/span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;insert&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(mask, index);
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        index
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The first time someone spawns an entity with &lt;code&gt;POSITION | VELOCITY&lt;/code&gt;, this creates a fresh table for that mask. Every subsequent spawn with the same mask reuses it.&lt;/p&gt;
&lt;h2 id=&quot;spawning&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#spawning&quot;&gt;#&lt;/a&gt;Spawning&lt;/h2&gt;
&lt;div class=&quot;bamboo-code-block&quot; data-bamboo-code data-bamboo-lang=&quot;rust&quot;&gt;&lt;div class=&quot;bamboo-code-toolbar&quot;&gt;&lt;button type=&quot;button&quot; class=&quot;bamboo-code-button&quot; data-bamboo-line-toggle aria-label=&quot;Toggle line numbers&quot; aria-pressed=&quot;false&quot; title=&quot;Toggle line numbers&quot;&gt;&lt;svg class=&quot;bamboo-code-icon&quot; viewBox=&quot;0 0 20 20&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;1.6&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M4 5h2M4 10h2M4 15h2&quot; stroke-linecap=&quot;round&quot;/&gt;&lt;path d=&quot;M9 5h7M9 10h7M9 15h7&quot; stroke-linecap=&quot;round&quot;/&gt;&lt;/svg&gt;&lt;/button&gt;&lt;button type=&quot;button&quot; class=&quot;bamboo-code-button&quot; data-bamboo-copy aria-label=&quot;Copy code&quot; title=&quot;Copy code&quot;&gt;&lt;svg class=&quot;bamboo-code-icon bamboo-code-icon-copy&quot; viewBox=&quot;0 0 20 20&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;1.6&quot; aria-hidden=&quot;true&quot;&gt;&lt;rect x=&quot;7&quot; y=&quot;3&quot; width=&quot;10&quot; height=&quot;12&quot; rx=&quot;2&quot;/&gt;&lt;path d=&quot;M5 7v8a2 2 0 0 0 2 2h6&quot;/&gt;&lt;/svg&gt;&lt;svg class=&quot;bamboo-code-icon bamboo-code-icon-check&quot; viewBox=&quot;0 0 20 20&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;2&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M4 10l4 4 8-8&quot; stroke-linecap=&quot;round&quot; stroke-linejoin=&quot;round&quot;/&gt;&lt;/svg&gt;&lt;/button&gt;&lt;/div&gt;&lt;pre style=&quot;background-color:#2b303b;color:#c0c5ce;&quot;&gt;&lt;code class=&quot;language-rust&quot;&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl &lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;World {
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub fn &lt;/span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;spawn&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(&amp;amp;&lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;mask&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;u64&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;) -&amp;gt; Entity {
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt; entity = &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;.allocator.&lt;/span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;allocate&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;();
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt; table_index = &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;get_or_create_table&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(mask);
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt; table = &amp;amp;&lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;.tables[table_index];
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt; array_index = table.entities.&lt;/span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;len&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;();
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        table.entities.&lt;/span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;push&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(entity);
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;if&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt; mask &amp;amp; &lt;/span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;POSITION &lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;!= &lt;/span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0 &lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;            table.positions.&lt;/span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;push&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(Position::default());
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;if&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt; mask &amp;amp; &lt;/span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;VELOCITY &lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;!= &lt;/span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0 &lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;            table.velocities.&lt;/span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;push&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(Velocity::default());
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;.entity_locations.&lt;/span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;set&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(entity, table_index, array_index);
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        entity
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Allocate the handle, find the table, append a slot to every component vec the mask says is present, record the entity&apos;s location. The mask-checked pushes are the manual fan-out the macro would generate. In a hand-written ECS, this block grows linearly with the number of component types, which is the main reason ECS libraries use macros.&lt;/p&gt;
&lt;p&gt;The components are initialized to &lt;code&gt;Default&lt;/code&gt;. In part 2 we will add a way to spawn with custom values. For now, the caller writes the components after spawn.&lt;/p&gt;
&lt;h2 id=&quot;reading-and-writing-components&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#reading-and-writing-components&quot;&gt;#&lt;/a&gt;Reading and writing components&lt;/h2&gt;
&lt;div class=&quot;bamboo-code-block&quot; data-bamboo-code data-bamboo-lang=&quot;rust&quot;&gt;&lt;div class=&quot;bamboo-code-toolbar&quot;&gt;&lt;button type=&quot;button&quot; class=&quot;bamboo-code-button&quot; data-bamboo-line-toggle aria-label=&quot;Toggle line numbers&quot; aria-pressed=&quot;false&quot; title=&quot;Toggle line numbers&quot;&gt;&lt;svg class=&quot;bamboo-code-icon&quot; viewBox=&quot;0 0 20 20&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;1.6&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M4 5h2M4 10h2M4 15h2&quot; stroke-linecap=&quot;round&quot;/&gt;&lt;path d=&quot;M9 5h7M9 10h7M9 15h7&quot; stroke-linecap=&quot;round&quot;/&gt;&lt;/svg&gt;&lt;/button&gt;&lt;button type=&quot;button&quot; class=&quot;bamboo-code-button&quot; data-bamboo-copy aria-label=&quot;Copy code&quot; title=&quot;Copy code&quot;&gt;&lt;svg class=&quot;bamboo-code-icon bamboo-code-icon-copy&quot; viewBox=&quot;0 0 20 20&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;1.6&quot; aria-hidden=&quot;true&quot;&gt;&lt;rect x=&quot;7&quot; y=&quot;3&quot; width=&quot;10&quot; height=&quot;12&quot; rx=&quot;2&quot;/&gt;&lt;path d=&quot;M5 7v8a2 2 0 0 0 2 2h6&quot;/&gt;&lt;/svg&gt;&lt;svg class=&quot;bamboo-code-icon bamboo-code-icon-check&quot; viewBox=&quot;0 0 20 20&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;2&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M4 10l4 4 8-8&quot; stroke-linecap=&quot;round&quot; stroke-linejoin=&quot;round&quot;/&gt;&lt;/svg&gt;&lt;/button&gt;&lt;/div&gt;&lt;pre style=&quot;background-color:#2b303b;color:#c0c5ce;&quot;&gt;&lt;code class=&quot;language-rust&quot;&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl &lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;World {
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub fn &lt;/span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;get_position&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(&amp;amp;&lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;entity&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;: Entity) -&amp;gt; Option&amp;lt;&amp;amp;Position&amp;gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let &lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(table_index, array_index) = &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;.entity_locations.&lt;/span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;get&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(entity)?;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt; table = &amp;amp;&lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;.tables[table_index];
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;if&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt; table.mask &amp;amp; &lt;/span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;POSITION &lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;== &lt;/span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0 &lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;            &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;return &lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;None;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        Some(&amp;amp;table.positions[array_index])
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub fn &lt;/span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;get_position_mut&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(&amp;amp;&lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;entity&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;: Entity) -&amp;gt; Option&amp;lt;&amp;amp;&lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt; Position&amp;gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let &lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(table_index, array_index) = &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;.entity_locations.&lt;/span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;get&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(entity)?;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt; table = &amp;amp;&lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;.tables[table_index];
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;if&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt; table.mask &amp;amp; &lt;/span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;POSITION &lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;== &lt;/span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0 &lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;            &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;return &lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;None;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        Some(&amp;amp;&lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt; table.positions[array_index])
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub fn &lt;/span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;get_velocity&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(&amp;amp;&lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;entity&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;: Entity) -&amp;gt; Option&amp;lt;&amp;amp;Velocity&amp;gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let &lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(table_index, array_index) = &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;.entity_locations.&lt;/span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;get&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(entity)?;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt; table = &amp;amp;&lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;.tables[table_index];
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;if&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt; table.mask &amp;amp; &lt;/span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;VELOCITY &lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;== &lt;/span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0 &lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;            &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;return &lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;None;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        Some(&amp;amp;table.velocities[array_index])
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub fn &lt;/span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;get_velocity_mut&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(&amp;amp;&lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;entity&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;: Entity) -&amp;gt; Option&amp;lt;&amp;amp;&lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt; Velocity&amp;gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let &lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(table_index, array_index) = &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;.entity_locations.&lt;/span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;get&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(entity)?;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt; table = &amp;amp;&lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;.tables[table_index];
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;if&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt; table.mask &amp;amp; &lt;/span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;VELOCITY &lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;== &lt;/span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0 &lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;            &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;return &lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;None;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        Some(&amp;amp;&lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt; table.velocities[array_index])
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Two reasons a get can fail. The entity is invalid (stale handle, despawned, never existed), or the entity is valid but its archetype does not contain this component. The first case bails out at &lt;code&gt;entity_locations.get&lt;/code&gt;. The second is the &lt;code&gt;mask &amp;amp; POSITION == 0&lt;/code&gt; check.&lt;/p&gt;
&lt;p&gt;This is fan-out again. Four near-identical functions per component type. A macro would write them. We are not.&lt;/p&gt;
&lt;h2 id=&quot;despawning&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#despawning&quot;&gt;#&lt;/a&gt;Despawning&lt;/h2&gt;
&lt;p&gt;Despawn has to do three things. Invalidate the entity so future lookups fail, remove its components from the table so they do not leak, and keep the table compact so iteration stays fast.&lt;/p&gt;
&lt;p&gt;The compactness requirement is the source of all the complexity. We could mark the slot as a tombstone and skip it during iteration, but that wastes memory and slows iteration with branching. The standard answer is &lt;code&gt;swap_remove&lt;/code&gt;. Take the last entry in the vec and move it into the deleted slot. That keeps the vec contiguous. The cost is that the entity formerly at the last slot now lives at a different array index, so its &lt;code&gt;EntityLocation&lt;/code&gt; needs updating.&lt;/p&gt;
&lt;div class=&quot;bamboo-code-block&quot; data-bamboo-code data-bamboo-lang=&quot;rust&quot;&gt;&lt;div class=&quot;bamboo-code-toolbar&quot;&gt;&lt;button type=&quot;button&quot; class=&quot;bamboo-code-button&quot; data-bamboo-line-toggle aria-label=&quot;Toggle line numbers&quot; aria-pressed=&quot;false&quot; title=&quot;Toggle line numbers&quot;&gt;&lt;svg class=&quot;bamboo-code-icon&quot; viewBox=&quot;0 0 20 20&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;1.6&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M4 5h2M4 10h2M4 15h2&quot; stroke-linecap=&quot;round&quot;/&gt;&lt;path d=&quot;M9 5h7M9 10h7M9 15h7&quot; stroke-linecap=&quot;round&quot;/&gt;&lt;/svg&gt;&lt;/button&gt;&lt;button type=&quot;button&quot; class=&quot;bamboo-code-button&quot; data-bamboo-copy aria-label=&quot;Copy code&quot; title=&quot;Copy code&quot;&gt;&lt;svg class=&quot;bamboo-code-icon bamboo-code-icon-copy&quot; viewBox=&quot;0 0 20 20&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;1.6&quot; aria-hidden=&quot;true&quot;&gt;&lt;rect x=&quot;7&quot; y=&quot;3&quot; width=&quot;10&quot; height=&quot;12&quot; rx=&quot;2&quot;/&gt;&lt;path d=&quot;M5 7v8a2 2 0 0 0 2 2h6&quot;/&gt;&lt;/svg&gt;&lt;svg class=&quot;bamboo-code-icon bamboo-code-icon-check&quot; viewBox=&quot;0 0 20 20&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;2&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M4 10l4 4 8-8&quot; stroke-linecap=&quot;round&quot; stroke-linejoin=&quot;round&quot;/&gt;&lt;/svg&gt;&lt;/button&gt;&lt;/div&gt;&lt;pre style=&quot;background-color:#2b303b;color:#c0c5ce;&quot;&gt;&lt;code class=&quot;language-rust&quot;&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;impl &lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;World {
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub fn &lt;/span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;despawn&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(&amp;amp;&lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;entity&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;: Entity) -&amp;gt; &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;bool &lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let &lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;Some((table_index, array_index)) = &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;.entity_locations.&lt;/span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;get&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(entity) &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;else &lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;            &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;return &lt;/span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;false&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        };
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;.entity_locations.&lt;/span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;mark_deallocated&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(entity.id);
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;.allocator.&lt;/span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;deallocate&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(entity);
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt; table = &amp;amp;&lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;mut &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;.tables[table_index];
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt; last_index = table.entities.&lt;/span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;len&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;() - &lt;/span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt; swapped = &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;if&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt; array_index &amp;lt; last_index {
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;            Some(table.entities[last_index])
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        } &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;else &lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;            None
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        };
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        table.entities.&lt;/span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;swap_remove&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(array_index);
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;if&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt; table.mask &amp;amp; &lt;/span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;POSITION &lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;!= &lt;/span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0 &lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;            table.positions.&lt;/span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;swap_remove&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(array_index);
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;if&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt; table.mask &amp;amp; &lt;/span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;VELOCITY &lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;!= &lt;/span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;0 &lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;            table.velocities.&lt;/span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;swap_remove&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(array_index);
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;if let &lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;Some(moved) = swapped {
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;            &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;.entity_locations.&lt;/span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;set&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(moved, table_index, array_index);
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;true
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Order matters here. We capture which entity is about to be moved &lt;em&gt;before&lt;/em&gt; we do the &lt;code&gt;swap_remove&lt;/code&gt;, because afterwards the last index is gone and we cannot recover it. We do all the &lt;code&gt;swap_remove&lt;/code&gt;s on the component vecs in lockstep, since &lt;code&gt;entities[i]&lt;/code&gt;, &lt;code&gt;positions[i]&lt;/code&gt;, and &lt;code&gt;velocities[i]&lt;/code&gt; must always describe the same entity. Then we update the moved entity&apos;s location.&lt;/p&gt;
&lt;p&gt;If the despawned entity was the last one in its table, there is no swap to track.&lt;/p&gt;
&lt;h2 id=&quot;what-we-built&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#what-we-built&quot;&gt;#&lt;/a&gt;What we built&lt;/h2&gt;
&lt;div class=&quot;bamboo-code-block&quot; data-bamboo-code&gt;&lt;div class=&quot;bamboo-code-toolbar&quot;&gt;&lt;button type=&quot;button&quot; class=&quot;bamboo-code-button&quot; data-bamboo-line-toggle aria-label=&quot;Toggle line numbers&quot; aria-pressed=&quot;false&quot; title=&quot;Toggle line numbers&quot;&gt;&lt;svg class=&quot;bamboo-code-icon&quot; viewBox=&quot;0 0 20 20&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;1.6&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M4 5h2M4 10h2M4 15h2&quot; stroke-linecap=&quot;round&quot;/&gt;&lt;path d=&quot;M9 5h7M9 10h7M9 15h7&quot; stroke-linecap=&quot;round&quot;/&gt;&lt;/svg&gt;&lt;/button&gt;&lt;button type=&quot;button&quot; class=&quot;bamboo-code-button&quot; data-bamboo-copy aria-label=&quot;Copy code&quot; title=&quot;Copy code&quot;&gt;&lt;svg class=&quot;bamboo-code-icon bamboo-code-icon-copy&quot; viewBox=&quot;0 0 20 20&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;1.6&quot; aria-hidden=&quot;true&quot;&gt;&lt;rect x=&quot;7&quot; y=&quot;3&quot; width=&quot;10&quot; height=&quot;12&quot; rx=&quot;2&quot;/&gt;&lt;path d=&quot;M5 7v8a2 2 0 0 0 2 2h6&quot;/&gt;&lt;/svg&gt;&lt;svg class=&quot;bamboo-code-icon bamboo-code-icon-check&quot; viewBox=&quot;0 0 20 20&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;2&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M4 10l4 4 8-8&quot; stroke-linecap=&quot;round&quot; stroke-linejoin=&quot;round&quot;/&gt;&lt;/svg&gt;&lt;/button&gt;&lt;/div&gt;&lt;pre style=&quot;background-color:#2b303b;color:#c0c5ce;&quot;&gt;&lt;code&gt;&lt;span class=&quot;bamboo-line&quot;&gt;World
&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;├── allocator: EntityAllocator          mints generational handles
&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;├── entity_locations: EntityLocations   maps entity id to (table, slot)
&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;├── tables: Vec&amp;lt;ComponentArrays&amp;gt;        one per archetype
&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;└── table_lookup: HashMap&amp;lt;u64, usize&amp;gt;   mask to table index
&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;ComponentArrays  (one per unique component combination)
&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;├── mask: u64                           which components this table holds
&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;├── entities: Vec&amp;lt;Entity&amp;gt;               which entity owns each slot
&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;├── positions: Vec&amp;lt;Position&amp;gt;            populated iff mask &amp;amp; POSITION
&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;└── velocities: Vec&amp;lt;Velocity&amp;gt;           populated iff mask &amp;amp; VELOCITY
&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;EntityLocation  (one per entity id)
&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;├── generation: u32                     ABA guard
&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;├── table_index: u32
&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;├── array_index: u32
&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;└── allocated: bool                     stale-handle guard
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Operations on &lt;code&gt;World&lt;/code&gt;. &lt;code&gt;spawn(mask)&lt;/code&gt;, &lt;code&gt;get_position&lt;/code&gt;/&lt;code&gt;get_position_mut&lt;/code&gt;, &lt;code&gt;get_velocity&lt;/code&gt;/&lt;code&gt;get_velocity_mut&lt;/code&gt;, &lt;code&gt;despawn&lt;/code&gt;. Despawned ids get recycled with a bumped generation, and stale handles fail closed with &lt;code&gt;None&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id=&quot;what-is-missing&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#what-is-missing&quot;&gt;#&lt;/a&gt;What is missing&lt;/h2&gt;
&lt;p&gt;There are several gaps in what we built. None of them are accidents.&lt;/p&gt;
&lt;p&gt;You cannot add a component to an entity that did not have it at spawn time. There is no &lt;code&gt;add_velocity(entity)&lt;/code&gt;. The entity is locked into the archetype it was spawned into. Real games need to add and remove components at runtime (a &quot;stunned&quot; effect, equipment, AI states), and the way archetypes handle this is the central trick of part 2. The entity has to be physically moved to a different table.&lt;/p&gt;
&lt;p&gt;There is no way to query. You can ask &quot;what is this entity&apos;s position?&quot; but you cannot ask &quot;give me every entity that has both a position and a velocity.&quot; That is also part 2.&lt;/p&gt;
&lt;p&gt;There is no &lt;code&gt;set_position&lt;/code&gt; that adds the component if it is missing. There is no batch spawn. There is no parallelism. There is no change tracking, no events, no tags, no commands. Those are part 3.&lt;/p&gt;
&lt;p&gt;Part 2 picks up structural change and queries. Making components addable and removable at runtime, walking the tables to find entities that match a component combination, and the two caches (archetype graph for migration, query cache for iteration) that turn the naive O(N) scans into near-constant time without changing the surface API.&lt;/p&gt;
&lt;h2 id=&quot;the-full-file&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#the-full-file&quot;&gt;#&lt;/a&gt;The full file&lt;/h2&gt;
&lt;p&gt;The complete file is around 250 lines and lives as a &lt;a href=&quot;https://gist.github.com/matthewjberger/bbf7e0dc3fd5be28fe01f5c72cdaedb7&quot;&gt;gist&lt;/a&gt;. Run &lt;code&gt;cargo new ecs &amp;amp;&amp;amp; cd ecs&lt;/code&gt;, replace &lt;code&gt;src/main.rs&lt;/code&gt; with its contents, then &lt;code&gt;cargo run&lt;/code&gt;. It should print the mover&apos;s state and then &lt;code&gt;ok&lt;/code&gt;. The final block of &lt;code&gt;main&lt;/code&gt; exercises the generational guard. After we despawn &lt;code&gt;mover&lt;/code&gt;, the next spawn reuses its id but bumps the generation, and the original handle no longer resolves.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Building a static site generator in Rust</title>
    <link href="https://matthewberger.dev/articles/posts/building-a-static-site-generator-in-rust/" rel="alternate"/>
    <id>https://matthewberger.dev/articles/posts/building-a-static-site-generator-in-rust/</id>
    <updated>2026-05-16T00:00:00+00:00</updated>
    <summary type="text">How bamboo is shaped: the SSG I wrote in Rust and use to build this site. Content walks, frontmatter, syntect, Tera, shortcodes, parallel rendering, and incremental rebuilds.</summary>
    <content type="html">&lt;p&gt;This site is generated by &lt;a href=&quot;https://github.com/matthewjberger/bamboo&quot;&gt;bamboo&lt;/a&gt;, the static site generator I wrote in Rust and use to build &lt;code&gt;matthewberger.dev/articles&lt;/code&gt;. Every page you read here starts as a markdown file with a TOML header on disk, gets turned into HTML by bamboo, and lands in a &lt;code&gt;dist/&lt;/code&gt; directory that gets uploaded to GitHub Pages. There is no server doing work at request time, no database, no framework. The deployed site is a few hundred plain files.&lt;/p&gt;
&lt;p&gt;This post is about how that machine is shaped. The pieces, why they ended up that way, and what the awkward parts cost. I will walk through the code in the order data flows through it: read the config, walk the content tree, render markdown, expand shortcodes, run templates, drop files, post-process.&lt;/p&gt;
&lt;p&gt;The whole codebase is in the &lt;a href=&quot;https://github.com/matthewjberger/bamboo&quot;&gt;matthewjberger/bamboo&lt;/a&gt; repo. Under ten thousand lines of Rust including tests, no &lt;code&gt;unsafe&lt;/code&gt;, no proc macros, edition 2024. The library crate is on crates.io as &lt;a href=&quot;https://crates.io/crates/bamboo-ssg&quot;&gt;bamboo-ssg&lt;/a&gt; and the CLI as &lt;a href=&quot;https://crates.io/crates/bamboo-cli&quot;&gt;bamboo-cli&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;what-a-static-site-generator-actually-is&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#what-a-static-site-generator-actually-is&quot;&gt;#&lt;/a&gt;What a static site generator actually is&lt;/h2&gt;
&lt;p&gt;A static site generator&apos;s input is a tree of markdown and configuration. Its output is a directory of HTML, CSS, and assets, laid out so a dumb file server can serve them at the right URLs. &quot;Static&quot; means the work happens at build time. Once &lt;code&gt;dist/&lt;/code&gt; is written, the site has no runtime dependencies. No PHP, no Node process, no database. You hand the directory to GitHub Pages or a CDN bucket and that is the whole deployment.&lt;/p&gt;
&lt;p&gt;I wrote my own because the existing ones do not compose the way I want. Zola, Hugo, Jekyll, Eleventy, and mdBook are all fine. Each has a paint-yourself-into-a-corner moment for some thing I wanted to do (multi-collection sites with their own templates, fingerprinted assets and Sass without a Node toolchain, a search index I controlled the shape of, an embedded default theme that needs no separate clone step). bamboo started as a small tool to host one site and accreted features until it could host the four I care about.&lt;/p&gt;
&lt;h2 id=&quot;shape-builder-renderer-cli&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#shape-builder-renderer-cli&quot;&gt;#&lt;/a&gt;Shape: builder, renderer, CLI&lt;/h2&gt;
&lt;p&gt;bamboo splits cleanly into three pieces.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;SiteBuilder&lt;/code&gt; reads a source directory and produces an in-memory &lt;code&gt;Site&lt;/code&gt;. &lt;code&gt;ThemeEngine&lt;/code&gt; consumes that &lt;code&gt;Site&lt;/code&gt; and renders to disk. The CLI ties them together with &lt;code&gt;clap&lt;/code&gt; for argument parsing and a &lt;code&gt;notify&lt;/code&gt; watcher for live reload.&lt;/p&gt;
&lt;p&gt;The split matters because it makes the library usable as a library. You can build the &lt;code&gt;Site&lt;/code&gt;, mutate it (drop drafts, reorder posts, attach extra metadata), then hand it to a different renderer. The &lt;code&gt;Site&lt;/code&gt; type is the IR:&lt;/p&gt;
&lt;div class=&quot;bamboo-code-block&quot; data-bamboo-code data-bamboo-lang=&quot;rust&quot;&gt;&lt;div class=&quot;bamboo-code-toolbar&quot;&gt;&lt;button type=&quot;button&quot; class=&quot;bamboo-code-button&quot; data-bamboo-line-toggle aria-label=&quot;Toggle line numbers&quot; aria-pressed=&quot;false&quot; title=&quot;Toggle line numbers&quot;&gt;&lt;svg class=&quot;bamboo-code-icon&quot; viewBox=&quot;0 0 20 20&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;1.6&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M4 5h2M4 10h2M4 15h2&quot; stroke-linecap=&quot;round&quot;/&gt;&lt;path d=&quot;M9 5h7M9 10h7M9 15h7&quot; stroke-linecap=&quot;round&quot;/&gt;&lt;/svg&gt;&lt;/button&gt;&lt;button type=&quot;button&quot; class=&quot;bamboo-code-button&quot; data-bamboo-copy aria-label=&quot;Copy code&quot; title=&quot;Copy code&quot;&gt;&lt;svg class=&quot;bamboo-code-icon bamboo-code-icon-copy&quot; viewBox=&quot;0 0 20 20&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;1.6&quot; aria-hidden=&quot;true&quot;&gt;&lt;rect x=&quot;7&quot; y=&quot;3&quot; width=&quot;10&quot; height=&quot;12&quot; rx=&quot;2&quot;/&gt;&lt;path d=&quot;M5 7v8a2 2 0 0 0 2 2h6&quot;/&gt;&lt;/svg&gt;&lt;svg class=&quot;bamboo-code-icon bamboo-code-icon-check&quot; viewBox=&quot;0 0 20 20&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;2&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M4 10l4 4 8-8&quot; stroke-linecap=&quot;round&quot; stroke-linejoin=&quot;round&quot;/&gt;&lt;/svg&gt;&lt;/button&gt;&lt;/div&gt;&lt;pre style=&quot;background-color:#2b303b;color:#c0c5ce;&quot;&gt;&lt;code class=&quot;language-rust&quot;&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub struct &lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;Site {
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;config&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;: SiteConfig,
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;home&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;: Option&amp;lt;Page&amp;gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;pages&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;: Vec&amp;lt;Page&amp;gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;posts&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;: Vec&amp;lt;Post&amp;gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;collections&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;: HashMap&amp;lt;String, Collection&amp;gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;data&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;: HashMap&amp;lt;String, Value&amp;gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;assets&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;: Vec&amp;lt;Asset&amp;gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Every field is &lt;code&gt;pub&lt;/code&gt;. The &lt;code&gt;Page&lt;/code&gt;/&lt;code&gt;Post&lt;/code&gt;/&lt;code&gt;Collection&lt;/code&gt; types all flatten a &lt;code&gt;Content&lt;/code&gt; substruct in via &lt;code&gt;#[serde(flatten)]&lt;/code&gt;, so templates see the inner fields directly instead of having to walk through &lt;code&gt;content.title&lt;/code&gt;. That flattening turns the struct nesting into a flat shape in the Tera context, which is what authors actually want when they write &lt;code&gt;{{ post.title }}&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id=&quot;reading-the-content-tree&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#reading-the-content-tree&quot;&gt;#&lt;/a&gt;Reading the content tree&lt;/h2&gt;
&lt;p&gt;The content walker is &lt;a href=&quot;https://docs.rs/walkdir&quot;&gt;walkdir&lt;/a&gt; with a filter chain: keep files only, keep &lt;code&gt;.md&lt;/code&gt; extension only, skip filenames starting with &lt;code&gt;_&lt;/code&gt; except &lt;code&gt;_index.md&lt;/code&gt;, skip the &lt;code&gt;posts/&lt;/code&gt; directory (handled separately), skip any directory holding a &lt;code&gt;_collection.toml&lt;/code&gt;. Sort the result lexically for deterministic output. Parse each file in parallel with rayon:&lt;/p&gt;
&lt;div class=&quot;bamboo-code-block&quot; data-bamboo-code data-bamboo-lang=&quot;rust&quot;&gt;&lt;div class=&quot;bamboo-code-toolbar&quot;&gt;&lt;button type=&quot;button&quot; class=&quot;bamboo-code-button&quot; data-bamboo-line-toggle aria-label=&quot;Toggle line numbers&quot; aria-pressed=&quot;false&quot; title=&quot;Toggle line numbers&quot;&gt;&lt;svg class=&quot;bamboo-code-icon&quot; viewBox=&quot;0 0 20 20&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;1.6&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M4 5h2M4 10h2M4 15h2&quot; stroke-linecap=&quot;round&quot;/&gt;&lt;path d=&quot;M9 5h7M9 10h7M9 15h7&quot; stroke-linecap=&quot;round&quot;/&gt;&lt;/svg&gt;&lt;/button&gt;&lt;button type=&quot;button&quot; class=&quot;bamboo-code-button&quot; data-bamboo-copy aria-label=&quot;Copy code&quot; title=&quot;Copy code&quot;&gt;&lt;svg class=&quot;bamboo-code-icon bamboo-code-icon-copy&quot; viewBox=&quot;0 0 20 20&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;1.6&quot; aria-hidden=&quot;true&quot;&gt;&lt;rect x=&quot;7&quot; y=&quot;3&quot; width=&quot;10&quot; height=&quot;12&quot; rx=&quot;2&quot;/&gt;&lt;path d=&quot;M5 7v8a2 2 0 0 0 2 2h6&quot;/&gt;&lt;/svg&gt;&lt;svg class=&quot;bamboo-code-icon bamboo-code-icon-check&quot; viewBox=&quot;0 0 20 20&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;2&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M4 10l4 4 8-8&quot; stroke-linecap=&quot;round&quot; stroke-linejoin=&quot;round&quot;/&gt;&lt;/svg&gt;&lt;/button&gt;&lt;/div&gt;&lt;pre style=&quot;background-color:#2b303b;color:#c0c5ce;&quot;&gt;&lt;code class=&quot;language-rust&quot;&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt; parsed_pages: Vec&amp;lt;(Page, PathBuf, PathBuf)&amp;gt; = file_entries
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    .&lt;/span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;par_iter&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;()
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    .&lt;/span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;map&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(|(&lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;path&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;relative&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;)| {
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt; page = &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;parse_page&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(path, relative)?;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        Ok((page, path.&lt;/span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;clone&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(), relative.&lt;/span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;clone&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;()))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    })
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    .collect::&amp;lt;Result&amp;lt;Vec&amp;lt;_&amp;gt;&amp;gt;&amp;gt;()?;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;For this site (a few dozen posts) the parallel parse is barely measurable, but it scales to hundreds of files without effort and the call site stays trivial.&lt;/p&gt;
&lt;p&gt;The same module finds collections (every top-level directory under &lt;code&gt;content/&lt;/code&gt; with a &lt;code&gt;_collection.toml&lt;/code&gt; is one), data files (&lt;code&gt;data/**/*.{toml,yaml,json}&lt;/code&gt;, nested directories become nested maps), and static assets (&lt;code&gt;static/**/*&lt;/code&gt; copied verbatim).&lt;/p&gt;
&lt;h2 id=&quot;frontmatter&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#frontmatter&quot;&gt;#&lt;/a&gt;Frontmatter&lt;/h2&gt;
&lt;p&gt;A bamboo content file looks like this:&lt;/p&gt;
&lt;div class=&quot;bamboo-code-block&quot; data-bamboo-code data-bamboo-lang=&quot;markdown&quot;&gt;&lt;div class=&quot;bamboo-code-toolbar&quot;&gt;&lt;button type=&quot;button&quot; class=&quot;bamboo-code-button&quot; data-bamboo-line-toggle aria-label=&quot;Toggle line numbers&quot; aria-pressed=&quot;false&quot; title=&quot;Toggle line numbers&quot;&gt;&lt;svg class=&quot;bamboo-code-icon&quot; viewBox=&quot;0 0 20 20&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;1.6&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M4 5h2M4 10h2M4 15h2&quot; stroke-linecap=&quot;round&quot;/&gt;&lt;path d=&quot;M9 5h7M9 10h7M9 15h7&quot; stroke-linecap=&quot;round&quot;/&gt;&lt;/svg&gt;&lt;/button&gt;&lt;button type=&quot;button&quot; class=&quot;bamboo-code-button&quot; data-bamboo-copy aria-label=&quot;Copy code&quot; title=&quot;Copy code&quot;&gt;&lt;svg class=&quot;bamboo-code-icon bamboo-code-icon-copy&quot; viewBox=&quot;0 0 20 20&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;1.6&quot; aria-hidden=&quot;true&quot;&gt;&lt;rect x=&quot;7&quot; y=&quot;3&quot; width=&quot;10&quot; height=&quot;12&quot; rx=&quot;2&quot;/&gt;&lt;path d=&quot;M5 7v8a2 2 0 0 0 2 2h6&quot;/&gt;&lt;/svg&gt;&lt;svg class=&quot;bamboo-code-icon bamboo-code-icon-check&quot; viewBox=&quot;0 0 20 20&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;2&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M4 10l4 4 8-8&quot; stroke-linecap=&quot;round&quot; stroke-linejoin=&quot;round&quot;/&gt;&lt;/svg&gt;&lt;/button&gt;&lt;/div&gt;&lt;pre style=&quot;background-color:#2b303b;color:#c0c5ce;&quot;&gt;&lt;code class=&quot;language-markdown&quot;&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;+++
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;title = &amp;quot;My Post&amp;quot;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;date = &amp;quot;2024-01-15&amp;quot;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;tags = [&amp;quot;rust&amp;quot;]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;+++
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;Body markdown.
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;TOML between &lt;code&gt;+++&lt;/code&gt;, or YAML between &lt;code&gt;---&lt;/code&gt;. The parser scans line-by-line for the closing delimiter, hands the slice to &lt;code&gt;toml::from_str&lt;/code&gt; or &lt;code&gt;serde_yml::from_str&lt;/code&gt;, and gets back a &lt;code&gt;HashMap&amp;lt;String, serde_json::Value&amp;gt;&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;bamboo-code-block&quot; data-bamboo-code data-bamboo-lang=&quot;rust&quot;&gt;&lt;div class=&quot;bamboo-code-toolbar&quot;&gt;&lt;button type=&quot;button&quot; class=&quot;bamboo-code-button&quot; data-bamboo-line-toggle aria-label=&quot;Toggle line numbers&quot; aria-pressed=&quot;false&quot; title=&quot;Toggle line numbers&quot;&gt;&lt;svg class=&quot;bamboo-code-icon&quot; viewBox=&quot;0 0 20 20&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;1.6&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M4 5h2M4 10h2M4 15h2&quot; stroke-linecap=&quot;round&quot;/&gt;&lt;path d=&quot;M9 5h7M9 10h7M9 15h7&quot; stroke-linecap=&quot;round&quot;/&gt;&lt;/svg&gt;&lt;/button&gt;&lt;button type=&quot;button&quot; class=&quot;bamboo-code-button&quot; data-bamboo-copy aria-label=&quot;Copy code&quot; title=&quot;Copy code&quot;&gt;&lt;svg class=&quot;bamboo-code-icon bamboo-code-icon-copy&quot; viewBox=&quot;0 0 20 20&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;1.6&quot; aria-hidden=&quot;true&quot;&gt;&lt;rect x=&quot;7&quot; y=&quot;3&quot; width=&quot;10&quot; height=&quot;12&quot; rx=&quot;2&quot;/&gt;&lt;path d=&quot;M5 7v8a2 2 0 0 0 2 2h6&quot;/&gt;&lt;/svg&gt;&lt;svg class=&quot;bamboo-code-icon bamboo-code-icon-check&quot; viewBox=&quot;0 0 20 20&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;2&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M4 10l4 4 8-8&quot; stroke-linecap=&quot;round&quot; stroke-linejoin=&quot;round&quot;/&gt;&lt;/svg&gt;&lt;/button&gt;&lt;/div&gt;&lt;pre style=&quot;background-color:#2b303b;color:#c0c5ce;&quot;&gt;&lt;code class=&quot;language-rust&quot;&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub struct &lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;Frontmatter {
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    #[serde(flatten)]
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;raw&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;: HashMap&amp;lt;String, Value&amp;gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The &lt;code&gt;Value&lt;/code&gt; map preserves every field the author wrote, known or not. Templates can reach for arbitrary &lt;code&gt;{{ post.frontmatter.whatever }}&lt;/code&gt; keys, which is the only way I have found to let authors invent new conventions without editing the schema in the SSG.&lt;/p&gt;
&lt;p&gt;Dates can also live in the filename. A file named &lt;code&gt;2024-01-15-hello.md&lt;/code&gt; parses out &lt;code&gt;2024-01-15&lt;/code&gt; as the date and &lt;code&gt;hello&lt;/code&gt; as the slug. The function in &lt;code&gt;parsing.rs&lt;/code&gt; returns &lt;code&gt;Option&lt;/code&gt; so a short filename like &lt;code&gt;about.md&lt;/code&gt; falls through harmlessly:&lt;/p&gt;
&lt;div class=&quot;bamboo-code-block&quot; data-bamboo-code data-bamboo-lang=&quot;rust&quot;&gt;&lt;div class=&quot;bamboo-code-toolbar&quot;&gt;&lt;button type=&quot;button&quot; class=&quot;bamboo-code-button&quot; data-bamboo-line-toggle aria-label=&quot;Toggle line numbers&quot; aria-pressed=&quot;false&quot; title=&quot;Toggle line numbers&quot;&gt;&lt;svg class=&quot;bamboo-code-icon&quot; viewBox=&quot;0 0 20 20&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;1.6&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M4 5h2M4 10h2M4 15h2&quot; stroke-linecap=&quot;round&quot;/&gt;&lt;path d=&quot;M9 5h7M9 10h7M9 15h7&quot; stroke-linecap=&quot;round&quot;/&gt;&lt;/svg&gt;&lt;/button&gt;&lt;button type=&quot;button&quot; class=&quot;bamboo-code-button&quot; data-bamboo-copy aria-label=&quot;Copy code&quot; title=&quot;Copy code&quot;&gt;&lt;svg class=&quot;bamboo-code-icon bamboo-code-icon-copy&quot; viewBox=&quot;0 0 20 20&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;1.6&quot; aria-hidden=&quot;true&quot;&gt;&lt;rect x=&quot;7&quot; y=&quot;3&quot; width=&quot;10&quot; height=&quot;12&quot; rx=&quot;2&quot;/&gt;&lt;path d=&quot;M5 7v8a2 2 0 0 0 2 2h6&quot;/&gt;&lt;/svg&gt;&lt;svg class=&quot;bamboo-code-icon bamboo-code-icon-check&quot; viewBox=&quot;0 0 20 20&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;2&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M4 10l4 4 8-8&quot; stroke-linecap=&quot;round&quot; stroke-linejoin=&quot;round&quot;/&gt;&lt;/svg&gt;&lt;/button&gt;&lt;/div&gt;&lt;pre style=&quot;background-color:#2b303b;color:#c0c5ce;&quot;&gt;&lt;code class=&quot;language-rust&quot;&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub fn &lt;/span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;parse_date_from_filename&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;filename&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;: &amp;amp;&lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;str&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;) -&amp;gt; Option&amp;lt;(String, String)&amp;gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt; name = filename.&lt;/span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;strip_suffix&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;.md&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;&amp;quot;).&lt;/span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;unwrap_or&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(filename);
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt; date_part = name.&lt;/span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;get&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(..&lt;/span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;10&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;)?;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    ...
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;name.get(..10)?&lt;/code&gt; matters. If &lt;code&gt;name&lt;/code&gt; is shorter than 10 bytes the slice is &lt;code&gt;None&lt;/code&gt; and the function returns immediately rather than panicking on out-of-range indexing.&lt;/p&gt;
&lt;h2 id=&quot;markdown-rendering&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#markdown-rendering&quot;&gt;#&lt;/a&gt;Markdown rendering&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://docs.rs/pulldown-cmark&quot;&gt;pulldown-cmark&lt;/a&gt; is the parser. It emits an event stream of &lt;code&gt;Start(Tag::Heading)&lt;/code&gt;, &lt;code&gt;Text&lt;/code&gt;, &lt;code&gt;Code&lt;/code&gt;, &lt;code&gt;Start(Tag::CodeBlock)&lt;/code&gt;, etc. bamboo does not use the convenience &lt;code&gt;html::push_html&lt;/code&gt; on the entire stream because two things need custom handling: code blocks and headings.&lt;/p&gt;
&lt;p&gt;Code blocks need syntax highlighting. The stream looks like &lt;code&gt;Start(CodeBlock(Fenced(lang)))&lt;/code&gt; → many &lt;code&gt;Text&lt;/code&gt; events → &lt;code&gt;End(CodeBlock)&lt;/code&gt;. bamboo accumulates the text into a buffer and hands it to syntect at the end event:&lt;/p&gt;
&lt;div class=&quot;bamboo-code-block&quot; data-bamboo-code data-bamboo-lang=&quot;rust&quot;&gt;&lt;div class=&quot;bamboo-code-toolbar&quot;&gt;&lt;button type=&quot;button&quot; class=&quot;bamboo-code-button&quot; data-bamboo-line-toggle aria-label=&quot;Toggle line numbers&quot; aria-pressed=&quot;false&quot; title=&quot;Toggle line numbers&quot;&gt;&lt;svg class=&quot;bamboo-code-icon&quot; viewBox=&quot;0 0 20 20&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;1.6&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M4 5h2M4 10h2M4 15h2&quot; stroke-linecap=&quot;round&quot;/&gt;&lt;path d=&quot;M9 5h7M9 10h7M9 15h7&quot; stroke-linecap=&quot;round&quot;/&gt;&lt;/svg&gt;&lt;/button&gt;&lt;button type=&quot;button&quot; class=&quot;bamboo-code-button&quot; data-bamboo-copy aria-label=&quot;Copy code&quot; title=&quot;Copy code&quot;&gt;&lt;svg class=&quot;bamboo-code-icon bamboo-code-icon-copy&quot; viewBox=&quot;0 0 20 20&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;1.6&quot; aria-hidden=&quot;true&quot;&gt;&lt;rect x=&quot;7&quot; y=&quot;3&quot; width=&quot;10&quot; height=&quot;12&quot; rx=&quot;2&quot;/&gt;&lt;path d=&quot;M5 7v8a2 2 0 0 0 2 2h6&quot;/&gt;&lt;/svg&gt;&lt;svg class=&quot;bamboo-code-icon bamboo-code-icon-check&quot; viewBox=&quot;0 0 20 20&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;2&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M4 10l4 4 8-8&quot; stroke-linecap=&quot;round&quot; stroke-linejoin=&quot;round&quot;/&gt;&lt;/svg&gt;&lt;/button&gt;&lt;/div&gt;&lt;pre style=&quot;background-color:#2b303b;color:#c0c5ce;&quot;&gt;&lt;code class=&quot;language-rust&quot;&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;Event::End(TagEnd::CodeBlock) =&amp;gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    in_code_block = &lt;/span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;false&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt; highlighted = &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;if let &lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;Some(&lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;ref&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt; lang) = code_block_lang {
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;.syntax_set
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;            .&lt;/span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;find_syntax_by_token&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(lang)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;            .&lt;/span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;map&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(|&lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;syntax&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;| {
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;                &lt;/span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;highlighted_html_for_string&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;                    &amp;amp;code_block_content,
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;                    &amp;amp;&lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;.syntax_set,
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;                    syntax,
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;                    theme,
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;                )
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;                .&lt;/span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;unwrap_or_else&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(|_| &lt;/span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;escape_html&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(&amp;amp;code_block_content))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;            })
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;            ...
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Headings need anchor links so URLs can point at sections. The renderer slugifies the heading text, dedupes against a &lt;code&gt;HashSet&amp;lt;String&amp;gt;&lt;/code&gt; of already-emitted ids so two &lt;code&gt;## Setup&lt;/code&gt; headings produce &lt;code&gt;setup&lt;/code&gt; and &lt;code&gt;setup-1&lt;/code&gt;, and emits:&lt;/p&gt;
&lt;div class=&quot;bamboo-code-block&quot; data-bamboo-code data-bamboo-lang=&quot;html&quot;&gt;&lt;div class=&quot;bamboo-code-toolbar&quot;&gt;&lt;button type=&quot;button&quot; class=&quot;bamboo-code-button&quot; data-bamboo-line-toggle aria-label=&quot;Toggle line numbers&quot; aria-pressed=&quot;false&quot; title=&quot;Toggle line numbers&quot;&gt;&lt;svg class=&quot;bamboo-code-icon&quot; viewBox=&quot;0 0 20 20&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;1.6&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M4 5h2M4 10h2M4 15h2&quot; stroke-linecap=&quot;round&quot;/&gt;&lt;path d=&quot;M9 5h7M9 10h7M9 15h7&quot; stroke-linecap=&quot;round&quot;/&gt;&lt;/svg&gt;&lt;/button&gt;&lt;button type=&quot;button&quot; class=&quot;bamboo-code-button&quot; data-bamboo-copy aria-label=&quot;Copy code&quot; title=&quot;Copy code&quot;&gt;&lt;svg class=&quot;bamboo-code-icon bamboo-code-icon-copy&quot; viewBox=&quot;0 0 20 20&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;1.6&quot; aria-hidden=&quot;true&quot;&gt;&lt;rect x=&quot;7&quot; y=&quot;3&quot; width=&quot;10&quot; height=&quot;12&quot; rx=&quot;2&quot;/&gt;&lt;path d=&quot;M5 7v8a2 2 0 0 0 2 2h6&quot;/&gt;&lt;/svg&gt;&lt;svg class=&quot;bamboo-code-icon bamboo-code-icon-check&quot; viewBox=&quot;0 0 20 20&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;2&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M4 10l4 4 8-8&quot; stroke-linecap=&quot;round&quot; stroke-linejoin=&quot;round&quot;/&gt;&lt;/svg&gt;&lt;/button&gt;&lt;/div&gt;&lt;pre style=&quot;background-color:#2b303b;color:#c0c5ce;&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;h2 &lt;/span&gt;&lt;span style=&quot;color:#8fa1b3;&quot;&gt;id&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;=&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;setup&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;&amp;quot;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;a &lt;/span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;class&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;=&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;anchor&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;&amp;quot; &lt;/span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;href&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;=&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;#setup&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;&amp;quot;&amp;gt;#&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;a&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;&amp;gt;Setup&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;h2&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;It also pushes every heading into a &lt;code&gt;Vec&amp;lt;TocEntry&amp;gt;&lt;/code&gt; so templates can render a table of contents without re-parsing. The TOC is just &lt;code&gt;(level, id, title)&lt;/code&gt; triples.&lt;/p&gt;
&lt;h2 id=&quot;shortcodes&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#shortcodes&quot;&gt;#&lt;/a&gt;Shortcodes&lt;/h2&gt;
&lt;p&gt;Plain markdown is fine for prose, awful for &quot;embed a youtube video&quot; or &quot;show a notice box.&quot; Hugo-style shortcodes fill that gap:&lt;/p&gt;
&lt;div class=&quot;bamboo-code-block&quot; data-bamboo-code&gt;&lt;div class=&quot;bamboo-code-toolbar&quot;&gt;&lt;button type=&quot;button&quot; class=&quot;bamboo-code-button&quot; data-bamboo-line-toggle aria-label=&quot;Toggle line numbers&quot; aria-pressed=&quot;false&quot; title=&quot;Toggle line numbers&quot;&gt;&lt;svg class=&quot;bamboo-code-icon&quot; viewBox=&quot;0 0 20 20&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;1.6&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M4 5h2M4 10h2M4 15h2&quot; stroke-linecap=&quot;round&quot;/&gt;&lt;path d=&quot;M9 5h7M9 10h7M9 15h7&quot; stroke-linecap=&quot;round&quot;/&gt;&lt;/svg&gt;&lt;/button&gt;&lt;button type=&quot;button&quot; class=&quot;bamboo-code-button&quot; data-bamboo-copy aria-label=&quot;Copy code&quot; title=&quot;Copy code&quot;&gt;&lt;svg class=&quot;bamboo-code-icon bamboo-code-icon-copy&quot; viewBox=&quot;0 0 20 20&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;1.6&quot; aria-hidden=&quot;true&quot;&gt;&lt;rect x=&quot;7&quot; y=&quot;3&quot; width=&quot;10&quot; height=&quot;12&quot; rx=&quot;2&quot;/&gt;&lt;path d=&quot;M5 7v8a2 2 0 0 0 2 2h6&quot;/&gt;&lt;/svg&gt;&lt;svg class=&quot;bamboo-code-icon bamboo-code-icon-check&quot; viewBox=&quot;0 0 20 20&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;2&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M4 10l4 4 8-8&quot; stroke-linecap=&quot;round&quot; stroke-linejoin=&quot;round&quot;/&gt;&lt;/svg&gt;&lt;/button&gt;&lt;/div&gt;&lt;pre style=&quot;background-color:#2b303b;color:#c0c5ce;&quot;&gt;&lt;code&gt;&lt;span class=&quot;bamboo-line&quot;&gt;{{&amp;lt; youtube id=&amp;quot;dQw4w9WgXcQ&amp;quot; &amp;gt;}}
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Two flavors. The inline form has no body; the block form wraps markdown content between an opening and matching closing tag:&lt;/p&gt;
&lt;div class=&quot;bamboo-code-block&quot; data-bamboo-code&gt;&lt;div class=&quot;bamboo-code-toolbar&quot;&gt;&lt;button type=&quot;button&quot; class=&quot;bamboo-code-button&quot; data-bamboo-line-toggle aria-label=&quot;Toggle line numbers&quot; aria-pressed=&quot;false&quot; title=&quot;Toggle line numbers&quot;&gt;&lt;svg class=&quot;bamboo-code-icon&quot; viewBox=&quot;0 0 20 20&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;1.6&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M4 5h2M4 10h2M4 15h2&quot; stroke-linecap=&quot;round&quot;/&gt;&lt;path d=&quot;M9 5h7M9 10h7M9 15h7&quot; stroke-linecap=&quot;round&quot;/&gt;&lt;/svg&gt;&lt;/button&gt;&lt;button type=&quot;button&quot; class=&quot;bamboo-code-button&quot; data-bamboo-copy aria-label=&quot;Copy code&quot; title=&quot;Copy code&quot;&gt;&lt;svg class=&quot;bamboo-code-icon bamboo-code-icon-copy&quot; viewBox=&quot;0 0 20 20&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;1.6&quot; aria-hidden=&quot;true&quot;&gt;&lt;rect x=&quot;7&quot; y=&quot;3&quot; width=&quot;10&quot; height=&quot;12&quot; rx=&quot;2&quot;/&gt;&lt;path d=&quot;M5 7v8a2 2 0 0 0 2 2h6&quot;/&gt;&lt;/svg&gt;&lt;svg class=&quot;bamboo-code-icon bamboo-code-icon-check&quot; viewBox=&quot;0 0 20 20&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;2&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M4 10l4 4 8-8&quot; stroke-linecap=&quot;round&quot; stroke-linejoin=&quot;round&quot;/&gt;&lt;/svg&gt;&lt;/button&gt;&lt;/div&gt;&lt;pre style=&quot;background-color:#2b303b;color:#c0c5ce;&quot;&gt;&lt;code&gt;&lt;span class=&quot;bamboo-line&quot;&gt;inline:  {{&amp;lt; name arg=&amp;quot;value&amp;quot; &amp;gt;}}
&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;block:   {{% name arg=&amp;quot;value&amp;quot; %}}
&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;         body markdown
&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;         {{% /name %}}
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The shortcode processor runs &lt;em&gt;before&lt;/em&gt; pulldown-cmark, scans the text for tags, replaces each with its rendered Tera template, and hands the result forward. Block bodies are themselves rendered through markdown first, so:&lt;/p&gt;
&lt;div class=&quot;bamboo-code-block&quot; data-bamboo-code&gt;&lt;div class=&quot;bamboo-code-toolbar&quot;&gt;&lt;button type=&quot;button&quot; class=&quot;bamboo-code-button&quot; data-bamboo-line-toggle aria-label=&quot;Toggle line numbers&quot; aria-pressed=&quot;false&quot; title=&quot;Toggle line numbers&quot;&gt;&lt;svg class=&quot;bamboo-code-icon&quot; viewBox=&quot;0 0 20 20&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;1.6&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M4 5h2M4 10h2M4 15h2&quot; stroke-linecap=&quot;round&quot;/&gt;&lt;path d=&quot;M9 5h7M9 10h7M9 15h7&quot; stroke-linecap=&quot;round&quot;/&gt;&lt;/svg&gt;&lt;/button&gt;&lt;button type=&quot;button&quot; class=&quot;bamboo-code-button&quot; data-bamboo-copy aria-label=&quot;Copy code&quot; title=&quot;Copy code&quot;&gt;&lt;svg class=&quot;bamboo-code-icon bamboo-code-icon-copy&quot; viewBox=&quot;0 0 20 20&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;1.6&quot; aria-hidden=&quot;true&quot;&gt;&lt;rect x=&quot;7&quot; y=&quot;3&quot; width=&quot;10&quot; height=&quot;12&quot; rx=&quot;2&quot;/&gt;&lt;path d=&quot;M5 7v8a2 2 0 0 0 2 2h6&quot;/&gt;&lt;/svg&gt;&lt;svg class=&quot;bamboo-code-icon bamboo-code-icon-check&quot; viewBox=&quot;0 0 20 20&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;2&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M4 10l4 4 8-8&quot; stroke-linecap=&quot;round&quot; stroke-linejoin=&quot;round&quot;/&gt;&lt;/svg&gt;&lt;/button&gt;&lt;/div&gt;&lt;pre style=&quot;background-color:#2b303b;color:#c0c5ce;&quot;&gt;&lt;code&gt;&lt;span class=&quot;bamboo-line&quot;&gt;{{% note type=&amp;quot;info&amp;quot; %}}
&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;This is **emphasized**.
&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;{{% /note %}}
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;emits a note containing &lt;code&gt;&amp;lt;strong&amp;gt;emphasized&amp;lt;/strong&amp;gt;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The processor tracks fenced code blocks (triple-backtick and triple-tilde) so a shortcode tag inside a code block stays literal. It does &lt;em&gt;not&lt;/em&gt; track inline single-backtick code spans, which means an inline-code example of an opening shortcode delimiter in prose still gets parsed as a real shortcode and triggers a hard error. I noticed this writing the draft of this post — the first build failed on a one-liner mention of the delimiter in flowing text, and the fix was to move every shortcode example into a fenced block instead. The scanning is hand-rolled because the shortcode pass runs before pulldown-cmark, so I cannot lean on its code-fence detection. Properly handling inline backticks belongs on the same list.&lt;/p&gt;
&lt;p&gt;One special shortcode renders no template:&lt;/p&gt;
&lt;div class=&quot;bamboo-code-block&quot; data-bamboo-code&gt;&lt;div class=&quot;bamboo-code-toolbar&quot;&gt;&lt;button type=&quot;button&quot; class=&quot;bamboo-code-button&quot; data-bamboo-line-toggle aria-label=&quot;Toggle line numbers&quot; aria-pressed=&quot;false&quot; title=&quot;Toggle line numbers&quot;&gt;&lt;svg class=&quot;bamboo-code-icon&quot; viewBox=&quot;0 0 20 20&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;1.6&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M4 5h2M4 10h2M4 15h2&quot; stroke-linecap=&quot;round&quot;/&gt;&lt;path d=&quot;M9 5h7M9 10h7M9 15h7&quot; stroke-linecap=&quot;round&quot;/&gt;&lt;/svg&gt;&lt;/button&gt;&lt;button type=&quot;button&quot; class=&quot;bamboo-code-button&quot; data-bamboo-copy aria-label=&quot;Copy code&quot; title=&quot;Copy code&quot;&gt;&lt;svg class=&quot;bamboo-code-icon bamboo-code-icon-copy&quot; viewBox=&quot;0 0 20 20&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;1.6&quot; aria-hidden=&quot;true&quot;&gt;&lt;rect x=&quot;7&quot; y=&quot;3&quot; width=&quot;10&quot; height=&quot;12&quot; rx=&quot;2&quot;/&gt;&lt;path d=&quot;M5 7v8a2 2 0 0 0 2 2h6&quot;/&gt;&lt;/svg&gt;&lt;svg class=&quot;bamboo-code-icon bamboo-code-icon-check&quot; viewBox=&quot;0 0 20 20&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;2&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M4 10l4 4 8-8&quot; stroke-linecap=&quot;round&quot; stroke-linejoin=&quot;round&quot;/&gt;&lt;/svg&gt;&lt;/button&gt;&lt;/div&gt;&lt;pre style=&quot;background-color:#2b303b;color:#c0c5ce;&quot;&gt;&lt;code&gt;&lt;span class=&quot;bamboo-line&quot;&gt;{{&amp;lt; ref &amp;quot;post-name.md&amp;quot; &amp;gt;}}
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;It resolves a source-path to the URL its content will deploy at. A registry is built during the initial content walk that maps source paths to final URLs, including &lt;code&gt;permalink&lt;/code&gt; overrides. Internal links survive renames and custom permalinks through this indirection.&lt;/p&gt;
&lt;h2 id=&quot;templates&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#templates&quot;&gt;#&lt;/a&gt;Templates&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://keats.github.io/tera/&quot;&gt;Tera&lt;/a&gt; is the templating engine. Jinja2-style: inheritance, includes, filters, macros. Every page handed to the renderer gets a Tera context containing the full &lt;code&gt;Site&lt;/code&gt; plus the page itself plus a few extras (pagination state, related posts, prev/next post for blog entries).&lt;/p&gt;
&lt;p&gt;The built-in default theme is embedded into the binary with &lt;code&gt;include_str!&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;bamboo-code-block&quot; data-bamboo-code data-bamboo-lang=&quot;rust&quot;&gt;&lt;div class=&quot;bamboo-code-toolbar&quot;&gt;&lt;button type=&quot;button&quot; class=&quot;bamboo-code-button&quot; data-bamboo-line-toggle aria-label=&quot;Toggle line numbers&quot; aria-pressed=&quot;false&quot; title=&quot;Toggle line numbers&quot;&gt;&lt;svg class=&quot;bamboo-code-icon&quot; viewBox=&quot;0 0 20 20&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;1.6&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M4 5h2M4 10h2M4 15h2&quot; stroke-linecap=&quot;round&quot;/&gt;&lt;path d=&quot;M9 5h7M9 10h7M9 15h7&quot; stroke-linecap=&quot;round&quot;/&gt;&lt;/svg&gt;&lt;/button&gt;&lt;button type=&quot;button&quot; class=&quot;bamboo-code-button&quot; data-bamboo-copy aria-label=&quot;Copy code&quot; title=&quot;Copy code&quot;&gt;&lt;svg class=&quot;bamboo-code-icon bamboo-code-icon-copy&quot; viewBox=&quot;0 0 20 20&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;1.6&quot; aria-hidden=&quot;true&quot;&gt;&lt;rect x=&quot;7&quot; y=&quot;3&quot; width=&quot;10&quot; height=&quot;12&quot; rx=&quot;2&quot;/&gt;&lt;path d=&quot;M5 7v8a2 2 0 0 0 2 2h6&quot;/&gt;&lt;/svg&gt;&lt;svg class=&quot;bamboo-code-icon bamboo-code-icon-check&quot; viewBox=&quot;0 0 20 20&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;2&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M4 10l4 4 8-8&quot; stroke-linecap=&quot;round&quot; stroke-linejoin=&quot;round&quot;/&gt;&lt;/svg&gt;&lt;/button&gt;&lt;/div&gt;&lt;pre style=&quot;background-color:#2b303b;color:#c0c5ce;&quot;&gt;&lt;code class=&quot;language-rust&quot;&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;const &lt;/span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;DEFAULT_BASE_TEMPLATE&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;: &amp;amp;&lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;str &lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;= include_str!(&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;../themes/default/templates/base.html&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;&amp;quot;);
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;const &lt;/span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;DEFAULT_INDEX_TEMPLATE&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;: &amp;amp;&lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;str &lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;= include_str!(&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;../themes/default/templates/index.html&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;&amp;quot;);
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;const &lt;/span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;DEFAULT_PAGE_TEMPLATE&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;: &amp;amp;&lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;str &lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;= include_str!(&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;../themes/default/templates/page.html&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;&amp;quot;);
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;const &lt;/span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;DEFAULT_POST_TEMPLATE&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;: &amp;amp;&lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;str &lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;= include_str!(&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;../themes/default/templates/post.html&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;&amp;quot;);
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;...
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;A fresh &lt;code&gt;Tera::default()&lt;/code&gt; gets each one stuffed in with &lt;code&gt;add_raw_template&lt;/code&gt;. The upside is &lt;code&gt;cargo install bamboo-cli&lt;/code&gt; produces a working SSG that needs no theme clone step. The downside is templates are not user-editable without dropping override files into the site&apos;s own &lt;code&gt;templates/&lt;/code&gt; directory. Site-level overrides are registered &lt;em&gt;after&lt;/em&gt; the theme, so Tera&apos;s later-registration-wins semantics let them shadow the theme without any priority machinery.&lt;/p&gt;
&lt;p&gt;Custom themes load from a directory pattern instead. The directory layout mirrors the embedded one: &lt;code&gt;templates/&lt;/code&gt;, &lt;code&gt;templates/partials/&lt;/code&gt;, &lt;code&gt;templates/shortcodes/&lt;/code&gt;, and a &lt;code&gt;static/&lt;/code&gt; for theme assets.&lt;/p&gt;
&lt;h2 id=&quot;custom-filters&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#custom-filters&quot;&gt;#&lt;/a&gt;Custom filters&lt;/h2&gt;
&lt;p&gt;Four bamboo-specific Tera filters: &lt;code&gt;slugify&lt;/code&gt;, &lt;code&gt;reading_time&lt;/code&gt;, &lt;code&gt;word_count&lt;/code&gt;, &lt;code&gt;toc&lt;/code&gt;. They live in &lt;code&gt;theme.rs::register_custom_filters&lt;/code&gt; and are plain closures:&lt;/p&gt;
&lt;div class=&quot;bamboo-code-block&quot; data-bamboo-code data-bamboo-lang=&quot;rust&quot;&gt;&lt;div class=&quot;bamboo-code-toolbar&quot;&gt;&lt;button type=&quot;button&quot; class=&quot;bamboo-code-button&quot; data-bamboo-line-toggle aria-label=&quot;Toggle line numbers&quot; aria-pressed=&quot;false&quot; title=&quot;Toggle line numbers&quot;&gt;&lt;svg class=&quot;bamboo-code-icon&quot; viewBox=&quot;0 0 20 20&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;1.6&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M4 5h2M4 10h2M4 15h2&quot; stroke-linecap=&quot;round&quot;/&gt;&lt;path d=&quot;M9 5h7M9 10h7M9 15h7&quot; stroke-linecap=&quot;round&quot;/&gt;&lt;/svg&gt;&lt;/button&gt;&lt;button type=&quot;button&quot; class=&quot;bamboo-code-button&quot; data-bamboo-copy aria-label=&quot;Copy code&quot; title=&quot;Copy code&quot;&gt;&lt;svg class=&quot;bamboo-code-icon bamboo-code-icon-copy&quot; viewBox=&quot;0 0 20 20&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;1.6&quot; aria-hidden=&quot;true&quot;&gt;&lt;rect x=&quot;7&quot; y=&quot;3&quot; width=&quot;10&quot; height=&quot;12&quot; rx=&quot;2&quot;/&gt;&lt;path d=&quot;M5 7v8a2 2 0 0 0 2 2h6&quot;/&gt;&lt;/svg&gt;&lt;svg class=&quot;bamboo-code-icon bamboo-code-icon-check&quot; viewBox=&quot;0 0 20 20&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;2&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M4 10l4 4 8-8&quot; stroke-linecap=&quot;round&quot; stroke-linejoin=&quot;round&quot;/&gt;&lt;/svg&gt;&lt;/button&gt;&lt;/div&gt;&lt;pre style=&quot;background-color:#2b303b;color:#c0c5ce;&quot;&gt;&lt;code class=&quot;language-rust&quot;&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;tera.&lt;/span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;register_filter&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    &amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;slugify&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;&amp;quot;,
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    |&lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;value&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;: &amp;amp;tera::Value, &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;_args&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;: &amp;amp;HashMap&amp;lt;String, tera::Value&amp;gt;| {
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;let&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt; text = value.&lt;/span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;as_str&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;().&lt;/span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;unwrap_or&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(&amp;quot;&amp;quot;);
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;        Ok(tera::Value::String(&lt;/span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;slugify&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(text)))
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    },
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The &lt;code&gt;toc&lt;/code&gt; filter takes the heading list off a post or page and emits a nested &lt;code&gt;&amp;lt;ul&amp;gt;&lt;/code&gt; indented by heading level. It is rendered inside templates with &lt;code&gt;{{ post.toc | toc | safe }}&lt;/code&gt; (Tera&apos;s autoescape makes you opt in with &lt;code&gt;safe&lt;/code&gt; for trusted HTML).&lt;/p&gt;
&lt;h2 id=&quot;parallel-rendering&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#parallel-rendering&quot;&gt;#&lt;/a&gt;Parallel rendering&lt;/h2&gt;
&lt;p&gt;After parsing, the engine renders pages, posts, and collections in parallel with rayon&apos;s &lt;code&gt;par_iter&lt;/code&gt;. Each task writes into its own slot in &lt;code&gt;dist/&lt;/code&gt;, so nothing needs coordination:&lt;/p&gt;
&lt;div class=&quot;bamboo-code-block&quot; data-bamboo-code data-bamboo-lang=&quot;rust&quot;&gt;&lt;div class=&quot;bamboo-code-toolbar&quot;&gt;&lt;button type=&quot;button&quot; class=&quot;bamboo-code-button&quot; data-bamboo-line-toggle aria-label=&quot;Toggle line numbers&quot; aria-pressed=&quot;false&quot; title=&quot;Toggle line numbers&quot;&gt;&lt;svg class=&quot;bamboo-code-icon&quot; viewBox=&quot;0 0 20 20&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;1.6&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M4 5h2M4 10h2M4 15h2&quot; stroke-linecap=&quot;round&quot;/&gt;&lt;path d=&quot;M9 5h7M9 10h7M9 15h7&quot; stroke-linecap=&quot;round&quot;/&gt;&lt;/svg&gt;&lt;/button&gt;&lt;button type=&quot;button&quot; class=&quot;bamboo-code-button&quot; data-bamboo-copy aria-label=&quot;Copy code&quot; title=&quot;Copy code&quot;&gt;&lt;svg class=&quot;bamboo-code-icon bamboo-code-icon-copy&quot; viewBox=&quot;0 0 20 20&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;1.6&quot; aria-hidden=&quot;true&quot;&gt;&lt;rect x=&quot;7&quot; y=&quot;3&quot; width=&quot;10&quot; height=&quot;12&quot; rx=&quot;2&quot;/&gt;&lt;path d=&quot;M5 7v8a2 2 0 0 0 2 2h6&quot;/&gt;&lt;/svg&gt;&lt;svg class=&quot;bamboo-code-icon bamboo-code-icon-check&quot; viewBox=&quot;0 0 20 20&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;2&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M4 10l4 4 8-8&quot; stroke-linecap=&quot;round&quot; stroke-linejoin=&quot;round&quot;/&gt;&lt;/svg&gt;&lt;/button&gt;&lt;/div&gt;&lt;pre style=&quot;background-color:#2b303b;color:#c0c5ce;&quot;&gt;&lt;code class=&quot;language-rust&quot;&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;site.posts.&lt;/span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;par_iter&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;().&lt;/span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;try_for_each&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(|&lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;post&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;| {
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#96b5b4;&quot;&gt;render_post&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;(site, post, prev_post, next_post, output_dir)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;})?;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Templates are registered up front and never mutated afterward. The renderer captures the &lt;code&gt;Tera&lt;/code&gt; instance by reference into each closure. &lt;code&gt;Tera&lt;/code&gt; is &lt;code&gt;Send + Sync&lt;/code&gt;, so the parallel pass works without locks.&lt;/p&gt;
&lt;h2 id=&quot;asset-pipeline&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#asset-pipeline&quot;&gt;#&lt;/a&gt;Asset pipeline&lt;/h2&gt;
&lt;p&gt;Once HTML lands on disk, an optional pass walks &lt;code&gt;output_dir&lt;/code&gt; and runs four kinds of post-processing:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Sass/SCSS compilation (&lt;a href=&quot;https://crates.io/crates/grass&quot;&gt;grass&lt;/a&gt;, a pure-Rust Sass compiler)&lt;/li&gt;
&lt;li&gt;CSS minification (&lt;a href=&quot;https://lightningcss.dev/&quot;&gt;lightningcss&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;JS minification (&lt;a href=&quot;https://crates.io/crates/minify-js&quot;&gt;minify-js&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;HTML minification (&lt;a href=&quot;https://crates.io/crates/minify-html&quot;&gt;minify-html&lt;/a&gt;)&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Plus optional content-hash fingerprinting: each &lt;code&gt;.css&lt;/code&gt; and &lt;code&gt;.js&lt;/code&gt; output gets renamed from &lt;code&gt;style.css&lt;/code&gt; to &lt;code&gt;style.a3f8c91d.css&lt;/code&gt;, and every HTML and XML file gets walked to rewrite references. Cache headers can be aggressive (&lt;code&gt;Cache-Control: public, max-age=31536000, immutable&lt;/code&gt;) after that without breaking deployments.&lt;/p&gt;
&lt;p&gt;The order is load-bearing. Sass → minify CSS/JS → fingerprint → minify HTML. Fingerprinting before HTML minification means the rewrite step can still find unminified &lt;code&gt;href=&amp;quot;/style.css&amp;quot;&lt;/code&gt; attributes. Fingerprinting after would require parsing minified HTML.&lt;/p&gt;
&lt;h2 id=&quot;responsive-images&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#responsive-images&quot;&gt;#&lt;/a&gt;Responsive images&lt;/h2&gt;
&lt;p&gt;Opt-in. If &lt;code&gt;[images]&lt;/code&gt; is set in &lt;code&gt;bamboo.toml&lt;/code&gt;, the engine walks the output for images, resizes each to a configured set of widths (320, 640, 1024, 1920 by default), and writes each variant as both WebP and JPEG. Then it walks every HTML file and rewrites:&lt;/p&gt;
&lt;div class=&quot;bamboo-code-block&quot; data-bamboo-code data-bamboo-lang=&quot;html&quot;&gt;&lt;div class=&quot;bamboo-code-toolbar&quot;&gt;&lt;button type=&quot;button&quot; class=&quot;bamboo-code-button&quot; data-bamboo-line-toggle aria-label=&quot;Toggle line numbers&quot; aria-pressed=&quot;false&quot; title=&quot;Toggle line numbers&quot;&gt;&lt;svg class=&quot;bamboo-code-icon&quot; viewBox=&quot;0 0 20 20&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;1.6&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M4 5h2M4 10h2M4 15h2&quot; stroke-linecap=&quot;round&quot;/&gt;&lt;path d=&quot;M9 5h7M9 10h7M9 15h7&quot; stroke-linecap=&quot;round&quot;/&gt;&lt;/svg&gt;&lt;/button&gt;&lt;button type=&quot;button&quot; class=&quot;bamboo-code-button&quot; data-bamboo-copy aria-label=&quot;Copy code&quot; title=&quot;Copy code&quot;&gt;&lt;svg class=&quot;bamboo-code-icon bamboo-code-icon-copy&quot; viewBox=&quot;0 0 20 20&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;1.6&quot; aria-hidden=&quot;true&quot;&gt;&lt;rect x=&quot;7&quot; y=&quot;3&quot; width=&quot;10&quot; height=&quot;12&quot; rx=&quot;2&quot;/&gt;&lt;path d=&quot;M5 7v8a2 2 0 0 0 2 2h6&quot;/&gt;&lt;/svg&gt;&lt;svg class=&quot;bamboo-code-icon bamboo-code-icon-check&quot; viewBox=&quot;0 0 20 20&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;2&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M4 10l4 4 8-8&quot; stroke-linecap=&quot;round&quot; stroke-linejoin=&quot;round&quot;/&gt;&lt;/svg&gt;&lt;/button&gt;&lt;/div&gt;&lt;pre style=&quot;background-color:#2b303b;color:#c0c5ce;&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;img &lt;/span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;src&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;=&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;/photo.jpg&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;&amp;quot;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;into:&lt;/p&gt;
&lt;div class=&quot;bamboo-code-block&quot; data-bamboo-code data-bamboo-lang=&quot;html&quot;&gt;&lt;div class=&quot;bamboo-code-toolbar&quot;&gt;&lt;button type=&quot;button&quot; class=&quot;bamboo-code-button&quot; data-bamboo-line-toggle aria-label=&quot;Toggle line numbers&quot; aria-pressed=&quot;false&quot; title=&quot;Toggle line numbers&quot;&gt;&lt;svg class=&quot;bamboo-code-icon&quot; viewBox=&quot;0 0 20 20&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;1.6&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M4 5h2M4 10h2M4 15h2&quot; stroke-linecap=&quot;round&quot;/&gt;&lt;path d=&quot;M9 5h7M9 10h7M9 15h7&quot; stroke-linecap=&quot;round&quot;/&gt;&lt;/svg&gt;&lt;/button&gt;&lt;button type=&quot;button&quot; class=&quot;bamboo-code-button&quot; data-bamboo-copy aria-label=&quot;Copy code&quot; title=&quot;Copy code&quot;&gt;&lt;svg class=&quot;bamboo-code-icon bamboo-code-icon-copy&quot; viewBox=&quot;0 0 20 20&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;1.6&quot; aria-hidden=&quot;true&quot;&gt;&lt;rect x=&quot;7&quot; y=&quot;3&quot; width=&quot;10&quot; height=&quot;12&quot; rx=&quot;2&quot;/&gt;&lt;path d=&quot;M5 7v8a2 2 0 0 0 2 2h6&quot;/&gt;&lt;/svg&gt;&lt;svg class=&quot;bamboo-code-icon bamboo-code-icon-check&quot; viewBox=&quot;0 0 20 20&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;2&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M4 10l4 4 8-8&quot; stroke-linecap=&quot;round&quot; stroke-linejoin=&quot;round&quot;/&gt;&lt;/svg&gt;&lt;/button&gt;&lt;/div&gt;&lt;pre style=&quot;background-color:#2b303b;color:#c0c5ce;&quot;&gt;&lt;code class=&quot;language-html&quot;&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;picture&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;  &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;source &lt;/span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;type&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;=&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;image/webp&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;&amp;quot; &lt;/span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;srcset&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;=&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;/photo-320w.webp 320w, /photo-640w.webp 640w, ...&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;&amp;quot;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;  &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;source &lt;/span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;type&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;=&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;image/jpeg&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;&amp;quot; &lt;/span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;srcset&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;=&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;/photo-320w.jpg 320w, /photo-640w.jpg 640w, ...&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;&amp;quot;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;  &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;img &lt;/span&gt;&lt;span style=&quot;color:#d08770;&quot;&gt;src&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;=&amp;quot;&lt;/span&gt;&lt;span style=&quot;color:#a3be8c;&quot;&gt;/photo.jpg&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;&amp;quot;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;&amp;lt;/&lt;/span&gt;&lt;span style=&quot;color:#bf616a;&quot;&gt;picture&lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;so the browser picks an appropriate resolution. The &lt;code&gt;image&lt;/code&gt; crate does the decode and resize. The &lt;code&gt;webp&lt;/code&gt; crate handles WebP encoding. The JPEG encoder comes from &lt;code&gt;image::codecs::jpeg&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The variants that the pipeline already generated have a &lt;code&gt;-{width}w.{ext}&lt;/code&gt; suffix, which is how the scanner avoids regenerating them on subsequent builds: any file whose stem ends in &lt;code&gt;-320w&lt;/code&gt; / &lt;code&gt;-640w&lt;/code&gt; / etc. is skipped as already-derived.&lt;/p&gt;
&lt;h2 id=&quot;rss-atom-sitemap-search&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#rss-atom-sitemap-search&quot;&gt;#&lt;/a&gt;RSS, Atom, sitemap, search&lt;/h2&gt;
&lt;p&gt;Each output is its own module taking the in-memory &lt;code&gt;Site&lt;/code&gt; and writing a single file:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;feeds::generate_rss&lt;/code&gt; → &lt;code&gt;rss.xml&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;feeds::generate_atom&lt;/code&gt; → &lt;code&gt;atom.xml&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;sitemap::generate_sitemap&lt;/code&gt; → &lt;code&gt;sitemap.xml&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;search::generate_search_index&lt;/code&gt; → &lt;code&gt;search-index.json&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The XML files are produced with &lt;code&gt;format!&lt;/code&gt; and a tiny &lt;code&gt;xml::escape&lt;/code&gt; helper for the five special characters. For five entities and a handful of fixed templates this is fine. For anything with attributes-in-elements or namespaces I would reach for a real serializer.&lt;/p&gt;
&lt;p&gt;The search index is a JSON array of &lt;code&gt;{ title, url, tags, date, excerpt, content }&lt;/code&gt; objects, where &lt;code&gt;content&lt;/code&gt; is the rendered HTML run through &lt;code&gt;strip_html_tags&lt;/code&gt; and truncated to 5000 characters per entry — small enough that the client-side Fuse.js search stays responsive even on sites with hundreds of posts. The default theme&apos;s search page pulls the file at request time and feeds it to &lt;a href=&quot;https://fusejs.io/&quot;&gt;Fuse.js&lt;/a&gt; client-side. There is no server-side search component because there is no server.&lt;/p&gt;
&lt;h2 id=&quot;internal-link-validation&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#internal-link-validation&quot;&gt;#&lt;/a&gt;Internal link validation&lt;/h2&gt;
&lt;p&gt;After the build, every HTML file under &lt;code&gt;output_dir&lt;/code&gt; is grepped for &lt;code&gt;href=&amp;quot;...&amp;quot;&lt;/code&gt; by byte scan (the templates are trusted, so a regex is overkill). Anything that looks like an internal link gets resolved against the output tree:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;/about/&lt;/code&gt; checks &lt;code&gt;output_dir/about/index.html&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;/style.css&lt;/code&gt; checks &lt;code&gt;output_dir/style.css&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;https://example.com/about/&lt;/code&gt; (when the base URL is &lt;code&gt;https://example.com&lt;/code&gt;) gets normalized to &lt;code&gt;/about/&lt;/code&gt; and checked the same way&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;External links and &lt;code&gt;#fragment-only&lt;/code&gt; links are skipped. Broken links print a warning. There is a &lt;code&gt;link_check_ignore&lt;/code&gt; config field for prefixes that share the deployment domain with sibling projects on the same host that bamboo cannot see into.&lt;/p&gt;
&lt;h2 id=&quot;incremental-builds-for-bamboo-serve&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#incremental-builds-for-bamboo-serve&quot;&gt;#&lt;/a&gt;Incremental builds for &lt;code&gt;bamboo serve&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;The dev server runs &lt;code&gt;bamboo serve --open&lt;/code&gt;, watches the project tree with &lt;a href=&quot;https://crates.io/crates/notify&quot;&gt;&lt;code&gt;notify&lt;/code&gt;&lt;/a&gt;, debounces FS events by 300ms, then rebuilds. The rebuild is incremental.&lt;/p&gt;
&lt;p&gt;Every tracked file (&lt;code&gt;content/&lt;/code&gt;, &lt;code&gt;data/&lt;/code&gt;, &lt;code&gt;static/&lt;/code&gt;, &lt;code&gt;templates/&lt;/code&gt;, &lt;code&gt;bamboo.toml&lt;/code&gt;) gets SHA-256 hashed at the start of each build. The hashes are compared against the cache at &lt;code&gt;.bamboo-cache/build-state.json&lt;/code&gt;. The diff produces a &lt;code&gt;ChangeClassification&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;bamboo-code-block&quot; data-bamboo-code data-bamboo-lang=&quot;rust&quot;&gt;&lt;div class=&quot;bamboo-code-toolbar&quot;&gt;&lt;button type=&quot;button&quot; class=&quot;bamboo-code-button&quot; data-bamboo-line-toggle aria-label=&quot;Toggle line numbers&quot; aria-pressed=&quot;false&quot; title=&quot;Toggle line numbers&quot;&gt;&lt;svg class=&quot;bamboo-code-icon&quot; viewBox=&quot;0 0 20 20&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;1.6&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M4 5h2M4 10h2M4 15h2&quot; stroke-linecap=&quot;round&quot;/&gt;&lt;path d=&quot;M9 5h7M9 10h7M9 15h7&quot; stroke-linecap=&quot;round&quot;/&gt;&lt;/svg&gt;&lt;/button&gt;&lt;button type=&quot;button&quot; class=&quot;bamboo-code-button&quot; data-bamboo-copy aria-label=&quot;Copy code&quot; title=&quot;Copy code&quot;&gt;&lt;svg class=&quot;bamboo-code-icon bamboo-code-icon-copy&quot; viewBox=&quot;0 0 20 20&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;1.6&quot; aria-hidden=&quot;true&quot;&gt;&lt;rect x=&quot;7&quot; y=&quot;3&quot; width=&quot;10&quot; height=&quot;12&quot; rx=&quot;2&quot;/&gt;&lt;path d=&quot;M5 7v8a2 2 0 0 0 2 2h6&quot;/&gt;&lt;/svg&gt;&lt;svg class=&quot;bamboo-code-icon bamboo-code-icon-check&quot; viewBox=&quot;0 0 20 20&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;2&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M4 10l4 4 8-8&quot; stroke-linecap=&quot;round&quot; stroke-linejoin=&quot;round&quot;/&gt;&lt;/svg&gt;&lt;/button&gt;&lt;/div&gt;&lt;pre style=&quot;background-color:#2b303b;color:#c0c5ce;&quot;&gt;&lt;code class=&quot;language-rust&quot;&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub enum &lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;ChangeClassification {
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    Full,
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    Targeted { changed_files: Vec&amp;lt;PathBuf&amp;gt; },
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;A change in &lt;code&gt;bamboo.toml&lt;/code&gt;, any &lt;code&gt;templates/*&lt;/code&gt;, or &lt;em&gt;any&lt;/em&gt; deletion forces a full rebuild. A change to &lt;code&gt;content/posts/2024-01-15-hello.md&lt;/code&gt; produces a &lt;code&gt;Targeted&lt;/code&gt; classification, which expands to a &lt;code&gt;HashSet&amp;lt;RenderTarget&amp;gt;&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;bamboo-code-block&quot; data-bamboo-code data-bamboo-lang=&quot;rust&quot;&gt;&lt;div class=&quot;bamboo-code-toolbar&quot;&gt;&lt;button type=&quot;button&quot; class=&quot;bamboo-code-button&quot; data-bamboo-line-toggle aria-label=&quot;Toggle line numbers&quot; aria-pressed=&quot;false&quot; title=&quot;Toggle line numbers&quot;&gt;&lt;svg class=&quot;bamboo-code-icon&quot; viewBox=&quot;0 0 20 20&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;1.6&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M4 5h2M4 10h2M4 15h2&quot; stroke-linecap=&quot;round&quot;/&gt;&lt;path d=&quot;M9 5h7M9 10h7M9 15h7&quot; stroke-linecap=&quot;round&quot;/&gt;&lt;/svg&gt;&lt;/button&gt;&lt;button type=&quot;button&quot; class=&quot;bamboo-code-button&quot; data-bamboo-copy aria-label=&quot;Copy code&quot; title=&quot;Copy code&quot;&gt;&lt;svg class=&quot;bamboo-code-icon bamboo-code-icon-copy&quot; viewBox=&quot;0 0 20 20&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;1.6&quot; aria-hidden=&quot;true&quot;&gt;&lt;rect x=&quot;7&quot; y=&quot;3&quot; width=&quot;10&quot; height=&quot;12&quot; rx=&quot;2&quot;/&gt;&lt;path d=&quot;M5 7v8a2 2 0 0 0 2 2h6&quot;/&gt;&lt;/svg&gt;&lt;svg class=&quot;bamboo-code-icon bamboo-code-icon-check&quot; viewBox=&quot;0 0 20 20&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;2&quot; aria-hidden=&quot;true&quot;&gt;&lt;path d=&quot;M4 10l4 4 8-8&quot; stroke-linecap=&quot;round&quot; stroke-linejoin=&quot;round&quot;/&gt;&lt;/svg&gt;&lt;/button&gt;&lt;/div&gt;&lt;pre style=&quot;background-color:#2b303b;color:#c0c5ce;&quot;&gt;&lt;code class=&quot;language-rust&quot;&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#b48ead;&quot;&gt;pub enum &lt;/span&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;RenderTarget {
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    Page(String),
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    Post(String),
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    Collection(String),
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    Pagination,
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    AllTaxonomies,
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    Feeds,
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    Sitemap,
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    SearchIndex,
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;    All,
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;bamboo-line&quot;&gt;&lt;span style=&quot;color:#c0c5ce;&quot;&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;A post edit invalidates pagination, feeds, sitemap, search, taxonomies, &lt;em&gt;and&lt;/em&gt; the index page (the index lists recent posts). A page edit only invalidates sitemap and search. The render functions accept the target set as &lt;code&gt;Option&amp;lt;&amp;amp;HashSet&amp;lt;RenderTarget&amp;gt;&amp;gt;&lt;/code&gt; and consult it before doing the work, so an incremental pass writes only the few files that actually changed.&lt;/p&gt;
&lt;p&gt;This is finicky. The win is that editing a post and saving rebuilds in ~50ms instead of ~500ms on a site this size. With &lt;code&gt;tower-livereload&lt;/code&gt; pushing a WebSocket message after each rebuild, the browser refreshes before I have tabbed back to it.&lt;/p&gt;
&lt;p&gt;The error path is interesting. If a build fails mid-rebuild, the server stashes the error string in an &lt;code&gt;Arc&amp;lt;Mutex&amp;lt;Option&amp;lt;String&amp;gt;&amp;gt;&amp;gt;&lt;/code&gt; and an Axum middleware intercepts the next page request, returning a styled error overlay with the message. As soon as the next successful build completes, the overlay clears and live reload fires. Editing markdown with a misformatted frontmatter no longer produces a 404 from the dev server; it produces a readable error screen.&lt;/p&gt;
&lt;h2 id=&quot;what-i-left-out-and-why&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#what-i-left-out-and-why&quot;&gt;#&lt;/a&gt;What I left out, and why&lt;/h2&gt;
&lt;p&gt;A real plugin system. bamboo&apos;s &quot;plugin&quot; is &quot;drop a Tera template into &lt;code&gt;templates/&lt;/code&gt;&quot; plus &quot;edit &lt;code&gt;bamboo.toml&lt;/code&gt;.&quot; That covers everything I want from a personal blog. Zola has the same answer.&lt;/p&gt;
&lt;p&gt;A proc-macro layer for typed frontmatter. The frontmatter is a &lt;code&gt;HashMap&amp;lt;String, Value&amp;gt;&lt;/code&gt;. Templates speak through the map. A typed struct per content type would be tidier in pure-Rust terms, but every site has a different schema, and I do not want to compile a per-site bamboo binary. The flat map wins.&lt;/p&gt;
&lt;p&gt;Configurable markdown extensions. pulldown-cmark options are hardcoded: tables, footnotes, strikethrough, task lists, heading attributes. I have never wanted any of these off.&lt;/p&gt;
&lt;p&gt;A theme registry. Themes are directories. The built-in is embedded. I have not built infrastructure to publish or install third-party themes because nobody has asked.&lt;/p&gt;
&lt;h2 id=&quot;dependencies&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#dependencies&quot;&gt;#&lt;/a&gt;Dependencies&lt;/h2&gt;
&lt;p&gt;A few non-obvious choices:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;pulldown-cmark&lt;/strong&gt;: event-stream API, fast. The custom code block highlighting and TOC extraction are straightforward against the event stream and awkward against any &quot;give me HTML&quot; wrapper.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;syntect&lt;/strong&gt;: syntax highlighter, the same one &lt;a href=&quot;https://github.com/sharkdp/bat&quot;&gt;bat&lt;/a&gt; uses. The default theme set covers enough languages.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Tera&lt;/strong&gt;: Jinja2-style templating with filters and macros. Performance is fine for site sizes that fit in memory, which is &quot;every site I care about.&quot;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;grass&lt;/strong&gt;: pure-Rust Sass compiler. The reason there is no Node.js anywhere in this toolchain.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;rayon&lt;/strong&gt;: parallel iterators. Used in content parsing, page/post/collection rendering, taxonomy term rendering, image resizing, and asset minification. Each loop writes to its own file so there is nothing to coordinate.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;walkdir&lt;/strong&gt;: recursive directory walks. Filter-then-collect-then-parallel is the pattern everywhere.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;lightningcss / minify-html / minify-js&lt;/strong&gt;: the three minifiers. lightningcss in particular is faster and produces tighter output than the JS-ecosystem alternatives.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;axum + tower-livereload + notify&lt;/strong&gt;: the live-reload dev server stack. &lt;code&gt;notify&lt;/code&gt; watches the disk, the rebuild thread fires through an &lt;code&gt;mpsc::channel&lt;/code&gt;, a &lt;code&gt;tokio::sync::broadcast&lt;/code&gt; fans out reload signals to connected WebSocket clients.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;closing&quot;&gt;&lt;a class=&quot;anchor&quot; href=&quot;#closing&quot;&gt;#&lt;/a&gt;Closing&lt;/h2&gt;
&lt;p&gt;The whole repo is at &lt;a href=&quot;https://github.com/matthewjberger/bamboo&quot;&gt;matthewjberger/bamboo&lt;/a&gt;. The source for this site is at &lt;a href=&quot;https://github.com/matthewjberger/articles&quot;&gt;matthewjberger/articles&lt;/a&gt;. If you want a ready-to-deploy starter with GitHub Pages CI, &lt;a href=&quot;https://github.com/matthewjberger/bamboo-template&quot;&gt;matthewjberger/bamboo-template&lt;/a&gt; is one &lt;code&gt;gh repo create --template&lt;/code&gt; away.&lt;/p&gt;
</content>
  </entry>
</feed>
