Post
April 26, 2026 • 14 min
Technical work
January 17-January 31
- double pendulum inspired random number generator + whoosh sfx test to try later made by chatgpt
- working on intent system
- fixed unique mapping checker (UMC) issue with fake bullets where fake bullets created by intent system scheduler would collide body userdata IDs with existing bullets eventually
February
- Made x64 build for windows
- fixed the UMC-detected failure - it was due to temp game object manager being used for bullets and also due to not differentiating tempID vs non-tempID correctly
- dynamic light fixes
- got bullets working in scheduler
- got local prediction of own player bullet firing working in scheduler
- got remote players predicting bullet firing via intent system / scheduler
- now using client ticks instead of server ticks for tick domain in bullet prediction (for intent system)
- improved handling of server lag
- improved Pid controller/tick diff adjusting when tons of packet loss and throttling/latency spikes
- Made server send rpcs, state updates, netvar, and scheduling to clients in post sim instead of pre sim.
- fixed packet loss causing issue sending client ID from server to clients where it would never be delivered (due to using wrong enet channel for it: before the fix, the rpcs were sent on another channel, meaning if the client ID packet was dropped then rpcs could arrive before client ID received, but client must drop rpcs if it has no client ID yet per my "protocol", so the fix was use same channel for client ID message as was originally intended)
- fixes for netvars repeatedly sending sideHP
- now have a ui to debug state update dirty marking
- debugged a rare issue where client thinks it "connected" to server but the server doesn't. This is basically due to the "two generals problem" when there is excessive packet loss and is only prevented by having a timeout on the client so that it disconnects after thinking it connected successfully (because server won't be sending packets in this case of server thinking client not connected, causing client to time out). My time out was set to infinite because I use that for debugging, so I never saw this happen.
- fixed too many state updates being incorrectly marked as dirty when packet loss occurred
March
- fixes for jitter in fake bullets in the intent system - it was because predicted bullet was colliding with the authoritative one. initially thought the issue was related to resim, so this debugging shows resim interference graph (what interacted with what in the past n ticks):
- fixed resim init on go thru portal fork / on Client::resetSimNetState
- fixed unit tests compilation
- fixed crash from going thru portal then back then thru again then back and then copying the dead clover shape -- it is rpc type id mismatch from server to client; fixed not flushing WriteStream on sending netvar bootstraps -- also for new rpc bootstrap in this commit; fixed undefined behavior in delta_compression.h for int64
- fixed netvars on late join using netvar bootstrap
- fix for auth bullet remaining visible in intent scheduler
- fixed seed for local ability exec prediction for intent system (but may have not yet fixed the long-standing issue with seed on use ability RPC?)
- fixed a snapstep rare bug where it called an old renamed function that no longer existed
- fixed spawning bullets past walls when up against a shape with a custom algo
- box2d dump saving + viewer for debugging courtesy of claude opus 4.6 extended. Helped me make the spawning bullets past walls algo.
- made it so mouse release is required after changing shape in order to use ability again.. unsure if this is good
- wip fixing replay v2 position diffs/issues
- fixed body ID diffs if spectatorV2 is present (i.e. if whoever is watching replay exists)
- now pauses sim on replay v2 position mismatch
- fixed body in orbits not having a body userdata ID which messed with replay sometimes
- now replay v2's can verify not only positions but also ID registration
- fixed player late join issue for replay v2's
- fixed enable players in replay v2 causing desync on the replay when it's a post-sim event
- ability inputs and when schedule was made are now saved to replay v2's to fix intent scheduler desync
- fixed toggle camera rpcs sticking around forever in replay v2 players' RPC queues (since these don't get sent because they're not actually backed by a connected client on server sim)
- unit test for replay v2
- potential fix for level identifiers not being created correctly on client when something gets spawned in the level as a new identifier post-level-load. It may be a hack though. Claude came up with the fix but I'm not sure it gets the entire big picture..
April 1-6
- got macOS build to compile but not link (yet)
- post sim not happening one final time on game over fix; fix for replay v2 unit tests disposing Server not clearing m_clientInfo on it
- unit tests pass on windows (then they broke later due to replay v2 something changed)
- crash fixed from short playtest related to noform copy state not being sync'ed within client among its internal data structures/predictors for it
- fix for lua ui with same name crash on double pressing the host game -> king of the hill button
- glsl change detector no longer errors entire program weirdly if fails such as due to running on a network drive
- found that apparently like most games, my game is black screen when run in virtualbox. In 2026 how in the world is the opengl in virtualbox not fully implemented yet...
- release bisect build to find non-determinism because replay v2 worked in non-release; found the issue: it was the sim rng seed not being applied in replays, noticeable in SS_RELEASE only due to mod for testmodule not being loaded which was what set a fixed seed (claude helped me find it)
- to fix this, now have an rng seed setter for replay v2
- still need to support which level the replay is for though. Right now it just assumes the replay applies to the loaded level
- nan fix for obelisk spawn location sometimes; potential fix for next level ident causing issue from earlier short playtest
- fix for dir monitor sometimes failing to init -- this is if ran with working dir not in the game folder
- fixed sublevel identifier issue where ID for newly spawned sublevels post-level-load was off by one from client vs server
Design / gameplay programming
April 6-26
- working on designing crown zones - new king of the hill (KoH) prototype (v4) since current is too sandboxy and not encouraging pvp
- working on design with claude sonnet, it's really helpful to plan with
- working on crown spawning. It makes a zone around it
- claude code hot fix for player idents in levels. Unsure if it gets big picture / is correct or is a hack.
- claude code also made a unit test for it
- I've found that claude code is useful when I'm currently working on design and don't want to pivot / switch hats/roles suddenly so I can focus on one aspect of the game at a time. So nice so far
- tried qwen code to make crown particles, it's not that good
- score bars for KoH
- basic crown arrow indicator
- claude code refactor to allow drawing to specific layers from Lua. Is basically "draw laters" but now it's "draw layers". "The pragmatic middle ground" to not having full rewrite says claude
- emissive draw layer now used for crown zone circle so it doesn't appear on top of shapes - looks better now
- "impact" line particles having too low alpha fixed
- claude code made particle attractor repeller system
- crown ability to steal "eminence" (score)
- beam animation from chatgpt 5.3
- nanovg offscreen rendering now supported from Lua for showing targeter at mouse hover for this using multiple transparent overlapped nanovg fills which don't increase alpha badly where they overlap because they render offscreen first at full alpha, then render the image result. The hover indicator shows if it can be used too. It's nice.
- reservation ledger (intent system) fix bug where energy was being spent even when shape request to use ability was not satisfied
- feature for replay v2 to record rpcs for reference/viewing purposes only currently
- fix for two spectators joining; fixed the bug that caused CallCustom RPC types to fail on late join
- unit conversion meters pixels usage fix from koh_sunform.lua; advancedFindOpenSpace is now supported for spawning enemies from level instance specifically
- minimap fixes and improvements from claude sonnet. Now has better camera movement in minimap, better sizing, readability, configurable blips
- claude opus fixed lifetime issues in Lua very effectively - the issue was that I realized a system update struct reference could be saved to any Lua table so that it became invalid memory on return from some caller C++ function. Fixed by invalidating references for specific types on return from C++ functions that call Lua ones automatically around when calling into Lua from C++
- claude code cooked up ability slots for rmb, 1, 2, 3, 4, and optionally more. They can be added at runtime to any shape. Using for crown zone
- basic team assignment
- claude code with opus 4.7 fixed issue with needing to transfer player teams post server level restart - elegant, flexible fix by having it so lua level managers can transfer any data post restart, then run code to apply that how they choose.
- team transfer works, thanks claude
- claude wall segment corner fixes for level ascii
- designed / laid out a map for KoH v4
- crown zone teams and buffs designed
- global netvar registry added for "custom global netvars" - will be using this for team score sending to clients
- [visuals/"artist tooling"] claude code opus 4.7 impl for day 1 of jungle ruins fog of war and decoration system for visuals. It's probably a lot of work so this is just the start of visuals.
- fixed debug profiler Graph pie chart having too many things to show sometimes causing insane lag spike
- fixed Lua stack missing a pop in newly-added callMethod_ifExists function
- team score implemented for KoH: refactored eminence bars to show them, etc. via claude
- fix for out-of-order arrival of global netvars
- "chevron" animation for eminence bars (got claude to make it for me)
- crown zone arrow colors based on which team is holding zone (claude made)
- red arrow when zone contested (claude made)
- bar flash for eminence bars (claude made)
- fixed issue with crown zone arrow not moving with actual crown if pushed around
- claude code mass lead / victory condition handling
- claude code timer toast for KoH
- Made ascii level for basic map structure implemented for KoH v4 from my drawing/layout plans
- Made player spawn point depend on player team
- fixed team handling for enemy AI / "attacks enemies instead" handling so that sun form can be on opposing teams for each team's sun form spawn point
- trying kimi llm via Nvidia NIM, not as good as claude but maybe approaching codex
- team colors, "street-fighter style" eminence bars if two teams, and mass budget indication and tracking for KoH via claude code oneshotting it
- has a few issues to fix, including sun form side HP vs budget sync'ing, and issue with player respawn mass not being correct when dying more than once it seems
- tried using kimi to make level regen/reset but it was mostly an echo chamber where I planned potentially too simple way to do it
- step 3.5 flash llm used to make a weird attempt at enemy wave spawning for KoH. Had to discard it and use opus with additional engine-level changes for it to make it easy, including better shape entity prototype Lua bindings, untested energy helper pickup system with invincibility until owner destroyed, refactor to move crown zone stuff from koh_sunform behavior to king_of_the_hill gamemode Lua code, will become resurrectable overrides from Lua now supported so not all helpers become graves
- "bit bending" with Claude opus 4.7 for serialization. now using bits for SerializeFnBuf and other stuff, fixing how serializing/deserializing Lua tables in netvars + global netvars was allocating 8 times as large of a buf as needed because was using bits as if they
were bytes for the buf size; wip fix for using LuaRegistryTable across threads causing a crash (due to
GlobalNetvarUpdate globalNetvarUpdateinGlobalNetvarIfPresentAndGamemodeMatchesEventandGlobalNetvarUpdateEventbeing used before this fix). But had to disable the thread ID tracking on luaregistrytable because it doesn't really work when starting Server which starts first ServerSim - fixed global netvar updates hash and equality checks not including the custom netvar type itself so it was incorrectly ignoring updates of different custom netvar type