[video output=day643 member=cmuratori stream_platform=twitch stream_username=handmade_hero  project=code title="Hunting for Collision Bugs" vod_platform=youtube id=HEU6qal7qD8 annotator=Miblo]
[0:00][Welcome to the stream, with a plug of Meow the Infinite: Book Two[ref
    site=Kickstarter
    page="Meow the Infinite: Book Two"
    url=https://www.kickstarter.com/projects/annarettberg/meow-the-infinite-book-two] and Consolidated Press printers[ref
        site="Consolidated Press"
        url=https://www.consolidatedpress.com/]][:speech]
[1:40][Problems with spam filtering of Molly Rocket's newsletter][:rant :speech]
[7:32][Determine to handle embedding recovery][:collision :speech]
[8:31][Demo :collision embedding][:run]
[11:27][Reproduce a corner embedding case and rebuild in -Od][:collision]
[12:10][Rebuild in -Od][:collision]
[13:16][Step through MoveEntity() while embedded in the corner][:collision :run]
[18:02][Rebuild in -O2][:collision]
[18:11][Compare the recorded Occupied cells with the visible scene][:collision :run]
[18:50][Rebuild in -Od][:collision]
[19:04][Step through MoveEntity() while embedded in the corner, and consider the Occupied cells to match the scene][:collision :run]
[21:21][Step through the :collision flood search in MoveEntity()][:run]
[23:57][Fix the logic of the Occupied tests in MoveEntity()][:collision]
[25:46][Embedding is fixed][:collision :run]
[26:13][We appear to tunnel][:collision :run]
[32:03][The :collision seems stable otherwise][:run]
[33:21][Reproduce our tunnelling bug][:collision :run]
[35:31][Consider our tunnelling bug][:collision :research]
[39:20][Augment diagram_group with ResetCounter and make DIAGRAM_Reset() let 16 diagrams pile up][:"debug visualisation"]
[40:01][Our diagrams keep on piling up][:"debug visualisation" :run]
[40:16][Fix DIAGRAM_Reset() to reset the ResetCounter][:"debug visualisation"]
[40:33][Reproduce our tunnelling bug][:collision :run]
[42:20][Consider increasing the wall :collision volume height][:run]
[43:51][Reacquaint ourselves with the :collision volume code][:"procedural generation" :research]
[45:31][Increase the wall :collision volume height in GenerateRoom()][:"procedural generation"]
[46:20][The wall :collision volume isn't much higher][:"procedural generation" :run]
[46:33][Increase the wall :collision volume height by FullWallHeight in GenerateRoom()][:"procedural generation"]
[46:55][Reproduce our tunnelling bug with taller wall :collision volumes][:run]
[49:30][Some corner wall :collision volumes fail to light up for collision][:run]
[50:52][Toggle on :collision volume drawing in UpdateAndRenderEntities()][:"debug visualisation"]
[51:27][All wall :collision volumes are present][:"debug visualisation" :run]
[52:23][Consider the :collision volume's failure to light up][:run]
[53:11][Toggle off :collision volume drawing in UpdateAndRenderEntities()][:"debug visualisation"]
[53:22][Reproduce our tunnelling bug][:collision :run]
[53:39][Consider adding diagram freezing and single-stepping][:collision :run]
[56:16][Scour CollidesAtP(), ShapesCollide() and RefineVoxelPlacement() for bugs][:collision :research]
[1:03:37][Diagram :collision voxel corners coloured by their Occupied status][:"debug visualisation"]
[1:06:36][Check out our coloured :collision voxel corners][:"debug visualisation" :run]
[1:07:34][Toggle off PushCube() in UpdateAndRenderEntities()][:"entity system" :rendering]
[1:08:07][Try to reproduce our tunnelling bug][:collision :run]
[1:08:32][Toggle on :collision volume drawing in UpdateAndRenderEntities()][:"debug visualisation"]
[1:08:46][Reproduce our tunnelling bug, with corners oddly coloured black][:collision :"debug visualisation" :run]
[1:10:24][Make DIAGRAM_Reset() let 32 diagrams pile up][:"debug visualisation"]
[1:11:44][Reproduce our tunnelling bug, and try to capture the diagrams][:collision :"debug visualisation" :run]
[1:13:00][Set Shift-F9 as a hotkey for diagram capturing][:"debug visualisation" :"input handling"]
[1:14:45][Try to reproduce our tunnelling bug][:collision :"debug visualisation" :run]
[1:17:00][Reproduce our tunnelling bug, and capture the diagrams][:collision :"debug visualisation" :run]
[1:17:05][Inspect our tunnelling bug diagrams][:collision :"debug visualisation" :run]
[1:18:19][The pink marks are the root-finding ones drawn by RefineVoxelPlacement()][:collision :"debug visualisation" :research]
[1:18:54][Inspect our tunnelling bug diagrams (cont.)][:collision :"debug visualisation" :run]
[1:19:21][Consider our tunnelling bug][:collision :"debug visualisation" :research]
[1:20:15][We shouldn't see a great mass of red Occupied corners][:collision :"debug visualisation" :run]
[1:21:30][Scour CheckCorners() for bugs in the :collision voxel stack push][:research]
[1:24:06][Hypothesis: Maybe RefineVoxelPlacement() can accidentally place you in an embedded position?][:collision :run]
[1:25:20][Scour RefineVoxelPlacement() for bugs][:collision :research]
[1:26:12][Toggle off the embedded corner occupancy resetting in CheckCorners()][:collision]
[1:26:37][Try to, but never reproduce our tunnelling bug][:collision :run]
[1:29:02][Scour GetClosestPointInBoxConservative() and RefineVoxelPlacement() for bugs][:collision :research]
[1:31:33][Assert in MoveEntity() that the target cell remains the same after RefineVoxelPlacement()][:collision]
[1:32:41][Try to reproduce our tunnelling bug][:collision :run]
[1:33:30][Assert in MoveEntity() that the Corners are not embedded][:collision]
[1:33:54][Immediately hit that assertion because the glove begins embedded][:collision :run]
[1:34:07][Comment out the Corner not embedded assertion in MoveEntity()][:collision]
[1:34:18][Our glove begins embedded][:collision :run]
[1:34:25][Re-enable the Corner not embedded assertion in MoveEntity() and make AddPlayer() spawn the glove to the side][:collision :"entity system"]
[1:34:51][Hit our assertion upon moving][:collision :run]
[1:35:25][Change that assertion in MoveEntity() to call DIAGRAM_Capture()][:collision :"debug visualisation"]
[1:35:47][Inspect our embedding-triggered diagrams][:collision :"debug visualisation" :run]
[1:36:27][Shrink the hero's head :collision volume in AddPlayer()][:"entity system"]
[1:36:55][We embed on a corner][:collision :run]
[1:37:30][Revert our embedding-triggered DIAGRAM_Capture() call to an assertion in MoveEntity()][:collision :"debug visualisation"]
[1:37:56][Hit that assertion at the doorway][:collision :run]
[1:38:04][Disable the hero's head collision volume in AddPlayer()][:"entity system"]
[1:38:17][Hit that assertion at the doorway][:collision :run]
[1:39:51][Change MoveEntity() to detect embedding, then perform and capture the :collision search][:collision]
[1:40:38][We detect occupied corners where there are no colliders][:collision :run]
[1:41:53][Scour CheckCorners() for bugs][:collision :research]
[1:45:14][Make CheckCorners() always recompute corner occupation][:collision]
[1:45:28][We still detect occupied corners where there are no colliders][:collision :run]
[1:46:02][Revert CheckCorners() to only compute corner occupation for CornerCode 0][:collision]
[1:46:08][Our options: 1) Testing the wrong TestP; 2) Buggy CollidesAtP()][:collision :research]
[1:47:02][Re-enable the :collision diagramming in ShapesCollide()][:"debug visualisation"]
[1:47:13][We see a giant jumble of :collision diagrams][:"debug visualisation" :run]
[1:48:01][Plan to add diagram single-stepping, debug the incorrect collider points, then handle embedding][:collision :speech]
[1:49:44][Q&A][:speech]
[1:50:30][@x13pixels][Q: The ~RemedyBG bug seen earlier with the MoveEntity() breakpoint happened because a function breakpoint, currently, is only added to the first valid location found. When :"hot reloading", two DLLs are loaded in the process: handmade_game_temp.dll and 1_handmade_game_temp.dll. The breakpoint ends up getting added to the DLL that is still loaded but not executing any code. Looks like this is intentional in [~hero Handmade Hero] (Win32Unloaded doesn't call FreeLibrary). In any case, my apologies for the inconvenience]
[1:51:54][How do breakpoints work on overloaded functions?][:speech]
[1:52:31][@x13pixels][Special handling for overloaded functions, yes, but not multiple modules]
[1:53:06][@x13pixels][Exactly, yes. Overloaded functions have their arguments hashed, etc.]
[1:53:18][Wrap it up][:speech]
[1:53:57][Plug Meow the Infinite: Book Two[ref
    site=Kickstarter
    page="Meow the Infinite: Book Two"
    url=https://www.kickstarter.com/projects/annarettberg/meow-the-infinite-book-two]][:research]
[1:54:15][@floorislava][Q: You have subscriber-only chat on for Q&A]
[1:56:57][Q&A (now with non-subscriber chat)][:speech]
[1:57:16][@akuma__][Sorry if this has been asked 1000 times, but any news on Star Code Galaxy?[ref
    site="Star Code Galaxy"
    url=https://starcodegalaxy.com/]]
[1:59:06][@manekenpix][[@cmuratori Casey], does Star Code Galaxy[ref
    site="Star Code Galaxy"
    url=https://starcodegalaxy.com/] have a subscriber limit number or something? I never get emails from it, and they're not in my spam folder]
[2:01:44][@internationalizationist][Q: By the way, does live looping still work?]
[2:01:51][Live looping crashes the game][:run]
[2:02:56][@vmttmv][Don't know if it's a known thing, but for me at least GMail's spam filters have been dog for the last 12 months or so]
[2:05:23][@internationalizationist][Q: Why doesn't that help? We recorded the entire state of the game every frame, and the replaying would have reproduced the bug][:collision]
[2:06:12][@manekenpix][Q: I just subscribed to Star Code Galaxy,[ref
    site="Star Code Galaxy"
    url=https://starcodegalaxy.com/] but I didn't get any confirmation email. Not sure if I should expect one]
[2:06:41][@tomisqi][Q: I read in email that the Handmade engine is mostly done and that from now, we will be doing :gameplay programming? Expect to finish in 2022?]
[2:07:14][@clayfreeman][How should I proceed if I use G Suite and your website thinks I'm already subscribed? I never got a confirmation e-mail from you]
[2:08:12][@hquil][Q: Wouldn't double opt-in through confirmation help? Because the subscriber will fish it out, mark it as trusted and click on a link]
[2:09:06][@qyxat][Q: You should make a DMARC record. Most services reject email from domains without it]
[2:10:35][@clayfreeman]["v=DMARC1; p=reject; sp=reject; adkim=s; aspf=s" is ideal]
[2:12:41][Check SparkPost's support for DMARC[ref
    site=SparkPost
    page="What Is DMARC?"
    url=https://www.sparkpost.com/resources/email-explained/dmarc-explained/]][:research]
[2:14:19][@jaythedeveloper][SendGrid is 10/10, in my opinion]
[2:15:08][@clayfreeman][If you intend to send out some mail today, I'll run an analysis on it and @ you via Twitter with what I find out]
[2:15:36][@ascentroid][With the email provider I use, when I log in to my account it has a section that shows me all the domain stuff I should set up, etc. Dunno if that could help]
[2:17:44][@brinktjofzki][Did SparkPost know that the mails were rejected? It is possible that Microsoft / Google were silently not delivering mail to end addresses]
[2:18:48][@caviar_liberta][@handmade_hero Isn't there an ack in the outbox?]
[2:18:59][@qyxat][There is a good chance that your IP is already blacklisted on Google, so changing provider may not help]
[2:20:26][@internationalizationist][I did get the mail, but didn't get notification that it came]
[2:20:37][@rastapharao][Are the emails properly marked as being bulk / list mail?]
[2:21:03][@clayfreeman][You'd want a List-Unsubscribe header]
[2:21:11][@rastapharao][Precedence: bulk, List-Id, List-Unsubscribe etc. headers]
[2:21:35][Thoughts on mailing lists][:speech]
[2:23:35][@heliumfactory][I miss RSS]
[2:23:50][Wrap it up with a plug of Meow the Infinite: Books One (physically) and Two[ref
    site=Kickstarter
    page="Meow the Infinite: Book Two"
    url=https://www.kickstarter.com/projects/annarettberg/meow-the-infinite-book-two]][:speech]
[2:25:32][@fractalmindmike][Q: Is there a backer tier to receive both editions of Meow?]
[2:28:31][Finish wrapping it up with a glimpse into the future][:speech]
[/video]
