NNory Blog
HomeReviewsLife GuidesJournal
NORY
Grish's Personal Space

A personal space where I share my thoughts on music, movies, and life through journaling. Join me on this journey of discovery and reflection.

Explore

  • Home
  • Reviews
  • Life Guides
  • Journal

Resources

  • Bookmarks
  • Tags
  • RSS Feed

Stay Updated

Get the latest articles and resources sent to your inbox.

© 2026 Grish. All rights reserved.

Privacy PolicyTerms of Service

    My Pathfinder Was Fast Until Chunks Made It Stupid

    I rewrote my Minecraft pathfinder in Rust. It is safer. It is also more annoying. A story of infinite worlds and finite RAM.

    NorySight
    NorySight
    December 23, 2025
    16 minutes
    Rust Minecraft Pathfinding Systems Engineering
    Status: Ready to listen

    Your browser does not support speech synthesis.

    The "Infinite" World Problem

    In a standard A* implementation, the world is a grid. You have start A and goal B. You iterate neighbors. You find the path.

    In Minecraft, the world does not exist.

    Only a tiny bubble around the player (the "loaded chunks") exists in memory. Everything else is null. And here lies the problem: A pathfinder that can't see the destination is just a random walker with an ego.

    The Failure Mode

    When the target is 500 blocks away, but only 160 blocks are loaded, standard A* panics. It treats the "void" as a massive bedrock wall.

    The Cost:

    • Nodes Explored: 200,000+ (Entire loaded area)
    • Time: 450ms (Frame drop city)
    • Result: "No Path"

    My "blazingly fast" Rust server was burning 100% CPU to calculate a path that didn't exist, simply because it couldn't see the horizon.

    Horizon-Chasing A*

    I couldn't just "load more chunks" without crashing the server. I needed a way to pathfind towards the unknown without knowing the unknown.

    I implemented Horizon-Chasing. Instead of solving the whole path A -> B, we solve A -> Edge of Known World.

    1

    Step 1: Check Visibility

    Is the Goal inside a loaded chunk?

    • YES: Traditional A* to Goal.
    • NO: Proceed to Step 2.
    2

    Step 2: Find the Horizon

    We don't need the best path to the goal. We need the path to the loaded block that is closest (heuristically) to the goal.

    3

    Step 3: Walk & Forget

    Send this partial path to the client. As the bot walks, it loads new chunks. The Horizon moves. Repeat.

    Here is the logic that saved the project:

    // The Horizon Algorithm
    // ~3,000 candidate nodes at the edge of loaded space
    border_nodes = world.get_walkable_nodes_on_chunk_boundary()
     
    // Find the one closest to the true target
    horizon_node = border_nodes.min_by_key(|n| distance(n, goal))
     
    // Pathfind to the edge, not the goal
    return a_star(start, horizon_node)

    Rust: Safer, But More Annoying

    The architecture split was simple on paper:

    1. Java Client: Dumb body, executes inputs.
    2. Rust Server: Big brain, holds state.

    But in practice, safety has a cost: Contention.

    Pathfinding requires a long-lived RwLock read-handle on the Chunk map to scan thousands of nodes. The physics thread needs a write-handle to move entities. If the pathfinder holds the lock for 50ms to scan a horizon, the physics thread starves. The server stutters.

    Java (Imagined)
    // "It just works"
    // GC handles references.
    // Thread safety? What's that?
    if (chunk == null) return null;
    return chunk.getNode(x, y, z);
    
    Rust (Reality)
    // The struggle
    // We lock the ENTIRE world state
    let world = self.world.read().unwrap(); 
    
    if let Some(chunk) = world.get_chunk(pos) {
      // Copy data out before lock release
      return chunk.get_node_copy(pos); 
    }
    None
    

    I traded the runtime errors of Java for the compile-time headaches of Rust.

    • Pros: Zero NullPointerExceptions. Concurrency is fearless.
    • Cons: Refactoring data structures is painful.

    The "Fake No-Path" Bug

    Even with Horizon-Chasing, I hit a nuanced edge case.

    The Scenario:

    • Bot is at (0, 70, 0)
    • Goal is (0, 70, 100) (Unloaded)
    • There is a wall at (0, 70, 50)
    • The loaded chunk ends at (0, 70, 60)

    What A Sees:* A* runs towards the goal. It hits the wall at 50. It tries to go around. It navigates left and right, exploring the local options. Eventually, it hits the chunk border at 60.

    To A*, the chunk border looks like another wall. It thinks it is trapped in a box formed by the real wall and the chunk border. It returns "No Path Found."

    The Reality: If the bot just walked closer to the chunk border, the server would load the next chunk, revealing the way around the wall.

    The Fix: I had to relax the "Success" condition. Even if we encounter a wall, return the path to the closest reachable point to the goal, even if it's a dead end locally.

    Progress beats correctness in partially observed worlds. Waiting for a perfect path in an incomplete world is a deadlock. Getting closer reveals the map.

    Current State

    The system is not perfect. It is "annoyingly correct."

    The bot can now travel 10,000 blocks autonomously. It pauses at chunk borders. It occasionally looks confused. But it never crashes.

    I stopped treating "No Path" as a failure and started treating it as a lack of information.

    Was it worth it?

    Ask me again when I figure out how to safely handle water elevators without creating a deadlock between the physics tick and the pathfinding read-lock.

    You Might Also Like

    Related Posts

    December 22, 2025
    Arch LinuxDebuggingLinux
    34 minutes

    Two Days of Debugging: A One-Character Story

    How I spent two days debugging a race condition in my Arch Linux customization script simply because I didn't read the manual.

    Read Article
    February 12, 2026
    DebuggingGame DevelopmentRust
    31 minutes

    How I Wasted 15 Hours Debugging a Bug I Created a Month Ago (And Completely Forgot About)

    A brutal debugging story from Brave: a self-inflicted location bug, Unicode mismatches, and the pragmatic server-side fix that shipped.

    Read Article
    December 19, 2025
    bojack-horsemanmental-healthpersonal-growth
    14 minutes

    Two and a Half Years Later: BoJack Horseman Still Haunts Me

    A personal reflection on how BoJack Horseman changed my perspective on growth, mental health, and the uncomfortable truth that nobody is looking out for you.

    Read Article